Newer
Older
import React, {
useContext,
useState,
useEffect,
useMemo,
import styled from "styled-components";
import { DocumentHelpers } from "wax-prosemirror-utilities";
import CommentsBoxList from "./../comments/CommentsBoxList";
import { each, uniqBy, sortBy } from "lodash";
const { view: { main }, app, activeView } = useContext(WaxContext);
const activeCommentPlugin = app.PmPlugins.get("activeComment");
const [marks, setMarks] = useState([]);
const [position, setPosition] = useState();
const setTops = useCallback(() => {
const result = [];
let annotationTop = 0;
let boxHeight = 0;
let top = 0;
each(marks[area], (mark, pos) => {
const { attrs: { id } } = mark;
const activeComment = activeCommentPlugin.getState(activeView.state)
.comment;
if (activeComment && mark.attrs.id === activeComment.attrs.id)
isActive = true;
markEl = document.querySelector(`span[data-id="${id}"]`);
if (markEl)
annotationTop = markEl.getBoundingClientRect().top - WaxSurface.top;
} else {
const panelWrapper = document.getElementsByClassName("panelWrapper");
const panelWrapperHeight = panelWrapper[0].getBoundingClientRect()
.height;
.querySelector("#notes-container")
.querySelector(`span[data-id="${id}"]`);
markEl.getBoundingClientRect().top - panelWrapperHeight - 50;
// get height of this mark box
const boxEl = document.querySelector(`div[data-comment="comment-${id}"]`);
if (boxEl) boxHeight = parseInt(boxEl.offsetHeight);
// where the box should move to
top = annotationTop;
// if the above comment box has already taken up the height, move down
if (pos > 0) {
const previousBox = marks[area][pos - 1];
const previousEndHeight = previousBox.endHeight;
if (annotationTop < previousEndHeight) {
top = previousEndHeight + 2;
}
}
// store where the box ends to be aware of overlaps in the next box
mark.endHeight = top + boxHeight + 2;
allCommentsTop.push({ [id]: result[pos] });
// if active, move as many boxes above as needed to bring it to the annotation's height
if (isActive) {
mark.endHeight = annotationTop + boxHeight + 2;
let b = true;
let i = pos;
// first one active, none above
const boxAbove = marks[area][i - 1];
const boxAboveEnds = boxAbove.endHeight;
const currentTop = result[i];
const doesOverlap = boxAboveEnds > currentTop;
if (doesOverlap) {
const overlap = boxAboveEnds - currentTop;
result[i - 1] -= overlap;
allCommentsTop[i - 1][marks[area][i - 1].attrs.id] = result[i - 1];
}
if (!doesOverlap) b = false;
if (i <= 1) b = false;
i -= 1;
}
}
});
setMarks(updateMarks(main));
[JSON.stringify(updateMarks(main)), JSON.stringify(setTops())]
const CommentTrackComponent = useMemo(
comments={marks[area] || []}
[marks[area] || [], position]
return <Fragment>{CommentTrackComponent}</Fragment>;
const updateMarks = view => {
const allBlockNodes = DocumentHelpers.findBlockNodes(view.state.doc);
const allInlineNodes = DocumentHelpers.findInlineNodes(view.state.doc);
const finalMarks = [];
allInlineNodes.map(node => {
if (node.node.marks.length > 0) {
node.node.marks.filter(mark => {
if (
mark.type.name === "comment" ||
mark.type.name === "insertion" ||
mark.type.name === "deletion" ||
mark.type.name === "format_change"
finalMarks.push(mark);
}
});
}
allBlockNodes.map(node => {
if (node.node.attrs.track && node.node.attrs.track.length > 0) {
finalNodes.push(node);
}
});
const nodesAndMarks = [...uniqBy(finalMarks, "attrs.id"), ...finalNodes];
const groupedMarkNodes = {};
sortBy(nodesAndMarks, ["pos"]).forEach(markNode => {
const markNodeAttrs = markNode.attrs
? markNode.attrs
: markNode.node.attrs;
if (!groupedMarkNodes[markNodeAttrs.group]) {
groupedMarkNodes[markNodeAttrs.group] = [markNode];
groupedMarkNodes[markNodeAttrs.group].push(markNode);