From fc0b91a4939632f894ab2a1a1297a6e918b891d1 Mon Sep 17 00:00:00 2001 From: Em_Dev Date: Sat, 25 May 2024 05:50:14 +0100 Subject: [PATCH] chore: simplify grading for self paced course (#326) * updated the grading flow for self paced course * updated some logic and translations * fix bug with newsfeed not opening for students and fix more bugs * remove console * add blog template route * add doc page --------- Co-authored-by: Rotimi Best --- .../routes/(redirects)/docs/+layout.svelte | 1 + .../src/routes/(redirects)/docs/+page.svelte | 0 .../components/Lesson/Exercise/Preview.svelte | 5 + .../Lesson/Exercise/ViewMode.svelte | 133 +++--------------- .../components/CourseContainer/index.svelte | 13 +- .../Question/CheckboxQuestion/index.svelte | 7 +- .../Question/RadioQuestion/index.svelte | 7 +- .../Question/TextareaQuestion/index.svelte | 8 +- .../TextEditor/TinymceSvelte/index.svelte | 8 +- .../src/lib/utils/functions/validator.js | 5 - .../src/lib/utils/translations/de.json | 16 ++- .../src/lib/utils/translations/en.json | 12 +- .../src/lib/utils/translations/es.json | 16 ++- .../src/lib/utils/translations/fr.json | 16 ++- .../src/lib/utils/translations/hi.json | 16 ++- .../src/lib/utils/translations/pt.json | 16 ++- .../src/lib/utils/translations/ru.json | 16 ++- .../src/lib/utils/translations/vi.json | 16 ++- .../src/routes/courses/[id]/+page.svelte | 2 +- .../routes/courses/[id]/lessons/+page.svelte | 2 +- .../courses/[id]/submissions/+page.svelte | 2 - .../js/tinymce/skins/content/light/content.js | 2 + .../skins/content/light/content.min.css | 1 + 23 files changed, 144 insertions(+), 176 deletions(-) create mode 100644 apps/classroomio-com/src/routes/(redirects)/docs/+layout.svelte create mode 100644 apps/classroomio-com/src/routes/(redirects)/docs/+page.svelte create mode 100644 apps/dashboard/static/js/tinymce/skins/content/light/content.js create mode 100644 apps/dashboard/static/js/tinymce/skins/content/light/content.min.css diff --git a/apps/classroomio-com/src/routes/(redirects)/docs/+layout.svelte b/apps/classroomio-com/src/routes/(redirects)/docs/+layout.svelte new file mode 100644 index 00000000..4fa864ce --- /dev/null +++ b/apps/classroomio-com/src/routes/(redirects)/docs/+layout.svelte @@ -0,0 +1 @@ + diff --git a/apps/classroomio-com/src/routes/(redirects)/docs/+page.svelte b/apps/classroomio-com/src/routes/(redirects)/docs/+page.svelte new file mode 100644 index 00000000..e69de29b diff --git a/apps/dashboard/src/lib/components/Course/components/Lesson/Exercise/Preview.svelte b/apps/dashboard/src/lib/components/Course/components/Lesson/Exercise/Preview.svelte index 79ca8f72..3e0bec46 100644 --- a/apps/dashboard/src/lib/components/Course/components/Lesson/Exercise/Preview.svelte +++ b/apps/dashboard/src/lib/components/Course/components/Lesson/Exercise/Preview.svelte @@ -4,6 +4,8 @@ import TextareaQuestion from '$lib/components/Question/TextareaQuestion/index.svelte'; import { QUESTION_TYPE } from '$lib/components/Question/constants'; import { getPropsForQuestion } from './functions'; + import { course } from '$lib/components/Course/store'; + import { COURSE_TYPE } from '$lib/utils/types'; export let questions = []; export let questionnaireMetaData = {}; @@ -37,6 +39,7 @@ handleGrade={handleGrade(currentQuestion.id)} {disableGrading} disabled={true} + hideGrading={$course.type === COURSE_TYPE.SELF_PACED} /> {:else if QUESTION_TYPE.CHECKBOX === currentQuestion.question_type.id} {:else if QUESTION_TYPE.TEXTAREA === currentQuestion.question_type.id} {/if} {/each} diff --git a/apps/dashboard/src/lib/components/Course/components/Lesson/Exercise/ViewMode.svelte b/apps/dashboard/src/lib/components/Course/components/Lesson/Exercise/ViewMode.svelte index cb0805c2..2e009185 100644 --- a/apps/dashboard/src/lib/components/Course/components/Lesson/Exercise/ViewMode.svelte +++ b/apps/dashboard/src/lib/components/Course/components/Lesson/Exercise/ViewMode.svelte @@ -17,11 +17,7 @@ import { getPropsForQuestion, filterOutDeleted, wasCorrectAnswerSelected } from './functions'; import { formatAnswers, getGroupMemberId } from '$lib/components/Course/function'; import { submitExercise } from '$lib/utils/services/courses'; - import { - fetchSubmission, - updateQuestionAnswer, - updateSubmission - } from '$lib/utils/services/submissions'; + import { fetchSubmission } from '$lib/utils/services/submissions'; import { profile } from '$lib/utils/store/user'; import { currentOrg } from '$lib/utils/store/org'; import { @@ -30,9 +26,8 @@ } from '$lib/utils/services/notification/notification'; import { lesson } from '../store/lessons'; import { browser } from '$app/environment'; - import { useCompletion } from 'ai/svelte'; import { COURSE_TYPE } from '$lib/utils/types'; - import GradingLoader from './GradingLoader.svelte'; + import { t } from '$lib/utils/functions/translations'; export let preview: boolean = false; export let exerciseId = ''; @@ -44,10 +39,7 @@ let hasSubmission = false; let isLoadingAutoSavedData = false; let alreadyCheckedAutoSavedData = false; - let gradedComment = true; - let isLoading = false; let submissionResponse; - let submissionId; function handleStart() { $questionnaireMetaData.currentQuestionIndex += 1; @@ -88,89 +80,7 @@ }); }; - const { input, handleSubmit, completion } = useCompletion({ - api: '/api/completion/gradingprompt', - onFinish: async () => { - try { - const responseData = $completion.replace('```json', '').replace('```', ''); - - let aiResponses = []; - try { - // Parse the modified response data as JSON - aiResponses = JSON.parse(responseData); - } catch (error) { - console.error('Error parsing AI response', error); - } - - $questionnaire.questions.forEach((question) => { - const { id, points, question_type_id } = question; - let questionAnswer = submissionResponse?.res?.data.find( - (answer) => answer.question_id === id - ); - - console.log('this is the question answer', questionAnswer); - if (question_type_id !== QUESTION_TYPE.TEXTAREA) { - const answer = $questionnaireMetaData.answers[question.name]; - let score = points / answer.length; - $questionnaireMetaData.grades = { - ...$questionnaireMetaData.grades, - [id]: score - }; - updateQuestionAnswer({ point: score }, { id: questionAnswer?.id }); - } else if (aiResponses.length) { - const graded = aiResponses.find((res) => res.id === id); - - $questionnaireMetaData.grades = { - ...$questionnaireMetaData.grades, - [id]: graded.score - }; - updateQuestionAnswer({ point: graded.score }, { id: questionAnswer?.id }); - } - }); - - $questionnaireMetaData.finalTotalGrade = Object.values( - $questionnaireMetaData.grades - ).reduce((acc, answer): number => { - return acc + answer; - }, 0); - - updateSubmission({ - id: submissionId, - status_id: STATUS.GRADED, - total: $questionnaireMetaData.finalTotalGrade - }); - - $questionnaireMetaData.status = STATUS.GRADED; - console.log('grade', $questionnaireMetaData.finalTotalGrade); - } catch (error) { - console.error('Error', error); - } finally { - isLoading = false; - } - } - }); - - function automaticGrading(answers, questions) { - const paragraphAiInput = questions - .filter((q) => q.question_type_id === QUESTION_TYPE.TEXTAREA) - .map((q) => { - const answer = answers?.answers[q.name]; // { open_answer: '' } - return { - id: q.id, - question: q.title, - answer: answer, - point: q.points - }; - }); - $input = JSON.stringify(paragraphAiInput); - handleSubmit({ preventDefault: () => {} }); - } - async function onSubmit(id, value) { - if ($course.type === COURSE_TYPE.SELF_PACED) { - isLoading = true; - } - const { answers } = $questionnaireMetaData; const { questions } = $questionnaire; const prevAnswer = answers[id] || []; @@ -220,11 +130,6 @@ ); if (response) { submissionResponse = response; - submissionId = submissionResponse.submission[0]?.id; - } - - if ($course.type === COURSE_TYPE.SELF_PACED) { - automaticGrading($questionnaireMetaData, $questionnaire.questions); } notifyEducator(); @@ -316,10 +221,6 @@ alreadyCheckedAutoSavedData = true; } - const toggleComments = () => { - gradedComment = !gradedComment; - }; - $: browser && !alreadyCheckedAutoSavedData && getAutoSavedData(); // Reactive code @@ -406,42 +307,46 @@ {:else if $questionnaireMetaData.isFinished} - {#if isLoading} - - {:else if !isLoading && !isLoadingAutoSavedData} + {#if !isLoadingAutoSavedData}

{$questionnaire.title}

+ {#if STATUS.GRADED === $questionnaireMetaData.status} - Graded + {$t('course.navItem.lessons.exercises.all_exercises.view_mode.graded')} + + {:else if $course.type === COURSE_TYPE.SELF_PACED} + + {$t('course.navItem.lessons.exercises.all_exercises.view_mode.submitted')} {:else} - Pending + {$t('course.navItem.lessons.exercises.all_exercises.view_mode.pending')} {/if}
- {#if STATUS.GRADED === $questionnaireMetaData.status} + {#if STATUS.GRADED === $questionnaireMetaData.status && $course.type !== COURSE_TYPE.SELF_PACED} {$questionnaireMetaData.finalTotalGrade}/{$questionnaireMetaData.totalPossibleGrade} {/if}
- {#if $questionnaireMetaData.status === STATUS.GRADED && $questionnaireMetaData.comment} -
+ {#if $questionnaireMetaData.status === STATUS.GRADED && $questionnaireMetaData.comment && $course.type !== COURSE_TYPE.SELF_PACED} +
{$questionnaireMetaData.comment}
{/if} diff --git a/apps/dashboard/src/lib/components/CourseContainer/index.svelte b/apps/dashboard/src/lib/components/CourseContainer/index.svelte index 4bb48aa9..381d3662 100644 --- a/apps/dashboard/src/lib/components/CourseContainer/index.svelte +++ b/apps/dashboard/src/lib/components/CourseContainer/index.svelte @@ -18,7 +18,6 @@ export let courseId = ''; export let path = ''; export let isExercisePage = false; - export let isStudent = false; export let isFetching = false; export let containerClass = ''; @@ -51,20 +50,16 @@ $: onCourseIdChange(courseId); - $: if (typeof $globalStore.isStudent !== 'boolean') { + $: { const user = $group.people.find((person) => person.profile_id === $profile.id); - if (user) { - isStudent = user.role_id === 3; - $globalStore.isStudent = isStudent; + $globalStore.isStudent = user.role_id === 3; - filterPollsByStatus(isStudent); + filterPollsByStatus($globalStore.isStudent); } else if ($profile.id && $group.people.length) { // Current User doesn't have permission to view isPermitted = false; } - } else { - isStudent = $globalStore.isStudent; } @@ -97,7 +92,7 @@
- +
{#if isExercisePage} diff --git a/apps/dashboard/src/lib/components/Question/CheckboxQuestion/index.svelte b/apps/dashboard/src/lib/components/Question/CheckboxQuestion/index.svelte index 3c7b1879..cc12bcad 100644 --- a/apps/dashboard/src/lib/components/Question/CheckboxQuestion/index.svelte +++ b/apps/dashboard/src/lib/components/Question/CheckboxQuestion/index.svelte @@ -7,6 +7,8 @@ import Grade from '$lib/components/Question/Grade.svelte'; import { t } from '$lib/utils/functions/translations'; import ReasonBox from '../ReasonBox.svelte'; + import { course } from '$lib/components/Course/store'; + import { COURSE_TYPE } from '$lib/utils/types'; export let title = ''; export let index = 1; @@ -17,6 +19,7 @@ export let onPrevious = () => {}; export let defaultValue = []; export let disablePreviousButton = false; + export let isLast = false; export let disabled = false; export let isPreview = false; export let nextButtonProps = {}; @@ -134,7 +137,9 @@ diff --git a/apps/dashboard/src/lib/components/Question/RadioQuestion/index.svelte b/apps/dashboard/src/lib/components/Question/RadioQuestion/index.svelte index e8ff0f18..b68c01c8 100644 --- a/apps/dashboard/src/lib/components/Question/RadioQuestion/index.svelte +++ b/apps/dashboard/src/lib/components/Question/RadioQuestion/index.svelte @@ -7,6 +7,8 @@ import Grade from '$lib/components/Question/Grade.svelte'; import { t } from '$lib/utils/functions/translations'; import ReasonBox from '../ReasonBox.svelte'; + import { COURSE_TYPE } from '$lib/utils/types'; + import { course } from '$lib/components/Course/store'; export let title = ''; export let index = 1; @@ -20,6 +22,7 @@ export let disabled = false; export let isPreview = false; export let nextButtonProps = {}; + export let isLast = false; export let grade: number; export let gradeMax = 0; export let disableGrading = false; @@ -135,7 +138,9 @@ diff --git a/apps/dashboard/src/lib/components/Question/TextareaQuestion/index.svelte b/apps/dashboard/src/lib/components/Question/TextareaQuestion/index.svelte index fa082e60..f6745553 100644 --- a/apps/dashboard/src/lib/components/Question/TextareaQuestion/index.svelte +++ b/apps/dashboard/src/lib/components/Question/TextareaQuestion/index.svelte @@ -7,6 +7,8 @@ import Grade from '$lib/components/Question/Grade.svelte'; import { t } from '$lib/utils/functions/translations'; import ReasonBox from '../ReasonBox.svelte'; + import { course } from '$lib/components/Course/store'; + import { COURSE_TYPE } from '$lib/utils/types'; export let title = ''; export let index = 1; @@ -76,7 +78,9 @@
{#if disabled}
- {defaultValue} + {defaultValue === '' + ? $t('course.navItem.lessons.exercises.all_exercises.no_answer') + : defaultValue}
{#if gradeWithAI} @@ -95,7 +99,7 @@
- + answer.question_id == questionId ); - console.log('this is the question answer in the admin side', questionAnswer); const point = questionAnswerByPoint[questionId]; totalPoints += parseInt(point, 10); diff --git a/apps/dashboard/static/js/tinymce/skins/content/light/content.js b/apps/dashboard/static/js/tinymce/skins/content/light/content.js new file mode 100644 index 00000000..37724029 --- /dev/null +++ b/apps/dashboard/static/js/tinymce/skins/content/light/content.js @@ -0,0 +1,2 @@ +tinymce.Resource.add('content/default/content.css', "body{font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Oxygen,Ubuntu,Cantarell,'Open Sans','Helvetica Neue',sans-serif;line-height:1.4;margin:1rem}table{border-collapse:collapse}table:not([cellpadding]) td,table:not([cellpadding]) th{padding:.4rem}table[border]:not([border=\"0\"]):not([style*=border-width]) td,table[border]:not([border=\"0\"]):not([style*=border-width]) th{border-width:1px}table[border]:not([border=\"0\"]):not([style*=border-style]) td,table[border]:not([border=\"0\"]):not([style*=border-style]) th{border-style:solid}table[border]:not([border=\"0\"]):not([style*=border-color]) td,table[border]:not([border=\"0\"]):not([style*=border-color]) th{border-color:#ccc}figure{display:table;margin:1rem auto}figure figcaption{color:#999;display:block;margin-top:.25rem;text-align:center}hr{border-color:#ccc;border-style:solid;border-width:1px 0 0 0}code{background-color:#e8e8e8;border-radius:3px;padding:.1rem .2rem}.mce-content-body:not([dir=rtl]) blockquote{border-left:2px solid #ccc;margin-left:1.5rem;padding-left:1rem}.mce-content-body[dir=rtl] blockquote{border-right:2px solid #ccc;margin-right:1.5rem;padding-right:1rem}") +//# sourceMappingURL=content.js.map diff --git a/apps/dashboard/static/js/tinymce/skins/content/light/content.min.css b/apps/dashboard/static/js/tinymce/skins/content/light/content.min.css new file mode 100644 index 00000000..54bb28d4 --- /dev/null +++ b/apps/dashboard/static/js/tinymce/skins/content/light/content.min.css @@ -0,0 +1 @@ +body{font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Oxygen,Ubuntu,Cantarell,'Open Sans','Helvetica Neue',sans-serif;line-height:1.4;margin:1rem}table{border-collapse:collapse}table:not([cellpadding]) td,table:not([cellpadding]) th{padding:.4rem}table[border]:not([border="0"]):not([style*=border-width]) td,table[border]:not([border="0"]):not([style*=border-width]) th{border-width:1px}table[border]:not([border="0"]):not([style*=border-style]) td,table[border]:not([border="0"]):not([style*=border-style]) th{border-style:solid}table[border]:not([border="0"]):not([style*=border-color]) td,table[border]:not([border="0"]):not([style*=border-color]) th{border-color:#ccc}figure{display:table;margin:1rem auto}figure figcaption{color:#999;display:block;margin-top:.25rem;text-align:center}hr{border-color:#ccc;border-style:solid;border-width:1px 0 0 0}code{background-color:#e8e8e8;border-radius:3px;padding:.1rem .2rem}.mce-content-body:not([dir=rtl]) blockquote{border-left:2px solid #ccc;margin-left:1.5rem;padding-left:1rem}.mce-content-body[dir=rtl] blockquote{border-right:2px solid #ccc;margin-right:1.5rem;padding-right:1rem}