diff --git a/codeGrader/backend/db/Exercise.py b/codeGrader/backend/db/Exercise.py index c37615b..2a9b42d 100644 --- a/codeGrader/backend/db/Exercise.py +++ b/codeGrader/backend/db/Exercise.py @@ -53,8 +53,8 @@ class Exercise(Base): order_by="[Task.name]", # cascade="all", passive_deletes=True, - lazy="joined", - backref=backref("TaskExercise", lazy="noload") + lazy="subquery", + backref=backref("TaskExercise", lazy="joined") ) def get_profile(self): diff --git a/codeGrader/backend/db/Task.py b/codeGrader/backend/db/Task.py index 0221480..01131af 100644 --- a/codeGrader/backend/db/Task.py +++ b/codeGrader/backend/db/Task.py @@ -112,6 +112,10 @@ def toJson(self, recursive: bool = True) -> dict: out["id"] = self.id out["name"] = self.name out["tag"] = self.tag + if self.TaskExercise is None: + out["exercise"] = None + else: + out["exercise"] = self.TaskExercise.toJson(recursive=False) if recursive: diff --git a/codeGrader/frontend/admin/handlers/AdminUser.py b/codeGrader/frontend/admin/handlers/AdminUser.py index 9e1244e..c45fdc3 100644 --- a/codeGrader/frontend/admin/handlers/AdminUser.py +++ b/codeGrader/frontend/admin/handlers/AdminUser.py @@ -63,7 +63,7 @@ def get(self, id_: int) -> Union[str, Response]: editable = self.admin.check_permission('w') admin["editable"] = editable - if self.admin.check_permission('r', admin["profile"]["name"]): # when admin is allowed to view this admin + if self.admin.check_permission('r', admin["profile"]["id"]): # when admin is allowed to view this admin return render_template("adminUser.html", **admin) else: # admin is not allowed to view this user @@ -80,7 +80,7 @@ def post(self, id_: int) -> Response: assert self.request.form is not None admin_before = self.api.get(f"/admin/{id_}") # get the admin data - if self.admin.check_permission('w', admin_before["profile"]["name"]): + if self.admin.check_permission('w', admin_before["profile"]["id"]): admin_data = dict() # getting the data from the form provided in the request @@ -207,7 +207,7 @@ def post(self, id_: int) -> Response: """ admin = self.api.get(f"/admin/{id_}") - if self.admin.check_permission('w', admin["profile"]["name"]): # admin is allowed to delete the admin + if self.admin.check_permission('w', admin["profile"]["id"]): # admin is allowed to delete the admin if self.get_value("action_button") == "Submit": self.api.delete(f"/admin/{id_}") diff --git a/codeGrader/frontend/admin/handlers/Exercise.py b/codeGrader/frontend/admin/handlers/Exercise.py index 19176b8..0e53e0a 100644 --- a/codeGrader/frontend/admin/handlers/Exercise.py +++ b/codeGrader/frontend/admin/handlers/Exercise.py @@ -50,17 +50,17 @@ def get(self, id_: int) -> Union[str, Response]: """ exercise = self.api.get(f"/exercise/{id_}") - editable = self.admin.check_permission('w', exercise["profile"]["name"]) - subjects = self.api.get("/subjects") + editable = self.admin.check_permission('w', exercise["profile"]["id"]) + subjects = self.api.get("/subjects", profile=self.admin.get_filter_profile()) exercise["subjects"] = subjects["subject"] exercise["editable"] = editable - if editable: # admin is allowed to see exercise + if self.admin.check_permission('r', exercise["profile"]["id"]): # when admin is allowed to view this user return render_template("exercise.html", **exercise) - else: # admin is not allowed to see exercise + else: # admin is not allowed to see exercise self.flash("You are not allowed to view this exercise. ") return redirect(url_for("exercises")) @@ -73,7 +73,7 @@ def post(self, id_: int) -> Response: assert self.request.form is not None exercise_before = self.api.get(f"/exercise/{id_}") # get the exercise data - if self.admin.check_permission('w', exercise_before["profile"]["name"]): + if self.admin.check_permission('w', exercise_before["profile"]["id"]): exercise_data = dict() exercise_data["name"] = self.get_value("name") @@ -164,7 +164,7 @@ def get(self, id_: int) -> Union[str, Response]: """ exercise = self.api.get(f"/exercise/{id_}") - editable = self.admin.check_permission('w', exercise["profile"]["name"]) + editable = self.admin.check_permission('w', exercise["profile"]["id"]) if editable: return render_template("deleteExercise.html", **exercise) @@ -182,7 +182,7 @@ def post(self, id_: int) -> Response: @return: Redirection to the Exercise table """ exercise = self.api.get(f"/exercise/{id_}") - if self.admin.check_permission('w', exercise["profile"]["name"]): # admin is allowed to delete the exercise + if self.admin.check_permission('w', exercise["profile"]["id"]): # admin is allowed to delete the exercise if self.get_value("action_button") == "Submit": response = self.api.delete(f"/exercise/{id_}") diff --git a/codeGrader/frontend/admin/handlers/Profile.py b/codeGrader/frontend/admin/handlers/Profile.py index 9add161..2d8fd1a 100644 --- a/codeGrader/frontend/admin/handlers/Profile.py +++ b/codeGrader/frontend/admin/handlers/Profile.py @@ -49,10 +49,10 @@ def get(self, id_: int) -> Union[str, Response]: @rtype: HTML """ profile = self.api.get(f"/profile/{id_}") - editable = self.admin.check_permission('w', profile["name"]) # checking if admin has write rights + editable = self.admin.check_permission('w', profile["id"]) # checking if admin has write rights profile["editable"] = editable # adding the rights to the render params - if self.admin.check_permission('r', profile["name"]): # when admin is allowed to view this profile + if self.admin.check_permission('r', profile["id"]): # when admin is allowed to view this profile return render_template("profile.html", **profile) else: # admin is not allowed to view this profile @@ -68,7 +68,7 @@ def post(self, id_: int) -> Response: assert self.request.form is not None profile_before = self.api.get(f"/profile/{id_}") # get the profile data - if self.admin.check_permission('w', profile_before["name"]): # admin is allowed to update + if self.admin.check_permission('w', profile_before["id"]): # admin is allowed to update profile_data = dict() profile_data["name"] = self.get_value("name") @@ -152,7 +152,7 @@ def get(self, id_: int) -> str: """ profile = self.api.get(f"/profile/{id_}") - editable = self.admin.check_permission('w', profile["profile"]["name"]) + editable = self.admin.check_permission('w', profile["profile"]["id"]) if editable: return render_template("deleteProfile.html", **profile) diff --git a/codeGrader/frontend/admin/handlers/SessionAdmin.py b/codeGrader/frontend/admin/handlers/SessionAdmin.py index aea72bd..1c2c566 100644 --- a/codeGrader/frontend/admin/handlers/SessionAdmin.py +++ b/codeGrader/frontend/admin/handlers/SessionAdmin.py @@ -26,21 +26,23 @@ def __init__(self, adminUser_id) -> None: self.username = user_dict["username"] self.profile = user_dict["profile"] if self.profile is not None: + self.profile_id = self.profile["id"] self.profile_name = self.profile["name"] else: + self.profile_id = None self.profile_name = None self.type = user_dict["admin_type"] self._admin_type_name = self.type["name"] - def check_permission(self, operation: str, profile_name: str = None, create_object: str = None) -> bool: + def check_permission(self, operation: str, profile_id: str = None, create_object: str = None) -> bool: """ Check the permission of the admin for a given Operation and profile If the operation on the given profile is allowed we return true else we return false @param operation: r or w r == Read w == Write @type operation: str - @param profile_name: - @type profile_name: str + @param profile_id: + @type profile_id: str @param create_object: What type of object we want to create @type create_object: str @return: True if the operation is allowed else false @@ -57,7 +59,7 @@ def check_permission(self, operation: str, profile_name: str = None, create_obje # it is a full read admin, so it is allowed return True - elif profile_name == self.profile_name: + elif profile_id == self.profile_id: # checking if the profile is allowed return True @@ -65,7 +67,7 @@ def check_permission(self, operation: str, profile_name: str = None, create_obje return False elif operation == 'w': - if self._admin_type_name == config.admin_rw_partial and profile_name == self.profile_name: + if self._admin_type_name == config.admin_rw_partial and profile_id == self.profile_id: return True elif self._admin_type_name == config.admin_rw_partial and create_object not in [None, "profile", "admin"]: diff --git a/codeGrader/frontend/admin/handlers/Subject.py b/codeGrader/frontend/admin/handlers/Subject.py index 409ad1f..32ac3d3 100644 --- a/codeGrader/frontend/admin/handlers/Subject.py +++ b/codeGrader/frontend/admin/handlers/Subject.py @@ -53,10 +53,10 @@ def get(self, id_: int) -> Union[str, Response]: subject["profiles"] = profiles["profile"] - editable = self.admin.check_permission('w', subject["profile"]["name"]) + editable = self.admin.check_permission('w', subject["profile"]["id"]) subject["editable"] = editable - if self.admin.check_permission('r', subject["profile"]["name"]): # when admin is allowed to view this user + if self.admin.check_permission('r', subject["profile"]["id"]): # when admin is allowed to view this user return render_template("subject.html", **subject) else: # admin is not allowed to view this subject @@ -71,7 +71,7 @@ def post(self, id_: int) -> Response: """ assert self.request.form is not None subject_before = self.api.get(f"/subject/{id_}") # get the subject data - if self.admin.check_permission('w', subject_before["profile"]["name"]): + if self.admin.check_permission('w', subject_before["profile"]["id"]): subject_data = dict() subject_data["name"] = self.get_value("name") @@ -165,7 +165,7 @@ def get(self, id_: int) -> Union[str, Response]: @return: Rendered Template """ subject = self.api.get(f"/subject/{id_}") - editable = self.admin.check_permission('w', subject["profile"]["name"]) + editable = self.admin.check_permission('w', subject["profile"]["id"]) if editable: return render_template("deleteSubject.html", **subject) @@ -183,7 +183,7 @@ def post(self, id_: int) -> Response: @return: Redirection to the Subject table """ subject = self.api.get(f"/subject/{id_}") - if self.admin.check_permission('w', subject["profile"]["name"]): # admin is allowed to delete the subject + if self.admin.check_permission('w', subject["profile"]["id"]): # admin is allowed to delete the subject if self.get_value("action_button") == "Submit": response = self.api.delete(f"/subject/{id_}") diff --git a/codeGrader/frontend/admin/handlers/Task.py b/codeGrader/frontend/admin/handlers/Task.py index 885df17..a1f0268 100644 --- a/codeGrader/frontend/admin/handlers/Task.py +++ b/codeGrader/frontend/admin/handlers/Task.py @@ -50,10 +50,12 @@ def get(self, id_: int) -> Union[str, Response]: """ task = self.api.get(f"/task/{id_}") - editable = self.admin.check_permission('w', task["profile"]["name"]) + editable = self.admin.check_permission('w', task["profile"]["id"]) + exercises = self.api.get("/exercises", profile=self.admin.get_filter_profile()) + task["exercises"] = exercises["exercise"] task["editable"] = editable - if self.admin.check_permission('r', task["profile"]["name"]): # when admin is allowed to view this task + if self.admin.check_permission('r', task["profile"]["id"]): # when admin is allowed to view this task return render_template("task.html", **task) else: # admin is not allowed to view this task @@ -69,11 +71,12 @@ def post(self, id_: int) -> Response: assert self.request.form is not None task_before = self.api.get(f"/task/{id_}") # get the task data - if self.admin.check_permission('w', task_before["profile"]["name"]): + if self.admin.check_permission('w', task_before["profile"]["id"]): task_data = dict() task_data["name"] = self.get_value("name") task_data["tag"] = self.get_value("tag") + task_data["exercise_id"] = self.get_value("exercise") # getting the data from the form provided in the request self.api.put(f"/task/{id_}", body=task_data) @@ -105,8 +108,11 @@ def get(self) -> Union[str, Response]: """ if self.admin.check_permission('w', 'task'): - - return render_template("addTask.html") + task = dict() + exercises = self.api.get("/exercises", profile=self.admin.get_filter_profile()) + task["exercises"] = exercises["exercise"] + print(task) + return render_template("addTask.html", **task) else: # admin is not allowed to view this task self.flash("You are not allowed to access this site! ") @@ -123,6 +129,7 @@ def post(self) -> Response: task_data["name"] = self.get_value("name") task_data["tag"] = self.get_value("tag") + task_data["exercise_id"] = self.get_value("exercise") self.api.post("/task/add", body=task_data) @@ -154,7 +161,7 @@ def get(self, id_: int) -> Union[str, Response]: """ task = self.api.get(f"/task/{id_}") - editable = self.admin.check_permission('w', task["profile"]["name"]) + editable = self.admin.check_permission('w', task["profile"]["id"]) if editable: return render_template("deleteTask.html", **task) @@ -172,7 +179,7 @@ def post(self, id_: int) -> Response: @return: Redirection to the Task table """ task = self.api.get(f"/task/{id_}") - if self.admin.check_permission('w', task["profile"]["name"]): # admin is allowed to delete the task + if self.admin.check_permission('w', task["profile"]["id"]): # admin is allowed to delete the task if self.get_value("action_button") == "Submit": response = self.api.delete(f"/task/{id_}") diff --git a/codeGrader/frontend/admin/handlers/User.py b/codeGrader/frontend/admin/handlers/User.py index be44076..71ffa52 100644 --- a/codeGrader/frontend/admin/handlers/User.py +++ b/codeGrader/frontend/admin/handlers/User.py @@ -59,11 +59,11 @@ def get(self, id_: int) -> Union[str, Response]: user["profiles"] = profiles["profile"] # checking if user will be able to edit the table - editable = self.admin.check_permission('w', user["profile"]["name"]) + editable = self.admin.check_permission('w', user["profile"]["id"]) user["editable"] = editable - if self.admin.check_permission('r', user["profile"]["name"]): # when admin is allowed to view this user + if self.admin.check_permission('r', user["profile"]["id"]): # when admin is allowed to view this user return render_template("user.html", **user) else: # admin is not allowed to view this user @@ -80,7 +80,7 @@ def post(self, id_: int) -> Response: assert self.request.form is not None user_before = self.api.get(f"/user/{id_}") # get the user data - if self.admin.check_permission('w', user_before["profile"]["name"]): + if self.admin.check_permission('w', user_before["profile"]["id"]): user_data = dict() # getting the data from the form provided in the request @@ -185,7 +185,7 @@ def get(self, id_: int) -> Union[str, Response]: user = self.api.get(f"/user/{id_}") - editable = self.admin.check_permission('w', user["profile"]["name"]) + editable = self.admin.check_permission('w', user["profile"]["id"]) if editable: return render_template("deleteUser.html", **user) @@ -203,7 +203,7 @@ def post(self, id_: int) -> Response: @return: Redirection to the users table """ user = self.api.get(f"/user/{id_}") - if self.admin.check_permission('w', user["profile"]["name"]): # admin is allowed to delete the user + if self.admin.check_permission('w', user["profile"]["id"]): # admin is allowed to delete the user if self.get_value("action_button") == "Submit": self.api.delete(f"/user/{id_}") diff --git a/codeGrader/frontend/admin/static/css/styling.css b/codeGrader/frontend/admin/static/css/styling.css index c7d0468..cb91d77 100644 --- a/codeGrader/frontend/admin/static/css/styling.css +++ b/codeGrader/frontend/admin/static/css/styling.css @@ -215,6 +215,35 @@ body { /* Table Styling end*/ +/*Collapsable Styling start*/ +.collapsible_content { + padding: 0 18px; + max-height: 0; + overflow: hidden; + transition: max-height 0.2s ease-out; +} + +.collapsible { + cursor: pointer; + border: none; + color: white; + text-align: center; + text-decoration: none; + display: inline-block; + font-size: 20px; +} + +.collapsible:before { + content: "\25B6"; + font-weight: bold; + float: left; + margin-left: 5px; +} + +.active:before{ + content: "\25BC"; +} + .flash { background-color: red; padding: 10px; diff --git a/codeGrader/frontend/admin/templates/addTask.html b/codeGrader/frontend/admin/templates/addTask.html index ac039f6..81f60b9 100644 --- a/codeGrader/frontend/admin/templates/addTask.html +++ b/codeGrader/frontend/admin/templates/addTask.html @@ -14,16 +14,27 @@
{{ ex['name'] }}
+ {% endfor %} +