diff --git a/backend/.tool-versions b/backend/.tool-versions index c10ee4eb..550b4b4c 100644 --- a/backend/.tool-versions +++ b/backend/.tool-versions @@ -1 +1 @@ -python 3.11.4 +python 3.11.8 diff --git a/backend/api/permissions/submission_permissions.py b/backend/api/permissions/submission_permissions.py index f69c81ef..8533c97f 100644 --- a/backend/api/permissions/submission_permissions.py +++ b/backend/api/permissions/submission_permissions.py @@ -37,6 +37,14 @@ def has_object_permission(self, request: Request, view: APIView, obj: Submission return obj.group.students.filter(id=user.id).exists() +class SubmissionFeedbackPermission(SubmissionPermission): + def has_permission(self, request: Request, view: APIView) -> bool: + return True + + def has_object_permission(self, request: Request, view: APIView, obj: Submission) -> bool: + return True + + class StructureCheckResultPermission(SubmissionPermission): def has_object_permission(self, request: Request, view: APIView, obj: StructureCheckResult) -> bool: return super().has_object_permission(request, view, obj.submission) diff --git a/backend/api/views/submission_view.py b/backend/api/views/submission_view.py index aef617d7..7f013959 100644 --- a/backend/api/views/submission_view.py +++ b/backend/api/views/submission_view.py @@ -8,7 +8,8 @@ from api.models.submission import Submission, StructureCheckResult, ExtraCheckResult from api.permissions.submission_permissions import SubmissionPermission, StructureCheckResultPermission, \ - ExtraCheckResultPermission, ExtraCheckResultArtifactPermission, ExtraCheckResultLogPermission + ExtraCheckResultPermission, ExtraCheckResultArtifactPermission, ExtraCheckResultLogPermission, \ + SubmissionFeedbackPermission from api.serializers.feedback_serializer import FeedbackSerializer from api.serializers.submission_serializer import ( ExtraCheckResultSerializer, StructureCheckResultSerializer, @@ -29,7 +30,7 @@ def zip(self, request, **__): return FileResponse(open(submission.zip.path, "rb"), as_attachment=True) - @action(detail=True, methods=["get"]) + @action(detail=True, methods=["get"], permission_classes=[IsAdminUser | SubmissionFeedbackPermission]) def feedback(self, request, **_) -> Response: """Returns all the feedback for the given submission""" submission = self.get_object() diff --git a/backend/ypovoli/asgi.py b/backend/ypovoli/asgi.py deleted file mode 100644 index ac8466f7..00000000 --- a/backend/ypovoli/asgi.py +++ /dev/null @@ -1,16 +0,0 @@ -""" -ASGI config for ypovoli project. - -It exposes the ASGI callable as a module-level variable named ``application``. - -For more information on this file, see -https://docs.djangoproject.com/en/5.0/howto/deployment/asgi/ -""" - -import os - -from django.core.asgi import get_asgi_application - -os.environ.setdefault("DJANGO_SETTINGS_MODULE", "ypovoli.settings") - -application = get_asgi_application() diff --git a/frontend/package-lock.json b/frontend/package-lock.json index b38c986e..a3bb206f 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -17,6 +17,7 @@ "moment": "^2.30.1", "msw": "^2.2.13", "pinia": "^2.1.7", + "prettier": "^3.2.5", "primeflex": "^3.3.1", "primeicons": "^7.0.0", "primevue": "^3.52.0", @@ -6097,8 +6098,6 @@ "version": "3.2.5", "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.2.5.tgz", "integrity": "sha512-3/GWa9aOC0YeD7LUfvOG2NiDyhOWRvt1k+rcKhOuYnMY24iiCphgneUfJDyFXd6rZCAnuLBv6UeAULtrhT/F4A==", - "dev": true, - "peer": true, "bin": { "prettier": "bin/prettier.cjs" }, @@ -7186,7 +7185,7 @@ "version": "5.4.5", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz", "integrity": "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==", - "devOptional": true, + "dev": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" diff --git a/frontend/package.json b/frontend/package.json index a6a82480..11a01b7e 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -40,6 +40,7 @@ "@types/node": "^20.11.30", "@typescript-eslint/eslint-plugin": "^6.21.0", "@vitejs/plugin-vue": "^5.0.4", + "prettier": "^3.2.5", "cypress": "^13.7.1", "cypress-vite": "^1.5.0", "eslint": "^8.57.0", diff --git a/frontend/src/assets/lang/app/en.json b/frontend/src/assets/lang/app/en.json index 36689926..30f0a0f3 100644 --- a/frontend/src/assets/lang/app/en.json +++ b/frontend/src/assets/lang/app/en.json @@ -91,6 +91,7 @@ "scoreVisibility": "Make score, when uploaded, automatically visible to students", "submissionStructure": "Structure of how a submission should be made", "noStudents": "No students in this group", + "alreadyStarted": "The project has already started", "locked": "Closed", "unlocked": "Open", "structureChecks": { @@ -98,6 +99,7 @@ "placeholder": "Give a name to this folder", "cancelSelection": "Deselect {0}", "newFolder": "New folder", + "noChecks": "Your submission does not have to comply with a specific structure.", "obligatedExtensions": "Obligated extensions", "blockedExtensions": "Blocked extensions" }, diff --git a/frontend/src/assets/lang/app/nl.json b/frontend/src/assets/lang/app/nl.json index 377a26c6..1507263a 100644 --- a/frontend/src/assets/lang/app/nl.json +++ b/frontend/src/assets/lang/app/nl.json @@ -67,13 +67,14 @@ "publishScores": "Publiceer scores", "groupName": "Groepsnaam", "groupPopulation": "Grootte", + "alreadyStarted": "Project is al gestart", "groupStatus": "Status", "start": "Startdatum", "submissionStatus": "Indienstatus", "group": "Groep", "groups": "Groepen", "groupSize": "Individueel | Groepen van {count} personen", - "noGroups": "Geen groepen beschikbaar", + "noGroups": "Geen groepen beschikbaar.", "groupMembers": "Groepsleden", "chooseGroup": "Kies een groep", "joinGroup": "Kies groep", @@ -99,7 +100,8 @@ "cancelSelection": "Deselecteer {0}", "obligatedExtensions": "Verplichte extensies", "blockedExtensions": "Niet toegelaten extensies", - "newFolder": "Nieuwe map" + "newFolder": "Nieuwe map", + "noChecks": "Je indiening moet niet voldoen aan een specifieke structuur." }, "extraChecks": { "title": "Automatische checks op een indiening", @@ -260,7 +262,7 @@ }, "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" + "showPastProjects": "Toon projecten met verstreken deadline" } }, "types": { diff --git a/frontend/src/components/projects/ProjectDeadlineCard.vue b/frontend/src/components/projects/ProjectDeadlineCard.vue index d1aecf2c..9497f380 100644 --- a/frontend/src/components/projects/ProjectDeadlineCard.vue +++ b/frontend/src/components/projects/ProjectDeadlineCard.vue @@ -24,8 +24,8 @@ const { t } = useI18n(); }, }" > -
-
+
+

