diff --git a/advlabdb/adminModelViews.py b/advlabdb/adminModelViews.py index 0aadda9..eae51b1 100644 --- a/advlabdb/adminModelViews.py +++ b/advlabdb/adminModelViews.py @@ -3,7 +3,7 @@ from pathlib import Path from flask import flash, redirect, request, url_for from flask_admin import expose from flask_admin.contrib.sqla.fields import QuerySelectField, QuerySelectMultipleField -from flask_admin.contrib.sqla.filters import BaseSQLAFilter +from flask_admin.contrib.sqla.filters import FilterEqual from flask_admin.helpers import get_form_data from flask_admin.menu import MenuLink from flask_admin.model.template import EndpointLinkRowAction @@ -211,6 +211,10 @@ class UserView(SecureAdminModelView): assistant = Assistant(user=model, semester_experiments=semester_experiments) self.session.add(assistant) + if model.has_role("admin") and not model.admin: + admin = Admin(user=model) + self.session.add(admin) + class RoleView(SecureAdminModelView): can_create = False @@ -835,19 +839,24 @@ class AppointmentView(SecureAdminModelView): class ExperimentMarkView(SecureAdminModelView): - class StudentIdFilter(BaseSQLAFilter): - def apply(self, query, value, alias=None): - return query.filter(self.column == value) - - def operation(self): - return "equals" + @expose("/") + def index_view(self): + # To update filter options + self._refresh_filters_cache() + return super().index_view() + class StudentFilter(FilterEqual): def validate(self, value): if Student.query.get(value): return True else: return False + class AssistantFilter(FilterEqual): + def get_options(self, view): + assistants = Assistant.query.filter(Assistant.user.has(User.active == True)).all() + return ((assistant.id, assistant.repr()) for assistant in assistants) + class CreateForm(Form): part_student = QuerySelectField( "Part Student", @@ -882,20 +891,19 @@ class ExperimentMarkView(SecureAdminModelView): "oral_mark": "Between 0 and 15", "protocol_mark": "Between 0 and 15", "final_experiment_mark": "Calculated automatically with oral and protocol marks and weightings", - "assistant": "The assistant who assigned the mark", - "edited_by_admin": "If the mark was edited by an admin", + "assistant": "The last assistant who edited the mark", + "admin": "The last admin who edited the mark", } column_filters = [ - StudentIdFilter(PartStudent.id, "Student / ID"), + StudentFilter(PartStudent.id, "Student / ID"), "part_student.part.program", "part_student.part", "part_student.student", "group_experiment.group", "group_experiment.semester_experiment.semester", "group_experiment.semester_experiment.experiment", - "edited_by_admin", - "assistant.user", + AssistantFilter(Assistant.id, "Assistant"), "oral_mark", "protocol_mark", "final_experiment_mark", @@ -923,7 +931,7 @@ class ExperimentMarkView(SecureAdminModelView): if (form.oral_mark and form.oral_mark.data != model.oral_mark) or ( form.protocol_mark and form.protocol_mark.data != model.protocol_mark ): - model.edited_by_admin = True + model.admin = current_user.admin ret = super().update_model(form, model) diff --git a/advlabdb/assistantModelViews.py b/advlabdb/assistantModelViews.py index 65a8759..15f8264 100644 --- a/advlabdb/assistantModelViews.py +++ b/advlabdb/assistantModelViews.py @@ -79,7 +79,7 @@ class AssistantExperimentMarkView(SecureAssistantModelView): "part_student.student.contact_email", "part_student.part", "assistant", - "edited_by_admin", + "admin", ] column_labels = { "group_experiment.semester_experiment.experiment": "Experiment", @@ -95,8 +95,8 @@ class AssistantExperimentMarkView(SecureAssistantModelView): "protocol_mark": "Between 0 and 15", "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 assistant who assigned the mark", - "edited_by_admin": "If the mark was edited by an admin", + "assistant": "The last assistant who edited the mark", + "admin": "The last admin who edited the mark", } column_editable_list = [ diff --git a/advlabdb/models.py b/advlabdb/models.py index 46be52a..bfa7cae 100644 --- a/advlabdb/models.py +++ b/advlabdb/models.py @@ -326,6 +326,20 @@ class Assistant(db.Model): return f"" +class Admin(db.Model): + id = db.Column(db.Integer, primary_key=True) + + user_id = db.Column(db.Integer, db.ForeignKey("user.id"), nullable=False, unique=True) + + experiment_marks = db.relationship("ExperimentMark", backref="admin", lazy=True) + + def repr(self): + return f"{self.user.first_name} {self.user.last_name}" + + def __repr__(self): + return f"" + + class Appointment(db.Model): id = db.Column(db.Integer, primary_key=True) date = db.Column(db.Date, nullable=False) # To be specified with the python package "datetime" @@ -493,13 +507,12 @@ class ExperimentMark(db.Model): nullable=True, ) - edited_by_admin = db.Column(db.Boolean, default=False, nullable=False) # TODO: Admin id - part_student_id = db.Column(db.Integer, db.ForeignKey("part_student.id"), nullable=False) group_experiment_id = db.Column(db.Integer, db.ForeignKey("group_experiment.id"), nullable=False) assistant_id = db.Column( db.Integer, db.ForeignKey("assistant.id"), nullable=True - ) # The assistant who gave the mark + ) # The last assistant who edited the mark + admin_id = db.Column(db.Integer, db.ForeignKey("admin.id"), nullable=True) # The last admin who edited the mark __table_args__ = (db.UniqueConstraint(part_student_id, group_experiment_id),) @@ -529,6 +542,7 @@ class User(db.Model, FsUserMixin): active_semester_id = db.Column(db.Integer, db.ForeignKey("semester.id"), nullable=True) + admin = db.relationship("Admin", backref="user", lazy=False, uselist=False) assistant = db.relationship("Assistant", backref="user", lazy=True, uselist=False) def repr(self): diff --git a/testDB.py b/testDB.py index 4d34563..c1e63b9 100644 --- a/testDB.py +++ b/testDB.py @@ -98,7 +98,7 @@ with app.app_context(): user_datastore.create_role(name="admin") user_datastore.create_role(name="assistant") - user_datastore.create_user( + admin_user = user_datastore.create_user( email="admin@advlabdb.de", password=hash_password("admin"), roles=["admin"], @@ -106,6 +106,10 @@ with app.app_context(): last_name="Blümler", ) + admin = Admin(user=admin_user) + + db.session.add(admin) + us1 = user_datastore.create_user( email="test@protonmail.com", password=hash_password("h1"), @@ -123,9 +127,7 @@ with app.app_context(): last_name="l", ) - as1 = Assistant( - user=us1, - ) + as1 = Assistant(user=us1) as2 = Assistant(user=us2) as1.semester_experiments.append(sx1)