mirror of
https://codeberg.org/Mo8it/AdvLabDB.git
synced 2024-11-08 21:21:06 +00:00
212 lines
6.7 KiB
Python
212 lines
6.7 KiB
Python
from flask import flash
|
|
from flask_admin import expose
|
|
from flask_admin.contrib.sqla.fields import QuerySelectField, QuerySelectMultipleField
|
|
from flask_security import admin_change_password, current_user
|
|
from sqlalchemy import and_
|
|
from wtforms import BooleanField, Form, RadioField, SelectField, StringField
|
|
from wtforms.fields import DateField
|
|
from wtforms.validators import NumberRange, Optional
|
|
|
|
from . import assistantSpace, db
|
|
from .advlabdb_independent_funs import flashRandomPassword
|
|
from .customClasses import SecureAssistantBaseView, SecureAssistantModelView
|
|
from .exceptions import DataBaseException, ModelViewException
|
|
from .model_dependent_funs import initActiveSemesterMenuLinks
|
|
from .model_independent_funs import randomPassword
|
|
from .models import (
|
|
MAX_MARK,
|
|
MIN_MARK,
|
|
Appointment,
|
|
Assistant,
|
|
Experiment,
|
|
ExperimentMark,
|
|
Group,
|
|
GroupExperiment,
|
|
Part,
|
|
PartStudent,
|
|
Program,
|
|
Role,
|
|
Semester,
|
|
SemesterExperiment,
|
|
Student,
|
|
User,
|
|
)
|
|
|
|
|
|
class AssistantAppointmentView(SecureAssistantModelView):
|
|
can_edit = True
|
|
|
|
column_list = [
|
|
"date",
|
|
"special",
|
|
"group_experiment.semester_experiment.experiment",
|
|
"group_experiment.group",
|
|
"group_experiment.group.part_students",
|
|
]
|
|
column_labels = {
|
|
"group_experiment.semester_experiment.experiment": "Experiment",
|
|
"group_experiment.group": "Group",
|
|
"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 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):
|
|
can_edit = True
|
|
|
|
column_list = [
|
|
"oral_mark",
|
|
"protocol_mark",
|
|
"final_experiment_mark",
|
|
"group_experiment.semester_experiment.experiment",
|
|
"part_student.student.first_name",
|
|
"part_student.student.last_name",
|
|
"part_student.group",
|
|
"part_student.student.uni_email",
|
|
"part_student.student.contact_email",
|
|
"part_student.part",
|
|
"assistant",
|
|
"admin",
|
|
]
|
|
column_labels = {
|
|
"group_experiment.semester_experiment.experiment": "Experiment",
|
|
"part_student.student.first_name": "First Name",
|
|
"part_student.student.last_name": "Last Name",
|
|
"part_student.group": "Group",
|
|
"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_editable_list = [
|
|
"oral_mark",
|
|
"protocol_mark",
|
|
]
|
|
form_columns = column_editable_list
|
|
|
|
form_args = {
|
|
"oral_mark": {"validators": [NumberRange(MIN_MARK, MAX_MARK)]},
|
|
"protocol_mark": {"validators": [NumberRange(MIN_MARK, MAX_MARK)]},
|
|
}
|
|
|
|
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 = StringField(
|
|
"Phone Number",
|
|
validators=[Optional()],
|
|
)
|
|
mobile_phone_number = StringField(
|
|
"Mobile Phone Number",
|
|
validators=[Optional()],
|
|
)
|
|
|
|
building = StringField(
|
|
"Building",
|
|
validators=[Optional()],
|
|
)
|
|
room = StringField(
|
|
"Room",
|
|
validators=[Optional()],
|
|
)
|
|
|
|
generate_new_password = BooleanField(
|
|
"Generate new random password. For security reasons, it is not possible to manually enter a password. Please use a password manager like Bitwarden or KeepassXC to save the randomly generated password.",
|
|
default=False,
|
|
)
|
|
|
|
can_edit = 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/assistant.html")
|
|
|
|
|
|
assistantSpace.add_view(
|
|
AssistantAppointmentView(Appointment, db.session, endpoint="assistant_appointment", url="appointment")
|
|
)
|
|
assistantSpace.add_view(
|
|
AssistantExperimentMarkView(ExperimentMark, db.session, endpoint="assistant_experimentmark", url="experimentmark")
|
|
)
|
|
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)
|