diff --git a/src/components/Course/components/Lesson/Exercise/MarkExerciseModal.svelte b/src/components/Course/components/Lesson/Exercise/MarkExerciseModal.svelte index 49e775c9..1bfd11e6 100644 --- a/src/components/Course/components/Lesson/Exercise/MarkExerciseModal.svelte +++ b/src/components/Course/components/Lesson/Exercise/MarkExerciseModal.svelte @@ -1,32 +1,35 @@ -
- + + { + handleSave(data); + }} + label="Save" + variant={VARIANTS.CONTAINED_SUCCESS} + className="py-2 px-8" + /> +
-

Total grade

-

{total} / {gradeTotal}

+

Total grade

+

{total} / {maxPoints}

-
+
-

Student

-

Jeremy Matt

+

Student

+ {#if data.student} + Student avatar +

{data.student.fullname}

+ {/if}
-
+
diff --git a/src/components/Course/components/Lesson/Exercise/Preview.svelte b/src/components/Course/components/Lesson/Exercise/Preview.svelte index c1d974b0..1ee8eab2 100644 --- a/src/components/Course/components/Lesson/Exercise/Preview.svelte +++ b/src/components/Course/components/Lesson/Exercise/Preview.svelte @@ -11,6 +11,7 @@ export let onSubmit = () => {}; export let onPrevious = () => {}; export let handleGrade = () => {}; + export let disableGrading = false; {#each questions as currentQuestion, currentQuestionIndex} @@ -25,9 +26,10 @@ onPrevious, true )} - bind:grade={grades[currentQuestion.name]} + bind:grade={grades[currentQuestion.id]} gradeMax={currentQuestion.points} - handleGrade={handleGrade(currentQuestion.name)} + handleGrade={handleGrade(currentQuestion.id)} + {disableGrading} /> {:else if QUESTION_TYPE.CHECKBOX === currentQuestion.question_type.id} {:else if QUESTION_TYPE.TEXTAREA === currentQuestion.question_type.id} {/if} {/each} diff --git a/src/components/Course/components/Lesson/Exercise/ViewMode.svelte b/src/components/Course/components/Lesson/Exercise/ViewMode.svelte index c017f7ab..e7a8dfbd 100644 --- a/src/components/Course/components/Lesson/Exercise/ViewMode.svelte +++ b/src/components/Course/components/Lesson/Exercise/ViewMode.svelte @@ -13,7 +13,9 @@ import { QUESTION_TYPE } from '../../../../Question/constants'; import { STATUS } from './constants'; import { getPropsForQuestion, filterOutDeleted } from './functions'; + import { formatAnswers } from '../../../function'; import { submitExercise } from '../../../../../utils/services/courses'; + import { fetchSubmission } from '../../../../../utils/services/submissions'; import { profile } from '../../../../../utils/store/user'; export let preview; @@ -21,6 +23,15 @@ let currentQuestion = {}; let renderProps = {}; + let submission; + + function getGroupMemberId(people, profileId) { + const groupMember = people.find( + (person) => person.profile_id === profileId + ); + + return groupMember ? groupMember.id : null; + } function handleStart() { $questionnaireMetaData.currentQuestionIndex += 1; @@ -55,13 +66,13 @@ // If last question send to server if (isFinished) { + $questionnaireMetaData.status = 1; submitExercise( $questionnaireMetaData.answers, questions, exerciseId, $course.id, - $group, - $profile + getGroupMemberId($group.people, $profile.id) ); } } @@ -70,15 +81,6 @@ $questionnaireMetaData.currentQuestionIndex -= 1; } - function getTotalScores() { - let total = 0; - for (const score in $questionnaireMetaData.scores) { - total += parseInt($questionnaireMetaData.scores[score]); - } - - return total; - } - function getProgressValue(currentQuestionIndex) { if ($questionnaireMetaData.isFinished) { return 100; @@ -91,6 +93,55 @@ ); } + function getTotalPossibleGrade() { + return $questionnaire.questions.reduce((acc, question) => { + acc += question.points; + return acc; + }, 0); + } + + async function checkForSubmission(people, profileId, courseId) { + console.log('checkForSubmission'); + + if (!Array.isArray(people) || !profileId || !courseId || !!submission) { + return; + } + + const args = { + exerciseId, + courseId, + submittedBy: getGroupMemberId(people, profileId), + }; + const { data } = await fetchSubmission(args); + + if (Array.isArray(data) && data.length) { + console.log(`submissions`, data); + submission = data[0]; + + $questionnaireMetaData.answers = formatAnswers({ + questions: $questionnaire.questions, + answers: submission.answers, + }); + + $questionnaireMetaData.totalPossibleGrade = getTotalPossibleGrade(); + + $questionnaireMetaData.currentQuestionIndex = + $questionnaire.questions.length; + $questionnaireMetaData.isFinished = true; + $questionnaireMetaData.status = submission.status_id; + $questionnaireMetaData.finalTotalGrade = 0; + $questionnaireMetaData.grades = submission.answers.reduce( + (acc, answer) => { + acc[answer.question_id] = answer.point; + $questionnaireMetaData.finalTotalGrade += answer.point; + + return acc; + }, + {} + ); + } + } + $: { currentQuestion = $questionnaire.questions[$questionnaireMetaData.currentQuestionIndex - 1]; @@ -114,6 +165,8 @@ $: $questionnaireMetaData.progressValue = getProgressValue( $questionnaireMetaData.currentQuestionIndex ); + + $: checkForSubmission($group.people, $profile.id, $course.id); {#if !preview && $questionnaire.questions.length && !$questionnaireMetaData.isFinished} @@ -137,7 +190,20 @@ {:else if $questionnaireMetaData.currentQuestionIndex === 0}

{$questionnaire.title}

-

{$questionnaire.description}

+ +
+

+ {$questionnaire.questions.length} questions +

+ | +

+ {getTotalPossibleGrade()} points. +

+ | +

All required

+
+ +

{$questionnaire.description}

{$questionnaire.title}

- {#if STATUS.PENDING === $questionnaireMetaData.status} - - Pending - - {:else if STATUS.GRADED === $questionnaireMetaData.status && getTotalScores() > 0} + {#if STATUS.GRADED === $questionnaireMetaData.status} Graded + {:else} + + Pending + {/if}
@@ -171,12 +237,14 @@ class="border-2 border-gray-700 rounded-full h-24 w-24 flex items-center justify-center text-2xl" title="Status: Pending Review" > - {getTotalScores()}/100 + {$questionnaireMetaData.finalTotalGrade}/{$questionnaireMetaData.totalPossibleGrade}
{:else if currentQuestion} {#key currentQuestion.id} diff --git a/src/components/Course/components/Lesson/Exercise/constants.js b/src/components/Course/components/Lesson/Exercise/constants.js index 0cfdfe64..f3e78a41 100644 --- a/src/components/Course/components/Lesson/Exercise/constants.js +++ b/src/components/Course/components/Lesson/Exercise/constants.js @@ -1,13 +1,13 @@ export const STATUS = { - PENDING: 0, - IN_PROGRESS: 1, - GRADED: 2, + SUBMITTED: 1, + IN_PROGRESS: 2, + GRADED: 3, }; export const SELECTABLE_STATUS = [ { label: 'Submitted', - value: STATUS.PENDING, + value: STATUS.SUBMITTED, }, { label: 'In progress', diff --git a/src/components/Course/components/Lesson/store/answers.js b/src/components/Course/components/Lesson/store/answers.js index 01bff1d0..22b519ec 100644 --- a/src/components/Course/components/Lesson/store/answers.js +++ b/src/components/Course/components/Lesson/store/answers.js @@ -13,6 +13,9 @@ import { STATUS } from '../Exercise/constants'; const initAnswerState = { answers: {}, scores: {}, + grades: {}, + totalPossibleGrade: 0, + finalTotalGrade: 0, currentQuestionIndex: 0, isFinished: false, progressValue: 100, diff --git a/src/components/Course/function.js b/src/components/Course/function.js index 1336e96a..b6e025df 100644 --- a/src/components/Course/function.js +++ b/src/components/Course/function.js @@ -1,4 +1,4 @@ -import { ROUTES } from "./constants"; +import { ROUTES } from './constants'; export function getNavItemRoute(courseId, routeId) { const path = `/${ROUTES.COURSES}/${courseId}`; @@ -27,3 +27,23 @@ export function getLectureNo(index) { return `0${index}`; } + +export function formatAnswers(data) { + const answers = {}; + const questionByIdAndName = {}; + + for (const question of data.questions) { + questionByIdAndName[question.id] = question.name; + } + + for (const answer of data.answers) { + const questionName = questionByIdAndName[answer.question_id]; + + answers[questionName] = + Array.isArray(answer.answers) && answer.answers.length + ? answer.answers + : answer.open_answer; + } + + return answers; +} diff --git a/src/components/Form/Select.svelte b/src/components/Form/Select.svelte index 33f6f405..18092ea6 100644 --- a/src/components/Form/Select.svelte +++ b/src/components/Form/Select.svelte @@ -7,6 +7,7 @@ export let labelKey = 'label'; export let isRequired = false; export let className = ''; + export let selectClassName = ''; export let color = 'default'; // primary export let onChange = () => {}; // This is to know if element is 'dirty' @@ -19,10 +20,10 @@ {#if label} {label} {/if}