diff --git a/wax-prosemirror-services/src/FillTheGapQuestionService/FillTheGapContainerNodeView.js b/wax-prosemirror-services/src/FillTheGapQuestionService/FillTheGapContainerNodeView.js index dec3f753bdf9c2a074293d884f0e4692fbfeffe7..8fee80cf883009fa78e3a9f61bf9764c90113269 100644 --- a/wax-prosemirror-services/src/FillTheGapQuestionService/FillTheGapContainerNodeView.js +++ b/wax-prosemirror-services/src/FillTheGapQuestionService/FillTheGapContainerNodeView.js @@ -50,6 +50,9 @@ export default class FillTheGapContainerNodeView extends AbstractNodeView { } stopEvent(event) { + if (event.target.type === 'text') { + return true; + } return ( this.context.view[this.node.attrs.id] !== undefined && event.target !== undefined && diff --git a/wax-prosemirror-services/src/FillTheGapQuestionService/components/ContainerEditor.js b/wax-prosemirror-services/src/FillTheGapQuestionService/components/ContainerEditor.js index 29cbe00d8b6be5cadd787805ef09d1f7a73fd27e..b25b24aa21fbbacb32121e9cee12fe2bdae3ce6a 100644 --- a/wax-prosemirror-services/src/FillTheGapQuestionService/components/ContainerEditor.js +++ b/wax-prosemirror-services/src/FillTheGapQuestionService/components/ContainerEditor.js @@ -13,18 +13,6 @@ import { WaxContext } from 'wax-prosemirror-core'; const EditorWrapper = styled.span` > .ProseMirror { - // background: #a6a6a6 !important; - // border: 1px solid #a6a6a6; - // border-radius: 4px; - // box-shadow: none; - // color: #fff !important; - // display: inline; - // min-width: 50px; - // padding: 0px 2px 0px 2px !important; - // white-space: break-spaces; - // width: auto; - // word-wrap: break-word; - &:focus { outline: none; } diff --git a/wax-prosemirror-services/src/FillTheGapQuestionService/components/FeedbackComponent.js b/wax-prosemirror-services/src/FillTheGapQuestionService/components/FeedbackComponent.js new file mode 100644 index 0000000000000000000000000000000000000000..1c34fe93fa6be2001264492c0520742cfbbb6a36 --- /dev/null +++ b/wax-prosemirror-services/src/FillTheGapQuestionService/components/FeedbackComponent.js @@ -0,0 +1,75 @@ +/* eslint-disable react/destructuring-assignment */ +/* eslint-disable react/prop-types */ + +import React, { useContext, useRef, useState, useEffect } from 'react'; +import styled from 'styled-components'; +import { TextSelection } from 'prosemirror-state'; +import { WaxContext } from 'wax-prosemirror-core'; +import { DocumentHelpers } from 'wax-prosemirror-utilities'; + +const FeedBack = styled.div` + color: black; + margin-top: 10px; +`; + +const FeedBackLabel = styled.span` + font-weight: 700; +`; + +const FeedBackInput = styled.input` + // border: none; + display: flex; + width: 100%; +`; + +export default ({ node, view, getPos }) => { + const context = useContext(WaxContext); + const [feedBack, setFeedBack] = useState(' '); + const [typing, setTyping] = useState(false); + const feedBackRef = useRef(null); + + useEffect(() => {}, []); + + const handleKeyDown = e => { + setTyping(true); + if (e.key === 'Backspace') { + context.view.main.dispatch( + context.view.main.state.tr.setSelection( + TextSelection.create(context.view.main.state.tr.doc, null), + ), + ); + } + }; + + const feedBackInput = () => { + setFeedBack(feedBackRef.current.value); + }; + + const saveFeedBack = () => { + return false; + }; + + const onFocus = () => { + context.view.main.dispatch( + context.view.main.state.tr.setSelection( + TextSelection.create(context.view.main.state.tr.doc, null), + ), + ); + }; + + return ( + <FeedBack> + <FeedBackLabel>Feedback</FeedBackLabel> + <FeedBackInput + onBlur={saveFeedBack} + onChange={feedBackInput} + onFocus={onFocus} + onKeyDown={handleKeyDown} + placeholder="Insert feedback" + ref={feedBackRef} + type="text" + value={feedBack} + /> + </FeedBack> + ); +}; diff --git a/wax-prosemirror-services/src/FillTheGapQuestionService/components/FillTheGapContainerComponent.js b/wax-prosemirror-services/src/FillTheGapQuestionService/components/FillTheGapContainerComponent.js index a776e83706530bb86c3c375cf0cc9c1dbf9286f1..742e1fe268d86225aefcca9901c977677409cda6 100644 --- a/wax-prosemirror-services/src/FillTheGapQuestionService/components/FillTheGapContainerComponent.js +++ b/wax-prosemirror-services/src/FillTheGapQuestionService/components/FillTheGapContainerComponent.js @@ -1,12 +1,20 @@ /* eslint-disable react/prop-types */ import React from 'react'; +import styled from 'styled-components'; import ContainerEditor from './ContainerEditor'; +import FeedbackComponent from './FeedbackComponent'; + +const FillTheGapContainer = styled.div` + margin-bottom: 15px; + margin-top: 10px; +`; export default ({ node, view, getPos }) => { return ( - <> + <FillTheGapContainer> + <span>Fill The Gap</span> <ContainerEditor getPos={getPos} node={node} view={view} /> - <div>feedback</div> - </> + <FeedbackComponent getPos={getPos} node={node} view={view} /> + </FillTheGapContainer> ); }; diff --git a/wax-prosemirror-services/src/MultipleChoiceQuestionService/MultipleChoiceContainerNodeView.js b/wax-prosemirror-services/src/MultipleChoiceQuestionService/MultipleChoiceContainerNodeView.js new file mode 100644 index 0000000000000000000000000000000000000000..c00da4041d4b54711280d4542ff97e31ff382117 --- /dev/null +++ b/wax-prosemirror-services/src/MultipleChoiceQuestionService/MultipleChoiceContainerNodeView.js @@ -0,0 +1,55 @@ +import AbstractNodeView from '../PortalService/AbstractNodeView'; + +export default class MultipleChoiceContainerNodeView extends AbstractNodeView { + constructor( + node, + view, + getPos, + decorations, + createPortal, + Component, + context, + ) { + super(node, view, getPos, decorations, createPortal, Component, context); + + this.node = node; + this.outerView = view; + this.getPos = getPos; + this.context = context; + } + + static name() { + return 'multiple_choice_container'; + } + + update(node) { + this.node = node; + if (this.context.view[node.attrs.id]) { + const { state } = this.context.view[node.attrs.id]; + const start = node.content.findDiffStart(state.doc.content); + if (start != null) { + let { a: endA, b: endB } = node.content.findDiffEnd(state.doc.content); + const overlap = start - Math.min(endA, endB); + if (overlap > 0) { + endA += overlap; + endB += overlap; + } + this.context.view[node.attrs.id].dispatch( + state.tr + .replace(start, endB, node.slice(start, endA)) + .setMeta('fromOutside', true), + ); + } + } + + return true; + } + + stopEvent(event) { + if (event.target.type === 'text') { + return true; + } + const innerView = this.context.view[this.node.attrs.id]; + return innerView && innerView.dom.contains(event.target); + } +} diff --git a/wax-prosemirror-services/src/MultipleChoiceQuestionService/MultipleChoiceQuestionService.js b/wax-prosemirror-services/src/MultipleChoiceQuestionService/MultipleChoiceQuestionService.js index 5227d4446a74b6ab56fa8e68f4b0dd645c6e1206..c2a28b8c6b2ff4e660770f005c5d440805c87421 100644 --- a/wax-prosemirror-services/src/MultipleChoiceQuestionService/MultipleChoiceQuestionService.js +++ b/wax-prosemirror-services/src/MultipleChoiceQuestionService/MultipleChoiceQuestionService.js @@ -5,6 +5,7 @@ import multipleChoiceContainerNode from './schema/multipleChoiceContainerNode'; import questionNode from './schema/questionNode'; import AnswerComponent from './components/AnswerComponent'; import QuestionComponent from './components/QuestionComponent'; +import MultipleChoiceContainerNodeView from './MultipleChoiceContainerNodeView'; import MultipleChoiceNodeView from './MultipleChoiceNodeView'; import QuestionNodeView from './QuestionNodeView'; import MultipleChoiceSingleCorrectQuestionService from './MultipleChoiceSingleCorrectQuestionService/MultipleChoiceSingleCorrectQuestionService'; @@ -30,6 +31,12 @@ class MultipleChoiceQuestionService extends Service { question_node_multiple: questionNode, }); + // addPortal({ + // nodeView: MultipleChoiceContainerNodeView, + // component: QuestionComponent, + // context: this.app, + // }); + addPortal({ nodeView: QuestionNodeView, component: QuestionComponent, diff --git a/wax-prosemirror-services/src/MultipleChoiceQuestionService/MultipleChoiceSingleCorrectQuestionService/MultipleChoiceSingleCorrectContainerNodeView.js b/wax-prosemirror-services/src/MultipleChoiceQuestionService/MultipleChoiceSingleCorrectQuestionService/MultipleChoiceSingleCorrectContainerNodeView.js new file mode 100644 index 0000000000000000000000000000000000000000..1e0db88629cc08a63a6c8dd1b8537a83d1ac1bff --- /dev/null +++ b/wax-prosemirror-services/src/MultipleChoiceQuestionService/MultipleChoiceSingleCorrectQuestionService/MultipleChoiceSingleCorrectContainerNodeView.js @@ -0,0 +1,55 @@ +import AbstractNodeView from '../../PortalService/AbstractNodeView'; + +export default class MultipleChoiceSingleCorrectContainerNodeView extends AbstractNodeView { + constructor( + node, + view, + getPos, + decorations, + createPortal, + Component, + context, + ) { + super(node, view, getPos, decorations, createPortal, Component, context); + + this.node = node; + this.outerView = view; + this.getPos = getPos; + this.context = context; + } + + static name() { + return 'multiple_choice_container'; + } + + update(node) { + this.node = node; + if (this.context.view[node.attrs.id]) { + const { state } = this.context.view[node.attrs.id]; + const start = node.content.findDiffStart(state.doc.content); + if (start != null) { + let { a: endA, b: endB } = node.content.findDiffEnd(state.doc.content); + const overlap = start - Math.min(endA, endB); + if (overlap > 0) { + endA += overlap; + endB += overlap; + } + this.context.view[node.attrs.id].dispatch( + state.tr + .replace(start, endB, node.slice(start, endA)) + .setMeta('fromOutside', true), + ); + } + } + + return true; + } + + stopEvent(event) { + if (event.target.type === 'text') { + return true; + } + const innerView = this.context.view[this.node.attrs.id]; + return innerView && innerView.dom.contains(event.target); + } +} diff --git a/wax-prosemirror-services/src/MultipleChoiceQuestionService/MultipleChoiceSingleCorrectQuestionService/MultipleChoiceSingleCorrectQuestionService.js b/wax-prosemirror-services/src/MultipleChoiceQuestionService/MultipleChoiceSingleCorrectQuestionService/MultipleChoiceSingleCorrectQuestionService.js index 48e7ac31ba2408f4a97e3589f6bcececa8d4d80f..9f1901ab66720b24f67e01e24b3b12b49111c931 100644 --- a/wax-prosemirror-services/src/MultipleChoiceQuestionService/MultipleChoiceSingleCorrectQuestionService/MultipleChoiceSingleCorrectQuestionService.js +++ b/wax-prosemirror-services/src/MultipleChoiceQuestionService/MultipleChoiceSingleCorrectQuestionService/MultipleChoiceSingleCorrectQuestionService.js @@ -4,6 +4,7 @@ import multipleChoiceSingleCorrectNode from './schema/multipleChoiceSingleCorrec import multipleChoiceSingleCorrectContainerNode from './schema/multipleChoiceSingleCorrectContainerNode'; import questionSingleNode from './schema/questionSingleNode'; import AnswerComponent from './components/AnswerComponent'; +import MultipleChoiceSingleCorrectContainerNodeView from './MultipleChoiceSingleCorrectContainerNodeView'; import MultipleChoiceSingleCorrectNodeView from './MultipleChoiceSingleCorrectNodeView'; import QuestionMultipleSingleNodeView from './QuestionMultipleSingleNodeView'; import QuestionComponent from '../components/QuestionComponent'; @@ -17,17 +18,23 @@ class MultipleChoiceSingleCorrectQuestionService extends Service { const addPortal = this.container.get('AddPortal'); createNode({ - multiple_choice_single_correct: multipleChoiceSingleCorrectNode, + multiple_choice_single_correct_container: multipleChoiceSingleCorrectContainerNode, }); createNode({ - multiple_choice_single_correct_container: multipleChoiceSingleCorrectContainerNode, + multiple_choice_single_correct: multipleChoiceSingleCorrectNode, }); createNode({ question_node_multiple_single: questionSingleNode, }); + // addPortal({ + // nodeView: MultipleChoiceSingleCorrectContainerNodeView, + // component: QuestionComponent, + // context: this.app, + // }); + addPortal({ nodeView: QuestionMultipleSingleNodeView, component: QuestionComponent, diff --git a/wax-prosemirror-services/src/MultipleChoiceQuestionService/TrueFalseQuestionService/TrueFalseContainerNodeView.js b/wax-prosemirror-services/src/MultipleChoiceQuestionService/TrueFalseQuestionService/TrueFalseContainerNodeView.js new file mode 100644 index 0000000000000000000000000000000000000000..f5f145d389e4e56f03b4df42fa506a37c799c23a --- /dev/null +++ b/wax-prosemirror-services/src/MultipleChoiceQuestionService/TrueFalseQuestionService/TrueFalseContainerNodeView.js @@ -0,0 +1,55 @@ +import AbstractNodeView from '../../PortalService/AbstractNodeView'; + +export default class TrueFalseContainerNodeView extends AbstractNodeView { + constructor( + node, + view, + getPos, + decorations, + createPortal, + Component, + context, + ) { + super(node, view, getPos, decorations, createPortal, Component, context); + + this.node = node; + this.outerView = view; + this.getPos = getPos; + this.context = context; + } + + static name() { + return 'true_false_container'; + } + + update(node) { + this.node = node; + if (this.context.view[node.attrs.id]) { + const { state } = this.context.view[node.attrs.id]; + const start = node.content.findDiffStart(state.doc.content); + if (start != null) { + let { a: endA, b: endB } = node.content.findDiffEnd(state.doc.content); + const overlap = start - Math.min(endA, endB); + if (overlap > 0) { + endA += overlap; + endB += overlap; + } + this.context.view[node.attrs.id].dispatch( + state.tr + .replace(start, endB, node.slice(start, endA)) + .setMeta('fromOutside', true), + ); + } + } + + return true; + } + + stopEvent(event) { + if (event.target.type === 'text') { + return true; + } + const innerView = this.context.view[this.node.attrs.id]; + return innerView && innerView.dom.contains(event.target); + } +} diff --git a/wax-prosemirror-services/src/MultipleChoiceQuestionService/TrueFalseQuestionService/TrueFalseQuestionService.js b/wax-prosemirror-services/src/MultipleChoiceQuestionService/TrueFalseQuestionService/TrueFalseQuestionService.js index 1ee73119c67208d7aeb3d15d0d01cc7086cc42fd..91aa037e71bdd6600fa05bc613e10d0906293e13 100644 --- a/wax-prosemirror-services/src/MultipleChoiceQuestionService/TrueFalseQuestionService/TrueFalseQuestionService.js +++ b/wax-prosemirror-services/src/MultipleChoiceQuestionService/TrueFalseQuestionService/TrueFalseQuestionService.js @@ -4,6 +4,7 @@ import trueFalseNode from './schema/trueFalseNode'; import questionTrueFalseNode from './schema/questionTrueFalseNode'; import trueFalseContainerNode from './schema/trueFalseContainerNode'; import AnswerComponent from './components/AnswerComponent'; +import TrueFalseContainerNodeView from './TrueFalseContainerNodeView'; import TrueFalseNodeView from './TrueFalseNodeView'; import QuestionTrueFalseNodeView from './QuestionTrueFalseNodeView'; import QuestionComponent from '../components/QuestionComponent'; @@ -26,6 +27,12 @@ class TrueFalseQuestionService extends Service { question_node_true_false: questionTrueFalseNode, }); + // addPortal({ + // nodeView: TrueFalseContainerNodeView, + // component: QuestionComponent, + // context: this.app, + // }); + addPortal({ nodeView: QuestionTrueFalseNodeView, component: QuestionComponent, diff --git a/wax-prosemirror-services/src/MultipleChoiceQuestionService/TrueFalseSingleCorrectQuestionService/TrueFalseSingleCorrectContainerNodeView.js b/wax-prosemirror-services/src/MultipleChoiceQuestionService/TrueFalseSingleCorrectQuestionService/TrueFalseSingleCorrectContainerNodeView.js new file mode 100644 index 0000000000000000000000000000000000000000..d8a8ed1c179151f15a6c1da18c459499eced5555 --- /dev/null +++ b/wax-prosemirror-services/src/MultipleChoiceQuestionService/TrueFalseSingleCorrectQuestionService/TrueFalseSingleCorrectContainerNodeView.js @@ -0,0 +1,55 @@ +import AbstractNodeView from '../../PortalService/AbstractNodeView'; + +export default class TrueFalseSingleCorrectContainerNodeView extends AbstractNodeView { + constructor( + node, + view, + getPos, + decorations, + createPortal, + Component, + context, + ) { + super(node, view, getPos, decorations, createPortal, Component, context); + + this.node = node; + this.outerView = view; + this.getPos = getPos; + this.context = context; + } + + static name() { + return 'true_false_single_correct_container'; + } + + update(node) { + this.node = node; + if (this.context.view[node.attrs.id]) { + const { state } = this.context.view[node.attrs.id]; + const start = node.content.findDiffStart(state.doc.content); + if (start != null) { + let { a: endA, b: endB } = node.content.findDiffEnd(state.doc.content); + const overlap = start - Math.min(endA, endB); + if (overlap > 0) { + endA += overlap; + endB += overlap; + } + this.context.view[node.attrs.id].dispatch( + state.tr + .replace(start, endB, node.slice(start, endA)) + .setMeta('fromOutside', true), + ); + } + } + + return true; + } + + stopEvent(event) { + if (event.target.type === 'text') { + return true; + } + const innerView = this.context.view[this.node.attrs.id]; + return innerView && innerView.dom.contains(event.target); + } +} diff --git a/wax-prosemirror-services/src/MultipleChoiceQuestionService/TrueFalseSingleCorrectQuestionService/TrueFalseSingleCorrectQuestionService.js b/wax-prosemirror-services/src/MultipleChoiceQuestionService/TrueFalseSingleCorrectQuestionService/TrueFalseSingleCorrectQuestionService.js index 27d1710560a54e7bf45ae60e3685ef84e1c04c7b..4f38a73f3d2c48f1075e8f75360bd8737dc994d4 100644 --- a/wax-prosemirror-services/src/MultipleChoiceQuestionService/TrueFalseSingleCorrectQuestionService/TrueFalseSingleCorrectQuestionService.js +++ b/wax-prosemirror-services/src/MultipleChoiceQuestionService/TrueFalseSingleCorrectQuestionService/TrueFalseSingleCorrectQuestionService.js @@ -4,6 +4,7 @@ import trueFalseSingleCorrectNode from './schema/trueFalseSingleCorrectNode'; import trueFalseSingleCorrectContainerNode from './schema/trueFalseSingleCorrectContainerNode'; import questionTrueFalseSingleNode from './schema/questionTrueFalseSingleNode'; import AnswerComponent from './components/AnswerComponent'; +import TrueFalseSingleCorrectContainerNodeView from './TrueFalseSingleCorrectContainerNodeView'; import TrueFalseSingleCorrectNodeView from './TrueFalseSingleCorrectNodeView'; import QuestionTrueFalseSingleNodeView from './QuestionTrueFalseSingleNodeView'; import QuestionComponent from '../components/QuestionComponent'; @@ -17,17 +18,23 @@ class TrueFalseSingleCorrectQuestionService extends Service { const addPortal = this.container.get('AddPortal'); createNode({ - true_false_single_correct: trueFalseSingleCorrectNode, + true_false_single_correct_container: trueFalseSingleCorrectContainerNode, }); createNode({ - true_false_single_correct_container: trueFalseSingleCorrectContainerNode, + question_node_true_false_single: questionTrueFalseSingleNode, }); createNode({ - question_node_true_false_single: questionTrueFalseSingleNode, + true_false_single_correct: trueFalseSingleCorrectNode, }); + // addPortal({ + // nodeView: TrueFalseSingleCorrectContainerNodeView, + // component: QuestionComponent, + // context: this.app, + // }); + addPortal({ nodeView: QuestionTrueFalseSingleNodeView, component: QuestionComponent,