mirror of
https://codeberg.org/Mo8it/AdvLabDB.git
synced 2024-11-08 21:21:06 +00:00
250 lines
8 KiB
Python
250 lines
8 KiB
Python
from flask import flash
|
|
from flask_admin import expose
|
|
from flask_security import admin_change_password, current_user
|
|
from wtforms import Form
|
|
from wtforms.fields import TextAreaField
|
|
from wtforms.validators import Optional
|
|
|
|
from . import assistantSpace, db
|
|
from .advlabdb_independent_funs import (
|
|
deep_getattr,
|
|
flashRandomPassword,
|
|
missing_formatter,
|
|
str_formatter,
|
|
str_without_semester_formatter,
|
|
)
|
|
from .customClasses import SecureAssistantBaseView, SecureAssistantModelView
|
|
from .exceptions import DataBaseException, ModelViewException
|
|
from .model_dependent_funs import (
|
|
generate_new_password_field,
|
|
initActiveSemesterMenuLinks,
|
|
mark_field,
|
|
user_info_fields,
|
|
)
|
|
from .model_independent_funs import randomPassword
|
|
from .models import (
|
|
MAX_MARK,
|
|
MIN_MARK,
|
|
Appointment,
|
|
Assistant,
|
|
ExperimentMark,
|
|
GroupExperiment,
|
|
SemesterExperiment,
|
|
User,
|
|
)
|
|
|
|
|
|
class AssistantGroupExperimentView(SecureAssistantModelView):
|
|
class EditForm(Form):
|
|
note = TextAreaField(
|
|
"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.",
|
|
)
|
|
|
|
can_edit = True
|
|
column_display_actions = True
|
|
|
|
column_list = [
|
|
"semester_experiment.experiment",
|
|
"group.number",
|
|
"note",
|
|
]
|
|
column_labels = {
|
|
"semester_experiment.experiment": "Experiment",
|
|
"group.number": "Group number",
|
|
}
|
|
column_formatters = {
|
|
"semester_experiment.experiment": str_formatter,
|
|
}
|
|
|
|
def query_modifier(self, query):
|
|
return (
|
|
query.join(SemesterExperiment)
|
|
.where(SemesterExperiment.semester == current_user.active_semester)
|
|
.join(SemesterExperiment.assistants)
|
|
.where(Assistant.user == current_user)
|
|
)
|
|
|
|
|
|
class AssistantAppointmentView(SecureAssistantModelView):
|
|
can_edit = True
|
|
|
|
column_list = [
|
|
"date",
|
|
"special",
|
|
"group_experiment.semester_experiment.experiment",
|
|
"group_experiment.group.number",
|
|
"group_experiment.group.part_students",
|
|
]
|
|
column_labels = {
|
|
"group_experiment.semester_experiment.experiment": "Experiment",
|
|
"group_experiment.group.number": "Group number",
|
|
"group_experiment.group.part_students": "Students",
|
|
}
|
|
|
|
column_editable_list = [
|
|
"date",
|
|
]
|
|
form_columns = column_editable_list
|
|
column_descriptions = {
|
|
"special": "A special appointment should take place in the semester break",
|
|
}
|
|
|
|
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,
|
|
}
|
|
|
|
def query_modifier(self, query):
|
|
return (
|
|
query.join(GroupExperiment)
|
|
.join(SemesterExperiment)
|
|
.where(
|
|
SemesterExperiment.semester == current_user.active_semester,
|
|
Appointment.assistant == current_user.assistant,
|
|
)
|
|
)
|
|
|
|
|
|
class AssistantExperimentMarkView(SecureAssistantModelView):
|
|
class EditForm(Form):
|
|
oral_mark = mark_field("Oral")
|
|
protocol_mark = mark_field("Protocol")
|
|
|
|
can_edit = True
|
|
column_display_actions = True
|
|
|
|
column_list = [
|
|
"oral_mark",
|
|
"protocol_mark",
|
|
"final_experiment_mark",
|
|
"group_experiment.semester_experiment.experiment.number",
|
|
"part_student.student",
|
|
"part_student.group.number",
|
|
"part_student.student.uni_email",
|
|
"part_student.student.contact_email",
|
|
"part_student.part",
|
|
"assistant",
|
|
"admin",
|
|
]
|
|
column_labels = {
|
|
"group_experiment.semester_experiment.experiment.number": "Experiment number",
|
|
"part_student.student": "Student",
|
|
"part_student.group.number": "Group number",
|
|
"part_student.student.uni_email": "Uni Email",
|
|
"part_student.student.contact_email": "Contact Email",
|
|
"part_student.part": "Part",
|
|
}
|
|
column_descriptions = {
|
|
"oral_mark": f"Between {MIN_MARK} and {MAX_MARK}",
|
|
"protocol_mark": f"Between {MIN_MARK} and {MAX_MARK}",
|
|
"final_experiment_mark": "Calculated automatically with oral and protocol marks and weightings",
|
|
"part_student.student.contact_email": "The preferred contact email address if entered by the student",
|
|
"assistant": "The last assistant who edited the mark",
|
|
"admin": "The last admin who edited the mark",
|
|
}
|
|
|
|
column_searchable_list = [
|
|
"part_student.student.first_name",
|
|
"part_student.student.last_name",
|
|
"part_student.student.uni_email",
|
|
"part_student.student.contact_email",
|
|
]
|
|
|
|
column_formatters = {
|
|
"oral_mark": missing_formatter,
|
|
"protocol_mark": missing_formatter,
|
|
"part_student.part": str_without_semester_formatter,
|
|
}
|
|
|
|
column_default_sort = [("oral_mark", False), ("protocol_mark", False)]
|
|
|
|
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)
|
|
)
|
|
|
|
def update_model(self, form, model):
|
|
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
|
|
):
|
|
model.assistant = current_user.assistant
|
|
|
|
updateSuccessful = super().update_model(form, model)
|
|
|
|
model.part_student.checkThenSetFinalPartMark()
|
|
|
|
return updateSuccessful
|
|
else:
|
|
# Nothing changed
|
|
return True
|
|
|
|
|
|
class AssistantUserView(SecureAssistantModelView):
|
|
class EditForm(Form):
|
|
phone_number, mobile_phone_number, building, room = user_info_fields()
|
|
|
|
generate_new_password = generate_new_password_field()
|
|
|
|
can_edit = True
|
|
can_view_details = True
|
|
column_display_actions = True
|
|
|
|
column_sortable_list = []
|
|
|
|
column_list = [
|
|
"email",
|
|
"phone_number",
|
|
"mobile_phone_number",
|
|
"building",
|
|
"room",
|
|
"assistant.semester_experiments",
|
|
]
|
|
column_labels = {
|
|
"assistant.semester_experiments": "Semester Experiments",
|
|
}
|
|
|
|
def query_modifier(self, query):
|
|
return query.where(User.id == current_user.id)
|
|
|
|
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
|
|
|
|
|
|
class AssistantDocsView(SecureAssistantBaseView):
|
|
@expose("/")
|
|
def index(self):
|
|
return self.render("docs/docs.html", role="assistant")
|
|
|
|
|
|
assistantSpace.add_view(
|
|
AssistantGroupExperimentView(
|
|
GroupExperiment, db.session, endpoint="assistant_groupexperiment", url="group_experiment"
|
|
)
|
|
)
|
|
assistantSpace.add_view(
|
|
AssistantAppointmentView(Appointment, db.session, endpoint="assistant_appointment", url="appointment")
|
|
)
|
|
assistantSpace.add_view(
|
|
AssistantExperimentMarkView(ExperimentMark, db.session, endpoint="assistant_experimentmark", url="experiment_mark")
|
|
)
|
|
assistantSpace.add_view(AssistantUserView(User, db.session, endpoint="assistant_user", url="user"))
|
|
assistantSpace.add_view(AssistantDocsView(name="Docs", endpoint="assistant_docs", url="docs"))
|
|
|
|
initActiveSemesterMenuLinks(assistantSpace)
|