From d564d86feb961b33e435c94cace9b4cb8d1788e9 Mon Sep 17 00:00:00 2001 From: Tiago Ribeiro Date: Fri, 15 Nov 2024 16:02:43 +0000 Subject: [PATCH 01/17] Updated the Assignment View to ignore practice questions --- src/dashboards/AssignmentView.tsx | 40 +++++++++++++++---------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/src/dashboards/AssignmentView.tsx b/src/dashboards/AssignmentView.tsx index 8b19aa0c..ee2506d9 100644 --- a/src/dashboards/AssignmentView.tsx +++ b/src/dashboards/AssignmentView.tsx @@ -2,23 +2,23 @@ import Button from "@/components/Low/Button"; import ProgressBar from "@/components/Low/ProgressBar"; import Modal from "@/components/Modal"; import useUsers from "@/hooks/useUsers"; -import {Module} from "@/interfaces"; -import {Assignment} from "@/interfaces/results"; -import {Stat, User} from "@/interfaces/user"; +import { Module } from "@/interfaces"; +import { Assignment } from "@/interfaces/results"; +import { Stat, User } from "@/interfaces/user"; import useExamStore from "@/stores/examStore"; -import {getExamById} from "@/utils/exams"; -import {sortByModule} from "@/utils/moduleUtils"; -import {calculateBandScore} from "@/utils/score"; -import {convertToUserSolutions} from "@/utils/stats"; -import {getUserName} from "@/utils/users"; +import { getExamById } from "@/utils/exams"; +import { sortByModule } from "@/utils/moduleUtils"; +import { calculateBandScore } from "@/utils/score"; +import { convertToUserSolutions } from "@/utils/stats"; +import { getUserName } from "@/utils/users"; import axios from "axios"; import clsx from "clsx"; -import {capitalize, uniqBy} from "lodash"; +import { capitalize, uniqBy } from "lodash"; import moment from "moment"; -import {useRouter} from "next/router"; -import {BsBook, BsClipboard, BsHeadphones, BsMegaphone, BsPen} from "react-icons/bs"; -import {toast} from "react-toastify"; -import {futureAssignmentFilter} from "@/utils/assignments"; +import { useRouter } from "next/router"; +import { BsBook, BsClipboard, BsHeadphones, BsMegaphone, BsPen } from "react-icons/bs"; +import { toast } from "react-toastify"; +import { futureAssignmentFilter } from "@/utils/assignments"; interface Props { isOpen: boolean; @@ -27,7 +27,7 @@ interface Props { onClose: () => void; } -export default function AssignmentView({isOpen, users, assignment, onClose}: Props) { +export default function AssignmentView({ isOpen, users, assignment, onClose }: Props) { const router = useRouter(); const setExams = useExamStore((state) => state.setExams); @@ -80,9 +80,9 @@ export default function AssignmentView({isOpen, users, assignment, onClose}: Pro return resultModuleBandScores.length === 0 ? -1 : resultModuleBandScores.reduce((acc, curr) => acc + curr, 0) / assignment.results.length; }; - const aggregateScoresByModule = (stats: Stat[]): {module: Module; total: number; missing: number; correct: number}[] => { + const aggregateScoresByModule = (stats: Stat[]): { module: Module; total: number; missing: number; correct: number }[] => { const scores: { - [key in Module]: {total: number; missing: number; correct: number}; + [key in Module]: { total: number; missing: number; correct: number }; } = { reading: { total: 0, @@ -111,7 +111,7 @@ export default function AssignmentView({isOpen, users, assignment, onClose}: Pro }, }; - stats.forEach((x) => { + stats.filter(x => !x.isPractice).forEach((x) => { scores[x.module!] = { total: scores[x.module!].total + x.score.total, correct: scores[x.module!].correct + x.score.correct, @@ -121,7 +121,7 @@ export default function AssignmentView({isOpen, users, assignment, onClose}: Pro return Object.keys(scores) .filter((x) => scores[x as Module].total > 0) - .map((x) => ({module: x as Module, ...scores[x as Module]})); + .map((x) => ({ module: x as Module, ...scores[x as Module] })); }; const customContent = (stats: Stat[], user: string, focus: "academic" | "general") => { @@ -180,7 +180,7 @@ export default function AssignmentView({isOpen, users, assignment, onClose}: Pro
- {aggregatedLevels.map(({module, level}) => ( + {aggregatedLevels.map(({ module, level }) => (
Average Scores
{assignment && - uniqBy(assignment.exams, (x) => x.module).map(({module}) => ( + uniqBy(assignment.exams, (x) => x.module).map(({ module }) => (
Date: Sat, 16 Nov 2024 12:03:08 +0000 Subject: [PATCH 02/17] Created a simple Practice Badge to showcase when an exercise is a practice exercise --- src/components/Exercises/FillBlanks/index.tsx | 5 ++++- src/components/Exercises/MatchSentences.tsx | 3 +++ src/components/Exercises/MultipleChoice.tsx | 9 ++++++++- src/components/Exercises/Speaking.tsx | 3 +++ src/components/Exercises/TrueFalse.tsx | 2 ++ src/components/Exercises/WriteBlanks.tsx | 4 +++- src/components/Exercises/Writing.tsx | 3 +++ src/components/Low/PracticeBadge.tsx | 11 +++++++++++ src/components/Solutions/MultipleChoice.tsx | 12 +++++++++--- 9 files changed, 46 insertions(+), 6 deletions(-) create mode 100644 src/components/Low/PracticeBadge.tsx diff --git a/src/components/Exercises/FillBlanks/index.tsx b/src/components/Exercises/FillBlanks/index.tsx index d138f66e..906d3634 100644 --- a/src/components/Exercises/FillBlanks/index.tsx +++ b/src/components/Exercises/FillBlanks/index.tsx @@ -7,6 +7,7 @@ import { CommonProps } from ".."; import Button from "../../Low/Button"; import { v4 } from "uuid"; import MCDropdown from "./MCDropdown"; +import PracticeBadge from "@/components/Low/PracticeBadge"; const FillBlanks: React.FC = ({ id, @@ -196,7 +197,7 @@ const FillBlanks: React.FC = ({
{!disableProgressButtons && progressButtons()} -
+
{variant !== "mc" && ( {prompt.split("\\n").map((line, index) => ( @@ -207,6 +208,7 @@ const FillBlanks: React.FC = ({ ))} )} + {isPractice && } {memoizedLines} {variant !== "mc" && (
@@ -234,6 +236,7 @@ const FillBlanks: React.FC = ({
)} +
{!disableProgressButtons && progressButtons()} diff --git a/src/components/Exercises/MatchSentences.tsx b/src/components/Exercises/MatchSentences.tsx index 0e00a90c..3709ef82 100644 --- a/src/components/Exercises/MatchSentences.tsx +++ b/src/components/Exercises/MatchSentences.tsx @@ -10,6 +10,7 @@ import Button from "../Low/Button"; import Xarrow from "react-xarrows"; import useExamStore from "@/stores/examStore"; import { DndContext, DragEndEvent, useDraggable, useDroppable } from "@dnd-kit/core"; +import PracticeBadge from "../Low/PracticeBadge"; function DroppableQuestionArea({ question, answer }: { question: MatchSentenceExerciseSentence; answer?: string }) { const { isOver, setNodeRef } = useDroppable({ id: `droppable_sentence_${question.id}` }); @@ -148,6 +149,8 @@ export default function MatchSentences({ ))} + {isPractice && } +
diff --git a/src/components/Exercises/MultipleChoice.tsx b/src/components/Exercises/MultipleChoice.tsx index bed48996..e4a5048c 100644 --- a/src/components/Exercises/MultipleChoice.tsx +++ b/src/components/Exercises/MultipleChoice.tsx @@ -7,6 +7,7 @@ import reactStringReplace from "react-string-replace"; import { CommonProps } from "."; import Button from "../Low/Button"; import { v4 } from "uuid"; +import PracticeBadge from "../Low/PracticeBadge"; function Question({ id, @@ -15,10 +16,12 @@ function Question({ options, userSolution, onSelectOption, + isPractice = false }: MultipleChoiceQuestion & { userSolution: string | undefined; onSelectOption?: (option: string) => void; showSolution?: boolean; + isPractice?: boolean }) { const renderPrompt = (prompt: string) => { return reactStringReplace(prompt, /(.*?<\/u>)/g, (match) => { @@ -28,7 +31,8 @@ function Question({ }; return ( -
+
+ {isPractice && } {isNaN(Number(id)) ? ( {renderPrompt(prompt).filter((x) => x?.toString() !== "")} ) : ( @@ -194,6 +198,7 @@ export default function MultipleChoice({ key={question.id} className="flex flex-col gap-8 h-fit w-full bg-mti-gray-smoke rounded-xl px-16 py-8"> question.id === x.question)?.option} onSelectOption={(option) => onSelectOption(option, question)} /> @@ -206,6 +211,7 @@ export default function MultipleChoice({ {questionIndex < questions.length && ( questions[questionIndex].id === x.question)?.option} onSelectOption={(option) => onSelectOption(option, questions[questionIndex])} /> @@ -216,6 +222,7 @@ export default function MultipleChoice({
questions[questionIndex + 1].id === x.question)?.option} onSelectOption={(option) => onSelectOption(option, questions[questionIndex + 1])} /> diff --git a/src/components/Exercises/Speaking.tsx b/src/components/Exercises/Speaking.tsx index 2614aca6..e6a4472b 100644 --- a/src/components/Exercises/Speaking.tsx +++ b/src/components/Exercises/Speaking.tsx @@ -8,6 +8,7 @@ import useExamStore from "@/stores/examStore"; import { downloadBlob } from "@/utils/evaluation"; import axios from "axios"; import Modal from "../Modal"; +import PracticeBadge from "../Low/PracticeBadge"; const Waveform = dynamic(() => import("../Waveform"), { ssr: false }); const ReactMediaRecorder = dynamic(() => import("react-media-recorder").then((mod) => mod.ReactMediaRecorder), { @@ -172,6 +173,8 @@ export default function Speaking({ id, title, text, video_url, type, prompts, su
+ {isPractice && } + {prompts && prompts.length > 0 && (