Skip to content

Conversation

@dancastellon
Copy link
Contributor

@dancastellon dancastellon commented Jul 24, 2018

Resolves #4480 and #4486
Impact: major
Type: performance

Changes

This PR adds Apollo Client integration in our Meteor app, and allows the product grid to consume data via GraphQL.

Breaking changes

Shops that have overridden the customer-facing product grid, will break, due to the Meteor publication no longer existing.

Testing

  1. reaction reset -n and start the app up
  2. Enable marketplace and invite a shop owner to create a new shop
  3. Dashboard -> Marketplace shops -> set shop to active
  4. Switch to new shop via admin header
  5. create & publish a single product - be sure to create a variant, that has some quantity, and make it & the product visible + publish
  6. Logout
  7. In DB, update new shop's domains[] to include "reaction1.localhost"
  8. In incognito mode (so a new user/account doc is created), visit reaction1.localhost:3000, confirm correct marketplace product appears
  9. Visit localhost:3000/shop/reaction1 (still in incognito window) and confirm the same product appears
  10. In another terminal window, use reaction-data-loader to load up some products with the developer dataset. Follow steps 1-3 in project's README. While the app is still running, run npx babel-node data/generator.js -m mongodb://localhost:3001 -l dev -n meteor --max_old_space_size=8192 --presets es2015,stage-2 to generate data
  11. Back in main (not incognito) browser window, visit homepage & confirm products load, infinite scroll works, clicking through to PDP works
  12. Confirm caching works - visit homepage, visit tag page, go back to homepage & confirm it loads instantly without another graphql-alpha network request
  13. Confirm the migration: confirm Migrations.version = 33 and Migrations.locked = false
  14. Confirm Packages where name = reaction-product-variant has the following values: layout[1].structure.template = Products, registry[0].template = Products
  15. Confirm improved infinite scrolling - should kick off graphql-alpha request for more products when you reach 80% to the bottom
  16. Confirm grid is sorted by newest first


export default function initApollo() {
return new ApolloClient({
link: meteorAccountsLink.concat(new HttpLink({ uri: Meteor.absoluteUrl('graphql-alpha') })),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If latest 1.14.0 is merged into this, Meteor.absoluteUrl can be changed to Reaction.absoluteUrl. (Everywhere else in app has been changed.)

createdAt: -1
}
});
// TODO graphql custom tag sort - $sort: { [`product.positions.${tagIdForPosition}.position`]: 1 }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We no longer support custom positioning so everything using product.positions can just be removed.

route: "/tag/:slug?",
name: "tag",
template: "products",
template: "Products",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe this needs a migration since this goes into the database. See migration 27 for an example

package.json Outdated
"@reactioncommerce/random": "1.0.1",
"@reactioncommerce/schemas": "1.1.0",
"accounting-js": "^1.1.1",
"apollo-cache-inmemory": "^1.2.5",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All added/changed packages should be pinned (no ^ prefix)

@aldeed
Copy link
Contributor

aldeed commented Jul 24, 2018

@dancastellon This is super exciting! I realize it's WIP but I left a few comments since I'm going to be out the rest of this week.

It can be a separate followup PR, but I'd also like to merge the two ProductGrids (the CustomerProductGrid from here and the one in next-starterkit) into a single component that lives in the component library. It would be mostly a copy of the newer starter kit component, but replacing MaterialUI components with our own styled-components divs. cc @machikoyasuda

@dancastellon
Copy link
Contributor Author

@aldeed Thanks! I have made the updates from your comments.

@dancastellon dancastellon changed the title WIP: #4480 Convert product grid to consume GraphQL data #4480 Convert product grid to consume GraphQL data Aug 3, 2018
@dancastellon
Copy link
Contributor Author

dancastellon commented Aug 3, 2018

@zenweasel, @spencern, @aldeed - I believe this gql grid PR is ready to merge, after a final review. Who wants to test? Next up: porting the storefront grid to component lib and the Meteor app. Thanks!

Copy link
Contributor

@aldeed aldeed left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dancastellon I took one more look and noticed a few things.

}
}, { bypassCollection2: true });
}
});
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These all need to be multi. Change { bypassCollection2: true } to { bypassCollection2: true, multi: true }

isSoldOut: PropTypes.bool,
media: PropTypes.arrayOf(PropTypes.object),
pricing: PropTypes.object,
pricing: PropTypes.array,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since you are relying on the shape of these, do PropTypes.arrayOf(PropTypes.shape({ ... })) with the correct props inside shape.


if (loading === false) {
const { catalogItems } = data;
props.catalogItems = catalogItems || {};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's best if we pass just the item nodes, i.e., do the map to item.node here before passing down. The wrapped component in almost all cases will not care about edges or cursors. If it ever needs them, we can add an option to provide them.

Also, fetchMore/loadMore should be passed down with pageInfo already bound to it. The wrapped component shouldn't need to know anything about pageInfo, cursors, or pagination. All it knows is that it calls this.props.loadMore when necessary, and you can pass down a hasMoreItems boolean so that it knows whether to display a load more button.

This is the pattern we've tried to use in the starter kit. It's a bit more complicated scenario, but you can see what I mean here: https://github.com/reactioncommerce/reaction-next-starterkit/blob/de613530d6aff10bdf5023d910b5ee07c06e127a/src/containers/cart/withCart.js#L205-L206

@dancastellon
Copy link
Contributor Author

dancastellon commented Aug 6, 2018

Thanks @aldeed, just made the changes. I'm liking the pattern of hasMoreCatalogItems, loadMoreCatalogItems, isLoadingCatalogItems, etc - makes things really clean.

@aldeed aldeed merged commit d128222 into release-1.15.0 Aug 8, 2018
@spencern spencern mentioned this pull request Aug 14, 2018
@spencern spencern deleted the feat-dan-graphql-customer-grid-experiment branch August 22, 2018 04:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants