diff --git a/editors/demo/src/Editoria/Editoria.js b/editors/demo/src/Editoria/Editoria.js index 5bd37509506da0181ca5f925a63c31f503c8a0ce..4293bf1a13cb9cb8ab75698003fed441428a1def 100644 --- a/editors/demo/src/Editoria/Editoria.js +++ b/editors/demo/src/Editoria/Editoria.js @@ -43,10 +43,6 @@ const Editoria = () => { const EditoriaComponent = useMemo( () => ( <> - <button onClick={() => console.log(editorRef.current.getContent())}> - Click - </button> - <Wax ref={editorRef} key={key} @@ -60,7 +56,6 @@ const Editoria = () => { // onChange={debounce(source => { // console.log(JSON.stringify(source)); // }, 200)} - // onBlur={source => console.log(source)} user={user} /> </> diff --git a/editors/demo/src/HHMI/HHMI.js b/editors/demo/src/HHMI/HHMI.js index bbd32b6ea531849610d820521da41394e34d5470..a9a1f565a5a0f238a17a178b2bd1b2ad63c07964 100644 --- a/editors/demo/src/HHMI/HHMI.js +++ b/editors/demo/src/HHMI/HHMI.js @@ -15,7 +15,7 @@ const renderImage = file => { }); }; -const t = `<p class="paragraph">Based on the equation below</p><math-display class="math-node">x + y = 5</math-display><p class="paragraph">Which ones are correct?</p><p class="paragraph"></p><div id="" class="multiple-choice"><div class="multiple-choice-option" id="d7b65415-ff82-446f-afa4-accaa3837f4a" correct="false" feedback=""><p class="paragraph">answer 1</p><p class="paragraph"><math-inline class="math-node">x+y=1</math-inline></p></div><div class="multiple-choice-option" id="e7d6bb2f-7cd7-44f1-92a0-281e72157538" correct="true" feedback=""><p class="paragraph">answer 2</p></div><div class="multiple-choice-option" id="d6fc749f-afae-4203-9562-d68c380a86e5" correct="false" feedback=""><p class="paragraph">answer 3</p></div></div><div id="" class="fill-the-gap"><p class="paragraph">A <span id="bfd4376c-4424-455e-9187-f53282fa1024" class="fill-the-gap">DNA</span> molecule is very long and usually consists of hundreds or thousands of genes.</p><p class="paragraph">An electron having a certain discrete amount of <span id="14dedf44-728f-4384-835f-e3af82b25623" class="fill-the-gap">energy</span> is something like a ball on a staircase.</p></div><p class="paragraph"></p>`; +const t = `<p class="paragraph">Based on the equation below</p><math-display class="math-node">x + y = 5</math-display><p class="paragraph">Which ones are correct?</p><p class="paragraph"></p><div id="" class="multiple-choice"><div class="multiple-choice-option" id="d7b65415-ff82-446f-afa4-accaa3837f4a" correct="false" feedback=""><p class="paragraph">answer 1</p><p class="paragraph"><math-inline class="math-node">x+y=1</math-inline></p></div><div class="multiple-choice-option" id="e7d6bb2f-7cd7-44f1-92a0-281e72157538" correct="true" feedback=""><p class="paragraph">answer 2</p></div><div class="multiple-choice-option" id="d6fc749f-afae-4203-9562-d68c380a86e5" correct="false" feedback="1111111"><p class="paragraph">answer 3</p></div></div><div id="" class="fill-the-gap"><p class="paragraph">A <span id="bfd4376c-4424-455e-9187-f53282fa1024" class="fill-the-gap">DNA</span> molecule is very long and usually consists of hundreds or thousands of genes.</p><p class="paragraph">An electron having a certain discrete amount of <span id="14dedf44-728f-4384-835f-e3af82b25623" class="fill-the-gap">energy</span> is something like a ball on a staircase.</p></div><p class="paragraph"></p>`; const Hhmi = () => { return ( diff --git a/wax-prosemirror-core/src/PmPlugins.js b/wax-prosemirror-core/src/PmPlugins.js index ac5b5bf562166fbbaca25ff0f027732a8385761a..98ccb800cea1583e0b1d9224acec04d70b8a9389 100644 --- a/wax-prosemirror-core/src/PmPlugins.js +++ b/wax-prosemirror-core/src/PmPlugins.js @@ -1,4 +1,4 @@ -import { injectable } from "inversify"; +import { injectable } from 'inversify'; @injectable() export default class PmPlugins { _plugins = new Map(); diff --git a/wax-prosemirror-core/src/WaxView.js b/wax-prosemirror-core/src/WaxView.js index f169ee5d9dd59ea292b6f1b2f7493d92f5e765e0..0ad8492495012ad46d505a6c9f69913862b90ef0 100644 --- a/wax-prosemirror-core/src/WaxView.js +++ b/wax-prosemirror-core/src/WaxView.js @@ -15,7 +15,6 @@ import { EditorView } from 'prosemirror-view'; import { trackedTransaction } from 'wax-prosemirror-services'; import { WaxContext } from './WaxContext'; import { PortalContext } from './PortalContext'; -import transformPasted from './helpers/TransformPasted'; import ComponentPlugin from './ComponentPlugin'; import WaxOptions from './WaxOptions'; import getDocContent from './helpers/GetDocContent'; @@ -75,9 +74,6 @@ const WaxView = forwardRef((props, ref) => { user, scrollMargin: 200, scrollThreshold: 200, - transformPasted: slice => { - return transformPasted(slice, view); - }, attributes: { spellcheck: browserSpellCheck ? 'true' : 'false', }, diff --git a/wax-prosemirror-core/src/helpers/TransformPasted.js b/wax-prosemirror-core/src/helpers/TransformPasted.js deleted file mode 100644 index 9a4ce541f0ae0911fedf9761b523e70031fa4dee..0000000000000000000000000000000000000000 --- a/wax-prosemirror-core/src/helpers/TransformPasted.js +++ /dev/null @@ -1,61 +0,0 @@ -/* eslint-disable array-callback-return */ -/* eslint-disable no-param-reassign */ -import { forEach, each } from 'lodash'; -import { v4 as uuidv4 } from 'uuid'; -import { DocumentHelpers } from 'wax-prosemirror-utilities'; - -const transformPasted = (slice, view) => { - const { content } = slice; - if (view.state.schema.marks.comment) { - const commentNodes = DocumentHelpers.findChildrenByMark( - content, - view.state.schema.marks.comment, - true, - ); - - const allComments = []; - - commentNodes.map(node => { - node.node.marks.map(comment => { - if (comment.type.name === 'comment') { - allComments.push(comment); - } - }); - }); - - const groupedCommentsById = allComments.reduce((obj, mark) => { - obj[mark.attrs.id] = [...(obj[mark.attrs.id] || []), mark]; - return obj; - }, {}); - - forEach(Object.keys(groupedCommentsById), key => { - const id = uuidv4(); - forEach(groupedCommentsById[key], comment => { - comment.attrs.id = id; - }); - }); - } - - const schemaNotes = []; - each(view.state.schema.nodes, node => { - if (node.groups.includes('notes')) schemaNotes.push(node); - }); - - if (schemaNotes.length > 0) { - schemaNotes.forEach(schemaNote => { - const notes = DocumentHelpers.findChildrenByType( - content, - view.state.schema.nodes[schemaNote.name], - true, - ); - - notes.forEach(note => { - note.node.attrs.id = uuidv4(); - }); - }); - } - - return slice; -}; - -export default transformPasted; diff --git a/wax-prosemirror-plugins/index.js b/wax-prosemirror-plugins/index.js index d0a198c76de0f10be29733fa77a2c6d8f9dbafa5..431000b44c6b2e7eae3a322bb6a4feb280e178bc 100644 --- a/wax-prosemirror-plugins/index.js +++ b/wax-prosemirror-plugins/index.js @@ -2,6 +2,8 @@ export { default as TrackChangePlugin } from './src/trackChanges/TrackChangePlug export { default as HideShowPlugin } from './src/trackChanges/HideShowPlugin'; export { default as CommentPlugin } from './src/comments/CommentPlugin'; +export { default as CopyPasteCommentPlugin } from './src/comments/CopyPasteCommentPlugin'; + export { default as WaxSelectionPlugin } from './src/WaxSelectionPlugin'; export { default as highlightPlugin } from './src/highlightPlugin'; diff --git a/wax-prosemirror-plugins/src/comments/CopyPasteCommentPlugin.js b/wax-prosemirror-plugins/src/comments/CopyPasteCommentPlugin.js new file mode 100644 index 0000000000000000000000000000000000000000..d246d34ab19b3f877f41b3a93e9614de97c1c81c --- /dev/null +++ b/wax-prosemirror-plugins/src/comments/CopyPasteCommentPlugin.js @@ -0,0 +1,67 @@ +/* eslint-disable no-param-reassign */ +import { forEach, each } from 'lodash'; +import { v4 as uuidv4 } from 'uuid'; +import { Plugin, PluginKey } from 'prosemirror-state'; +import { DocumentHelpers } from 'wax-prosemirror-utilities'; + +const copyPasteCommentPugin = new PluginKey('copyPasteCommentPugin'); + +export default (props, context) => { + return new Plugin({ + key: copyPasteCommentPugin, + props: { + transformPasted: slice => { + const { activeView } = context.app.context; + const { content } = slice; + const commentNodes = DocumentHelpers.findChildrenByMark( + content, + activeView.state.schema.marks.comment, + true, + ); + + const allComments = []; + + commentNodes.map(node => { + node.node.marks.map(comment => { + if (comment.type.name === 'comment') { + allComments.push(comment); + } + }); + }); + + const groupedCommentsById = allComments.reduce((obj, mark) => { + obj[mark.attrs.id] = [...(obj[mark.attrs.id] || []), mark]; + return obj; + }, {}); + + forEach(Object.keys(groupedCommentsById), key => { + const id = uuidv4(); + forEach(groupedCommentsById[key], comment => { + comment.attrs.id = id; + }); + }); + + const schemaNotes = []; + each(activeView.state.schema.nodes, node => { + if (node.groups.includes('notes')) schemaNotes.push(node); + }); + + if (schemaNotes.length > 0) { + schemaNotes.forEach(schemaNote => { + const notes = DocumentHelpers.findChildrenByType( + content, + activeView.state.schema.nodes[schemaNote.name], + true, + ); + + notes.forEach(note => { + note.node.attrs.id = uuidv4(); + }); + }); + } + + return slice; + }, + }, + }); +}; diff --git a/wax-prosemirror-services/src/CommentsService/CommentsService.js b/wax-prosemirror-services/src/CommentsService/CommentsService.js index 6a2b16d5fb00baf2375f96333b61ad76a8ebef10..11e5ca070e2d2c7fdb2eabea02fb7a6ce26ef3ed 100644 --- a/wax-prosemirror-services/src/CommentsService/CommentsService.js +++ b/wax-prosemirror-services/src/CommentsService/CommentsService.js @@ -1,6 +1,6 @@ import { commentMark } from 'wax-prosemirror-schema'; import { RightArea, CommentBubbleComponent } from 'wax-prosemirror-components'; -import { CommentPlugin } from 'wax-prosemirror-plugins'; +import { CommentPlugin, CopyPasteCommentPlugin } from 'wax-prosemirror-plugins'; import Service from '../Service'; const PLUGIN_KEY = 'commentPlugin'; @@ -8,6 +8,10 @@ const PLUGIN_KEY = 'commentPlugin'; export default class CommentsService extends Service { boot() { this.app.PmPlugins.add(PLUGIN_KEY, CommentPlugin(PLUGIN_KEY)); + this.app.PmPlugins.add( + 'copyPasteCommentPlugin', + CopyPasteCommentPlugin('copyPasteCommentPlugin', this.app.context), + ); const createOverlay = this.container.get('CreateOverlay'); const layout = this.container.get('Layout'); createOverlay( diff --git a/wax-prosemirror-services/src/MultipleChoiceQuestionService/components/FeedbackComponent.js b/wax-prosemirror-services/src/MultipleChoiceQuestionService/components/FeedbackComponent.js index bc33af7b13d8371e270c2afe4666313a77874ac1..0fa7d157c701c499a128e98776835af53f5db5b7 100644 --- a/wax-prosemirror-services/src/MultipleChoiceQuestionService/components/FeedbackComponent.js +++ b/wax-prosemirror-services/src/MultipleChoiceQuestionService/components/FeedbackComponent.js @@ -26,23 +26,24 @@ export default ({ node, view, getPos }) => { const context = useContext(WaxContext); const [feedBack, setFeedBack] = useState(''); const [isFirstRun, setFirstRun] = useState(true); + const [typing, setTyping] = useState(false); const feedBackRef = useRef(null); useEffect(() => { const allNodes = getNodes(context.view.main); allNodes.forEach(singNode => { if (singNode.node.attrs.id === node.attrs.id) { + if (!typing) setFeedBack(singNode.node.attrs.feedback); if (!isFirstRun) { if (singNode.node.attrs.feedback === '') setFeedBack(singNode.node.attrs.feedback); } - if (singNode.node.attrs.feedback !== '') - setFeedBack(singNode.node.attrs.feedback); } }); }, [getNodes(context.view.main)]); const handleKeyDown = e => { + setTyping(true); if (e.key === 'Backspace') { context.view.main.dispatch( context.view.main.state.tr.setSelection( diff --git a/wax-prosemirror-services/src/NoteService/Editor.js b/wax-prosemirror-services/src/NoteService/Editor.js index 5fffc0b55429113ffec7eccaa53bc2b66047c905..30d736d6ea2c535bb715318b0539c37ee65379fd 100644 --- a/wax-prosemirror-services/src/NoteService/Editor.js +++ b/wax-prosemirror-services/src/NoteService/Editor.js @@ -11,7 +11,6 @@ import { undo, redo } from 'prosemirror-history'; import { WaxContext } from 'wax-prosemirror-core'; import { NoteEditorContainer } from 'wax-prosemirror-components'; import { DocumentHelpers } from 'wax-prosemirror-utilities'; -import transformPasted from './helpers/TransformPasted'; import trackedTransaction from '../TrackChangeService/track-changes/trackedTransaction'; export default ({ node, view }) => { @@ -63,9 +62,6 @@ export default ({ node, view }) => { handleTextInput: (editorView, from, to, text) => { typing = true; }, - transformPasted: slice => { - return transformPasted(slice, noteView); - }, attributes: { spellcheck: 'false', diff --git a/wax-prosemirror-services/src/NoteService/NoteService.js b/wax-prosemirror-services/src/NoteService/NoteService.js index db23620a2423b480b442f1754af90d763d738829..c27dc354296ba55a8332c5f1d7acb6401f91d3da 100644 --- a/wax-prosemirror-services/src/NoteService/NoteService.js +++ b/wax-prosemirror-services/src/NoteService/NoteService.js @@ -1,6 +1,6 @@ -import Service from '../Service'; import { footNoteNode } from 'wax-prosemirror-schema'; import { CommentBubbleComponent } from 'wax-prosemirror-components'; +import Service from '../Service'; import Note from './Note'; import NoteComponent from './NoteComponent'; diff --git a/wax-prosemirror-services/src/NoteService/helpers/TransformPasted.js b/wax-prosemirror-services/src/NoteService/helpers/TransformPasted.js deleted file mode 100644 index 353c11a4bae400864330f4abc9726fbc81dc5a85..0000000000000000000000000000000000000000 --- a/wax-prosemirror-services/src/NoteService/helpers/TransformPasted.js +++ /dev/null @@ -1,38 +0,0 @@ -import { forEach } from "lodash"; -import { v4 as uuidv4 } from "uuid"; -import { DocumentHelpers } from "wax-prosemirror-utilities"; - -const transformPasted = (slice, view) => { - const { content } = slice; - const commentNodes = DocumentHelpers.findChildrenByMark( - content, - view.state.schema.marks.comment, - true - ); - - const allComments = []; - - commentNodes.map(node => { - node.node.marks.map(comment => { - if (comment.type.name === "comment") { - allComments.push(comment); - } - }); - }); - - let groupedCommentsById = allComments.reduce((obj, mark) => { - obj[mark.attrs.id] = [...(obj[mark.attrs.id] || []), mark]; - return obj; - }, {}); - - forEach(Object.keys(groupedCommentsById), key => { - let id = uuidv4(); - forEach(groupedCommentsById[key], comment => { - comment.attrs.id = id; - }); - }); - - return slice; -}; - -export default transformPasted;