diff --git a/backend/pigeonhole/apps/submissions/migrations/0005_submissions_feedback_simple_test_and_more.py b/backend/pigeonhole/apps/submissions/migrations/0005_submissions_feedback_simple_test_and_more.py new file mode 100644 index 00000000..1a9af38e --- /dev/null +++ b/backend/pigeonhole/apps/submissions/migrations/0005_submissions_feedback_simple_test_and_more.py @@ -0,0 +1,23 @@ +# Generated by Django 4.2.13 on 2024-05-22 15:53 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('submissions', '0004_remove_submissions_file_and_more'), + ] + + operations = [ + migrations.AddField( + model_name='submissions', + name='feedback_simple_test', + field=models.JSONField(blank=True, null=True), + ), + migrations.AddField( + model_name='submissions', + name='output_simple_test', + field=models.BooleanField(blank=True, default=False), + ), + ] diff --git a/backend/pigeonhole/apps/submissions/models.py b/backend/pigeonhole/apps/submissions/models.py index f1df2f89..da968bee 100644 --- a/backend/pigeonhole/apps/submissions/models.py +++ b/backend/pigeonhole/apps/submissions/models.py @@ -31,6 +31,8 @@ class Submissions(models.Model): file_urls = models.TextField(null=True) timestamp = models.DateTimeField(auto_now_add=True, blank=True) draft = models.BooleanField(default=True) + output_simple_test = models.BooleanField(default=False, blank=True) + feedback_simple_test = models.JSONField(null=True, blank=True) objects = models.Manager() # submission_nr is automatically assigned and unique per group, and @@ -58,4 +60,6 @@ class Meta: "submission_nr", "group_id", "draft", + "output_simple_test", + "feedback_simple_test", ] diff --git a/backend/pigeonhole/apps/submissions/views.py b/backend/pigeonhole/apps/submissions/views.py index 61504082..22bb167b 100644 --- a/backend/pigeonhole/apps/submissions/views.py +++ b/backend/pigeonhole/apps/submissions/views.py @@ -1,4 +1,5 @@ import fnmatch +import json import os import shutil import zipfile @@ -75,9 +76,6 @@ def create(self, request, *args, **kwargs): else: file_urls = request.data["file_urls"].split(",") - serializer = SubmissionsSerializer(data=data) - serializer.is_valid(raise_exception=True) - if not group: return Response( {"message": "Group not found", "errorcode": @@ -101,6 +99,26 @@ def create(self, request, *args, **kwargs): status=status.HTTP_400_BAD_REQUEST ) + project = Project.objects.get(project_id=group.project_id.project_id) + # return Response(",".join(file_urls), status=status.HTTP_201_CREATED) + if project.file_structure is None or project.file_structure == "": + complete_message = {"message": "Submission successful"} + else: + violations = check_restrictions(file_urls, project.file_structure.split(",")) + + if not violations[0] and not violations[2]: + complete_message = {"success": 0} + data["output_simple_test"] = True + else: + violations.update({'success': 1}) + data["output_simple_test"] = False + complete_message = violations + + json_violations = json.dumps(violations) + data["feedback_simple_test"] = json_violations + + serializer = SubmissionsSerializer(data=data) + serializer.is_valid(raise_exception=True) serializer.save() # upload files @@ -123,19 +141,7 @@ def create(self, request, *args, **kwargs): "ERROR_FILE_UPLOAD"}, status=status.HTTP_400_BAD_REQUEST ) - project = Project.objects.get(project_id=group.project_id.project_id) - # return Response(",".join(file_urls), status=status.HTTP_201_CREATED) - if project.file_structure is None or project.file_structure == "": - complete_message = {"message": "Submission successful"} - else: - violations = check_restrictions(file_urls, project.file_structure.split(",")) - - if not violations[0] and not violations[2]: - complete_message = {"success": 0} - else: - violations.update({'success': 1}) - complete_message = violations - + complete_message["submission_id"] = serializer.data["submission_id"] return Response(complete_message, status=status.HTTP_201_CREATED) def update(self, request, *args, **kwargs): diff --git a/frontend/app/[locale]/components/CourseCard.tsx b/frontend/app/[locale]/components/CourseCard.tsx index 6d7f6386..44b60f4d 100644 --- a/frontend/app/[locale]/components/CourseCard.tsx +++ b/frontend/app/[locale]/components/CourseCard.tsx @@ -16,7 +16,8 @@ const CourseCard = ({params: {course}}: { params: { course: Course } }) => { submission_nr: 0, file: '', timestamp: '', - output_test: '', + output_simple_test: false, + feedback_simple_test: {}, }); const [hover, setHover] = useState(false); @@ -45,17 +46,6 @@ const CourseCard = ({params: {course}}: { params: { course: Course } }) => { - - - - - - - - - - - const headers = [ {" " + t('name')}, {" " +t('deadline')}, diff --git a/frontend/app/[locale]/components/ListView.tsx b/frontend/app/[locale]/components/ListView.tsx index 34a49f0b..83159154 100644 --- a/frontend/app/[locale]/components/ListView.tsx +++ b/frontend/app/[locale]/components/ListView.tsx @@ -189,8 +189,8 @@ const ListView: NextPage = ({ setGroupSize((await getProject(data.project_id)).group_size); return [data.group_id, data.user, data.group_nr, l.join(', ')]; }, - 'submissions': (data) => [data.submission_id, data.group_id, convertDate(t,data.timestamp), data.output_test !== undefined], - 'submissions_group': (data) => [data.submission_id, data.group_id, convertDate(t,data.timestamp), data.output_test !== undefined], + 'submissions': (data) => [data.submission_id, data.group_id, convertDate(t, data.timestamp), data.output_simple_test], + 'submissions_group': (data) => [data.submission_id, data.group_id, convertDate(t, data.timestamp), data.output_simple_test], 'archived_courses': (data) => [data.course_id, data.name, data.description, data.open_course], }; diff --git a/frontend/app/[locale]/components/SubmissionDetailsPage.tsx b/frontend/app/[locale]/components/SubmissionDetailsPage.tsx index 14f5927b..64b672c9 100644 --- a/frontend/app/[locale]/components/SubmissionDetailsPage.tsx +++ b/frontend/app/[locale]/components/SubmissionDetailsPage.tsx @@ -65,11 +65,11 @@ const SubmissionDetailsPage: React.FC = ({ locale, s return ( - - + + - + @@ -82,14 +82,14 @@ const SubmissionDetailsPage: React.FC = ({ locale, s {`${t("evaluation")} status`}
- {submission?.output_test !== "" ? ( + {submission?.output_simple_test ? ( ) : ( )}
- {submission?.output_test !== "" ? t("accepted") : t("denied")} + {submission?.output_simple_test ? t("accepted") : t("denied")} {`(${t("timestamp")}: ${formatDate(submission?.timestamp)})`} @@ -113,6 +113,40 @@ const SubmissionDetailsPage: React.FC = ({ locale, s + { + !submission?.output_simple_test ? ( + <> + + + {submission?.feedback_simple_test["0"].length > 0 ? ( + <> + + {t("feedback_simple_test_0")} + + {submission?.feedback_simple_test["0"].map((feedback, index) => ( + + {feedback} + + ))} + + ) : null} + + {submission?.feedback_simple_test["2"].length > 0 ? ( + <> + + {t("feedback_simple_test_2")} + + {submission?.feedback_simple_test["2"].map((feedback, index) => ( + + {feedback} + + ))} + + ) : null} + + ) : null + } + diff --git a/frontend/app/[locale]/components/SubmitDetailsPage.tsx b/frontend/app/[locale]/components/SubmitDetailsPage.tsx index 33e213f1..9f159f29 100644 --- a/frontend/app/[locale]/components/SubmitDetailsPage.tsx +++ b/frontend/app/[locale]/components/SubmitDetailsPage.tsx @@ -57,7 +57,9 @@ const SubmitDetailsPage: React.FC = ({ }; const handleSubmit = async (e) => { - setSubmitted(await uploadSubmissionFile(e, project_id)); + const response = await uploadSubmissionFile(e, project_id); + setSubmitted(response); + window.location.href = `/submission/${response.submission_id}/`; }; useEffect(() => { diff --git a/frontend/lib/api.ts b/frontend/lib/api.ts index 37cafd91..dd74a828 100644 --- a/frontend/lib/api.ts +++ b/frontend/lib/api.ts @@ -78,7 +78,8 @@ export type Submission = { submission_nr: number; file: string; timestamp: string; - output_test: string; + output_simple_test: boolean; + feedback_simple_test: object; } export type UserData = { @@ -681,13 +682,14 @@ export async function joinCourseUsingToken(course_id: number, token: string) { type uploadResult = { result: string; errorcode: string | undefined; + submission_id: number; } export async function uploadSubmissionFile(event: any, project_id: string) : Promise{ axios.defaults.headers.get['X-CSRFToken'] = getCookieValue('csrftoken'); axios.defaults.headers.post['X-CSRFToken'] = getCookieValue('csrftoken'); event.preventDefault(); - console.log(event.target.fileList.files); + const formData = new FormData(event.target); //filter files by key @@ -710,13 +712,13 @@ export async function uploadSubmissionFile(event: any, project_id: string) : Pro let groupres = await axios.get(backend_url + "/projects/" + project_id + "/get_group/", {withCredentials: true}); const group_id = groupres.data.group_id; formDataObject.group_id = group_id; - await axios.post(backend_url + '/submissions/', formDataObject, + const response = await axios.post(backend_url + '/submissions/', formDataObject, { withCredentials: true, headers: { 'Content-Type': 'multipart/form-data' } }); - return {result: "ok", errorcode: undefined}; + return {result: "ok", errorcode: undefined, submission_id: response.data.submission_id}; } catch (error) { const apierror : APIError = new APIError(); apierror.message = "error posting form"; diff --git a/frontend/locales/en/common.json b/frontend/locales/en/common.json index 0b4cc7ec..623fa825 100644 --- a/frontend/locales/en/common.json +++ b/frontend/locales/en/common.json @@ -1,5 +1,5 @@ { - "accepted": "accepted", + "accepted": "Accepted", "description_of_your_course": "Description of your course", "access": "Access", "action_dialog": "This action cannot be undone.", @@ -101,7 +101,6 @@ "visibility": "Visibility", "year": "Year", "archive_course": "Archive course", - "visibility": "Visibility", "download_file": "Download", "denied": "Denied", "show_more": "Show more", @@ -152,5 +151,7 @@ "teachers": "Teachers", "courses_archive": "Courses archive", "courses_all": "All courses", - "open": "Open" + "open": "Open", + "feedback_simple_test_0": "You forgot to upload the following files:", + "feedback_simple_test_2": "You uploaded the following files that were not required:" } \ No newline at end of file diff --git a/frontend/locales/nl/common.json b/frontend/locales/nl/common.json index ed74d721..1e894b03 100644 --- a/frontend/locales/nl/common.json +++ b/frontend/locales/nl/common.json @@ -1,5 +1,5 @@ { - "accepted": "aanvaard", + "accepted": "Aanvaard", "description_of_your_course": "Beschrijving van je cursus", "access": "Toegang", "action_dialog": "Deze actie kan niet ongedaan worden gemaakt.", @@ -149,6 +149,8 @@ "project_calendar": "Project kalender", "edit_user_details": "Gebruiker bewerken", "status_button_tooltip": "Verplicht, optioneel of verboden bestand", + "feedback_simple_test_0": "Je hebt de volgende bestanden niet ingeleverd:", + "feedback_simple_test_2": "Je hebt de volgende bestanden ingeleverd die niet nodig zijn:", "no_deadline": "Geen deadline", "all_submissions": "Alle indieningen", "students": "Studenten", diff --git a/scripts/opdracht_enkel_verboden/extra/verslag.pdf b/scripts/opdracht_enkel_verboden/extra/verslag.pdf new file mode 100644 index 00000000..e69de29b diff --git a/scripts/opdracht_enkel_verboden/src/main.py b/scripts/opdracht_enkel_verboden/src/main.py new file mode 100644 index 00000000..e69de29b diff --git a/scripts/opdracht_enkel_verboden/tests/test.test b/scripts/opdracht_enkel_verboden/tests/test.test new file mode 100644 index 00000000..e69de29b diff --git a/scripts/opdracht_incorrect/tests/test.test b/scripts/opdracht_incorrect/tests/test.test new file mode 100644 index 00000000..73d1dd37 --- /dev/null +++ b/scripts/opdracht_incorrect/tests/test.test @@ -0,0 +1 @@ +dit bestand is verboden