diff --git a/package-lock.json b/package-lock.json index b753c433..bfa4398a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3208,6 +3208,7 @@ "version": "2.3.2", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, "hasInstallScript": true, "optional": true, "os": [ @@ -4647,11 +4648,11 @@ } }, "node_modules/polka": { - "version": "1.0.0-next.15", - "resolved": "https://registry.npmjs.org/polka/-/polka-1.0.0-next.15.tgz", - "integrity": "sha512-zBCZO40+USkSj0GDHMqufthqk4TIRc9xVGd50LbMvYNEwGHK8dZczLBQtw9pPHBM+i/Xg7ed7+c+r6J68XkWLg==", + "version": "1.0.0-next.20", + "resolved": "https://registry.npmjs.org/polka/-/polka-1.0.0-next.20.tgz", + "integrity": "sha512-7NIxlPOIpv4+fNPk0lQYKGSP60TZOT360XUIMMWSP5BcCegSFIKz5KyQ6nF4aFE7a6ajmIbtPDzsu9Kowsorkg==", "dependencies": { - "@polka/url": "^1.0.0-next.15", + "@polka/url": "^1.0.0-next.20", "trouter": "^3.1.0" }, "engines": { @@ -4659,9 +4660,9 @@ } }, "node_modules/polka/node_modules/@polka/url": { - "version": "1.0.0-next.15", - "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.15.tgz", - "integrity": "sha512-15spi3V28QdevleWBNXE4pIls3nFZmBbUGrW9IVPwiQczuSb9n76TCB4bsk8TSel+I1OkHEdPhu5QKMfY6rQHA==" + "version": "1.0.0-next.20", + "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.20.tgz", + "integrity": "sha512-88p7+M0QGxKpmnkfXjS4V26AnoC/eiqZutE8GLdaI5X12NY75bXSdTY9NkmYb2Xyk1O+MmkuO6Frmsj84V6I8Q==" }, "node_modules/postcss": { "version": "8.3.0", @@ -9049,6 +9050,7 @@ "version": "2.3.2", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, "optional": true }, "function-bind": { @@ -10132,18 +10134,18 @@ } }, "polka": { - "version": "1.0.0-next.15", - "resolved": "https://registry.npmjs.org/polka/-/polka-1.0.0-next.15.tgz", - "integrity": "sha512-zBCZO40+USkSj0GDHMqufthqk4TIRc9xVGd50LbMvYNEwGHK8dZczLBQtw9pPHBM+i/Xg7ed7+c+r6J68XkWLg==", + "version": "1.0.0-next.20", + "resolved": "https://registry.npmjs.org/polka/-/polka-1.0.0-next.20.tgz", + "integrity": "sha512-7NIxlPOIpv4+fNPk0lQYKGSP60TZOT360XUIMMWSP5BcCegSFIKz5KyQ6nF4aFE7a6ajmIbtPDzsu9Kowsorkg==", "requires": { - "@polka/url": "^1.0.0-next.15", + "@polka/url": "^1.0.0-next.20", "trouter": "^3.1.0" }, "dependencies": { "@polka/url": { - "version": "1.0.0-next.15", - "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.15.tgz", - "integrity": "sha512-15spi3V28QdevleWBNXE4pIls3nFZmBbUGrW9IVPwiQczuSb9n76TCB4bsk8TSel+I1OkHEdPhu5QKMfY6rQHA==" + "version": "1.0.0-next.20", + "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.20.tgz", + "integrity": "sha512-88p7+M0QGxKpmnkfXjS4V26AnoC/eiqZutE8GLdaI5X12NY75bXSdTY9NkmYb2Xyk1O+MmkuO6Frmsj84V6I8Q==" } } }, diff --git a/src/components/Backdrop/index.svelte b/src/components/Backdrop/index.svelte new file mode 100644 index 00000000..e9d05276 --- /dev/null +++ b/src/components/Backdrop/index.svelte @@ -0,0 +1,22 @@ +
+ +
+ + diff --git a/src/components/Course/components/Navigation/index.svelte b/src/components/Course/components/Navigation/index.svelte index 7b3795bc..9feae186 100644 --- a/src/components/Course/components/Navigation/index.svelte +++ b/src/components/Course/components/Navigation/index.svelte @@ -1,6 +1,5 @@ diff --git a/src/routes/_layout.svelte b/src/routes/_layout.svelte index 1d9a69c3..2ad54b7d 100644 --- a/src/routes/_layout.svelte +++ b/src/routes/_layout.svelte @@ -6,10 +6,13 @@ - + + +
+
+
+

Student

