fix #1541: increasePostViewCount mutation + associated resolver; store posts viewed on the client session on postsViewed in the redux store; document PostsPage HOC & lifecycle hook

This commit is contained in:
xavcz 2017-02-01 16:37:06 +01:00
parent 4810947eea
commit 08c171ed64
5 changed files with 119 additions and 28 deletions

View file

@ -1,44 +1,104 @@
import { Components, registerComponent, withDocument, withCurrentUser } from 'meteor/nova:core';
import React from 'react';
import { Components, registerComponent, withDocument, withCurrentUser, getActions, withMutation } from 'meteor/nova:core';
import Posts from 'meteor/nova:posts';
import React, { Component, PropTypes } from 'react';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
const PostsPage = (props) => {
class PostsPage extends Component {
render() {
if (this.props.loading) {
return <div className="posts-page"><Components.Loading/></div>
} else {
const post = this.props.document;
if (props.loading) {
const htmlBody = {__html: post.htmlBody};
return <div className="posts-page"><Components.Loading/></div>
return (
<div className="posts-page">
<Components.HeadTags url={Posts.getLink(post)} title={post.title} image={post.thumbnailUrl} description={post.excerpt} />
<Components.PostsItem post={post} currentUser={this.props.currentUser} />
} else {
{post.htmlBody ? <div className="posts-page-body" dangerouslySetInnerHTML={htmlBody}></div> : null}
const post = props.document;
<Components.PostsCommentsThread terms={{postId: post._id}} />
const htmlBody = {__html: post.htmlBody};
return (
<div className="posts-page">
<Components.HeadTags url={Posts.getLink(post)} title={post.title} image={post.thumbnailUrl} description={post.excerpt} />
<Components.PostsItem post={post} currentUser={props.currentUser} />
{post.htmlBody ? <div className="posts-page-body" dangerouslySetInnerHTML={htmlBody}></div> : null}
<Components.PostsCommentsThread terms={{postId: post._id}} />
</div>
)
</div>
);
}
}
};
// triggered after the component did mount on the client
async componentDidMount() {
try {
// destructure the relevant props
const {
// from the parent component, used in withDocument, GraphQL HOC
documentId,
// from connect, Redux HOC
setViewed,
postsViewed,
// from withMutation, GraphQL HOC
increasePostViewCount,
} = this.props;
// a post id has been found & it's has not been seen yet on this client session
if (documentId && !postsViewed.includes(documentId)) {
// trigger the asynchronous mutation with postId as an argument
await increasePostViewCount({postId: documentId});
// once the mutation is done, update the redux store
setViewed(documentId);
}
} catch(error) {
console.log(error); // eslint-disable-line
}
}
}
PostsPage.displayName = "PostsPage";
PostsPage.propTypes = {
document: React.PropTypes.object
documentId: PropTypes.string,
document: PropTypes.object,
postsViewed: PropTypes.array,
setViewed: PropTypes.func,
increasePostViewCount: PropTypes.func,
}
const options = {
const queryOptions = {
collection: Posts,
queryName: 'postsSingleQuery',
fragmentName: 'PostsPage',
};
registerComponent('PostsPage', PostsPage, withCurrentUser, [withDocument, options]);
const mutationOptions = {
name: 'increasePostViewCount',
args: {postId: 'String'},
};
const mapStateToProps = state => ({ postsViewed: state.postsViewed });
const mapDispatchToProps = dispatch => bindActionCreators(getActions().postsViewed, dispatch);
registerComponent(
// component name used by Nova
'PostsPage',
// React component
PostsPage,
// HOC to give access to the current user
withCurrentUser,
// HOC to load the data of the document, based on queryOptions & a documentId props
[withDocument, queryOptions],
// HOC to provide a single mutation, based on mutationOptions
withMutation(mutationOptions),
// HOC to give access to the redux store & related actions
connect(mapStateToProps, mapDispatchToProps)
);

View file

@ -13,5 +13,6 @@ import './emails.js';
import './permissions.js';
import './resolvers.js';
import './mutations.js';
import './redux.js';
export default Posts;
export default Posts;

View file

@ -1,4 +1,4 @@
import { newMutation, editMutation, removeMutation } from 'meteor/nova:core';
import { newMutation, editMutation, removeMutation, GraphQLSchema } from 'meteor/nova:core';
import Users from 'meteor/nova:users';
const performCheck = (mutation, user, document) => {
@ -85,4 +85,6 @@ const mutations = {
};
export default mutations;
GraphQLSchema.addMutation('increasePostViewCount(postId: String): Float');
export default mutations;

View file

@ -0,0 +1,23 @@
import { addAction, addReducer } from 'meteor/nova:core';
addAction({
postsViewed: {
setViewed: (postId) => ({
type: 'SET_VIEWED',
postId,
}),
},
});
addReducer({
postsViewed: (state = [], action) => {
if (action.type === 'SET_VIEWED') {
return [
...state,
action.postId,
];
}
return state;
},
});

View file

@ -6,6 +6,11 @@ const specificResolvers = {
return context.Users.findOne({ _id: post.userId }, { fields: context.getViewableFields(context.currentUser, context.Users) });
},
},
Mutation: {
increasePostViewCount(root, { postId }, context) {
return context.Posts.update({_id: postId}, { $inc: { viewCount: 1 }});
}
}
};
GraphQLSchema.addResolvers(specificResolvers);