diff --git a/editors/editoria/src/config/config.js b/editors/editoria/src/config/config.js index 6a29c0f794a50e5f6a3a00eb066093403b02ca58..294e15fb56eb986a343aa68f0edce98cc36626cf 100644 --- a/editors/editoria/src/config/config.js +++ b/editors/editoria/src/config/config.js @@ -72,11 +72,11 @@ export default { new TextToolGroupService(), new ListsService(), new LinkService(), + new InlineAnnotationsService(), new TrackChangeService(), new CommentsService(), new PlaceholderService(), new ImageService(), - new InlineAnnotationsService(), new TablesService(), new BaseService(), new BaseToolGroupService(), diff --git a/wax-prosemirror-components/src/components/comments/Comment.js b/wax-prosemirror-components/src/components/comments/Comment.js index e0b9f1205733c0608d4235014ca0774e1299046d..c1672acb275b845cdf09c5d3d1c6390dbb3d1b22 100644 --- a/wax-prosemirror-components/src/components/comments/Comment.js +++ b/wax-prosemirror-components/src/components/comments/Comment.js @@ -37,18 +37,21 @@ export default ({ comment, activeView, user }) => { const obj = { [user.username]: value }; commentAnnotation.attrs.conversation.push(obj); - const actualComment = DocumentHelpers.findMark(state, commentMark); - dispatch( - tr.addMark( - actualComment.from, - actualComment.to, - commentMark.create({ - ...((commentAnnotation && commentAnnotation.attrs) || {}), - conversation: commentAnnotation.attrs.conversation - }) - ) - ); + const allComments = DocumentHelpers.findAllCommentsWithSameId(state); + allComments.forEach(singleComment => { + dispatch( + tr.addMark( + singleComment.pos, + singleComment.pos + singleComment.nodeSize, + commentMark.create({ + ...((commentAnnotation && commentAnnotation.attrs) || {}), + conversation: commentAnnotation.attrs.conversation + }) + ) + ); + }); + setcommentInputValue(""); }; diff --git a/wax-prosemirror-components/src/components/comments/CommentBox.js b/wax-prosemirror-components/src/components/comments/CommentBox.js index 1f8d67f404a7f6d5dd8774eaf93ffeac5fe49b5a..436da90fe5144056613273bc7bcd0b7e18aa3554 100644 --- a/wax-prosemirror-components/src/components/comments/CommentBox.js +++ b/wax-prosemirror-components/src/components/comments/CommentBox.js @@ -40,8 +40,8 @@ export default ({ comment, view, top, dataBox }) => { ), [animate, setAnimate] = useState(false), { attrs: { id } } = comment, - activeCommentPlugin = app.PmPlugins.get("activeComment"), - activeComment = activeCommentPlugin.getState(activeView.state).comment; + commentPlugin = app.PmPlugins.get("commentPlugin"), + activeComment = commentPlugin.getState(activeView.state).comment; let active = false; if (activeComment && id === activeComment.attrs.id) active = true; diff --git a/wax-prosemirror-components/src/components/rightArea/RightArea.js b/wax-prosemirror-components/src/components/rightArea/RightArea.js index fe0fc66e1504872deb8251c24ebfc3d723a9d9a0..7c080201a3d49b6c1ba5cc640337df601433d44c 100644 --- a/wax-prosemirror-components/src/components/rightArea/RightArea.js +++ b/wax-prosemirror-components/src/components/rightArea/RightArea.js @@ -15,7 +15,7 @@ import { each, uniqBy, sortBy } from "lodash"; export default ({ area }) => { const { view: { main }, app, activeView } = useContext(WaxContext); - const activeCommentPlugin = app.PmPlugins.get("activeComment"); + const commentPlugin = app.PmPlugins.get("commentPlugin"); const [marksNodes, setMarksNodes] = useState([]); const [position, setPosition] = useState(); @@ -32,8 +32,7 @@ export default ({ area }) => { const id = markNode instanceof Mark ? markNode.attrs.id : markNode.node.attrs.id; - const activeComment = activeCommentPlugin.getState(activeView.state) - .comment; + const activeComment = commentPlugin.getState(activeView.state).comment; let isActive = false; if (activeComment && id === activeComment.attrs.id) isActive = true; diff --git a/wax-prosemirror-components/src/components/trackChanges/TrackChangeBox.js b/wax-prosemirror-components/src/components/trackChanges/TrackChangeBox.js index 84d2d9b35d656ddc35ddfbf123369c003b5e85a2..d2ec7235f617014fde5d83da1c61a40437f3c674 100644 --- a/wax-prosemirror-components/src/components/trackChanges/TrackChangeBox.js +++ b/wax-prosemirror-components/src/components/trackChanges/TrackChangeBox.js @@ -39,12 +39,8 @@ export default ({ trackChange, view, top, dataBox }) => { } else { action = `User demo changed paragraph to heading 1`; } - // const { attrs: { id } } = comment; - // const activeCommentPlugin = app.PmPlugins.get("activeComment"); - // const activeComment = activeCommentPlugin.getState(activeView.state).comment; let active = false; - // if (activeComment && id === activeComment.attrs.id) active = true; useEffect(() => { setAnimate(true); }, []); diff --git a/wax-prosemirror-plugins/index.js b/wax-prosemirror-plugins/index.js index aceed8d2f7e65b45b655590e393fd66f0b636c01..5377fcb7230b178788d69bf79f966224c53bd20c 100644 --- a/wax-prosemirror-plugins/index.js +++ b/wax-prosemirror-plugins/index.js @@ -2,5 +2,5 @@ export { default as TrackChangePlugin } from "./src/trackChanges/TrackChangePlugin"; -export { default as ActiveComment } from "./src/comments/ActiveComment"; +export { default as CommentPlugin } from "./src/comments/CommentPlugin"; export { default as WaxSelectionPlugin } from "./src/WaxSelectionPlugin"; diff --git a/wax-prosemirror-plugins/src/comments/ActiveComment.js b/wax-prosemirror-plugins/src/comments/CommentPlugin.js similarity index 86% rename from wax-prosemirror-plugins/src/comments/ActiveComment.js rename to wax-prosemirror-plugins/src/comments/CommentPlugin.js index 5c7c63bab296a49db29cb5ffebda9a915d1f2190..7597afd04903ad99ad8076098c75dda83bda5790 100644 --- a/wax-prosemirror-plugins/src/comments/ActiveComment.js +++ b/wax-prosemirror-plugins/src/comments/CommentPlugin.js @@ -3,11 +3,23 @@ import { Plugin, PluginKey } from "prosemirror-state"; import { Decoration, DecorationSet } from "prosemirror-view"; import { DocumentHelpers } from "wax-prosemirror-utilities"; -const activeComment = new PluginKey("activeComment"); +const commentPlugin = new PluginKey("commentPlugin"); const getComment = state => { const commentMark = state.schema.marks["comment"]; - const commentOnSelection = DocumentHelpers.findMark(state, commentMark); + const commentOnSelection = DocumentHelpers.findFragmentedMark( + state, + commentMark + ); + + // Don't allow Active comment if selection is not collapsed + if ( + state.selection.from !== state.selection.to && + commentOnSelection && + commentOnSelection.attrs.conversation.length + ) { + return; + } if (commentOnSelection) { const commentNodes = DocumentHelpers.findChildrenByMark( @@ -40,19 +52,13 @@ const getComment = state => { }; } } - if ( - state.selection.from !== state.selection.to && - commentOnSelection && - commentOnSelection.attrs.conversation.length - ) - return; return commentOnSelection; }; export default props => { return new Plugin({ - key: activeComment, + key: commentPlugin, state: { init: (_, state) => { return { comment: getComment(state) }; @@ -75,7 +81,7 @@ export default props => { }, props: { decorations: state => { - const commentPluginState = state && activeComment.getState(state); + const commentPluginState = state && commentPlugin.getState(state); return commentPluginState.createDecoration; } } diff --git a/wax-prosemirror-schema/src/marks/trackChangesMarks/index.js b/wax-prosemirror-schema/src/marks/trackChangesMarks/index.js index 1be38fc68e227dd5b301df09880453d6cde8b02a..65843faf61d185a84596cbeda62975d1b0127ff1 100644 --- a/wax-prosemirror-schema/src/marks/trackChangesMarks/index.js +++ b/wax-prosemirror-schema/src/marks/trackChangesMarks/index.js @@ -3,7 +3,7 @@ import deletionMark from "./deletionMark"; import formatChangeMark from "./formatChangeMark"; export default { + format_change: formatChangeMark, insertion: insertionMark, - deletion: deletionMark, - format_change: formatChangeMark + deletion: deletionMark }; diff --git a/wax-prosemirror-services/src/CommentsService/CommentsService.js b/wax-prosemirror-services/src/CommentsService/CommentsService.js index 1a35255163621987ac19d1abbf8f56c9d78f7fd5..d79a5c039e79c666d4236c0ee073a744d6d3115d 100644 --- a/wax-prosemirror-services/src/CommentsService/CommentsService.js +++ b/wax-prosemirror-services/src/CommentsService/CommentsService.js @@ -1,15 +1,15 @@ import Service from "../Service"; import { commentMark } from "wax-prosemirror-schema"; import { RightArea, CommentBubbleComponent } from "wax-prosemirror-components"; -import { ActiveComment } from "wax-prosemirror-plugins"; +import { CommentPlugin } from "wax-prosemirror-plugins"; -const PLUGIN_KEY = "activeComment"; +const PLUGIN_KEY = "commentPlugin"; export default class CommentsService extends Service { name = "CommentsService"; boot() { - this.app.PmPlugins.add(PLUGIN_KEY, ActiveComment(PLUGIN_KEY)); + this.app.PmPlugins.add(PLUGIN_KEY, CommentPlugin(PLUGIN_KEY)); const createOverlay = this.container.get("CreateOverlay"); const layout = this.container.get("Layout"); createOverlay( diff --git a/wax-prosemirror-utilities/src/document/DocumentHelpers.js b/wax-prosemirror-utilities/src/document/DocumentHelpers.js index f29e9bad9975c17100a787fac0fb0dc8b2a6cd42..f5fa3c1a2c5980af0dba40716ca2e0197d96d973 100644 --- a/wax-prosemirror-utilities/src/document/DocumentHelpers.js +++ b/wax-prosemirror-utilities/src/document/DocumentHelpers.js @@ -1,6 +1,5 @@ const findMark = (state, PMmark, toArr = false) => { const { selection: { $from, $to }, doc } = state; - const fromMark = $from.marks().find(mark => mark.type === PMmark); const toMark = $to.marks().find(mark => mark.type === PMmark); let markFound; @@ -42,6 +41,57 @@ const getSelectionMark = (state, PMmark) => { return markFound; }; +/* this is a workaround for now to find marks + that are pm will break them +*/ +const findFragmentedMark = (state, PMmark) => { + const { selection: { $from, $to }, doc } = state; + const fromPos = [$from.pos - 1, $from.pos]; + const toPos = [$to.pos - 1, $to.pos]; + let markFound; + + for (let i = 0; i < fromPos.length; i++) { + doc.nodesBetween(fromPos[i], toPos[i], (node, from) => { + if (node.marks) { + const actualMark = node.marks.find(mark => mark.type === PMmark); + if (actualMark) { + markFound = { + from, + to: from + node.nodeSize, + attrs: actualMark.attrs + }; + } + } + }); + if (markFound) { + return markFound; + break; + } + } + return markFound; +}; + +const findAllCommentsWithSameId = state => { + const commentMark = state.schema.marks["comment"]; + const commentOnSelection = findFragmentedMark(state, commentMark); + + const commentNodes = findChildrenByMark(state.doc, commentMark, true); + + const allCommentsWithSameId = []; + commentNodes.map(node => { + node.node.marks.filter(mark => { + if ( + mark.type.name === "comment" && + commentOnSelection.attrs.id === mark.attrs.id + ) { + allCommentsWithSameId.push(node); + } + }); + }); + console.log(allCommentsWithSameId); + return allCommentsWithSameId; +}; + export const flatten = (node, descend = true) => { if (!node) { throw new Error('Invalid "node" parameter'); @@ -92,5 +142,7 @@ export default { findInlineNodes, findChildrenByMark, findChildrenByAttr, - getSelectionMark + getSelectionMark, + findFragmentedMark, + findAllCommentsWithSameId };