[Improvement] resolve open comment menu and remove anti pattern editorStatus property from comment

This commit is contained in:
Qolzam
2018-02-23 21:57:05 +07:00
parent 014fa9ef3d
commit 2ce8da6ae2
13 changed files with 55 additions and 40 deletions

View File

@@ -130,7 +130,6 @@ export const dbGetComments = (ownerUserId: string, postId: string) => {
*/ */
export const dbUpdateComment = (comment: Comment) => { export const dbUpdateComment = (comment: Comment) => {
return (dispatch: any, getState: Function) => { return (dispatch: any, getState: Function) => {
delete comment.editorStatus
dispatch(globalActions.showTopLoading()) dispatch(globalActions.showTopLoading())
return commentService.updateComment(comment) return commentService.updateComment(comment)

View File

@@ -112,6 +112,9 @@ export const hideMessage = () => {
* @param {string} message * @param {string} message
*/ */
export const showMessage = (message: string) => { export const showMessage = (message: string) => {
if (!message || message === '' || (message && message.trim() === '')) {
message = 'Bad request'
}
return { return {
type: GlobalActionType.SHOW_MESSAGE_GLOBAL, type: GlobalActionType.SHOW_MESSAGE_GLOBAL,
payload: message payload: message

View File

@@ -113,7 +113,7 @@ export const dbAddImagePost = (newPost: Post, callBack: Function) => {
*/ */
export const dbUpdatePost = (updatedPost: Post, callBack: Function) => { export const dbUpdatePost = (updatedPost: Post, callBack: Function) => {
return (dispatch: any, getState: Function) => { return (dispatch: any, getState: Function) => {
console.trace('update post ', updatedPost)
dispatch(globalActions.showTopLoading()) dispatch(globalActions.showTopLoading())
return postService.updatePost(updatedPost).then(() => { return postService.updatePost(updatedPost).then(() => {

View File

@@ -221,7 +221,6 @@ export class CommentComponent extends Component<ICommentComponentProps, IComment
*/ */
handleUpdateComment = (evt: any) => { handleUpdateComment = (evt: any) => {
const { comment } = this.props const { comment } = this.props
comment.editorStatus = undefined
comment.text = this.state.text comment.text = this.state.text
this.props.update!(comment) this.props.update!(comment)
this.setState({ this.setState({
@@ -291,11 +290,11 @@ export class CommentComponent extends Component<ICommentComponentProps, IComment
/** /**
* Comment object from props * Comment object from props
*/ */
const { comment, classes, fullName, avatar, translate } = this.props const { comment, classes, fullName, avatar, translate , editorStatus} = this.props
const { openMenu } = this.state const { openMenu } = this.state
const RightIconMenu = () => ( const rightIconMenu = (
<Manager <Manager
className={classes.iconButton} className={classes.iconButton}
> >
@@ -336,7 +335,7 @@ export class CommentComponent extends Component<ICommentComponentProps, IComment
}}>{moment.unix(comment.creationDate!).fromNow()}</span> }}>{moment.unix(comment.creationDate!).fromNow()}</span>
</div> </div>
) )
const { userId, editorStatus } = comment const { userId } = comment
const commentBody = ( const commentBody = (
<div style={{ outline: 'none', flex: 'auto', flexGrow: 1 }}> <div style={{ outline: 'none', flex: 'auto', flexGrow: 1 }}>
{ editorStatus ? <TextField { editorStatus ? <TextField
@@ -373,7 +372,7 @@ export class CommentComponent extends Component<ICommentComponentProps, IComment
title={editorStatus ? '' : <Author />} title={editorStatus ? '' : <Author />}
subheader={commentBody} subheader={commentBody}
avatar={<NavLink to={`/${userId}`}><UserAvatar fullName={fullName!} fileName={avatar!} size={24} /></NavLink>} avatar={<NavLink to={`/${userId}`}><UserAvatar fullName={fullName!} fileName={avatar!} size={24} /></NavLink>}
action={(!this.props.isCommentOwner && !this.props.isPostOwner && this.props.disableComments) || editorStatus ? '' : (<RightIconMenu />)} action={(!this.props.isCommentOwner && !this.props.isPostOwner && this.props.disableComments) || editorStatus ? '' : rightIconMenu}
> >
</CardHeader> </CardHeader>

View File

@@ -95,6 +95,11 @@ export interface ICommentComponentProps {
*/ */
disableComments?: boolean disableComments?: boolean
/**
* Whether comment edit is open
*/
editorStatus: boolean
/** /**
* Styles * Styles
*/ */

View File

@@ -317,7 +317,7 @@ export class CommentGroupComponent extends Component<ICommentGroupComponentProps
const showComments = ( comments && Object.keys(comments).length > 0 const showComments = ( comments && Object.keys(comments).length > 0
? ( ? (
<Paper elevation={0} style={open ? { display: 'block', padding: '0px 0px' } : { display: 'none', padding: '12px 16px' }}> <Paper elevation={0} style={open ? { display: 'block', padding: '0px 0px' } : { display: 'none', padding: '12px 16px' }}>
<CommentListComponent comments={comments!} isPostOwner={this.props.isPostOwner} disableComments={this.props.disableComments} /> <CommentListComponent comments={comments!} isPostOwner={this.props.isPostOwner} disableComments={this.props.disableComments} postId={postId}/>
</Paper>) </Paper>)
: '') : '')
const loadComments = (( getCommentsRequest === undefined || (getCommentsRequest && getCommentsRequest!.status !== ServerRequestStatusType.OK)) ? <LinearProgress style={this.styles.progressbar} variant='indeterminate' /> : showComments) const loadComments = (( getCommentsRequest === undefined || (getCommentsRequest && getCommentsRequest!.status !== ServerRequestStatusType.OK)) ? <LinearProgress style={this.styles.progressbar} variant='indeterminate' /> : showComments)

View File

@@ -54,7 +54,7 @@ export class CommentListComponent extends Component<ICommentListComponentProps,
* @return {DOM} list of comments' DOM * @return {DOM} list of comments' DOM
*/ */
commentList = () => { commentList = () => {
let comments = this.props.comments let {comments, commentsEditorStatus} = this.props
if (comments) { if (comments) {
let parsedComments: Comment[] = [] let parsedComments: Comment[] = []
@@ -68,7 +68,15 @@ export class CommentListComponent extends Component<ICommentListComponentProps,
return sortedComments.map((comment: Comment, index: number, array: Comment) => { return sortedComments.map((comment: Comment, index: number, array: Comment) => {
return <CommentComponent key={comment.id!} comment={comment} isPostOwner={this.props.isPostOwner} disableComments={this.props.disableComments}/> return (
<CommentComponent
key={comment.id!}
comment={comment}
isPostOwner={this.props.isPostOwner}
disableComments={this.props.disableComments}
editorStatus={(commentsEditorStatus![comment.id!]) || false}
/>
)
}) })
@@ -116,9 +124,11 @@ const mapDispatchToProps = (dispatch: any, ownProps: ICommentListComponentProps)
* @param {object} ownProps is the props belong to component * @param {object} ownProps is the props belong to component
* @return {object} props of component * @return {object} props of component
*/ */
const mapStateToProps = (state: any) => { const mapStateToProps = (state: any, ownProps: ICommentListComponentProps) => {
const { comment } = state
const commentsEditorStatus: { [commentId: string]: Comment } = comment.editorStatus[ownProps.postId] || {}
return { return {
commentsEditorStatus
} }
} }

View File

@@ -10,6 +10,11 @@ export interface ICommentListComponentProps {
*/ */
comments: {[commentId: string]: Comment} comments: {[commentId: string]: Comment}
/**
* Comments editor status
*/
commentsEditorStatus?: {[commentId: string]: boolean}
/** /**
* Current user is post the post owner {true} or not false * Current user is post the post owner {true} or not false
* *
@@ -18,6 +23,11 @@ export interface ICommentListComponentProps {
*/ */
isPostOwner: boolean isPostOwner: boolean
/**
* The post identifier comments belong to
*/
postId: string
/** /**
* Comment on the post is disabled {false} or not {true} * Comment on the post is disabled {false} or not {true}
* *

View File

@@ -160,7 +160,6 @@ export class HomeComponent extends Component<IHomeComponentProps, IHomeComponent
* Handle drawer toggle * Handle drawer toggle
*/ */
handleDrawerToggle = () => { handleDrawerToggle = () => {
console.trace('toggle')
this.setState({ drawerOpen: !this.state.drawerOpen }) this.setState({ drawerOpen: !this.state.drawerOpen })
} }

View File

@@ -340,7 +340,7 @@ export class PostComponent extends Component<IPostComponentProps, IPostComponent
render () { render () {
const { post, setHomeTitle, goTo, fullName, isPostOwner, commentList, avatar, classes , translate} = this.props const { post, setHomeTitle, goTo, fullName, isPostOwner, commentList, avatar, classes , translate} = this.props
const { postMenuAnchorEl, isPostMenuOpen } = this.state const { postMenuAnchorEl, isPostMenuOpen } = this.state
const RightIconMenu = () => ( const rightIconMenu = (
<Manager> <Manager>
<Target> <Target>
<IconButton <IconButton
@@ -355,10 +355,10 @@ export class PostComponent extends Component<IPostComponentProps, IPostComponent
<Popper <Popper
placement='bottom-start' placement='bottom-start'
eventsEnabled={isPostMenuOpen!} eventsEnabled={isPostMenuOpen!}
className={classNames({ [classes.popperClose]: !isPostMenuOpen! }, { [classes.popperOpen]: isPostMenuOpen! })} className={classNames({ [classes.popperClose]: !isPostMenuOpen }, { [classes.popperOpen]: isPostMenuOpen })}
> >
<ClickAwayListener onClickAway={this.closePostMenu}> <ClickAwayListener onClickAway={this.closePostMenu}>
<Grow in={isPostMenuOpen!} > <Grow in={isPostMenuOpen} >
<Paper> <Paper>
<MenuList role='menu'> <MenuList role='menu'>
<MenuItem onClick={this.handleOpenPostWrite} > {translate!('post.edit')} </MenuItem> <MenuItem onClick={this.handleOpenPostWrite} > {translate!('post.edit')} </MenuItem>
@@ -387,7 +387,7 @@ export class PostComponent extends Component<IPostComponentProps, IPostComponent
title={<NavLink to={`/${ownerUserId}`}>{ownerDisplayName}</NavLink>} title={<NavLink to={`/${ownerUserId}`}>{ownerDisplayName}</NavLink>}
subheader={moment.unix(creationDate!).fromNow() + ' | ' + translate!('post.public')} subheader={moment.unix(creationDate!).fromNow() + ' | ' + translate!('post.public')}
avatar={<NavLink to={`/${ownerUserId}`}><UserAvatar fullName={fullName!} fileName={avatar!} size={36} /></NavLink>} avatar={<NavLink to={`/${ownerUserId}`}><UserAvatar fullName={fullName!} fileName={avatar!} size={36} /></NavLink>}
action={isPostOwner ? <RightIconMenu /> : ''} action={isPostOwner ? rightIconMenu : ''}
> >
</CardHeader> </CardHeader>
{image ? ( {image ? (

View File

@@ -66,13 +66,4 @@ export class Comment extends BaseDomain {
*/ */
public userId?: string public userId?: string
/**
* Comment is in edit state {true} or not {false}
*
* @type {boolean}
* @memberof Comment
*/
// TODO: Should be changed to reuseable component and remove this property
editorStatus?: boolean
} }

View File

@@ -17,6 +17,11 @@ export class CommentState {
*/ */
postComments: {[postId: string]: {[commentId: string]: Comment}} = {} postComments: {[postId: string]: {[commentId: string]: Comment}} = {}
/**
* Whether comment editor is open
*/
editorStatus: {[postId: string]: {[commentId: string]: boolean}} = {}
/** /**
* If the comments are loaded {true} or not {false} * If the comments are loaded {true} or not {false}
* *

View File

@@ -85,28 +85,22 @@ export let commentReducer = (state: CommentState = new CommentState(), action: I
case CommentActionType.CLOSE_COMMENT_EDITOR: case CommentActionType.CLOSE_COMMENT_EDITOR:
return { return {
...state, ...state,
postComments: { editorStatus: {
...state.postComments, ...state.editorStatus,
[payload.postId]: { [payload.postId]: {
...state.postComments![payload.postId], ...state.editorStatus![payload.postId],
[payload.id]: { [payload.id]: false
...state.postComments![payload.postId][payload.id],
editorStatus: false
}
} }
} }
} }
case CommentActionType.OPEN_COMMENT_EDITOR: case CommentActionType.OPEN_COMMENT_EDITOR:
return { return {
...state, ...state,
postComments: { editorStatus: {
...state.postComments, ...state.editorStatus,
[payload.postId]: { [payload.postId]: {
...state.postComments![payload.postId], ...state.editorStatus![payload.postId],
[payload.id]: { [payload.id]: true
...state.postComments![payload.postId][payload.id],
editorStatus: true
}
} }
} }
} }