{{ project.name }}

diff --git a/frontend/src/components/projects/ProjectList.vue b/frontend/src/components/projects/ProjectList.vue index 90f01b64..cbe8eda1 100644 --- a/frontend/src/components/projects/ProjectList.vue +++ b/frontend/src/components/projects/ProjectList.vue @@ -1,6 +1,6 @@ diff --git a/frontend/src/types/submission/Submission.ts b/frontend/src/types/submission/Submission.ts index f1bba8c7..fe0c26ab 100644 --- a/frontend/src/types/submission/Submission.ts +++ b/frontend/src/types/submission/Submission.ts @@ -30,6 +30,22 @@ export class Submission { return this.isExtraCheckPassed() && this.isStructureCheckPassed(); } + /** + * Check if the submission is failed. + * @returns boolean + */ + public isFailed(): boolean { + return !this.isPassed(); + } + + /** + * Check if the submission is failed. + * @returns boolean + */ + public isNonePassed(): boolean { + return !this.isExtraCheckPassed() && !this.isStructureCheckPassed(); + } + /** * Check if some of the checks is passed. */ diff --git a/frontend/src/views/calendar/CalendarView.vue b/frontend/src/views/calendar/CalendarView.vue index 694c464e..cc59f39d 100644 --- a/frontend/src/views/calendar/CalendarView.vue +++ b/frontend/src/views/calendar/CalendarView.vue @@ -164,7 +164,7 @@ watch(selectedDate, (date) => {