mirror of
https://codeberg.org/Mo8it/AdvLabDB.git
synced 2024-11-08 21:21:06 +00:00
181 lines
7.6 KiB
Python
181 lines
7.6 KiB
Python
from flask import url_for, flash, request
|
|
from flask_admin.menu import MenuLink
|
|
from flask_admin.contrib.sqla.filters import BaseSQLAFilter
|
|
from flask_security import hash_password
|
|
from wtforms import BooleanField, SelectField, TextField
|
|
from wtforms.validators import DataRequired, Email
|
|
|
|
from advlabdb import admin, app, user_datastore, db
|
|
from advlabdb.utils import randomPassword, userActiveSemester, partFromLabelInUserActiveSemester, setActiveSemester
|
|
from advlabdb.customClasses import SecureModelView
|
|
from advlabdb.models import User, Role, Semester, Part, Student, PartStudent, Group, GroupExperiment, Experiment, Assistant, Appointment, PartExperiment, ExperimentMark
|
|
from advlabdb.configUtils import getConfig
|
|
|
|
class UserModelView(SecureModelView):
|
|
column_list = ["email", "active", "roles", "assistant"]
|
|
column_searchable_list = ["email"]
|
|
column_filters = ["active"]
|
|
form_columns = ["email", "active", "roles"]
|
|
|
|
form_args = {
|
|
"email": {"validators": [Email()]},
|
|
"active": {"default": True},
|
|
"roles": {"validators": [DataRequired(message="A role is required!")]}
|
|
}
|
|
|
|
def create_model(self, form):
|
|
password = randomPassword()
|
|
passwordHash = hash_password(password)
|
|
|
|
email = form.email.data.lower()
|
|
|
|
roles = [role.name for role in form.roles.data]
|
|
if "admin" in roles:
|
|
flash("You have registered a new admin!", "danger")
|
|
|
|
model = user_datastore.create_user(email=email, password=passwordHash, roles=roles)
|
|
db.session.commit()
|
|
flash(f"{email} registered with roles: {', '.join([role.name for role in form.roles.data])}.", category="success")
|
|
flash(f"Random password: {password}", category="warning")
|
|
return model
|
|
|
|
|
|
class RoleModelView(SecureModelView):
|
|
column_exclude_list = ["update_datetime"]
|
|
|
|
|
|
class SemesterModelView(SecureModelView):
|
|
column_list = ["label", "parts"]
|
|
form_columns = ["label", "create_parts"]
|
|
|
|
form_extra_fields = {
|
|
"create_parts": BooleanField("Create parts:" + ", ".join(getConfig("partsLabels")) + ".", default=True)
|
|
}
|
|
|
|
def after_model_change(self, form, model, is_created):
|
|
if form.create_parts.data:
|
|
if is_created == False and model.parts != []:
|
|
flash("This semester already has parts!", "danger")
|
|
return
|
|
|
|
for partLabel in getConfig("partsLabels"):
|
|
db.session.add(Part(label=partLabel, semester=model))
|
|
db.session.commit()
|
|
|
|
if is_created:
|
|
admin.add_link(MenuLink(name=model.label,
|
|
url=url_for("set_semester") + "?semester_id=" + str(model.id),
|
|
category="Active semester"))
|
|
setActiveSemester(model.id)
|
|
|
|
|
|
class PartModelView(SecureModelView):
|
|
can_view_details = True
|
|
column_details_list = ["label", "semester", "part_experiments", "part_students", "groups"]
|
|
form_columns = ["label", "semester"]
|
|
|
|
partsLabels = getConfig("partsLabels")
|
|
form_choices = {"label": list(zip(partsLabels, partsLabels))}
|
|
|
|
|
|
class StudentModelView(SecureModelView):
|
|
can_view_details = True
|
|
column_list = ["student_number", "first_name", "last_name", "uni_email", "contact_email", "part_students"]
|
|
column_details_list = column_list + ["bachelor_thesis", "bachelor_thesis_work_group", "note"]
|
|
column_searchable_list = ["student_number", "uni_email", "contact_email", "first_name", "last_name"]
|
|
form_columns = column_details_list + ["new_part_student_part", "new_part_student_group_number"]
|
|
|
|
form_args = {
|
|
"uni_email": {"validators": [Email()]},
|
|
"contact_email": {"validators": [Email()]},
|
|
}
|
|
|
|
partChoices = ["-"] + getConfig("partsLabels")
|
|
form_extra_fields = {
|
|
"new_part_student_part": SelectField("Part", choices=list(zip(partChoices, partChoices)), default=partChoices[0]),
|
|
"new_part_student_group_number": TextField("Group number")
|
|
}
|
|
|
|
def validate_form(self, form):
|
|
if request.method == "POST":
|
|
partLabel = form.new_part_student_part.data
|
|
groupNumber = form.new_part_student_group_number.data
|
|
if (partLabel != self.partChoices[0] and groupNumber == "") or (partLabel == self.partChoices[0] and groupNumber != ""):
|
|
flash("You have to assign both part and group if you want to add a part student!", "danger")
|
|
return False
|
|
if partLabel != self.partChoices[0] and not partFromLabelInUserActiveSemester(partLabel):
|
|
flash(f"Part {partLabel} is not created in {str(userActiveSemester())} yet!", "danger")
|
|
return False
|
|
if groupNumber != "":
|
|
message = "The group number has to be an integer > 0 !"
|
|
try:
|
|
groupNumber = int(groupNumber)
|
|
except:
|
|
flash(message, "danger")
|
|
return False
|
|
if groupNumber < 1:
|
|
flash(message, "danger")
|
|
return False
|
|
return super().validate_form(form)
|
|
|
|
def after_model_change(self, form, model, is_created):
|
|
partLabel = form.new_part_student_part.data
|
|
print("\nLL\n")
|
|
if partLabel != self.partChoices[0]:
|
|
groupNumber = int(form.new_part_student_group_number.data)
|
|
|
|
part = partFromLabelInUserActiveSemester(partLabel)
|
|
group = Group.query.filter(Group.number == groupNumber, Group.part == part).first()
|
|
|
|
if group is None:
|
|
group = Group(number=groupNumber, part=part)
|
|
db.session.add(group)
|
|
flash(f"Added the new group with number {str(groupNumber)} in part {str(part)}.", "success")
|
|
|
|
partStudent = PartStudent(student=model, part=part, group=group)
|
|
db.session.add(partStudent)
|
|
db.session.commit()
|
|
flash("Added part student.", "success")
|
|
|
|
|
|
class PartFilter(BaseSQLAFilter):
|
|
def apply(self, query, value, alias=None):
|
|
return query.filter(self.column == partFromLabelInUserActiveSemester(value).id)
|
|
|
|
def operation(self):
|
|
return "equals"
|
|
|
|
def validate(self, value):
|
|
if partFromLabelInUserActiveSemester(value):
|
|
return True
|
|
else:
|
|
flash(f"Part {value} not found in your active semester {userActiveSemester()}!", "danger")
|
|
return False
|
|
|
|
|
|
class PartStudentModelView(SecureModelView):
|
|
partsLabels = getConfig("partsLabels")
|
|
column_filters = [PartFilter(PartStudent.part_id, "Part", options=list(zip(partsLabels, partsLabels)))]
|
|
form_excluded_columns = ["experiment_marks"]
|
|
|
|
|
|
admin.add_view(StudentModelView(Student, db.session))
|
|
admin.add_view(PartStudentModelView(PartStudent, db.session))
|
|
admin.add_view(SecureModelView(Group, db.session))
|
|
admin.add_view(SecureModelView(GroupExperiment, db.session))
|
|
admin.add_view(SecureModelView(Experiment, db.session))
|
|
admin.add_view(SecureModelView(PartExperiment, db.session))
|
|
admin.add_view(SecureModelView(Assistant, db.session))
|
|
admin.add_view(SecureModelView(Appointment, db.session))
|
|
admin.add_view(PartModelView(Part, db.session))
|
|
admin.add_view(SemesterModelView(Semester, db.session))
|
|
admin.add_view(SecureModelView(ExperimentMark, db.session))
|
|
admin.add_view(UserModelView(User, db.session))
|
|
admin.add_view(RoleModelView(Role, db.session))
|
|
|
|
with app.app_context():
|
|
semesters = Semester.query.all()[::-1]
|
|
for semester in semesters:
|
|
admin.add_link(MenuLink(name=semester.label,
|
|
url=url_for("set_semester") + "?semester_id=" + str(semester.id),
|
|
category="Active semester"))
|