2021-07-30 21:50:10 +00:00
|
|
|
from flask import flash
|
2022-02-23 18:37:09 +00:00
|
|
|
from flask_admin import expose
|
2022-02-23 19:36:29 +00:00
|
|
|
from flask_security import admin_change_password, current_user
|
2022-06-01 21:03:41 +00:00
|
|
|
from wtforms import Form
|
|
|
|
from wtforms.fields import BooleanField, IntegerField, StringField
|
2021-07-30 00:50:49 +00:00
|
|
|
|
2022-05-08 19:26:25 +00:00
|
|
|
from . import assistantSpace, db
|
2022-06-01 21:57:28 +00:00
|
|
|
from .advlabdb_independent_funs import (
|
|
|
|
deep_getattr,
|
|
|
|
flashRandomPassword,
|
|
|
|
missing_formatter,
|
|
|
|
str_formatter,
|
|
|
|
str_without_semester_formatter,
|
|
|
|
)
|
2022-05-08 19:26:25 +00:00
|
|
|
from .customClasses import SecureAssistantBaseView, SecureAssistantModelView
|
|
|
|
from .exceptions import DataBaseException, ModelViewException
|
2022-06-17 18:56:14 +00:00
|
|
|
from .model_dependent_funs import (
|
|
|
|
generate_new_password_field,
|
|
|
|
initActiveSemesterMenuLinks,
|
|
|
|
mark_field,
|
|
|
|
user_info_fields,
|
|
|
|
)
|
2022-05-29 17:03:54 +00:00
|
|
|
from .model_independent_funs import randomPassword
|
2022-05-08 19:26:25 +00:00
|
|
|
from .models import (
|
2022-04-11 23:44:53 +00:00
|
|
|
MAX_MARK,
|
|
|
|
MIN_MARK,
|
2021-07-30 00:50:49 +00:00
|
|
|
Appointment,
|
|
|
|
Assistant,
|
|
|
|
ExperimentMark,
|
|
|
|
GroupExperiment,
|
2021-07-30 12:20:54 +00:00
|
|
|
SemesterExperiment,
|
2021-07-30 00:50:49 +00:00
|
|
|
User,
|
|
|
|
)
|
|
|
|
|
|
|
|
|
2021-07-30 21:50:10 +00:00
|
|
|
class AssistantAppointmentView(SecureAssistantModelView):
|
2022-02-24 00:28:09 +00:00
|
|
|
can_edit = True
|
|
|
|
|
2021-07-31 22:41:21 +00:00
|
|
|
column_list = [
|
|
|
|
"date",
|
|
|
|
"special",
|
|
|
|
"group_experiment.semester_experiment.experiment",
|
2022-06-01 21:15:22 +00:00
|
|
|
"group_experiment.group.number",
|
2021-07-31 22:41:21 +00:00
|
|
|
"group_experiment.group.part_students",
|
|
|
|
]
|
|
|
|
column_labels = {
|
|
|
|
"group_experiment.semester_experiment.experiment": "Experiment",
|
2022-06-01 21:15:22 +00:00
|
|
|
"group_experiment.group.number": "Group number",
|
2021-07-31 22:41:21 +00:00
|
|
|
"group_experiment.group.part_students": "Students",
|
|
|
|
}
|
|
|
|
|
2021-11-30 00:47:37 +00:00
|
|
|
column_editable_list = [
|
|
|
|
"date",
|
|
|
|
]
|
2022-02-24 00:28:09 +00:00
|
|
|
form_columns = column_editable_list
|
2022-05-30 02:18:19 +00:00
|
|
|
column_descriptions = {
|
|
|
|
"special": "A special appointment should take place in the semester break",
|
|
|
|
}
|
2021-07-30 21:50:10 +00:00
|
|
|
|
2022-06-01 21:57:28 +00:00
|
|
|
def part_students_formatter(view, context, model, name):
|
|
|
|
part_students = deep_getattr(model, name)
|
|
|
|
if part_students is not None:
|
|
|
|
return ", ".join([str(part_student.student) for part_student in part_students])
|
|
|
|
|
|
|
|
return attr
|
|
|
|
|
|
|
|
column_formatters = {
|
|
|
|
"group_experiment.semester_experiment.experiment": str_formatter,
|
|
|
|
"group_experiment.group.part_students": part_students_formatter,
|
|
|
|
}
|
|
|
|
|
2022-05-16 22:42:49 +00:00
|
|
|
def query_modifier(self, query):
|
|
|
|
return (
|
|
|
|
query.join(GroupExperiment)
|
|
|
|
.join(SemesterExperiment)
|
|
|
|
.where(
|
|
|
|
SemesterExperiment.semester == current_user.active_semester,
|
|
|
|
Appointment.assistant == current_user.assistant,
|
|
|
|
)
|
2021-07-30 21:50:10 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
class AssistantExperimentMarkView(SecureAssistantModelView):
|
2022-06-01 21:03:41 +00:00
|
|
|
class EditForm(Form):
|
2022-06-17 18:56:14 +00:00
|
|
|
oral_mark = mark_field("Oral")
|
|
|
|
protocol_mark = mark_field("Protocol")
|
2022-06-01 21:03:41 +00:00
|
|
|
|
2022-02-24 00:28:09 +00:00
|
|
|
can_edit = True
|
2022-06-01 21:03:41 +00:00
|
|
|
column_display_actions = True
|
2022-02-24 00:28:09 +00:00
|
|
|
|
2021-07-31 22:41:21 +00:00
|
|
|
column_list = [
|
|
|
|
"oral_mark",
|
|
|
|
"protocol_mark",
|
2021-08-29 16:15:14 +00:00
|
|
|
"final_experiment_mark",
|
2022-06-01 21:57:28 +00:00
|
|
|
"group_experiment.semester_experiment.experiment.number",
|
2022-06-01 21:15:22 +00:00
|
|
|
"part_student.student",
|
|
|
|
"part_student.group.number",
|
2021-07-31 22:41:21 +00:00
|
|
|
"part_student.student.uni_email",
|
|
|
|
"part_student.student.contact_email",
|
|
|
|
"part_student.part",
|
|
|
|
"assistant",
|
2022-02-27 18:30:28 +00:00
|
|
|
"admin",
|
2021-07-31 22:41:21 +00:00
|
|
|
]
|
|
|
|
column_labels = {
|
2022-06-01 21:57:28 +00:00
|
|
|
"group_experiment.semester_experiment.experiment.number": "Experiment number",
|
2022-06-01 21:15:22 +00:00
|
|
|
"part_student.student": "Student",
|
|
|
|
"part_student.group.number": "Group number",
|
2021-07-31 22:41:21 +00:00
|
|
|
"part_student.student.uni_email": "Uni Email",
|
|
|
|
"part_student.student.contact_email": "Contact Email",
|
|
|
|
"part_student.part": "Part",
|
|
|
|
}
|
|
|
|
column_descriptions = {
|
2022-04-11 23:44:53 +00:00
|
|
|
"oral_mark": f"Between {MIN_MARK} and {MAX_MARK}",
|
|
|
|
"protocol_mark": f"Between {MIN_MARK} and {MAX_MARK}",
|
2021-08-29 16:15:14 +00:00
|
|
|
"final_experiment_mark": "Calculated automatically with oral and protocol marks and weightings",
|
2021-07-31 22:41:21 +00:00
|
|
|
"part_student.student.contact_email": "The preferred contact email address if entered by the student",
|
2022-02-27 18:30:28 +00:00
|
|
|
"assistant": "The last assistant who edited the mark",
|
|
|
|
"admin": "The last admin who edited the mark",
|
2021-07-31 22:41:21 +00:00
|
|
|
}
|
|
|
|
|
2022-05-30 02:29:02 +00:00
|
|
|
column_searchable_list = [
|
|
|
|
"part_student.student.first_name",
|
|
|
|
"part_student.student.last_name",
|
|
|
|
"part_student.student.uni_email",
|
|
|
|
"part_student.student.contact_email",
|
|
|
|
]
|
|
|
|
|
2022-06-01 21:57:28 +00:00
|
|
|
column_formatters = {
|
|
|
|
"oral_mark": missing_formatter,
|
|
|
|
"protocol_mark": missing_formatter,
|
|
|
|
"part_student.part": str_without_semester_formatter,
|
|
|
|
}
|
2021-07-30 00:50:49 +00:00
|
|
|
|
2021-07-30 21:50:10 +00:00
|
|
|
column_default_sort = [("oral_mark", False), ("protocol_mark", False)]
|
2021-07-30 00:50:49 +00:00
|
|
|
|
2022-05-21 16:30:23 +00:00
|
|
|
def query_modifier(self, query):
|
|
|
|
return (
|
|
|
|
query.join(GroupExperiment)
|
|
|
|
.join(SemesterExperiment)
|
|
|
|
.where(SemesterExperiment.semester == current_user.active_semester)
|
|
|
|
.join(SemesterExperiment.assistants)
|
|
|
|
.where(Assistant.user == current_user)
|
2021-07-30 00:50:49 +00:00
|
|
|
)
|
|
|
|
|
2021-08-21 21:08:32 +00:00
|
|
|
def update_model(self, form, model):
|
2022-05-15 20:25:19 +00:00
|
|
|
if (form.oral_mark is not None and form.oral_mark.data != model.oral_mark) or (
|
|
|
|
form.protocol_mark is not None and form.protocol_mark.data != model.protocol_mark
|
2021-08-21 21:08:32 +00:00
|
|
|
):
|
|
|
|
model.assistant = current_user.assistant
|
2021-07-30 00:50:49 +00:00
|
|
|
|
2022-05-15 20:25:19 +00:00
|
|
|
updateSuccessful = super().update_model(form, model)
|
2021-07-30 00:50:49 +00:00
|
|
|
|
2021-08-21 21:08:32 +00:00
|
|
|
model.part_student.checkThenSetFinalPartMark()
|
|
|
|
|
2022-05-15 20:25:19 +00:00
|
|
|
return updateSuccessful
|
2021-08-21 21:08:32 +00:00
|
|
|
else:
|
|
|
|
# Nothing changed
|
|
|
|
return True
|
2021-07-30 00:50:49 +00:00
|
|
|
|
2021-07-30 21:50:10 +00:00
|
|
|
|
2021-11-30 00:47:37 +00:00
|
|
|
class AssistantUserView(SecureAssistantModelView):
|
2022-02-23 19:36:29 +00:00
|
|
|
class EditForm(Form):
|
2022-06-17 18:56:14 +00:00
|
|
|
phone_number, mobile_phone_number, building, room = user_info_fields()
|
2022-02-23 19:36:29 +00:00
|
|
|
|
2022-06-17 18:56:14 +00:00
|
|
|
generate_new_password = generate_new_password_field()
|
2022-02-23 19:36:29 +00:00
|
|
|
|
|
|
|
can_edit = True
|
2022-05-30 13:38:20 +00:00
|
|
|
can_view_details = True
|
2022-02-23 19:36:29 +00:00
|
|
|
column_display_actions = True
|
|
|
|
|
2021-11-30 00:47:37 +00:00
|
|
|
column_sortable_list = []
|
|
|
|
|
|
|
|
column_list = [
|
|
|
|
"email",
|
|
|
|
"phone_number",
|
|
|
|
"mobile_phone_number",
|
|
|
|
"building",
|
2022-02-23 19:36:29 +00:00
|
|
|
"room",
|
2021-11-30 00:47:37 +00:00
|
|
|
"assistant.semester_experiments",
|
|
|
|
]
|
|
|
|
column_labels = {
|
|
|
|
"assistant.semester_experiments": "Semester Experiments",
|
|
|
|
}
|
|
|
|
|
2022-05-21 16:30:23 +00:00
|
|
|
def query_modifier(self, query):
|
|
|
|
return query.where(User.id == current_user.id)
|
2021-11-30 00:47:37 +00:00
|
|
|
|
2022-02-23 19:36:29 +00:00
|
|
|
def on_model_change(self, form, model, is_created):
|
|
|
|
if form.generate_new_password.data:
|
|
|
|
password = randomPassword()
|
|
|
|
flashRandomPassword(password)
|
|
|
|
|
|
|
|
admin_change_password(model, password, notify=False) # Password is automatically hashed with this function
|
|
|
|
|
2021-11-30 00:47:37 +00:00
|
|
|
|
2022-02-23 18:37:09 +00:00
|
|
|
class AssistantDocsView(SecureAssistantBaseView):
|
2022-03-04 02:49:02 +00:00
|
|
|
@expose("/")
|
2022-02-23 18:37:09 +00:00
|
|
|
def index(self):
|
2022-05-30 15:02:00 +00:00
|
|
|
return self.render("docs/docs.html", role="assistant")
|
2022-02-23 18:37:09 +00:00
|
|
|
|
|
|
|
|
2021-07-30 21:50:10 +00:00
|
|
|
assistantSpace.add_view(
|
|
|
|
AssistantAppointmentView(Appointment, db.session, endpoint="assistant_appointment", url="appointment")
|
|
|
|
)
|
2021-07-30 00:50:49 +00:00
|
|
|
assistantSpace.add_view(
|
2022-05-30 15:02:00 +00:00
|
|
|
AssistantExperimentMarkView(ExperimentMark, db.session, endpoint="assistant_experimentmark", url="experiment_mark")
|
2021-07-30 00:50:49 +00:00
|
|
|
)
|
2021-11-30 00:47:37 +00:00
|
|
|
assistantSpace.add_view(AssistantUserView(User, db.session, endpoint="assistant_user", url="user"))
|
2022-02-23 18:37:09 +00:00
|
|
|
assistantSpace.add_view(AssistantDocsView(name="Docs", endpoint="assistant_docs", url="docs"))
|
2021-07-30 22:12:37 +00:00
|
|
|
|
|
|
|
initActiveSemesterMenuLinks(assistantSpace)
|