diff --git a/DB.drawio b/DB.drawio index 0be006b..b567c33 100644 --- a/DB.drawio +++ b/DB.drawio @@ -1 +1 @@ -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 \ No newline at end of file +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 \ No newline at end of file diff --git a/advlabdb/modelViews.py b/advlabdb/modelViews.py index 43c10ed..656cd8f 100644 --- a/advlabdb/modelViews.py +++ b/advlabdb/modelViews.py @@ -8,6 +8,10 @@ from advlabdb import admin, app, user_datastore, db from advlabdb.models import * from advlabdb.utils import randomPassword + +partsLabels = ["A/1", "A/2", "B/1", "B/2"] + + class UserModelView(SecureModelView): column_list = ["email", "active", "roles", "assistant"] column_searchable_list = ["email"] @@ -40,10 +44,8 @@ class SemesterModelView(SecureModelView): column_list = ["label", "parts"] form_columns = ["label", "create_parts"] - parts = ["A/1", "A/2", "B/1", "B/2"] - form_extra_fields = { - "create_parts": BooleanField("Create parts:" + ", ".join(parts) + ".", default=True) + "create_parts": BooleanField("Create parts:" + ", ".join(partsLabels) + ".", default=True) } def after_model_change(self, form, model, is_created): @@ -58,7 +60,16 @@ class PartModelView(SecureModelView): column_details_list = ["label", "semester", "part_experiments", "part_students", "groups"] form_columns = ["label", "semester"] -admin.add_view(SecureModelView(Student, db.session)) + +class StudentModelView(SecureModelView): + can_view_details = True + column_list = ["student_number", "first_name", "last_name", "email", "part_students"] + column_details_list = column_list + ["bachelor_thesis", "bachelor_thesis_work_group"] + column_searchable_list = ["student_number", "email", "first_name", "last_name"] + form_columns = column_list + + +admin.add_view(StudentModelView(Student, db.session)) admin.add_view(SecureModelView(PartStudent, db.session)) admin.add_view(SecureModelView(Group, db.session)) admin.add_view(SecureModelView(GroupExperiment, db.session)) diff --git a/advlabdb/models.py b/advlabdb/models.py index a4dfcb2..4a3c28e 100644 --- a/advlabdb/models.py +++ b/advlabdb/models.py @@ -134,7 +134,7 @@ class Part(db.Model): class Semester(db.Model): id = db.Column(db.Integer, primary_key=True) - label = db.Column(db.String(100), nullable=False) # WS2122 for example + label = db.Column(db.String(100), nullable=False, unique=True) # WS2122 for example parts = db.relationship("Part", backref="semester", lazy=True) def __repr__(self): @@ -154,6 +154,7 @@ class ExperimentMark(db.Model): class User(db.Model, FsUserMixin): assistant = db.relationship("Assistant", backref="user", lazy=True, uselist=False) + active_semester_id = db.Column(db.Integer, nullable=True) def __repr__(self): return f"" diff --git a/advlabdb/routes.py b/advlabdb/routes.py index 91ff43e..d49650b 100644 --- a/advlabdb/routes.py +++ b/advlabdb/routes.py @@ -1,6 +1,6 @@ import json from advlabdb import app, user_datastore -from flask import render_template, request, url_for, flash, redirect, session +from flask import render_template, request, url_for, flash, redirect from flask_security import auth_required, roles_required, hash_password, current_user from advlabdb.utils import * @@ -18,19 +18,6 @@ def util_processor(): str(semester.id) + '">' + semester.label + '') return items - def activeSemesterLabel(): - lastSemesterId = Semester.query.all()[-1].id - if "activeSemesterId" not in session: - session["activeSemesterId"] = lastSemesterId - elif session["activeSemesterId"] != lastSemesterId: - activeSemester = Semester.query.get(session['activeSemesterId']) - if activeSemester: - flash(f"You are in the old semester {activeSemester.label}!", "warning") - else: - flash(f"Semester changed!", "warning") - session["activeSemesterId"] = lastSemesterId - return Semester.query.get(session["activeSemesterId"]).label - def navbarItems(title): adminPages = ["Students", "Assistants", "Experiments", "Appointments", "Groups", "Users", "Semesters"] assistantPages = ["Students", "Assistants", "Experiments", "Appointments", "Groups"] @@ -61,7 +48,7 @@ def util_processor(): return items return dict(semesterDropDownItems=semesterDropDownItems, - activeSemesterLabel=activeSemesterLabel, + userActiveSemester=userActiveSemester, navbarItems=navbarItems, current_user=current_user, ) @@ -76,7 +63,7 @@ def index(): @app.route("/students") @roles_required("admin") def students(): - semester = Semester.query.get(session["activeSemesterId"]) + semester = Semester.query.get(current_user.active_semester_id) parts = semester.parts tables = [] tablesLabels = [] @@ -128,7 +115,7 @@ def assistants(): @app.route("/experiments") @roles_required("admin") def experiments(): - semester = Semester.query.get(session["activeSemesterId"]) + semester = Semester.query.get(current_user.active_semester_id) parts = semester.parts tables = [] tablesLabels = [] @@ -159,7 +146,7 @@ def appointments(): @app.route("/groups") @roles_required("admin") def groups(): - semester = Semester.query.get(session["activeSemesterId"]) + semester = Semester.query.get(current_user.active_semester_id) parts = semester.parts tables = [] tablesLabels = [] @@ -219,5 +206,5 @@ def semesters(): @app.route("/set_semester", methods=["GET"]) @auth_required() def set_semester(): - session["activeSemesterId"] = int(request.args.get("semester_id")) + current_user.active_semester_id = int(request.args.get("semester_id")) return redirect(request.referrer) diff --git a/advlabdb/templates/layout.html b/advlabdb/templates/layout.html index b8e9c3b..b141405 100644 --- a/advlabdb/templates/layout.html +++ b/advlabdb/templates/layout.html @@ -35,7 +35,7 @@ {% if current_user.is_authenticated %}