+
+ {#each $lessons as lesson, index} + {#if lessonMapping[lesson.id]} +
+

+ {getLectureNo(index + 1)} +

+
+ {#each Object.keys(lessonMapping[lesson.id]) as exerciseId, index} +

+ {lessonMapping[lesson.id][exerciseId].title} + ({lessonMapping[lesson.id][exerciseId].points}) +

+ {/each} +
+
+ {/if} + {/each} +
+

Total

+
+
+ + {#each students as student} +
+
+ Student avatar +
+

{student.profile.fullname}

+

+ {`${ + student.assigned_student_id + ? '#' + student.assigned_student_id + : '-' + }`} +

+
+
+ {#each $lessons as lesson} + {#if lessonMapping[lesson.id]} +
+ {#each Object.keys(lessonMapping[lesson.id]) as exerciseId} +

+ {studentMarksByExerciseId[student.id] + ? studentMarksByExerciseId[student.id][exerciseId] || '-' + : '-'} +

+ {/each} +
+ {/if} + {/each} + +
+
+

+ {calculateStudentTotal(studentMarksByExerciseId[student.id])} +

+
+
+
+ {:else} + + +

No Student Added

+
+ {/each} +
+
+ + diff --git a/src/routes/courses/[id]/submissions.svelte b/src/routes/courses/[id]/submissions.svelte index e7ba8ee1..f0e55b34 100644 --- a/src/routes/courses/[id]/submissions.svelte +++ b/src/routes/courses/[id]/submissions.svelte @@ -1,17 +1,6 @@ @@ -25,6 +14,7 @@ import Chip from '../../../components/Chip/index.svelte'; import PageBody from '../../../components/PageBody/index.svelte'; import CourseContainer from '../../../components/CourseContainer/index.svelte'; + import { fetchCourse } from '../../../utils/services/courses'; import { setCourseData, course } from '../../../components/Course/store'; import { fetchSubmissions, @@ -36,7 +26,7 @@ const flipDurationMs = 300; - export let courseData = {}; + export let courseId; let sections = [ { @@ -155,6 +145,8 @@ async function handleSave(submission) { const { questionAnswerByPoint, questionAnswers } = submission; + let totalPoints = 0; + const updates = Object.keys(questionAnswerByPoint).map((questionId) => { const questionAnswer = questionAnswers.find( (answer) => answer.question_id == questionId @@ -162,19 +154,32 @@ const point = questionAnswerByPoint[questionId]; + totalPoints += parseInt(point, 10); + return updateQuestionAnswer({ point }, { id: questionAnswer.id }); }); + updateSubmission( + { + id: submissionId, + total: totalPoints, + }, + { returning: 'minimal' } + ).then((res) => console.log('Updated submission', res)); + await Promise.all(updates); $snackbarStore.open = true; $snackbarStore.message = `Saved successfully`; } onMount(async () => { - setCourseData(courseData); + if (!$course.id) { + const { data } = await fetchCourse(courseId); + setCourseData(data); + } const { data: submissions } = await fetchSubmissions( - courseData.id || $course.id + courseId || $course.id ); const sectionById = {}; diff --git a/src/utils/services/courses/index.js b/src/utils/services/courses/index.js index 70e7f613..0dda1d9e 100644 --- a/src/utils/services/courses/index.js +++ b/src/utils/services/courses/index.js @@ -165,6 +165,10 @@ export function createExercise(exercise) { return supabase.from('exercise').insert(exercise); } +export function fetchExercises(courseId) { + return supabase.rpc('get_exercises').eq('course_id', courseId); +} + function isNew(item) { return isNaN(item); } diff --git a/src/utils/services/marks/index.js b/src/utils/services/marks/index.js new file mode 100644 index 00000000..3fbceed1 --- /dev/null +++ b/src/utils/services/marks/index.js @@ -0,0 +1,7 @@ +import { supabase } from '../../functions/supabase'; + +export async function fetchMarks(courseId) { + const { data } = await supabase.rpc('get_marks').eq('course_id', courseId); + + return { data }; +} diff --git a/src/utils/services/submissions/index.js b/src/utils/services/submissions/index.js index a8ec1ebc..fe709f89 100644 --- a/src/utils/services/submissions/index.js +++ b/src/utils/services/submissions/index.js @@ -49,7 +49,7 @@ export async function fetchSubmission({ courseId, exerciseId, submittedBy }) { }); } -export async function updateSubmission({ id, status_id, total }) { +export async function updateSubmission({ id, status_id, total }, otherArgs) { const toUpdate = { status_id, }; @@ -58,7 +58,7 @@ export async function updateSubmission({ id, status_id, total }) { toUpdate.total = total; } - return supabase.from('submission').update(toUpdate).match({ id }); + return supabase.from('submission').update(toUpdate, otherArgs).match({ id }); } export async function updateQuestionAnswer(update, match) {