diff --git a/wax-questions-service/src/MultipleChoiceQuestionService/MultipleChoiceSingleCorrectQuestionService/components/AnswerComponent.js b/wax-questions-service/src/MultipleChoiceQuestionService/MultipleChoiceSingleCorrectQuestionService/components/AnswerComponent.js index 5108d752fb49020ad4ce4f7b10c125414a80d6a6..fddfcd316177624c54df76b93ceaa0a20f0da98d 100644 --- a/wax-questions-service/src/MultipleChoiceQuestionService/MultipleChoiceSingleCorrectQuestionService/components/AnswerComponent.js +++ b/wax-questions-service/src/MultipleChoiceQuestionService/MultipleChoiceSingleCorrectQuestionService/components/AnswerComponent.js @@ -5,7 +5,7 @@ import { WaxContext, DocumentHelpers, Icon } from 'wax-prosemirror-core'; import { Fragment } from 'prosemirror-model'; import { v4 as uuidv4 } from 'uuid'; import helpers from '../../helpers/helpers'; -import EditorAnswerComponent from '../../components/EditorAnswerComponent'; +import EditorComponent from '../../components/EditorComponent'; import FeedbackComponent from '../../components/FeedbackComponent'; import SwitchComponent from './SwitchComponent'; @@ -64,6 +64,15 @@ const QuestionData = styled.div` align-items: normal; display: flex; flex-direction: row; + .ProseMirror { + :empty::before { + content: 'Type your answer'; + color: #aaa; + float: left; + font-style: italic; + pointer-events: none; + } + } `; const ActionButton = styled.button` @@ -226,7 +235,12 @@ export default ({ node, view, getPos }) => { </InfoRow> <QuestionWrapper> <QuestionData> - <EditorAnswerComponent getPos={getPos} node={node} view={view} /> + <EditorComponent + getPos={getPos} + node={node} + placeholderText="Type your answer" + view={view} + /> </QuestionData> {!testMode && !(readOnly && feedback === '') && ( <FeedbackComponent diff --git a/wax-questions-service/src/MultipleChoiceQuestionService/TrueFalseQuestionService/components/AnswerComponent.js b/wax-questions-service/src/MultipleChoiceQuestionService/TrueFalseQuestionService/components/AnswerComponent.js index c2e6c35f048071b6ab0febbbdf52173beba78ed0..bb1944d7cb3c3b736129eb530c8c067a82300d16 100644 --- a/wax-questions-service/src/MultipleChoiceQuestionService/TrueFalseQuestionService/components/AnswerComponent.js +++ b/wax-questions-service/src/MultipleChoiceQuestionService/TrueFalseQuestionService/components/AnswerComponent.js @@ -6,7 +6,7 @@ import { Fragment } from 'prosemirror-model'; import { v4 as uuidv4 } from 'uuid'; import helpers from '../../helpers/helpers'; import FeedbackComponent from '../../components/FeedbackComponent'; -import EditorAnswerComponent from '../../components/EditorAnswerComponent'; +import EditorComponent from '../../components/EditorComponent'; import SwitchComponent from './SwitchComponent'; const Wrapper = styled.div` @@ -64,6 +64,15 @@ const QuestionData = styled.div` align-items: normal; display: flex; flex-direction: row; + .ProseMirror { + :empty::before { + content: 'Type your answer'; + color: #aaa; + float: left; + font-style: italic; + pointer-events: none; + } + } `; const ActionButton = styled.button` @@ -226,7 +235,12 @@ export default ({ node, view, getPos }) => { </InfoRow> <QuestionWrapper> <QuestionData> - <EditorAnswerComponent getPos={getPos} node={node} view={view} /> + <EditorComponent + getPos={getPos} + node={node} + placeholderText="Type your answer" + view={view} + /> </QuestionData> {!testMode && !(readOnly && feedback === '') && ( <FeedbackComponent diff --git a/wax-questions-service/src/MultipleChoiceQuestionService/TrueFalseSingleCorrectQuestionService/components/AnswerComponent.js b/wax-questions-service/src/MultipleChoiceQuestionService/TrueFalseSingleCorrectQuestionService/components/AnswerComponent.js index bf4fec586349720e9744eba016e66d98c459928e..e478656ee6452ccbb37e412783f6a5eb698c48c4 100644 --- a/wax-questions-service/src/MultipleChoiceQuestionService/TrueFalseSingleCorrectQuestionService/components/AnswerComponent.js +++ b/wax-questions-service/src/MultipleChoiceQuestionService/TrueFalseSingleCorrectQuestionService/components/AnswerComponent.js @@ -5,7 +5,7 @@ import { WaxContext, DocumentHelpers, Icon } from 'wax-prosemirror-core'; import { Fragment } from 'prosemirror-model'; import { v4 as uuidv4 } from 'uuid'; import helpers from '../../helpers/helpers'; -import EditorAnswerComponent from '../../components/EditorAnswerComponent'; +import EditorComponent from '../../components/EditorComponent'; import FeedbackComponent from '../../components/FeedbackComponent'; import SwitchComponent from './SwitchComponent'; @@ -64,6 +64,15 @@ const QuestionData = styled.div` align-items: normal; display: flex; flex-direction: row; + .ProseMirror { + :empty::before { + content: 'Type your answer'; + color: #aaa; + float: left; + font-style: italic; + pointer-events: none; + } + } `; const ActionButton = styled.button` @@ -226,7 +235,12 @@ export default ({ node, view, getPos }) => { </InfoRow> <QuestionWrapper> <QuestionData> - <EditorAnswerComponent getPos={getPos} node={node} view={view} /> + <EditorComponent + getPos={getPos} + node={node} + placeholderText="Type your answer" + view={view} + /> </QuestionData> {!testMode && !(readOnly && feedback === '') && ( <FeedbackComponent diff --git a/wax-questions-service/src/MultipleChoiceQuestionService/components/AnswerComponent.js b/wax-questions-service/src/MultipleChoiceQuestionService/components/AnswerComponent.js index a8beee3cdf422f646f509bb90a882b6f73847758..c8c6fc818c9d2df17e3c4ac3a0d8274cdbcb32b8 100644 --- a/wax-questions-service/src/MultipleChoiceQuestionService/components/AnswerComponent.js +++ b/wax-questions-service/src/MultipleChoiceQuestionService/components/AnswerComponent.js @@ -4,7 +4,7 @@ import { TextSelection, NodeSelection } from 'prosemirror-state'; import { WaxContext, DocumentHelpers, Icon } from 'wax-prosemirror-core'; import { Fragment } from 'prosemirror-model'; import { v4 as uuidv4 } from 'uuid'; -import EditorAnswerComponent from './EditorAnswerComponent'; +import EditorComponent from './EditorComponent'; import SwitchComponent from './SwitchComponent'; import FeedbackComponent from './FeedbackComponent'; import helpers from '../helpers/helpers'; @@ -64,6 +64,15 @@ const QuestionData = styled.div` align-items: normal; display: flex; flex-direction: row; + .ProseMirror { + :empty::before { + content: 'Type your answer'; + color: #aaa; + float: left; + font-style: italic; + pointer-events: none; + } + } `; const ActionButton = styled.button` @@ -224,7 +233,12 @@ export default ({ node, view, getPos }) => { </InfoRow> <QuestionWrapper> <QuestionData> - <EditorAnswerComponent getPos={getPos} node={node} view={view} /> + <EditorComponent + getPos={getPos} + node={node} + placeholderText="type your answer" + view={view} + /> </QuestionData> {!testMode && !(readOnly && feedback === '') && ( <FeedbackComponent diff --git a/wax-questions-service/src/MultipleChoiceQuestionService/components/EditorAnswerComponent.js b/wax-questions-service/src/MultipleChoiceQuestionService/components/EditorAnswerComponent.js deleted file mode 100644 index 8d43e90ec531a42d7ef2354167bceea4a41d921c..0000000000000000000000000000000000000000 --- a/wax-questions-service/src/MultipleChoiceQuestionService/components/EditorAnswerComponent.js +++ /dev/null @@ -1,228 +0,0 @@ -import React, { useContext, useRef, useEffect } from 'react'; -import styled from 'styled-components'; -import { EditorView } from 'prosemirror-view'; -import { EditorState, TextSelection, NodeSelection } from 'prosemirror-state'; -import { StepMap } from 'prosemirror-transform'; -import { keymap } from 'prosemirror-keymap'; -import { baseKeymap, chainCommands } from 'prosemirror-commands'; -import { undo, redo } from 'prosemirror-history'; -import { WaxContext, ComponentPlugin } from 'wax-prosemirror-core'; -import { - splitListItem, - liftListItem, - sinkListItem, -} from 'prosemirror-schema-list'; -import Placeholder from '../plugins/placeholder'; -import FakeCursorPlugin from '../../MultipleDropDownService/plugins/FakeCursorPlugin'; - -const EditorWrapper = styled.div` - border: none; - display: flex; - flex: 2 1 auto; - justify-content: left; - - .ProseMirror { - white-space: break-spaces; - width: 100%; - word-wrap: break-word; - - &:focus { - outline: none; - } - - :empty::before { - content: 'Type your answer'; - color: #aaa; - float: left; - font-style: italic; - pointer-events: none; - } - - p:first-child { - margin: 0; - } - - p.empty-node:first-child::before { - content: attr(data-content); - } - - .empty-node::before { - color: rgb(170, 170, 170); - float: left; - font-style: italic; - height: 0px; - pointer-events: none; - } - } -`; - -let WaxOverlays = () => true; - -const EditorAnswerComponent = ({ node, view, getPos }) => { - const editorRef = useRef(); - - const context = useContext(WaxContext); - const { - app, - pmViews: { main }, - } = context; - let answerView; - const questionId = node.attrs.id; - const isEditable = main.props.editable(editable => { - return editable; - }); - - let finalPlugins = [FakeCursorPlugin()]; - - const createKeyBindings = () => { - const keys = getKeys(); - Object.keys(baseKeymap).forEach(key => { - if (keys[key]) { - keys[key] = chainCommands(keys[key], baseKeymap[key]); - } else { - keys[key] = baseKeymap[key]; - } - }); - return keys; - }; - - const pressEnter = (state, dispatch) => { - if (state.selection.node && state.selection.node.type.name === 'image') { - const { $from, to } = state.selection; - - const same = $from.sharedDepth(to); - - const pos = $from.before(same); - dispatch(state.tr.setSelection(NodeSelection.create(state.doc, pos))); - return true; - } - // LISTS - if (splitListItem(state.schema.nodes.list_item)(state)) { - splitListItem(state.schema.nodes.list_item)(state, dispatch); - return true; - } - - return false; - }; - - const getKeys = () => { - return { - 'Mod-z': () => undo(view.state, view.dispatch), - 'Mod-y': () => redo(view.state, view.dispatch), - 'Mod-[': liftListItem(view.state.schema.nodes.list_item), - 'Mod-]': sinkListItem(view.state.schema.nodes.list_item), - // Enter: () => - // splitListItem(answerView.state.schema.nodes.list_item)( - // answerView.state, - // answerView.dispatch, - // ), - Enter: pressEnter, - }; - }; - - const plugins = [keymap(createKeyBindings()), ...app.getPlugins()]; - - const createPlaceholder = placeholder => { - return Placeholder({ - content: placeholder, - }); - }; - - finalPlugins = finalPlugins.concat([ - createPlaceholder('Type your answer'), - ...plugins, - ]); - - useEffect(() => { - WaxOverlays = ComponentPlugin('waxOverlays'); - answerView = new EditorView( - { - mount: editorRef.current, - }, - { - editable: () => isEditable, - state: EditorState.create({ - doc: node, - plugins: finalPlugins, - }), - dispatchTransaction, - disallowedTools: ['MultipleChoice'], - handleDOMEvents: { - mousedown: () => { - context.updateView({}, questionId); - main.dispatch( - main.state.tr - .setMeta('outsideView', questionId) - .setSelection( - new TextSelection( - main.state.tr.doc.resolve( - getPos() + - 1 + - context.pmViews[questionId].state.selection.to, - ), - ), - ), - ); - // context.pmViews[activeViewId].dispatch( - // context.pmViews[activeViewId].state.tr.setSelection( - // TextSelection.between( - // context.pmViews[activeViewId].state.selection.$anchor, - // context.pmViews[activeViewId].state.selection.$head, - // ), - // ), - // ); - - context.updateView({}, questionId); - - if (answerView.hasFocus()) answerView.focus(); - }, - blur: (editorView, event) => { - if (answerView && event.relatedTarget === null) { - answerView.focus(); - } - }, - }, - - attributes: { - spellcheck: 'false', - }, - }, - ); - - // Set Each note into Wax's Context - context.updateView( - { - [questionId]: answerView, - }, - questionId, - ); - if (answerView.hasFocus()) answerView.focus(); - }, []); - - const dispatchTransaction = tr => { - const { state, transactions } = answerView.state.applyTransaction(tr); - answerView.updateState(state); - context.updateView({}, questionId); - - if (!tr.getMeta('fromOutside')) { - const outerTr = view.state.tr; - const offsetMap = StepMap.offset(getPos() + 1); - for (let i = 0; i < transactions.length; i++) { - const { steps } = transactions[i]; - for (let j = 0; j < steps.length; j++) - outerTr.step(steps[j].map(offsetMap)); - } - if (outerTr.docChanged) - view.dispatch(outerTr.setMeta('outsideView', questionId)); - } - }; - - return ( - <EditorWrapper> - <div ref={editorRef} /> - <WaxOverlays activeViewId={questionId} /> - </EditorWrapper> - ); -}; - -export default EditorAnswerComponent; diff --git a/wax-questions-service/src/MultipleChoiceQuestionService/components/EditorComponent.js b/wax-questions-service/src/MultipleChoiceQuestionService/components/EditorComponent.js index 4fef337a14e9e75e64af6f75262c864634faab03..6ddb82cee023359d451fa31d76cbed605e7f8d9d 100644 --- a/wax-questions-service/src/MultipleChoiceQuestionService/components/EditorComponent.js +++ b/wax-questions-service/src/MultipleChoiceQuestionService/components/EditorComponent.js @@ -1,3 +1,4 @@ +/* eslint-disable react/prop-types */ import React, { useContext, useRef, useEffect } from 'react'; import styled from 'styled-components'; import { EditorView } from 'prosemirror-view'; @@ -58,7 +59,12 @@ const EditorWrapper = styled.div` let WaxOverlays = () => true; -const QuestionEditorComponent = ({ node, view, getPos }) => { +const QuestionEditorComponent = ({ + node, + view, + getPos, + placeholderText = 'Type your question', +}) => { const editorRef = useRef(); const context = useContext(WaxContext); @@ -129,7 +135,7 @@ const QuestionEditorComponent = ({ node, view, getPos }) => { }; finalPlugins = finalPlugins.concat([ - createPlaceholder('Type your question'), + createPlaceholder(placeholderText), ...plugins, ]);