// - Import react components import React, { Component } from 'react' import { connect } from 'react-redux' import { NavLink} from 'react-router-dom' import PropTypes from 'prop-types' import { createAction as action } from 'redux-actions' import moment from 'moment' import Linkify from 'react-linkify' // - Import material UI libraries import { List, ListItem } from 'material-ui/List' import Divider from 'material-ui/Divider' import Paper from 'material-ui/Paper' import FlatButton from 'material-ui/FlatButton' import { grey400, darkBlack, lightBlack } from 'material-ui/styles/colors' import IconButton from 'material-ui/IconButton' import MoreVertIcon from 'material-ui/svg-icons/navigation/more-vert' import IconMenu from 'material-ui/IconMenu' import MenuItem from 'material-ui/MenuItem' import TextField from 'material-ui/TextField' // - Import app components import UserAvatar from 'UserAvatar' // - Import API // - Import action types import * as types from 'actionTypes' // - Import actions import * as commentActions from 'commentActions' import * as userActions from 'userActions' /** * Create component class */ export class Comment extends Component { static propTypes = { /** * Comment object */ comment: PropTypes.object, /** * If it's true the post owner is the logged in user which this post be long to the comment */ isPostOwner: PropTypes.bool, /** * If it's true the comment is disable to write */ disableComments: PropTypes.bool, } /** * Component constructor * @param {object} props is an object properties of component */ constructor(props) { super(props) this.textareaRef = i => { this.inputText = i } this.divCommentRef = i => { this.divComment = i } //Defaul state this.state = { /** * Comment text */ text: this.props.comment.text, /** * Comment text to match edit with new comment that is edited */ initialText: this.props.comment.text, /** * If comment text dosn't take any change it will be true */ editDisabled: true, /** * If it's true the post owner is the logged in user which this post be long to the comment */ isPostOwner: PropTypes.bool } // Binding functions to `this` this.handleDelete = this.handleDelete.bind(this) this.handleUpdateComment = this.handleUpdateComment.bind(this) this.handleOnChange = this.handleOnChange.bind(this) this.handleCancelEdit = this.handleCancelEdit.bind(this) this.handleEditComment = this.handleEditComment.bind(this) } /** * Handle show edit comment * @param {event} evt is an event passed by clicking on edit button */ handleEditComment = (evt) => { this.inputText.style.height = this.divComment.clientHeight + 'px' this.props.openEditor() } /** * Handle cancel edit * @param {event} evt is an event passed by clicking on cancel button */ handleCancelEdit = (evt) => { this.setState({ text: this.state.initialText }) this.props.closeEditor() } /** * Handle edit comment * @param {event} evt is an event passed by clicking on post button */ handleUpdateComment = (evt) => { this.props.update(this.props.comment.id, this.props.comment.postId, this.state.text) this.setState({ initialText: this.state.text }) } /** * When comment text changed * @param {event} evt is an event passed by change comment text callback funciton * @param {string} data is the comment text which user writes */ handleOnChange = (evt) => { const data = evt.target.value this.inputText.style.height = evt.target.scrollHeight + 'px' if (data.length === 0 || data.trim() === '' || data.trim() === this.state.initialText) { this.setState({ text: data, editDisabled: true }) } else { this.setState({ text: data, editDisabled: false }) } } /** * Delete a comment * @param {event} evt an event passed by click on delete comment * @param {string} id comment identifire * @param {string} postId post identifier which comment belong to */ handleDelete = (evt, id, postId) => { this.props.delete(id, postId) } componentWillMount() { const {userId} = this.props.comment if (!this.props.isCommentOwner && !this.props.info[userId]) { this.props.getUserInfo() } } /** * Reneder component DOM * @return {react element} return the DOM which rendered by component */ render() { /** * DOM styles * * * @memberof Comment */ const styles = { comment: { marginBottom: '12px' }, iconButton: { width: 16, height: 16 }, author:{ fontSize: "13px", paddingRight: "10px", fontWeight: 400, color: "rgba(0,0,0,0.87)", textOverflow: "ellipsis", overflow: "hidden" }, commentBody:{ fontSize: "13px", lineHeight: "20px", color: "rgba(0,0,0,0.87)", fontWeight: 300, height: "", display: "block" } } /** * Comment object from props */ const {comment} = this.props const iconButtonElement = ( ) const RightIconMenu = () => ( Reply {this.props.isCommentOwner ? (Edit): ''} {(this.props.isCommentOwner || this.props.isPostOwner) ? ( this.handleDelete(evt, comment.id, comment.postId)}>Delete): ''} ) const Author = () => (
{comment.userDisplayName}{moment.unix(comment.creationDate).fromNow()}
) const commentBody = (

{comment.text}

) const {userId} = comment return (
{(!this.props.isCommentOwner && !this.props.isPostOwner && this.props.disableComments )? '' : ()}
{this.state.text}
) } } /** * Map dispatch to props * @param {func} dispatch is the function to dispatch action to reducers * @param {object} ownProps is the props belong to component * @return {object} props of component */ const mapDispatchToProps = (dispatch, ownProps) => { return { delete: (id, postId) => dispatch(commentActions.dbDeleteComment(id, postId)), update: (id, postId, comment) => dispatch(commentActions.dbUpdateComment(id, postId, comment)), openEditor: () => dispatch(commentActions.openCommentEditor({ id: ownProps.comment.id, postId: ownProps.comment.postId })), closeEditor: () => dispatch(commentActions.closeCommentEditor({ id: ownProps.comment.id, postId: ownProps.comment.postId })), getUserInfo: () => dispatch(userActions.dbGetUserInfoByUserId(ownProps.comment.userId)) } } /** * Map state to props * @param {object} state is the obeject from redux store * @param {object} ownProps is the props belong to component * @return {object} props of component */ const mapStateToProps = (state, ownProps) => { const {uid} = state.authorize const avatar = state.user.info && state.user.info[ownProps.comment.userId] ? state.user.info[ownProps.comment.userId].avatar || '' : '' const fullName = state.user.info && state.user.info[ownProps.comment.userId] ? state.user.info[ownProps.comment.userId].fullName || '' : '' return { uid: uid, isCommentOwner: (uid === ownProps.comment.userId), info: state.user.info, avatar, fullName } } // - Connect component to redux store export default connect(mapStateToProps, mapDispatchToProps)(Comment)