diff --git a/packages/custom-collection-demo/lib/components/Movie.jsx b/packages/custom-collection-demo/lib/components/Movie.jsx index 9d1af0629..82ca1496e 100644 --- a/packages/custom-collection-demo/lib/components/Movie.jsx +++ b/packages/custom-collection-demo/lib/components/Movie.jsx @@ -40,7 +40,7 @@ class Movie extends Component { return (

{movie.name} ({movie.year})

-

{movie.review} – by {movie.user && movie.user.username}

+

{movie.review} – by {movie.user && movie.user.__displayName}

{this.renderEdit()}
) diff --git a/packages/custom-collection-demo/lib/components/MoviesList.jsx b/packages/custom-collection-demo/lib/components/MoviesList.jsx index 8b952dd77..4b39306b6 100644 --- a/packages/custom-collection-demo/lib/components/MoviesList.jsx +++ b/packages/custom-collection-demo/lib/components/MoviesList.jsx @@ -6,6 +6,7 @@ import { Accounts } from 'meteor/std:accounts-ui'; import { ModalTrigger } from "meteor/nova:core"; import Movie from './Movie.jsx'; import Movies from '../collection.js'; +import { compose } from 'react-apollo'; import { withCurrentUser, withList } from 'meteor/nova:core'; import { moviesListProps, moviesSingleProps } from '../containers/fragments.js'; @@ -60,4 +61,4 @@ const listOptions = { fragmentName: 'moviesListProps', }; -export default withList(listOptions)(withCurrentUser(MoviesList)); +export default compose(withList(listOptions), withCurrentUser)(MoviesList); diff --git a/packages/custom-collection-demo/lib/containers/fragments.js b/packages/custom-collection-demo/lib/containers/fragments.js index 2197ee698..de3ff5daf 100644 --- a/packages/custom-collection-demo/lib/containers/fragments.js +++ b/packages/custom-collection-demo/lib/containers/fragments.js @@ -11,6 +11,9 @@ const moviesListProps = createFragment(gql` year review privateComments + user { + __displayName + } } `) diff --git a/packages/custom-collection-demo/lib/resolvers.js b/packages/custom-collection-demo/lib/resolvers.js index 88ea653ab..e2f26acf3 100644 --- a/packages/custom-collection-demo/lib/resolvers.js +++ b/packages/custom-collection-demo/lib/resolvers.js @@ -2,11 +2,11 @@ import Telescope from 'meteor/nova:lib'; import mutations from './mutations.js'; const resolvers = { - // Movie: { - // user(post, args, context) { - // return context.Users.findOne({ _id: post.userId }, { fields: context.getViewableFields(context.currentUser, context.Users) }); - // }, - // }, + Movie: { + user(movie, args, context) { + return context.Users.findOne({ _id: movie.userId }, { fields: context.getViewableFields(context.currentUser, context.Users) }); + }, + }, Query: { moviesList(root, {offset, limit}, context, info) { const protectedLimit = (limit < 1 || limit > 10) ? 10 : limit; diff --git a/packages/nova-base-components/lib/categories/CategoriesList.jsx b/packages/nova-base-components/lib/categories/CategoriesList.jsx index 58b97ba64..88f34b2d8 100644 --- a/packages/nova-base-components/lib/categories/CategoriesList.jsx +++ b/packages/nova-base-components/lib/categories/CategoriesList.jsx @@ -2,11 +2,11 @@ import Telescope from 'meteor/nova:lib'; import React, { PropTypes, Component } from 'react'; import { FormattedMessage } from 'react-intl'; 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 { LinkContainer } from 'react-router-bootstrap'; 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 @@ -152,4 +152,13 @@ CategoriesList.propTypes = { results: React.PropTypes.array, }; -Telescope.registerComponent('CategoriesList', CategoriesList, withRouter, withCategoriesList); \ No newline at end of file +const categoriesListOptions = { + queryName: 'getCategoriesList', + collection: CategoriesList, + listResolverName: 'categoriesList', + totalResolverName: 'categoriesListTotal', + fragment: Categories.fragments.full, + fragmentName: 'fullCategoryInfo', +}; + +Telescope.registerComponent('CategoriesList', CategoriesList, withRouter, withList(categoriesListOptions)); \ No newline at end of file diff --git a/packages/nova-base-components/lib/categories/CategoriesNewForm.jsx b/packages/nova-base-components/lib/categories/CategoriesNewForm.jsx index 85c114469..6dd66b74a 100644 --- a/packages/nova-base-components/lib/categories/CategoriesNewForm.jsx +++ b/packages/nova-base-components/lib/categories/CategoriesNewForm.jsx @@ -18,14 +18,13 @@ const CategoriesNewForm = (props, context) => { getCategoriesList: (prev, {mutationResult}) => { const newCategory = mutationResult.data.categoriesNew; const newCategoriesList = update(prev, { - categories: { + categoriesList: { $push: [newCategory] }, categoriesListTotal: { $set: prev.categoriesListTotal + 1 }, }); - // note: 'newCategoriesList' is extended with the category but somehow when the query updates it e return newCategoriesList; }, }} diff --git a/packages/nova-base-components/lib/comments/CommentsNewForm.jsx b/packages/nova-base-components/lib/comments/CommentsNewForm.jsx index 25105444b..076b508fb 100644 --- a/packages/nova-base-components/lib/comments/CommentsNewForm.jsx +++ b/packages/nova-base-components/lib/comments/CommentsNewForm.jsx @@ -46,7 +46,7 @@ const CommentsNewForm = (props, context) => { // console.log('[commentsNew] previous comment list', prev); const newComment = mutationResult.data.commentsNew; const newCommentsList = update(prev, { - comments: { + commentsList: { $push: [newComment] }, commentsListTotal: { diff --git a/packages/nova-base-components/lib/posts/PostsCommentsThread.jsx b/packages/nova-base-components/lib/posts/PostsCommentsThread.jsx index 75ed0557f..859604a98 100644 --- a/packages/nova-base-components/lib/posts/PostsCommentsThread.jsx +++ b/packages/nova-base-components/lib/posts/PostsCommentsThread.jsx @@ -1,10 +1,8 @@ import Telescope from 'meteor/nova:lib'; import React from 'react'; 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 { withCommentsList } from 'meteor/nova:base-containers'; - const PostsCommentsThread = (props, context) => { @@ -50,4 +48,16 @@ PostsCommentsThread.propTypes = { 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)); diff --git a/packages/nova-base-components/lib/posts/PostsList.jsx b/packages/nova-base-components/lib/posts/PostsList.jsx index f5d842205..9540bc610 100644 --- a/packages/nova-base-components/lib/posts/PostsList.jsx +++ b/packages/nova-base-components/lib/posts/PostsList.jsx @@ -1,6 +1,7 @@ import Telescope from 'meteor/nova:lib'; 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) => { @@ -54,4 +55,19 @@ PostsList.propTypes = { 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)); diff --git a/packages/nova-base-components/lib/posts/PostsNewForm.jsx b/packages/nova-base-components/lib/posts/PostsNewForm.jsx index cea7b0666..2b432fe1f 100644 --- a/packages/nova-base-components/lib/posts/PostsNewForm.jsx +++ b/packages/nova-base-components/lib/posts/PostsNewForm.jsx @@ -24,7 +24,7 @@ const PostsNewForm = (props, context) => { getPostsList: (prev, { mutationResult }) => { const newPost = mutationResult.data.postsNew; const newList = update(prev, { - posts: { + postsList: { $unshift: [newPost], }, postsListTotal: { diff --git a/packages/nova-categories/lib/queries.js b/packages/nova-categories/lib/queries.js index 152c32c22..b992e3129 100644 --- a/packages/nova-categories/lib/queries.js +++ b/packages/nova-categories/lib/queries.js @@ -2,7 +2,7 @@ import Telescope from 'meteor/nova:lib'; import Categories from './collection.js'; Telescope.graphQL.addQuery(` - categories: [Category] + categoriesList(offset: Int, limit: Int): [Category] categoriesListTotal: Int category(_id: String): Category `); \ No newline at end of file diff --git a/packages/nova-categories/lib/resolvers.js b/packages/nova-categories/lib/resolvers.js index d860655f1..63ef996fd 100644 --- a/packages/nova-categories/lib/resolvers.js +++ b/packages/nova-categories/lib/resolvers.js @@ -13,7 +13,7 @@ export default resolvers = { } }, Query: { - categories(root, args, context) { + categoriesList(root, args, context) { const options = { fields: context.getViewableFields(context.currentUser, context.Categories) }; diff --git a/packages/nova-comments/lib/queries.js b/packages/nova-comments/lib/queries.js index da6ebe58f..7e837863f 100644 --- a/packages/nova-comments/lib/queries.js +++ b/packages/nova-comments/lib/queries.js @@ -3,7 +3,7 @@ import Comments from './collection.js'; // declare comments queries Telescope.graphQL.addQuery(` - comments(postId: String): [Comment] + commentsList(postId: String, offset: Int, limit: Int): [Comment] commentsListTotal(postId: String): Int comment(_id: String): Comment `); diff --git a/packages/nova-comments/lib/resolvers.js b/packages/nova-comments/lib/resolvers.js index 3d2a11cc9..19a9f0343 100644 --- a/packages/nova-comments/lib/resolvers.js +++ b/packages/nova-comments/lib/resolvers.js @@ -31,11 +31,13 @@ const resolvers = { }, }, Query: { - comments(root, {postId}, context) { + commentsList(root, {postId, offset, limit}, context) { const options = { - // limit: 5, // no limit for now + limit: (limit < 1 || limit > 10) ? 10 : limit, + skip: offset, fields: context.getViewableFields(context.currentUser, context.Comments) - } + }; + return context.Comments.find({postId: postId}, options).fetch(); }, commentsListTotal(root, {postId}, context) { diff --git a/packages/nova-core/lib/containers/withList.js b/packages/nova-core/lib/containers/withList.js index 787a21476..d74579e77 100644 --- a/packages/nova-core/lib/containers/withList.js +++ b/packages/nova-core/lib/containers/withList.js @@ -5,27 +5,77 @@ import gql from 'graphql-tag'; export default function withList (options) { - console.log("withList") - console.log(options) + // extract arguments from the options of the hoc + 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` - query ${queryName}($offset: Int, $limit: Int) { - ${totalResolverName} - ${listResolverName}(offset: $offset, limit: $limit) { + query ${queryName}(${queryVariablesTypeDef}) { + ${totalResolverName}${callQueryVariablesTotal} + ${listResolverName}(${queryVariablesList}) { ...${fragmentName} } } `, { options(ownProps) { + + const queryVariables = propsVariables.reduce((variables, {propName, defaultValue}) => ({ + ...variables, + [propName]: ownProps[propName] || defaultValue + }), {}); + + console.log('actual query variables', queryVariables); + return { - variables: { - offset: 0, - limit: 5 - }, + variables: queryVariables, fragments: fragment, - pollInterval: 20000, + // pollInterval: 20000, }; }, props(props) { diff --git a/packages/nova-posts/lib/resolvers.js b/packages/nova-posts/lib/resolvers.js index f61eec0d8..ee14814f5 100644 --- a/packages/nova-posts/lib/resolvers.js +++ b/packages/nova-posts/lib/resolvers.js @@ -14,7 +14,7 @@ export default resolvers = { }, }, Query: { - posts(root, {terms, offset, limit}, context, info) { + postsList(root, {terms, offset, limit}, context, info) { // console.log("// context") // console.log(context) let {selector, options} = context.Posts.parameters.get(terms); @@ -40,7 +40,7 @@ export default resolvers = { Telescope.graphQL.addResolvers(resolvers); Telescope.graphQL.addQuery(` - posts(terms: Terms, offset: Int, limit: Int): [Post] + postsList(terms: Terms, offset: Int, limit: Int): [Post] postsListTotal(terms: Terms): Int post(_id: String): Post `); \ No newline at end of file