From 4cee4133a8a81321c2c0169191f9dcfca5018704 Mon Sep 17 00:00:00 2001 From: Ivan Procaccini Date: Wed, 2 Oct 2024 12:55:40 +0200 Subject: [PATCH 1/5] feat: implement read-only task components for marking --- .../Task/{ => assessment}/index.tsx | 6 +-- .../{ => assessment}/variants/CodeTask.tsx | 10 ++-- .../{ => assessment}/variants/EssayTask.tsx | 8 +-- .../variants/FlagTask.tsx} | 6 +-- .../Task/{ => assessment}/variants/MCQ.tsx | 8 +-- .../{ => assessment}/variants/NumberTask.tsx | 8 +-- .../handwriting/ProcessedHandwritingTask.tsx | 6 +-- .../handwriting/RawHandwritingTask.tsx | 6 +-- .../handwriting/components/Canvas/index.scss | 0 .../handwriting/components/Canvas/index.tsx | 2 +- .../components/ViewOnlyCanvas/index.scss | 0 .../components/ViewOnlyCanvas/index.tsx | 0 .../ProcessedHandwritingEditor/index.css | 0 .../ProcessedHandwritingEditor/index.tsx | 0 .../editors/RawHandwritingEditor/index.css | 0 .../rawHandwritingEditor.tsx | 0 .../handwriting/hooks/live-updates.hook.ts | 4 +- .../variants/handwriting/types.ts | 0 .../FlagTask/index.css => flagTask.css} | 4 +- .../questionStructure/Task/marking/index.tsx | 49 +++++++++++++++++++ .../Task/marking/variants/CodeTask.tsx | 22 +++++++++ .../Task/marking/variants/EssayTask.tsx | 20 ++++++++ .../Task/marking/variants/FlagTask.tsx | 33 +++++++++++++ .../Task/marking/variants/MCQ.tsx | 45 +++++++++++++++++ .../Task/marking/variants/NumberTask.tsx | 13 +++++ .../handwriting/ProcessedHandwritingTask.tsx | 31 ++++++++++++ .../handwriting/RawHandwritingTask.tsx | 18 +++++++ .../components/ViewOnlyCanvas/index.scss | 16 ++++++ .../components/ViewOnlyCanvas/index.tsx | 44 +++++++++++++++++ .../marking/variants/handwriting/types.ts | 21 ++++++++ .../questionStructure/Task/types.ts | 3 ++ src/pages/MarkingPage/MarkableSubmission.tsx | 6 +-- src/pages/QuestionPage/index.tsx | 2 +- .../questionStructure/Task.test.tsx | 6 +-- .../questionStructure/TaskVariants.test.tsx | 13 +++-- 35 files changed, 363 insertions(+), 47 deletions(-) rename src/components/questionStructure/Task/{ => assessment}/index.tsx (93%) rename src/components/questionStructure/Task/{ => assessment}/variants/CodeTask.tsx (83%) rename src/components/questionStructure/Task/{ => assessment}/variants/EssayTask.tsx (84%) rename src/components/questionStructure/Task/{variants/FlagTask/index.tsx => assessment/variants/FlagTask.tsx} (92%) rename src/components/questionStructure/Task/{ => assessment}/variants/MCQ.tsx (90%) rename src/components/questionStructure/Task/{ => assessment}/variants/NumberTask.tsx (82%) rename src/components/questionStructure/Task/{ => assessment}/variants/handwriting/ProcessedHandwritingTask.tsx (92%) rename src/components/questionStructure/Task/{ => assessment}/variants/handwriting/RawHandwritingTask.tsx (91%) rename src/components/questionStructure/Task/{ => assessment}/variants/handwriting/components/Canvas/index.scss (100%) rename src/components/questionStructure/Task/{ => assessment}/variants/handwriting/components/Canvas/index.tsx (98%) rename src/components/questionStructure/Task/{ => assessment}/variants/handwriting/components/ViewOnlyCanvas/index.scss (100%) rename src/components/questionStructure/Task/{ => assessment}/variants/handwriting/components/ViewOnlyCanvas/index.tsx (100%) rename src/components/questionStructure/Task/{ => assessment}/variants/handwriting/editors/ProcessedHandwritingEditor/index.css (100%) rename src/components/questionStructure/Task/{ => assessment}/variants/handwriting/editors/ProcessedHandwritingEditor/index.tsx (100%) rename src/components/questionStructure/Task/{ => assessment}/variants/handwriting/editors/RawHandwritingEditor/index.css (100%) rename src/components/questionStructure/Task/{ => assessment}/variants/handwriting/editors/RawHandwritingEditor/rawHandwritingEditor.tsx (100%) rename src/components/questionStructure/Task/{ => assessment}/variants/handwriting/hooks/live-updates.hook.ts (97%) rename src/components/questionStructure/Task/{ => assessment}/variants/handwriting/types.ts (100%) rename src/components/questionStructure/Task/{variants/FlagTask/index.css => flagTask.css} (83%) create mode 100644 src/components/questionStructure/Task/marking/index.tsx create mode 100644 src/components/questionStructure/Task/marking/variants/CodeTask.tsx create mode 100644 src/components/questionStructure/Task/marking/variants/EssayTask.tsx create mode 100644 src/components/questionStructure/Task/marking/variants/FlagTask.tsx create mode 100644 src/components/questionStructure/Task/marking/variants/MCQ.tsx create mode 100644 src/components/questionStructure/Task/marking/variants/NumberTask.tsx create mode 100644 src/components/questionStructure/Task/marking/variants/handwriting/ProcessedHandwritingTask.tsx create mode 100644 src/components/questionStructure/Task/marking/variants/handwriting/RawHandwritingTask.tsx create mode 100644 src/components/questionStructure/Task/marking/variants/handwriting/components/ViewOnlyCanvas/index.scss create mode 100644 src/components/questionStructure/Task/marking/variants/handwriting/components/ViewOnlyCanvas/index.tsx create mode 100644 src/components/questionStructure/Task/marking/variants/handwriting/types.ts diff --git a/src/components/questionStructure/Task/index.tsx b/src/components/questionStructure/Task/assessment/index.tsx similarity index 93% rename from src/components/questionStructure/Task/index.tsx rename to src/components/questionStructure/Task/assessment/index.tsx index cd72aa5..d974bd4 100644 --- a/src/components/questionStructure/Task/index.tsx +++ b/src/components/questionStructure/Task/assessment/index.tsx @@ -1,9 +1,9 @@ import { Flex } from '@radix-ui/themes' import React, { FC } from 'react' -import Markdown from '../../Markdown' -import { TaskType } from './constants' -import './index.css' +import Markdown from '../../../Markdown' +import { TaskType } from '../constants' +import '../index.css' import { CodeTask, CodeTaskProps } from './variants/CodeTask' import { EssayTask, EssayTaskProps } from './variants/EssayTask' import { FlagTask, FlagTaskProps } from './variants/FlagTask' diff --git a/src/components/questionStructure/Task/variants/CodeTask.tsx b/src/components/questionStructure/Task/assessment/variants/CodeTask.tsx similarity index 83% rename from src/components/questionStructure/Task/variants/CodeTask.tsx rename to src/components/questionStructure/Task/assessment/variants/CodeTask.tsx index da6eeff..1fbfbb2 100644 --- a/src/components/questionStructure/Task/variants/CodeTask.tsx +++ b/src/components/questionStructure/Task/assessment/variants/CodeTask.tsx @@ -2,12 +2,12 @@ import { TextArea, TextField } from '@radix-ui/themes' import { isEqual } from 'lodash' import React, { FC, useEffect, useMemo, useState } from 'react' -import useDebounce from '../../../../hooks/debouncing' -import { TaskType } from '../constants' -import '../index.css' -import { TaskBaseProps } from '../types' +import useDebounce from '../../../../../hooks/debouncing' +import { TaskType } from '../../constants' +import '../../index.css' +import { AssessmentTaskProps } from '../../types' -export interface CodeTaskProps extends TaskBaseProps { +export interface CodeTaskProps extends AssessmentTaskProps { type: TaskType.CODE lines?: number } diff --git a/src/components/questionStructure/Task/variants/EssayTask.tsx b/src/components/questionStructure/Task/assessment/variants/EssayTask.tsx similarity index 84% rename from src/components/questionStructure/Task/variants/EssayTask.tsx rename to src/components/questionStructure/Task/assessment/variants/EssayTask.tsx index 9cd0dea..80002b1 100644 --- a/src/components/questionStructure/Task/variants/EssayTask.tsx +++ b/src/components/questionStructure/Task/assessment/variants/EssayTask.tsx @@ -2,11 +2,11 @@ import { TextArea, TextField } from '@radix-ui/themes' import { isEqual } from 'lodash' import React, { FC, useEffect, useMemo, useState } from 'react' -import useDebounce from '../../../../hooks/debouncing' -import { TaskType } from '../constants' -import { TaskBaseProps } from '../types' +import useDebounce from '../../../../../hooks/debouncing' +import { TaskType } from '../../constants' +import { AssessmentTaskProps } from '../../types' -export interface EssayTaskProps extends TaskBaseProps { +export interface EssayTaskProps extends AssessmentTaskProps { type: TaskType.ESSAY lines?: number } diff --git a/src/components/questionStructure/Task/variants/FlagTask/index.tsx b/src/components/questionStructure/Task/assessment/variants/FlagTask.tsx similarity index 92% rename from src/components/questionStructure/Task/variants/FlagTask/index.tsx rename to src/components/questionStructure/Task/assessment/variants/FlagTask.tsx index d93d88f..839b55c 100644 --- a/src/components/questionStructure/Task/variants/FlagTask/index.tsx +++ b/src/components/questionStructure/Task/assessment/variants/FlagTask.tsx @@ -5,10 +5,10 @@ import React, { FC, useEffect, useMemo, useState } from 'react' import useDebounce from '../../../../../hooks/debouncing' import { TaskType } from '../../constants' -import { TaskBaseProps } from '../../types' -import './index.css' +import '../../flagTask.css' +import { AssessmentTaskProps } from '../../types' -export interface FlagTaskProps extends TaskBaseProps { +export interface FlagTaskProps extends AssessmentTaskProps { type: TaskType.FLAG showOrnament?: boolean } diff --git a/src/components/questionStructure/Task/variants/MCQ.tsx b/src/components/questionStructure/Task/assessment/variants/MCQ.tsx similarity index 90% rename from src/components/questionStructure/Task/variants/MCQ.tsx rename to src/components/questionStructure/Task/assessment/variants/MCQ.tsx index b4f83d5..887f3b6 100644 --- a/src/components/questionStructure/Task/variants/MCQ.tsx +++ b/src/components/questionStructure/Task/assessment/variants/MCQ.tsx @@ -2,20 +2,20 @@ import { CheckboxGroup, RadioGroup } from '@radix-ui/themes' import { isEqual, map } from 'lodash' import React, { FC, useEffect, useMemo, useState } from 'react' -import { TaskType } from '../constants' -import { TaskBaseProps } from '../types' +import { TaskType } from '../../constants' +import { AssessmentTaskProps } from '../../types' type MCQOption = { value: string label: string } -export interface MCQOneTaskProps extends TaskBaseProps { +export interface MCQOneTaskProps extends AssessmentTaskProps { type: TaskType.MULTIPLE_CHOICE_SELECT_ONE choices: MCQOption[] } -export interface MCQMultiTaskProps extends TaskBaseProps { +export interface MCQMultiTaskProps extends AssessmentTaskProps { type: TaskType.MULTIPLE_CHOICE_SELECT_SEVERAL choices: MCQOption[] } diff --git a/src/components/questionStructure/Task/variants/NumberTask.tsx b/src/components/questionStructure/Task/assessment/variants/NumberTask.tsx similarity index 82% rename from src/components/questionStructure/Task/variants/NumberTask.tsx rename to src/components/questionStructure/Task/assessment/variants/NumberTask.tsx index 90502d0..ab2ee24 100644 --- a/src/components/questionStructure/Task/variants/NumberTask.tsx +++ b/src/components/questionStructure/Task/assessment/variants/NumberTask.tsx @@ -2,11 +2,11 @@ import { TextField } from '@radix-ui/themes' import { isEqual } from 'lodash' import React, { FC, useEffect, useMemo, useState } from 'react' -import useDebounce from '../../../../hooks/debouncing' -import { TaskType } from '../constants' -import { TaskBaseProps } from '../types' +import useDebounce from '../../../../../hooks/debouncing' +import { TaskType } from '../../constants' +import { AssessmentTaskProps } from '../../types' -export interface NumberTaskProps extends TaskBaseProps { +export interface NumberTaskProps extends AssessmentTaskProps { type: TaskType.INTEGER } diff --git a/src/components/questionStructure/Task/variants/handwriting/ProcessedHandwritingTask.tsx b/src/components/questionStructure/Task/assessment/variants/handwriting/ProcessedHandwritingTask.tsx similarity index 92% rename from src/components/questionStructure/Task/variants/handwriting/ProcessedHandwritingTask.tsx rename to src/components/questionStructure/Task/assessment/variants/handwriting/ProcessedHandwritingTask.tsx index 19c52e2..f79dfa7 100644 --- a/src/components/questionStructure/Task/variants/handwriting/ProcessedHandwritingTask.tsx +++ b/src/components/questionStructure/Task/assessment/variants/handwriting/ProcessedHandwritingTask.tsx @@ -4,12 +4,12 @@ import { MathJax } from 'better-react-mathjax' import { isEmpty, isEqual } from 'lodash' import { FC, useEffect, useMemo, useState } from 'react' -import { TaskType } from '../../constants' -import { TaskBaseProps } from '../../types' +import { TaskType } from '../../../constants' +import { AssessmentTaskProps } from '../../../types' import { ViewOnlyCanvas } from './components/ViewOnlyCanvas' import { ProcessedHandwritingEditor } from './editors/ProcessedHandwritingEditor' -export interface ProcessedHandwritingProps extends TaskBaseProps { +export interface ProcessedHandwritingProps extends AssessmentTaskProps { type: TaskType.PROCESSED_HANDWRITING } diff --git a/src/components/questionStructure/Task/variants/handwriting/RawHandwritingTask.tsx b/src/components/questionStructure/Task/assessment/variants/handwriting/RawHandwritingTask.tsx similarity index 91% rename from src/components/questionStructure/Task/variants/handwriting/RawHandwritingTask.tsx rename to src/components/questionStructure/Task/assessment/variants/handwriting/RawHandwritingTask.tsx index 5a23b27..bf460a0 100644 --- a/src/components/questionStructure/Task/variants/handwriting/RawHandwritingTask.tsx +++ b/src/components/questionStructure/Task/assessment/variants/handwriting/RawHandwritingTask.tsx @@ -3,12 +3,12 @@ import { Button, Dialog, Flex } from '@radix-ui/themes' import { isEmpty, isEqual } from 'lodash' import { FC, useEffect, useMemo, useState } from 'react' -import { TaskType } from '../../constants' -import { TaskBaseProps } from '../../types' +import { TaskType } from '../../../constants' +import { AssessmentTaskProps } from '../../../types' import { ViewOnlyCanvas } from './components/ViewOnlyCanvas' import RawHandwritingEditor from './editors/RawHandwritingEditor/rawHandwritingEditor' -export interface RawHandwritingProps extends TaskBaseProps { +export interface RawHandwritingProps extends AssessmentTaskProps { type: TaskType.RAW_HANDWRITING } diff --git a/src/components/questionStructure/Task/variants/handwriting/components/Canvas/index.scss b/src/components/questionStructure/Task/assessment/variants/handwriting/components/Canvas/index.scss similarity index 100% rename from src/components/questionStructure/Task/variants/handwriting/components/Canvas/index.scss rename to src/components/questionStructure/Task/assessment/variants/handwriting/components/Canvas/index.scss diff --git a/src/components/questionStructure/Task/variants/handwriting/components/Canvas/index.tsx b/src/components/questionStructure/Task/assessment/variants/handwriting/components/Canvas/index.tsx similarity index 98% rename from src/components/questionStructure/Task/variants/handwriting/components/Canvas/index.tsx rename to src/components/questionStructure/Task/assessment/variants/handwriting/components/Canvas/index.tsx index ecc2046..5238244 100644 --- a/src/components/questionStructure/Task/variants/handwriting/components/Canvas/index.tsx +++ b/src/components/questionStructure/Task/assessment/variants/handwriting/components/Canvas/index.tsx @@ -13,7 +13,7 @@ import React, { useState, } from 'react' -import { ConfirmDialog } from '../../../../../../ConfirmDialog' +import { ConfirmDialog } from '../../../../../../../ConfirmDialog' import { RawHandwritingAnswer } from '../../types' import './index.scss' diff --git a/src/components/questionStructure/Task/variants/handwriting/components/ViewOnlyCanvas/index.scss b/src/components/questionStructure/Task/assessment/variants/handwriting/components/ViewOnlyCanvas/index.scss similarity index 100% rename from src/components/questionStructure/Task/variants/handwriting/components/ViewOnlyCanvas/index.scss rename to src/components/questionStructure/Task/assessment/variants/handwriting/components/ViewOnlyCanvas/index.scss diff --git a/src/components/questionStructure/Task/variants/handwriting/components/ViewOnlyCanvas/index.tsx b/src/components/questionStructure/Task/assessment/variants/handwriting/components/ViewOnlyCanvas/index.tsx similarity index 100% rename from src/components/questionStructure/Task/variants/handwriting/components/ViewOnlyCanvas/index.tsx rename to src/components/questionStructure/Task/assessment/variants/handwriting/components/ViewOnlyCanvas/index.tsx diff --git a/src/components/questionStructure/Task/variants/handwriting/editors/ProcessedHandwritingEditor/index.css b/src/components/questionStructure/Task/assessment/variants/handwriting/editors/ProcessedHandwritingEditor/index.css similarity index 100% rename from src/components/questionStructure/Task/variants/handwriting/editors/ProcessedHandwritingEditor/index.css rename to src/components/questionStructure/Task/assessment/variants/handwriting/editors/ProcessedHandwritingEditor/index.css diff --git a/src/components/questionStructure/Task/variants/handwriting/editors/ProcessedHandwritingEditor/index.tsx b/src/components/questionStructure/Task/assessment/variants/handwriting/editors/ProcessedHandwritingEditor/index.tsx similarity index 100% rename from src/components/questionStructure/Task/variants/handwriting/editors/ProcessedHandwritingEditor/index.tsx rename to src/components/questionStructure/Task/assessment/variants/handwriting/editors/ProcessedHandwritingEditor/index.tsx diff --git a/src/components/questionStructure/Task/variants/handwriting/editors/RawHandwritingEditor/index.css b/src/components/questionStructure/Task/assessment/variants/handwriting/editors/RawHandwritingEditor/index.css similarity index 100% rename from src/components/questionStructure/Task/variants/handwriting/editors/RawHandwritingEditor/index.css rename to src/components/questionStructure/Task/assessment/variants/handwriting/editors/RawHandwritingEditor/index.css diff --git a/src/components/questionStructure/Task/variants/handwriting/editors/RawHandwritingEditor/rawHandwritingEditor.tsx b/src/components/questionStructure/Task/assessment/variants/handwriting/editors/RawHandwritingEditor/rawHandwritingEditor.tsx similarity index 100% rename from src/components/questionStructure/Task/variants/handwriting/editors/RawHandwritingEditor/rawHandwritingEditor.tsx rename to src/components/questionStructure/Task/assessment/variants/handwriting/editors/RawHandwritingEditor/rawHandwritingEditor.tsx diff --git a/src/components/questionStructure/Task/variants/handwriting/hooks/live-updates.hook.ts b/src/components/questionStructure/Task/assessment/variants/handwriting/hooks/live-updates.hook.ts similarity index 97% rename from src/components/questionStructure/Task/variants/handwriting/hooks/live-updates.hook.ts rename to src/components/questionStructure/Task/assessment/variants/handwriting/hooks/live-updates.hook.ts index 5369052..95d3554 100644 --- a/src/components/questionStructure/Task/variants/handwriting/hooks/live-updates.hook.ts +++ b/src/components/questionStructure/Task/assessment/variants/handwriting/hooks/live-updates.hook.ts @@ -7,8 +7,8 @@ import { SceneData } from '@excalidraw/excalidraw/types/types' import axios, { AxiosError } from 'axios' import { useCallback, useEffect, useRef, useState } from 'react' -import axiosInstance from '../../../../../../api/axiosInstance' -import routes from '../../../../../../api/routes' +import axiosInstance from '../../../../../../../api/axiosInstance' +import routes from '../../../../../../../api/routes' // Constants /** Time to wait with user putting no stroks on the pages before API call */ diff --git a/src/components/questionStructure/Task/variants/handwriting/types.ts b/src/components/questionStructure/Task/assessment/variants/handwriting/types.ts similarity index 100% rename from src/components/questionStructure/Task/variants/handwriting/types.ts rename to src/components/questionStructure/Task/assessment/variants/handwriting/types.ts diff --git a/src/components/questionStructure/Task/variants/FlagTask/index.css b/src/components/questionStructure/Task/flagTask.css similarity index 83% rename from src/components/questionStructure/Task/variants/FlagTask/index.css rename to src/components/questionStructure/Task/flagTask.css index 767ced1..9480411 100644 --- a/src/components/questionStructure/Task/variants/FlagTask/index.css +++ b/src/components/questionStructure/Task/flagTask.css @@ -1,7 +1,7 @@ .flag { /* the very anonymous value of 18 was obtained via trial and error - * TODO identify a more programmatic way to derive it - */ + * TODO identify a more programmatic way to derive it + */ width: calc(var(--default-font-size) * 18); } diff --git a/src/components/questionStructure/Task/marking/index.tsx b/src/components/questionStructure/Task/marking/index.tsx new file mode 100644 index 0000000..d974bd4 --- /dev/null +++ b/src/components/questionStructure/Task/marking/index.tsx @@ -0,0 +1,49 @@ +import { Flex } from '@radix-ui/themes' +import React, { FC } from 'react' + +import Markdown from '../../../Markdown' +import { TaskType } from '../constants' +import '../index.css' +import { CodeTask, CodeTaskProps } from './variants/CodeTask' +import { EssayTask, EssayTaskProps } from './variants/EssayTask' +import { FlagTask, FlagTaskProps } from './variants/FlagTask' +import { MCQMultiTask, MCQMultiTaskProps, MCQOneTask, MCQOneTaskProps } from './variants/MCQ' +import { NumberTask, NumberTaskProps } from './variants/NumberTask' +import { + ProcessedHandwritingProps, + ProcessedHandwritingTask, +} from './variants/handwriting/ProcessedHandwritingTask' +import { RawHandwritingProps, RawHandwritingTask } from './variants/handwriting/RawHandwritingTask' + +export type TaskProps = + | FlagTaskProps + | NumberTaskProps + | EssayTaskProps + | CodeTaskProps + | MCQOneTaskProps + | MCQMultiTaskProps + | ProcessedHandwritingProps + | RawHandwritingProps + +const taskComponentMap = { + [TaskType.ESSAY]: EssayTask, + [TaskType.CODE]: CodeTask, + [TaskType.INTEGER]: NumberTask, + [TaskType.FLAG]: FlagTask, + [TaskType.MULTIPLE_CHOICE_SELECT_ONE]: MCQOneTask, + [TaskType.MULTIPLE_CHOICE_SELECT_SEVERAL]: MCQMultiTask, + [TaskType.RAW_HANDWRITING]: RawHandwritingTask, + [TaskType.PROCESSED_HANDWRITING]: ProcessedHandwritingTask, +} as const + +type TaskComponent = FC + +export const TaskFactory: TaskComponent = ({ instructions, ...taskProps }) => { + const Component = taskComponentMap[taskProps.type] as TaskComponent + return ( + + {instructions && {instructions}} + + + ) +} diff --git a/src/components/questionStructure/Task/marking/variants/CodeTask.tsx b/src/components/questionStructure/Task/marking/variants/CodeTask.tsx new file mode 100644 index 0000000..d1d47d9 --- /dev/null +++ b/src/components/questionStructure/Task/marking/variants/CodeTask.tsx @@ -0,0 +1,22 @@ +import { TextArea, TextField } from '@radix-ui/themes' +import React, { FC } from 'react' + +import { TaskType } from '../../constants' +import '../../index.css' +import { TaskBaseProps } from '../../types' + +export interface CodeTaskProps extends TaskBaseProps { + type: TaskType.ESSAY + lines?: number +} + +export const CodeTask: FC = ({ answer, lines }) => { + const commonProps = { + value: answer.answer, + disabled: true, + variant: 'soft' as 'soft', + className: 'monospaced', + } + if (lines === 1) return + return