diff --git a/backend/api/fixtures/realistic/realistic.yaml b/backend/api/fixtures/realistic/realistic.yaml index bf2f4f15..2b101567 100644 --- a/backend/api/fixtures/realistic/realistic.yaml +++ b/backend/api/fixtures/realistic/realistic.yaml @@ -324,6 +324,54 @@ submission_time: 2024-05-11 12:08:21.147551+00:00 is_valid: true zip: fixtures/realistic/projects/0/0/submissions/1/submission_2/submission.zip +- model: api.submission + pk: 5 + fields: + group: 1 + submission_number: 5 + submission_time: 2024-05-12 12:08:21.147551+00:00 + is_valid: true + zip: fixtures/realistic/projects/0/0/submissions/1/submission_2/submission.zip +- model: api.submission + pk: 6 + fields: + group: 1 + submission_number: 6 + submission_time: 2024-05-13 12:08:21.147551+00:00 + is_valid: true + zip: fixtures/realistic/projects/0/0/submissions/1/submission_2/submission.zip +- model: api.submission + pk: 7 + fields: + group: 1 + submission_number: 7 + submission_time: 2024-05-14 12:08:21.147551+00:00 + is_valid: true + zip: fixtures/realistic/projects/0/0/submissions/1/submission_2/submission.zip +- model: api.submission + pk: 8 + fields: + group: 1 + submission_number: 8 + submission_time: 2024-05-15 12:08:21.147551+00:00 + is_valid: true + zip: fixtures/realistic/projects/0/0/submissions/1/submission_2/submission.zip +- model: api.submission + pk: 9 + fields: + group: 1 + submission_number: 9 + submission_time: 2024-05-16 12:08:21.147551+00:00 + is_valid: true + zip: fixtures/realistic/projects/0/0/submissions/1/submission_2/submission.zip +- model: api.submission + pk: 10 + fields: + group: 1 + submission_number: 10 + submission_time: 2024-05-17 12:08:21.147551+00:00 + is_valid: true + zip: fixtures/realistic/projects/0/0/submissions/1/submission_2/submission.zip # MARK: Check Result - model: api.checkresult @@ -434,6 +482,168 @@ submission: 4 result: SUCCESS error_message: null +- model: api.checkresult + pk: 13 + fields: + polymorphic_ctype: + - api + - structurecheckresult + submission: 5 + result: FAILED + error_message: BLOCKED_EXTENSION +- model: api.checkresult + pk: 14 + fields: + polymorphic_ctype: + - api + - extracheckresult + submission: 5 + result: FAILED + error_message: FAILED_STRUCTURE_CHECK +- model: api.checkresult + pk: 15 + fields: + polymorphic_ctype: + - api + - extracheckresult + submission: 5 + result: FAILED + error_message: FAILED_STRUCTURE_CHECK +- model: api.checkresult + pk: 16 + fields: + polymorphic_ctype: + - api + - structurecheckresult + submission: 6 + result: FAILED + error_message: OBLIGATED_EXTENSION_NOT_FOUND +- model: api.checkresult + pk: 17 + fields: + polymorphic_ctype: + - api + - extracheckresult + submission: 6 + result: FAILED + error_message: FAILED_STRUCTURE_CHECK +- model: api.checkresult + pk: 18 + fields: + polymorphic_ctype: + - api + - extracheckresult + submission: 6 + result: FAILED + error_message: FAILED_STRUCTURE_CHECK +- model: api.checkresult + pk: 19 + fields: + polymorphic_ctype: + - api + - structurecheckresult + submission: 7 + result: FAILED + error_message: FILE_DIR_NOT_FOUND +- model: api.checkresult + pk: 20 + fields: + polymorphic_ctype: + - api + - extracheckresult + submission: 7 + result: FAILED + error_message: FAILED_STRUCTURE_CHECK +- model: api.checkresult + pk: 21 + fields: + polymorphic_ctype: + - api + - extracheckresult + submission: 7 + result: FAILED + error_message: FAILED_STRUCTURE_CHECK +- model: api.checkresult + pk: 22 + fields: + polymorphic_ctype: + - api + - structurecheckresult + submission: 8 + result: SUCCESS + error_message: null +- model: api.checkresult + pk: 23 + fields: + polymorphic_ctype: + - api + - extracheckresult + submission: 8 + result: FAILED + error_message: DOCKER_IMAGE_ERROR +- model: api.checkresult + pk: 24 + fields: + polymorphic_ctype: + - api + - extracheckresult + submission: 8 + result: FAILED + error_message: TIME_LIMIT +- model: api.checkresult + pk: 25 + fields: + polymorphic_ctype: + - api + - structurecheckresult + submission: 9 + result: SUCCESS + error_message: null +- model: api.checkresult + pk: 26 + fields: + polymorphic_ctype: + - api + - extracheckresult + submission: 9 + result: FAILED + error_message: MEMORY_LIMIT +- model: api.checkresult + pk: 27 + fields: + polymorphic_ctype: + - api + - extracheckresult + submission: 9 + result: FAILED + error_message: CHECK_ERROR +- model: api.checkresult + pk: 28 + fields: + polymorphic_ctype: + - api + - structurecheckresult + submission: 10 + result: SUCCESS + error_message: null +- model: api.checkresult + pk: 29 + fields: + polymorphic_ctype: + - api + - extracheckresult + submission: 10 + result: FAILED + error_message: RUNTIME_ERROR +- model: api.checkresult + pk: 30 + fields: + polymorphic_ctype: + - api + - extracheckresult + submission: 10 + result: FAILED + error_message: UNKNOWN # MARK: Strucure Check results - model: api.structurecheckresult @@ -452,6 +662,30 @@ pk: 10 fields: structure_check: 0 +- model: api.structurecheckresult + pk: 13 + fields: + structure_check: 0 +- model: api.structurecheckresult + pk: 16 + fields: + structure_check: 0 +- model: api.structurecheckresult + pk: 19 + fields: + structure_check: 0 +- model: api.structurecheckresult + pk: 22 + fields: + structure_check: 0 +- model: api.structurecheckresult + pk: 25 + fields: + structure_check: 0 +- model: api.structurecheckresult + pk: 28 + fields: + structure_check: 0 # MARK: Extra Check Results - model: api.extracheckresult @@ -502,6 +736,78 @@ extra_check: 1 log_file: fixtures/realistic/projects/0/0/submissions/1/submission_2/logs/log_extra_check_1.txt artifact: "" +- model: api.extracheckresult + pk: 14 + fields: + extra_check: 0 + log_file: fixtures/realistic/projects/0/0/submissions/1/submission_2/logs/log_extra_check_0.txt + artifact: "" +- model: api.extracheckresult + pk: 15 + fields: + extra_check: 1 + log_file: fixtures/realistic/projects/0/0/submissions/1/submission_2/logs/log_extra_check_1.txt + artifact: "" +- model: api.extracheckresult + pk: 17 + fields: + extra_check: 0 + log_file: fixtures/realistic/projects/0/0/submissions/1/submission_2/logs/log_extra_check_0.txt + artifact: "" +- model: api.extracheckresult + pk: 18 + fields: + extra_check: 1 + log_file: fixtures/realistic/projects/0/0/submissions/1/submission_2/logs/log_extra_check_1.txt + artifact: "" +- model: api.extracheckresult + pk: 20 + fields: + extra_check: 0 + log_file: fixtures/realistic/projects/0/0/submissions/1/submission_2/logs/log_extra_check_0.txt + artifact: "" +- model: api.extracheckresult + pk: 21 + fields: + extra_check: 1 + log_file: fixtures/realistic/projects/0/0/submissions/1/submission_2/logs/log_extra_check_1.txt + artifact: "" +- model: api.extracheckresult + pk: 23 + fields: + extra_check: 0 + log_file: fixtures/realistic/projects/0/0/submissions/1/submission_2/logs/log_extra_check_0.txt + artifact: "" +- model: api.extracheckresult + pk: 24 + fields: + extra_check: 1 + log_file: fixtures/realistic/projects/0/0/submissions/1/submission_2/logs/log_extra_check_1.txt + artifact: "" +- model: api.extracheckresult + pk: 26 + fields: + extra_check: 0 + log_file: fixtures/realistic/projects/0/0/submissions/1/submission_2/logs/log_extra_check_0.txt + artifact: "" +- model: api.extracheckresult + pk: 27 + fields: + extra_check: 1 + log_file: fixtures/realistic/projects/0/0/submissions/1/submission_2/logs/log_extra_check_1.txt + artifact: "" +- model: api.extracheckresult + pk: 29 + fields: + extra_check: 0 + log_file: fixtures/realistic/projects/0/0/submissions/1/submission_2/logs/log_extra_check_0.txt + artifact: "" +- model: api.extracheckresult + pk: 30 + fields: + extra_check: 1 + log_file: fixtures/realistic/projects/0/0/submissions/1/submission_2/logs/log_extra_check_1.txt + artifact: "" # MARK: Teachers - model: api.teacher diff --git a/backend/api/locale/en/LC_MESSAGES/django.po b/backend/api/locale/en/LC_MESSAGES/django.po index dbf3b355..51b4c470 100755 --- a/backend/api/locale/en/LC_MESSAGES/django.po +++ b/backend/api/locale/en/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2024-05-15 19:49+0200\n" +"POT-Creation-Date: 2024-05-20 12:28+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -152,67 +152,71 @@ msgstr "User is not allowed to assign othher owners than himself to the image." msgid "docker.errors.custom" msgstr "User is not allowed to create public images" -#: serializers/group_serializer.py:56 +#: serializers/group_serializer.py:57 msgid "group.errors.score_exceeds_max" msgstr "The score exceeds the group's max score." -#: serializers/group_serializer.py:66 serializers/group_serializer.py:96 +#: serializers/group_serializer.py:67 serializers/group_serializer.py:97 msgid "group.error.context" msgstr "The group is not supplied in the context." -#: serializers/group_serializer.py:74 serializers/group_serializer.py:108 +#: serializers/group_serializer.py:75 serializers/group_serializer.py:113 msgid "group.errors.locked" msgstr "The group is currently locked." -#: serializers/group_serializer.py:78 +#: serializers/group_serializer.py:79 msgid "group.errors.full" msgstr "The group is already full." -#: serializers/group_serializer.py:82 +#: serializers/group_serializer.py:83 msgid "group.errors.not_in_course" msgstr "The student is not present in the related course." -#: serializers/group_serializer.py:86 +#: serializers/group_serializer.py:87 msgid "group.errors.already_in_group" msgstr "The student is already in the group." -#: serializers/group_serializer.py:104 +#: serializers/group_serializer.py:105 +msgid "group.errors.size_one" +msgstr "Unable to leave a group with size 1." + +#: serializers/group_serializer.py:109 msgid "group.errors.not_present" msgstr "The student is currently not in the group." -#: serializers/project_serializer.py:22 +#: serializers/project_serializer.py:23 msgid "project.errors.invalid_instance" msgstr "Error while parsing the provided zip." -#: serializers/project_serializer.py:81 +#: serializers/project_serializer.py:122 msgid "project.errors.context" msgstr "The project is not supplied in the context." -#: serializers/project_serializer.py:86 +#: serializers/project_serializer.py:127 msgid "project.errors.start_date_in_past" msgstr "The start date of the project lies in the past." -#: serializers/project_serializer.py:100 +#: serializers/project_serializer.py:141 msgid "project.errors.deadline_before_start_date" msgstr "The deadline of the project lies before the start date of the project." -#: serializers/project_serializer.py:142 +#: serializers/project_serializer.py:183 msgid "project.errors.zip_structure" msgstr "Error while parsing the provided zip." -#: serializers/submission_serializer.py:96 tests/test_submission.py:275 +#: serializers/submission_serializer.py:99 tests/test_submission.py:275 msgid "project.error.submissions.past_project" msgstr "The deadline of the project has already passed." -#: serializers/submission_serializer.py:99 tests/test_submission.py:346 +#: serializers/submission_serializer.py:102 tests/test_submission.py:346 msgid "project.error.submissions.non_visible_project" msgstr "The project is currently in a non-visible state." -#: serializers/submission_serializer.py:102 tests/test_submission.py:376 +#: serializers/submission_serializer.py:105 tests/test_submission.py:376 msgid "project.error.submissions.archived_project" msgstr "The project is archived." -#: serializers/submission_serializer.py:105 +#: serializers/submission_serializer.py:108 msgid "project.error.submissions.no_files" msgstr "The submission is empty." @@ -228,39 +232,39 @@ msgstr "The teacher was successfully added." msgid "teachers.success.destroy" msgstr "The teacher was successfully destroyed." -#: views/course_view.py:137 +#: views/course_view.py:136 msgid "courses.success.assistants.add" msgstr "The assistant was successfully added to the course." -#: views/course_view.py:164 +#: views/course_view.py:163 msgid "courses.success.assistants.remove" msgstr "The assistant was successfully removed from the course." -#: views/course_view.py:226 +#: views/course_view.py:225 msgid "courses.success.students.add" msgstr "The student was successfully added to the course." -#: views/course_view.py:247 +#: views/course_view.py:246 msgid "courses.success.students.remove" msgstr "The student was successfully removed from the course." -#: views/course_view.py:292 +#: views/course_view.py:291 msgid "courses.success.teachers.add" msgstr "The teacher was successfully added to the course." -#: views/course_view.py:316 +#: views/course_view.py:315 msgid "courses.success.teachers.remove" msgstr "The teacher was successfully removed from the course." -#: views/group_view.py:74 +#: views/group_view.py:73 msgid "group.success.students.add" msgstr "The student was successfully added to the group." -#: views/group_view.py:94 +#: views/group_view.py:93 msgid "group.success.students.remove" msgstr "The student was successfully removed from the group." -#: views/group_view.py:113 +#: views/group_view.py:112 msgid "group.success.submissions.add" msgstr "The submission was successfully added to the group." @@ -288,6 +292,6 @@ msgstr "No zip file available." msgid "extra_check_result.download.log" msgstr "No log file available." -#: views/submission_view.py:60 +#: views/submission_view.py:59 msgid "extra_check_result.download.artifact" msgstr "No artifact available." diff --git a/backend/api/locale/nl/LC_MESSAGES/django.po b/backend/api/locale/nl/LC_MESSAGES/django.po index 7acb1b3d..4e39a9b6 100755 --- a/backend/api/locale/nl/LC_MESSAGES/django.po +++ b/backend/api/locale/nl/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2024-05-15 19:49+0200\n" +"POT-Creation-Date: 2024-05-20 12:28+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -152,68 +152,72 @@ msgstr "Gebruiker is alleen toegelaten om zichzelf als eigenaar op te geven" msgid "docker.errors.custom" msgstr "Gebruiker is niet toegelaten om publieke afbeeldingen te maken" -#: serializers/group_serializer.py:56 +#: serializers/group_serializer.py:57 msgid "group.errors.score_exceeds_max" msgstr "De score van de groep is groter dan de maximum score." -#: serializers/group_serializer.py:66 serializers/group_serializer.py:96 +#: serializers/group_serializer.py:67 serializers/group_serializer.py:97 msgid "group.error.context" msgstr "De groep is niet meegegeven als context waar dat nodig is." -#: serializers/group_serializer.py:74 serializers/group_serializer.py:108 +#: serializers/group_serializer.py:75 serializers/group_serializer.py:113 msgid "group.errors.locked" msgstr "De groep is momenteel vergrendeld." -#: serializers/group_serializer.py:78 +#: serializers/group_serializer.py:79 msgid "group.errors.full" msgstr "De groep is al vol." -#: serializers/group_serializer.py:82 +#: serializers/group_serializer.py:83 msgid "group.errors.not_in_course" msgstr "" "De student bevindt zich niet in de opleiding waartoe het project hoort." -#: serializers/group_serializer.py:86 +#: serializers/group_serializer.py:87 msgid "group.errors.already_in_group" msgstr "De student bevindt zich al in de groep." -#: serializers/group_serializer.py:104 +#: serializers/group_serializer.py:105 +msgid "group.errors.size_one" +msgstr "Het is niet mogelijk om een group met grootte 1 te verlaten." + +#: serializers/group_serializer.py:109 msgid "group.errors.not_present" msgstr "De student bevindt zich niet in de groep." -#: serializers/project_serializer.py:22 +#: serializers/project_serializer.py:23 msgid "project.errors.invalid_instance" msgstr "Error tijdens de zip te overlopen." -#: serializers/project_serializer.py:81 +#: serializers/project_serializer.py:122 msgid "project.errors.context" msgstr "Het project is niet meegegeven als context waar dat nodig is." -#: serializers/project_serializer.py:86 +#: serializers/project_serializer.py:127 msgid "project.errors.start_date_in_past" msgstr "De startdatum van het project ligt in het verleden." -#: serializers/project_serializer.py:100 +#: serializers/project_serializer.py:141 msgid "project.errors.deadline_before_start_date" msgstr "De uiterste inleverdatum voor het project ligt voor de startdatum." -#: serializers/project_serializer.py:142 +#: serializers/project_serializer.py:183 msgid "project.errors.zip_structure" msgstr "Error tijdens de zip te overlopen." -#: serializers/submission_serializer.py:96 tests/test_submission.py:275 +#: serializers/submission_serializer.py:99 tests/test_submission.py:275 msgid "project.error.submissions.past_project" msgstr "De uiterste inleverdatum voor het project is gepasseerd." -#: serializers/submission_serializer.py:99 tests/test_submission.py:346 +#: serializers/submission_serializer.py:102 tests/test_submission.py:346 msgid "project.error.submissions.non_visible_project" msgstr "Het project is niet zichtbaar." -#: serializers/submission_serializer.py:102 tests/test_submission.py:376 +#: serializers/submission_serializer.py:105 tests/test_submission.py:376 msgid "project.error.submissions.archived_project" msgstr "Het project is gearchiveerd." -#: serializers/submission_serializer.py:105 +#: serializers/submission_serializer.py:108 msgid "project.error.submissions.no_files" msgstr "De indiening is leeg" @@ -229,39 +233,39 @@ msgstr "De lesgever is successvol toegevoegd." msgid "teachers.success.destroy" msgstr "De lesgever is succesvol verwijderd." -#: views/course_view.py:137 +#: views/course_view.py:136 msgid "courses.success.assistants.add" msgstr "De assistent is succesvol toegevoegd aan de opleiding." -#: views/course_view.py:164 +#: views/course_view.py:163 msgid "courses.success.assistants.remove" msgstr "De assistent is succesvol verwijderd uit de opleiding." -#: views/course_view.py:226 +#: views/course_view.py:225 msgid "courses.success.students.add" msgstr "De student is succesvol toegevoegd aan de opleiding." -#: views/course_view.py:247 +#: views/course_view.py:246 msgid "courses.success.students.remove" msgstr "De student is succesvol verwijderd uit de opleiding." -#: views/course_view.py:292 +#: views/course_view.py:291 msgid "courses.success.teachers.add" msgstr "De lesgever is succesvol toegevoegd aan de opleiding." -#: views/course_view.py:316 +#: views/course_view.py:315 msgid "courses.success.teachers.remove" msgstr "De lesgever is succesvol verwijderd uit de opleiding." -#: views/group_view.py:74 +#: views/group_view.py:73 msgid "group.success.students.add" msgstr "De student is succesvol toegevoegd aan de groep." -#: views/group_view.py:94 +#: views/group_view.py:93 msgid "group.success.students.remove" msgstr "De student is succesvol verwijderd uit de groep." -#: views/group_view.py:113 +#: views/group_view.py:112 msgid "group.success.submissions.add" msgstr "De indiening is succesvol toegevoegd aan de groep." @@ -289,7 +293,7 @@ msgstr "Geen zip bestand beschikbaar." msgid "extra_check_result.download.log" msgstr "Geen log bestand beschikbaar." -#: views/submission_view.py:60 +#: views/submission_view.py:59 #, fuzzy #| msgid "extra_check_result.download.log" msgid "extra_check_result.download.artifact" diff --git a/backend/api/serializers/group_serializer.py b/backend/api/serializers/group_serializer.py index b262889c..ae2e474f 100644 --- a/backend/api/serializers/group_serializer.py +++ b/backend/api/serializers/group_serializer.py @@ -1,5 +1,7 @@ +from api.models.assistant import Assistant from api.models.group import Group from api.models.student import Student +from api.models.teacher import Teacher from api.permissions.role_permissions import (is_assistant, is_student, is_teacher) from api.serializers.project_serializer import ProjectSerializer @@ -99,6 +101,10 @@ def validate(self, attrs): group: Group = self.context["group"] student: Student = attrs["student"] + # Make sure the group size is not 1 + if group.project.group_size == 1: + raise ValidationError(gettext("group.errors.size_one")) + # Make sure the student was in the group if not group.students.filter(id=student.id).exists(): raise ValidationError(gettext("group.errors.not_present")) diff --git a/backend/api/serializers/project_serializer.py b/backend/api/serializers/project_serializer.py index b4493229..caa2cec9 100644 --- a/backend/api/serializers/project_serializer.py +++ b/backend/api/serializers/project_serializer.py @@ -2,6 +2,7 @@ from api.models.group import Group from api.models.project import Project from api.models.submission import Submission, ExtraCheckResult, StructureCheckResult, StateEnum +from api.models.checks import ExtraCheck, StructureCheck from api.serializers.course_serializer import CourseSerializer from django.core.files.uploadedfile import InMemoryUploadedFile from django.utils import timezone @@ -33,6 +34,22 @@ def to_representation(self, instance: Project): if (groups_submitted > non_empty_groups): non_empty_groups = groups_submitted + extra_checks_count = instance.extra_checks.count() + + if extra_checks_count: + passed_extra_checks_submission_ids = ExtraCheckResult.objects.filter( + submission__group__project=instance, + submission__is_valid=True, + result=StateEnum.SUCCESS + ).values_list('submission__id', flat=True) + + passed_extra_checks_group_ids = Submission.objects.filter( + id__in=passed_extra_checks_submission_ids + ).values_list('group_id', flat=True) + + unique_groups = set(passed_extra_checks_group_ids) + extra_checks_passed = len(unique_groups) + passed_structure_checks_submission_ids = StructureCheckResult.objects.filter( submission__group__project=instance, submission__is_valid=True, @@ -46,18 +63,12 @@ def to_representation(self, instance: Project): unique_groups = set(passed_structure_checks_group_ids) structure_checks_passed = len(unique_groups) - passed_extra_checks_submission_ids = ExtraCheckResult.objects.filter( - submission__group__project=instance, - submission__is_valid=True, - result=StateEnum.SUCCESS - ).values_list('submission__id', flat=True) - - passed_extra_checks_group_ids = Submission.objects.filter( - id__in=passed_extra_checks_submission_ids - ).values_list('group_id', flat=True) + # If there are no extra checks, we can set extra_checks_passed equal to structure_checks_passed + if not extra_checks_count: + extra_checks_passed = structure_checks_passed - unique_groups = set(passed_extra_checks_group_ids) - extra_checks_passed = len(unique_groups) + # If the extra checks succeed, the structure checks also succeed + structure_checks_passed -= extra_checks_passed # The total number of passed extra checks combined with the number of passed structure checks # can never exceed the total number of submissions (the seeder does not account for this restriction) diff --git a/backend/poetry.lock b/backend/poetry.lock index efb7f1f0..de94c864 100644 --- a/backend/poetry.lock +++ b/backend/poetry.lock @@ -1317,13 +1317,13 @@ ocsp = ["cryptography (>=36.0.1)", "pyopenssl (==20.0.1)", "requests (>=2.26.0)" [[package]] name = "requests" -version = "2.31.0" +version = "2.32.0" description = "Python HTTP for Humans." optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "requests-2.31.0-py3-none-any.whl", hash = "sha256:58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f"}, - {file = "requests-2.31.0.tar.gz", hash = "sha256:942c5a758f98d790eaed1a29cb6eefc7ffb0d1cf7af05c3d2791656dbd6ad1e1"}, + {file = "requests-2.32.0-py3-none-any.whl", hash = "sha256:f2c3881dddb70d056c5bd7600a4fae312b2a300e39be6a118d30b90bd27262b5"}, + {file = "requests-2.32.0.tar.gz", hash = "sha256:fa5490319474c82ef1d2c9bc459d3652e3ae4ef4c4ebdd18a21145a47ca4b6b8"}, ] [package.dependencies] @@ -1626,4 +1626,4 @@ brotli = ["Brotli"] [metadata] lock-version = "2.0" python-versions = "^3.11.4" -content-hash = "eb154813d38b776ea62b72172e5127abd79f4006005d097421c14dfe40c557df" +content-hash = "fe59ecb1d9eb60d2f1cce90067f18cf9cac4748498c357640a8ab39f38a9a9e5" diff --git a/backend/pyproject.toml b/backend/pyproject.toml index 3e5e66a0..d1eba8fc 100644 --- a/backend/pyproject.toml +++ b/backend/pyproject.toml @@ -13,7 +13,7 @@ django-sslserver = "^0.22" djangorestframework = "^3.15.1" django-rest-swagger = "^2.2.0" drf-yasg = "^1.21.7" -requests = "^2.31.0" +requests = "^2.32.0" cas-client = "^1.0.0" psycopg2-binary = "^2.9.9" djangorestframework-simplejwt = "^5.3.1" diff --git a/frontend/src/assets/lang/app/en.json b/frontend/src/assets/lang/app/en.json index 9e86d683..b90ecd77 100644 --- a/frontend/src/assets/lang/app/en.json +++ b/frontend/src/assets/lang/app/en.json @@ -2,16 +2,14 @@ "layout": { "header": { "logo": "Ghent University logo", - "login": "login", + "login": "Login", "view": "View as {0}", "user": "Logged in as {0}", "navigation": { "dashboard": "Dashboard", "calendar": "Calendar", - "courses": "courses", - "projects": "projects", - "settings": "preferences", - "help": "help" + "courses": "Courses", + "projects": "Projects" }, "language": { "nl": "Nederlands", @@ -46,7 +44,7 @@ "coming": "Near deadlines", "deadline": "Deadline", "days": "Today at {hour} | Tomorrow at {hour} | In {count} days", - "ago": "{count} days ago", + "ago": "1 day ago | {count} days ago", "groupName": "Group name", "groupPopulation": "Size", "groupStatus": "Status", @@ -63,10 +61,10 @@ "edit": "Edit project", "name": "Project name", "description": "Description", - "start_date": "Start project", - "group_size": "Number of students in a group (1 for an individual project)", - "number_of_groups": "Number of groups (optional, otherwise #students / group size)", - "max_score": "Maximum score that can be achieved", + "startDate": "Start project", + "numberStudentsGroup": "Number of students in a group (1 for an individual project)", + "numberOfGroups": "Number of groups (optional, otherwise #students / group size)", + "maxScore": "Maximum score that can be achieved", "visibility": "Make project visible to students", "scoreVisibility": "Make score, when uploaded, automatically visible to students", "submissionStructure": "Structure of how a submission should be made", @@ -82,7 +80,7 @@ "dockerImage": "Docker image", "timeLimit": "Time limit for execution (in seconds)", "memoryLimit": "Memory limit for execution (in MB)", - "showLog": "Making the extra logs of the docker container visible to the students" + "showLog": "Make the extra logs of the docker container visible to the students" } }, "submissions": { @@ -110,7 +108,6 @@ "clone": "Clone course", "cloneAssistants": "Clone assistants:", "cloneTeachers": "Clone teachers:", - "cloneCourse": "Clone teachers:", "name": "Course name", "description": "Description", "excerpt": "Short description", @@ -122,17 +119,14 @@ "noProjects": "No projects available for this course", "teachersAndAssistants": { "title": "People linked to this course", - "enroll": "Add as {0}", - "leave": "Remove from course", "edit": "Edit users", "search": { "search": "Search", "faculty": "Faculty", - "role": "Role", - "no_role": "None", + "noRole": "None", "placeholder": "Search a user by name", "title": "Find users to link to this course", - "results": "{0} users found for set filters" + "results": "1 user found for set filters | {count} users found for set filters" } }, "search": { @@ -141,10 +135,7 @@ "year": "Academic year", "placeholder": "Search a course by name", "title": "Search a course", - "results": "{0} courses found for set filters" - }, - "searchByLink": { - "placeholder": "Find a course using the registration link" + "results": "1 course found for set filters | {count} courses found for set filters" }, "share": { "title": "Activate invitation link", @@ -157,14 +148,13 @@ "helpers": { "errors": { "notFound": "Not found", - "notFoundDetail": "Source not found", - "unauthorized": "unauthorized", + "notFoundDetail": "Source not found.", + "unauthorized": "Unauthorized", "unauthorizedDetail": "You are not authorized to access this resource.", - "server": "Server Error", - "serverDetail": "An error occurred on the server.", - "network": "Network Error", + "server": "Server error", + "network": "Network error", "networkDetail": "Unable to reach the server.", - "request": "request error", + "request": "Request error", "requestDetail": "An error occurred while creating the request." } } @@ -176,8 +166,6 @@ "createProject": "Create a new project", "searchCourse": "Search a course", "createCourse": "Create a new course", - "public": "Public", - "protected": "Protected", "csv": "Download grades as a .csv file" }, "card": { @@ -201,7 +189,6 @@ "teacher": "No courses found. Create a new course with the button below.", "search": "No courses found for the given search criteria." }, - "noResults": "No results.", "noIncomingProjects": "No projects with a deadline within 7 days.", "selectCourse": "Select the course for which you want to create a project:", "showPastProjects": "Projects with passed deadline" @@ -250,7 +237,7 @@ "save": { "error": { "title": "Invalid save operation", - "detail": "You are trying to save an item without selecting it" + "detail": "You are trying to save an item without selecting it." } } } @@ -266,25 +253,8 @@ "leaveCourse": "Are you sure you want to leave this course? You will no longer have access to this course.", "shareCourse": "By activating the invitation link, you allow students in possession of this link to enroll in this course. Please copy the generated link, only when you click on \"Activate invitation link\" will this link become active." }, - "protectedCourses": { - "screen1": { - "title": "Obtain invitation link", - "content": "Teachers can choose to make their courses private. This means you have to ask the teacher for an invitation link, to be able to join the course." - }, - "screen2": { - "title": "Search course", - "content": "Use the invitation link to search a course. If you can't find the course, ask the teacher to share a new link." - - }, - "screen3": { - "title": "Enroll", - "content": "Enroll in the course. Now you can see all the current projects, deadlines, ..." - - } - }, "admin": { "title": "Admin", - "keyword": "Keyword", "id": "ID", "list": "List", "add": "Add", @@ -303,31 +273,19 @@ "roles": "Roles" }, "user": "User", - "assistants": { - "title": "Assistants" - }, "assistant": "Assistant", - "students": { - "title": "Students" - }, "student": "Student", - "teachers": { - "title": "Teachers" - }, "teacher": "Teacher", - "catalog": "Catalog", - "docker_images": { + "dockerImages": { "title": "Docker Images", - "name_input": "Name of docker image", + "nameInput": "Name of docker image", "name": "Name", "owner": "Owner ID", - "public": "Public", - "private": "Private" + "public": "Public" }, - "none_found": "No matching data.", + "noneFound": "No matching data.", "loading": "Loading data. Please wait.", - "safeGuard": "Are you sure?", - "no_file": "No file found." + "safeGuard": "Are you sure?" }, "primevue": { "startsWith": "Starts with", diff --git a/frontend/src/assets/lang/app/nl.json b/frontend/src/assets/lang/app/nl.json index 884cb246..e9ed6148 100644 --- a/frontend/src/assets/lang/app/nl.json +++ b/frontend/src/assets/lang/app/nl.json @@ -9,9 +9,7 @@ "dashboard": "Dashboard", "calendar": "Kalender", "courses": "Vakken", - "projects": "Projecten", - "settings": "Voorkeuren", - "help": "Help" + "projects": "Projecten" }, "language": { "nl": "Nederlands", @@ -25,7 +23,7 @@ "projects": "Lopende projecten" }, "verify": { - "redirect": "Je wordt zo meteen doorverwezen" + "redirect": "Je wordt zo meteen doorverwezen..." }, "login": { "title": "Inloggen", @@ -34,7 +32,7 @@ "button": "UGent login", "card": { "title": "Ypovoli", - "subtitle": "Het officieel indieningsplatform van de Universiteit Gent." + "subtitle": "Het officiële indieningsplatform van de Universiteit Gent." } }, "calendar": { @@ -46,7 +44,7 @@ "coming": "Aankomende deadlines", "deadline": "Deadline", "days": "Vandaag om {hour} | Morgen om {hour} | Over {count} dagen", - "ago": "{count} dagen geleden", + "ago": "1 dag geleden | {count} dagen geleden", "groupName": "Groepsnaam", "groupPopulation": "Grootte", "groupStatus": "Status", @@ -63,14 +61,16 @@ "edit": "Bewerk project", "name": "Projectnaam", "description": "Beschrijving", - "start_date": "Start project", - "group_size": "Aantal studenten per groep (1 voor individueel project)", - "number_of_groups": "Aantal groepen (optioneel, anders #studenten / grootte groep)", - "max_score": "Maximale te behalen score", + "startDate": "Start project", + "numberStudentsGroup": "Aantal studenten per groep (1 voor individueel project)", + "numberOfGroups": "Aantal groepen (optioneel, anders #studenten / grootte groep)", + "maxScore": "Maximale te behalen score", "visibility": "Project zichtbaar maken voor studenten", "scoreVisibility": "Maak score, wanneer ingevuld, automatisch zichtbaar voor studenten", "submissionStructure": "Structuur van hoe de indiening moet gebeuren", "noStudents": "Geen studenten in deze groep", + "locked": "Gesloten", + "unlocked": "Open", "extraChecks": { "title": "Automatische checks op een indiening", "add": "Nieuwe check", @@ -84,7 +84,7 @@ } }, "submissions": { - "title": "Inzendingen", + "title": "Indieningen", "submit": "Indienen", "course": "Vak", "chooseFile": "Kies bestand(en)", @@ -112,24 +112,21 @@ "description": "Beschrijving", "excerpt": "Korte beschrijving", "faculty": "Faculteit", - "private": "Gesloten vak (studenten kunnen enkel inschrijven via uitnodigingslink)", + "private": "Gesloten vak (studenten kunnen enkel inschrijven met een uitnodigingslink)", "year": "Academiejaar", "enroll": "Inschrijven", "leave": "Uitschrijven", "noProjects": "Geen projecten beschikbaar voor dit vak", "teachersAndAssistants": { "title": "Lesgevers gelinkt aan dit vak", - "enroll": "Voeg toe als {0}", - "leave": "Verwijder uit vak", "edit": "Bewerk gebruikers", "search": { "search": "Zoeken", "faculty": "Faculteit", - "role": "Rol", - "no_role": "Geen", + "noRole": "Geen", "placeholder": "Zoek een gebruiker op naam", "title": "Zoek gebuikers om aan dit vak toe te voegen", - "results": "{0} gebruikers gevonden voor ingestelde filters" + "results": "1 gebruiker gevonden voor ingestelde filters | {count} gebruikers gevonden voor ingestelde filters" } }, "search": { @@ -138,28 +135,24 @@ "year": "Academiejaar", "placeholder": "Zoek een vak op naam", "title": "Zoek een vak", - "results": "{0} vakken gevonden voor ingestelde filters" - }, - "searchByLink": { - "placeholder": "Zoek een vak gebruik makende van een uitnodigingslink" + "results": "1 vak gevonden voor ingestelde filters | {count} vakken gevonden voor ingestelde filters" }, "share": { "title": "Activeer invitatielink", "duration": "Geldigheidsduur van link (in dagen):", "link": "Invitatielink:" } - } + } }, "composables": { "helpers": { "errors": { - "notFound": "Niet Gevonden", + "notFound": "Niet gevonden", "notFoundDetail": "Bron niet gevonden.", "unauthorized": "Onbevoegd", "unauthorizedDetail": "Je bent niet bevoegd om deze bron te bereiken.", - "server": "Server Fout", - "serverDetail": "Er vond een fout plaats op de server.", - "network": "Netwerk Fout", + "server": "Server fout", + "network": "Netwerk fout", "networkDetail": "Kan de server niet bereiken.", "request": "Fout verzoek", "requestDetail": "Een fout vond plaats tijdens het maken van het verzoek." @@ -173,8 +166,6 @@ "createProject": "Creëer nieuw project", "searchCourse": "Zoek een vak", "createCourse": "Maak een vak", - "public": "Publiek", - "protected": "Besloten", "csv": "Download punten als een .csv bestand" }, "card": { @@ -191,14 +182,13 @@ "list": { "noProjects": { "student": "Geen lopende projecten gevonden voor alle ingeschreven vakken. Schrijf in op een openbaar vak met de zoekfunctie, of gebruik een uitnodiginslink van een lesgever.", - "teacher": "Geen lopende projecten gevonden voor de vakken waarvoor je lesgever bent." + "teacher": "Geen lopende projecten gevonden voor de vakken waarvoor je lesgever bent. Maak een nieuw project voor een vak met onderstaande knop." }, "noCourses": { "student": "Geen vakken gevonden. Schrijf in op een openbaar vak met de zoekfunctie, of gebruik een uitnodiginslink van een lesgever.", "teacher": "Geen vakken gevonden. Maak een vak aan met onderstaande knop.", "search": "Geen vakken gevonden voor de gegeven zoekcriteria." }, - "noResults": "Geen resultaten.", "noIncomingProjects": "Geen projecten met een deadline binnen de 7 dagen.", "selectCourse": "Selecteer het vak waarvoor je een project wil maken:", "showPastProjects": "Projecten met verstreken deadline" @@ -246,8 +236,8 @@ "admin": { "save": { "error": { - "title": "Ongeldige opsla operatie", - "detail": "U probeert een item op te slaan zonder dit te selecteren" + "title": "Ongeldige opsla bewerking", + "detail": "U probeert een item op te slaan zonder dit te selecteren." } } } @@ -263,24 +253,8 @@ "leaveCourse": "Ben je zeker dat je dit vak wil verlaten? Je zal geen toegang meer hebben tot dit vak.", "shareCourse": "Door het activeren van de invitatielink staat u studenten in bezit van deze link toe zich in te schrijven voor dit vak. Gelieve de gegenereerde link te kopiëren, pas wanneer u op \"Activeer invitatielink\" klikt zal deze link actief worden." }, - "protectedCourses": { - "screen1": { - "title": "Bemachtigen link", - "content": "Professoren kunnen kiezen om hun vakken niet publiek te maken. Vraag de prof om een invitatielink te delen om te kunnen toetreden tot het vak." - }, - "screen2": { - "title": "Vak zoeken", - "content": "Gebruik de link om het vak te zoeken. Als je het vak niet kan vinden, kan je de prof vragen om een nieuwe link te delen." - - }, - "screen3": { - "title": "Inschrijven", - "content": "Schrijf je in voor het vak. Je kan nu een overzicht raadplegen van alle lopende projecten, deadlines, ..." - } - }, "admin": { "title": "Beheerder", - "keyword": "Trefwoord", "id": "ID", "list": "Lijst", "add": "Voeg toe", @@ -299,28 +273,17 @@ "roles": "Functies" }, "user": "Gebruiker", - "assistants": { - "title": "Assistenten" - }, "assistant": "Assistent", - "students": { - "title": "Studenten" - }, "student": "Student", - "teachers": { - "title": "Proffen" - }, "teacher": "Prof", - "catalog": "Catalogus", - "docker_images": { + "dockerImages": { "title": "Docker Images", - "name_input": "Naam van docker image", + "nameInput": "Naam van docker image", "name": "Naam", "owner": "Eigenaar ID", - "public": "Publiek", - "private": "Privaat" + "public": "Publiek" }, - "none_found": "Geen overeenkomende data gevonden.", + "noneFound": "Geen overeenkomende data gevonden.", "loading": "Aan het laden. Wacht even aub.", "safeGuard": "Bent u het zeker?" }, diff --git a/frontend/src/components/admin/LazyDataTable.vue b/frontend/src/components/admin/LazyDataTable.vue index dcdfe499..49b91e89 100644 --- a/frontend/src/components/admin/LazyDataTable.vue +++ b/frontend/src/components/admin/LazyDataTable.vue @@ -118,7 +118,7 @@ defineExpose({ fetch });