diff --git a/wax-prosemirror-services/src/CommentsService/plugins/AnnotationDecoration.js b/wax-prosemirror-services/src/CommentsService/plugins/CommentDecoration.js similarity index 94% rename from wax-prosemirror-services/src/CommentsService/plugins/AnnotationDecoration.js rename to wax-prosemirror-services/src/CommentsService/plugins/CommentDecoration.js index afb4284d928bfdf53809f94842f11888f7ff8bb5..caf61271e4ddc2ca74218cea8281ab298709633e 100644 --- a/wax-prosemirror-services/src/CommentsService/plugins/AnnotationDecoration.js +++ b/wax-prosemirror-services/src/CommentsService/plugins/CommentDecoration.js @@ -1,4 +1,4 @@ -export default class AnnotationDecoration { +export default class CommentDecoration { constructor(decoration) { this.decoration = decoration; } diff --git a/wax-prosemirror-services/src/CommentsService/plugins/CommentState.js b/wax-prosemirror-services/src/CommentsService/plugins/CommentState.js new file mode 100644 index 0000000000000000000000000000000000000000..c88cb1990d629f302cac9fd2fe9252ce71335c85 --- /dev/null +++ b/wax-prosemirror-services/src/CommentsService/plugins/CommentState.js @@ -0,0 +1,121 @@ +/* eslint-disable no-param-reassign */ +import { v4 as uuidv4 } from 'uuid'; +import { Decoration, DecorationSet } from 'prosemirror-view'; +import CommentDecoration from './CommentDecoration'; +import { AnnotationPluginKey } from './AnnotationPlugin'; + +const randomId = () => { + return uuidv4(); +}; + +export default class CommentState { + constructor(options) { + this.decorations = DecorationSet.empty; + this.options = options; + } + + addComment(action) { + const { map } = this.options; + const { from, to, data } = action; + const id = randomId(); + map.set(id, { id, from, to, data }); + } + + updateComment(action) { + const { map } = this.options; + const annotationToUpdate = map.get(action.id); + if (annotationToUpdate) { + annotationToUpdate.data = action.data; + } + } + + deleteComment(id) { + const { map } = this.options; + map.delete(id); + } + + commentsAt(position, to) { + return this.decorations.find(position, to || position).map(decoration => { + return new CommentDecoration(decoration); + }); + } + + allCommentsList() { + const { map } = this.options; + return Array.from(map, ([key, value]) => { + // eslint-disable-next-line prefer-object-spread + return Object.assign(Object.assign({}, value), { + id: key, + }); + }).filter(value => { + return 'from' in value && 'to' in value; + }); + } + + createDecorations(state) { + const { map } = this.options; + + const decorations = []; + const termList = Array.from(map, ([key, value]) => { + // eslint-disable-next-line prefer-object-spread + return Object.assign(Object.assign({}, value), { + id: key, + }); + }).filter(value => { + return 'from' in value && 'to' in value; + }); + + termList.forEach(annotation => { + const { from, to } = annotation; + + decorations.push( + Decoration.inline( + from, + to, + { + class: 'comment', + 'data-id': annotation.id, + }, + { + id: annotation.id, + data: annotation, + inclusiveEnd: true, + }, + ), + ); + }); + this.decorations = DecorationSet.create(state.doc, decorations); + } + + apply(transaction, state) { + const action = transaction.getMeta(AnnotationPluginKey); + if (action && action.type) { + if (action.type === 'addComment') { + this.addComment(action); + } + if (action.type === 'updateComment') { + this.updateComment(action); + } + if (action.type === 'deleteComment') { + this.deleteComment(action.id); + } + this.createDecorations(state); + return this; + } + + // manually map annotation positions + this.options.map.forEach((annotation, _) => { + if ('from' in annotation && 'to' in annotation) { + annotation.from = transaction.mapping.map(annotation.from); + annotation.to = transaction.mapping.map(annotation.to); + } + }); + this.createDecorations(state); + return this; + } +} + +// let res = +// annotation.to === state.selection.to && +// state.selection.from === state.selection.to; +// console.log(res, transaction.docChanged);