work on withList and queries generation

This commit is contained in:
xavcz 2016-11-19 20:01:17 +01:00
parent 4ac4c4cd06
commit 6c14712a74
16 changed files with 129 additions and 39 deletions

View file

@ -40,7 +40,7 @@ class Movie extends Component {
return ( return (
<div key={movie.name} style={{paddingBottom: "15px",marginBottom: "15px", borderBottom: "1px solid #ccc"}}> <div key={movie.name} style={{paddingBottom: "15px",marginBottom: "15px", borderBottom: "1px solid #ccc"}}>
<h2>{movie.name} ({movie.year})</h2> <h2>{movie.name} ({movie.year})</h2>
<p>{movie.review} by <strong>{movie.user && movie.user.username}</strong></p> <p>{movie.review} by <strong>{movie.user && movie.user.__displayName}</strong></p>
{this.renderEdit()} {this.renderEdit()}
</div> </div>
) )

View file

@ -6,6 +6,7 @@ import { Accounts } from 'meteor/std:accounts-ui';
import { ModalTrigger } from "meteor/nova:core"; import { ModalTrigger } from "meteor/nova:core";
import Movie from './Movie.jsx'; import Movie from './Movie.jsx';
import Movies from '../collection.js'; import Movies from '../collection.js';
import { compose } from 'react-apollo';
import { withCurrentUser, withList } from 'meteor/nova:core'; import { withCurrentUser, withList } from 'meteor/nova:core';
import { moviesListProps, moviesSingleProps } from '../containers/fragments.js'; import { moviesListProps, moviesSingleProps } from '../containers/fragments.js';
@ -60,4 +61,4 @@ const listOptions = {
fragmentName: 'moviesListProps', fragmentName: 'moviesListProps',
}; };
export default withList(listOptions)(withCurrentUser(MoviesList)); export default compose(withList(listOptions), withCurrentUser)(MoviesList);

View file

