working on comments mutations

This commit is contained in:
Sacha Greif 2016-11-05 18:37:46 +09:00
parent 5372aace33
commit a0a7d235e9
17 changed files with 228 additions and 54 deletions

View file

@ -75,7 +75,8 @@ class CommentsItem extends Component{
return (
<div className="comments-item-reply">
<Telescope.components.CommentsNew
<Telescope.components.CommentsNewFormContainer
component={Telescope.components.CommentsNewForm}
postId={this.props.comment.postId}
parentComment={this.props.comment}
successCallback={this.replySuccessCallback}

View file

@ -2,7 +2,7 @@ import React, { PropTypes, Component } from 'react';
import NovaForm from "meteor/nova:forms";
import Comments from "meteor/nova:comments";
class CommentsNew extends Component {
class CommentsNewForm extends Component {
render() {
@ -20,7 +20,7 @@ class CommentsNew extends Component {
<div className="comments-new-form">
<NovaForm
collection={Comments}
methodName="comments.new"
novaFormMutation={props.novaFormMutation}
prefilledProps={prefilledProps}
//successCallback={this.props.successCallback}
layout="elementOnly"
@ -32,18 +32,21 @@ class CommentsNew extends Component {
};
CommentsNew.propTypes = {
CommentsNewForm.propTypes = {
postId: React.PropTypes.string.isRequired,
type: React.PropTypes.string, // "comment" or "reply"
parentComment: React.PropTypes.object, // if reply, the comment being replied to
parentCommentId: React.PropTypes.string, // if reply
topLevelCommentId: React.PropTypes.string, // if reply
successCallback: React.PropTypes.func, // a callback to execute when the submission has been successful
cancelCallback: React.PropTypes.func
cancelCallback: React.PropTypes.func,
novaFormMutation: React.PropTypes.func,
router: React.PropTypes.object,
flash: React.PropTypes.object,
}
CommentsNew.contextTypes = {
CommentsNewForm.contextTypes = {
currentUser: React.PropTypes.object
}
module.exports = CommentsNew;
module.exports = CommentsNewForm;

View file

@ -49,8 +49,8 @@ Telescope.registerComponent("PostsCommentsThread", require('./posts/Posts
Telescope.registerComponent("CommentsItem", require('./comments/CommentsItem.jsx'));
Telescope.registerComponent("CommentsList", require('./comments/CommentsList.jsx'));
Telescope.registerComponent("CommentsNode", require('./comments/CommentsNode.jsx'));
Telescope.registerComponent("CommentsNew", require('./comments/CommentsNew.jsx'));
Telescope.registerComponent("CommentsEdit", require('./comments/CommentsEdit.jsx'));
Telescope.registerComponent("CommentsNewForm", require('./comments/CommentsNewForm.jsx'));
Telescope.registerComponent("CommentsEditForm", require('./comments/CommentsEditForm.jsx'));
Telescope.registerComponent("CommentsLoadMore", require('./comments/CommentsLoadMore.jsx'));
// categories
@ -86,3 +86,5 @@ Telescope.registerComponent("PostsNewFormContainer", require('./containers/Pos
Telescope.registerComponent("PostsEditFormContainer", require('./containers/PostsEditFormContainer.jsx'));
Telescope.registerComponent("UsersSingleContainer", require('./containers/UsersSingleContainer.jsx'));
Telescope.registerComponent("VoteContainer", require('./containers/VoteContainer.jsx'));
Telescope.registerComponent("CommentsNewFormContainer", require('./containers/CommentsNewFormContainer.jsx'));
Telescope.registerComponent("CommentsEditFormContainer", require('./containers/CommentsEditFormContainer.jsx'));

View file

@ -0,0 +1,50 @@
import Telescope from 'meteor/nova:lib';
import React, { PropTypes, Component } from 'react';
import { FormattedMessage, intlShape } from 'react-intl';
import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';
import { withRouter } from 'react-router'
import { graphql } from 'react-apollo';
import gql from 'graphql-tag';
const CommentsEditFormContainer = (props, context) => {
const Component = props.component;
return <Component post={props.post} flash={props.flash} novaFormMutation={props.novaFormMutation} router={props.router} />;
};
CommentsEditFormContainer.propTypes = {
flash: React.PropTypes.func,
novaFormMutation: React.PropTypes.func,
post: React.PropTypes.object.isRequired,
router: React.PropTypes.object,
};
const mapStateToProps = state => ({ messages: state.messages, });
const mapDispatchToProps = dispatch => bindActionCreators(Telescope.actions.messages, dispatch);
const CommentsEditFormContainerWithMutation = graphql(gql`
mutation commentsEdit($commentId: String, $set: CommentInput, $unset: CommentUnsetModifier) {
commentsEdit(commentId: $commentId, set: $set, unset: $unset) {
_id
}
}
`, {
props: ({ownProps, mutate}) => ({
novaFormMutation: ({documentId, set, unset}) => {
return mutate({
variables: {postId: documentId, set, unset},
// optimisticResponse: {
// __typename: 'Mutation',
// postsEdit: {
// __typename: 'Post',
// ...set
// }
// },
})
}
}),
})(CommentsEditFormContainer);
module.exports = withRouter(connect(mapStateToProps, mapDispatchToProps)(CommentsEditFormContainerWithMutation));

View file

@ -0,0 +1,80 @@
import Telescope from 'meteor/nova:lib';
import React, { PropTypes, Component } from 'react';
import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';
import NovaForm from "meteor/nova:forms";
import { withRouter } from 'react-router'
import { graphql } from 'react-apollo';
import gql from 'graphql-tag';
import update from 'immutability-helper';
const CommentsNewFormContainer = (props, context) => {
const Component = props.component;
return <Component router={props.router} novaFormMutation={props.novaFormMutation} flash={props.flash} {...props} />
}
CommentsNewFormContainer.propTypes = {
router: React.PropTypes.object,
novaFormMutation: React.PropTypes.func,
component: React.PropTypes.func,
postId: React.PropTypes.string.isRequired,
type: React.PropTypes.string, // "comment" or "reply"
parentComment: React.PropTypes.object, // if reply, the comment being replied to
parentCommentId: React.PropTypes.string, // if reply
topLevelCommentId: React.PropTypes.string, // if reply
successCallback: React.PropTypes.func, // a callback to execute when the submission has been successful
cancelCallback: React.PropTypes.func,
};
CommentsNewFormContainer.displayName = "CommentsNewFormContainer";
const mapStateToProps = state => ({ messages: state.messages });
const mapDispatchToProps = dispatch => bindActionCreators(Telescope.actions.messages, dispatch);
const CommentsNewFormContainerWithMutation = graphql(gql`
mutation commentsNew($comment: CommentInput) {
commentsNew(comment: $comment) {
_id
}
}
`, {
props: ({ownProps, mutate}) => ({
novaFormMutation: ({document}) => {
// const optimisticResponseItem = {
// ...document,
// title: "optimisitc!",
// __typename: 'Post',
// id: 123,
// slug: 'foo'
// }
// console.log(document)
// console.log(optimisticResponseItem)
return mutate({
variables: {post: document},
// optimisticResponse: {
// __typename: 'Mutation',
// postsNew: optimisticResponseItem,
// },
updateQueries: {
getPostsView: (prev, { mutationResult }) => {
const newPost = mutationResult.data.postsNew;
const newList = update(prev, {
posts: {
$unshift: [newPost],
},
postsViewTotal: {
$set: prev.postsViewTotal + 1
}
});
return newList;
},
}
})
}
}),
})(CommentsNewFormContainer);
module.exports = withRouter(connect(mapStateToProps, mapDispatchToProps)(CommentsNewFormContainerWithMutation));

View file

@ -25,7 +25,7 @@ const mapStateToProps = state => ({ messages: state.messages, });
const mapDispatchToProps = dispatch => bindActionCreators(Telescope.actions.messages, dispatch);
const PostsEditFormContainerWithMutation = graphql(gql`
mutation postsEdit($postId: String, $set: PostSetModifier, $unset: PostUnsetModifier) {
mutation postsEdit($postId: String, $set: PostInput, $unset: PostUnsetModifier) {
postsEdit(postId: $postId, set: $set, unset: $unset) {
_id
title
@ -91,12 +91,15 @@ const PostsEditFormContainerWithMutation = graphql(gql`
`, {
props: ({ownProps, mutate}) => ({
novaFormMutation: ({documentId, set, unset}) => {
console.log("novaFormMutation")
console.log(documentId)
console.log(set)
console.log(unset)
return mutate({
variables: {postId: documentId, set, unset}
variables: {postId: documentId, set, unset},
// optimisticResponse: {
// __typename: 'Mutation',
// postsEdit: {
// __typename: 'Post',
// ...set
// }
// },
})
}
}),

View file

@ -15,9 +15,6 @@ class PostsSingleContainer extends Component {
render() {
console.log("// PostsSingleContainer")
console.log(this.props.data)
const {loading, post, refetch} = this.props.data;
const Component = this.props.component

View file

@ -15,7 +15,11 @@ const PostsCommentsThread = ({document, refetchQuery}, {currentUser}) => {
{ currentUser ?
<div className="posts-comments-thread-new">
<h4><FormattedMessage id="comments.new"/></h4>
<Telescope.components.CommentsNew type="comment" postId={post._id} successCallback={refetchQuery} />
<Telescope.components.CommentsNewFormContainer
component={Telescope.components.CommentsNewForm}
postId={post._id}
type="comment"
/>
</div> :
<div>
<ModalTrigger size="small" component={<a><FormattedMessage id="comments.please_log_in"/></a>}>

View file

@ -25,6 +25,12 @@ const PostsNewForm = (props, context) => {
);
};
PostsNewForm.propTypes = {
novaFormMutation: React.PropTypes.func,
router: React.PropTypes.object,
flash: React.PropTypes.object,
}
PostsNewForm.contextTypes = {
currentUser: React.PropTypes.object,
triggerMainRefetch: React.PropTypes.func,

View file

@ -12,5 +12,6 @@ import './emails.js';
import './published_fields.js';
import './permissions.js';
import './resolvers.js';
import './mutations.js';
export default Comments;

View file

@ -0,0 +1,39 @@
import Telescope from 'meteor/nova:lib';
import Comments from './collection.js'
import Users from 'meteor/nova:users';
import Events from "meteor/nova:events";
/**
*
* Post Methods (and Mutations)
*
*/
// define GraphQL mutations
Telescope.graphQL.addMutation('commentsNew(comment: CommentInput) : Comment');
Telescope.graphQL.addMutation('commentsEdit(commentId: String, set: CommentInput, unset: CommentUnsetModifier) : Comment');
Telescope.graphQL.addMutation('commentsVote(commentId: String, voteType: String) : Comment');
// resolvers
Comments.mutations = {
commentsNew(root, {comment}, context) {
},
commentsEdit(root, {commentId, set, unset}, context) {
},
commentsVote(root, {commentId, voteType}, context) {
},
};
export default Comments.mutations;

View file

@ -1,4 +1,5 @@
import Telescope from 'meteor/nova:lib';
import mutations from './mutations.js';
const resolvers = {
Post: {
@ -40,7 +41,8 @@ const resolvers = {
comment(root, args, context) {
return context.Comments.findOne({_id: args._id}, { fields: context.getViewableFields(context.currentUser, Comments) });
},
}
},
Mutation: mutations
};
Telescope.graphQL.addResolvers(resolvers);

View file

@ -204,7 +204,19 @@ Comments.graphQLSchema = `
baseScore: Int
score: Float
}
`
input CommentInput {
parentCommentId: String
topLevelCommentId: String
body: String!
}
input CommentUnsetModifier {
parentCommentId: Boolean
topLevelCommentId: Boolean
body: Boolean
}
`;
Telescope.graphQL.addSchema(Comments.graphQLSchema);

View file

@ -12,7 +12,7 @@ import Events from "meteor/nova:events";
// define GraphQL mutations
Telescope.graphQL.addMutation('postsNew(post: PostInput) : Post');
Telescope.graphQL.addMutation('postsEdit(postId: String, set: PostSetModifier, unset: PostUnsetModifier) : Post');
Telescope.graphQL.addMutation('postsEdit(postId: String, set: PostInput, unset: PostUnsetModifier) : Post');
Telescope.graphQL.addMutation('postsVote(postId: String, voteType: String) : Post');
// resolvers
@ -44,12 +44,7 @@ Posts.mutations = {
},
postsEdit(root, parameters, context) {
console.log("// postsEdit")
console.log(parameters)
let {postId, set, unset} = parameters;
postsEdit(root, {postId, set, unset}, context) {
let modifier = {$set: set, $unset: unset};

View file

@ -4,13 +4,13 @@ import mutations from './mutations.js';
const resolvers = {
Post: {
user(post, args, context) {
return context.Users.findOne({ _id: post.userId }, { fields: context.getViewableFields(context.currentUser, Users) });
return context.Users.findOne({ _id: post.userId }, { fields: context.getViewableFields(context.currentUser, context.Users) });
},
upvoters(post, args, context) {
return post.upvoters ? context.Users.find({_id: {$in: post.upvoters}}, { fields: context.getViewableFields(context.currentUser, Users) }).fetch() : [];
return post.upvoters ? context.Users.find({_id: {$in: post.upvoters}}, { fields: context.getViewableFields(context.currentUser, context.Users) }).fetch() : [];
},
downvoters(post, args, context) {
return post.downvoters ? context.Users.find({_id: {$in: post.downvoters}}, { fields: context.getViewableFields(context.currentUser, Users) }).fetch() : [];
return post.downvoters ? context.Users.find({_id: {$in: post.downvoters}}, { fields: context.getViewableFields(context.currentUser, context.Users) }).fetch() : [];
},
},
Query: {
@ -22,7 +22,7 @@ const resolvers = {
options.limit = protectedLimit;
options.skip = offset;
// keep only fields that should be viewable by current user
options.fields = context.getViewableFields(context.currentUser, Posts);
options.fields = context.getViewableFields(context.currentUser, context.Posts);
return context.Posts.find(selector, options).fetch();
},
postsViewTotal(root, {terms}, context) {
@ -31,18 +31,10 @@ const resolvers = {
},
post(root, args, context) {
// Meteor._sleepForMs(10000); // wait 2 seconds
return context.Posts.findOne({_id: args._id}, { fields: context.getViewableFields(context.currentUser, Posts) });
return context.Posts.findOne({_id: args._id}, { fields: context.getViewableFields(context.currentUser, context.Posts) });
},
},
Mutation: mutations
// Mutation: {
// postVote(root, {postId, voteType}, context) {
// Meteor._sleepForMs(2000); // wait 2 seconds for demonstration purpose
// console.log("sleep done");
// const post = Posts.findOne(postId);
// return context.Users.canDo(context.currentUser, `posts.${voteType}`) ? Telescope.operateOnItem(context.Posts, post, context.currentUser, voteType) : false;
// },
// }
};
Telescope.graphQL.addResolvers(resolvers);

View file

@ -336,19 +336,6 @@ Posts.graphQLSchema = `
thumbnailUrl: String
}
input PostSetModifier {
postedAt: String
url: String
title: String
slug: String
body: String
sticky: Boolean
status: Int
categories: [String]
scheduledAt: String
thumbnailUrl: String
}
input PostUnsetModifier {
postedAt: Boolean
url: Boolean