Skip to content
Snippets Groups Projects
Comment.js 3.99 KiB
Newer Older
chris's avatar
chris committed
/* eslint react/prop-types: 0 */
chris's avatar
chris committed
import React, { useState, useRef, useEffect } from 'react';
chris's avatar
chris committed
import { v4 as uuidv4 } from 'uuid';
import { last } from 'lodash';
chris's avatar
chris committed
import styled from 'styled-components';
import { DocumentHelpers } from 'wax-prosemirror-utilities';
chris's avatar
chris committed

chris's avatar
chris committed
const SinlgeCommentRow = styled.div`
  padding: 4px;
  border-bottom: 1px solid #ffab20;
chris's avatar
chris committed
  cursor: pointer;
chris's avatar
chris committed
`;

chris's avatar
chris committed
export default ({ comment, activeView, user, active }) => {
chris's avatar
chris committed
  const commentInput = useRef(null);
  const [commentAnnotation, setCommentAnnotation] = useState(comment);
chris's avatar
chris committed
  const [commentInputValue, setcommentInputValue] = useState('');
chris's avatar
chris committed
  const { state, dispatch } = activeView;
chris's avatar
chris committed
  const allCommentsWithSameId = DocumentHelpers.findAllMarksWithSameId(
    state,
    comment,
  );
chris's avatar
chris committed
  const {
    attrs: { conversation },
  } = comment;
  const commentMark = state.schema.marks.comment;
chris's avatar
chris committed

chris's avatar
chris committed
  useEffect(() => {
    setTimeout(() => {
chris's avatar
chris committed
      if (commentInput.current !== null && conversation.length === 0)
        commentInput.current.focus();
chris's avatar
chris committed
    }, 500);
  }, [active]);

chris's avatar
chris committed
  const handleKeyDown = event => {
chris's avatar
chris committed
    if (event.key === 'Enter' || event.which === 13) {
      saveComment(event);
  const saveComment = event => {
    event.stopPropagation();

chris's avatar
chris committed
    const {
      current: { value },
    } = commentInput;
chris's avatar
chris committed
    const { tr } = state;
chris's avatar
chris committed

chris's avatar
chris committed
    const obj = {
      content: value,
      displayName: user.username,
      timestamp: Math.floor(Date.now() / 300000),
    };

chris's avatar
chris committed
    commentAnnotation.attrs.conversation.push(obj);

    allCommentsWithSameId.forEach(singleComment => {
chris's avatar
chris committed
      dispatch(
        tr.addMark(
          singleComment.pos,
          singleComment.pos + singleComment.nodeSize,
          commentMark.create({
            ...((commentAnnotation && commentAnnotation.attrs) || {}),
chris's avatar
chris committed
            conversation: commentAnnotation.attrs.conversation,
          }),
        ),
chris's avatar
chris committed
      );
    });

chris's avatar
chris committed
    setcommentInputValue('');
chris's avatar
chris committed
  };

  const updateCommentInputValue = () => {
chris's avatar
chris committed
    const {
      current: { value },
    } = commentInput;
chris's avatar
chris committed
    setcommentInputValue(value);
  };

  const onBlur = () => {
    const {
      current: { value },
    } = commentInput;
    if (value !== '') {
chris's avatar
chris committed
      // saveComment();
    }

    if (conversation.length === 0 && value === '') {
      resolveComment();
  const resolveComment = event => {
    if (event) event.stopPropagation();
chris's avatar
chris committed
    let maxPos = comment.pos;
    let minPos = comment.pos;
chris's avatar
chris committed
    allCommentsWithSameId.forEach(singleComment => {
      const markPosition = DocumentHelpers.findMarkPosition(
        state,
        singleComment.pos,
        'comment',
      );
      if (markPosition.from < minPos) minPos = markPosition.from;
      if (markPosition.to > maxPos) maxPos = markPosition.to;
    });
chris's avatar
chris committed
    if (allCommentsWithSameId.length > 1)
      maxPos += last(allCommentsWithSameId).node.nodeSize;
    dispatch(state.tr.removeMark(minPos, maxPos, commentMark));
    activeView.focus();
chris's avatar
chris committed
  const commentInputReply = () => {
    return (
chris's avatar
chris committed
      <>
chris's avatar
chris committed
        <input
          type="text"
          ref={commentInput}
          placeholder="add a new comment"
          onChange={updateCommentInputValue}
          onKeyPress={handleKeyDown}
          onBlur={onBlur}
          onClick={event => {
            event.stopPropagation();
          }}
chris's avatar
chris committed
          value={commentInputValue}
chris's avatar
chris committed
          disabled={!active}
chris's avatar
chris committed
        />
chris's avatar
chris committed
        <button
          disabled={!active}
          type="button"
          onClick={event => saveComment(event)}
        >
chris's avatar
chris committed
          Post
        </button>
chris's avatar
chris committed
        <button
          disabled={!active}
          type="button"
          onClick={event => resolveComment(event)}
        >
          Resolve
        </button>
chris's avatar
chris committed
      </>
chris's avatar
chris committed
    );
chris's avatar
chris committed
  };

chris's avatar
chris committed
  return conversation.length === 0 ? (
chris's avatar
chris committed
    <>{commentInputReply()}</>
chris's avatar
chris committed
  ) : (
chris's avatar
chris committed
    <>
chris's avatar
chris committed
      {conversation.map((singleComment, index) => {
        return (
chris's avatar
chris committed
          <SinlgeCommentRow key={uuidv4()}>
            {`${singleComment.displayName} : ${singleComment.content}`}
          </SinlgeCommentRow>
chris's avatar
chris committed
        );
      })}
      {commentInputReply()}
chris's avatar
chris committed
    </>
chris's avatar
chris committed
  );
};