// - Import react components import React, { Component } from 'react' import PropTypes from 'prop-types' import _ from 'lodash' import { NavLink } from 'react-router-dom' import { connect } from 'react-redux' import moment from 'moment/moment' import { getTranslate, getActiveLanguage } from 'react-localize-redux' import Paper from 'material-ui/Paper' import Button from 'material-ui/Button' import TextField from 'material-ui/TextField' import Divider from 'material-ui/Divider' import { ListItemIcon, ListItemText, ListItem } from 'material-ui/List' import { grey, teal } from 'material-ui/colors' import { LinearProgress } from 'material-ui/Progress' import { withStyles } from 'material-ui/styles' import { Manager, Target, Popper } from 'react-popper' import { Card, CardActions, CardHeader, CardMedia, CardContent } from 'material-ui' import Grow from 'material-ui/transitions/Grow' import ClickAwayListener from 'material-ui/utils/ClickAwayListener' import classNames from 'classnames' // - Import actions import * as commentActions from 'actions/commentActions' // - Import app components import CommentListComponent from 'components/commentList' import UserAvatar from 'components/userAvatar' import { ICommentGroupComponentProps } from './ICommentGroupComponentProps' import { ICommentGroupComponentState } from './ICommentGroupComponentState' import { Comment } from 'core/domain/comments/comment' import { ServerRequestModel } from 'models/server' import StringAPI from 'api/StringAPI' import { ServerRequestType } from 'constants/serverRequestType' import { ServerRequestStatusType } from 'actions/serverRequestStatusType' const styles = (theme: any) => ({ textField: { fontWeight: 400, fontSize: '14px' }, header: { padding: '2px 3px 3px 10px' }, commentBody: { color: 'black', fontWeight: 400, fontSize: '12px', height: '100%', border: 'none', width: '100%', outline: 'none', resize: 'none' }, author: { fontSize: '10px', paddingRight: '10px', fontWeight: 400, color: 'rgba(0,0,0,0.87)', textOverflow: 'ellipsis', overflow: 'hidden' }, noUnderline: { display: 'none' }, postButton: { flexDirection: 'row-reverse' } }) /** * Create component class */ export class CommentGroupComponent extends Component { static propTypes = { /** * If it's true comment box will be open */ open: PropTypes.bool, /** * If it's true the comment is disable to write */ disableComments: PropTypes.bool, /** * The post identifier which comment belong to */ postId: PropTypes.string, /** * If it's true the post owner is the logged in user which this post be long to the comment */ isPostOwner: PropTypes.bool, /** * Toggle on show/hide comment by passing callback from parent component */ onToggleRequest: PropTypes.func, /** * The user identifier of the post owner which comment belong to */ ownerPostUserId: PropTypes.string } styles = { commentItem: { height: '60px', position: '', zIndex: '' }, toggleShowList: { height: '60px', zIndex: 5 }, writeCommentTextField: { width: '100%', fontWeight: 400, fontSize: '14px' }, progressbar: { height: '1.5px', backgroundColor: 'rgb(245, 243, 243)', color: teal['A400'] }, secondaryText: { fontSize: '13px', lineHeight: '20px', color: 'rgba(0,0,0,0.87)', fontWeight: 300, whiteSpace: 'pre-wrap' }, primaryText: { fontSize: '13px', paddingRight: '10px', fontWeight: 400, color: 'rgba(0,0,0,0.87)', textOverflow: 'ellipsis', overflow: 'hidden' } } /** * Component constructor * @param {object} props is an object properties of component */ constructor (props: ICommentGroupComponentProps) { super(props) /** * Defaul state */ this.state = { commentText: '', postDisable: true } // Binding functions to `this` this.commentList = this.commentList.bind(this) this.handlePostComment = this.handlePostComment.bind(this) this.clearCommentWrite = this.clearCommentWrite.bind(this) } /** * Clear comment text field */ clearCommentWrite = () => { this.setState({ commentText: '', postDisable: true }) } /** * Post comment */ handlePostComment = () => { this.props.send!(this.state.commentText, this.props.postId, this.clearCommentWrite) this.clearCommentWrite() } /** * 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 */ handleChange = (event: any) => { const data = event.target.value this.setState({ commentText: data }) if (data.length === 0 || data.trim() === '') { this.setState({ commentText: '', postDisable: true }) } else { this.setState({ commentText: data, postDisable: false }) } } /** * Get comments' DOM * @return {DOM} list of comments' DOM */ commentList = () => { const {classes} = this.props let comments = this.props.commentSlides if (comments) { comments = _.fromPairs(_.toPairs(comments) .sort((a: any, b: any) => parseInt(b[1].creationDate, 10) - parseInt(a[1].creationDate, 10))) let parsedComments: Comment[] = [] Object.keys(comments).forEach((commentId) => { parsedComments.push({ id: commentId, ...comments![commentId] }) }) if (parsedComments.length === 2) { parsedComments.push(parsedComments[0]) } else if (parsedComments.length === 1) { parsedComments.push(parsedComments[0]) parsedComments.push(parsedComments[0]) } return parsedComments.map((comment, index) => { const { userInfo } = this.props const commentAvatar = userInfo && userInfo[comment.userId!] ? userInfo[comment.userId!].avatar || '' : '' const commentFullName = userInfo && userInfo[comment.userId!] ? userInfo[comment.userId!].fullName || '' : '' const commentBody = (
{comment.text}
) const Author = () => (
{comment.userDisplayName}{moment.unix(comment.creationDate!).fromNow()}
) return ( } avatar={} subheader={commentBody} > ) }) } } /** * Reneder component DOM * @return {react element} return the DOM which rendered by component */ render () { const { comments, classes, postId, fullName, avatar, getCommentsRequest, open, commentSlides, translate } = this.props /** * Comment list box */ const commentWriteBox = (
} subheader={} >
) const showComments = ( comments && Object.keys(comments).length > 0 ? ( ) : '') const loadComments = (( getCommentsRequest === undefined || (getCommentsRequest && getCommentsRequest!.status !== ServerRequestStatusType.OK)) ? : showComments) /** * Return Elements */ return (
0 ? { display: 'block' } : { display: 'none' }}>
{this.commentList()}
{ open ? loadComments : '' }
{ (!this.props.disableComments && open ) ? commentWriteBox : '' }
) } } /** * 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: any, ownProps: ICommentGroupComponentProps) => { return { send: (text: string, postId: string, callBack: Function) => { dispatch(commentActions.dbAddComment(ownProps.ownerPostUserId, { postId: postId, text: text }, callBack)) } } } /** * 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: any, ownProps: ICommentGroupComponentProps) => { const { post, user, authorize, server } = state const {request} = server const { ownerPostUserId, postId } = ownProps const commentSlides = post.userPosts[ownerPostUserId] && post.userPosts[ownerPostUserId][postId] ? post.userPosts[ownerPostUserId][postId].comments : {} const getCommentsRequest: ServerRequestModel = request ? request[StringAPI.createServerRequestId(ServerRequestType.CommentGetComments, postId)] : null return { translate: getTranslate(state.locale), getCommentsRequest, commentSlides, avatar: user.info && user.info[state.authorize.uid] ? user.info[authorize.uid].avatar || '' : '', fullName: user.info && user.info[state.authorize.uid] ? user.info[authorize.uid].fullName || '' : '', userInfo: user.info } } // - Connect component to redux store export default connect(mapStateToProps, mapDispatchToProps)(withStyles(styles as any)(CommentGroupComponent as any) as any)