Compare commits
4
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
61a189a7a2 | ||
|
|
ab6f0b09d7 | ||
|
|
16ae3aa089 | ||
|
|
496ec2cbf9 |
@@ -6,7 +6,7 @@ import ArrowBackIcon from '@mui/icons-material/ArrowBack'
|
|||||||
import SaveIcon from '@mui/icons-material/Save'
|
import SaveIcon from '@mui/icons-material/Save'
|
||||||
import MouseIcon from '@mui/icons-material/Mouse'
|
import MouseIcon from '@mui/icons-material/Mouse'
|
||||||
import '@tldraw/tldraw/tldraw.css'
|
import '@tldraw/tldraw/tldraw.css'
|
||||||
import { Editor, Tldraw, createShapeId, defaultBindingUtils, TLShape } from '@tldraw/tldraw'
|
import { Editor, Tldraw, createShapeId, TLShape } from '@tldraw/tldraw'
|
||||||
import axios from 'axios'
|
import axios from 'axios'
|
||||||
|
|
||||||
import { ErrorBoundary } from '../../../components/ErrorBoundary'
|
import { ErrorBoundary } from '../../../components/ErrorBoundary'
|
||||||
@@ -17,7 +17,7 @@ import { ExamCanvasShapeModel, PAGE_HEIGHT, PAGE_WIDTH, isUuid, newDomainId, ser
|
|||||||
import { examCanvasShapeUtils, examCanvasTools, ExamCanvasTLShape, SHAPE_TYPES, shapeTypeToKind } from './examCanvasShapes'
|
import { examCanvasShapeUtils, examCanvasTools, ExamCanvasTLShape, SHAPE_TYPES, shapeTypeToKind } from './examCanvasShapes'
|
||||||
|
|
||||||
const TOOLS = [
|
const TOOLS = [
|
||||||
{ id: 'select', label: 'Select', tip: 'Move, resize, or delete shapes.', color: 'default' as const },
|
{ id: 'select', label: 'Select', tip: 'Move, resize, or delete shapes.', color: 'inherit' as const },
|
||||||
{ id: SHAPE_TYPES.boundary, label: 'Boundary', tip: 'Draw one horizontal line. A main question is saved from each top+bottom pair.', color: 'error' as const },
|
{ id: SHAPE_TYPES.boundary, label: 'Boundary', tip: 'Draw one horizontal line. A main question is saved from each top+bottom pair.', color: 'error' as const },
|
||||||
{ id: SHAPE_TYPES.part, label: 'Part', tip: 'Draw the markable sub-question box inside a boundary pair.', color: 'warning' as const },
|
{ id: SHAPE_TYPES.part, label: 'Part', tip: 'Draw the markable sub-question box inside a boundary pair.', color: 'warning' as const },
|
||||||
{ id: SHAPE_TYPES.response, label: 'Response', tip: 'Draw around where the student writes; saved with response_form=lines.', color: 'primary' as const },
|
{ id: SHAPE_TYPES.response, label: 'Response', tip: 'Draw around where the student writes; saved with response_form=lines.', color: 'primary' as const },
|
||||||
@@ -25,7 +25,7 @@ const TOOLS = [
|
|||||||
{ id: SHAPE_TYPES.question_number, label: 'Q Number', tip: 'Box the printed question number.', color: 'success' as const },
|
{ id: SHAPE_TYPES.question_number, label: 'Q Number', tip: 'Box the printed question number.', color: 'success' as const },
|
||||||
{ id: SHAPE_TYPES.mark_area, label: 'Mark Area', tip: 'Box printed marks such as [2].', color: 'success' as const },
|
{ id: SHAPE_TYPES.mark_area, label: 'Mark Area', tip: 'Box printed marks such as [2].', color: 'success' as const },
|
||||||
{ id: SHAPE_TYPES.reference, label: 'Reference', tip: 'Box student resources/reference material.', color: 'info' as const },
|
{ id: SHAPE_TYPES.reference, label: 'Reference', tip: 'Box student resources/reference material.', color: 'info' as const },
|
||||||
{ id: SHAPE_TYPES.furniture, label: 'Furniture', tip: 'Mark margins/page numbers/ignored decoration.', color: 'default' as const },
|
{ id: SHAPE_TYPES.furniture, label: 'Furniture', tip: 'Mark margins/page numbers/ignored decoration.', color: 'inherit' as const },
|
||||||
]
|
]
|
||||||
|
|
||||||
function apiMessage(err: unknown): { message: string; conflict: boolean } {
|
function apiMessage(err: unknown): { message: string; conflict: boolean } {
|
||||||
@@ -178,14 +178,13 @@ const ExamTemplateSetupInner: React.FC = () => {
|
|||||||
<Box sx={{ position: 'absolute', inset: 0, '& .tlui-layout': { display: 'none' } }} data-testid="exam-template-setup-canvas">
|
<Box sx={{ position: 'absolute', inset: 0, '& .tlui-layout': { display: 'none' } }} data-testid="exam-template-setup-canvas">
|
||||||
<Tldraw
|
<Tldraw
|
||||||
shapeUtils={examCanvasShapeUtils as any}
|
shapeUtils={examCanvasShapeUtils as any}
|
||||||
bindingUtils={defaultBindingUtils}
|
|
||||||
tools={examCanvasTools as any}
|
tools={examCanvasTools as any}
|
||||||
hideUi
|
hideUi
|
||||||
inferDarkMode={theme.palette.mode === 'dark'}
|
inferDarkMode={theme.palette.mode === 'dark'}
|
||||||
autoFocus
|
autoFocus
|
||||||
onMount={(editor) => {
|
onMount={(editor) => {
|
||||||
editorRef.current = editor
|
editorRef.current = editor
|
||||||
editor.user.updateUserPreferences({ isDarkMode: theme.palette.mode === 'dark' })
|
editor.user.updateUserPreferences({ colorScheme: theme.palette.mode === 'dark' ? 'dark' : 'light' })
|
||||||
editor.store.listen(() => setDirty(true), { scope: 'document' })
|
editor.store.listen(() => setDirty(true), { scope: 'document' })
|
||||||
if (template) loadShapes(editor, shapesFromTemplate(template)); else seedGuide(editor)
|
if (template) loadShapes(editor, shapesFromTemplate(template)); else seedGuide(editor)
|
||||||
}}
|
}}
|
||||||
|
|||||||
@@ -67,9 +67,11 @@ function defaultProps(kind: ExamCanvasShapeKind, w: number, h: number) {
|
|||||||
return { w, h, label: p.label, kind, responseForm: kind === 'response' ? 'lines' : undefined, contextType: kind === 'context' ? 'generic' : undefined }
|
return { w, h, label: p.label, kind, responseForm: kind === 'response' ? 'lines' : undefined, contextType: kind === 'context' ? 'generic' : undefined }
|
||||||
}
|
}
|
||||||
|
|
||||||
class BoundaryUtil extends BaseBoxShapeUtil<ExamCanvasTLShape> { static override type = SHAPE_TYPES.boundary; static override props = { w: T.number, h: T.number, label: T.string, kind: T.string, maxMarks: T.optional(T.number), responseForm: T.optional(T.string), contextType: T.optional(T.string), questionId: T.optional(T.string), domainId: T.optional(T.string) }; override getDefaultProps(){ return defaultProps('boundary', 680, 8) }; override component(shape: ExamCanvasTLShape){ return renderShape(shape) } }
|
const sharedProps = { w: T.number, h: T.number, label: T.string, kind: T.string, maxMarks: T.optional(T.number), responseForm: T.optional(T.string), contextType: T.optional(T.string), questionId: T.optional(T.string), domainId: T.optional(T.string) }
|
||||||
class PartUtil extends BaseBoxShapeUtil<ExamCanvasTLShape> { static override type = SHAPE_TYPES.part; static override props = BoundaryUtil.props; override getDefaultProps(){ return defaultProps('part', 420, 170) }; override component(shape: ExamCanvasTLShape){ return renderShape(shape) } }
|
const ind = (s: ExamCanvasTLShape) => <rect width={toDomPrecision(s.props.w)} height={toDomPrecision(s.props.h)} />
|
||||||
function regionUtil(type: string, kind: ExamCanvasRegionKind, w = 360, h = 120) { return class extends BaseBoxShapeUtil<ExamCanvasTLShape> { static override type = type; static override props = BoundaryUtil.props; override getDefaultProps(){ return defaultProps(kind, w, h) }; override component(shape: ExamCanvasTLShape){ return renderShape(shape) } } }
|
class BoundaryUtil extends BaseBoxShapeUtil<ExamCanvasTLShape> { static override type = SHAPE_TYPES.boundary; static override props = sharedProps; override getDefaultProps(){ return defaultProps('boundary', 680, 8) }; override component(shape: ExamCanvasTLShape){ return renderShape(shape) }; override indicator(shape: ExamCanvasTLShape){ return ind(shape) } }
|
||||||
|
class PartUtil extends BaseBoxShapeUtil<ExamCanvasTLShape> { static override type = SHAPE_TYPES.part; static override props = sharedProps; override getDefaultProps(){ return defaultProps('part', 420, 170) }; override component(shape: ExamCanvasTLShape){ return renderShape(shape) }; override indicator(shape: ExamCanvasTLShape){ return ind(shape) } }
|
||||||
|
function regionUtil(type: string, kind: ExamCanvasRegionKind, w = 360, h = 120) { return class extends BaseBoxShapeUtil<ExamCanvasTLShape> { static override type = type; static override props = sharedProps; override getDefaultProps(){ return defaultProps(kind, w, h) }; override component(shape: ExamCanvasTLShape){ return renderShape(shape) }; override indicator(shape: ExamCanvasTLShape){ return ind(shape) } } }
|
||||||
|
|
||||||
class BoundaryTool extends BaseBoxShapeTool { static override id = SHAPE_TYPES.boundary; static override initial = 'pointing'; shapeType = SHAPE_TYPES.boundary }
|
class BoundaryTool extends BaseBoxShapeTool { static override id = SHAPE_TYPES.boundary; static override initial = 'pointing'; shapeType = SHAPE_TYPES.boundary }
|
||||||
class PartTool extends BaseBoxShapeTool { static override id = SHAPE_TYPES.part; static override initial = 'pointing'; shapeType = SHAPE_TYPES.part }
|
class PartTool extends BaseBoxShapeTool { static override id = SHAPE_TYPES.part; static override initial = 'pointing'; shapeType = SHAPE_TYPES.part }
|
||||||
|
|||||||
Reference in New Issue
Block a user