react_comments-8.x-1.0-beta2/js/src/src/components/Comment.js

js/src/src/components/Comment.js
import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import CommentBox from './CommentBox';
import './Comment.css';
import timeago from 'timeago.js';
import Constants from '../utils/constants';
import ReplyArrow from '../icons/reply-arrow';
import Permalink from '../icons/permalink';
import DeletedComment from './DeletedComment';
import ReplyList from './ReplyList';
import CommentActions from './CommentActions';
import CommentMenu from './CommentMenu';
import UserPicture from './UserPicture';

class Comment extends Component {
  state = {
    replyActive: false,
    editActive: false,
    message: null
  };

  toggleState = (stateToToggle) => {
    this.setState({[stateToToggle]: !this.state[stateToToggle]});
  };

  postReply = (commentText, anonName, anonEmail, notify) => {
    return this.props.postReply(this.props.id, commentText, anonName, anonEmail, notify);
  };

  saveEdit = (commentText, notify) => {
    return this.props.saveEdit(this.props.id, commentText, notify);
  };

  deleteComment = (id) => {
    return this.props.deleteComment(id).catch((err) => {
      this.setState({
        message: {
          message: err.message,
          type: 'error'
        }
      })
    });
  };

  closeMenu = () => {
    if (this.props.id === this.props.openMenu) {
      this.props.toggleMenu(this.props.id);
    }
  };

  convertTimestampToDate = (created_at) => {
    const date = new Date(created_at * 1000);
    const created_ago = timeago().format(created_at * 1000);

    // if the comment was posted more than a week ago show the date instead
    if (Date.now() - created_at * 1000 > 604800000) {
      return window.Drupal.t('@month/@day/@year', {
        '@month': date.getMonth() + 1,
        '@day': date.getDate(),
        '@year': date.getFullYear()
      });
    }

    // If it seconds/minutes/hours/days ago
    const created_ago_parts = created_ago.match(/(\d+)\s([a-zA-Z]+)\sago/);
    if (created_ago_parts) {
      let created_ago_time = created_ago_parts[2];

      switch (created_ago_parts[2]) {
        // We need to list all options using Drupal.t, to be able to translate
        case 'day': created_ago_time = window.Drupal.t('day'); break;
        case 'days': created_ago_time = window.Drupal.t('days'); break;
        case 'hour': created_ago_time = window.Drupal.t('hour'); break;
        case 'hours': created_ago_time = window.Drupal.t('hours'); break;
        case 'minute': created_ago_time = window.Drupal.t('minute'); break;
        case 'minutes': created_ago_time = window.Drupal.t('minutes'); break;
        case 'second': created_ago_time = window.Drupal.t('second'); break;
        case 'seconds': created_ago_time = window.Drupal.t('seconds'); break;
        default: break;
      }

      return window.Drupal.t('@created_ago ago', {
        '@created_ago': +created_ago_parts[1] + ' ' + created_ago_time
      });
    }

    // Just now
    return window.Drupal.t('just now');
  };

  componentDidMount() {
    window.addEventListener('hashchange', event => {
      const [ , id ] = window.location.hash.split('#');

      this.scrollToComment(id);
      event.preventDefault();
    });

    const event = document.createEvent('HTMLEvents');
    event.initEvent('hashchange', false, true);
    window.dispatchEvent(event);
  }

  scrollToComment(id) {
    if (`comment-${this.props.id}` === id) {
      const document = window.document.documentElement;
      const rect = ReactDOM
        .findDOMNode(this.refs[id])
        .getBoundingClientRect();

      const top = rect.top + window.pageYOffset - document.clientTop;
      const margin = window.rcTopMargin > 0 ? window.rcTopMargin : 0;

      window.scrollTo(0, top - margin);
    }
  }

  render() {
    const { id, currentUser, settings, comment, replies, replyTo, created_at, openMenu, toggleMenu, status, flagComment, publishComment, unpublishComment, published, name, notify } = this.props;
    const { replyActive, editActive, message } = this.state;

    let { user } = this.props;

    if (user.isAnon) {
      user.name = name;
    }

    if (status === Constants.deleted || status === Constants.flaggedUnpublished) {
      return !window.commentsAppFullDelete
        ? <DeletedComment {...this.props} />
        : null;
    }

    return (
      <div className={editActive ? "rc_comment rc_comment--edit-active" : "rc_comment"} id={`comment-${id}`} ref={`comment-${id}`}>
        <div className={ (published === '0') ? "rc_comment-container rc_comment-container--unpublished" : "rc_comment-container" }>
          <UserPicture thumbnail={user.thumbnail} />
          <div className="rc_body">
            { message && <div className={`rc_message rc_message-type--${message.type}`}>{message.message}</div> }
            <div className="rc_comment-details">
              <span className="rc_username">{user.name}</span>
              { replyTo && <span className="rc_reply-to"><ReplyArrow/>{replyTo.name}</span> }
              {/* Apparently javascript uses 13 digit timestamps (including milliseconds)... Append 000 to the unix timestamp to get it to work. */}
              <span className="rc_time-ago">{this.convertTimestampToDate(created_at)}</span>
              <span className="rc_permalink">
                <a href={`#comment-${id}`}><Permalink /></a>
              </span>

              { window.commentsAppStatus && <CommentMenu
                  user={user}
                  currentUser={currentUser}
                  id={id}
                  openMenu={openMenu}
                  closeMenu={this.closeMenu}
                  toggleMenu={toggleMenu}
                  flagComment={flagComment}
                  publishComment={publishComment}
                  unpublishComment={unpublishComment}
                  deleteComment={this.deleteComment}
                  status={status}
                  published={published}
              /> }
            </div>

            { editActive ?
              <CommentBox
                commentId={id}
                settings={settings}
                text={comment}
                notify={notify}
                user={currentUser}
                isEdit={true}
                type="edit"
                cancelEdit={() => this.toggleState('editActive')}
                saveEdit={this.saveEdit}
              /> :
              <div className="rc_comment-text" dangerouslySetInnerHTML={{__html: comment.replace(/(?:\r\n|\r|\n)/g, '<br />')}}></div>
            }

            { window.commentsAppStatus && <CommentActions
              currentUser={currentUser}
              user={user}
              editActive={editActive}
              replyActive={replyActive}
              toggleState={this.toggleState}
            /> }

            { replyActive &&
              <CommentBox
                commentId={id}
                isReply={true}
                type="reply"
                user={currentUser}
                settings={settings}
                postReply={this.postReply}
                closeReplyBox={() => this.toggleState('replyActive')}
              /> }

          </div>
        </div>
        { replies &&
          <ReplyList
              {...this.props}
              replyTo={user}
          />
        }
      </div>
    );
  }
}

export default Comment;

Главная | Обратная связь

drupal hosting | друпал хостинг | it patrol .inc