mirror of
https://github.com/vale981/Vulcan
synced 2025-03-08 19:11:38 -05:00
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:
parent
4810947eea
commit
08c171ed64
5 changed files with 119 additions and 28 deletions
|
@ -1,44 +1,104 @@
|
||||||
import { Components, registerComponent, withDocument, withCurrentUser } from 'meteor/nova:core';
|
import { Components, registerComponent, withDocument, withCurrentUser, getActions, withMutation } from 'meteor/nova:core';
|
||||||
import React from 'react';
|
|
||||||
import Posts from 'meteor/nova:posts';
|
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};
|
</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={props.currentUser} />
|
|
||||||
|
|
||||||
{post.htmlBody ? <div className="posts-page-body" dangerouslySetInnerHTML={htmlBody}></div> : null}
|
|
||||||
|
|
||||||
<Components.PostsCommentsThread terms={{postId: post._id}} />
|
|
||||||
|
|
||||||
</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.displayName = "PostsPage";
|
||||||
|
|
||||||
PostsPage.propTypes = {
|
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,
|
collection: Posts,
|
||||||
queryName: 'postsSingleQuery',
|
queryName: 'postsSingleQuery',
|
||||||
fragmentName: 'PostsPage',
|
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)
|
||||||
|
);
|
||||||
|
|
|
@ -13,5 +13,6 @@ import './emails.js';
|
||||||
import './permissions.js';
|
import './permissions.js';
|
||||||
import './resolvers.js';
|
import './resolvers.js';
|
||||||
import './mutations.js';
|
import './mutations.js';
|
||||||
|
import './redux.js';
|
||||||
|
|
||||||
export default Posts;
|
export default Posts;
|
||||||
|
|
|
@ -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';
|
import Users from 'meteor/nova:users';
|
||||||
|
|
||||||
const performCheck = (mutation, user, document) => {
|
const performCheck = (mutation, user, document) => {
|
||||||
|
@ -85,4 +85,6 @@ const mutations = {
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default mutations;
|
GraphQLSchema.addMutation('increasePostViewCount(postId: String): Float');
|
||||||
|
|
||||||
|
export default mutations;
|
||||||
|
|
23
packages/nova-posts/lib/redux.js
Normal file
23
packages/nova-posts/lib/redux.js
Normal 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;
|
||||||
|
},
|
||||||
|
});
|
|
@ -6,6 +6,11 @@ const specificResolvers = {
|
||||||
return context.Users.findOne({ _id: post.userId }, { fields: context.getViewableFields(context.currentUser, context.Users) });
|
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);
|
GraphQLSchema.addResolvers(specificResolvers);
|
||||||
|
|
Loading…
Add table
Reference in a new issue