Skip to content
Snippets Groups Projects
CommentBox.js 4.49 KiB
Newer Older
import React from 'react';
import PropTypes from 'prop-types';
import styled, { css } from 'styled-components';
import { isEmpty } from 'lodash';
import { useTranslation } from 'react-i18next';
chris's avatar
chris committed
import { th, override } from '@pubsweet/ui-toolkit';
import CommentItemList from './CommentItemList';
import CommentReply from './CommentReply';
Yannis Barlas's avatar
Yannis Barlas committed

const inactive = css`
chris's avatar
chris committed
  background: ${th('colorBackgroundHue')};
Yannis Barlas's avatar
Yannis Barlas committed
  cursor: pointer;
  transition: box-shadow 0.2s;
  /* transition: background-color 0.2s; */

  &:hover {
    /* background: white; */
chris's avatar
chris committed
    box-shadow: 0 0 1px 2px ${th('colorBackgroundTabs')};
Yannis Barlas's avatar
Yannis Barlas committed
  }
Yannis Barlas's avatar
Yannis Barlas committed

chris's avatar
chris committed
const inactiveButton = css`
  cursor: not-allowed;
  opacity: 0.3;
`;

Yannis Barlas's avatar
Yannis Barlas committed
const Wrapper = styled.div`
  background: white;
chris's avatar
chris committed
  border: 1px solid ${th('colorBackgroundTabs')};
Yannis Barlas's avatar
Yannis Barlas committed
  border-radius: 3px;
  box-sizing: border-box;
  display: flex;
  flex-direction: column;
  font-family: ${th('fontInterface')};
Yannis Barlas's avatar
Yannis Barlas committed

  ${props => !props.active && inactive}
chris's avatar
chris committed

  ${override('Wax.CommentWrapper')}
Yannis Barlas's avatar
Yannis Barlas committed

const Head = styled.div`
  display: flex;
  justify-content: flex-end;
  padding: 8px 16px 0;
chris's avatar
chris committed

chris's avatar
chris committed
  ${override('Wax.CommentResolveWrapper')}
Yannis Barlas's avatar
Yannis Barlas committed

const Resolve = styled.button`
  align-self: flex-end;
chris's avatar
chris committed
  background: none;
chris's avatar
chris committed
  border: none;
chris's avatar
chris committed
  color: #0042c7;
Yannis Barlas's avatar
Yannis Barlas committed
  cursor: pointer;
  margin-bottom: 12px;

  &:hover {
chris's avatar
chris committed
    background: ${th('colorBackgroundHue')};
    border: none;
Yannis Barlas's avatar
Yannis Barlas committed
  }
chris's avatar
chris committed

  ${props => props.isReadOnly && inactiveButton}
chris's avatar
chris committed

  ${override('Wax.CommentResolve')}
Yannis Barlas's avatar
Yannis Barlas committed

const StyledReply = styled(CommentReply)`
chris's avatar
chris committed
  border-top: ${props => !props.isNewComment && `3px solid #E1EBFF`};
chris's avatar
chris committed

  ${override('Wax.CommentReplyWrapper')}
Yannis Barlas's avatar
Yannis Barlas committed

const CommentBox = props => {
  const {
    active,
    className,
    commentId,
    commentData,
chris's avatar
chris committed
    isReadOnly,
Yannis Barlas's avatar
Yannis Barlas committed
    onClickBox,
Yannis Barlas's avatar
Yannis Barlas committed
    onClickResolve,
chris's avatar
chris committed
    onTextAreaBlur,
chris's avatar
chris committed
    usersMentionList,
Yannis Barlas's avatar
Yannis Barlas committed

  // send signal to make this comment active
  const onClickWrapper = () => {
    if (active) return;
    onClickBox(commentId);
  };
Yannis Barlas's avatar
Yannis Barlas committed

chris's avatar
chris committed
  if (!active && (!commentData || commentData.length === 0)) return null;
  const { t, i18n } = useTranslation();
Yannis Barlas's avatar
Yannis Barlas committed
  return (
    <Wrapper active={active} className={className} onClick={onClickWrapper}>
      {active && commentData.length > 0 && (
Yannis Barlas's avatar
Yannis Barlas committed
        <Head>
chris's avatar
chris committed
          <Resolve
            isReadOnly={isReadOnly}
            onClick={() => {
              if (!isReadOnly) return onClickResolve(commentId);
              return false;
            }}
          >
            {!isEmpty(i18n) && i18n.exists(`Wax.Comments.Resolve`)
              ? t(`Wax.Comments.Resolve`)
              : 'Resolve'}
chris's avatar
chris committed
          </Resolve>
Yannis Barlas's avatar
Yannis Barlas committed
        </Head>
      )}
      <CommentItemList
        active={active}
        data={commentData}
        title={title}
        users={users}
      />
      {active && (
        <StyledReply
chris's avatar
chris committed
          isNewComment={commentData.length === 0}
chris's avatar
chris committed
          isReadOnly={isReadOnly}
chris's avatar
chris committed
          onClickPost={onClickPost}
chris's avatar
chris committed
          onTextAreaBlur={onTextAreaBlur}
          showTitle={showTitle}
chris's avatar
chris committed
          usersMentionList={usersMentionList}
chris's avatar
chris committed
        />
      )}
Yannis Barlas's avatar
Yannis Barlas committed
    </Wrapper>
Yannis Barlas's avatar
Yannis Barlas committed

CommentBox.propTypes = {
  /** Whether this is the current active comment */
  active: PropTypes.bool,
chris's avatar
chris committed
  isReadOnly: PropTypes.bool.isRequired,
Yannis Barlas's avatar
Yannis Barlas committed
  /** List of objects containing data for comment items */
  commentData: PropTypes.arrayOf(
    PropTypes.shape({
      content: PropTypes.string.isRequired,
      displayName: PropTypes.string.isRequired,
      userId: PropTypes.string,
chris's avatar
chris committed
      timestamp: PropTypes.string.number,
Yannis Barlas's avatar
Yannis Barlas committed
    }),
  ),
  /** This comment's id in the document */
  commentId: PropTypes.string.isRequired,
  /** Function to run when box is clicked on.
   *  Use this to make comment active on click (it passes on the comment id).
   *  eg. `onClickBox = commentId => doSth(commentId)`
   *  Will only run if comment is not active already.
   */
  onClickBox: PropTypes.func.isRequired,
  /** Function to run when "post" button is clicked to send reply */
  onClickPost: PropTypes.func.isRequired,
Yannis Barlas's avatar
Yannis Barlas committed
  /** Function to run when "resolve" button is clicked */
  onClickResolve: PropTypes.func.isRequired,
chris's avatar
chris committed
  /** Function to run when text area loses focus */
  onTextAreaBlur: PropTypes.func.isRequired,
  title: PropTypes.string,
  showTitle: PropTypes.bool.isRequired,
  users: PropTypes.arrayOf(
    PropTypes.shape({
      displayName: PropTypes.string.isRequired,
      userId: PropTypes.string.isRequired,
      currentUser: PropTypes.bool,
    }),
  ),
Yannis Barlas's avatar
Yannis Barlas committed

CommentBox.defaultProps = {
  active: false,
  commentData: [],
Yannis Barlas's avatar
Yannis Barlas committed

export default CommentBox;