/* Generic mutation wrapper to insert a new document in a collection and update a related query on the client with the new item and a new total item count. Sample mutation: mutation moviesNew($document: MoviesInput) { moviesNew(document: $document) { ...MoviesNewFormFragment } } */ import React, { Component } from 'react'; import { graphql } from 'react-apollo'; import gql from 'graphql-tag'; import hoistStatics from 'hoist-non-react-statics' import Telescope from 'meteor/nova:lib'; import update from 'immutability-helper'; export default function withNew(WrappedComponent) { // create a new stateless component so we can access its props const WithNew = props => { console.log(props) const { collection, fragmentName, fragment, queryName } = props, collectionName = collection._name, mutationName = collection.options.mutations.new.name, listResolverName = collection.options.resolvers.list.name, totalResolverName = collection.options.resolvers.total.name; // if a queryName is passed as prop, generate updateQueries function let updateQueries = {}; if (queryName) { updateQueries = { [queryName]: (prev, { mutationResult }) => { // get new document to insert const newDocument = mutationResult.data[mutationName]; // generate new list with updated total count and document inserted at top const newList = update(prev, { [listResolverName]: { $unshift: [newDocument] }, [totalResolverName]: { $set: prev[totalResolverName] + 1 } }); console.log(`// updated query ${queryName}:`) console.log(prev) console.log(newList) return newList; } } } // wrap component with graphql HoC const ComponentWithNew = graphql(gql` mutation ${mutationName}($document: ${collectionName}Input) { ${mutationName}(document: $document) { ...${fragmentName} } } ${fragment} `, { props: ({ownProps, mutate}) => ({ newMutation: ({document}) => { console.log('// newMutation') console.log(updateQueries) return mutate({ variables: { document }, updateQueries: props.updateQueries || updateQueries }) } }), })(WrappedComponent); // render wrapped component return } WithNew.displayName = `withNew(${Telescope.utils.getComponentDisplayName(WrappedComponent)}`; WithNew.WrappedComponent = WrappedComponent; // hoist wrapped component's statics up to the new wrapper component and return it return hoistStatics(WithNew, WrappedComponent); } withNew.propTypes = { collection: React.PropTypes.object, // the collection to mutate fragmentName: React.PropTypes.string, // the name of the fragment fragment: React.PropTypes.object, // controls what data the mutation should return queryName: React.PropTypes.string, // the query to update on the client }