@ -11,6 +11,9 @@ const moviesListProps = createFragment(gql`
year year
review review
privateComments privateComments
user {
__displayName
}
} }
`) `)

View file

@ -2,11 +2,11 @@ import Telescope from 'meteor/nova:lib';
import mutations from './mutations.js'; import mutations from './mutations.js';
const resolvers = { const resolvers = {
// Movie: { Movie: {
// user(post, args, context) { user(movie, args, context) {
// return context.Users.findOne({ _id: post.userId }, { fields: context.getViewableFields(context.currentUser, context.Users) }); return context.Users.findOne({ _id: movie.userId }, { fields: context.getViewableFields(context.currentUser, context.Users) });
// }, },
// }, },
Query: { Query: {
moviesList(root, {offset, limit}, context, info) { moviesList(root, {offset, limit}, context, info) {
const protectedLimit = (limit < 1 || limit > 10) ? 10 : limit; const protectedLimit = (limit < 1 || limit > 10) ? 10 : limit;

View file

@ -2,11 +2,11 @@ import Telescope from 'meteor/nova:lib';
import React, { PropTypes, Component } from 'react'; import React, { PropTypes, Component } from 'react';
import { FormattedMessage } from 'react-intl'; import { FormattedMessage } from 'react-intl';
import { Button, DropdownButton, MenuItem, Modal } from 'react-bootstrap'; import { Button, DropdownButton, MenuItem, Modal } from 'react-bootstrap';
import { /* ModalTrigger, */ ContextPasser } from "meteor/nova:core"; import { /* ModalTrigger, */ ContextPasser, withList } from "meteor/nova:core";
import { withRouter } from 'react-router' import { withRouter } from 'react-router'
import { LinkContainer } from 'react-router-bootstrap'; import { LinkContainer } from 'react-router-bootstrap';
import Users from 'meteor/nova:users'; import Users from 'meteor/nova:users';
import { withCategoriesList } from 'meteor/nova:base-containers'; import Categories from 'meteor/nova:categories';
// note: cannot use ModalTrigger component because of https://github.com/react-bootstrap/react-bootstrap/issues/1808 // note: cannot use ModalTrigger component because of https://github.com/react-bootstrap/react-bootstrap/issues/1808
@ -152,4 +152,13 @@ CategoriesList.propTypes = {
results: React.PropTypes.array, results: React.PropTypes.array,
}; };
Telescope.registerComponent('CategoriesList', CategoriesList, withRouter, withCategoriesList); const categoriesListOptions = {
queryName: 'getCategoriesList',
collection: CategoriesList,
listResolverName: 'categoriesList',
totalResolverName: 'categoriesListTotal',
fragment: Categories.fragments.full,
fragmentName: 'fullCategoryInfo',
};
Telescope.registerComponent('CategoriesList', CategoriesList, withRouter, withList(categoriesListOptions));

View file

@ -18,14 +18,13 @@ const CategoriesNewForm = (props, context) => {
getCategoriesList: (prev, {mutationResult}) => { getCategoriesList: (prev, {mutationResult}) => {
const newCategory = mutationResult.data.categoriesNew; const newCategory = mutationResult.data.categoriesNew;
const newCategoriesList = update(prev, { const newCategoriesList = update(prev, {
categories: { categoriesList: {
$push: [newCategory] $push: [newCategory]
}, },
categoriesListTotal: { categoriesListTotal: {
$set: prev.categoriesListTotal + 1 $set: prev.categoriesListTotal + 1
}, },
}); });
// note: 'newCategoriesList' is extended with the category but somehow when the query updates it e
return newCategoriesList; return newCategoriesList;
}, },
}} }}

View file

@ -46,7 +46,7 @@ const CommentsNewForm = (props, context) => {
// console.log('[commentsNew] previous comment list', prev); // console.log('[commentsNew] previous comment list', prev);
const newComment = mutationResult.data.commentsNew; const newComment = mutationResult.data.commentsNew;
const newCommentsList = update(prev, { const newCommentsList = update(prev, {
comments: { commentsList: {
$push: [newComment] $push: [newComment]
}, },
commentsListTotal: { commentsListTotal: {

View file

@ -1,10 +1,8 @@
import Telescope from 'meteor/nova:lib'; import Telescope from 'meteor/nova:lib';
import React from 'react'; import React from 'react';
import {FormattedMessage } from 'react-intl'; import {FormattedMessage } from 'react-intl';
import { ModalTrigger, withCurrentUser } from 'meteor/nova:core'; import { ModalTrigger, withCurrentUser, withList } from 'meteor/nova:core';
import Comments from 'meteor/nova:comments'; import Comments from 'meteor/nova:comments';
import { withCommentsList } from 'meteor/nova:base-containers';
const PostsCommentsThread = (props, context) => { const PostsCommentsThread = (props, context) => {
@ -50,4 +48,16 @@ PostsCommentsThread.propTypes = {
currentUser: React.PropTypes.object currentUser: React.PropTypes.object
}; };
Telescope.registerComponent('PostsCommentsThread', PostsCommentsThread, withCurrentUser, withCommentsList); const commentsListOptions = {
queryName: 'getCommentsList',
collection: Comments,
listResolverName: 'commentsList',
totalResolverName: 'commentsListTotal',
fragment: Comments.fragments.full,
fragmentName: 'fullCommentInfo',
ownPropsVariables: [
{propName: 'postId', graphqlType: 'String', usedForTotal: true},
],
};
Telescope.registerComponent('PostsCommentsThread', PostsCommentsThread, withCurrentUser, withList(commentsListOptions));

View file

@ -1,6 +1,7 @@
import Telescope from 'meteor/nova:lib'; import Telescope from 'meteor/nova:lib';
import React from 'react'; import React from 'react';
import { withPostsList } from 'meteor/nova:base-containers'; import { withList } from 'meteor/nova:core';
import Posts from 'meteor/nova:posts';
const PostsList = (props) => { const PostsList = (props) => {
@ -54,4 +55,19 @@ PostsList.propTypes = {
showHeader: React.PropTypes.bool, showHeader: React.PropTypes.bool,
}; };
Telescope.registerComponent('PostsList', PostsList, withPostsList); const postsListOptions = {
queryName: 'getPostsList',
collection: Posts,
listResolverName: 'postsList',
totalResolverName: 'postsListTotal',
fragment: Posts.fragments.full,
fragmentName: 'fullPostInfo',
ownPropsVariables: [
// test note: can't overwrite atm
// {propName: 'limit', graphqlType: 'Int', defaultValue: 2, usedForTotal: false},
// note:give the list hoc the ability to catch props coming from upper in the component tree
{propName: 'terms', graphqlType: 'Terms', usedForTotal: true},
],
};
Telescope.registerComponent('PostsList', PostsList, withList(postsListOptions));

View file

@ -24,7 +24,7 @@ const PostsNewForm = (props, context) => {
getPostsList: (prev, { mutationResult }) => { getPostsList: (prev, { mutationResult }) => {
const newPost = mutationResult.data.postsNew; const newPost = mutationResult.data.postsNew;
const newList = update(prev, { const newList = update(prev, {
posts: { postsList: {
$unshift: [newPost], $unshift: [newPost],
}, },
postsListTotal: { postsListTotal: {

View file

@ -2,7 +2,7 @@ import Telescope from 'meteor/nova:lib';
import Categories from './collection.js'; import Categories from './collection.js';
Telescope.graphQL.addQuery(` Telescope.graphQL.addQuery(`
categories: [Category] categoriesList(offset: Int, limit: Int): [Category]
categoriesListTotal: Int categoriesListTotal: Int
category(_id: String): Category category(_id: String): Category
`); `);

View file

@ -13,7 +13,7 @@ export default resolvers = {
} }
}, },
Query: { Query: {
categories(root, args, context) { categoriesList(root, args, context) {
const options = { const options = {
fields: context.getViewableFields(context.currentUser, context.Categories) fields: context.getViewableFields(context.currentUser, context.Categories)
}; };

View file

@ -3,7 +3,7 @@ import Comments from './collection.js';
// declare comments queries // declare comments queries
Telescope.graphQL.addQuery(` Telescope.graphQL.addQuery(`
comments(postId: String): [Comment] commentsList(postId: String, offset: Int, limit: Int): [Comment]
commentsListTotal(postId: String): Int commentsListTotal(postId: String): Int
comment(_id: String): Comment comment(_id: String): Comment
`); `);

View file

@ -31,11 +31,13 @@ const resolvers = {
}, },
}, },
Query: { Query: {
comments(root, {postId}, context) { commentsList(root, {postId, offset, limit}, context) {
const options = { const options = {
// limit: 5, // no limit for now limit: (limit < 1 || limit > 10) ? 10 : limit,
skip: offset,
fields: context.getViewableFields(context.currentUser, context.Comments) fields: context.getViewableFields(context.currentUser, context.Comments)
} };
return context.Comments.find({postId: postId}, options).fetch(); return context.Comments.find({postId: postId}, options).fetch();
}, },
commentsListTotal(root, {postId}, context) { commentsListTotal(root, {postId}, context) {

View file

@ -5,27 +5,77 @@ import gql from 'graphql-tag';
export default function withList (options) { export default function withList (options) {
console.log("withList") // extract arguments from the options of the hoc
console.log(options) const { queryName, collection, listResolverName, totalResolverName, fragment, fragmentName, ownPropsVariables = [] } = options;
console.log("withList: ", queryName);
// console.log(options);
const { queryName, collection, listResolverName, totalResolverName, fragment, fragmentName } = options; // default variables for the gql query list
const defaultQueryVariables = [
{propName: 'offset', graphqlType: 'Int', defaultValue: 0, usedForTotal: false},
{propName: 'limit', graphqlType: 'Int', defaultValue: 5, usedForTotal: false},
];
// concat the default query variables with the ones from the props of the wrapped component
const propsVariables = [...defaultQueryVariables, ...ownPropsVariables];
console.log('props variables (default+ownProps)', propsVariables);
// output something like: `$offset: Int, $limit: Int, $terms: Terms`
const queryVariablesTypeDef = propsVariables.reduce((string, {propName, graphqlType}, index) => {
// don't add ", " if the current typeDef is the first iteration
const commaSeparation = index === 0 ? "" : ", ";
return `${string}${commaSeparation}$${propName}: ${graphqlType}`;
}, "");
console.log('query variables type def', queryVariablesTypeDef);
// output something like: `offset: $offset, limit: $limit, terms: $terms`
const queryVariablesList = propsVariables.reduce((string, {propName}, index) => {
// don't add ", " if the current typeDef is the first iteration
const commaSeparation = index === 0 ? "" : ", ";
return `${string}${commaSeparation}${propName}: $${propName}`;
}, "");
console.log('query variables list', queryVariablesList);
// output something like: `terms: $terms`
const queryVariablesTotal = propsVariables.filter(({usedForTotal}) => !!usedForTotal).reduce((string, {propName}, index) => {
// don't add ", " if the current typeDef is the first iteration
const commaSeparation = index === 0 ? "" : ", ";
return `${string}${commaSeparation}${propName}: $${propName}`;
}, "");
console.log('query variables total', queryVariablesTotal);
const callQueryVariablesTotal = !!queryVariablesTotal ? `(${queryVariablesTotal})` : "";
return graphql(gql` return graphql(gql`
query ${queryName}($offset: Int, $limit: Int) { query ${queryName}(${queryVariablesTypeDef}) {
${totalResolverName} ${totalResolverName}${callQueryVariablesTotal}
${listResolverName}(offset: $offset, limit: $limit) { ${listResolverName}(${queryVariablesList}) {
...${fragmentName} ...${fragmentName}
} }
} }
`, { `, {
options(ownProps) { options(ownProps) {
const queryVariables = propsVariables.reduce((variables, {propName, defaultValue}) => ({
...variables,
[propName]: ownProps[propName] || defaultValue
}), {});
console.log('actual query variables', queryVariables);
return { return {
variables: { variables: queryVariables,
offset: 0,
limit: 5
},
fragments: fragment, fragments: fragment,
pollInterval: 20000, // pollInterval: 20000,
}; };
}, },
props(props) { props(props) {

View file

@ -14,7 +14,7 @@ export default resolvers = {
}, },
}, },
Query: { Query: {
posts(root, {terms, offset, limit}, context, info) { postsList(root, {terms, offset, limit}, context, info) {
// console.log("// context") // console.log("// context")
// console.log(context) // console.log(context)
let {selector, options} = context.Posts.parameters.get(terms); let {selector, options} = context.Posts.parameters.get(terms);
@ -40,7 +40,7 @@ export default resolvers = {
Telescope.graphQL.addResolvers(resolvers); Telescope.graphQL.addResolvers(resolvers);
Telescope.graphQL.addQuery(` Telescope.graphQL.addQuery(`
posts(terms: Terms, offset: Int, limit: Int): [Post] postsList(terms: Terms, offset: Int, limit: Int): [Post]
postsListTotal(terms: Terms): Int postsListTotal(terms: Terms): Int
post(_id: String): Post post(_id: String): Post
`); `);