From 94613893152784402a41de68a006019aba6b77d2 Mon Sep 17 00:00:00 2001 From: Paul Hachmang Date: Mon, 8 Jan 2024 12:50:50 +0100 Subject: [PATCH 01/33] Working on abstracting away hygraph from example directory --- .../components/GraphCMS/index.ts | 4 -- examples/magento-graphcms/components/index.ts | 4 +- examples/magento-graphcms/package.json | 1 + examples/magento-graphcms/pages/[...url].tsx | 27 +++++++++++-- .../magento-graphcms/pages/blog/[url].tsx | 11 ++++-- .../pages/blog/page/[page].tsx | 10 +++-- .../pages/blog/tagged/[url].tsx | 11 ++++-- examples/magento-graphcms/pages/index.tsx | 17 +++++++-- .../magento-graphcms/pages/modal/[...url].tsx | 10 +++-- .../pages/newsletter/index.tsx | 11 ++++-- examples/magento-graphcms/pages/p/[url].tsx | 27 ++++++++++--- .../pages/service/[[...url]].tsx | 12 ++++-- examples/magento-graphcms/tsconfig.json | 10 ++++- .../components/ContentArea/Areas.tsx | 8 ++++ .../components/ContentArea/ContentArea.tsx | 12 ++++++ .../components/ContentArea/index.ts | 2 + packages/content-areas/components/index.ts | 1 + packages/content-areas/index.ts | 3 ++ packages/content-areas/package.json | 31 +++++++++++++++ packages/content-areas/server/pageContent.ts | 11 ++++++ packages/content-areas/types.ts | 1 + .../components}/Asset/AssetWithAlt.graphql | 0 .../components/Blog/BlogAuthor.graphql | 4 ++ .../hygraph-ui/components/Blog/BlogAuthor.tsx | 10 +++++ .../hygraph-ui/components/Blog/BlogHeader.tsx | 11 ++++++ .../components/Blog/BlogItem.graphql | 8 ++++ .../hygraph-ui/components/Blog/BlogItem.tsx | 38 +++++++++++++++++++ .../components/Blog/BlogList.graphql | 14 +++++++ .../hygraph-ui/components/Blog/BlogList.tsx | 17 +++++++++ .../components/Blog/BlogListTagged.graphql | 14 +++++++ .../components/Blog/BlogPaths.graphql | 7 ++++ .../components/Blog/BlogPostPaths.graphql | 5 +++ .../Blog/BlogPostTaggedPaths.graphql | 5 +++ .../components/Blog/BlogTags.graphql | 6 +++ .../hygraph-ui/components/Blog/BlogTags.tsx | 16 ++++++++ .../components/Blog/RowBlogContent.graphql | 5 +++ .../components/Blog/RowBlogContent.tsx | 15 ++++++++ packages/hygraph-ui/components/Blog/index.ts | 12 ++++++ .../PageContentQueryFragment.graphql | 0 .../RowButtonLinkList.graphql | 0 .../RowButtonLinkList/RowButtonLinkList.tsx | 0 .../RowColumnOne/RowColumnOne.graphql | 0 .../components}/RowColumnOne/RowColumnOne.tsx | 2 +- .../RowColumnOne/RowColumnOneBoxed.tsx | 2 +- .../RowColumnOne/RowColumnOneCentered.tsx | 2 +- .../RowColumnOne/RowColumnOneDoubleSpread.tsx | 2 +- .../RowColumnOne/RowColumnOneSpread.tsx | 2 +- .../RowColumnOne/variant/Default.tsx | 2 +- .../RowColumnOne/variant/Message.tsx | 2 +- .../RowColumnOne/variant/index.tsx | 0 .../RowColumnThree/RowColumnThree.graphql | 0 .../RowColumnThree/RowColumnThree.tsx | 2 +- .../RowColumnTwo/RowColumnTwo.graphql | 0 .../components}/RowColumnTwo/RowColumnTwo.tsx | 2 +- .../RowColumnTwo/RowColumnTwoSpread.tsx | 5 ++- .../RowContentLinks/RowContentLinks.graphql | 0 .../RowContentLinks/RowContentLinks.tsx | 0 .../RowHeroBanner/RowHeroBanner.graphql | 0 .../RowHeroBanner/RowHeroBanner.tsx | 2 +- .../components}/RowLinks/RowLinks.graphql | 0 .../components}/RowLinks/RowLinks.tsx | 1 - .../RowLinks/variant/ImageLabelSwiper.tsx | 3 +- .../components}/RowLinks/variant/Inline.tsx | 0 .../RowLinks/variant/LogoSwiper.tsx | 2 +- .../components}/RowLinks/variant/Usps.tsx | 2 +- .../components}/RowLinks/variant/index.tsx | 0 .../components}/RowProduct/RowProduct.graphql | 0 .../components}/RowProduct/RowProduct.tsx | 0 .../RowProduct/variant/Backstory.tsx | 4 +- .../RowProduct/variant/Feature.tsx | 2 +- .../RowProduct/variant/FeatureBoxed.tsx | 2 +- .../components}/RowProduct/variant/Grid.tsx | 5 ++- .../variant/ProductFeatureMedia.graphql | 0 .../variant/ProductFeatureMediaBoxed.graphql | 0 .../RowProduct/variant/Related.tsx | 2 +- .../RowProduct/variant/Reviews.tsx | 0 .../components}/RowProduct/variant/Specs.tsx | 0 .../RowProduct/variant/Swipeable.tsx | 2 +- .../RowProduct/variant/Upsells.tsx | 2 +- .../components}/RowProduct/variant/index.tsx | 0 .../components}/RowQuote/RowQuote.graphql | 0 .../components}/RowQuote/RowQuote.tsx | 2 +- .../components}/RowRenderer.graphql | 0 .../hygraph-ui/components}/RowRenderer.tsx | 4 +- .../RowServiceOptions.graphql | 0 .../RowServiceOptions/RowServiceOptions.tsx | 2 +- .../RowSpecialBanner/RowSpecialBanner.graphql | 0 .../RowSpecialBanner/RowSpecialBanner.tsx | 3 +- packages/hygraph-ui/components/index.ts | 5 +++ packages/hygraph-ui/lib/hygraphPageContent.ts | 2 +- packages/hygraph-ui/package.json | 2 + .../hygraph-ui/plugins/HygraphContentArea.tsx | 20 ++++++++++ .../plugins/hygraphPageContentPlugin.ts | 26 +++++++++++++ packages/hygraph-ui/types.ts | 13 +++++++ .../ProductListItems/getFilterTypes.ts | 3 +- yarn.lock | 23 +++++++++++ 96 files changed, 494 insertions(+), 74 deletions(-) delete mode 100644 examples/magento-graphcms/components/GraphCMS/index.ts create mode 100644 packages/content-areas/components/ContentArea/Areas.tsx create mode 100644 packages/content-areas/components/ContentArea/ContentArea.tsx create mode 100644 packages/content-areas/components/ContentArea/index.ts create mode 100644 packages/content-areas/components/index.ts create mode 100644 packages/content-areas/index.ts create mode 100644 packages/content-areas/package.json create mode 100644 packages/content-areas/server/pageContent.ts create mode 100644 packages/content-areas/types.ts rename {examples/magento-graphcms/components/GraphCMS => packages/hygraph-ui/components}/Asset/AssetWithAlt.graphql (100%) create mode 100644 packages/hygraph-ui/components/Blog/BlogAuthor.graphql create mode 100644 packages/hygraph-ui/components/Blog/BlogAuthor.tsx create mode 100644 packages/hygraph-ui/components/Blog/BlogHeader.tsx create mode 100644 packages/hygraph-ui/components/Blog/BlogItem.graphql create mode 100644 packages/hygraph-ui/components/Blog/BlogItem.tsx create mode 100644 packages/hygraph-ui/components/Blog/BlogList.graphql create mode 100644 packages/hygraph-ui/components/Blog/BlogList.tsx create mode 100644 packages/hygraph-ui/components/Blog/BlogListTagged.graphql create mode 100644 packages/hygraph-ui/components/Blog/BlogPaths.graphql create mode 100644 packages/hygraph-ui/components/Blog/BlogPostPaths.graphql create mode 100644 packages/hygraph-ui/components/Blog/BlogPostTaggedPaths.graphql create mode 100644 packages/hygraph-ui/components/Blog/BlogTags.graphql create mode 100644 packages/hygraph-ui/components/Blog/BlogTags.tsx create mode 100644 packages/hygraph-ui/components/Blog/RowBlogContent.graphql create mode 100644 packages/hygraph-ui/components/Blog/RowBlogContent.tsx create mode 100644 packages/hygraph-ui/components/Blog/index.ts rename {examples/magento-graphcms/components/GraphCMS => packages/hygraph-ui/components}/PageContentQueryFragment.graphql (100%) rename {examples/magento-graphcms/components/GraphCMS => packages/hygraph-ui/components}/RowButtonLinkList/RowButtonLinkList.graphql (100%) rename {examples/magento-graphcms/components/GraphCMS => packages/hygraph-ui/components}/RowButtonLinkList/RowButtonLinkList.tsx (100%) rename {examples/magento-graphcms/components/GraphCMS => packages/hygraph-ui/components}/RowColumnOne/RowColumnOne.graphql (100%) rename {examples/magento-graphcms/components/GraphCMS => packages/hygraph-ui/components}/RowColumnOne/RowColumnOne.tsx (94%) rename {examples/magento-graphcms/components/GraphCMS => packages/hygraph-ui/components}/RowColumnOne/RowColumnOneBoxed.tsx (85%) rename {examples/magento-graphcms/components/GraphCMS => packages/hygraph-ui/components}/RowColumnOne/RowColumnOneCentered.tsx (85%) rename {examples/magento-graphcms/components/GraphCMS => packages/hygraph-ui/components}/RowColumnOne/RowColumnOneDoubleSpread.tsx (90%) rename {examples/magento-graphcms/components/GraphCMS => packages/hygraph-ui/components}/RowColumnOne/RowColumnOneSpread.tsx (89%) rename {examples/magento-graphcms/components/GraphCMS => packages/hygraph-ui/components}/RowColumnOne/variant/Default.tsx (85%) rename {examples/magento-graphcms/components/GraphCMS => packages/hygraph-ui/components}/RowColumnOne/variant/Message.tsx (86%) rename {examples/magento-graphcms/components/GraphCMS => packages/hygraph-ui/components}/RowColumnOne/variant/index.tsx (100%) rename {examples/magento-graphcms/components/GraphCMS => packages/hygraph-ui/components}/RowColumnThree/RowColumnThree.graphql (100%) rename {examples/magento-graphcms/components/GraphCMS => packages/hygraph-ui/components}/RowColumnThree/RowColumnThree.tsx (88%) rename {examples/magento-graphcms/components/GraphCMS => packages/hygraph-ui/components}/RowColumnTwo/RowColumnTwo.graphql (100%) rename {examples/magento-graphcms/components/GraphCMS => packages/hygraph-ui/components}/RowColumnTwo/RowColumnTwo.tsx (85%) rename {examples/magento-graphcms/components/GraphCMS => packages/hygraph-ui/components}/RowColumnTwo/RowColumnTwoSpread.tsx (90%) rename {examples/magento-graphcms/components/GraphCMS => packages/hygraph-ui/components}/RowContentLinks/RowContentLinks.graphql (100%) rename {examples/magento-graphcms/components/GraphCMS => packages/hygraph-ui/components}/RowContentLinks/RowContentLinks.tsx (100%) rename {examples/magento-graphcms/components/GraphCMS => packages/hygraph-ui/components}/RowHeroBanner/RowHeroBanner.graphql (100%) rename {examples/magento-graphcms/components/GraphCMS => packages/hygraph-ui/components}/RowHeroBanner/RowHeroBanner.tsx (96%) rename {examples/magento-graphcms/components/GraphCMS => packages/hygraph-ui/components}/RowLinks/RowLinks.graphql (100%) rename {examples/magento-graphcms/components/GraphCMS => packages/hygraph-ui/components}/RowLinks/RowLinks.tsx (95%) rename {examples/magento-graphcms/components/GraphCMS => packages/hygraph-ui/components}/RowLinks/variant/ImageLabelSwiper.tsx (94%) rename {examples/magento-graphcms/components/GraphCMS => packages/hygraph-ui/components}/RowLinks/variant/Inline.tsx (100%) rename {examples/magento-graphcms/components/GraphCMS => packages/hygraph-ui/components}/RowLinks/variant/LogoSwiper.tsx (96%) rename {examples/magento-graphcms/components/GraphCMS => packages/hygraph-ui/components}/RowLinks/variant/Usps.tsx (96%) rename {examples/magento-graphcms/components/GraphCMS => packages/hygraph-ui/components}/RowLinks/variant/index.tsx (100%) rename {examples/magento-graphcms/components/GraphCMS => packages/hygraph-ui/components}/RowProduct/RowProduct.graphql (100%) rename {examples/magento-graphcms/components/GraphCMS => packages/hygraph-ui/components}/RowProduct/RowProduct.tsx (100%) rename {examples/magento-graphcms/components/GraphCMS => packages/hygraph-ui/components}/RowProduct/variant/Backstory.tsx (91%) rename {examples/magento-graphcms/components/GraphCMS => packages/hygraph-ui/components}/RowProduct/variant/Feature.tsx (96%) rename {examples/magento-graphcms/components/GraphCMS => packages/hygraph-ui/components}/RowProduct/variant/FeatureBoxed.tsx (96%) rename {examples/magento-graphcms/components/GraphCMS => packages/hygraph-ui/components}/RowProduct/variant/Grid.tsx (82%) rename {examples/magento-graphcms/components/GraphCMS => packages/hygraph-ui/components}/RowProduct/variant/ProductFeatureMedia.graphql (100%) rename {examples/magento-graphcms/components/GraphCMS => packages/hygraph-ui/components}/RowProduct/variant/ProductFeatureMediaBoxed.graphql (100%) rename {examples/magento-graphcms/components/GraphCMS => packages/hygraph-ui/components}/RowProduct/variant/Related.tsx (89%) rename {examples/magento-graphcms/components/GraphCMS => packages/hygraph-ui/components}/RowProduct/variant/Reviews.tsx (100%) rename {examples/magento-graphcms/components/GraphCMS => packages/hygraph-ui/components}/RowProduct/variant/Specs.tsx (100%) rename {examples/magento-graphcms/components/GraphCMS => packages/hygraph-ui/components}/RowProduct/variant/Swipeable.tsx (91%) rename {examples/magento-graphcms/components/GraphCMS => packages/hygraph-ui/components}/RowProduct/variant/Upsells.tsx (89%) rename {examples/magento-graphcms/components/GraphCMS => packages/hygraph-ui/components}/RowProduct/variant/index.tsx (100%) rename {examples/magento-graphcms/components/GraphCMS => packages/hygraph-ui/components}/RowQuote/RowQuote.graphql (100%) rename {examples/magento-graphcms/components/GraphCMS => packages/hygraph-ui/components}/RowQuote/RowQuote.tsx (93%) rename {examples/magento-graphcms/components/GraphCMS => packages/hygraph-ui/components}/RowRenderer.graphql (100%) rename {examples/magento-graphcms/components/GraphCMS => packages/hygraph-ui/components}/RowRenderer.tsx (94%) rename {examples/magento-graphcms/components/GraphCMS => packages/hygraph-ui/components}/RowServiceOptions/RowServiceOptions.graphql (100%) rename {examples/magento-graphcms/components/GraphCMS => packages/hygraph-ui/components}/RowServiceOptions/RowServiceOptions.tsx (95%) rename {examples/magento-graphcms/components/GraphCMS => packages/hygraph-ui/components}/RowSpecialBanner/RowSpecialBanner.graphql (100%) rename {examples/magento-graphcms/components/GraphCMS => packages/hygraph-ui/components}/RowSpecialBanner/RowSpecialBanner.tsx (94%) create mode 100644 packages/hygraph-ui/plugins/HygraphContentArea.tsx create mode 100644 packages/hygraph-ui/plugins/hygraphPageContentPlugin.ts create mode 100644 packages/hygraph-ui/types.ts diff --git a/examples/magento-graphcms/components/GraphCMS/index.ts b/examples/magento-graphcms/components/GraphCMS/index.ts deleted file mode 100644 index 925e70dccdf..00000000000 --- a/examples/magento-graphcms/components/GraphCMS/index.ts +++ /dev/null @@ -1,4 +0,0 @@ -export * from './RowProduct/RowProduct' - -// The actual renderer -export * from './RowRenderer' diff --git a/examples/magento-graphcms/components/index.ts b/examples/magento-graphcms/components/index.ts index 6fb2bd59b2b..6c91a74478a 100644 --- a/examples/magento-graphcms/components/index.ts +++ b/examples/magento-graphcms/components/index.ts @@ -1,5 +1,5 @@ -export * from './Blog' +export * from '@graphcommerce/graphcms-ui/components/Blog' export * from './Layout' export * from './Usps/Usps' -export * from './GraphCMS' +export * from '@graphcommerce/graphcms-ui/components' export * from './ProductListItems' diff --git a/examples/magento-graphcms/package.json b/examples/magento-graphcms/package.json index e83dd08171e..de65a34755e 100644 --- a/examples/magento-graphcms/package.json +++ b/examples/magento-graphcms/package.json @@ -22,6 +22,7 @@ "@apollo/client": "~3.8.8", "@ducanh2912/next-pwa": "9.7.2", "@graphcommerce/cli": "8.0.0-canary.74", + "@graphcommerce/content-areas": "8.0.0-canary.74", "@graphcommerce/demo-magento-graphcommerce": "8.0.0-canary.74", "@graphcommerce/ecommerce-ui": "8.0.0-canary.74", "@graphcommerce/framer-next-pages": "8.0.0-canary.74", diff --git a/examples/magento-graphcms/pages/[...url].tsx b/examples/magento-graphcms/pages/[...url].tsx index 8690d449bf1..932e532e1b0 100644 --- a/examples/magento-graphcms/pages/[...url].tsx +++ b/examples/magento-graphcms/pages/[...url].tsx @@ -1,3 +1,9 @@ +import { + ContentAreaCategoryPage, + ContentAreaCategoryPageBefore, + pageContent, + PageContent, +} from '@graphcommerce/content-areas' import { PageOptions } from '@graphcommerce/framer-next-pages' import { Asset, hygraphPageContent, HygraphPagesQuery } from '@graphcommerce/graphcms-ui' import { flushMeasurePerf } from '@graphcommerce/graphql' @@ -38,14 +44,18 @@ import { graphqlSharedClient, graphqlSsrClient } from '../lib/graphql/graphqlSsr export type CategoryProps = CategoryPageQuery & HygraphPagesQuery & ProductListQuery & - ProductFiltersQuery & { filterTypes?: FilterTypes; params?: ProductListParams } + ProductFiltersQuery & { + filterTypes?: FilterTypes + params?: ProductListParams + content: PageContent + } export type CategoryRoute = { url: string[] } type GetPageStaticPaths = GetStaticPaths type GetPageStaticProps = GetStaticProps function CategoryPage(props: CategoryProps) { - const { categories, products, filters, params, filterTypes, pages } = props + const { content, categories, products, filters, params, filterTypes, pages } = props const category = categories?.items?.[0] const isLanding = category?.display_mode === 'PAGE' @@ -62,6 +72,9 @@ function CategoryPage(props: CategoryProps) { canonical={page?.url ? `/${page.url}` : undefined} {...category} /> + + + {category?.name ?? page.title} @@ -105,7 +118,10 @@ function CategoryPage(props: CategoryProps) { /> )} - {page && ( + + + + {/* {page && ( - )} + )} */} ) } @@ -166,6 +182,7 @@ export const getStaticProps: GetPageStaticProps = async ({ params, locale }) => } const pages = hygraphPageContent(staticClient, url, category) + const content = pageContent(staticClient, url, category) const hasPage = filteredCategoryUid ? false : (await pages).data.pages.length > 0 const hasCategory = Boolean(productListParams && categoryUid) @@ -175,6 +192,7 @@ export const getStaticProps: GetPageStaticProps = async ({ params, locale }) => if (!hasCategory) { return { props: { + content: await content, ...(await categoryPage).data, ...(await pages).data, ...(await layout).data, @@ -209,6 +227,7 @@ export const getStaticProps: GetPageStaticProps = async ({ params, locale }) => const result = { props: { + content: await content, ...(await categoryPage).data, ...(await products).data, ...(await pages).data, diff --git a/examples/magento-graphcms/pages/blog/[url].tsx b/examples/magento-graphcms/pages/blog/[url].tsx index 2b0437f2572..d939b1ced08 100644 --- a/examples/magento-graphcms/pages/blog/[url].tsx +++ b/examples/magento-graphcms/pages/blog/[url].tsx @@ -1,3 +1,4 @@ +import { ContentArea, PageContent, pageContent } from '@graphcommerce/content-areas' import { PageOptions } from '@graphcommerce/framer-next-pages' import { hygraphPageContent, HygraphPagesQuery } from '@graphcommerce/graphcms-ui' import { StoreConfigDocument } from '@graphcommerce/magento-store' @@ -25,13 +26,13 @@ import { } from '../../components' import { graphqlSharedClient, graphqlSsrClient } from '../../lib/graphql/graphqlSsrClient' -type Props = HygraphPagesQuery & BlogListQuery +type Props = HygraphPagesQuery & BlogListQuery & { content: PageContent } type RouteProps = { url: string } type GetPageStaticPaths = GetStaticPaths type GetPageStaticProps = GetStaticProps function BlogPage(props: Props) { - const { blogPosts, pages } = props + const { blogPosts, content, pages } = props const page = pages[0] const title = page?.title ?? '' @@ -50,7 +51,9 @@ function BlogPage(props: Props) { {page.author ? : null} {page.asset ? : null} - + + + @@ -88,6 +91,7 @@ export const getStaticProps: GetPageStaticProps = async ({ locale, params }) => const conf = client.query({ query: StoreConfigDocument }) const page = hygraphPageContent(staticClient, `blog/${urlKey}`) + const content = pageContent(staticClient, `blog/${urlKey}`) const layout = staticClient.query({ query: LayoutDocument, fetchPolicy: 'cache-first' }) const blogPosts = staticClient.query({ @@ -98,6 +102,7 @@ export const getStaticProps: GetPageStaticProps = async ({ locale, params }) => return { props: { + content: await content, ...(await page).data, ...(await blogPosts).data, ...(await layout).data, diff --git a/examples/magento-graphcms/pages/blog/page/[page].tsx b/examples/magento-graphcms/pages/blog/page/[page].tsx index 0e9f3ad3913..fbdd4092a9a 100644 --- a/examples/magento-graphcms/pages/blog/page/[page].tsx +++ b/examples/magento-graphcms/pages/blog/page/[page].tsx @@ -1,3 +1,4 @@ +import { ContentArea, PageContent, pageContent } from '@graphcommerce/content-areas' import { PageOptions } from '@graphcommerce/framer-next-pages' import { hygraphPageContent, HygraphPagesQuery } from '@graphcommerce/graphcms-ui' import { StoreConfigDocument } from '@graphcommerce/magento-store' @@ -21,11 +22,10 @@ import { LayoutDocument, LayoutNavigation, LayoutNavigationProps, - RowRenderer, } from '../../../components' import { graphqlSsrClient, graphqlSharedClient } from '../../../lib/graphql/graphqlSsrClient' -type Props = HygraphPagesQuery & BlogListQuery & BlogPathsQuery +type Props = HygraphPagesQuery & BlogListQuery & BlogPathsQuery & { content: PageContent } type RouteProps = { page: string } type GetPageStaticPaths = GetStaticPaths type GetPageStaticProps = GetStaticProps @@ -33,7 +33,7 @@ type GetPageStaticProps = GetStaticProps - + ) } @@ -99,6 +99,7 @@ export const getStaticProps: GetPageStaticProps = async ({ locale, params }) => const conf = client.query({ query: StoreConfigDocument }) const defaultPage = hygraphPageContent(staticClient, 'blog') + const content = pageContent(staticClient, 'blog') const layout = staticClient.query({ query: LayoutDocument, fetchPolicy: 'cache-first' }) const blogPosts = staticClient.query({ @@ -113,6 +114,7 @@ export const getStaticProps: GetPageStaticProps = async ({ locale, params }) => return { props: { + content: await content, ...(await defaultPage).data, ...(await blogPosts).data, ...(await blogPaths).data, diff --git a/examples/magento-graphcms/pages/blog/tagged/[url].tsx b/examples/magento-graphcms/pages/blog/tagged/[url].tsx index 41f7d123f08..c7caa20e6db 100644 --- a/examples/magento-graphcms/pages/blog/tagged/[url].tsx +++ b/examples/magento-graphcms/pages/blog/tagged/[url].tsx @@ -1,3 +1,4 @@ +import { ContentArea, PageContent, pageContent } from '@graphcommerce/content-areas' import { PageOptions } from '@graphcommerce/framer-next-pages' import { hygraphPageContent, HygraphPagesQuery } from '@graphcommerce/graphcms-ui' import { StoreConfigDocument } from '@graphcommerce/magento-store' @@ -16,17 +17,16 @@ import { LayoutDocument, LayoutNavigation, LayoutNavigationProps, - RowRenderer, } from '../../../components' import { graphqlSsrClient, graphqlSharedClient } from '../../../lib/graphql/graphqlSsrClient' -type Props = HygraphPagesQuery & BlogListTaggedQuery +type Props = HygraphPagesQuery & BlogListTaggedQuery & { content: PageContent } type RouteProps = { url: string } type GetPageStaticPaths = GetStaticPaths type GetPageStaticProps = GetStaticProps function BlogPage(props: Props) { - const { pages, blogPosts } = props + const { content, pages, blogPosts } = props const page = pages[0] const title = page.title ?? '' @@ -44,7 +44,8 @@ function BlogPage(props: Props) { {page.author ? : null} {page.asset ? : null} - + + @@ -83,6 +84,7 @@ export const getStaticProps: GetPageStaticProps = async ({ locale, params }) => const limit = 99 const conf = client.query({ query: StoreConfigDocument }) const page = hygraphPageContent(staticClient, `blog/tagged/${urlKey}`) + const content = pageContent(staticClient, `blog/tagged/${urlKey}`) const layout = staticClient.query({ query: LayoutDocument, fetchPolicy: 'cache-first' }) const blogPosts = staticClient.query({ @@ -93,6 +95,7 @@ export const getStaticProps: GetPageStaticProps = async ({ locale, params }) => return { props: { + content: await content, ...(await page).data, ...(await blogPosts).data, ...(await layout).data, diff --git a/examples/magento-graphcms/pages/index.tsx b/examples/magento-graphcms/pages/index.tsx index c6405ce2647..7ed47e04c55 100644 --- a/examples/magento-graphcms/pages/index.tsx +++ b/examples/magento-graphcms/pages/index.tsx @@ -1,3 +1,9 @@ +import { + ContentAreaHome, + ContentAreaProps, + PageContent, + pageContent, +} from '@graphcommerce/content-areas' import { PageOptions } from '@graphcommerce/framer-next-pages' import { hygraphPageContent, HygraphPagesQuery } from '@graphcommerce/graphcms-ui' import { ProductListDocument, ProductListQuery } from '@graphcommerce/magento-product' @@ -16,12 +22,13 @@ type Props = HygraphPagesQuery & { latestList: ProductListQuery favoritesList: ProductListQuery swipableList: ProductListQuery + content: PageContent } type RouteProps = { url: string } type GetPageStaticProps = GetStaticProps function CmsPage(props: Props) { - const { pages, latestList, favoritesList, swipableList } = props + const { content, pages, latestList, favoritesList, swipableList } = props const page = pages?.[0] const latest = latestList?.products?.items?.[0] @@ -39,7 +46,9 @@ function CmsPage(props: Props) { - {page && ( + + + {/* {page && ( - )} + )} */} ) } @@ -79,6 +88,7 @@ export const getStaticProps: GetPageStaticProps = async ({ locale }) => { const conf = client.query({ query: StoreConfigDocument }) const page = hygraphPageContent(staticClient, 'page/home') + const content = pageContent(staticClient, 'page/home') const layout = staticClient.query({ query: LayoutDocument, fetchPolicy: 'cache-first' }) // todo(paales): Remove when https://github.com/Urigo/graphql-mesh/issues/1257 is resolved @@ -101,6 +111,7 @@ export const getStaticProps: GetPageStaticProps = async ({ locale }) => { return { props: { + content: await content, ...(await page).data, ...(await layout).data, latestList: (await latestList).data, diff --git a/examples/magento-graphcms/pages/modal/[...url].tsx b/examples/magento-graphcms/pages/modal/[...url].tsx index 4cc77943006..91a65aa38a5 100644 --- a/examples/magento-graphcms/pages/modal/[...url].tsx +++ b/examples/magento-graphcms/pages/modal/[...url].tsx @@ -1,3 +1,4 @@ +import { ContentArea, PageContent, pageContent } from '@graphcommerce/content-areas' import { PageOptions } from '@graphcommerce/framer-next-pages' import { hygraphPageContent, HygraphPagesQuery } from '@graphcommerce/graphcms-ui' import { StoreConfigDocument } from '@graphcommerce/magento-store' @@ -13,13 +14,13 @@ import { GetStaticPaths } from 'next' import { LayoutDocument, LayoutOverlay, LayoutOverlayProps, RowRenderer } from '../../components' import { graphqlSsrClient, graphqlSharedClient } from '../../lib/graphql/graphqlSsrClient' -type Props = HygraphPagesQuery +type Props = HygraphPagesQuery & { content: PageContent } type RouteProps = { url: string[] } type GetPageStaticPaths = GetStaticPaths type GetPageStaticProps = GetStaticProps function ModalPage(props: Props) { - const { pages } = props + const { content, pages } = props const page = pages?.[0] if (!pages?.[0]) return
@@ -45,7 +46,7 @@ function ModalPage(props: Props) { - + ) } @@ -75,13 +76,14 @@ export const getStaticProps: GetPageStaticProps = async ({ locale, params }) => const conf = client.query({ query: StoreConfigDocument }) const page = hygraphPageContent(staticClient, `modal/${urlKey}`) - + const content = pageContent(staticClient, `modal/${urlKey}`) const layout = staticClient.query({ query: LayoutDocument, fetchPolicy: 'cache-first' }) if (!(await page).data.pages?.[0]) return { notFound: true } return { props: { + content: await content, ...(await page).data, ...(await layout).data, apolloState: await conf.then(() => client.cache.extract()), diff --git a/examples/magento-graphcms/pages/newsletter/index.tsx b/examples/magento-graphcms/pages/newsletter/index.tsx index 59afb945934..a7b16ae3273 100644 --- a/examples/magento-graphcms/pages/newsletter/index.tsx +++ b/examples/magento-graphcms/pages/newsletter/index.tsx @@ -1,3 +1,4 @@ +import { ContentArea, PageContent, pageContent } from '@graphcommerce/content-areas' import { PageOptions } from '@graphcommerce/framer-next-pages' import { hygraphPageContent, HygraphPagesQuery } from '@graphcommerce/graphcms-ui' import { GuestNewsletter } from '@graphcommerce/magento-newsletter' @@ -9,15 +10,15 @@ import { LayoutOverlay, LayoutOverlayProps, LayoutNavigationProps, - RowRenderer, } from '../../components' import { graphqlSsrClient, graphqlSharedClient } from '../../lib/graphql/graphqlSsrClient' -type Props = HygraphPagesQuery +type Props = HygraphPagesQuery & { content: PageContent } type RouteProps = { url: string[] } type GetPageStaticProps = GetStaticProps -function NewsletterSubscribe({ pages }: Props) { +function NewsletterSubscribe(props: Props) { + const { content, pages } = props const page = pages?.[0] const title = page.title ?? '' @@ -43,7 +44,7 @@ function NewsletterSubscribe({ pages }: Props) { - + @@ -73,12 +74,14 @@ export const getStaticProps: GetPageStaticProps = async ({ locale }) => { const staticClient = graphqlSsrClient(locale) const conf = client.query({ query: StoreConfigDocument }) const page = hygraphPageContent(staticClient, url) + const content = pageContent(staticClient, url) const layout = staticClient.query({ query: LayoutDocument, fetchPolicy: 'cache-first' }) if (!(await page).data.pages?.[0]) return { notFound: true } return { props: { + content: await content, ...(await page).data, ...(await layout).data, apolloState: await conf.then(() => client.cache.extract()), diff --git a/examples/magento-graphcms/pages/p/[url].tsx b/examples/magento-graphcms/pages/p/[url].tsx index 5c8c5aab765..d6fa8b853d4 100644 --- a/examples/magento-graphcms/pages/p/[url].tsx +++ b/examples/magento-graphcms/pages/p/[url].tsx @@ -1,3 +1,10 @@ +import { + ContentAreaProductPage, + ContentAreaProductPageBefore, + ContentAreaProductPageSidebar, + PageContent, + pageContent, +} from '@graphcommerce/content-areas' import { PageOptions } from '@graphcommerce/framer-next-pages' import { hygraphPageContent, HygraphPagesQuery } from '@graphcommerce/graphcms-ui' import { mergeDeep } from '@graphcommerce/graphql' @@ -43,8 +50,6 @@ import { LayoutNavigation, LayoutNavigationProps, productListRenderer, - RowProduct, - RowRenderer, Usps, } from '../../components' import { UspsDocument, UspsQuery } from '../../components/Usps/Usps.gql' @@ -54,14 +59,16 @@ import { graphqlSharedClient, graphqlSsrClient } from '../../lib/graphql/graphql type Props = HygraphPagesQuery & UspsQuery & ProductPage2Query & - Pick + Pick & { + content: PageContent + } type RouteProps = { url: string } type GetPageStaticPaths = GetStaticPaths type GetPageStaticProps = GetStaticProps function ProductPage(props: Props) { - const { products, relatedUpsells, usps, sidebarUsps, pages, defaultValues } = props + const { content, products, relatedUpsells, usps, sidebarUsps, pages, defaultValues } = props const product = mergeDeep( products?.items?.[0], @@ -91,6 +98,8 @@ function ProductPage(props: Props) { + + ({ @@ -165,6 +174,8 @@ function ProductPage(props: Props) { + + } @@ -172,7 +183,9 @@ function ProductPage(props: Props) { /> - {pages?.[0] && ( + + + {/* {pages?.[0] && ( - )} + )} */} } @@ -229,6 +242,7 @@ export const getStaticProps: GetPageStaticProps = async ({ params, locale }) => ) const pages = hygraphPageContent(staticClient, 'product/global', product, true) + const content = pageContent(staticClient, 'product/global', product, true) if (!(await product)) return redirectOrNotFound(staticClient, conf, params, locale) const category = productPageCategory(await product) @@ -240,6 +254,7 @@ export const getStaticProps: GetPageStaticProps = async ({ params, locale }) => return { props: { + content: await content, ...defaultConfigurableOptionsSelection(urlKey, client, (await productPage).data), ...(await layout).data, ...(await pages).data, diff --git a/examples/magento-graphcms/pages/service/[[...url]].tsx b/examples/magento-graphcms/pages/service/[[...url]].tsx index 725cc4fbb04..edd390d9d63 100644 --- a/examples/magento-graphcms/pages/service/[[...url]].tsx +++ b/examples/magento-graphcms/pages/service/[[...url]].tsx @@ -1,3 +1,4 @@ +import { ContentArea, PageContent, pageContent } from '@graphcommerce/content-areas' import { PageOptions } from '@graphcommerce/framer-next-pages' import { PagesStaticPathsDocument, @@ -14,16 +15,16 @@ import { LayoutOverlay, LayoutOverlayProps, LayoutNavigationProps, - RowRenderer, } from '../../components' import { graphqlSsrClient, graphqlSharedClient } from '../../lib/graphql/graphqlSsrClient' -type Props = HygraphPagesQuery +type Props = HygraphPagesQuery & { content: PageContent } type RouteProps = { url: string[] } type GetPageStaticPaths = GetStaticPaths type GetPageStaticProps = GetStaticProps -function ServicePage({ pages }: Props) { +function ServicePage(props: Props) { + const { content, pages } = props const title = pages?.[0].title ?? '' return ( @@ -42,7 +43,8 @@ function ServicePage({ pages }: Props) { {title} - + + ) } @@ -82,6 +84,7 @@ export const getStaticProps: GetPageStaticProps = async ({ locale, params }) => const staticClient = graphqlSsrClient(locale) const conf = client.query({ query: StoreConfigDocument }) const page = hygraphPageContent(staticClient, url) + const content = pageContent(staticClient, url) const layout = staticClient.query({ query: LayoutDocument, fetchPolicy: 'cache-first' }) if (!(await page).data.pages?.[0]) return { notFound: true } @@ -90,6 +93,7 @@ export const getStaticProps: GetPageStaticProps = async ({ locale, params }) => return { props: { + content: await content, ...(await page).data, ...(await layout).data, up: isRoot ? null : { href: '/service', title: i18n._(/* i18n */ 'Customer Service') }, diff --git a/examples/magento-graphcms/tsconfig.json b/examples/magento-graphcms/tsconfig.json index a8f3f4f9ee9..bd0a33997c5 100644 --- a/examples/magento-graphcms/tsconfig.json +++ b/examples/magento-graphcms/tsconfig.json @@ -17,6 +17,14 @@ "jsxImportSource": "@emotion/react", "incremental": true }, - "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"], + "include": [ + "next-env.d.ts", + "**/*.ts", + "**/*.tsx", + "../../packages/hygraph-ui/components/index.ts", + "../../packages/hygraph-ui/components/PageContentQueryFragment.gql.ts", + "../../packages/hygraph-ui/components/RowRenderer.gql.ts", + "../../packages/hygraph-ui/components/RowRenderer.tsx" + ], "exclude": ["node_modules"] } diff --git a/packages/content-areas/components/ContentArea/Areas.tsx b/packages/content-areas/components/ContentArea/Areas.tsx new file mode 100644 index 00000000000..e230026127e --- /dev/null +++ b/packages/content-areas/components/ContentArea/Areas.tsx @@ -0,0 +1,8 @@ +import { ContentArea } from './ContentArea' + +export const ContentAreaHome = ContentArea +export const ContentAreaProductPageBefore = ContentArea +export const ContentAreaProductPageSidebar = ContentArea +export const ContentAreaProductPage = ContentArea +export const ContentAreaCategoryPageBefore = ContentArea +export const ContentAreaCategoryPage = ContentArea diff --git a/packages/content-areas/components/ContentArea/ContentArea.tsx b/packages/content-areas/components/ContentArea/ContentArea.tsx new file mode 100644 index 00000000000..ccf50151e6e --- /dev/null +++ b/packages/content-areas/components/ContentArea/ContentArea.tsx @@ -0,0 +1,12 @@ +import { ProductListItemRenderer } from '@graphcommerce/magento-product' +import { PageContent } from '../../types' + +export interface ContentAreaProps { + content: PageContent + productListRenderer: ProductListItemRenderer +} + +export function ContentArea(props: ContentAreaProps) { + const { content, productListRenderer } = props + return
+} diff --git a/packages/content-areas/components/ContentArea/index.ts b/packages/content-areas/components/ContentArea/index.ts new file mode 100644 index 00000000000..7a44ba31b63 --- /dev/null +++ b/packages/content-areas/components/ContentArea/index.ts @@ -0,0 +1,2 @@ +export * from './Areas' +export * from './ContentArea' diff --git a/packages/content-areas/components/index.ts b/packages/content-areas/components/index.ts new file mode 100644 index 00000000000..0c5ef136dff --- /dev/null +++ b/packages/content-areas/components/index.ts @@ -0,0 +1 @@ +export * from './ContentArea' diff --git a/packages/content-areas/index.ts b/packages/content-areas/index.ts new file mode 100644 index 00000000000..10061e87466 --- /dev/null +++ b/packages/content-areas/index.ts @@ -0,0 +1,3 @@ +export * from './components' +export * from './server/pageContent' +export * from './types' diff --git a/packages/content-areas/package.json b/packages/content-areas/package.json new file mode 100644 index 00000000000..2ae7b73fc74 --- /dev/null +++ b/packages/content-areas/package.json @@ -0,0 +1,31 @@ +{ + "name": "@graphcommerce/content-areas", + "homepage": "https://www.graphcommerce.org/", + "repository": "github:graphcommerce-org/graphcommerce", + "version": "8.0.0-canary.74", + "sideEffects": false, + "prettier": "@graphcommerce/prettier-config-pwa", + "eslintConfig": { + "extends": "@graphcommerce/eslint-config-pwa", + "parserOptions": { + "project": "./tsconfig.json" + } + }, + "peerDependencies": { + "@graphcommerce/magento-product": "^8.0.0-canary.74", + "@graphcommerce/eslint-config-pwa": "^8.0.0-canary.74", + "@graphcommerce/graphql": "^8.0.0-canary.74", + "@graphcommerce/next-ui": "^8.0.0-canary.74", + "@graphcommerce/prettier-config-pwa": "^8.0.0-canary.74", + "@graphcommerce/react-hook-form": "^8.0.0-canary.74", + "@graphcommerce/typescript-config-pwa": "^8.0.0-canary.74", + "@lingui/core": "^4.2.1", + "@lingui/macro": "^4.2.1", + "@lingui/react": "^4.2.1", + "@mui/material": "^5.10.16", + "framer-motion": "^10.0.0", + "next": "*", + "react": "^18.2.0", + "react-dom": "^18.2.0" + } +} diff --git a/packages/content-areas/server/pageContent.ts b/packages/content-areas/server/pageContent.ts new file mode 100644 index 00000000000..97a90066e0e --- /dev/null +++ b/packages/content-areas/server/pageContent.ts @@ -0,0 +1,11 @@ +import { ApolloClient, NormalizedCacheObject } from '@graphcommerce/graphql' +import { PageContent } from '../types' + +export function pageContent( + client: ApolloClient, + url: string, + additionalProperties?: Promise | object, + cached = false, +): Promise { + return Promise.resolve({}) +} diff --git a/packages/content-areas/types.ts b/packages/content-areas/types.ts new file mode 100644 index 00000000000..2d0e9bbbbdf --- /dev/null +++ b/packages/content-areas/types.ts @@ -0,0 +1 @@ +export interface PageContent {} diff --git a/examples/magento-graphcms/components/GraphCMS/Asset/AssetWithAlt.graphql b/packages/hygraph-ui/components/Asset/AssetWithAlt.graphql similarity index 100% rename from examples/magento-graphcms/components/GraphCMS/Asset/AssetWithAlt.graphql rename to packages/hygraph-ui/components/Asset/AssetWithAlt.graphql diff --git a/packages/hygraph-ui/components/Blog/BlogAuthor.graphql b/packages/hygraph-ui/components/Blog/BlogAuthor.graphql new file mode 100644 index 00000000000..934c0d505cb --- /dev/null +++ b/packages/hygraph-ui/components/Blog/BlogAuthor.graphql @@ -0,0 +1,4 @@ +fragment BlogAuthor on Page { + date + author +} diff --git a/packages/hygraph-ui/components/Blog/BlogAuthor.tsx b/packages/hygraph-ui/components/Blog/BlogAuthor.tsx new file mode 100644 index 00000000000..5c964c91cc9 --- /dev/null +++ b/packages/hygraph-ui/components/Blog/BlogAuthor.tsx @@ -0,0 +1,10 @@ +import { BlogAuthor as NextBlogAuthor } from '@graphcommerce/next-ui' +import { BlogAuthorFragment } from './BlogAuthor.gql' + +type BlogAuthorProps = BlogAuthorFragment + +export function BlogAuthor(props: BlogAuthorProps) { + const { author, date } = props + if (!author) return null + return +} diff --git a/packages/hygraph-ui/components/Blog/BlogHeader.tsx b/packages/hygraph-ui/components/Blog/BlogHeader.tsx new file mode 100644 index 00000000000..68c2b6da2b6 --- /dev/null +++ b/packages/hygraph-ui/components/Blog/BlogHeader.tsx @@ -0,0 +1,11 @@ +import { Asset, AssetFragment } from '@graphcommerce/graphcms-ui' +import { BlogHeader as NextBlogHeader } from '@graphcommerce/next-ui' + +export function BlogHeader(props: { asset?: AssetFragment }) { + const { asset } = props + return ( + : null} + /> + ) +} diff --git a/packages/hygraph-ui/components/Blog/BlogItem.graphql b/packages/hygraph-ui/components/Blog/BlogItem.graphql new file mode 100644 index 00000000000..ee371f34d1a --- /dev/null +++ b/packages/hygraph-ui/components/Blog/BlogItem.graphql @@ -0,0 +1,8 @@ +fragment BlogItem on Page { + title + url + date + asset { + ...Asset + } +} diff --git a/packages/hygraph-ui/components/Blog/BlogItem.tsx b/packages/hygraph-ui/components/Blog/BlogItem.tsx new file mode 100644 index 00000000000..8629246d7ca --- /dev/null +++ b/packages/hygraph-ui/components/Blog/BlogItem.tsx @@ -0,0 +1,38 @@ +import { Asset } from '@graphcommerce/graphcms-ui' +import { BlogListItem } from '@graphcommerce/next-ui' +import { Trans } from '@lingui/react' +import { Typography, useTheme } from '@mui/material' +import { BlogItemFragment } from './BlogItem.gql' + +type BlogItemProps = BlogItemFragment + +export function BlogItem(props: BlogItemProps) { + const { title, url, asset, date } = props + + const theme = useTheme() + + return ( + + ) : ( + + + + ) + } + title={title ?? ''} + date={date} + url={url} + /> + ) +} diff --git a/packages/hygraph-ui/components/Blog/BlogList.graphql b/packages/hygraph-ui/components/Blog/BlogList.graphql new file mode 100644 index 00000000000..c9494ff54b2 --- /dev/null +++ b/packages/hygraph-ui/components/Blog/BlogList.graphql @@ -0,0 +1,14 @@ +query BlogList($currentUrl: [String!]!, $first: Int = 4, $skip: Int = 0) { + blogPosts: pages( + where: { + url_not_starts_with: "blog/tagged/" + url_starts_with: "blog/" + url_not_in: $currentUrl + } + orderBy: date_DESC + first: $first + skip: $skip + ) { + ...BlogItem + } +} diff --git a/packages/hygraph-ui/components/Blog/BlogList.tsx b/packages/hygraph-ui/components/Blog/BlogList.tsx new file mode 100644 index 00000000000..63d3775152b --- /dev/null +++ b/packages/hygraph-ui/components/Blog/BlogList.tsx @@ -0,0 +1,17 @@ +import { BlogItemGrid } from '@graphcommerce/next-ui' +import { BlogItem } from './BlogItem' +import { BlogListQuery } from './BlogList.gql' + +type BlogListProps = BlogListQuery + +export function BlogList(props: BlogListProps) { + const { blogPosts } = props + + return ( + + {blogPosts.map((BlogPost) => ( + + ))} + + ) +} diff --git a/packages/hygraph-ui/components/Blog/BlogListTagged.graphql b/packages/hygraph-ui/components/Blog/BlogListTagged.graphql new file mode 100644 index 00000000000..f30a359337d --- /dev/null +++ b/packages/hygraph-ui/components/Blog/BlogListTagged.graphql @@ -0,0 +1,14 @@ +query BlogListTagged($currentUrl: [String!]!, $first: Int = 4, $skip: Int = 0, $tagged: String) { + blogPosts: pages( + where: { + url_starts_with: "blog/" + relatedPages_some: { url_contains: $tagged } + url_not_in: $currentUrl + } + orderBy: date_DESC + first: $first + skip: $skip + ) { + ...BlogItem + } +} diff --git a/packages/hygraph-ui/components/Blog/BlogPaths.graphql b/packages/hygraph-ui/components/Blog/BlogPaths.graphql new file mode 100644 index 00000000000..40a772cc68e --- /dev/null +++ b/packages/hygraph-ui/components/Blog/BlogPaths.graphql @@ -0,0 +1,7 @@ +query BlogPaths { + pagesConnection(where: { url_not_starts_with: "blog/tagged/", url_starts_with: "blog/" }) { + aggregate { + count + } + } +} diff --git a/packages/hygraph-ui/components/Blog/BlogPostPaths.graphql b/packages/hygraph-ui/components/Blog/BlogPostPaths.graphql new file mode 100644 index 00000000000..340b06a48d6 --- /dev/null +++ b/packages/hygraph-ui/components/Blog/BlogPostPaths.graphql @@ -0,0 +1,5 @@ +query BlogPostPaths { + pages(where: { url_not_starts_with: "blog/tagged/", url_starts_with: "blog/" }) { + url + } +} diff --git a/packages/hygraph-ui/components/Blog/BlogPostTaggedPaths.graphql b/packages/hygraph-ui/components/Blog/BlogPostTaggedPaths.graphql new file mode 100644 index 00000000000..0d8edc4830f --- /dev/null +++ b/packages/hygraph-ui/components/Blog/BlogPostTaggedPaths.graphql @@ -0,0 +1,5 @@ +query BlogPostTaggedPaths { + pages(where: { url_starts_with: "blog/tagged/" }) { + url + } +} diff --git a/packages/hygraph-ui/components/Blog/BlogTags.graphql b/packages/hygraph-ui/components/Blog/BlogTags.graphql new file mode 100644 index 00000000000..f44e2e108b4 --- /dev/null +++ b/packages/hygraph-ui/components/Blog/BlogTags.graphql @@ -0,0 +1,6 @@ +fragment BlogTags on Page { + relatedPages { + title + url + } +} diff --git a/packages/hygraph-ui/components/Blog/BlogTags.tsx b/packages/hygraph-ui/components/Blog/BlogTags.tsx new file mode 100644 index 00000000000..7628013a88f --- /dev/null +++ b/packages/hygraph-ui/components/Blog/BlogTags.tsx @@ -0,0 +1,16 @@ +import { BlogTag, BlogTags as NextBlogTags } from '@graphcommerce/next-ui' +import { BlogTagsFragment } from './BlogTags.gql' + +type BlogTagsProps = BlogTagsFragment + +export function BlogTags(props: BlogTagsProps) { + const { relatedPages } = props + return ( + + {relatedPages.map(({ url, title }) => { + if (!title) return null + return + })} + + ) +} diff --git a/packages/hygraph-ui/components/Blog/RowBlogContent.graphql b/packages/hygraph-ui/components/Blog/RowBlogContent.graphql new file mode 100644 index 00000000000..bd169574849 --- /dev/null +++ b/packages/hygraph-ui/components/Blog/RowBlogContent.graphql @@ -0,0 +1,5 @@ +fragment RowBlogContent on RowBlogContent { + content { + raw + } +} diff --git a/packages/hygraph-ui/components/Blog/RowBlogContent.tsx b/packages/hygraph-ui/components/Blog/RowBlogContent.tsx new file mode 100644 index 00000000000..5b76d12b3db --- /dev/null +++ b/packages/hygraph-ui/components/Blog/RowBlogContent.tsx @@ -0,0 +1,15 @@ +import { RichText } from '@graphcommerce/graphcms-ui' +import { BlogContent } from '@graphcommerce/next-ui' +import { RowBlogContentFragment } from './RowBlogContent.gql' + +type RowBlogContentProps = RowBlogContentFragment + +export function RowBlogContent(props: RowBlogContentProps) { + const { content } = props + if (!content) return null + return ( + + + + ) +} diff --git a/packages/hygraph-ui/components/Blog/index.ts b/packages/hygraph-ui/components/Blog/index.ts new file mode 100644 index 00000000000..86e8ba13c5e --- /dev/null +++ b/packages/hygraph-ui/components/Blog/index.ts @@ -0,0 +1,12 @@ +export * from './BlogAuthor' +export * from './BlogHeader' +export * from './BlogItem' +export * from './BlogList' +export * from './BlogList.gql' +export * from './BlogListTagged.gql' +export * from './BlogPaths.gql' +export * from './BlogPostPaths.gql' +export * from './BlogPostTaggedPaths.gql' +export * from './BlogTags' +export * from './RowBlogContent' +export { BlogTitle } from '@graphcommerce/next-ui' diff --git a/examples/magento-graphcms/components/GraphCMS/PageContentQueryFragment.graphql b/packages/hygraph-ui/components/PageContentQueryFragment.graphql similarity index 100% rename from examples/magento-graphcms/components/GraphCMS/PageContentQueryFragment.graphql rename to packages/hygraph-ui/components/PageContentQueryFragment.graphql diff --git a/examples/magento-graphcms/components/GraphCMS/RowButtonLinkList/RowButtonLinkList.graphql b/packages/hygraph-ui/components/RowButtonLinkList/RowButtonLinkList.graphql similarity index 100% rename from examples/magento-graphcms/components/GraphCMS/RowButtonLinkList/RowButtonLinkList.graphql rename to packages/hygraph-ui/components/RowButtonLinkList/RowButtonLinkList.graphql diff --git a/examples/magento-graphcms/components/GraphCMS/RowButtonLinkList/RowButtonLinkList.tsx b/packages/hygraph-ui/components/RowButtonLinkList/RowButtonLinkList.tsx similarity index 100% rename from examples/magento-graphcms/components/GraphCMS/RowButtonLinkList/RowButtonLinkList.tsx rename to packages/hygraph-ui/components/RowButtonLinkList/RowButtonLinkList.tsx diff --git a/examples/magento-graphcms/components/GraphCMS/RowColumnOne/RowColumnOne.graphql b/packages/hygraph-ui/components/RowColumnOne/RowColumnOne.graphql similarity index 100% rename from examples/magento-graphcms/components/GraphCMS/RowColumnOne/RowColumnOne.graphql rename to packages/hygraph-ui/components/RowColumnOne/RowColumnOne.graphql diff --git a/examples/magento-graphcms/components/GraphCMS/RowColumnOne/RowColumnOne.tsx b/packages/hygraph-ui/components/RowColumnOne/RowColumnOne.tsx similarity index 94% rename from examples/magento-graphcms/components/GraphCMS/RowColumnOne/RowColumnOne.tsx rename to packages/hygraph-ui/components/RowColumnOne/RowColumnOne.tsx index 738b143683e..72d619bb619 100644 --- a/examples/magento-graphcms/components/GraphCMS/RowColumnOne/RowColumnOne.tsx +++ b/packages/hygraph-ui/components/RowColumnOne/RowColumnOne.tsx @@ -1,4 +1,4 @@ -import { RichTextProps } from '@graphcommerce/graphcms-ui' +import { RichTextProps } from '../RichText' import type { RowColumnOneFragment } from './RowColumnOne.gql' import { Default, Message } from './variant' diff --git a/examples/magento-graphcms/components/GraphCMS/RowColumnOne/RowColumnOneBoxed.tsx b/packages/hygraph-ui/components/RowColumnOne/RowColumnOneBoxed.tsx similarity index 85% rename from examples/magento-graphcms/components/GraphCMS/RowColumnOne/RowColumnOneBoxed.tsx rename to packages/hygraph-ui/components/RowColumnOne/RowColumnOneBoxed.tsx index 8805fb51c96..acec494d734 100644 --- a/examples/magento-graphcms/components/GraphCMS/RowColumnOne/RowColumnOneBoxed.tsx +++ b/packages/hygraph-ui/components/RowColumnOne/RowColumnOneBoxed.tsx @@ -1,6 +1,6 @@ -import { RichText } from '@graphcommerce/graphcms-ui' import { ColumnOneBoxed } from '@graphcommerce/next-ui' import { RowColumnOneProps } from './RowColumnOne' +import { RichText } from '../RichText' export function RowColumnOneBoxed(props: RowColumnOneProps) { const { colOne, richTextOne } = props diff --git a/examples/magento-graphcms/components/GraphCMS/RowColumnOne/RowColumnOneCentered.tsx b/packages/hygraph-ui/components/RowColumnOne/RowColumnOneCentered.tsx similarity index 85% rename from examples/magento-graphcms/components/GraphCMS/RowColumnOne/RowColumnOneCentered.tsx rename to packages/hygraph-ui/components/RowColumnOne/RowColumnOneCentered.tsx index 5f8342af2e3..96a123d15bb 100644 --- a/examples/magento-graphcms/components/GraphCMS/RowColumnOne/RowColumnOneCentered.tsx +++ b/packages/hygraph-ui/components/RowColumnOne/RowColumnOneCentered.tsx @@ -1,6 +1,6 @@ -import { RichText } from '@graphcommerce/graphcms-ui' import { ColumnOneCentered } from '@graphcommerce/next-ui' import { RowColumnOneProps } from './RowColumnOne' +import { RichText } from '../RichText' export function RowColumnOneCentered(props: RowColumnOneProps) { const { colOne, richTextOne } = props diff --git a/examples/magento-graphcms/components/GraphCMS/RowColumnOne/RowColumnOneDoubleSpread.tsx b/packages/hygraph-ui/components/RowColumnOne/RowColumnOneDoubleSpread.tsx similarity index 90% rename from examples/magento-graphcms/components/GraphCMS/RowColumnOne/RowColumnOneDoubleSpread.tsx rename to packages/hygraph-ui/components/RowColumnOne/RowColumnOneDoubleSpread.tsx index 14426d0beac..a1e27f7bdb1 100644 --- a/examples/magento-graphcms/components/GraphCMS/RowColumnOne/RowColumnOneDoubleSpread.tsx +++ b/packages/hygraph-ui/components/RowColumnOne/RowColumnOneDoubleSpread.tsx @@ -1,6 +1,6 @@ -import { RichText } from '@graphcommerce/graphcms-ui' import { ColumnOne } from '@graphcommerce/next-ui' import { RowColumnOneFragment } from './RowColumnOne.gql' +import { RichText } from '../RichText' type RowColumnOneDoubleSpreadProps = RowColumnOneFragment diff --git a/examples/magento-graphcms/components/GraphCMS/RowColumnOne/RowColumnOneSpread.tsx b/packages/hygraph-ui/components/RowColumnOne/RowColumnOneSpread.tsx similarity index 89% rename from examples/magento-graphcms/components/GraphCMS/RowColumnOne/RowColumnOneSpread.tsx rename to packages/hygraph-ui/components/RowColumnOne/RowColumnOneSpread.tsx index e27b553d6e6..0571c50c759 100644 --- a/examples/magento-graphcms/components/GraphCMS/RowColumnOne/RowColumnOneSpread.tsx +++ b/packages/hygraph-ui/components/RowColumnOne/RowColumnOneSpread.tsx @@ -1,6 +1,6 @@ -import { RichText } from '@graphcommerce/graphcms-ui' import { ColumnOne } from '@graphcommerce/next-ui' import { RowColumnOneFragment } from './RowColumnOne.gql' +import { RichText } from '../RichText' export function RowColumnOneSpread(props: RowColumnOneFragment) { const { colOne } = props diff --git a/examples/magento-graphcms/components/GraphCMS/RowColumnOne/variant/Default.tsx b/packages/hygraph-ui/components/RowColumnOne/variant/Default.tsx similarity index 85% rename from examples/magento-graphcms/components/GraphCMS/RowColumnOne/variant/Default.tsx rename to packages/hygraph-ui/components/RowColumnOne/variant/Default.tsx index 36d419506ba..e2876c50768 100644 --- a/examples/magento-graphcms/components/GraphCMS/RowColumnOne/variant/Default.tsx +++ b/packages/hygraph-ui/components/RowColumnOne/variant/Default.tsx @@ -1,6 +1,6 @@ -import { RichText, RichTextProps } from '@graphcommerce/graphcms-ui' import { ColumnOne } from '@graphcommerce/next-ui' import type { RowColumnOneFragment } from '../RowColumnOne.gql' +import { RichTextProps, RichText } from '../../RichText' type RowColumnOneProps = RowColumnOneFragment & { richTextOne?: Omit diff --git a/examples/magento-graphcms/components/GraphCMS/RowColumnOne/variant/Message.tsx b/packages/hygraph-ui/components/RowColumnOne/variant/Message.tsx similarity index 86% rename from examples/magento-graphcms/components/GraphCMS/RowColumnOne/variant/Message.tsx rename to packages/hygraph-ui/components/RowColumnOne/variant/Message.tsx index 4d03327457c..a9e823f5df0 100644 --- a/examples/magento-graphcms/components/GraphCMS/RowColumnOne/variant/Message.tsx +++ b/packages/hygraph-ui/components/RowColumnOne/variant/Message.tsx @@ -1,6 +1,6 @@ -import { RichText, RichTextProps } from '@graphcommerce/graphcms-ui' import { VariantMessage } from '@graphcommerce/next-ui' import type { RowColumnOneFragment } from '../RowColumnOne.gql' +import { RichTextProps, RichText } from '../../RichText' type RowColumnOneProps = RowColumnOneFragment & { richTextOne?: Omit diff --git a/examples/magento-graphcms/components/GraphCMS/RowColumnOne/variant/index.tsx b/packages/hygraph-ui/components/RowColumnOne/variant/index.tsx similarity index 100% rename from examples/magento-graphcms/components/GraphCMS/RowColumnOne/variant/index.tsx rename to packages/hygraph-ui/components/RowColumnOne/variant/index.tsx diff --git a/examples/magento-graphcms/components/GraphCMS/RowColumnThree/RowColumnThree.graphql b/packages/hygraph-ui/components/RowColumnThree/RowColumnThree.graphql similarity index 100% rename from examples/magento-graphcms/components/GraphCMS/RowColumnThree/RowColumnThree.graphql rename to packages/hygraph-ui/components/RowColumnThree/RowColumnThree.graphql diff --git a/examples/magento-graphcms/components/GraphCMS/RowColumnThree/RowColumnThree.tsx b/packages/hygraph-ui/components/RowColumnThree/RowColumnThree.tsx similarity index 88% rename from examples/magento-graphcms/components/GraphCMS/RowColumnThree/RowColumnThree.tsx rename to packages/hygraph-ui/components/RowColumnThree/RowColumnThree.tsx index 898cd46e2f9..38ed584bced 100644 --- a/examples/magento-graphcms/components/GraphCMS/RowColumnThree/RowColumnThree.tsx +++ b/packages/hygraph-ui/components/RowColumnThree/RowColumnThree.tsx @@ -1,6 +1,6 @@ -import { RichText } from '@graphcommerce/graphcms-ui' import { ColumnThree } from '@graphcommerce/next-ui' import { RowColumnThreeFragment } from './RowColumnThree.gql' +import { RichText } from '../RichText' export function RowColumnThree(props: RowColumnThreeFragment) { const { colOne, colTwo, colThree } = props diff --git a/examples/magento-graphcms/components/GraphCMS/RowColumnTwo/RowColumnTwo.graphql b/packages/hygraph-ui/components/RowColumnTwo/RowColumnTwo.graphql similarity index 100% rename from examples/magento-graphcms/components/GraphCMS/RowColumnTwo/RowColumnTwo.graphql rename to packages/hygraph-ui/components/RowColumnTwo/RowColumnTwo.graphql diff --git a/examples/magento-graphcms/components/GraphCMS/RowColumnTwo/RowColumnTwo.tsx b/packages/hygraph-ui/components/RowColumnTwo/RowColumnTwo.tsx similarity index 85% rename from examples/magento-graphcms/components/GraphCMS/RowColumnTwo/RowColumnTwo.tsx rename to packages/hygraph-ui/components/RowColumnTwo/RowColumnTwo.tsx index cafb4eabf13..93b861a408e 100644 --- a/examples/magento-graphcms/components/GraphCMS/RowColumnTwo/RowColumnTwo.tsx +++ b/packages/hygraph-ui/components/RowColumnTwo/RowColumnTwo.tsx @@ -1,6 +1,6 @@ -import { RichText } from '@graphcommerce/graphcms-ui' import { ColumnTwo } from '@graphcommerce/next-ui' import { RowColumnTwoFragment } from './RowColumnTwo.gql' +import { RichText } from '../RichText' export function RowColumnTwo(props: RowColumnTwoFragment) { const { colOne, colTwo } = props diff --git a/examples/magento-graphcms/components/GraphCMS/RowColumnTwo/RowColumnTwoSpread.tsx b/packages/hygraph-ui/components/RowColumnTwo/RowColumnTwoSpread.tsx similarity index 90% rename from examples/magento-graphcms/components/GraphCMS/RowColumnTwo/RowColumnTwoSpread.tsx rename to packages/hygraph-ui/components/RowColumnTwo/RowColumnTwoSpread.tsx index 8293653ee8f..c1a64d2ab80 100644 --- a/examples/magento-graphcms/components/GraphCMS/RowColumnTwo/RowColumnTwoSpread.tsx +++ b/packages/hygraph-ui/components/RowColumnTwo/RowColumnTwoSpread.tsx @@ -1,6 +1,7 @@ -import { getNodeLength, RichText } from '@graphcommerce/graphcms-ui' -import { ElementOrTextNode } from '@graphcommerce/graphcms-ui/components/RichText/types' import { ColumnTwoSpread } from '@graphcommerce/next-ui' +import { RichText } from '../RichText' +import { getNodeLength } from '../RichText/getNodeLength' +import { ElementOrTextNode } from '../RichText/types' import { RowColumnTwoFragment } from './RowColumnTwo.gql' const getColumnCount = (props: RowColumnTwoFragment, columnId: number) => { diff --git a/examples/magento-graphcms/components/GraphCMS/RowContentLinks/RowContentLinks.graphql b/packages/hygraph-ui/components/RowContentLinks/RowContentLinks.graphql similarity index 100% rename from examples/magento-graphcms/components/GraphCMS/RowContentLinks/RowContentLinks.graphql rename to packages/hygraph-ui/components/RowContentLinks/RowContentLinks.graphql diff --git a/examples/magento-graphcms/components/GraphCMS/RowContentLinks/RowContentLinks.tsx b/packages/hygraph-ui/components/RowContentLinks/RowContentLinks.tsx similarity index 100% rename from examples/magento-graphcms/components/GraphCMS/RowContentLinks/RowContentLinks.tsx rename to packages/hygraph-ui/components/RowContentLinks/RowContentLinks.tsx diff --git a/examples/magento-graphcms/components/GraphCMS/RowHeroBanner/RowHeroBanner.graphql b/packages/hygraph-ui/components/RowHeroBanner/RowHeroBanner.graphql similarity index 100% rename from examples/magento-graphcms/components/GraphCMS/RowHeroBanner/RowHeroBanner.graphql rename to packages/hygraph-ui/components/RowHeroBanner/RowHeroBanner.graphql diff --git a/examples/magento-graphcms/components/GraphCMS/RowHeroBanner/RowHeroBanner.tsx b/packages/hygraph-ui/components/RowHeroBanner/RowHeroBanner.tsx similarity index 96% rename from examples/magento-graphcms/components/GraphCMS/RowHeroBanner/RowHeroBanner.tsx rename to packages/hygraph-ui/components/RowHeroBanner/RowHeroBanner.tsx index ce590c163d2..87d1d9ede22 100644 --- a/examples/magento-graphcms/components/GraphCMS/RowHeroBanner/RowHeroBanner.tsx +++ b/packages/hygraph-ui/components/RowHeroBanner/RowHeroBanner.tsx @@ -1,7 +1,7 @@ -import { RichText } from '@graphcommerce/graphcms-ui' import { breakpointVal, HeroBanner } from '@graphcommerce/next-ui' import { Button } from '@mui/material' import { RowHeroBannerFragment } from './RowHeroBanner.gql' +import { RichText } from '../RichText' export function RowHeroBanner(props: RowHeroBannerFragment) { const { copy, heroAsset, pageLinks } = props diff --git a/examples/magento-graphcms/components/GraphCMS/RowLinks/RowLinks.graphql b/packages/hygraph-ui/components/RowLinks/RowLinks.graphql similarity index 100% rename from examples/magento-graphcms/components/GraphCMS/RowLinks/RowLinks.graphql rename to packages/hygraph-ui/components/RowLinks/RowLinks.graphql diff --git a/examples/magento-graphcms/components/GraphCMS/RowLinks/RowLinks.tsx b/packages/hygraph-ui/components/RowLinks/RowLinks.tsx similarity index 95% rename from examples/magento-graphcms/components/GraphCMS/RowLinks/RowLinks.tsx rename to packages/hygraph-ui/components/RowLinks/RowLinks.tsx index ae1170169d4..fdcbc50b65a 100644 --- a/examples/magento-graphcms/components/GraphCMS/RowLinks/RowLinks.tsx +++ b/packages/hygraph-ui/components/RowLinks/RowLinks.tsx @@ -1,4 +1,3 @@ -import {} from '@graphcommerce/graphcms-ui' import { RowLinksFragment } from './RowLinks.gql' import { LogoSwiper, ImageLabelSwiper, Inline, Usps } from './variant' diff --git a/examples/magento-graphcms/components/GraphCMS/RowLinks/variant/ImageLabelSwiper.tsx b/packages/hygraph-ui/components/RowLinks/variant/ImageLabelSwiper.tsx similarity index 94% rename from examples/magento-graphcms/components/GraphCMS/RowLinks/variant/ImageLabelSwiper.tsx rename to packages/hygraph-ui/components/RowLinks/variant/ImageLabelSwiper.tsx index 9447f6a5373..a16dbd7f3f4 100644 --- a/examples/magento-graphcms/components/GraphCMS/RowLinks/variant/ImageLabelSwiper.tsx +++ b/packages/hygraph-ui/components/RowLinks/variant/ImageLabelSwiper.tsx @@ -1,7 +1,8 @@ -import { Asset, RichText } from '@graphcommerce/graphcms-ui' import { responsiveVal, VariantImageLabelSwiper } from '@graphcommerce/next-ui' import { Box, ButtonBase, Typography } from '@mui/material' import { RowLinksFragment } from '../RowLinks.gql' +import { Asset } from '../../Asset/Asset' +import { RichText } from '../../RichText' export function ImageLabelSwiper(props: RowLinksFragment) { const { title, rowLinksCopy, pageLinks } = props diff --git a/examples/magento-graphcms/components/GraphCMS/RowLinks/variant/Inline.tsx b/packages/hygraph-ui/components/RowLinks/variant/Inline.tsx similarity index 100% rename from examples/magento-graphcms/components/GraphCMS/RowLinks/variant/Inline.tsx rename to packages/hygraph-ui/components/RowLinks/variant/Inline.tsx diff --git a/examples/magento-graphcms/components/GraphCMS/RowLinks/variant/LogoSwiper.tsx b/packages/hygraph-ui/components/RowLinks/variant/LogoSwiper.tsx similarity index 96% rename from examples/magento-graphcms/components/GraphCMS/RowLinks/variant/LogoSwiper.tsx rename to packages/hygraph-ui/components/RowLinks/variant/LogoSwiper.tsx index 1b87a158a9b..ba1a1953050 100644 --- a/examples/magento-graphcms/components/GraphCMS/RowLinks/variant/LogoSwiper.tsx +++ b/packages/hygraph-ui/components/RowLinks/variant/LogoSwiper.tsx @@ -1,7 +1,7 @@ -import { Asset } from '@graphcommerce/graphcms-ui' import { VariantLogoSwiper } from '@graphcommerce/next-ui' import { Link } from '@mui/material' import { RowLinksFragment } from '../RowLinks.gql' +import { Asset } from '../../Asset/Asset' export function LogoSwiper(props: RowLinksFragment) { const { title, pageLinks } = props diff --git a/examples/magento-graphcms/components/GraphCMS/RowLinks/variant/Usps.tsx b/packages/hygraph-ui/components/RowLinks/variant/Usps.tsx similarity index 96% rename from examples/magento-graphcms/components/GraphCMS/RowLinks/variant/Usps.tsx rename to packages/hygraph-ui/components/RowLinks/variant/Usps.tsx index 77df6834346..7fc6ac33c87 100644 --- a/examples/magento-graphcms/components/GraphCMS/RowLinks/variant/Usps.tsx +++ b/packages/hygraph-ui/components/RowLinks/variant/Usps.tsx @@ -1,8 +1,8 @@ -import { RichText } from '@graphcommerce/graphcms-ui' import { iconCheckmark, IconSvg, VariantUsps } from '@graphcommerce/next-ui' import { Box } from '@mui/material' import { RowLinksFragment } from '../RowLinks.gql' +import { RichText } from '../../RichText' export function Usps(props: RowLinksFragment) { const { title, pageLinks } = props diff --git a/examples/magento-graphcms/components/GraphCMS/RowLinks/variant/index.tsx b/packages/hygraph-ui/components/RowLinks/variant/index.tsx similarity index 100% rename from examples/magento-graphcms/components/GraphCMS/RowLinks/variant/index.tsx rename to packages/hygraph-ui/components/RowLinks/variant/index.tsx diff --git a/examples/magento-graphcms/components/GraphCMS/RowProduct/RowProduct.graphql b/packages/hygraph-ui/components/RowProduct/RowProduct.graphql similarity index 100% rename from examples/magento-graphcms/components/GraphCMS/RowProduct/RowProduct.graphql rename to packages/hygraph-ui/components/RowProduct/RowProduct.graphql diff --git a/examples/magento-graphcms/components/GraphCMS/RowProduct/RowProduct.tsx b/packages/hygraph-ui/components/RowProduct/RowProduct.tsx similarity index 100% rename from examples/magento-graphcms/components/GraphCMS/RowProduct/RowProduct.tsx rename to packages/hygraph-ui/components/RowProduct/RowProduct.tsx diff --git a/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Backstory.tsx b/packages/hygraph-ui/components/RowProduct/variant/Backstory.tsx similarity index 91% rename from examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Backstory.tsx rename to packages/hygraph-ui/components/RowProduct/variant/Backstory.tsx index f57ab4d091b..78c2050c63b 100644 --- a/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Backstory.tsx +++ b/packages/hygraph-ui/components/RowProduct/variant/Backstory.tsx @@ -1,9 +1,9 @@ -import { Asset, RichText } from '@graphcommerce/graphcms-ui' import { AddProductsToCartForm, ProductListItemsFragment } from '@graphcommerce/magento-product' import { ParagraphWithSidebarSlide, RenderType } from '@graphcommerce/next-ui' import { useTheme } from '@mui/material' -import { productListRenderer } from '../../../ProductListItems' +import { productListRenderer } from '../../../../../examples/magento-graphcms/components/ProductListItems' import { RowProductFragment } from '../RowProduct.gql' +import { Asset } from '../../Asset/Asset' type BackstoryProps = RowProductFragment & ProductListItemsFragment diff --git a/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Feature.tsx b/packages/hygraph-ui/components/RowProduct/variant/Feature.tsx similarity index 96% rename from examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Feature.tsx rename to packages/hygraph-ui/components/RowProduct/variant/Feature.tsx index b3dd3d09d44..1e288b05500 100644 --- a/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Feature.tsx +++ b/packages/hygraph-ui/components/RowProduct/variant/Feature.tsx @@ -1,9 +1,9 @@ -import { RichText } from '@graphcommerce/graphcms-ui' import { Image } from '@graphcommerce/image' import { ImageText } from '@graphcommerce/next-ui' import { Typography, useTheme } from '@mui/material' import { RowProductFragment } from '../RowProduct.gql' import { ProductFeatureMediaFragment } from './ProductFeatureMedia.gql' +import { RichText } from '../../RichText' type FeatureProps = RowProductFragment & ProductFeatureMediaFragment diff --git a/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/FeatureBoxed.tsx b/packages/hygraph-ui/components/RowProduct/variant/FeatureBoxed.tsx similarity index 96% rename from examples/magento-graphcms/components/GraphCMS/RowProduct/variant/FeatureBoxed.tsx rename to packages/hygraph-ui/components/RowProduct/variant/FeatureBoxed.tsx index 64f064d578d..040a8f5c71a 100644 --- a/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/FeatureBoxed.tsx +++ b/packages/hygraph-ui/components/RowProduct/variant/FeatureBoxed.tsx @@ -1,9 +1,9 @@ -import { RichText } from '@graphcommerce/graphcms-ui' import { Image } from '@graphcommerce/image' import { ImageTextBoxed, responsiveVal } from '@graphcommerce/next-ui' import { Typography, useTheme } from '@mui/material' import { RowProductFragment } from '../RowProduct.gql' import { ProductFeatureMediaBoxedFragment } from './ProductFeatureMediaBoxed.gql' +import { RichText } from '../../RichText' type FeatureBoxedProps = RowProductFragment & ProductFeatureMediaBoxedFragment diff --git a/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Grid.tsx b/packages/hygraph-ui/components/RowProduct/variant/Grid.tsx similarity index 82% rename from examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Grid.tsx rename to packages/hygraph-ui/components/RowProduct/variant/Grid.tsx index 6fbf98caef0..d36aea4613f 100644 --- a/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Grid.tsx +++ b/packages/hygraph-ui/components/RowProduct/variant/Grid.tsx @@ -1,6 +1,9 @@ import { ContainerWithHeader } from '@graphcommerce/next-ui' import { Link } from '@mui/material' -import { ProductListItems, ProductListItemsProps } from '../../../ProductListItems/ProductListItems' +import { + ProductListItems, + ProductListItemsProps, +} from '../../../../../examples/magento-graphcms/components/ProductListItems/ProductListItems' import { RowProductFragment } from '../RowProduct.gql' type GridProps = RowProductFragment & ProductListItemsProps diff --git a/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/ProductFeatureMedia.graphql b/packages/hygraph-ui/components/RowProduct/variant/ProductFeatureMedia.graphql similarity index 100% rename from examples/magento-graphcms/components/GraphCMS/RowProduct/variant/ProductFeatureMedia.graphql rename to packages/hygraph-ui/components/RowProduct/variant/ProductFeatureMedia.graphql diff --git a/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/ProductFeatureMediaBoxed.graphql b/packages/hygraph-ui/components/RowProduct/variant/ProductFeatureMediaBoxed.graphql similarity index 100% rename from examples/magento-graphcms/components/GraphCMS/RowProduct/variant/ProductFeatureMediaBoxed.graphql rename to packages/hygraph-ui/components/RowProduct/variant/ProductFeatureMediaBoxed.graphql diff --git a/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Related.tsx b/packages/hygraph-ui/components/RowProduct/variant/Related.tsx similarity index 89% rename from examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Related.tsx rename to packages/hygraph-ui/components/RowProduct/variant/Related.tsx index 9791fc73cd3..af2fef1ed6a 100644 --- a/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Related.tsx +++ b/packages/hygraph-ui/components/RowProduct/variant/Related.tsx @@ -6,7 +6,7 @@ import { SidebarSliderProps, } from '@graphcommerce/next-ui' import { Typography } from '@mui/material' -import { productListRenderer } from '../../../ProductListItems/productListRenderer' +import { productListRenderer } from '../../../../../examples/magento-graphcms/components/ProductListItems/productListRenderer' import { RowProductFragment } from '../RowProduct.gql' type RelatedProps = RowProductFragment & RelatedProductsFragment & Pick diff --git a/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Reviews.tsx b/packages/hygraph-ui/components/RowProduct/variant/Reviews.tsx similarity index 100% rename from examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Reviews.tsx rename to packages/hygraph-ui/components/RowProduct/variant/Reviews.tsx diff --git a/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Specs.tsx b/packages/hygraph-ui/components/RowProduct/variant/Specs.tsx similarity index 100% rename from examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Specs.tsx rename to packages/hygraph-ui/components/RowProduct/variant/Specs.tsx diff --git a/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Swipeable.tsx b/packages/hygraph-ui/components/RowProduct/variant/Swipeable.tsx similarity index 91% rename from examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Swipeable.tsx rename to packages/hygraph-ui/components/RowProduct/variant/Swipeable.tsx index 62d6e7354fe..ab8a0ad68df 100644 --- a/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Swipeable.tsx +++ b/packages/hygraph-ui/components/RowProduct/variant/Swipeable.tsx @@ -6,7 +6,7 @@ import { SidebarSliderProps, } from '@graphcommerce/next-ui' import { Typography } from '@mui/material' -import { productListRenderer } from '../../../ProductListItems/productListRenderer' +import { productListRenderer } from '../../../../../examples/magento-graphcms/components/ProductListItems/productListRenderer' import { RowProductFragment } from '../RowProduct.gql' type SwipeableProps = RowProductFragment & ProductListItemsFragment & Pick diff --git a/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Upsells.tsx b/packages/hygraph-ui/components/RowProduct/variant/Upsells.tsx similarity index 89% rename from examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Upsells.tsx rename to packages/hygraph-ui/components/RowProduct/variant/Upsells.tsx index ab1a496cbed..859e6eae6e6 100644 --- a/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Upsells.tsx +++ b/packages/hygraph-ui/components/RowProduct/variant/Upsells.tsx @@ -6,7 +6,7 @@ import { SidebarSliderProps, } from '@graphcommerce/next-ui' import { Typography } from '@mui/material' -import { productListRenderer } from '../../../ProductListItems/productListRenderer' +import { productListRenderer } from '../../../../../examples/magento-graphcms/components/ProductListItems/productListRenderer' import { RowProductFragment } from '../RowProduct.gql' type UpsellsProps = RowProductFragment & UpsellProductsFragment & Pick diff --git a/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/index.tsx b/packages/hygraph-ui/components/RowProduct/variant/index.tsx similarity index 100% rename from examples/magento-graphcms/components/GraphCMS/RowProduct/variant/index.tsx rename to packages/hygraph-ui/components/RowProduct/variant/index.tsx diff --git a/examples/magento-graphcms/components/GraphCMS/RowQuote/RowQuote.graphql b/packages/hygraph-ui/components/RowQuote/RowQuote.graphql similarity index 100% rename from examples/magento-graphcms/components/GraphCMS/RowQuote/RowQuote.graphql rename to packages/hygraph-ui/components/RowQuote/RowQuote.graphql diff --git a/examples/magento-graphcms/components/GraphCMS/RowQuote/RowQuote.tsx b/packages/hygraph-ui/components/RowQuote/RowQuote.tsx similarity index 93% rename from examples/magento-graphcms/components/GraphCMS/RowQuote/RowQuote.tsx rename to packages/hygraph-ui/components/RowQuote/RowQuote.tsx index b41a13822b8..a26bcf69f94 100644 --- a/examples/magento-graphcms/components/GraphCMS/RowQuote/RowQuote.tsx +++ b/packages/hygraph-ui/components/RowQuote/RowQuote.tsx @@ -1,6 +1,6 @@ -import { RichText } from '@graphcommerce/graphcms-ui' import { Quote } from '@graphcommerce/next-ui' import React from 'react' +import { RichText } from '../RichText' import { RowQuoteFragment } from './RowQuote.gql' type RowQuoteProps = RowQuoteFragment diff --git a/examples/magento-graphcms/components/GraphCMS/RowRenderer.graphql b/packages/hygraph-ui/components/RowRenderer.graphql similarity index 100% rename from examples/magento-graphcms/components/GraphCMS/RowRenderer.graphql rename to packages/hygraph-ui/components/RowRenderer.graphql diff --git a/examples/magento-graphcms/components/GraphCMS/RowRenderer.tsx b/packages/hygraph-ui/components/RowRenderer.tsx similarity index 94% rename from examples/magento-graphcms/components/GraphCMS/RowRenderer.tsx rename to packages/hygraph-ui/components/RowRenderer.tsx index 34e560e34d4..ad8acc67e1a 100644 --- a/examples/magento-graphcms/components/GraphCMS/RowRenderer.tsx +++ b/packages/hygraph-ui/components/RowRenderer.tsx @@ -1,5 +1,5 @@ import { LazyHydrate, RenderType, TypeRenderer } from '@graphcommerce/next-ui' -import { RowBlogContent } from '../Blog' +// import { RowBlogContent } from '../../../examples/magento-graphcms/components/Blog' import { PageContentQueryFragment } from './PageContentQueryFragment.gql' import { RowButtonLinkList } from './RowButtonLinkList/RowButtonLinkList' import { RowColumnOne } from './RowColumnOne/RowColumnOne' @@ -23,7 +23,7 @@ const defaultRenderer: Partial = { RowHeroBanner, RowSpecialBanner, RowQuote, - RowBlogContent, + // RowBlogContent, RowButtonLinkList, RowServiceOptions, RowContentLinks, diff --git a/examples/magento-graphcms/components/GraphCMS/RowServiceOptions/RowServiceOptions.graphql b/packages/hygraph-ui/components/RowServiceOptions/RowServiceOptions.graphql similarity index 100% rename from examples/magento-graphcms/components/GraphCMS/RowServiceOptions/RowServiceOptions.graphql rename to packages/hygraph-ui/components/RowServiceOptions/RowServiceOptions.graphql diff --git a/examples/magento-graphcms/components/GraphCMS/RowServiceOptions/RowServiceOptions.tsx b/packages/hygraph-ui/components/RowServiceOptions/RowServiceOptions.tsx similarity index 95% rename from examples/magento-graphcms/components/GraphCMS/RowServiceOptions/RowServiceOptions.tsx rename to packages/hygraph-ui/components/RowServiceOptions/RowServiceOptions.tsx index cade4920302..504c2c611d0 100644 --- a/examples/magento-graphcms/components/GraphCMS/RowServiceOptions/RowServiceOptions.tsx +++ b/packages/hygraph-ui/components/RowServiceOptions/RowServiceOptions.tsx @@ -1,4 +1,3 @@ -import { RichText } from '@graphcommerce/graphcms-ui' import { IconBlock, IconBlocks, @@ -8,6 +7,7 @@ import { IconSvg, } from '@graphcommerce/next-ui' import { RowServiceOptionsFragment } from './RowServiceOptions.gql' +import { RichText } from '../RichText' type RowServiceOptionsProps = RowServiceOptionsFragment diff --git a/examples/magento-graphcms/components/GraphCMS/RowSpecialBanner/RowSpecialBanner.graphql b/packages/hygraph-ui/components/RowSpecialBanner/RowSpecialBanner.graphql similarity index 100% rename from examples/magento-graphcms/components/GraphCMS/RowSpecialBanner/RowSpecialBanner.graphql rename to packages/hygraph-ui/components/RowSpecialBanner/RowSpecialBanner.graphql diff --git a/examples/magento-graphcms/components/GraphCMS/RowSpecialBanner/RowSpecialBanner.tsx b/packages/hygraph-ui/components/RowSpecialBanner/RowSpecialBanner.tsx similarity index 94% rename from examples/magento-graphcms/components/GraphCMS/RowSpecialBanner/RowSpecialBanner.tsx rename to packages/hygraph-ui/components/RowSpecialBanner/RowSpecialBanner.tsx index 6bde87c3b32..884b4080b2e 100644 --- a/examples/magento-graphcms/components/GraphCMS/RowSpecialBanner/RowSpecialBanner.tsx +++ b/packages/hygraph-ui/components/RowSpecialBanner/RowSpecialBanner.tsx @@ -1,7 +1,8 @@ -import { RichText, Asset } from '@graphcommerce/graphcms-ui' import { breakpointVal, SpecialBanner } from '@graphcommerce/next-ui' import { Link } from '@mui/material' import { RowSpecialBannerFragment } from './RowSpecialBanner.gql' +import { Asset } from '../Asset/Asset' +import { RichText } from '../RichText' type RowSpecialBannerProps = RowSpecialBannerFragment diff --git a/packages/hygraph-ui/components/index.ts b/packages/hygraph-ui/components/index.ts index ba63b58aa0a..3201a9e1413 100644 --- a/packages/hygraph-ui/components/index.ts +++ b/packages/hygraph-ui/components/index.ts @@ -1,2 +1,7 @@ export * from './RichText' export * from './Asset/Asset' + +export * from './RowProduct/RowProduct' + +// The actual renderer +export * from './RowRenderer' diff --git a/packages/hygraph-ui/lib/hygraphPageContent.ts b/packages/hygraph-ui/lib/hygraphPageContent.ts index d9b1102f011..944e73ff0b5 100644 --- a/packages/hygraph-ui/lib/hygraphPageContent.ts +++ b/packages/hygraph-ui/lib/hygraphPageContent.ts @@ -1,4 +1,4 @@ -import { ApolloClient, NormalizedCacheObject } from '@graphcommerce/graphql' +import type { ApolloClient, NormalizedCacheObject } from '@graphcommerce/graphql' import { HygraphAllPagesDocument, HygraphPagesQuery, HygraphPagesDocument } from '../graphql' /** diff --git a/packages/hygraph-ui/package.json b/packages/hygraph-ui/package.json index ff665e03e82..4999940eca1 100644 --- a/packages/hygraph-ui/package.json +++ b/packages/hygraph-ui/package.json @@ -12,9 +12,11 @@ } }, "peerDependencies": { + "@graphcommerce/ecommerce-ui": "^8.0.0-canary.74", "@graphcommerce/eslint-config-pwa": "^8.0.0-canary.74", "@graphcommerce/graphql": "^8.0.0-canary.74", "@graphcommerce/image": "^8.0.0-canary.74", + "@graphcommerce/next-config": "^8.0.0-canary.74", "@graphcommerce/next-ui": "^8.0.0-canary.74", "@graphcommerce/prettier-config-pwa": "^8.0.0-canary.74", "@graphcommerce/typescript-config-pwa": "^8.0.0-canary.74", diff --git a/packages/hygraph-ui/plugins/HygraphContentArea.tsx b/packages/hygraph-ui/plugins/HygraphContentArea.tsx new file mode 100644 index 00000000000..6da03530d97 --- /dev/null +++ b/packages/hygraph-ui/plugins/HygraphContentArea.tsx @@ -0,0 +1,20 @@ +import type { ContentArea } from '@graphcommerce/content-areas' +import type { ReactPlugin } from '@graphcommerce/next-config' +import { RowRenderer } from '../components' + +export const component = 'ContentArea' +export const exported = '@graphcommerce/content-areas/components/ContentArea/ContentArea' + +const HygraphContentArea: ReactPlugin = (props) => { + const { Prev, ...rest } = props + const { content } = props + + return ( + <> + + {content.hygraphPage && } + + ) +} + +export const Plugin = HygraphContentArea diff --git a/packages/hygraph-ui/plugins/hygraphPageContentPlugin.ts b/packages/hygraph-ui/plugins/hygraphPageContentPlugin.ts new file mode 100644 index 00000000000..b89e7a336d0 --- /dev/null +++ b/packages/hygraph-ui/plugins/hygraphPageContentPlugin.ts @@ -0,0 +1,26 @@ +import type { pageContent } from '@graphcommerce/content-areas' +import type { MethodPlugin } from '@graphcommerce/next-config' +import { hygraphPageContent } from '..' + +export const func = 'pageContent' +export const exported = '@graphcommerce/content-areas/server/pageContent' + +const hygraphPageContentPlugin: MethodPlugin = async ( + prev, + client, + url, + additionalProperties, + cached, +) => { + const [prevResults, content] = await Promise.all([ + prev(client, url, additionalProperties, cached), + hygraphPageContent(client, url, additionalProperties, cached), + ]) + + return { + ...prevResults, + hygraphPage: content.data.pages?.[0], + } +} + +export const plugin = hygraphPageContentPlugin diff --git a/packages/hygraph-ui/types.ts b/packages/hygraph-ui/types.ts new file mode 100644 index 00000000000..3e43eef6713 --- /dev/null +++ b/packages/hygraph-ui/types.ts @@ -0,0 +1,13 @@ +import { HygraphPageFragment } from './graphql' + +declare module '@graphcommerce/content-areas/components/ContentArea' { + export interface ContentAreaProps { + renderer: string + } +} + +declare module '@graphcommerce/content-areas/types' { + export interface PageContent { + hygraphPage?: HygraphPageFragment | null | undefined + } +} diff --git a/packages/magento-product/components/ProductListItems/getFilterTypes.ts b/packages/magento-product/components/ProductListItems/getFilterTypes.ts index 1c2f4cd954c..cab9d8c345d 100644 --- a/packages/magento-product/components/ProductListItems/getFilterTypes.ts +++ b/packages/magento-product/components/ProductListItems/getFilterTypes.ts @@ -1,4 +1,5 @@ -import { gql, ApolloClient, NormalizedCacheObject, TypedDocumentNode } from '@graphcommerce/graphql' +import type { ApolloClient, NormalizedCacheObject, TypedDocumentNode } from '@graphcommerce/graphql' +import { gql } from '@graphcommerce/graphql/apollo' import type { Exact } from '@graphcommerce/graphql-mesh' type FilterInputTypesQueryVariables = Exact<{ [key: string]: never }> diff --git a/yarn.lock b/yarn.lock index 055c99bd05b..d4ac5a46cfe 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2668,6 +2668,27 @@ __metadata: languageName: unknown linkType: soft +"@graphcommerce/content-areas@workspace:packages/content-areas": + version: 0.0.0-use.local + resolution: "@graphcommerce/content-areas@workspace:packages/content-areas" + peerDependencies: + "@graphcommerce/eslint-config-pwa": ^8.0.0-canary.74 + "@graphcommerce/graphql": ^8.0.0-canary.74 + "@graphcommerce/next-ui": ^8.0.0-canary.74 + "@graphcommerce/prettier-config-pwa": ^8.0.0-canary.74 + "@graphcommerce/react-hook-form": ^8.0.0-canary.74 + "@graphcommerce/typescript-config-pwa": ^8.0.0-canary.74 + "@lingui/core": ^4.2.1 + "@lingui/macro": ^4.2.1 + "@lingui/react": ^4.2.1 + "@mui/material": ^5.10.16 + framer-motion: ^10.0.0 + next: "*" + react: ^18.2.0 + react-dom: ^18.2.0 + languageName: unknown + linkType: soft + "@graphcommerce/demo-magento-graphcommerce@npm:8.0.0-canary.74, @graphcommerce/demo-magento-graphcommerce@workspace:packages/demo-magento-graphcommerce": version: 0.0.0-use.local resolution: "@graphcommerce/demo-magento-graphcommerce@workspace:packages/demo-magento-graphcommerce" @@ -2938,9 +2959,11 @@ __metadata: version: 0.0.0-use.local resolution: "@graphcommerce/graphcms-ui@workspace:packages/hygraph-ui" peerDependencies: + "@graphcommerce/ecommerce-ui": ^8.0.0-canary.74 "@graphcommerce/eslint-config-pwa": ^8.0.0-canary.74 "@graphcommerce/graphql": ^8.0.0-canary.74 "@graphcommerce/image": ^8.0.0-canary.74 + "@graphcommerce/next-config": ^8.0.0-canary.74 "@graphcommerce/next-ui": ^8.0.0-canary.74 "@graphcommerce/prettier-config-pwa": ^8.0.0-canary.74 "@graphcommerce/typescript-config-pwa": ^8.0.0-canary.74 From d7fd6e986179199ea31d7557ee98f9f74af2bf79 Mon Sep 17 00:00:00 2001 From: Paul Hachmang Date: Mon, 8 Jan 2024 14:44:24 +0100 Subject: [PATCH 02/33] =?UTF-8?q?Implement=20metadata=20based=20on=20next?= =?UTF-8?q?=E2=80=99s=20new=20metadata=20object?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- examples/magento-graphcms/pages/[...url].tsx | 28 +-- .../magento-graphcms/pages/blog/[url].tsx | 11 +- .../pages/blog/page/[page].tsx | 10 +- .../pages/blog/tagged/[url].tsx | 26 ++- examples/magento-graphcms/pages/index.tsx | 29 +--- .../magento-graphcms/pages/modal/[...url].tsx | 45 ++--- .../pages/newsletter/index.tsx | 22 +-- examples/magento-graphcms/pages/p/[url].tsx | 22 +-- .../pages/service/[[...url]].tsx | 25 +-- packages/content-areas/index.ts | 1 + .../content-areas/server/resolveMetadata.ts | 164 ++++++++++++++++++ packages/content-areas/types.ts | 9 +- .../RowProduct/variant/Backstory.tsx | 4 +- .../components/RowProduct/variant/Related.tsx | 1 - .../RowProduct/variant/Swipeable.tsx | 1 - .../components/RowProduct/variant/Upsells.tsx | 1 - .../plugins/hygraphPageContentPlugin.ts | 17 +- packages/next-ui/PageMeta/PageMeta.tsx | 17 +- packages/next-ui/PageMeta/PageMetaNew.tsx | 55 ++++++ 19 files changed, 333 insertions(+), 155 deletions(-) create mode 100644 packages/content-areas/server/resolveMetadata.ts create mode 100644 packages/next-ui/PageMeta/PageMetaNew.tsx diff --git a/examples/magento-graphcms/pages/[...url].tsx b/examples/magento-graphcms/pages/[...url].tsx index 932e532e1b0..612fb63032e 100644 --- a/examples/magento-graphcms/pages/[...url].tsx +++ b/examples/magento-graphcms/pages/[...url].tsx @@ -5,7 +5,7 @@ import { PageContent, } from '@graphcommerce/content-areas' import { PageOptions } from '@graphcommerce/framer-next-pages' -import { Asset, hygraphPageContent, HygraphPagesQuery } from '@graphcommerce/graphcms-ui' +import { Asset } from '@graphcommerce/graphcms-ui' import { flushMeasurePerf } from '@graphcommerce/graphql' import { CategoryChildren, @@ -35,6 +35,7 @@ import { LayoutDocument, LayoutNavigation, LayoutNavigationProps, + productListRenderer, RowProduct, RowRenderer, } from '../components' @@ -42,7 +43,6 @@ import { CategoryPageDocument, CategoryPageQuery } from '../graphql/CategoryPage import { graphqlSharedClient, graphqlSsrClient } from '../lib/graphql/graphqlSsrClient' export type CategoryProps = CategoryPageQuery & - HygraphPagesQuery & ProductListQuery & ProductFiltersQuery & { filterTypes?: FilterTypes @@ -55,29 +55,21 @@ type GetPageStaticPaths = GetStaticPaths type GetPageStaticProps = GetStaticProps function CategoryPage(props: CategoryProps) { - const { content, categories, products, filters, params, filterTypes, pages } = props + const { content, categories, products, filters, params, filterTypes } = props const category = categories?.items?.[0] const isLanding = category?.display_mode === 'PAGE' - const page = pages?.[0] const isCategory = params && category && products?.items && filterTypes return ( <> - + - + - {category?.name ?? page.title} + {category?.name ?? content.title} {!isLanding && ( @@ -99,7 +91,6 @@ function CategoryPage(props: CategoryProps) { {isCategory && isLanding && ( } title={{category?.name}} /> )} @@ -119,7 +110,7 @@ function CategoryPage(props: CategoryProps) { )} - + {/* {page && ( if (productListParams) productListParams.filters.category_uid = { in: [categoryUid] } } - const pages = hygraphPageContent(staticClient, url, category) const content = pageContent(staticClient, url, category) - const hasPage = filteredCategoryUid ? false : (await pages).data.pages.length > 0 + const hasPage = filteredCategoryUid ? false : (await content).notFound !== true const hasCategory = Boolean(productListParams && categoryUid) if (!productListParams || !(hasPage || hasCategory)) @@ -194,7 +184,6 @@ export const getStaticProps: GetPageStaticProps = async ({ params, locale }) => props: { content: await content, ...(await categoryPage).data, - ...(await pages).data, ...(await layout).data, apolloState: await conf.then(() => client.cache.extract()), }, @@ -230,7 +219,6 @@ export const getStaticProps: GetPageStaticProps = async ({ params, locale }) => content: await content, ...(await categoryPage).data, ...(await products).data, - ...(await pages).data, ...(await filters).data, ...(await layout).data, filterTypes: await filterTypes, diff --git a/examples/magento-graphcms/pages/blog/[url].tsx b/examples/magento-graphcms/pages/blog/[url].tsx index d939b1ced08..01fd1f86737 100644 --- a/examples/magento-graphcms/pages/blog/[url].tsx +++ b/examples/magento-graphcms/pages/blog/[url].tsx @@ -1,6 +1,5 @@ import { ContentArea, PageContent, pageContent } from '@graphcommerce/content-areas' import { PageOptions } from '@graphcommerce/framer-next-pages' -import { hygraphPageContent, HygraphPagesQuery } from '@graphcommerce/graphcms-ui' import { StoreConfigDocument } from '@graphcommerce/magento-store' import { PageMeta, @@ -22,11 +21,11 @@ import { LayoutDocument, LayoutNavigation, LayoutNavigationProps, - RowRenderer, + productListRenderer, } from '../../components' import { graphqlSharedClient, graphqlSsrClient } from '../../lib/graphql/graphqlSsrClient' -type Props = HygraphPagesQuery & BlogListQuery & { content: PageContent } +type Props = BlogListQuery & { content: PageContent } type RouteProps = { url: string } type GetPageStaticPaths = GetStaticPaths type GetPageStaticProps = GetStaticProps @@ -52,7 +51,7 @@ function BlogPage(props: Props) { {page.author ? : null} {page.asset ? : null} - + @@ -90,7 +89,6 @@ export const getStaticProps: GetPageStaticProps = async ({ locale, params }) => const limit = 4 const conf = client.query({ query: StoreConfigDocument }) - const page = hygraphPageContent(staticClient, `blog/${urlKey}`) const content = pageContent(staticClient, `blog/${urlKey}`) const layout = staticClient.query({ query: LayoutDocument, fetchPolicy: 'cache-first' }) @@ -98,12 +96,11 @@ export const getStaticProps: GetPageStaticProps = async ({ locale, params }) => query: BlogListDocument, variables: { currentUrl: [`blog/${urlKey}`], first: limit }, }) - if (!(await page).data.pages?.[0]) return { notFound: true } + if ((await content).notFound) return { notFound: true } return { props: { content: await content, - ...(await page).data, ...(await blogPosts).data, ...(await layout).data, up: { href: '/', title: 'Home' }, diff --git a/examples/magento-graphcms/pages/blog/page/[page].tsx b/examples/magento-graphcms/pages/blog/page/[page].tsx index fbdd4092a9a..58f7951c4b5 100644 --- a/examples/magento-graphcms/pages/blog/page/[page].tsx +++ b/examples/magento-graphcms/pages/blog/page/[page].tsx @@ -1,6 +1,5 @@ import { ContentArea, PageContent, pageContent } from '@graphcommerce/content-areas' import { PageOptions } from '@graphcommerce/framer-next-pages' -import { hygraphPageContent, HygraphPagesQuery } from '@graphcommerce/graphcms-ui' import { StoreConfigDocument } from '@graphcommerce/magento-store' import { PageMeta, @@ -22,10 +21,11 @@ import { LayoutDocument, LayoutNavigation, LayoutNavigationProps, + productListRenderer, } from '../../../components' import { graphqlSsrClient, graphqlSharedClient } from '../../../lib/graphql/graphqlSsrClient' -type Props = HygraphPagesQuery & BlogListQuery & BlogPathsQuery & { content: PageContent } +type Props = BlogListQuery & BlogPathsQuery & { content: PageContent } type RouteProps = { page: string } type GetPageStaticPaths = GetStaticPaths type GetPageStaticProps = GetStaticProps @@ -63,7 +63,7 @@ function BlogPage(props: Props) { )} /> - + ) } @@ -98,7 +98,6 @@ export const getStaticProps: GetPageStaticProps = async ({ locale, params }) => const staticClient = graphqlSsrClient(locale) const conf = client.query({ query: StoreConfigDocument }) - const defaultPage = hygraphPageContent(staticClient, 'blog') const content = pageContent(staticClient, 'blog') const layout = staticClient.query({ query: LayoutDocument, fetchPolicy: 'cache-first' }) @@ -108,14 +107,13 @@ export const getStaticProps: GetPageStaticProps = async ({ locale, params }) => }) const blogPaths = staticClient.query({ query: BlogPathsDocument }) - if (!(await defaultPage).data.pages?.[0]) return { notFound: true } + if ((await content).notFound) return { notFound: true } if (!(await blogPosts).data.blogPosts.length) return { notFound: true } if (Number(params?.page) <= 0) return { notFound: true } return { props: { content: await content, - ...(await defaultPage).data, ...(await blogPosts).data, ...(await blogPaths).data, ...(await layout).data, diff --git a/examples/magento-graphcms/pages/blog/tagged/[url].tsx b/examples/magento-graphcms/pages/blog/tagged/[url].tsx index c7caa20e6db..c43aff6a589 100644 --- a/examples/magento-graphcms/pages/blog/tagged/[url].tsx +++ b/examples/magento-graphcms/pages/blog/tagged/[url].tsx @@ -1,6 +1,5 @@ import { ContentArea, PageContent, pageContent } from '@graphcommerce/content-areas' import { PageOptions } from '@graphcommerce/framer-next-pages' -import { hygraphPageContent, HygraphPagesQuery } from '@graphcommerce/graphcms-ui' import { StoreConfigDocument } from '@graphcommerce/magento-store' import { PageMeta, GetStaticProps, Row, LayoutTitle, LayoutHeader } from '@graphcommerce/next-ui' import { Trans } from '@lingui/react' @@ -17,36 +16,35 @@ import { LayoutDocument, LayoutNavigation, LayoutNavigationProps, + productListRenderer, } from '../../../components' import { graphqlSsrClient, graphqlSharedClient } from '../../../lib/graphql/graphqlSsrClient' -type Props = HygraphPagesQuery & BlogListTaggedQuery & { content: PageContent } +type Props = BlogListTaggedQuery & { content: PageContent } type RouteProps = { url: string } type GetPageStaticPaths = GetStaticPaths type GetPageStaticProps = GetStaticProps function BlogPage(props: Props) { - const { content, pages, blogPosts } = props - const page = pages[0] - const title = page.title ?? '' + const { content, blogPosts } = props return ( <> - {title} + {content.title} - + - + - {page.author ? : null} - {page.asset ? : null} + {/* {page.author ? : null} */} + {/* {page.asset ? : null} */} - - + + {/* */} @@ -83,7 +81,6 @@ export const getStaticProps: GetPageStaticProps = async ({ locale, params }) => const staticClient = graphqlSsrClient(locale) const limit = 99 const conf = client.query({ query: StoreConfigDocument }) - const page = hygraphPageContent(staticClient, `blog/tagged/${urlKey}`) const content = pageContent(staticClient, `blog/tagged/${urlKey}`) const layout = staticClient.query({ query: LayoutDocument, fetchPolicy: 'cache-first' }) @@ -91,12 +88,11 @@ export const getStaticProps: GetPageStaticProps = async ({ locale, params }) => query: BlogListTaggedDocument, variables: { currentUrl: [`blog/tagged/${urlKey}`], first: limit, tagged: params?.url }, }) - if (!(await page).data.pages?.[0]) return { notFound: true } + if ((await content).notFound) return { notFound: true } return { props: { content: await content, - ...(await page).data, ...(await blogPosts).data, ...(await layout).data, up: { href: '/blog', title: 'Blog' }, diff --git a/examples/magento-graphcms/pages/index.tsx b/examples/magento-graphcms/pages/index.tsx index 7ed47e04c55..fecb134edae 100644 --- a/examples/magento-graphcms/pages/index.tsx +++ b/examples/magento-graphcms/pages/index.tsx @@ -1,11 +1,5 @@ -import { - ContentAreaHome, - ContentAreaProps, - PageContent, - pageContent, -} from '@graphcommerce/content-areas' +import { ContentAreaHome, PageContent, pageContent } from '@graphcommerce/content-areas' import { PageOptions } from '@graphcommerce/framer-next-pages' -import { hygraphPageContent, HygraphPagesQuery } from '@graphcommerce/graphcms-ui' import { ProductListDocument, ProductListQuery } from '@graphcommerce/magento-product' import { StoreConfigDocument } from '@graphcommerce/magento-store' import { GetStaticProps, LayoutHeader, MetaRobots, PageMeta } from '@graphcommerce/next-ui' @@ -13,12 +7,11 @@ import { LayoutDocument, LayoutNavigation, LayoutNavigationProps, - RowProduct, - RowRenderer, + productListRenderer, } from '../components' import { graphqlSharedClient, graphqlSsrClient } from '../lib/graphql/graphqlSsrClient' -type Props = HygraphPagesQuery & { +type Props = { latestList: ProductListQuery favoritesList: ProductListQuery swipableList: ProductListQuery @@ -28,8 +21,7 @@ type RouteProps = { url: string } type GetPageStaticProps = GetStaticProps function CmsPage(props: Props) { - const { content, pages, latestList, favoritesList, swipableList } = props - const page = pages?.[0] + const { content, latestList, favoritesList, swipableList } = props const latest = latestList?.products?.items?.[0] const favorite = favoritesList?.products?.items?.[0] @@ -37,16 +29,11 @@ function CmsPage(props: Props) { return ( <> - + - + {/* {page && ( { const staticClient = graphqlSsrClient(locale) const conf = client.query({ query: StoreConfigDocument }) - const page = hygraphPageContent(staticClient, 'page/home') const content = pageContent(staticClient, 'page/home') const layout = staticClient.query({ query: LayoutDocument, fetchPolicy: 'cache-first' }) @@ -107,12 +93,11 @@ export const getStaticProps: GetPageStaticProps = async ({ locale }) => { variables: { pageSize: 8, filters: { category_uid: { eq: 'MTIy' } } }, }) - if (!(await page).data.pages?.[0]) return { notFound: true } + if ((await content).notFound) return { notFound: true } return { props: { content: await content, - ...(await page).data, ...(await layout).data, latestList: (await latestList).data, favoritesList: (await favoritesList).data, diff --git a/examples/magento-graphcms/pages/modal/[...url].tsx b/examples/magento-graphcms/pages/modal/[...url].tsx index 91a65aa38a5..b8cd9831524 100644 --- a/examples/magento-graphcms/pages/modal/[...url].tsx +++ b/examples/magento-graphcms/pages/modal/[...url].tsx @@ -1,52 +1,38 @@ import { ContentArea, PageContent, pageContent } from '@graphcommerce/content-areas' import { PageOptions } from '@graphcommerce/framer-next-pages' -import { hygraphPageContent, HygraphPagesQuery } from '@graphcommerce/graphcms-ui' import { StoreConfigDocument } from '@graphcommerce/magento-store' -import { - GetStaticProps, - MetaRobots, - LayoutOverlayHeader, - LayoutTitle, - PageMeta, -} from '@graphcommerce/next-ui' -import { Box, Typography } from '@mui/material' +import { GetStaticProps, LayoutOverlayHeader, LayoutTitle, PageMeta } from '@graphcommerce/next-ui' +import { Box } from '@mui/material' import { GetStaticPaths } from 'next' -import { LayoutDocument, LayoutOverlay, LayoutOverlayProps, RowRenderer } from '../../components' +import { + LayoutDocument, + LayoutOverlay, + LayoutOverlayProps, + productListRenderer, +} from '../../components' import { graphqlSsrClient, graphqlSharedClient } from '../../lib/graphql/graphqlSsrClient' -type Props = HygraphPagesQuery & { content: PageContent } +type Props = { content: PageContent } type RouteProps = { url: string[] } type GetPageStaticPaths = GetStaticPaths type GetPageStaticProps = GetStaticProps function ModalPage(props: Props) { - const { content, pages } = props - const page = pages?.[0] - - if (!pages?.[0]) return
- - const metaRobots = page?.metaRobots.toLowerCase().split('_').flat(1) as MetaRobots[] + const { content } = props return ( <> - {page.title} + {content.title} - + - {page.title} - - {page.metaDescription ?? ''} - + {content.title} - + ) } @@ -75,11 +61,10 @@ export const getStaticProps: GetPageStaticProps = async ({ locale, params }) => const staticClient = graphqlSsrClient(locale) const conf = client.query({ query: StoreConfigDocument }) - const page = hygraphPageContent(staticClient, `modal/${urlKey}`) const content = pageContent(staticClient, `modal/${urlKey}`) const layout = staticClient.query({ query: LayoutDocument, fetchPolicy: 'cache-first' }) - if (!(await page).data.pages?.[0]) return { notFound: true } + if ((await content).notFound) return { notFound: true } return { props: { diff --git a/examples/magento-graphcms/pages/newsletter/index.tsx b/examples/magento-graphcms/pages/newsletter/index.tsx index a7b16ae3273..15cce913cd2 100644 --- a/examples/magento-graphcms/pages/newsletter/index.tsx +++ b/examples/magento-graphcms/pages/newsletter/index.tsx @@ -1,6 +1,5 @@ import { ContentArea, PageContent, pageContent } from '@graphcommerce/content-areas' import { PageOptions } from '@graphcommerce/framer-next-pages' -import { hygraphPageContent, HygraphPagesQuery } from '@graphcommerce/graphcms-ui' import { GuestNewsletter } from '@graphcommerce/magento-newsletter' import { StoreConfigDocument } from '@graphcommerce/magento-store' import { PageMeta, GetStaticProps, LayoutOverlayHeader, LayoutTitle } from '@graphcommerce/next-ui' @@ -10,25 +9,20 @@ import { LayoutOverlay, LayoutOverlayProps, LayoutNavigationProps, + productListRenderer, } from '../../components' import { graphqlSsrClient, graphqlSharedClient } from '../../lib/graphql/graphqlSsrClient' -type Props = HygraphPagesQuery & { content: PageContent } +type Props = { content: PageContent } type RouteProps = { url: string[] } type GetPageStaticProps = GetStaticProps function NewsletterSubscribe(props: Props) { - const { content, pages } = props - const page = pages?.[0] - const title = page.title ?? '' + const { content } = props return ( <> - + - {title} + {content.title} - + @@ -73,16 +67,14 @@ export const getStaticProps: GetPageStaticProps = async ({ locale }) => { const client = graphqlSharedClient(locale) const staticClient = graphqlSsrClient(locale) const conf = client.query({ query: StoreConfigDocument }) - const page = hygraphPageContent(staticClient, url) const content = pageContent(staticClient, url) const layout = staticClient.query({ query: LayoutDocument, fetchPolicy: 'cache-first' }) - if (!(await page).data.pages?.[0]) return { notFound: true } + if ((await content).notFound) return { notFound: true } return { props: { content: await content, - ...(await page).data, ...(await layout).data, apolloState: await conf.then(() => client.cache.extract()), }, diff --git a/examples/magento-graphcms/pages/p/[url].tsx b/examples/magento-graphcms/pages/p/[url].tsx index d6fa8b853d4..fef7d7c6326 100644 --- a/examples/magento-graphcms/pages/p/[url].tsx +++ b/examples/magento-graphcms/pages/p/[url].tsx @@ -6,7 +6,6 @@ import { pageContent, } from '@graphcommerce/content-areas' import { PageOptions } from '@graphcommerce/framer-next-pages' -import { hygraphPageContent, HygraphPagesQuery } from '@graphcommerce/graphcms-ui' import { mergeDeep } from '@graphcommerce/graphql' import { AddProductsToCartButton, @@ -56,8 +55,7 @@ import { UspsDocument, UspsQuery } from '../../components/Usps/Usps.gql' import { ProductPage2Document, ProductPage2Query } from '../../graphql/ProductPage2.gql' import { graphqlSharedClient, graphqlSsrClient } from '../../lib/graphql/graphqlSsrClient' -type Props = HygraphPagesQuery & - UspsQuery & +type Props = UspsQuery & ProductPage2Query & Pick & { content: PageContent @@ -98,7 +96,7 @@ function ProductPage(props: Props) { - + - + - + - {/* {pages?.[0] && ( - ( ), }} - /> - )} */} + /> */} } @@ -241,7 +239,6 @@ export const getStaticProps: GetPageStaticProps = async ({ params, locale }) => (pp) => pp.data.products?.items?.find((p) => p?.url_key === urlKey), ) - const pages = hygraphPageContent(staticClient, 'product/global', product, true) const content = pageContent(staticClient, 'product/global', product, true) if (!(await product)) return redirectOrNotFound(staticClient, conf, params, locale) @@ -257,7 +254,6 @@ export const getStaticProps: GetPageStaticProps = async ({ params, locale }) => content: await content, ...defaultConfigurableOptionsSelection(urlKey, client, (await productPage).data), ...(await layout).data, - ...(await pages).data, ...(await usps).data, apolloState: await conf.then(() => client.cache.extract()), up, diff --git a/examples/magento-graphcms/pages/service/[[...url]].tsx b/examples/magento-graphcms/pages/service/[[...url]].tsx index edd390d9d63..0e85bbf1fbe 100644 --- a/examples/magento-graphcms/pages/service/[[...url]].tsx +++ b/examples/magento-graphcms/pages/service/[[...url]].tsx @@ -1,10 +1,6 @@ import { ContentArea, PageContent, pageContent } from '@graphcommerce/content-areas' import { PageOptions } from '@graphcommerce/framer-next-pages' -import { - PagesStaticPathsDocument, - hygraphPageContent, - HygraphPagesQuery, -} from '@graphcommerce/graphcms-ui' +import { PagesStaticPathsDocument } from '@graphcommerce/graphcms-ui' import { StoreConfigDocument } from '@graphcommerce/magento-store' import { PageMeta, GetStaticProps, LayoutOverlayHeader, LayoutTitle } from '@graphcommerce/next-ui' import { i18n } from '@lingui/core' @@ -15,36 +11,32 @@ import { LayoutOverlay, LayoutOverlayProps, LayoutNavigationProps, + productListRenderer, } from '../../components' import { graphqlSsrClient, graphqlSharedClient } from '../../lib/graphql/graphqlSsrClient' -type Props = HygraphPagesQuery & { content: PageContent } +type Props = { content: PageContent } type RouteProps = { url: string[] } type GetPageStaticPaths = GetStaticPaths type GetPageStaticProps = GetStaticProps function ServicePage(props: Props) { const { content, pages } = props - const title = pages?.[0].title ?? '' return ( <> - + - {title} + {content.title} - {title} + {content.title} - + ) } @@ -83,11 +75,10 @@ export const getStaticProps: GetPageStaticProps = async ({ locale, params }) => const client = graphqlSharedClient(locale) const staticClient = graphqlSsrClient(locale) const conf = client.query({ query: StoreConfigDocument }) - const page = hygraphPageContent(staticClient, url) const content = pageContent(staticClient, url) const layout = staticClient.query({ query: LayoutDocument, fetchPolicy: 'cache-first' }) - if (!(await page).data.pages?.[0]) return { notFound: true } + if ((await content).notFound) return { notFound: true } const isRoot = url === 'service' diff --git a/packages/content-areas/index.ts b/packages/content-areas/index.ts index 10061e87466..5aaef4e9a00 100644 --- a/packages/content-areas/index.ts +++ b/packages/content-areas/index.ts @@ -1,3 +1,4 @@ export * from './components' export * from './server/pageContent' export * from './types' +export * from './server/resolveMetadata' diff --git a/packages/content-areas/server/resolveMetadata.ts b/packages/content-areas/server/resolveMetadata.ts new file mode 100644 index 00000000000..4ca6161cd43 --- /dev/null +++ b/packages/content-areas/server/resolveMetadata.ts @@ -0,0 +1,164 @@ +/* eslint-disable guard-for-in */ +/* eslint-disable no-restricted-syntax */ +import { + createDefaultMetadata, + createDefaultViewport, +} from 'next/dist/lib/metadata/default-metadata' +import { resolveAsArrayOrUndefined } from 'next/dist/lib/metadata/generate/utils' +import { + resolveAlternates, + resolveAppleWebApp, + resolveAppLinks, + resolveRobots, + resolveVerification, + resolveItunes, +} from 'next/dist/lib/metadata/resolvers/resolve-basics' +import { resolveIcons } from 'next/dist/lib/metadata/resolvers/resolve-icons' +import { + resolveOpenGraph, + resolveTwitter, +} from 'next/dist/lib/metadata/resolvers/resolve-opengraph' +import { resolveTitle } from 'next/dist/lib/metadata/resolvers/resolve-title' +import type { + Metadata, + ResolvedMetadata, + ResolvedViewport, + ResolvingMetadata, + ResolvingViewport, + Viewport, +} from 'next/dist/lib/metadata/types/metadata-interface' +import type { AbsoluteTemplateString } from 'next/dist/lib/metadata/types/metadata-types' +import type { MetadataContext } from 'next/dist/lib/metadata/types/resolvers' + +type MetadataResolver = (parent: ResolvingMetadata) => Metadata | Promise +type ViewportResolver = (parent: ResolvingViewport) => Viewport | Promise + +export type MetadataItems = [ + Metadata | MetadataResolver | null, + Viewport | ViewportResolver | null, +][] + +type TitleTemplates = { + title: string | null + twitter: string | null + openGraph: string | null +} + +export type BuildState = { + warnings: Set +} + +type ReducedMetadata = Omit< + Metadata, + | 'viewport' + | 'themeColor' + | 'colorScheme' + | 'apple-touch-fullscreen' + | 'apple-touch-icon-precomposed' +> + +// Merge the source metadata into the resolved target metadata. +export function resolveMetadata( + source: ReducedMetadata | null, + { + titleTemplates, + metadataContext, + }: { + titleTemplates: TitleTemplates + metadataContext: MetadataContext + } = { + metadataContext: { pathname: '/' }, + titleTemplates: { openGraph: null, title: null, twitter: null }, + }, +): ResolvedMetadata { + const target: ResolvedMetadata = createDefaultMetadata() + // If there's override metadata, prefer it otherwise fallback to the default metadata. + const metadataBase = + typeof source?.metadataBase !== 'undefined' ? source.metadataBase : target.metadataBase + for (const key_ in source) { + const key = key_ as keyof ReducedMetadata + + switch (key) { + case 'title': { + target.title = resolveTitle(source.title, titleTemplates.title) + break + } + case 'alternates': { + target.alternates = resolveAlternates(source.alternates, metadataBase, metadataContext) + break + } + case 'openGraph': { + target.openGraph = resolveOpenGraph( + source.openGraph, + metadataBase, + metadataContext, + titleTemplates.openGraph, + ) + break + } + case 'twitter': { + target.twitter = resolveTwitter(source.twitter, metadataBase, titleTemplates.twitter) + break + } + case 'verification': + target.verification = resolveVerification(source.verification) + break + + case 'icons': { + target.icons = resolveIcons(source.icons) + break + } + case 'appleWebApp': + target.appleWebApp = resolveAppleWebApp(source.appleWebApp) + break + case 'appLinks': + target.appLinks = resolveAppLinks(source.appLinks) + break + case 'robots': { + target.robots = resolveRobots(source.robots) + break + } + case 'archives': + case 'assets': + case 'bookmarks': + case 'keywords': { + target[key] = resolveAsArrayOrUndefined(source[key]) + break + } + case 'authors': { + target[key] = resolveAsArrayOrUndefined(source.authors) + break + } + case 'itunes': { + target[key] = resolveItunes(source.itunes, metadataBase, metadataContext) + break + } + // directly assign fields that fallback to null + case 'applicationName': + case 'description': + case 'generator': + case 'creator': + case 'publisher': + case 'category': + case 'classification': + case 'referrer': + case 'formatDetection': + case 'manifest': + // @ts-expect-error TODO: support inferring + target[key] = source[key] || null + break + case 'other': + target.other = { ...target.other, ...source.other } + break + case 'metadataBase': + target.metadataBase = metadataBase + break + + default: { + break + } + } + } + + return target +} diff --git a/packages/content-areas/types.ts b/packages/content-areas/types.ts index 2d0e9bbbbdf..c53792a867e 100644 --- a/packages/content-areas/types.ts +++ b/packages/content-areas/types.ts @@ -1 +1,8 @@ -export interface PageContent {} +import { ResolvedMetadata } from 'next' + +export interface PageContent { + notFound?: boolean + title?: string + + metadata: ResolvedMetadata +} diff --git a/packages/hygraph-ui/components/RowProduct/variant/Backstory.tsx b/packages/hygraph-ui/components/RowProduct/variant/Backstory.tsx index 78c2050c63b..9ec1493f2d1 100644 --- a/packages/hygraph-ui/components/RowProduct/variant/Backstory.tsx +++ b/packages/hygraph-ui/components/RowProduct/variant/Backstory.tsx @@ -1,9 +1,9 @@ import { AddProductsToCartForm, ProductListItemsFragment } from '@graphcommerce/magento-product' import { ParagraphWithSidebarSlide, RenderType } from '@graphcommerce/next-ui' import { useTheme } from '@mui/material' -import { productListRenderer } from '../../../../../examples/magento-graphcms/components/ProductListItems' -import { RowProductFragment } from '../RowProduct.gql' import { Asset } from '../../Asset/Asset' +import { RowProductFragment } from '../RowProduct.gql' +import { RichText } from '../../RichText' type BackstoryProps = RowProductFragment & ProductListItemsFragment diff --git a/packages/hygraph-ui/components/RowProduct/variant/Related.tsx b/packages/hygraph-ui/components/RowProduct/variant/Related.tsx index af2fef1ed6a..1e4659f5404 100644 --- a/packages/hygraph-ui/components/RowProduct/variant/Related.tsx +++ b/packages/hygraph-ui/components/RowProduct/variant/Related.tsx @@ -6,7 +6,6 @@ import { SidebarSliderProps, } from '@graphcommerce/next-ui' import { Typography } from '@mui/material' -import { productListRenderer } from '../../../../../examples/magento-graphcms/components/ProductListItems/productListRenderer' import { RowProductFragment } from '../RowProduct.gql' type RelatedProps = RowProductFragment & RelatedProductsFragment & Pick diff --git a/packages/hygraph-ui/components/RowProduct/variant/Swipeable.tsx b/packages/hygraph-ui/components/RowProduct/variant/Swipeable.tsx index ab8a0ad68df..c0a8f9ba287 100644 --- a/packages/hygraph-ui/components/RowProduct/variant/Swipeable.tsx +++ b/packages/hygraph-ui/components/RowProduct/variant/Swipeable.tsx @@ -6,7 +6,6 @@ import { SidebarSliderProps, } from '@graphcommerce/next-ui' import { Typography } from '@mui/material' -import { productListRenderer } from '../../../../../examples/magento-graphcms/components/ProductListItems/productListRenderer' import { RowProductFragment } from '../RowProduct.gql' type SwipeableProps = RowProductFragment & ProductListItemsFragment & Pick diff --git a/packages/hygraph-ui/components/RowProduct/variant/Upsells.tsx b/packages/hygraph-ui/components/RowProduct/variant/Upsells.tsx index 859e6eae6e6..b006222d850 100644 --- a/packages/hygraph-ui/components/RowProduct/variant/Upsells.tsx +++ b/packages/hygraph-ui/components/RowProduct/variant/Upsells.tsx @@ -6,7 +6,6 @@ import { SidebarSliderProps, } from '@graphcommerce/next-ui' import { Typography } from '@mui/material' -import { productListRenderer } from '../../../../../examples/magento-graphcms/components/ProductListItems/productListRenderer' import { RowProductFragment } from '../RowProduct.gql' type UpsellsProps = RowProductFragment & UpsellProductsFragment & Pick diff --git a/packages/hygraph-ui/plugins/hygraphPageContentPlugin.ts b/packages/hygraph-ui/plugins/hygraphPageContentPlugin.ts index b89e7a336d0..43452d12480 100644 --- a/packages/hygraph-ui/plugins/hygraphPageContentPlugin.ts +++ b/packages/hygraph-ui/plugins/hygraphPageContentPlugin.ts @@ -1,4 +1,4 @@ -import type { pageContent } from '@graphcommerce/content-areas' +import { resolveMetadata, type pageContent } from '@graphcommerce/content-areas' import type { MethodPlugin } from '@graphcommerce/next-config' import { hygraphPageContent } from '..' @@ -17,8 +17,23 @@ const hygraphPageContentPlugin: MethodPlugin = async ( hygraphPageContent(client, url, additionalProperties, cached), ]) + const page = content.data.pages?.[0] + + if (!page) return { ...prevResults, notFound: true } + return { ...prevResults, + metadata: resolveMetadata({ + metadataBase: new URL(import.meta.graphCommerce.canonicalBaseUrl), + title: page.title, + description: page.metaDescription, + robots: page.metaRobots + ? { + index: !page.metaRobots.includes('noindex'), + follow: !page.metaRobots.includes('nofollow'), + } + : { index: true, follow: true }, + }), hygraphPage: content.data.pages?.[0], } } diff --git a/packages/next-ui/PageMeta/PageMeta.tsx b/packages/next-ui/PageMeta/PageMeta.tsx index 075e3f93873..d51b7d22516 100644 --- a/packages/next-ui/PageMeta/PageMeta.tsx +++ b/packages/next-ui/PageMeta/PageMeta.tsx @@ -8,6 +8,7 @@ import Head from 'next/head' import { useRouter } from 'next/router' import type {} from '@graphcommerce/next-config' import { storefrontConfig } from '../hooks' +import { PageMetaNew, PageMetaPropsNew } from './PageMetaNew' // https://developers.google.com/search/docs/advanced/robots/robots_meta_tag#directives export type MetaRobots = @@ -25,7 +26,7 @@ type MetaRobotsAll = ['all' | 'none'] type Canonical = `http://${string}` | `https://${string}` | `/${string}` | string -export type PageMetaProps = { +type PageMetaPropsOld = { title: string canonical?: Canonical metaDescription?: string @@ -36,6 +37,12 @@ export type PageMetaProps = { ogType?: string | null } +export function isPageMetaPropsNew(props: PageMetaProps): props is PageMetaPropsNew { + return 'metadata' in props +} + +export type PageMetaProps = PageMetaPropsNew | PageMetaPropsOld + type PartialNextRouter = Pick< NextRouter, 'pathname' | 'locale' | 'locales' | 'isLocaleDomain' | 'domainLocales' | 'defaultLocale' @@ -91,7 +98,7 @@ export function useCanonical(incoming?: Canonical) { return canonicalize(router, incoming) } -export function PageMeta(props: PageMetaProps) { +export function PageMetaOld(props: PageMetaPropsOld) { const { active } = usePageContext() const { children, @@ -109,7 +116,7 @@ export function PageMeta(props: PageMetaProps) { if (!active) return null return ( - {title.trim()} + {title} {metaDescription && ( <> @@ -129,3 +136,7 @@ export function PageMeta(props: PageMetaProps) { ) } + +export function PageMeta(props: PageMetaProps) { + return isPageMetaPropsNew(props) ? : +} diff --git a/packages/next-ui/PageMeta/PageMetaNew.tsx b/packages/next-ui/PageMeta/PageMetaNew.tsx new file mode 100644 index 00000000000..556018d2218 --- /dev/null +++ b/packages/next-ui/PageMeta/PageMetaNew.tsx @@ -0,0 +1,55 @@ +import { ResolvedMetadata } from 'next' +import { + createDefaultMetadata, + createDefaultViewport, +} from 'next/dist/lib/metadata/default-metadata' +import { AlternatesMetadata } from 'next/dist/lib/metadata/generate/alternate' +import { + ViewportMeta, + AppleWebAppMeta, + BasicMeta, + FormatDetectionMeta, + ItunesMeta, + VerificationMeta, +} from 'next/dist/lib/metadata/generate/basic' +import { IconsMetadata } from 'next/dist/lib/metadata/generate/icons' +import { MetaFilter } from 'next/dist/lib/metadata/generate/meta' +import { + AppLinksMeta, + OpenGraphMetadata, + TwitterMetadata, +} from 'next/dist/lib/metadata/generate/opengraph' +import Head from 'next/head' +import React from 'react' + +export type PageMetaPropsNew = { + metadata: ResolvedMetadata + children?: React.ReactNode +} + +export function PageMetaNew(props: PageMetaPropsNew) { + const { metadata, children } = props + + const elements = MetaFilter([ + BasicMeta({ metadata }), + AlternatesMetadata({ alternates: metadata.alternates }), + ItunesMeta({ itunes: metadata.itunes }), + FormatDetectionMeta({ formatDetection: metadata.formatDetection }), + VerificationMeta({ verification: metadata.verification }), + AppleWebAppMeta({ appleWebApp: metadata.appleWebApp }), + OpenGraphMetadata({ openGraph: metadata.openGraph }), + TwitterMetadata({ twitter: metadata.twitter }), + AppLinksMeta({ appLinks: metadata.appLinks }), + IconsMetadata({ icons: metadata.icons }), + ]) + + return ( + + {elements.map((el, idx) => ( + // eslint-disable-next-line react/no-array-index-key + {el} + ))} + {children} + + ) +} From 326df0df10102b43b707169988a0349404f5480b Mon Sep 17 00:00:00 2001 From: Paul Hachmang Date: Mon, 8 Jan 2024 16:45:37 +0100 Subject: [PATCH 03/33] Added superjson for now --- examples/magento-graphcms/next.config.js | 4 +- examples/magento-graphcms/package.json | 2 + packages/content-areas/package.json | 2 +- packages/content-areas/server/jsonifyMeta.ts | 57 +++++++++++++++++++ .../content-areas/server/resolveMetadata.ts | 19 +------ packages/content-areas/types.ts | 23 +++++++- yarn.lock | 43 +++++++++++++- 7 files changed, 126 insertions(+), 24 deletions(-) create mode 100644 packages/content-areas/server/jsonifyMeta.ts diff --git a/examples/magento-graphcms/next.config.js b/examples/magento-graphcms/next.config.js index cb88b682934..5e8be76914c 100644 --- a/examples/magento-graphcms/next.config.js +++ b/examples/magento-graphcms/next.config.js @@ -22,6 +22,7 @@ const nextConfig = { }, experimental: { scrollRestoration: true, + swcPlugins: [['next-superjson-plugin', { excluded: [] }]], }, optimizeFonts: false, images: { @@ -30,9 +31,6 @@ const nextConfig = { eslint: { ignoreDuringBuilds: true, }, - experimental: { - scrollRestoration: true, - }, } module.exports = withGraphCommerce(withPWA(nextConfig), __dirname) diff --git a/examples/magento-graphcms/package.json b/examples/magento-graphcms/package.json index de65a34755e..b721ebcea91 100644 --- a/examples/magento-graphcms/package.json +++ b/examples/magento-graphcms/package.json @@ -83,11 +83,13 @@ "graphql": "^16.8.1", "next": "14.0.4", "next-sitemap": "4.2.3", + "next-superjson-plugin": "^0.5.10", "patch-package": "8.0.0", "react": "^18.2.0", "react-dom": "^18.2.0", "react-hook-form": "^7.49.0", "sharp": "0.33.0", + "superjson": "^1", "webpack": "5.89.0" }, "devDependencies": { diff --git a/packages/content-areas/package.json b/packages/content-areas/package.json index 2ae7b73fc74..573d40d3481 100644 --- a/packages/content-areas/package.json +++ b/packages/content-areas/package.json @@ -12,9 +12,9 @@ } }, "peerDependencies": { - "@graphcommerce/magento-product": "^8.0.0-canary.74", "@graphcommerce/eslint-config-pwa": "^8.0.0-canary.74", "@graphcommerce/graphql": "^8.0.0-canary.74", + "@graphcommerce/magento-product": "^8.0.0-canary.74", "@graphcommerce/next-ui": "^8.0.0-canary.74", "@graphcommerce/prettier-config-pwa": "^8.0.0-canary.74", "@graphcommerce/react-hook-form": "^8.0.0-canary.74", diff --git a/packages/content-areas/server/jsonifyMeta.ts b/packages/content-areas/server/jsonifyMeta.ts new file mode 100644 index 00000000000..09f2650e8de --- /dev/null +++ b/packages/content-areas/server/jsonifyMeta.ts @@ -0,0 +1,57 @@ +import { ResolvedMetadata } from 'next' +import { AlternateLinkDescriptor } from 'next/dist/lib/metadata/types/alternative-urls-types' +import type { Jsonify } from 'type-fest' + +function alternateLinkDescriptorToJSON( + link: AlternateLinkDescriptor | null | undefined, +): Jsonify | null { + if (!link) return null + return { + ...link, + url: link.url.toString(), + } +} + +export function resolvedMetadataToJSON(metadata: ResolvedMetadata): Jsonify { + return { + ...metadata, + metadataBase: metadata.metadataBase?.toString() ?? null, + authors: + metadata.authors?.map((author) => ({ + ...author, + url: author.url?.toString(), + })) ?? null, + alternates: { + ...metadata.alternates, + canonical: alternateLinkDescriptorToJSON(metadata.alternates?.canonical), + languages: Object.fromEntries( + Object.entries(metadata.alternates?.languages ?? {}).map(([key, val]) => [ + key, + val?.map(alternateLinkDescriptorToJSON), + ]), + ) as Jsonify['languages']>, + + media: Object.fromEntries( + Object.entries(metadata.alternates?.media ?? {}).map(([key, val]) => [ + key, + val?.map(alternateLinkDescriptorToJSON), + ]), + ) as Jsonify['media']>, + + types: Object.fromEntries( + Object.entries(metadata.alternates?.types ?? {}).map(([key, val]) => [ + key, + val?.map(alternateLinkDescriptorToJSON), + ]), + ) as Jsonify['types']>, + }, + + icons: { + ...metadata.icons, + apple: (metadata.icons?.apple ?? [])?.map((icon) => ({ + ...icon, + url: icon.url?.toString(), + })), + }, + } +} diff --git a/packages/content-areas/server/resolveMetadata.ts b/packages/content-areas/server/resolveMetadata.ts index 4ca6161cd43..c1d08739f15 100644 --- a/packages/content-areas/server/resolveMetadata.ts +++ b/packages/content-areas/server/resolveMetadata.ts @@ -1,9 +1,6 @@ /* eslint-disable guard-for-in */ /* eslint-disable no-restricted-syntax */ -import { - createDefaultMetadata, - createDefaultViewport, -} from 'next/dist/lib/metadata/default-metadata' +import { createDefaultMetadata } from 'next/dist/lib/metadata/default-metadata' import { resolveAsArrayOrUndefined } from 'next/dist/lib/metadata/generate/utils' import { resolveAlternates, @@ -22,13 +19,12 @@ import { resolveTitle } from 'next/dist/lib/metadata/resolvers/resolve-title' import type { Metadata, ResolvedMetadata, - ResolvedViewport, ResolvingMetadata, ResolvingViewport, Viewport, } from 'next/dist/lib/metadata/types/metadata-interface' -import type { AbsoluteTemplateString } from 'next/dist/lib/metadata/types/metadata-types' import type { MetadataContext } from 'next/dist/lib/metadata/types/resolvers' +import { ReducedMetadata, ReducedResolvedMetadata } from '../types' type MetadataResolver = (parent: ResolvingMetadata) => Metadata | Promise type ViewportResolver = (parent: ResolvingViewport) => Viewport | Promise @@ -48,15 +44,6 @@ export type BuildState = { warnings: Set } -type ReducedMetadata = Omit< - Metadata, - | 'viewport' - | 'themeColor' - | 'colorScheme' - | 'apple-touch-fullscreen' - | 'apple-touch-icon-precomposed' -> - // Merge the source metadata into the resolved target metadata. export function resolveMetadata( source: ReducedMetadata | null, @@ -70,7 +57,7 @@ export function resolveMetadata( metadataContext: { pathname: '/' }, titleTemplates: { openGraph: null, title: null, twitter: null }, }, -): ResolvedMetadata { +): ReducedResolvedMetadata { const target: ResolvedMetadata = createDefaultMetadata() // If there's override metadata, prefer it otherwise fallback to the default metadata. const metadataBase = diff --git a/packages/content-areas/types.ts b/packages/content-areas/types.ts index c53792a867e..929d8950625 100644 --- a/packages/content-areas/types.ts +++ b/packages/content-areas/types.ts @@ -1,8 +1,25 @@ -import { ResolvedMetadata } from 'next' +import { Metadata, ResolvedMetadata } from 'next' + +export type ReducedMetadata = Omit< + Metadata, + | 'viewport' + | 'themeColor' + | 'colorScheme' + | 'apple-touch-fullscreen' + | 'apple-touch-icon-precomposed' +> + +export type ReducedResolvedMetadata = Omit< + ResolvedMetadata, + | 'viewport' + | 'themeColor' + | 'colorScheme' + | 'apple-touch-fullscreen' + | 'apple-touch-icon-precomposed' +> export interface PageContent { notFound?: boolean title?: string - - metadata: ResolvedMetadata + metadata: ReducedResolvedMetadata } diff --git a/yarn.lock b/yarn.lock index d4ac5a46cfe..ddd031333c6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2668,12 +2668,13 @@ __metadata: languageName: unknown linkType: soft -"@graphcommerce/content-areas@workspace:packages/content-areas": +"@graphcommerce/content-areas@npm:8.0.0-canary.74, @graphcommerce/content-areas@workspace:packages/content-areas": version: 0.0.0-use.local resolution: "@graphcommerce/content-areas@workspace:packages/content-areas" peerDependencies: "@graphcommerce/eslint-config-pwa": ^8.0.0-canary.74 "@graphcommerce/graphql": ^8.0.0-canary.74 + "@graphcommerce/magento-product": ^8.0.0-canary.74 "@graphcommerce/next-ui": ^8.0.0-canary.74 "@graphcommerce/prettier-config-pwa": ^8.0.0-canary.74 "@graphcommerce/react-hook-form": ^8.0.0-canary.74 @@ -3643,6 +3644,7 @@ __metadata: "@apollo/client": "npm:~3.8.8" "@ducanh2912/next-pwa": "npm:9.7.2" "@graphcommerce/cli": "npm:8.0.0-canary.74" + "@graphcommerce/content-areas": "npm:8.0.0-canary.74" "@graphcommerce/demo-magento-graphcommerce": "npm:8.0.0-canary.74" "@graphcommerce/ecommerce-ui": "npm:8.0.0-canary.74" "@graphcommerce/eslint-config-pwa": "npm:8.0.0-canary.74" @@ -3714,12 +3716,14 @@ __metadata: graphql: "npm:^16.8.1" next: "npm:14.0.4" next-sitemap: "npm:4.2.3" + next-superjson-plugin: "npm:^0.5.10" patch-package: "npm:8.0.0" prettier: "npm:3.1.1" react: "npm:^18.2.0" react-dom: "npm:^18.2.0" react-hook-form: "npm:^7.49.0" sharp: "npm:0.33.0" + superjson: "npm:^1" type-fest: "npm:^4.8.3" typescript: "npm:5.3.3" webpack: "npm:5.89.0" @@ -9642,6 +9646,15 @@ __metadata: languageName: node linkType: hard +"copy-anything@npm:^3.0.2": + version: 3.0.5 + resolution: "copy-anything@npm:3.0.5" + dependencies: + is-what: "npm:^4.1.8" + checksum: 01eadd500c7e1db71d32d95a3bfaaedcb839ef891c741f6305ab0461398056133de08f2d1bf4c392b364e7bdb7ce498513896e137a7a183ac2516b065c28a4fe + languageName: node + linkType: hard + "core-js-compat@npm:^3.31.0, core-js-compat@npm:^3.33.1": version: 3.35.0 resolution: "core-js-compat@npm:3.35.0" @@ -12875,6 +12888,13 @@ __metadata: languageName: node linkType: hard +"is-what@npm:^4.1.8": + version: 4.1.16 + resolution: "is-what@npm:4.1.16" + checksum: 611f1947776826dcf85b57cfb7bd3b3ea6f4b94a9c2f551d4a53f653cf0cb9d1e6518846648256d46ee6c91d114b6d09d2ac8a07306f7430c5900f87466aae5b + languageName: node + linkType: hard + "is-windows@npm:^1.0.0, is-windows@npm:^1.0.1": version: 1.0.2 resolution: "is-windows@npm:1.0.2" @@ -14909,6 +14929,18 @@ __metadata: languageName: node linkType: hard +"next-superjson-plugin@npm:^0.5.10": + version: 0.5.10 + resolution: "next-superjson-plugin@npm:0.5.10" + dependencies: + hoist-non-react-statics: "npm:^3.3.2" + peerDependencies: + next: ^13.0 || ^14.0 + superjson: ^1 + checksum: 3a7528389fc0b5317f0151d815b51c870524407c80ec13e8d877ae400822e47e029d243edfc9151084fc98950d55c2139255346f126999fdcf3163d09d7259be + languageName: node + linkType: hard + "next@npm:14.0.4": version: 14.0.4 resolution: "next@npm:14.0.4" @@ -17523,6 +17555,15 @@ __metadata: languageName: node linkType: hard +"superjson@npm:^1": + version: 1.13.3 + resolution: "superjson@npm:1.13.3" + dependencies: + copy-anything: "npm:^3.0.2" + checksum: 389a0a0c86884dd0558361af5d6d7f37102b71dda9595a665fe8b39d1ba0e57c859e39a9bd79b6f1fde6f4dcceac49a1c205f248d292744b2a340ee52846efdb + languageName: node + linkType: hard + "supports-color@npm:^5.3.0": version: 5.5.0 resolution: "supports-color@npm:5.5.0" From 75fc6cf648294b48b59da748f78dabcb82e8bb47 Mon Sep 17 00:00:00 2001 From: Paul Hachmang Date: Tue, 9 Jan 2024 10:40:02 +0100 Subject: [PATCH 04/33] CategoryMeta fix --- examples/magento-graphcms/pages/[...url].tsx | 6 +- packages/content-areas/types.ts | 2 +- .../components/CategoryMeta/CategoryMeta.tsx | 84 +++++++++++-------- packages/next-ui/PageMeta/PageMetaNew.tsx | 18 ++-- 4 files changed, 64 insertions(+), 46 deletions(-) diff --git a/examples/magento-graphcms/pages/[...url].tsx b/examples/magento-graphcms/pages/[...url].tsx index fa1311905f5..2329331c1f0 100644 --- a/examples/magento-graphcms/pages/[...url].tsx +++ b/examples/magento-graphcms/pages/[...url].tsx @@ -63,7 +63,7 @@ function CategoryPage(props: CategoryProps) { return ( <> - + @@ -84,7 +84,7 @@ function CategoryPage(props: CategoryProps) { !isCategory || (!category?.description && category?.children?.length === 0) } > - {category?.name ?? page.title} + {category?.name ?? content.title} )} @@ -192,7 +192,7 @@ export const getStaticProps: GetPageStaticProps = async ({ params, locale }) => }) : undefined - const hasPage = filteredCategoryUid ? false : (await pages).data.pages.length > 0 + const hasPage = filteredCategoryUid ? false : (await content).notFound !== false if (!hasCategory && !hasPage) return redirectOrNotFound(staticClient, conf, params, locale) if ((await products)?.errors) return { notFound: true } diff --git a/packages/content-areas/types.ts b/packages/content-areas/types.ts index 929d8950625..225796d1aa9 100644 --- a/packages/content-areas/types.ts +++ b/packages/content-areas/types.ts @@ -21,5 +21,5 @@ export type ReducedResolvedMetadata = Omit< export interface PageContent { notFound?: boolean title?: string - metadata: ReducedResolvedMetadata + metadata: ResolvedMetadata | null } diff --git a/packages/magento-category/components/CategoryMeta/CategoryMeta.tsx b/packages/magento-category/components/CategoryMeta/CategoryMeta.tsx index cf8567e70b7..10561b850d1 100644 --- a/packages/magento-category/components/CategoryMeta/CategoryMeta.tsx +++ b/packages/magento-category/components/CategoryMeta/CategoryMeta.tsx @@ -1,36 +1,29 @@ import { ProductListParams } from '@graphcommerce/magento-product' -import { PageMeta } from '@graphcommerce/magento-store' -import { PageMetaProps } from '@graphcommerce/next-ui' +import { PageMetaNew, PageMetaPropsNew } from '@graphcommerce/next-ui/PageMeta/PageMetaNew' import { i18n } from '@lingui/core' import { CategoryMetaFragment } from './CategoryMeta.gql' -export type CategoryMetaProps = CategoryMetaFragment & - Omit & { - params?: ProductListParams - title?: string | null - metaDescription?: string | null - } +export type CategoryMetaProps = PageMetaPropsNew & { + category?: CategoryMetaFragment | null + params?: ProductListParams +} export function CategoryMeta(props: CategoryMetaProps) { - const { meta_title, meta_description, name, params, image, ogImageUseFallback } = props - let { title, metaDescription, metaRobots, canonical, ogImage } = props - if (!title) title = '' - if (!metaDescription) metaDescription = '' + const { params, metadata, category } = props + + let title = metadata?.title?.absolute ?? '' + if (!title && category?.meta_title) title = category?.meta_title + if (!title && category?.name) title = category?.name - if (!title && meta_title) title = meta_title - if (!title && name) title = name - if (!ogImage && image) ogImage = image - if (!metaDescription && meta_description) metaDescription = meta_description + let metaDescription = metadata?.description ?? '' + if (!metaDescription && category?.meta_description) metaDescription = category.meta_description - if (params?.url && !canonical) canonical = `/${params.url}` + let canonical = metadata?.alternates?.canonical?.url ?? null + if (!canonical) canonical = `/${params?.url}` const anyFilterActive = Object.keys(params?.filters ?? {}).filter((k) => k !== 'category_uid').length > 0 - const sortActive = params?.sort && Object.keys(params?.sort).length !== 0 - const limitAcitve = !!params?.pageSize - const noIndex = anyFilterActive || sortActive || limitAcitve - const currentPage = params?.currentPage ?? 1 const isPaginated = currentPage > 1 && !anyFilterActive @@ -39,22 +32,43 @@ export function CategoryMeta(props: CategoryMetaProps) { ? i18n._(/* i18n */ '{title} - Page {currentPage}', { title, currentPage }) : title - const metaDescriptionTrans = - metaDescription && isPaginated - ? i18n._(/* i18n */ '{metaDescription} - Page {currentPage}', { - metaDescription, - currentPage, - }) - : metaDescription + const sortActive = params?.sort && Object.keys(params?.sort).length !== 0 + const limitAcitve = !!params?.pageSize + const noIndex = anyFilterActive || sortActive || limitAcitve return ( - ) } diff --git a/packages/next-ui/PageMeta/PageMetaNew.tsx b/packages/next-ui/PageMeta/PageMetaNew.tsx index 556018d2218..aa3b0dd0f0d 100644 --- a/packages/next-ui/PageMeta/PageMetaNew.tsx +++ b/packages/next-ui/PageMeta/PageMetaNew.tsx @@ -1,11 +1,7 @@ import { ResolvedMetadata } from 'next' -import { - createDefaultMetadata, - createDefaultViewport, -} from 'next/dist/lib/metadata/default-metadata' +import { createDefaultMetadata } from 'next/dist/lib/metadata/default-metadata' import { AlternatesMetadata } from 'next/dist/lib/metadata/generate/alternate' import { - ViewportMeta, AppleWebAppMeta, BasicMeta, FormatDetectionMeta, @@ -23,12 +19,20 @@ import Head from 'next/head' import React from 'react' export type PageMetaPropsNew = { - metadata: ResolvedMetadata + metadata?: Partial | null children?: React.ReactNode } export function PageMetaNew(props: PageMetaPropsNew) { - const { metadata, children } = props + const { metadata: metaIncoming, children } = props + + if (!metaIncoming) return null + + const metadata: ResolvedMetadata = { + ...createDefaultMetadata(), + ...metaIncoming, + metadataBase: new URL(import.meta.graphCommerce.canonicalBaseUrl), + } const elements = MetaFilter([ BasicMeta({ metadata }), From c5863793475533f843886716c539fcd91aad1d96 Mon Sep 17 00:00:00 2001 From: Paul Hachmang Date: Tue, 9 Jan 2024 11:51:58 +0100 Subject: [PATCH 05/33] Refactor --- .vscode/settings.json | 6 ++- .../components/Blog/BlogAuthor.graphql | 4 -- .../components/Blog/BlogAuthor.tsx | 10 ----- .../components/Blog/BlogHeader.tsx | 11 ----- .../components/Blog/BlogItem.graphql | 8 ---- .../components/Blog/BlogItem.tsx | 38 ---------------- .../components/Blog/BlogList.graphql | 14 ------ .../components/Blog/BlogList.tsx | 17 ------- .../components/Blog/BlogListTagged.graphql | 14 ------ .../components/Blog/BlogPaths.graphql | 7 --- .../components/Blog/BlogPostPaths.graphql | 5 --- .../Blog/BlogPostTaggedPaths.graphql | 5 --- .../components/Blog/BlogTags.graphql | 6 --- .../components/Blog/BlogTags.tsx | 16 ------- .../components/Blog/RowBlogContent.graphql | 5 --- .../components/Blog/RowBlogContent.tsx | 15 ------- .../magento-graphcms/components/Blog/index.ts | 12 ----- .../components/Layout/Layout.graphql | 1 - .../ProductListItems/CategoryFilterLayout.tsx | 11 ++++- examples/magento-graphcms/components/index.ts | 3 -- .../graphql/DefaultPage.graphql | 4 -- .../graphql/ProductPage.graphql | 6 --- examples/magento-graphcms/pages/[...url].tsx | 3 -- .../magento-graphcms/pages/blog/[url].tsx | 36 +++++---------- .../pages/blog/page/[page].tsx | 15 ++----- .../pages/blog/tagged/[url].tsx | 8 ---- .../magento-graphcms/pages/modal/[...url].tsx | 1 - examples/magento-graphcms/pages/p/[url].tsx | 4 +- .../pages/service/[[...url]].tsx | 3 +- packages/content-areas/server/pageContent.ts | 4 +- .../hygraph-ui/components/Blog/BlogHeader.tsx | 2 +- .../hygraph-ui/components/Blog/BlogItem.tsx | 2 +- .../components}/FooterQueryFragment.graphql | 0 .../components/RowProduct/variant/Grid.tsx | 16 ++++--- .../hygraph-ui}/components/Usps/Usps.graphql | 0 .../hygraph-ui}/components/Usps/Usps.tsx | 3 +- .../components/Usps/UspsQueryFragment.graphql | 0 packages/hygraph-ui/package.json | 4 ++ .../ProductPageMeta/ProductPageMeta.tsx | 4 +- packages/magento-store/PageMeta.tsx | 44 +++++++++++++------ packages/next-ui/PageMeta/PageMeta.tsx | 2 +- yarn.lock | 4 ++ 42 files changed, 89 insertions(+), 284 deletions(-) delete mode 100644 examples/magento-graphcms/components/Blog/BlogAuthor.graphql delete mode 100644 examples/magento-graphcms/components/Blog/BlogAuthor.tsx delete mode 100644 examples/magento-graphcms/components/Blog/BlogHeader.tsx delete mode 100644 examples/magento-graphcms/components/Blog/BlogItem.graphql delete mode 100644 examples/magento-graphcms/components/Blog/BlogItem.tsx delete mode 100644 examples/magento-graphcms/components/Blog/BlogList.graphql delete mode 100644 examples/magento-graphcms/components/Blog/BlogList.tsx delete mode 100644 examples/magento-graphcms/components/Blog/BlogListTagged.graphql delete mode 100644 examples/magento-graphcms/components/Blog/BlogPaths.graphql delete mode 100644 examples/magento-graphcms/components/Blog/BlogPostPaths.graphql delete mode 100644 examples/magento-graphcms/components/Blog/BlogPostTaggedPaths.graphql delete mode 100644 examples/magento-graphcms/components/Blog/BlogTags.graphql delete mode 100644 examples/magento-graphcms/components/Blog/BlogTags.tsx delete mode 100644 examples/magento-graphcms/components/Blog/RowBlogContent.graphql delete mode 100644 examples/magento-graphcms/components/Blog/RowBlogContent.tsx delete mode 100644 examples/magento-graphcms/components/Blog/index.ts delete mode 100644 examples/magento-graphcms/graphql/DefaultPage.graphql delete mode 100644 examples/magento-graphcms/graphql/ProductPage.graphql rename {examples/magento-graphcms/components/Layout => packages/hygraph-ui/components}/FooterQueryFragment.graphql (100%) rename {examples/magento-graphcms => packages/hygraph-ui}/components/Usps/Usps.graphql (100%) rename {examples/magento-graphcms => packages/hygraph-ui}/components/Usps/Usps.tsx (90%) rename {examples/magento-graphcms => packages/hygraph-ui}/components/Usps/UspsQueryFragment.graphql (100%) diff --git a/.vscode/settings.json b/.vscode/settings.json index c0edc2635c0..7fa3b314715 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -2,10 +2,12 @@ "editor.formatOnSave": true, "editor.tabSize": 2, "editor.defaultFormatter": "esbenp.prettier-vscode", - "editor.codeActionsOnSave": { "source.fixAll.eslint": false }, + "editor.codeActionsOnSave": { + "source.fixAll.eslint": "never" + }, "editor.snippetSuggestions": "none", "emmet.showExpandedAbbreviation": "never", - "editor.wordBasedSuggestions": false, + "editor.wordBasedSuggestions": "off", "javascript.suggest.names": false, "typescript.tsdk": "node_modules/typescript/lib", "search.exclude": { diff --git a/examples/magento-graphcms/components/Blog/BlogAuthor.graphql b/examples/magento-graphcms/components/Blog/BlogAuthor.graphql deleted file mode 100644 index 934c0d505cb..00000000000 --- a/examples/magento-graphcms/components/Blog/BlogAuthor.graphql +++ /dev/null @@ -1,4 +0,0 @@ -fragment BlogAuthor on Page { - date - author -} diff --git a/examples/magento-graphcms/components/Blog/BlogAuthor.tsx b/examples/magento-graphcms/components/Blog/BlogAuthor.tsx deleted file mode 100644 index 5c964c91cc9..00000000000 --- a/examples/magento-graphcms/components/Blog/BlogAuthor.tsx +++ /dev/null @@ -1,10 +0,0 @@ -import { BlogAuthor as NextBlogAuthor } from '@graphcommerce/next-ui' -import { BlogAuthorFragment } from './BlogAuthor.gql' - -type BlogAuthorProps = BlogAuthorFragment - -export function BlogAuthor(props: BlogAuthorProps) { - const { author, date } = props - if (!author) return null - return -} diff --git a/examples/magento-graphcms/components/Blog/BlogHeader.tsx b/examples/magento-graphcms/components/Blog/BlogHeader.tsx deleted file mode 100644 index 68c2b6da2b6..00000000000 --- a/examples/magento-graphcms/components/Blog/BlogHeader.tsx +++ /dev/null @@ -1,11 +0,0 @@ -import { Asset, AssetFragment } from '@graphcommerce/graphcms-ui' -import { BlogHeader as NextBlogHeader } from '@graphcommerce/next-ui' - -export function BlogHeader(props: { asset?: AssetFragment }) { - const { asset } = props - return ( - : null} - /> - ) -} diff --git a/examples/magento-graphcms/components/Blog/BlogItem.graphql b/examples/magento-graphcms/components/Blog/BlogItem.graphql deleted file mode 100644 index ee371f34d1a..00000000000 --- a/examples/magento-graphcms/components/Blog/BlogItem.graphql +++ /dev/null @@ -1,8 +0,0 @@ -fragment BlogItem on Page { - title - url - date - asset { - ...Asset - } -} diff --git a/examples/magento-graphcms/components/Blog/BlogItem.tsx b/examples/magento-graphcms/components/Blog/BlogItem.tsx deleted file mode 100644 index 8629246d7ca..00000000000 --- a/examples/magento-graphcms/components/Blog/BlogItem.tsx +++ /dev/null @@ -1,38 +0,0 @@ -import { Asset } from '@graphcommerce/graphcms-ui' -import { BlogListItem } from '@graphcommerce/next-ui' -import { Trans } from '@lingui/react' -import { Typography, useTheme } from '@mui/material' -import { BlogItemFragment } from './BlogItem.gql' - -type BlogItemProps = BlogItemFragment - -export function BlogItem(props: BlogItemProps) { - const { title, url, asset, date } = props - - const theme = useTheme() - - return ( - - ) : ( - - - - ) - } - title={title ?? ''} - date={date} - url={url} - /> - ) -} diff --git a/examples/magento-graphcms/components/Blog/BlogList.graphql b/examples/magento-graphcms/components/Blog/BlogList.graphql deleted file mode 100644 index c9494ff54b2..00000000000 --- a/examples/magento-graphcms/components/Blog/BlogList.graphql +++ /dev/null @@ -1,14 +0,0 @@ -query BlogList($currentUrl: [String!]!, $first: Int = 4, $skip: Int = 0) { - blogPosts: pages( - where: { - url_not_starts_with: "blog/tagged/" - url_starts_with: "blog/" - url_not_in: $currentUrl - } - orderBy: date_DESC - first: $first - skip: $skip - ) { - ...BlogItem - } -} diff --git a/examples/magento-graphcms/components/Blog/BlogList.tsx b/examples/magento-graphcms/components/Blog/BlogList.tsx deleted file mode 100644 index 63d3775152b..00000000000 --- a/examples/magento-graphcms/components/Blog/BlogList.tsx +++ /dev/null @@ -1,17 +0,0 @@ -import { BlogItemGrid } from '@graphcommerce/next-ui' -import { BlogItem } from './BlogItem' -import { BlogListQuery } from './BlogList.gql' - -type BlogListProps = BlogListQuery - -export function BlogList(props: BlogListProps) { - const { blogPosts } = props - - return ( - - {blogPosts.map((BlogPost) => ( - - ))} - - ) -} diff --git a/examples/magento-graphcms/components/Blog/BlogListTagged.graphql b/examples/magento-graphcms/components/Blog/BlogListTagged.graphql deleted file mode 100644 index f30a359337d..00000000000 --- a/examples/magento-graphcms/components/Blog/BlogListTagged.graphql +++ /dev/null @@ -1,14 +0,0 @@ -query BlogListTagged($currentUrl: [String!]!, $first: Int = 4, $skip: Int = 0, $tagged: String) { - blogPosts: pages( - where: { - url_starts_with: "blog/" - relatedPages_some: { url_contains: $tagged } - url_not_in: $currentUrl - } - orderBy: date_DESC - first: $first - skip: $skip - ) { - ...BlogItem - } -} diff --git a/examples/magento-graphcms/components/Blog/BlogPaths.graphql b/examples/magento-graphcms/components/Blog/BlogPaths.graphql deleted file mode 100644 index 40a772cc68e..00000000000 --- a/examples/magento-graphcms/components/Blog/BlogPaths.graphql +++ /dev/null @@ -1,7 +0,0 @@ -query BlogPaths { - pagesConnection(where: { url_not_starts_with: "blog/tagged/", url_starts_with: "blog/" }) { - aggregate { - count - } - } -} diff --git a/examples/magento-graphcms/components/Blog/BlogPostPaths.graphql b/examples/magento-graphcms/components/Blog/BlogPostPaths.graphql deleted file mode 100644 index 340b06a48d6..00000000000 --- a/examples/magento-graphcms/components/Blog/BlogPostPaths.graphql +++ /dev/null @@ -1,5 +0,0 @@ -query BlogPostPaths { - pages(where: { url_not_starts_with: "blog/tagged/", url_starts_with: "blog/" }) { - url - } -} diff --git a/examples/magento-graphcms/components/Blog/BlogPostTaggedPaths.graphql b/examples/magento-graphcms/components/Blog/BlogPostTaggedPaths.graphql deleted file mode 100644 index 0d8edc4830f..00000000000 --- a/examples/magento-graphcms/components/Blog/BlogPostTaggedPaths.graphql +++ /dev/null @@ -1,5 +0,0 @@ -query BlogPostTaggedPaths { - pages(where: { url_starts_with: "blog/tagged/" }) { - url - } -} diff --git a/examples/magento-graphcms/components/Blog/BlogTags.graphql b/examples/magento-graphcms/components/Blog/BlogTags.graphql deleted file mode 100644 index f44e2e108b4..00000000000 --- a/examples/magento-graphcms/components/Blog/BlogTags.graphql +++ /dev/null @@ -1,6 +0,0 @@ -fragment BlogTags on Page { - relatedPages { - title - url - } -} diff --git a/examples/magento-graphcms/components/Blog/BlogTags.tsx b/examples/magento-graphcms/components/Blog/BlogTags.tsx deleted file mode 100644 index 7628013a88f..00000000000 --- a/examples/magento-graphcms/components/Blog/BlogTags.tsx +++ /dev/null @@ -1,16 +0,0 @@ -import { BlogTag, BlogTags as NextBlogTags } from '@graphcommerce/next-ui' -import { BlogTagsFragment } from './BlogTags.gql' - -type BlogTagsProps = BlogTagsFragment - -export function BlogTags(props: BlogTagsProps) { - const { relatedPages } = props - return ( - - {relatedPages.map(({ url, title }) => { - if (!title) return null - return - })} - - ) -} diff --git a/examples/magento-graphcms/components/Blog/RowBlogContent.graphql b/examples/magento-graphcms/components/Blog/RowBlogContent.graphql deleted file mode 100644 index bd169574849..00000000000 --- a/examples/magento-graphcms/components/Blog/RowBlogContent.graphql +++ /dev/null @@ -1,5 +0,0 @@ -fragment RowBlogContent on RowBlogContent { - content { - raw - } -} diff --git a/examples/magento-graphcms/components/Blog/RowBlogContent.tsx b/examples/magento-graphcms/components/Blog/RowBlogContent.tsx deleted file mode 100644 index 5b76d12b3db..00000000000 --- a/examples/magento-graphcms/components/Blog/RowBlogContent.tsx +++ /dev/null @@ -1,15 +0,0 @@ -import { RichText } from '@graphcommerce/graphcms-ui' -import { BlogContent } from '@graphcommerce/next-ui' -import { RowBlogContentFragment } from './RowBlogContent.gql' - -type RowBlogContentProps = RowBlogContentFragment - -export function RowBlogContent(props: RowBlogContentProps) { - const { content } = props - if (!content) return null - return ( - - - - ) -} diff --git a/examples/magento-graphcms/components/Blog/index.ts b/examples/magento-graphcms/components/Blog/index.ts deleted file mode 100644 index 86e8ba13c5e..00000000000 --- a/examples/magento-graphcms/components/Blog/index.ts +++ /dev/null @@ -1,12 +0,0 @@ -export * from './BlogAuthor' -export * from './BlogHeader' -export * from './BlogItem' -export * from './BlogList' -export * from './BlogList.gql' -export * from './BlogListTagged.gql' -export * from './BlogPaths.gql' -export * from './BlogPostPaths.gql' -export * from './BlogPostTaggedPaths.gql' -export * from './BlogTags' -export * from './RowBlogContent' -export { BlogTitle } from '@graphcommerce/next-ui' diff --git a/examples/magento-graphcms/components/Layout/Layout.graphql b/examples/magento-graphcms/components/Layout/Layout.graphql index 05c9ba65625..018d5dc9531 100644 --- a/examples/magento-graphcms/components/Layout/Layout.graphql +++ b/examples/magento-graphcms/components/Layout/Layout.graphql @@ -3,5 +3,4 @@ query Layout { __typename } ...MenuQueryFragment - ...FooterQueryFragment } diff --git a/examples/magento-graphcms/components/ProductListItems/CategoryFilterLayout.tsx b/examples/magento-graphcms/components/ProductListItems/CategoryFilterLayout.tsx index a912fa13089..4017df069e2 100644 --- a/examples/magento-graphcms/components/ProductListItems/CategoryFilterLayout.tsx +++ b/examples/magento-graphcms/components/ProductListItems/CategoryFilterLayout.tsx @@ -12,6 +12,7 @@ import { ProductListCount, ProductListFilters, ProductListFiltersContainer, + ProductListItemsBase, ProductListPagination, ProductListParams, ProductListParamsProvider, @@ -21,6 +22,7 @@ import { import { StickyBelowHeader } from '@graphcommerce/next-ui' import { Container } from '@mui/material' import { ProductListItems } from './ProductListItems' +import { productListRenderer } from './productListRenderer' export type ProductListFilterLayoutProps = ProductListQuery & ProductFiltersQuery & { @@ -37,7 +39,14 @@ export function CategoryFilterLayout(props: ProductListFilterLayoutProps) { const { total_count, sort_fields, page_info } = products - const items = + const items = ( + + ) if (import.meta.graphCommerce.productFiltersPro) { const horizontalFilters = ( diff --git a/examples/magento-graphcms/components/index.ts b/examples/magento-graphcms/components/index.ts index 6c91a74478a..7fa07cee05d 100644 --- a/examples/magento-graphcms/components/index.ts +++ b/examples/magento-graphcms/components/index.ts @@ -1,5 +1,2 @@ -export * from '@graphcommerce/graphcms-ui/components/Blog' export * from './Layout' -export * from './Usps/Usps' -export * from '@graphcommerce/graphcms-ui/components' export * from './ProductListItems' diff --git a/examples/magento-graphcms/graphql/DefaultPage.graphql b/examples/magento-graphcms/graphql/DefaultPage.graphql deleted file mode 100644 index 86ae409e85b..00000000000 --- a/examples/magento-graphcms/graphql/DefaultPage.graphql +++ /dev/null @@ -1,4 +0,0 @@ -# @deprecated, please use pageContent form @graphcommerce/graphcms-ui -query DefaultPage($url: String!) { - ...PageContentQueryFragment -} diff --git a/examples/magento-graphcms/graphql/ProductPage.graphql b/examples/magento-graphcms/graphql/ProductPage.graphql deleted file mode 100644 index e0f05dd22a0..00000000000 --- a/examples/magento-graphcms/graphql/ProductPage.graphql +++ /dev/null @@ -1,6 +0,0 @@ -# @deprecated This query is for the legacyProductPages (/product/[url]) and will be removed. -query ProductPage($url: String!, $urlKey: String!, $reviewPageSize: Int = 3, $reviewPage: Int = 1) { - ...UspsQueryFragment - ...ProductPageQueryFragment - ...PageContentQueryFragment -} diff --git a/examples/magento-graphcms/pages/[...url].tsx b/examples/magento-graphcms/pages/[...url].tsx index 2329331c1f0..63e9951e760 100644 --- a/examples/magento-graphcms/pages/[...url].tsx +++ b/examples/magento-graphcms/pages/[...url].tsx @@ -5,7 +5,6 @@ import { PageContent, } from '@graphcommerce/content-areas' import { PageOptions } from '@graphcommerce/framer-next-pages' -import { Asset } from '@graphcommerce/graphcms-ui' import { flushMeasurePerf } from '@graphcommerce/graphql' import { CategoryChildren, @@ -36,8 +35,6 @@ import { LayoutNavigation, LayoutNavigationProps, productListRenderer, - RowProduct, - RowRenderer, } from '../components' import { CategoryPageDocument, CategoryPageQuery } from '../graphql/CategoryPage.gql' import { graphqlSharedClient, graphqlSsrClient } from '../lib/graphql/graphqlSsrClient' diff --git a/examples/magento-graphcms/pages/blog/[url].tsx b/examples/magento-graphcms/pages/blog/[url].tsx index 01fd1f86737..5a9aed03d5d 100644 --- a/examples/magento-graphcms/pages/blog/[url].tsx +++ b/examples/magento-graphcms/pages/blog/[url].tsx @@ -1,23 +1,10 @@ import { ContentArea, PageContent, pageContent } from '@graphcommerce/content-areas' import { PageOptions } from '@graphcommerce/framer-next-pages' import { StoreConfigDocument } from '@graphcommerce/magento-store' -import { - PageMeta, - BlogTitle, - GetStaticProps, - Row, - LayoutTitle, - LayoutHeader, -} from '@graphcommerce/next-ui' +import { PageMeta, GetStaticProps, Row, LayoutTitle, LayoutHeader } from '@graphcommerce/next-ui' +import { Box } from '@mui/material' import { GetStaticPaths } from 'next' import { - BlogAuthor, - BlogHeader, - BlogList, - BlogListDocument, - BlogListQuery, - BlogPostPathsDocument, - BlogTags, LayoutDocument, LayoutNavigation, LayoutNavigationProps, @@ -31,29 +18,28 @@ type GetPageStaticPaths = GetStaticPaths type GetPageStaticProps = GetStaticProps function BlogPage(props: Props) { - const { blogPosts, content, pages } = props - - const page = pages[0] - const title = page?.title ?? '' + const { blogPosts, content } = props return ( <> - {title} + {content.title} - + - {title} + ({ maxWidth: theme.breakpoints.values.md, margin: '0 auto' })]}> + {content.title} + - {page.author ? : null} - {page.asset ? : null} + {/* {page.author ? : null} */} + {/* {page.asset ? : null} */} - + {/* */} diff --git a/examples/magento-graphcms/pages/blog/page/[page].tsx b/examples/magento-graphcms/pages/blog/page/[page].tsx index 58f7951c4b5..d090e7a83ef 100644 --- a/examples/magento-graphcms/pages/blog/page/[page].tsx +++ b/examples/magento-graphcms/pages/blog/page/[page].tsx @@ -13,11 +13,6 @@ import { GetStaticPaths } from 'next' import { useRouter } from 'next/router' import React from 'react' import { - BlogList, - BlogListDocument, - BlogListQuery, - BlogPathsDocument, - BlogPathsQuery, LayoutDocument, LayoutNavigation, LayoutNavigationProps, @@ -33,23 +28,21 @@ type GetPageStaticProps = GetStaticProps - + - {title} + {content.title} - {title} + {content.title} diff --git a/examples/magento-graphcms/pages/blog/tagged/[url].tsx b/examples/magento-graphcms/pages/blog/tagged/[url].tsx index c43aff6a589..3949cdde6ed 100644 --- a/examples/magento-graphcms/pages/blog/tagged/[url].tsx +++ b/examples/magento-graphcms/pages/blog/tagged/[url].tsx @@ -5,14 +5,6 @@ import { PageMeta, GetStaticProps, Row, LayoutTitle, LayoutHeader } from '@graph import { Trans } from '@lingui/react' import { GetStaticPaths } from 'next' import { - BlogAuthor, - BlogHeader, - BlogList, - BlogPostTaggedPathsDocument, - BlogListTaggedDocument, - BlogListTaggedQuery, - BlogTags, - BlogTitle, LayoutDocument, LayoutNavigation, LayoutNavigationProps, diff --git a/examples/magento-graphcms/pages/modal/[...url].tsx b/examples/magento-graphcms/pages/modal/[...url].tsx index b8cd9831524..530df24da5b 100644 --- a/examples/magento-graphcms/pages/modal/[...url].tsx +++ b/examples/magento-graphcms/pages/modal/[...url].tsx @@ -69,7 +69,6 @@ export const getStaticProps: GetPageStaticProps = async ({ locale, params }) => return { props: { content: await content, - ...(await page).data, ...(await layout).data, apolloState: await conf.then(() => client.cache.extract()), variantMd: 'bottom', diff --git a/examples/magento-graphcms/pages/p/[url].tsx b/examples/magento-graphcms/pages/p/[url].tsx index fef7d7c6326..c0e17903f01 100644 --- a/examples/magento-graphcms/pages/p/[url].tsx +++ b/examples/magento-graphcms/pages/p/[url].tsx @@ -49,9 +49,7 @@ import { LayoutNavigation, LayoutNavigationProps, productListRenderer, - Usps, } from '../../components' -import { UspsDocument, UspsQuery } from '../../components/Usps/Usps.gql' import { ProductPage2Document, ProductPage2Query } from '../../graphql/ProductPage2.gql' import { graphqlSharedClient, graphqlSsrClient } from '../../lib/graphql/graphqlSsrClient' @@ -66,7 +64,7 @@ type GetPageStaticPaths = GetStaticPaths type GetPageStaticProps = GetStaticProps function ProductPage(props: Props) { - const { content, products, relatedUpsells, usps, sidebarUsps, pages, defaultValues } = props + const { content, products, relatedUpsells, usps, sidebarUsps, defaultValues } = props const product = mergeDeep( products?.items?.[0], diff --git a/examples/magento-graphcms/pages/service/[[...url]].tsx b/examples/magento-graphcms/pages/service/[[...url]].tsx index 0e85bbf1fbe..09cd5eab02d 100644 --- a/examples/magento-graphcms/pages/service/[[...url]].tsx +++ b/examples/magento-graphcms/pages/service/[[...url]].tsx @@ -21,7 +21,7 @@ type GetPageStaticPaths = GetStaticPaths type GetPageStaticProps = GetStaticProps function ServicePage(props: Props) { - const { content, pages } = props + const { content } = props return ( <> @@ -85,7 +85,6 @@ export const getStaticProps: GetPageStaticProps = async ({ locale, params }) => return { props: { content: await content, - ...(await page).data, ...(await layout).data, up: isRoot ? null : { href: '/service', title: i18n._(/* i18n */ 'Customer Service') }, apolloState: await conf.then(() => client.cache.extract()), diff --git a/packages/content-areas/server/pageContent.ts b/packages/content-areas/server/pageContent.ts index 97a90066e0e..7dd1095955e 100644 --- a/packages/content-areas/server/pageContent.ts +++ b/packages/content-areas/server/pageContent.ts @@ -7,5 +7,7 @@ export function pageContent( additionalProperties?: Promise | object, cached = false, ): Promise { - return Promise.resolve({}) + return Promise.resolve({ + metadata: null, + }) } diff --git a/packages/hygraph-ui/components/Blog/BlogHeader.tsx b/packages/hygraph-ui/components/Blog/BlogHeader.tsx index 68c2b6da2b6..945b454b5e9 100644 --- a/packages/hygraph-ui/components/Blog/BlogHeader.tsx +++ b/packages/hygraph-ui/components/Blog/BlogHeader.tsx @@ -1,5 +1,5 @@ -import { Asset, AssetFragment } from '@graphcommerce/graphcms-ui' import { BlogHeader as NextBlogHeader } from '@graphcommerce/next-ui' +import { Asset, AssetFragment } from '../Asset/Asset' export function BlogHeader(props: { asset?: AssetFragment }) { const { asset } = props diff --git a/packages/hygraph-ui/components/Blog/BlogItem.tsx b/packages/hygraph-ui/components/Blog/BlogItem.tsx index 8629246d7ca..f29b1d3f414 100644 --- a/packages/hygraph-ui/components/Blog/BlogItem.tsx +++ b/packages/hygraph-ui/components/Blog/BlogItem.tsx @@ -1,8 +1,8 @@ -import { Asset } from '@graphcommerce/graphcms-ui' import { BlogListItem } from '@graphcommerce/next-ui' import { Trans } from '@lingui/react' import { Typography, useTheme } from '@mui/material' import { BlogItemFragment } from './BlogItem.gql' +import { Asset } from '../Asset/Asset' type BlogItemProps = BlogItemFragment diff --git a/examples/magento-graphcms/components/Layout/FooterQueryFragment.graphql b/packages/hygraph-ui/components/FooterQueryFragment.graphql similarity index 100% rename from examples/magento-graphcms/components/Layout/FooterQueryFragment.graphql rename to packages/hygraph-ui/components/FooterQueryFragment.graphql diff --git a/packages/hygraph-ui/components/RowProduct/variant/Grid.tsx b/packages/hygraph-ui/components/RowProduct/variant/Grid.tsx index d36aea4613f..6e349fff4e4 100644 --- a/packages/hygraph-ui/components/RowProduct/variant/Grid.tsx +++ b/packages/hygraph-ui/components/RowProduct/variant/Grid.tsx @@ -1,12 +1,10 @@ +import { ProductItemsGridProps, ProductListItemsBase } from '@graphcommerce/magento-product' import { ContainerWithHeader } from '@graphcommerce/next-ui' import { Link } from '@mui/material' -import { - ProductListItems, - ProductListItemsProps, -} from '../../../../../examples/magento-graphcms/components/ProductListItems/ProductListItems' import { RowProductFragment } from '../RowProduct.gql' +import { productListRenderer } from '../../../../../examples/magento-graphcms/components/ProductListItems/productListRenderer' -type GridProps = RowProductFragment & ProductListItemsProps +type GridProps = RowProductFragment & Omit export function Grid(props: GridProps) { const { title, pageLinks, productCopy, ...productListItems } = props @@ -20,7 +18,13 @@ export function Grid(props: GridProps) { ))} > - + ) } diff --git a/examples/magento-graphcms/components/Usps/Usps.graphql b/packages/hygraph-ui/components/Usps/Usps.graphql similarity index 100% rename from examples/magento-graphcms/components/Usps/Usps.graphql rename to packages/hygraph-ui/components/Usps/Usps.graphql diff --git a/examples/magento-graphcms/components/Usps/Usps.tsx b/packages/hygraph-ui/components/Usps/Usps.tsx similarity index 90% rename from examples/magento-graphcms/components/Usps/Usps.tsx rename to packages/hygraph-ui/components/Usps/Usps.tsx index f517692acd6..038c44669d5 100644 --- a/examples/magento-graphcms/components/Usps/Usps.tsx +++ b/packages/hygraph-ui/components/Usps/Usps.tsx @@ -1,5 +1,6 @@ -import { RichText, Asset } from '@graphcommerce/graphcms-ui' import { UspList, UspListItem, UspListProps } from '@graphcommerce/next-ui' +import { Asset } from '../Asset/Asset' +import { RichText } from '../RichText' import { UspsQueryFragment } from './UspsQueryFragment.gql' export type ProductUspsProps = UspsQueryFragment & Pick diff --git a/examples/magento-graphcms/components/Usps/UspsQueryFragment.graphql b/packages/hygraph-ui/components/Usps/UspsQueryFragment.graphql similarity index 100% rename from examples/magento-graphcms/components/Usps/UspsQueryFragment.graphql rename to packages/hygraph-ui/components/Usps/UspsQueryFragment.graphql diff --git a/packages/hygraph-ui/package.json b/packages/hygraph-ui/package.json index 7076adcae3f..f882e03d982 100644 --- a/packages/hygraph-ui/package.json +++ b/packages/hygraph-ui/package.json @@ -16,10 +16,14 @@ "@graphcommerce/eslint-config-pwa": "^8.0.0-canary.75", "@graphcommerce/graphql": "^8.0.0-canary.75", "@graphcommerce/image": "^8.0.0-canary.75", + "@graphcommerce/magento-product": "^8.0.0-canary.75", "@graphcommerce/next-config": "^8.0.0-canary.75", "@graphcommerce/next-ui": "^8.0.0-canary.75", "@graphcommerce/prettier-config-pwa": "^8.0.0-canary.75", "@graphcommerce/typescript-config-pwa": "^8.0.0-canary.75", + "@lingui/core": "^4.2.1", + "@lingui/macro": "^4.2.1", + "@lingui/react": "^4.2.1", "@mui/material": "^5.10.16", "next": "*", "react": "^18.2.0", diff --git a/packages/magento-product/components/ProductPageMeta/ProductPageMeta.tsx b/packages/magento-product/components/ProductPageMeta/ProductPageMeta.tsx index 3675a67a124..2c579bbcaf6 100644 --- a/packages/magento-product/components/ProductPageMeta/ProductPageMeta.tsx +++ b/packages/magento-product/components/ProductPageMeta/ProductPageMeta.tsx @@ -1,10 +1,10 @@ import { PageMeta } from '@graphcommerce/magento-store' -import { PageMetaProps } from '@graphcommerce/next-ui' import { productLink } from '../../hooks/useProductLink' import { ProductPageMetaFragment } from './ProductPageMeta.gql' +import { PageMetaPropsOld } from '@graphcommerce/next-ui' export type ProductPageMetaProps = { product: ProductPageMetaFragment } & Pick< - PageMetaProps, + PageMetaPropsOld, 'children' | 'ogImage' | 'ogImageUseFallback' > diff --git a/packages/magento-store/PageMeta.tsx b/packages/magento-store/PageMeta.tsx index cad4b8c1506..f80c819d811 100644 --- a/packages/magento-store/PageMeta.tsx +++ b/packages/magento-store/PageMeta.tsx @@ -1,16 +1,15 @@ import { useQuery } from '@graphcommerce/graphql' import { - PageMeta as NextPageMeta, PageMetaProps as NextPageMetaProps, + PageMetaOld, + isPageMetaPropsNew, } from '@graphcommerce/next-ui' +import { PageMetaNew } from '@graphcommerce/next-ui/PageMeta/PageMetaNew' import { StoreConfigDocument } from './StoreConfig.gql' -type PageMetaProps = Omit & { - canonical?: string -} +type PageMetaProps = NextPageMetaProps export function PageMeta(props: PageMetaProps) { - const { children, title, ...pageMetaProps } = props const config = useQuery(StoreConfigDocument) const prefix = config.data?.storeConfig?.title_prefix ?? '' @@ -18,14 +17,31 @@ export function PageMeta(props: PageMetaProps) { const defaultTitle = config.data?.storeConfig?.default_title ?? '' const suffix = config.data?.storeConfig?.title_suffix ?? '' - let pageTitle = prefix ?? '' - if (title ?? defaultTitle) pageTitle += ` ${title ?? defaultTitle}` - if (separator && suffix) pageTitle += ` ${separator}` - if (suffix) pageTitle += ` ${suffix}` + function addPrefix(title: string) { + let pageTitle = prefix ?? '' + if (title ?? defaultTitle) pageTitle += ` ${title ?? defaultTitle}` + if (separator && suffix) pageTitle += ` ${separator}` + if (suffix) pageTitle += ` ${suffix}` + return pageTitle + } + + if (isPageMetaPropsNew(props)) { + const { metadata } = props + + return ( + + ) + } - return ( - - {children} - - ) + const { title, ...pageMetaProps } = props + return } diff --git a/packages/next-ui/PageMeta/PageMeta.tsx b/packages/next-ui/PageMeta/PageMeta.tsx index d51b7d22516..0c88fb267f1 100644 --- a/packages/next-ui/PageMeta/PageMeta.tsx +++ b/packages/next-ui/PageMeta/PageMeta.tsx @@ -26,7 +26,7 @@ type MetaRobotsAll = ['all' | 'none'] type Canonical = `http://${string}` | `https://${string}` | `/${string}` | string -type PageMetaPropsOld = { +export type PageMetaPropsOld = { title: string canonical?: Canonical metaDescription?: string diff --git a/yarn.lock b/yarn.lock index b68072a81a9..c6a92419fd5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2964,10 +2964,14 @@ __metadata: "@graphcommerce/eslint-config-pwa": ^8.0.0-canary.75 "@graphcommerce/graphql": ^8.0.0-canary.75 "@graphcommerce/image": ^8.0.0-canary.75 + "@graphcommerce/magento-product": ^8.0.0-canary.75 "@graphcommerce/next-config": ^8.0.0-canary.75 "@graphcommerce/next-ui": ^8.0.0-canary.75 "@graphcommerce/prettier-config-pwa": ^8.0.0-canary.75 "@graphcommerce/typescript-config-pwa": ^8.0.0-canary.75 + "@lingui/core": ^4.2.1 + "@lingui/macro": ^4.2.1 + "@lingui/react": ^4.2.1 "@mui/material": ^5.10.16 next: "*" react: ^18.2.0 From dcf9d5edcafd646b8b6abeda41b9ed188838df38 Mon Sep 17 00:00:00 2001 From: Joshua Bolk Date: Wed, 10 Jan 2024 13:55:47 +0100 Subject: [PATCH 06/33] [GCOM-1260] add content-area pkg to hygraph-ui --- examples/magento-graphcms/pages/[...url].tsx | 2 +- packages/hygraph-ui/package.json | 1 + packages/hygraph-ui/plugins/hygraphPageContentPlugin.ts | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/examples/magento-graphcms/pages/[...url].tsx b/examples/magento-graphcms/pages/[...url].tsx index 63e9951e760..21985c1dd1b 100644 --- a/examples/magento-graphcms/pages/[...url].tsx +++ b/examples/magento-graphcms/pages/[...url].tsx @@ -26,7 +26,7 @@ import { ProductListQuery, } from '@graphcommerce/magento-product' import { redirectOrNotFound, StoreConfigDocument } from '@graphcommerce/magento-store' -import { GetStaticProps, LayoutHeader, LayoutTitle, MetaRobots } from '@graphcommerce/next-ui' +import { GetStaticProps, LayoutHeader, LayoutTitle } from '@graphcommerce/next-ui' import { Container } from '@mui/material' import { GetStaticPaths } from 'next' import { diff --git a/packages/hygraph-ui/package.json b/packages/hygraph-ui/package.json index f882e03d982..68ed4c5a688 100644 --- a/packages/hygraph-ui/package.json +++ b/packages/hygraph-ui/package.json @@ -12,6 +12,7 @@ } }, "peerDependencies": { + "@graphcommerce/content-areas": "^8.0.0-canary.75", "@graphcommerce/ecommerce-ui": "^8.0.0-canary.75", "@graphcommerce/eslint-config-pwa": "^8.0.0-canary.75", "@graphcommerce/graphql": "^8.0.0-canary.75", diff --git a/packages/hygraph-ui/plugins/hygraphPageContentPlugin.ts b/packages/hygraph-ui/plugins/hygraphPageContentPlugin.ts index 43452d12480..8bba41406ed 100644 --- a/packages/hygraph-ui/plugins/hygraphPageContentPlugin.ts +++ b/packages/hygraph-ui/plugins/hygraphPageContentPlugin.ts @@ -34,7 +34,7 @@ const hygraphPageContentPlugin: MethodPlugin = async ( } : { index: true, follow: true }, }), - hygraphPage: content.data.pages?.[0], + hygraphPage: page, } } From e4874d73d5f0e13f4195a2da5dd9d9676ee1ac53 Mon Sep 17 00:00:00 2001 From: Joshua Bolk Date: Thu, 11 Jan 2024 14:37:08 +0100 Subject: [PATCH 07/33] [GCOM-1260] add renderer to HygraphRowRenderer --- examples/magento-graphcms/pages/index.tsx | 23 +++++++++++++++++-- .../components/ContentArea/ContentArea.tsx | 2 +- .../hygraph-ui/components/RowRenderer.tsx | 2 +- .../hygraph-ui/plugins/HygraphContentArea.tsx | 4 ++-- packages/hygraph-ui/types.ts | 3 ++- yarn.lock | 1 + 6 files changed, 28 insertions(+), 7 deletions(-) diff --git a/examples/magento-graphcms/pages/index.tsx b/examples/magento-graphcms/pages/index.tsx index fecb134edae..9477d7792aa 100644 --- a/examples/magento-graphcms/pages/index.tsx +++ b/examples/magento-graphcms/pages/index.tsx @@ -1,8 +1,9 @@ import { ContentAreaHome, PageContent, pageContent } from '@graphcommerce/content-areas' import { PageOptions } from '@graphcommerce/framer-next-pages' +import { RowProduct } from '@graphcommerce/graphcms-ui' import { ProductListDocument, ProductListQuery } from '@graphcommerce/magento-product' import { StoreConfigDocument } from '@graphcommerce/magento-store' -import { GetStaticProps, LayoutHeader, MetaRobots, PageMeta } from '@graphcommerce/next-ui' +import { GetStaticProps, LayoutHeader, PageMeta } from '@graphcommerce/next-ui' import { LayoutDocument, LayoutNavigation, @@ -33,7 +34,25 @@ function CmsPage(props: Props) { - + { + const { identity } = rowProps + + if (identity === 'home-favorites') + return ( + + ) + if (identity === 'home-latest') + return + if (identity === 'home-swipable') + return + return + }, + }} + /> {/* {page && ( } diff --git a/packages/hygraph-ui/components/RowRenderer.tsx b/packages/hygraph-ui/components/RowRenderer.tsx index ad8acc67e1a..dd102fd61c7 100644 --- a/packages/hygraph-ui/components/RowRenderer.tsx +++ b/packages/hygraph-ui/components/RowRenderer.tsx @@ -14,7 +14,7 @@ import { RowRendererFragment } from './RowRenderer.gql' import { RowServiceOptions } from './RowServiceOptions/RowServiceOptions' import { RowSpecialBanner } from './RowSpecialBanner/RowSpecialBanner' -type ContentTypeRenderer = TypeRenderer +export type ContentTypeRenderer = TypeRenderer const defaultRenderer: Partial = { RowColumnOne, diff --git a/packages/hygraph-ui/plugins/HygraphContentArea.tsx b/packages/hygraph-ui/plugins/HygraphContentArea.tsx index 6da03530d97..36b3f065e49 100644 --- a/packages/hygraph-ui/plugins/HygraphContentArea.tsx +++ b/packages/hygraph-ui/plugins/HygraphContentArea.tsx @@ -7,12 +7,12 @@ export const exported = '@graphcommerce/content-areas/components/ContentArea/Con const HygraphContentArea: ReactPlugin = (props) => { const { Prev, ...rest } = props - const { content } = props + const { content, renderer } = props return ( <> - {content.hygraphPage && } + {content.hygraphPage && } ) } diff --git a/packages/hygraph-ui/types.ts b/packages/hygraph-ui/types.ts index 3e43eef6713..a7f62224835 100644 --- a/packages/hygraph-ui/types.ts +++ b/packages/hygraph-ui/types.ts @@ -1,8 +1,9 @@ +import { ContentTypeRenderer } from './components' import { HygraphPageFragment } from './graphql' declare module '@graphcommerce/content-areas/components/ContentArea' { export interface ContentAreaProps { - renderer: string + renderer: Partial } } diff --git a/yarn.lock b/yarn.lock index c6a92419fd5..a2d2afecd89 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2960,6 +2960,7 @@ __metadata: version: 0.0.0-use.local resolution: "@graphcommerce/graphcms-ui@workspace:packages/hygraph-ui" peerDependencies: + "@graphcommerce/content-areas": ^8.0.0-canary.75 "@graphcommerce/ecommerce-ui": ^8.0.0-canary.75 "@graphcommerce/eslint-config-pwa": ^8.0.0-canary.75 "@graphcommerce/graphql": ^8.0.0-canary.75 From cad7f56bedf227d17dd74df7e0b472c76bdd2140 Mon Sep 17 00:00:00 2001 From: Joshua Bolk Date: Thu, 11 Jan 2024 15:46:34 +0100 Subject: [PATCH 08/33] [GCOM-1260] Make Hygraph RowRenderer extenable --- .../GraphCMS/ExtendRowRenderer.graphql | 5 ++++ .../plugins/ExtendRowRenderer.tsx | 23 +++++++++++++++++++ .../components/RowLinks/RowLinks.tsx | 6 +++-- .../components/RowProduct/RowProduct.tsx | 5 ++-- .../hygraph-ui/components/RowRenderer.tsx | 2 +- 5 files changed, 36 insertions(+), 5 deletions(-) create mode 100644 examples/magento-graphcms/components/GraphCMS/ExtendRowRenderer.graphql create mode 100644 examples/magento-graphcms/plugins/ExtendRowRenderer.tsx diff --git a/examples/magento-graphcms/components/GraphCMS/ExtendRowRenderer.graphql b/examples/magento-graphcms/components/GraphCMS/ExtendRowRenderer.graphql new file mode 100644 index 00000000000..899a4014be1 --- /dev/null +++ b/examples/magento-graphcms/components/GraphCMS/ExtendRowRenderer.graphql @@ -0,0 +1,5 @@ +# fragment ExtendRowRenderer on Page @inject(into: ["HygraphPage"]) { +# content { +# ...CustomRow +# } +# } diff --git a/examples/magento-graphcms/plugins/ExtendRowRenderer.tsx b/examples/magento-graphcms/plugins/ExtendRowRenderer.tsx new file mode 100644 index 00000000000..bb7fc38f532 --- /dev/null +++ b/examples/magento-graphcms/plugins/ExtendRowRenderer.tsx @@ -0,0 +1,23 @@ +import { PageProps, defaultRenderer } from '@graphcommerce/graphcms-ui' +import { PluginProps } from '@graphcommerce/next-config' + +export const component = 'RowRenderer' +export const exported = '@graphcommerce/graphcms-ui/components/RowRenderer' + +const extendedRenderer: { [key: string]: (props) => React.ReactElement } = { + // CustomRow, +} + +function ExtendRowRendererPlugin(props: PluginProps) { + const { Prev, renderer, ...rest } = props + + const mergedRenderer = { + ...defaultRenderer, + ...extendedRenderer, + ...renderer, + } + + return +} + +export const Plugin = ExtendRowRendererPlugin diff --git a/packages/hygraph-ui/components/RowLinks/RowLinks.tsx b/packages/hygraph-ui/components/RowLinks/RowLinks.tsx index fdcbc50b65a..5cd9ffe552c 100644 --- a/packages/hygraph-ui/components/RowLinks/RowLinks.tsx +++ b/packages/hygraph-ui/components/RowLinks/RowLinks.tsx @@ -18,10 +18,12 @@ const defaultRenderer: Partial = { } export function RowLinks(props: RowLinksProps) { - const { renderer, linksVariant, ...RowLinksProps } = props + const { renderer, ...RowLinksProps } = props + + let { linksVariant } = props const mergedRenderer = { ...defaultRenderer, ...renderer } as VariantRenderer - if (!linksVariant) return null + if (!linksVariant) linksVariant = 'Inline' const RenderType = mergedRenderer?.[linksVariant] ?? diff --git a/packages/hygraph-ui/components/RowProduct/RowProduct.tsx b/packages/hygraph-ui/components/RowProduct/RowProduct.tsx index ce6e3e4d884..d735d28fe8b 100644 --- a/packages/hygraph-ui/components/RowProduct/RowProduct.tsx +++ b/packages/hygraph-ui/components/RowProduct/RowProduct.tsx @@ -34,10 +34,11 @@ const defaultRenderer: Partial = { } export function RowProduct(props: RowProductProps) { - const { renderer, variant, ...RowProductProps } = props + const { renderer, ...RowProductProps } = props + let { variant } = props const mergedRenderer = { ...defaultRenderer, ...renderer } as VariantRenderer - if (!variant) return null + if (!variant) variant = 'Related' const RenderType = mergedRenderer?.[variant] ?? diff --git a/packages/hygraph-ui/components/RowRenderer.tsx b/packages/hygraph-ui/components/RowRenderer.tsx index dd102fd61c7..e61a83373ff 100644 --- a/packages/hygraph-ui/components/RowRenderer.tsx +++ b/packages/hygraph-ui/components/RowRenderer.tsx @@ -16,7 +16,7 @@ import { RowSpecialBanner } from './RowSpecialBanner/RowSpecialBanner' export type ContentTypeRenderer = TypeRenderer -const defaultRenderer: Partial = { +export const defaultRenderer: { [key: string]: (props) => React.ReactElement } = { RowColumnOne, RowColumnTwo, RowColumnThree, From a13118c15e9b25c285f2d5e9ed841ebc4cfc338a Mon Sep 17 00:00:00 2001 From: Joshua Bolk Date: Thu, 11 Jan 2024 17:00:23 +0100 Subject: [PATCH 09/33] [GCOM-1260] Fix ProductListRenderer in ContentArea --- .../magento-graphcms/plugins/ExtendRowRenderer.tsx | 3 +-- .../components/RowProduct/RowProduct.tsx | 8 +++++--- .../components/RowProduct/variant/Backstory.tsx | 13 +++++++++---- .../components/RowProduct/variant/Feature.tsx | 4 +++- .../components/RowProduct/variant/FeatureBoxed.tsx | 4 +++- .../components/RowProduct/variant/Grid.tsx | 14 +++++++++----- .../components/RowProduct/variant/Related.tsx | 14 ++++++++++---- .../components/RowProduct/variant/Reviews.tsx | 4 +++- .../components/RowProduct/variant/Specs.tsx | 5 +++-- .../components/RowProduct/variant/Swipeable.tsx | 14 ++++++++++---- .../components/RowProduct/variant/Upsells.tsx | 14 ++++++++++---- packages/hygraph-ui/components/RowRenderer.tsx | 13 +++++++++++-- packages/hygraph-ui/plugins/HygraphContentArea.tsx | 10 ++++++++-- 13 files changed, 85 insertions(+), 35 deletions(-) diff --git a/examples/magento-graphcms/plugins/ExtendRowRenderer.tsx b/examples/magento-graphcms/plugins/ExtendRowRenderer.tsx index bb7fc38f532..1d46d6b0285 100644 --- a/examples/magento-graphcms/plugins/ExtendRowRenderer.tsx +++ b/examples/magento-graphcms/plugins/ExtendRowRenderer.tsx @@ -12,9 +12,8 @@ function ExtendRowRendererPlugin(props: PluginProps) { const { Prev, renderer, ...rest } = props const mergedRenderer = { - ...defaultRenderer, - ...extendedRenderer, ...renderer, + ...extendedRenderer, } return diff --git a/packages/hygraph-ui/components/RowProduct/RowProduct.tsx b/packages/hygraph-ui/components/RowProduct/RowProduct.tsx index d735d28fe8b..e5bd75d331f 100644 --- a/packages/hygraph-ui/components/RowProduct/RowProduct.tsx +++ b/packages/hygraph-ui/components/RowProduct/RowProduct.tsx @@ -1,3 +1,4 @@ +import { ProductListItemRenderer } from '@graphcommerce/magento-product' import { ProductSpecsFragment } from '@graphcommerce/magento-product/components/ProductSpecs/ProductSpecs.gql' import { RowProductFragment } from './RowProduct.gql' import { @@ -14,11 +15,12 @@ import { type VariantRenderer = Record< NonNullable, - React.VFC + React.VFC > type RowProductProps = RowProductFragment & { renderer?: Partial + productListItemRenderer: ProductListItemRenderer } & ProductSpecsFragment & { items?: unknown } & { sku?: string | null | undefined } const defaultRenderer: Partial = { @@ -34,7 +36,7 @@ const defaultRenderer: Partial = { } export function RowProduct(props: RowProductProps) { - const { renderer, ...RowProductProps } = props + const { renderer, productListItemRenderer, ...RowProductProps } = props let { variant } = props const mergedRenderer = { ...defaultRenderer, ...renderer } as VariantRenderer @@ -47,5 +49,5 @@ export function RowProduct(props: RowProductProps) { return null }) - return + return } diff --git a/packages/hygraph-ui/components/RowProduct/variant/Backstory.tsx b/packages/hygraph-ui/components/RowProduct/variant/Backstory.tsx index 9ec1493f2d1..9c20caf2f99 100644 --- a/packages/hygraph-ui/components/RowProduct/variant/Backstory.tsx +++ b/packages/hygraph-ui/components/RowProduct/variant/Backstory.tsx @@ -1,14 +1,19 @@ -import { AddProductsToCartForm, ProductListItemsFragment } from '@graphcommerce/magento-product' +import { + AddProductsToCartForm, + ProductListItemRenderer, + ProductListItemsFragment, +} from '@graphcommerce/magento-product' import { ParagraphWithSidebarSlide, RenderType } from '@graphcommerce/next-ui' import { useTheme } from '@mui/material' import { Asset } from '../../Asset/Asset' import { RowProductFragment } from '../RowProduct.gql' import { RichText } from '../../RichText' -type BackstoryProps = RowProductFragment & ProductListItemsFragment +type BackstoryProps = RowProductFragment & + ProductListItemsFragment & { productListItemRenderer: ProductListItemRenderer } export function Backstory(props: BackstoryProps) { - const { productCopy, asset, ...productListItems } = props + const { productCopy, asset, productListItemRenderer, ...productListItems } = props const theme = useTheme() const singleItem = productListItems?.items?.[(productListItems.items?.length ?? 1) - 1] @@ -24,7 +29,7 @@ export function Backstory(props: BackstoryProps) { } slidingItems={ diff --git a/packages/hygraph-ui/components/RowProduct/variant/Feature.tsx b/packages/hygraph-ui/components/RowProduct/variant/Feature.tsx index 1e288b05500..08aacdf09a7 100644 --- a/packages/hygraph-ui/components/RowProduct/variant/Feature.tsx +++ b/packages/hygraph-ui/components/RowProduct/variant/Feature.tsx @@ -4,8 +4,10 @@ import { Typography, useTheme } from '@mui/material' import { RowProductFragment } from '../RowProduct.gql' import { ProductFeatureMediaFragment } from './ProductFeatureMedia.gql' import { RichText } from '../../RichText' +import { ProductListItemRenderer } from '@graphcommerce/magento-product' -type FeatureProps = RowProductFragment & ProductFeatureMediaFragment +type FeatureProps = RowProductFragment & + ProductFeatureMediaFragment & { productListItemRenderer: ProductListItemRenderer } export function Feature(props: FeatureProps) { const { productCopy, title, media_gallery } = props diff --git a/packages/hygraph-ui/components/RowProduct/variant/FeatureBoxed.tsx b/packages/hygraph-ui/components/RowProduct/variant/FeatureBoxed.tsx index 040a8f5c71a..ee616ecb67b 100644 --- a/packages/hygraph-ui/components/RowProduct/variant/FeatureBoxed.tsx +++ b/packages/hygraph-ui/components/RowProduct/variant/FeatureBoxed.tsx @@ -4,8 +4,10 @@ import { Typography, useTheme } from '@mui/material' import { RowProductFragment } from '../RowProduct.gql' import { ProductFeatureMediaBoxedFragment } from './ProductFeatureMediaBoxed.gql' import { RichText } from '../../RichText' +import { ProductListItemRenderer } from '@graphcommerce/magento-product' -type FeatureBoxedProps = RowProductFragment & ProductFeatureMediaBoxedFragment +type FeatureBoxedProps = RowProductFragment & + ProductFeatureMediaBoxedFragment & { productListItemRenderer: ProductListItemRenderer } export function FeatureBoxed(props: FeatureBoxedProps) { const { productCopy, title, media_gallery } = props diff --git a/packages/hygraph-ui/components/RowProduct/variant/Grid.tsx b/packages/hygraph-ui/components/RowProduct/variant/Grid.tsx index 6e349fff4e4..b5acd330330 100644 --- a/packages/hygraph-ui/components/RowProduct/variant/Grid.tsx +++ b/packages/hygraph-ui/components/RowProduct/variant/Grid.tsx @@ -1,13 +1,17 @@ -import { ProductItemsGridProps, ProductListItemsBase } from '@graphcommerce/magento-product' +import { + ProductItemsGridProps, + ProductListItemRenderer, + ProductListItemsBase, +} from '@graphcommerce/magento-product' import { ContainerWithHeader } from '@graphcommerce/next-ui' import { Link } from '@mui/material' import { RowProductFragment } from '../RowProduct.gql' -import { productListRenderer } from '../../../../../examples/magento-graphcms/components/ProductListItems/productListRenderer' -type GridProps = RowProductFragment & Omit +type GridProps = RowProductFragment & + Omit & { productListItemRenderer: ProductListItemRenderer } export function Grid(props: GridProps) { - const { title, pageLinks, productCopy, ...productListItems } = props + const { title, pageLinks, productCopy, productListItemRenderer, ...productListItems } = props return ( +type RelatedProps = RowProductFragment & + RelatedProductsFragment & + Pick & { productListItemRenderer: ProductListItemRenderer } export function Related(props: RelatedProps) { - const { title, related_products, sx } = props + const { title, related_products, productListItemRenderer, sx } = props if (!related_products || related_products.length === 0) return null @@ -22,7 +28,7 @@ export function Related(props: RelatedProps) { item ? ( +type ReviewsProps = RowProductFragment & + Partial & { productListItemRenderer: ProductListItemRenderer } export function Reviews(props: ReviewsProps) { const { title, reviews, url_key, review_count, sku } = props diff --git a/packages/hygraph-ui/components/RowProduct/variant/Specs.tsx b/packages/hygraph-ui/components/RowProduct/variant/Specs.tsx index dce125cd2b5..210e815dfac 100644 --- a/packages/hygraph-ui/components/RowProduct/variant/Specs.tsx +++ b/packages/hygraph-ui/components/RowProduct/variant/Specs.tsx @@ -1,8 +1,9 @@ -import { ProductSpecs } from '@graphcommerce/magento-product' +import { ProductListItemRenderer, ProductSpecs } from '@graphcommerce/magento-product' import { ProductSpecsFragment } from '@graphcommerce/magento-product/components/ProductSpecs/ProductSpecs.gql' import { RowProductFragment } from '../RowProduct.gql' -type SpecsProps = RowProductFragment & ProductSpecsFragment +type SpecsProps = RowProductFragment & + ProductSpecsFragment & { productListItemRenderer: ProductListItemRenderer } export function Specs(props: SpecsProps) { const { title, aggregations } = props diff --git a/packages/hygraph-ui/components/RowProduct/variant/Swipeable.tsx b/packages/hygraph-ui/components/RowProduct/variant/Swipeable.tsx index c0a8f9ba287..4e3a89e11c3 100644 --- a/packages/hygraph-ui/components/RowProduct/variant/Swipeable.tsx +++ b/packages/hygraph-ui/components/RowProduct/variant/Swipeable.tsx @@ -1,4 +1,8 @@ -import { AddProductsToCartForm, ProductListItemsFragment } from '@graphcommerce/magento-product' +import { + AddProductsToCartForm, + ProductListItemRenderer, + ProductListItemsFragment, +} from '@graphcommerce/magento-product' import { RenderType, responsiveVal, @@ -8,10 +12,12 @@ import { import { Typography } from '@mui/material' import { RowProductFragment } from '../RowProduct.gql' -type SwipeableProps = RowProductFragment & ProductListItemsFragment & Pick +type SwipeableProps = RowProductFragment & + ProductListItemsFragment & + Pick & { productListItemRenderer: ProductListItemRenderer } export function Swipeable(props: SwipeableProps) { - const { title, items, sx = [] } = props + const { title, items, productListItemRenderer, sx = [] } = props if (!items || items.length === 0) return null @@ -36,7 +42,7 @@ export function Swipeable(props: SwipeableProps) { item ? ( +type UpsellsProps = RowProductFragment & + UpsellProductsFragment & + Pick & { productListItemRenderer: ProductListItemRenderer } export function Upsells(props: UpsellsProps) { - const { title, upsell_products, sx } = props + const { title, upsell_products, productListItemRenderer, sx } = props if (!upsell_products || upsell_products.length === 0) return null @@ -22,7 +28,7 @@ export function Upsells(props: UpsellsProps) { item ? ( React.ReactElement } = export type PageProps = RowRendererFragment & { renderer?: Partial loadingEager?: number + productListItemRenderer?: ProductListItemRenderer } export function RowRenderer(props: PageProps) { - const { content, renderer, loadingEager = 2 } = props + const { content, renderer, productListItemRenderer, loadingEager = 2 } = props const mergedRenderer = { ...defaultRenderer, ...renderer } as ContentTypeRenderer return ( <> {content?.map((item, index) => ( - + {item.__typename === 'RowProduct' && ( + + )} + {item.__typename !== 'RowProduct' && } ))} diff --git a/packages/hygraph-ui/plugins/HygraphContentArea.tsx b/packages/hygraph-ui/plugins/HygraphContentArea.tsx index 36b3f065e49..e30865c53f1 100644 --- a/packages/hygraph-ui/plugins/HygraphContentArea.tsx +++ b/packages/hygraph-ui/plugins/HygraphContentArea.tsx @@ -7,12 +7,18 @@ export const exported = '@graphcommerce/content-areas/components/ContentArea/Con const HygraphContentArea: ReactPlugin = (props) => { const { Prev, ...rest } = props - const { content, renderer } = props + const { content, renderer, productListRenderer } = props return ( <> - {content.hygraphPage && } + {content.hygraphPage && ( + + )} ) } From 197389a6892699e1922608e2e714f011ce2af711 Mon Sep 17 00:00:00 2001 From: Paul Hachmang Date: Fri, 26 Jan 2024 10:22:45 +0100 Subject: [PATCH 10/33] Proof of concept for universal renderer for rows --- examples/magento-graphcms/pages/index.tsx | 82 ++++------ graphql.config.js | 1 + packages/cli/dist/bin/mesh.js | 14 ++ packages/cli/src/bin/mesh.ts | 18 ++- .../components/ContentArea/ContentArea.tsx | 5 +- packages/content-areas/index.ts | 6 +- .../queries/UniversalPage.graphql | 5 + .../queries/UniversalPage_Data.graphql | 7 + packages/content-areas/schema.graphqls | 24 +++ packages/content-areas/server/jsonifyMeta.ts | 57 ------- packages/content-areas/server/pageContent.ts | 13 -- .../content-areas/server/resolveMetadata.ts | 151 ------------------ packages/content-areas/types.ts | 25 --- packages/graphql-mesh/directive/mesh.graphqls | 16 ++ .../dist/migrations/graphcommerce7to8.js | 96 +++++------ .../components/RowProduct/RowProduct.graphql | 11 ++ .../components/RowProduct/RowProduct.tsx | 4 +- .../RowProduct/variant/Backstory.tsx | 15 +- .../components/RowProduct/variant/Feature.tsx | 3 +- .../components/RowProduct/variant/Grid.tsx | 13 +- .../RowProduct/variant/Swipeable.tsx | 33 ++-- .../graphql/UniversalPage_Hygraph.graphql | 5 + packages/hygraph-ui/mesh.ts | 58 +++++++ .../hygraph-ui/plugins/HygraphContentArea.tsx | 8 +- .../plugins/hygraphPageContentPlugin.ts | 41 ----- packages/hygraph-ui/schema.graphqls | 21 +++ 26 files changed, 288 insertions(+), 444 deletions(-) create mode 100644 packages/content-areas/queries/UniversalPage.graphql create mode 100644 packages/content-areas/queries/UniversalPage_Data.graphql create mode 100644 packages/content-areas/schema.graphqls delete mode 100644 packages/content-areas/server/jsonifyMeta.ts delete mode 100644 packages/content-areas/server/pageContent.ts delete mode 100644 packages/content-areas/server/resolveMetadata.ts delete mode 100644 packages/content-areas/types.ts create mode 100644 packages/graphql-mesh/directive/mesh.graphqls create mode 100644 packages/hygraph-ui/graphql/UniversalPage_Hygraph.graphql create mode 100644 packages/hygraph-ui/mesh.ts delete mode 100644 packages/hygraph-ui/plugins/hygraphPageContentPlugin.ts create mode 100644 packages/hygraph-ui/schema.graphqls diff --git a/examples/magento-graphcms/pages/index.tsx b/examples/magento-graphcms/pages/index.tsx index 9477d7792aa..98df2e171f8 100644 --- a/examples/magento-graphcms/pages/index.tsx +++ b/examples/magento-graphcms/pages/index.tsx @@ -1,4 +1,9 @@ -import { ContentAreaHome, PageContent, pageContent } from '@graphcommerce/content-areas' +import { + ContentAreaHome, + PageContent, + UniversalPageDocument, + UniversalPageQuery, +} from '@graphcommerce/content-areas' import { PageOptions } from '@graphcommerce/framer-next-pages' import { RowProduct } from '@graphcommerce/graphcms-ui' import { ProductListDocument, ProductListQuery } from '@graphcommerce/magento-product' @@ -16,13 +21,13 @@ type Props = { latestList: ProductListQuery favoritesList: ProductListQuery swipableList: ProductListQuery - content: PageContent -} +} & UniversalPageQuery + type RouteProps = { url: string } type GetPageStaticProps = GetStaticProps function CmsPage(props: Props) { - const { content, latestList, favoritesList, swipableList } = props + const { pageContent, latestList, favoritesList, swipableList } = props const latest = latestList?.products?.items?.[0] const favorite = favoritesList?.products?.items?.[0] @@ -30,54 +35,29 @@ function CmsPage(props: Props) { return ( <> - + {/* */} { - const { identity } = rowProps - - if (identity === 'home-favorites') - return ( - - ) - if (identity === 'home-latest') - return - if (identity === 'home-swipable') - return - return - }, - }} + // renderer={{ + // RowProduct: (rowProps) => { + // const { identity } = rowProps + + // if (identity === 'home-favorites') + // return ( + // + // ) + // if (identity === 'home-latest') + // return + // if (identity === 'home-swipable') + // return + // return + // }, + // }} /> - - {/* {page && ( - { - const { identity } = rowProps - - if (identity === 'home-favorites') - return ( - - ) - if (identity === 'home-latest') - return - if (identity === 'home-swipable') - return ( - - ) - return ( - - ) - }, - }} - /> - )} */} ) } @@ -93,7 +73,11 @@ export const getStaticProps: GetPageStaticProps = async ({ locale }) => { const staticClient = graphqlSsrClient(locale) const conf = client.query({ query: StoreConfigDocument }) - const content = pageContent(staticClient, 'page/home') + const page = client.query({ + query: UniversalPageDocument, + variables: { input: { url: 'page/home' } }, + }) + const layout = staticClient.query({ query: LayoutDocument, fetchPolicy: 'cache-first' }) // todo(paales): Remove when https://github.com/Urigo/graphql-mesh/issues/1257 is resolved @@ -112,11 +96,11 @@ export const getStaticProps: GetPageStaticProps = async ({ locale }) => { variables: { pageSize: 8, filters: { category_uid: { eq: 'MTIy' } } }, }) - if ((await content).notFound) return { notFound: true } + if (!(await page).data) return { notFound: true } return { props: { - content: await content, + ...(await page).data, ...(await layout).data, latestList: (await latestList).data, favoritesList: (await favoritesList).data, diff --git a/graphql.config.js b/graphql.config.js index e6ca6613a7f..454dd12443d 100644 --- a/graphql.config.js +++ b/graphql.config.js @@ -17,6 +17,7 @@ module.exports = { 'packages/graphql/apollo-client.graphql', 'packagesDev/graphql-codegen-near-operation-file/src/directive/env.graphqls', 'packagesDev/graphql-codegen-near-operation-file/src/directive/injectable.graphqls', + 'packages/graphql-mesh/directive/mesh.graphqls', ], documents: [ 'examples/magento-graphcms/components/**/*.graphql', diff --git a/packages/cli/dist/bin/mesh.js b/packages/cli/dist/bin/mesh.js index c20dc5761d8..c5a50230e22 100755 --- a/packages/cli/dist/bin/mesh.js +++ b/packages/cli/dist/bin/mesh.js @@ -70,11 +70,25 @@ const main = async () => { }); // Scan the current working directory to also read all graphqls files. conf.additionalTypeDefs.push('**/*.graphqls'); + conf.additionalResolvers = []; + // conf.additionalResolvers.push('**/resolvers/**/*.ts') const deps = (0, next_config_1.resolveDependenciesSync)(); const packages = [...deps.values()].filter((p) => p !== '.'); (0, next_config_1.packageRoots)(packages).forEach((r) => { conf.additionalTypeDefs.push(`${r}/**/*.graphqls`); }); + const meshScan = [...deps.values()].map(async (r) => { + const resolver = `${r}/mesh.ts`; + const hasResolver = await node_fs_1.promises + .stat(resolver) + .then(() => true) + .catch(() => false); + if (!conf.additionalResolvers) + conf.additionalResolvers = []; + if (hasResolver) + conf.additionalResolvers.push(resolver); + }); + await Promise.all(meshScan); if (!conf.serve) conf.serve = {}; if (!conf.serve.playgroundTitle) diff --git a/packages/cli/src/bin/mesh.ts b/packages/cli/src/bin/mesh.ts index af4d2faf670..5807b46d80f 100755 --- a/packages/cli/src/bin/mesh.ts +++ b/packages/cli/src/bin/mesh.ts @@ -4,7 +4,6 @@ import { promises as fs } from 'node:fs' import path from 'node:path' import { exit } from 'node:process' import { - isMonorepo, loadConfig, packageRoots, replaceConfigInString, @@ -81,12 +80,29 @@ const main = async () => { // Scan the current working directory to also read all graphqls files. conf.additionalTypeDefs.push('**/*.graphqls') + conf.additionalResolvers = [] + + // conf.additionalResolvers.push('**/resolvers/**/*.ts') + const deps = resolveDependenciesSync() const packages = [...deps.values()].filter((p) => p !== '.') packageRoots(packages).forEach((r) => { conf.additionalTypeDefs.push(`${r}/**/*.graphqls`) }) + const meshScan = [...deps.values()].map(async (r) => { + const resolver = `${r}/mesh.ts` + + const hasResolver = await fs + .stat(resolver) + .then(() => true) + .catch(() => false) + + if (!conf.additionalResolvers) conf.additionalResolvers = [] + if (hasResolver) conf.additionalResolvers.push(resolver) + }) + await Promise.all(meshScan) + if (!conf.serve) conf.serve = {} if (!conf.serve.playgroundTitle) conf.serve.playgroundTitle = 'GraphCommerce® Mesh' diff --git a/packages/content-areas/components/ContentArea/ContentArea.tsx b/packages/content-areas/components/ContentArea/ContentArea.tsx index 383214ec07b..f8c0909bcd7 100644 --- a/packages/content-areas/components/ContentArea/ContentArea.tsx +++ b/packages/content-areas/components/ContentArea/ContentArea.tsx @@ -1,8 +1,7 @@ import { ProductListItemRenderer } from '@graphcommerce/magento-product' -import { PageContent } from '../../types' +import { UniversalPageQuery } from '../../queries/UniversalPage.gql' -export interface ContentAreaProps { - content: PageContent +type ContentAreaProps = UniversalPageQuery & { productListRenderer: ProductListItemRenderer } diff --git a/packages/content-areas/index.ts b/packages/content-areas/index.ts index 5aaef4e9a00..abaf242e687 100644 --- a/packages/content-areas/index.ts +++ b/packages/content-areas/index.ts @@ -1,4 +1,4 @@ export * from './components' -export * from './server/pageContent' -export * from './types' -export * from './server/resolveMetadata' +// export * from './server/resolveMetadata' +export * from './queries/UniversalPage.gql' +export * from './queries/UniversalPage_Data.gql' diff --git a/packages/content-areas/queries/UniversalPage.graphql b/packages/content-areas/queries/UniversalPage.graphql new file mode 100644 index 00000000000..8f6b39c733e --- /dev/null +++ b/packages/content-areas/queries/UniversalPage.graphql @@ -0,0 +1,5 @@ +query UniversalPage($input: UniversalPageInput!) { + pageContent(input: $input) { + ...UniversalPage_Data + } +} diff --git a/packages/content-areas/queries/UniversalPage_Data.graphql b/packages/content-areas/queries/UniversalPage_Data.graphql new file mode 100644 index 00000000000..234f0ced482 --- /dev/null +++ b/packages/content-areas/queries/UniversalPage_Data.graphql @@ -0,0 +1,7 @@ +fragment UniversalPage_Data on UniversalPage @injectable { + title + meta { + title + description + } +} diff --git a/packages/content-areas/schema.graphqls b/packages/content-areas/schema.graphqls new file mode 100644 index 00000000000..fd65a4e92e7 --- /dev/null +++ b/packages/content-areas/schema.graphqls @@ -0,0 +1,24 @@ +type UniversalMeta { + """ + Meta title + """ + title: String + + """ + A description of the product for usage in search engine results. + """ + description: String +} + +type UniversalPage { + title: String + meta: UniversalMeta +} + +input UniversalPageInput { + url: String! +} + +extend type Query { + pageContent(input: UniversalPageInput!): UniversalPage +} diff --git a/packages/content-areas/server/jsonifyMeta.ts b/packages/content-areas/server/jsonifyMeta.ts deleted file mode 100644 index 09f2650e8de..00000000000 --- a/packages/content-areas/server/jsonifyMeta.ts +++ /dev/null @@ -1,57 +0,0 @@ -import { ResolvedMetadata } from 'next' -import { AlternateLinkDescriptor } from 'next/dist/lib/metadata/types/alternative-urls-types' -import type { Jsonify } from 'type-fest' - -function alternateLinkDescriptorToJSON( - link: AlternateLinkDescriptor | null | undefined, -): Jsonify | null { - if (!link) return null - return { - ...link, - url: link.url.toString(), - } -} - -export function resolvedMetadataToJSON(metadata: ResolvedMetadata): Jsonify { - return { - ...metadata, - metadataBase: metadata.metadataBase?.toString() ?? null, - authors: - metadata.authors?.map((author) => ({ - ...author, - url: author.url?.toString(), - })) ?? null, - alternates: { - ...metadata.alternates, - canonical: alternateLinkDescriptorToJSON(metadata.alternates?.canonical), - languages: Object.fromEntries( - Object.entries(metadata.alternates?.languages ?? {}).map(([key, val]) => [ - key, - val?.map(alternateLinkDescriptorToJSON), - ]), - ) as Jsonify['languages']>, - - media: Object.fromEntries( - Object.entries(metadata.alternates?.media ?? {}).map(([key, val]) => [ - key, - val?.map(alternateLinkDescriptorToJSON), - ]), - ) as Jsonify['media']>, - - types: Object.fromEntries( - Object.entries(metadata.alternates?.types ?? {}).map(([key, val]) => [ - key, - val?.map(alternateLinkDescriptorToJSON), - ]), - ) as Jsonify['types']>, - }, - - icons: { - ...metadata.icons, - apple: (metadata.icons?.apple ?? [])?.map((icon) => ({ - ...icon, - url: icon.url?.toString(), - })), - }, - } -} diff --git a/packages/content-areas/server/pageContent.ts b/packages/content-areas/server/pageContent.ts deleted file mode 100644 index 7dd1095955e..00000000000 --- a/packages/content-areas/server/pageContent.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { ApolloClient, NormalizedCacheObject } from '@graphcommerce/graphql' -import { PageContent } from '../types' - -export function pageContent( - client: ApolloClient, - url: string, - additionalProperties?: Promise | object, - cached = false, -): Promise { - return Promise.resolve({ - metadata: null, - }) -} diff --git a/packages/content-areas/server/resolveMetadata.ts b/packages/content-areas/server/resolveMetadata.ts deleted file mode 100644 index c1d08739f15..00000000000 --- a/packages/content-areas/server/resolveMetadata.ts +++ /dev/null @@ -1,151 +0,0 @@ -/* eslint-disable guard-for-in */ -/* eslint-disable no-restricted-syntax */ -import { createDefaultMetadata } from 'next/dist/lib/metadata/default-metadata' -import { resolveAsArrayOrUndefined } from 'next/dist/lib/metadata/generate/utils' -import { - resolveAlternates, - resolveAppleWebApp, - resolveAppLinks, - resolveRobots, - resolveVerification, - resolveItunes, -} from 'next/dist/lib/metadata/resolvers/resolve-basics' -import { resolveIcons } from 'next/dist/lib/metadata/resolvers/resolve-icons' -import { - resolveOpenGraph, - resolveTwitter, -} from 'next/dist/lib/metadata/resolvers/resolve-opengraph' -import { resolveTitle } from 'next/dist/lib/metadata/resolvers/resolve-title' -import type { - Metadata, - ResolvedMetadata, - ResolvingMetadata, - ResolvingViewport, - Viewport, -} from 'next/dist/lib/metadata/types/metadata-interface' -import type { MetadataContext } from 'next/dist/lib/metadata/types/resolvers' -import { ReducedMetadata, ReducedResolvedMetadata } from '../types' - -type MetadataResolver = (parent: ResolvingMetadata) => Metadata | Promise -type ViewportResolver = (parent: ResolvingViewport) => Viewport | Promise - -export type MetadataItems = [ - Metadata | MetadataResolver | null, - Viewport | ViewportResolver | null, -][] - -type TitleTemplates = { - title: string | null - twitter: string | null - openGraph: string | null -} - -export type BuildState = { - warnings: Set -} - -// Merge the source metadata into the resolved target metadata. -export function resolveMetadata( - source: ReducedMetadata | null, - { - titleTemplates, - metadataContext, - }: { - titleTemplates: TitleTemplates - metadataContext: MetadataContext - } = { - metadataContext: { pathname: '/' }, - titleTemplates: { openGraph: null, title: null, twitter: null }, - }, -): ReducedResolvedMetadata { - const target: ResolvedMetadata = createDefaultMetadata() - // If there's override metadata, prefer it otherwise fallback to the default metadata. - const metadataBase = - typeof source?.metadataBase !== 'undefined' ? source.metadataBase : target.metadataBase - for (const key_ in source) { - const key = key_ as keyof ReducedMetadata - - switch (key) { - case 'title': { - target.title = resolveTitle(source.title, titleTemplates.title) - break - } - case 'alternates': { - target.alternates = resolveAlternates(source.alternates, metadataBase, metadataContext) - break - } - case 'openGraph': { - target.openGraph = resolveOpenGraph( - source.openGraph, - metadataBase, - metadataContext, - titleTemplates.openGraph, - ) - break - } - case 'twitter': { - target.twitter = resolveTwitter(source.twitter, metadataBase, titleTemplates.twitter) - break - } - case 'verification': - target.verification = resolveVerification(source.verification) - break - - case 'icons': { - target.icons = resolveIcons(source.icons) - break - } - case 'appleWebApp': - target.appleWebApp = resolveAppleWebApp(source.appleWebApp) - break - case 'appLinks': - target.appLinks = resolveAppLinks(source.appLinks) - break - case 'robots': { - target.robots = resolveRobots(source.robots) - break - } - case 'archives': - case 'assets': - case 'bookmarks': - case 'keywords': { - target[key] = resolveAsArrayOrUndefined(source[key]) - break - } - case 'authors': { - target[key] = resolveAsArrayOrUndefined(source.authors) - break - } - case 'itunes': { - target[key] = resolveItunes(source.itunes, metadataBase, metadataContext) - break - } - // directly assign fields that fallback to null - case 'applicationName': - case 'description': - case 'generator': - case 'creator': - case 'publisher': - case 'category': - case 'classification': - case 'referrer': - case 'formatDetection': - case 'manifest': - // @ts-expect-error TODO: support inferring - target[key] = source[key] || null - break - case 'other': - target.other = { ...target.other, ...source.other } - break - case 'metadataBase': - target.metadataBase = metadataBase - break - - default: { - break - } - } - } - - return target -} diff --git a/packages/content-areas/types.ts b/packages/content-areas/types.ts deleted file mode 100644 index 225796d1aa9..00000000000 --- a/packages/content-areas/types.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { Metadata, ResolvedMetadata } from 'next' - -export type ReducedMetadata = Omit< - Metadata, - | 'viewport' - | 'themeColor' - | 'colorScheme' - | 'apple-touch-fullscreen' - | 'apple-touch-icon-precomposed' -> - -export type ReducedResolvedMetadata = Omit< - ResolvedMetadata, - | 'viewport' - | 'themeColor' - | 'colorScheme' - | 'apple-touch-fullscreen' - | 'apple-touch-icon-precomposed' -> - -export interface PageContent { - notFound?: boolean - title?: string - metadata: ResolvedMetadata | null -} diff --git a/packages/graphql-mesh/directive/mesh.graphqls b/packages/graphql-mesh/directive/mesh.graphqls new file mode 100644 index 00000000000..a934c9d07ae --- /dev/null +++ b/packages/graphql-mesh/directive/mesh.graphqls @@ -0,0 +1,16 @@ +scalar ResolveToSourceArgs +directive @resolveTo( + requiredSelectionSet: String + sourceName: String! + sourceTypeName: String! + sourceFieldName: String! + sourceSelectionSet: String + sourceArgs: ResolveToSourceArgs + keyField: String + keysArg: String + pubsubTopic: String + filterBy: String + additionalArgs: ResolveToSourceArgs + result: String + resultType: String +) on FIELD_DEFINITION diff --git a/packages/hygraph-cli/dist/migrations/graphcommerce7to8.js b/packages/hygraph-cli/dist/migrations/graphcommerce7to8.js index ee78731e8b0..adbe81a0058 100644 --- a/packages/hygraph-cli/dist/migrations/graphcommerce7to8.js +++ b/packages/hygraph-cli/dist/migrations/graphcommerce7to8.js @@ -1,57 +1,43 @@ -'use strict' -Object.defineProperty(exports, '__esModule', { value: true }) -exports.graphcommerce7to8 = void 0 -const management_sdk_1 = require('@hygraph/management-sdk') -const migrationAction_1 = require('../migrationAction') +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.graphcommerce7to8 = void 0; +const management_sdk_1 = require("@hygraph/management-sdk"); +const migrationAction_1 = require("../migrationAction"); const graphcommerce7to8 = async (schema) => { - if (!migrationAction_1.client) { - return 0 - } - const hasRow = schema.models - .find((m) => m.apiId === 'DynamicRow') - ?.fields.some((f) => f.apiId === 'row') - if (hasRow) { - ;(0, migrationAction_1.migrationAction)(schema, 'unionField', 'update', { - apiId: 'row', - displayName: 'Row Deprecated', - parentApiId: 'DynamicRow', - description: 'This field is deprecated. Use Rows instead.', - }) - } - ;(0, migrationAction_1.migrationAction)( - schema, - 'unionField', - 'create', - { - displayName: 'Rows', - apiId: 'rows', - isList: true, - reverseField: { - modelApiIds: ['RowQuote', 'RowLinks', 'RowColumnOne'], - apiId: 'dynamicRows', - displayName: 'Dynamic Rows', - visibility: management_sdk_1.VisibilityTypes.Hidden, + if (!migrationAction_1.client) { + return 0; + } + const hasRow = schema.models + .find((m) => m.apiId === 'DynamicRow') + ?.fields.some((f) => f.apiId === 'row'); + if (hasRow) { + (0, migrationAction_1.migrationAction)(schema, 'unionField', 'update', { + apiId: 'row', + displayName: 'Row Deprecated', + parentApiId: 'DynamicRow', + description: 'This field is deprecated. Use Rows instead.', + }); + } + (0, migrationAction_1.migrationAction)(schema, 'unionField', 'create', { + displayName: 'Rows', + apiId: 'rows', isList: true, - }, - parentApiId: 'DynamicRow', - }, - 'DynamicRow', - 'model', - ) - ;(0, migrationAction_1.migrationAction)( - schema, - 'componentUnionField', - 'create', - { - displayName: 'Conditions', - apiId: 'conditions', - parentApiId: 'ConditionOr', - componentApiIds: ['ConditionText', 'ConditionNumber'], - isList: true, - }, - 'ConditionOr', - 'component', - ) - return migrationAction_1.client.run(true) -} -exports.graphcommerce7to8 = graphcommerce7to8 + reverseField: { + modelApiIds: ['RowQuote', 'RowLinks', 'RowColumnOne'], + apiId: 'dynamicRows', + displayName: 'Dynamic Rows', + visibility: management_sdk_1.VisibilityTypes.Hidden, + isList: true, + }, + parentApiId: 'DynamicRow', + }, 'DynamicRow', 'model'); + (0, migrationAction_1.migrationAction)(schema, 'componentUnionField', 'create', { + displayName: 'Conditions', + apiId: 'conditions', + parentApiId: 'ConditionOr', + componentApiIds: ['ConditionText', 'ConditionNumber'], + isList: true, + }, 'ConditionOr', 'component'); + return migrationAction_1.client.run(true); +}; +exports.graphcommerce7to8 = graphcommerce7to8; diff --git a/packages/hygraph-ui/components/RowProduct/RowProduct.graphql b/packages/hygraph-ui/components/RowProduct/RowProduct.graphql index 89eddd5f446..bca10ed90cb 100644 --- a/packages/hygraph-ui/components/RowProduct/RowProduct.graphql +++ b/packages/hygraph-ui/components/RowProduct/RowProduct.graphql @@ -11,4 +11,15 @@ fragment RowProduct on RowProduct { pageLinks { ...PageLink } + + category { + uid + products { + items { + __typename + uid + ...ProductListItem + } + } + } } diff --git a/packages/hygraph-ui/components/RowProduct/RowProduct.tsx b/packages/hygraph-ui/components/RowProduct/RowProduct.tsx index e5bd75d331f..38a9c795eeb 100644 --- a/packages/hygraph-ui/components/RowProduct/RowProduct.tsx +++ b/packages/hygraph-ui/components/RowProduct/RowProduct.tsx @@ -15,13 +15,13 @@ import { type VariantRenderer = Record< NonNullable, - React.VFC + React.FC > type RowProductProps = RowProductFragment & { renderer?: Partial productListItemRenderer: ProductListItemRenderer -} & ProductSpecsFragment & { items?: unknown } & { sku?: string | null | undefined } +} & ProductSpecsFragment & { sku?: string | null | undefined } const defaultRenderer: Partial = { Specs, diff --git a/packages/hygraph-ui/components/RowProduct/variant/Backstory.tsx b/packages/hygraph-ui/components/RowProduct/variant/Backstory.tsx index 9c20caf2f99..331f4bd298a 100644 --- a/packages/hygraph-ui/components/RowProduct/variant/Backstory.tsx +++ b/packages/hygraph-ui/components/RowProduct/variant/Backstory.tsx @@ -1,21 +1,16 @@ -import { - AddProductsToCartForm, - ProductListItemRenderer, - ProductListItemsFragment, -} from '@graphcommerce/magento-product' +import { AddProductsToCartForm, ProductListItemRenderer } from '@graphcommerce/magento-product' import { ParagraphWithSidebarSlide, RenderType } from '@graphcommerce/next-ui' import { useTheme } from '@mui/material' import { Asset } from '../../Asset/Asset' -import { RowProductFragment } from '../RowProduct.gql' import { RichText } from '../../RichText' +import { RowProductFragment } from '../RowProduct.gql' -type BackstoryProps = RowProductFragment & - ProductListItemsFragment & { productListItemRenderer: ProductListItemRenderer } +type BackstoryProps = RowProductFragment & { productListItemRenderer: ProductListItemRenderer } export function Backstory(props: BackstoryProps) { - const { productCopy, asset, productListItemRenderer, ...productListItems } = props + const { productCopy, asset, category, productListItemRenderer } = props const theme = useTheme() - const singleItem = productListItems?.items?.[(productListItems.items?.length ?? 1) - 1] + const singleItem = category?.products?.items?.[(category?.products?.items?.length ?? 1) - 1] if (!singleItem) return null diff --git a/packages/hygraph-ui/components/RowProduct/variant/Feature.tsx b/packages/hygraph-ui/components/RowProduct/variant/Feature.tsx index 08aacdf09a7..3dd55fc845e 100644 --- a/packages/hygraph-ui/components/RowProduct/variant/Feature.tsx +++ b/packages/hygraph-ui/components/RowProduct/variant/Feature.tsx @@ -6,8 +6,7 @@ import { ProductFeatureMediaFragment } from './ProductFeatureMedia.gql' import { RichText } from '../../RichText' import { ProductListItemRenderer } from '@graphcommerce/magento-product' -type FeatureProps = RowProductFragment & - ProductFeatureMediaFragment & { productListItemRenderer: ProductListItemRenderer } +type FeatureProps = RowProductFragment & { productListItemRenderer: ProductListItemRenderer } export function Feature(props: FeatureProps) { const { productCopy, title, media_gallery } = props diff --git a/packages/hygraph-ui/components/RowProduct/variant/Grid.tsx b/packages/hygraph-ui/components/RowProduct/variant/Grid.tsx index b5acd330330..8f62a5a0d1c 100644 --- a/packages/hygraph-ui/components/RowProduct/variant/Grid.tsx +++ b/packages/hygraph-ui/components/RowProduct/variant/Grid.tsx @@ -1,17 +1,12 @@ -import { - ProductItemsGridProps, - ProductListItemRenderer, - ProductListItemsBase, -} from '@graphcommerce/magento-product' +import { ProductListItemRenderer, ProductListItemsBase } from '@graphcommerce/magento-product' import { ContainerWithHeader } from '@graphcommerce/next-ui' import { Link } from '@mui/material' import { RowProductFragment } from '../RowProduct.gql' -type GridProps = RowProductFragment & - Omit & { productListItemRenderer: ProductListItemRenderer } +type GridProps = RowProductFragment & { productListItemRenderer: ProductListItemRenderer } export function Grid(props: GridProps) { - const { title, pageLinks, productCopy, productListItemRenderer, ...productListItems } = props + const { title, pageLinks, productListItemRenderer, category } = props return ( diff --git a/packages/hygraph-ui/components/RowProduct/variant/Swipeable.tsx b/packages/hygraph-ui/components/RowProduct/variant/Swipeable.tsx index 4e3a89e11c3..0a00b05f1d8 100644 --- a/packages/hygraph-ui/components/RowProduct/variant/Swipeable.tsx +++ b/packages/hygraph-ui/components/RowProduct/variant/Swipeable.tsx @@ -1,9 +1,6 @@ +import { AddProductsToCartForm, ProductListItemRenderer } from '@graphcommerce/magento-product' import { - AddProductsToCartForm, - ProductListItemRenderer, - ProductListItemsFragment, -} from '@graphcommerce/magento-product' -import { + filterNonNullableKeys, RenderType, responsiveVal, SidebarSlider, @@ -13,13 +10,13 @@ import { Typography } from '@mui/material' import { RowProductFragment } from '../RowProduct.gql' type SwipeableProps = RowProductFragment & - ProductListItemsFragment & Pick & { productListItemRenderer: ProductListItemRenderer } export function Swipeable(props: SwipeableProps) { - const { title, items, productListItemRenderer, sx = [] } = props + const { title, category, productListItemRenderer, sx = [] } = props - if (!items || items.length === 0) return null + const items = filterNonNullableKeys(category?.products?.items) + if (items.length === 0) return null return ( @@ -38,17 +35,15 @@ export function Swipeable(props: SwipeableProps) { } > - {items?.map((item) => - item ? ( - - ) : null, - )} + {items.map((item) => ( + + ))} ) diff --git a/packages/hygraph-ui/graphql/UniversalPage_Hygraph.graphql b/packages/hygraph-ui/graphql/UniversalPage_Hygraph.graphql new file mode 100644 index 00000000000..12b654a846c --- /dev/null +++ b/packages/hygraph-ui/graphql/UniversalPage_Hygraph.graphql @@ -0,0 +1,5 @@ +fragment UniversalPage_Hygraph on UniversalPage @inject(into: ["UniversalPage_Data"]) { + hygraphPage { + ...HygraphPage + } +} diff --git a/packages/hygraph-ui/mesh.ts b/packages/hygraph-ui/mesh.ts new file mode 100644 index 00000000000..563b0d765da --- /dev/null +++ b/packages/hygraph-ui/mesh.ts @@ -0,0 +1,58 @@ +/* eslint-disable import/no-extraneous-dependencies */ +import type { Resolvers } from '@graphcommerce/graphql-mesh' +import { parseSelectionSet } from '@graphql-tools/utils' +import { Kind, FieldNode, SelectionSetNode } from 'graphql' + +function selectionSetFromPath(path: string[], selectionSet: SelectionSetNode) { + const [fieldName, ...rest] = path + + const selection = selectionSet.selections.find( + (s) => s.kind === Kind.FIELD && s.name.value === fieldName, + ) as FieldNode + + if (!selection.selectionSet) return undefined + if (rest.length === 0) return selection.selectionSet + + return selectionSetFromPath(rest, selection.selectionSet) +} + +function mergeSelectionSetNodes( + node1: SelectionSetNode | undefined, + node2: SelectionSetNode | undefined, +): SelectionSetNode { + const selections = [...(node1?.selections ?? []), ...(node2?.selections ?? [])] + + return { + kind: Kind.SELECTION_SET, + selections, + } +} + +export const resolvers: Resolvers = { + Query: { + pageContent: async (root, { input }, context, info) => { + const selectionSet = mergeSelectionSetNodes( + selectionSetFromPath(['pageContent', 'hygraphPage'], info.operation.selectionSet), + parseSelectionSet(`{ title metaTitle metaDescription }`, { noLocation: true }), + ) + + const pages = await context.hygraph.Query.pages({ + root, + args: { where: input }, + context, + info, + selectionSet, + }) + + const hygraphPage = pages?.[0] + if (!hygraphPage) return null + + const { title, metaTitle, metaDescription } = hygraphPage + return { + title, + meta: { title: metaTitle, description: metaDescription }, + hygraphPage, + } + }, + }, +} diff --git a/packages/hygraph-ui/plugins/HygraphContentArea.tsx b/packages/hygraph-ui/plugins/HygraphContentArea.tsx index e30865c53f1..067fc474be3 100644 --- a/packages/hygraph-ui/plugins/HygraphContentArea.tsx +++ b/packages/hygraph-ui/plugins/HygraphContentArea.tsx @@ -7,16 +7,16 @@ export const exported = '@graphcommerce/content-areas/components/ContentArea/Con const HygraphContentArea: ReactPlugin = (props) => { const { Prev, ...rest } = props - const { content, renderer, productListRenderer } = props + const { pageContent, renderer, productListRenderer } = props return ( <> - {content.hygraphPage && ( + {pageContent?.hygraphPage && ( )} diff --git a/packages/hygraph-ui/plugins/hygraphPageContentPlugin.ts b/packages/hygraph-ui/plugins/hygraphPageContentPlugin.ts deleted file mode 100644 index 8bba41406ed..00000000000 --- a/packages/hygraph-ui/plugins/hygraphPageContentPlugin.ts +++ /dev/null @@ -1,41 +0,0 @@ -import { resolveMetadata, type pageContent } from '@graphcommerce/content-areas' -import type { MethodPlugin } from '@graphcommerce/next-config' -import { hygraphPageContent } from '..' - -export const func = 'pageContent' -export const exported = '@graphcommerce/content-areas/server/pageContent' - -const hygraphPageContentPlugin: MethodPlugin = async ( - prev, - client, - url, - additionalProperties, - cached, -) => { - const [prevResults, content] = await Promise.all([ - prev(client, url, additionalProperties, cached), - hygraphPageContent(client, url, additionalProperties, cached), - ]) - - const page = content.data.pages?.[0] - - if (!page) return { ...prevResults, notFound: true } - - return { - ...prevResults, - metadata: resolveMetadata({ - metadataBase: new URL(import.meta.graphCommerce.canonicalBaseUrl), - title: page.title, - description: page.metaDescription, - robots: page.metaRobots - ? { - index: !page.metaRobots.includes('noindex'), - follow: !page.metaRobots.includes('nofollow'), - } - : { index: true, follow: true }, - }), - hygraphPage: page, - } -} - -export const plugin = hygraphPageContentPlugin diff --git a/packages/hygraph-ui/schema.graphqls b/packages/hygraph-ui/schema.graphqls new file mode 100644 index 00000000000..0f65f11109c --- /dev/null +++ b/packages/hygraph-ui/schema.graphqls @@ -0,0 +1,21 @@ +extend type UniversalPage { + hygraphPage: Page +} + +extend type RowProduct { + category: CategoryTree + @resolveTo( + sourceName: "m2" # Which source does the target field belong to? + sourceTypeName: "Query" # Which root type does the target field belong to? + sourceFieldName: "categories" # What is the source field name? + # Regular resolver + requiredSelectionSet: "{ identity }" + sourceArgs: { filters: { url_key: { eq: "{root.identity}" } } } + result: "items[0]" + + # Batching resolver (requires all values to resolve, so nothing will be returned if any of the values are missing) + # keyField: "identity" + # keysArg: "filters.url_key.in" + # result: "items" + ) +} From f538fbd277d2868864737c32ad2c6f7fc4b660cd Mon Sep 17 00:00:00 2001 From: Paul Hachmang Date: Sun, 28 Jan 2024 12:18:41 +0100 Subject: [PATCH 11/33] Further messing around with the new api --- examples/magento-graphcms/.meshrc.yml | 8 ++ examples/magento-graphcms/pages/index.tsx | 57 +-------- .../components/ContentArea/ContentArea.tsx | 2 +- packages/content-areas/schema.graphqls | 10 +- packages/graphql-mesh/package.json | 6 + packages/hygraph-ui/mesh.ts | 10 +- packages/hygraph-ui/schema.graphqls | 24 +++- packages/universal-schema/README.md | 8 ++ yarn.lock | 121 +++++++++++++++++- 9 files changed, 183 insertions(+), 63 deletions(-) create mode 100644 packages/universal-schema/README.md diff --git a/examples/magento-graphcms/.meshrc.yml b/examples/magento-graphcms/.meshrc.yml index 9bcb5646b4b..db0fcd7ac07 100644 --- a/examples/magento-graphcms/.meshrc.yml +++ b/examples/magento-graphcms/.meshrc.yml @@ -17,6 +17,14 @@ sources: - '*.*.!{after,before,last,forceParentLocale,locales}' # Remove type any input or type fields: `input MyInput {}` or `type MyType { anyfield }` - '*.!{localizations,scheduledIn,documentInStages*,createdAt*,updatedAt*,publishedAt*,createdBy,updatedBy,publishedBy,history,scheduledIn*}' + # - prefix: + # includeRootOperations: true + # includeTypes: false + # value: 'hygraph_' + # - prefix: + # includeRootOperations: false + # includeTypes: true + # value: 'Hygraph' - prune: skipPruning: [] - name: m2 diff --git a/examples/magento-graphcms/pages/index.tsx b/examples/magento-graphcms/pages/index.tsx index 98df2e171f8..6ab27caaa13 100644 --- a/examples/magento-graphcms/pages/index.tsx +++ b/examples/magento-graphcms/pages/index.tsx @@ -1,14 +1,11 @@ import { ContentAreaHome, - PageContent, UniversalPageDocument, UniversalPageQuery, } from '@graphcommerce/content-areas' import { PageOptions } from '@graphcommerce/framer-next-pages' -import { RowProduct } from '@graphcommerce/graphcms-ui' -import { ProductListDocument, ProductListQuery } from '@graphcommerce/magento-product' import { StoreConfigDocument } from '@graphcommerce/magento-store' -import { GetStaticProps, LayoutHeader, PageMeta } from '@graphcommerce/next-ui' +import { GetStaticProps, LayoutHeader } from '@graphcommerce/next-ui' import { LayoutDocument, LayoutNavigation, @@ -17,47 +14,20 @@ import { } from '../components' import { graphqlSharedClient, graphqlSsrClient } from '../lib/graphql/graphqlSsrClient' -type Props = { - latestList: ProductListQuery - favoritesList: ProductListQuery - swipableList: ProductListQuery -} & UniversalPageQuery +type Props = UniversalPageQuery type RouteProps = { url: string } type GetPageStaticProps = GetStaticProps function CmsPage(props: Props) { - const { pageContent, latestList, favoritesList, swipableList } = props - - const latest = latestList?.products?.items?.[0] - const favorite = favoritesList?.products?.items?.[0] - const swipable = swipableList?.products?.items?.[0] + const { pageContent } = props return ( <> {/* */} - - { - // const { identity } = rowProps - - // if (identity === 'home-favorites') - // return ( - // - // ) - // if (identity === 'home-latest') - // return - // if (identity === 'home-swipable') - // return - // return - // }, - // }} - /> + ) } @@ -80,31 +50,12 @@ export const getStaticProps: GetPageStaticProps = async ({ locale }) => { const layout = staticClient.query({ query: LayoutDocument, fetchPolicy: 'cache-first' }) - // todo(paales): Remove when https://github.com/Urigo/graphql-mesh/issues/1257 is resolved - const favoritesList = staticClient.query({ - query: ProductListDocument, - variables: { pageSize: 8, filters: { category_uid: { eq: 'MTIx' } } }, - }) - - const latestList = staticClient.query({ - query: ProductListDocument, - variables: { pageSize: 8, filters: { category_uid: { eq: 'MTAy' } } }, - }) - - const swipableList = staticClient.query({ - query: ProductListDocument, - variables: { pageSize: 8, filters: { category_uid: { eq: 'MTIy' } } }, - }) - if (!(await page).data) return { notFound: true } return { props: { ...(await page).data, ...(await layout).data, - latestList: (await latestList).data, - favoritesList: (await favoritesList).data, - swipableList: (await swipableList).data, apolloState: await conf.then(() => client.cache.extract()), }, revalidate: 60 * 20, diff --git a/packages/content-areas/components/ContentArea/ContentArea.tsx b/packages/content-areas/components/ContentArea/ContentArea.tsx index f8c0909bcd7..5932a075b63 100644 --- a/packages/content-areas/components/ContentArea/ContentArea.tsx +++ b/packages/content-areas/components/ContentArea/ContentArea.tsx @@ -6,6 +6,6 @@ type ContentAreaProps = UniversalPageQuery & { } export function ContentArea(props: ContentAreaProps) { - const { content, productListRenderer, renderer } = props + const { pageContent } = props return
} diff --git a/packages/content-areas/schema.graphqls b/packages/content-areas/schema.graphqls index fd65a4e92e7..c2282faf587 100644 --- a/packages/content-areas/schema.graphqls +++ b/packages/content-areas/schema.graphqls @@ -1,4 +1,4 @@ -type UniversalMeta { +type UniSeo { """ Meta title """ @@ -12,13 +12,17 @@ type UniversalMeta { type UniversalPage { title: String - meta: UniversalMeta + meta: Seo } input UniversalPageInput { url: String! } -extend type Query { +type UniversalApi { pageContent(input: UniversalPageInput!): UniversalPage } + +extend type Query { + common: UniversalApi +} diff --git a/packages/graphql-mesh/package.json b/packages/graphql-mesh/package.json index 86c88b50727..9cb9d9e87d3 100644 --- a/packages/graphql-mesh/package.json +++ b/packages/graphql-mesh/package.json @@ -13,8 +13,14 @@ "@graphql-mesh/plugin-http-details-extensions": "latest", "@graphql-mesh/runtime": "latest", "@graphql-mesh/store": "latest", + "@graphql-mesh/transform-encapsulate": "latest", "@graphql-mesh/transform-filter-schema": "latest", + "@graphql-mesh/transform-hoist-field": "latest", + "@graphql-mesh/transform-naming-convention": "latest", + "@graphql-mesh/transform-prefix": "latest", "@graphql-mesh/transform-prune": "latest", + "@graphql-mesh/transform-rename": "latest", + "@graphql-mesh/transform-replace-field": "latest", "@graphql-mesh/types": "latest", "@graphql-mesh/utils": "latest", "@graphql-tools/utils": "^10.0.12", diff --git a/packages/hygraph-ui/mesh.ts b/packages/hygraph-ui/mesh.ts index 563b0d765da..8bca87ff128 100644 --- a/packages/hygraph-ui/mesh.ts +++ b/packages/hygraph-ui/mesh.ts @@ -43,10 +43,8 @@ export const resolvers: Resolvers = { info, selectionSet, }) - const hygraphPage = pages?.[0] if (!hygraphPage) return null - const { title, metaTitle, metaDescription } = hygraphPage return { title, @@ -55,4 +53,12 @@ export const resolvers: Resolvers = { } }, }, + + RowProduct: { + category: async (root, _args, context, info) => { + // This resolver should be called as a RowProduct is returned by the resolver below. + console.log('Called') + return null + }, + }, } diff --git a/packages/hygraph-ui/schema.graphqls b/packages/hygraph-ui/schema.graphqls index 0f65f11109c..8f45ffa1d5f 100644 --- a/packages/hygraph-ui/schema.graphqls +++ b/packages/hygraph-ui/schema.graphqls @@ -2,12 +2,30 @@ extend type UniversalPage { hygraphPage: Page } +extend type Query { + pageContent(input: UniversalPageInput!): UniversalPage + @resolveTo( + sourceName: "hygraph" + sourceTypeName: "Query" + sourceFieldName: "categories" + # Regular resolver + requiredSelectionSet: "{ identity }" + sourceArgs: { where: { url: "{args.input.url}" } } + result: "[0]" + + # Batching resolver (requires all values to resolve, so nothing will be returned if any of the values are missing) + # keyField: "identity" + # keysArg: "filters.url_key.in" + # result: "items" + ) +} + extend type RowProduct { category: CategoryTree @resolveTo( - sourceName: "m2" # Which source does the target field belong to? - sourceTypeName: "Query" # Which root type does the target field belong to? - sourceFieldName: "categories" # What is the source field name? + sourceName: "m2" + sourceTypeName: "Query" + sourceFieldName: "categories" # Regular resolver requiredSelectionSet: "{ identity }" sourceArgs: { filters: { url_key: { eq: "{root.identity}" } } } diff --git a/packages/universal-schema/README.md b/packages/universal-schema/README.md new file mode 100644 index 00000000000..299e1d2a981 --- /dev/null +++ b/packages/universal-schema/README.md @@ -0,0 +1,8 @@ +A unufied data model based on the spec defined by ecommerce platforms like +Shopify, BigCommerce, and Magento. + +Backends to check for schema's: https://graphcommerce.vercel.app/api/graphql + +| Entity | Magento | Shopify | BigCommerce | +| ------- | ----------------------------------------------------------------------------------------------------------------------- | ------- | ----------- | +| Product | [ProductInterface](https://developer.adobe.com/commerce/webapi/graphql-api/beta/index.html#definition-ProductInterface) | diff --git a/yarn.lock b/yarn.lock index 954b9ac4919..94e9996ff64 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3073,8 +3073,14 @@ __metadata: "@graphql-mesh/plugin-http-details-extensions": "npm:latest" "@graphql-mesh/runtime": "npm:latest" "@graphql-mesh/store": "npm:latest" + "@graphql-mesh/transform-encapsulate": "npm:latest" "@graphql-mesh/transform-filter-schema": "npm:latest" + "@graphql-mesh/transform-hoist-field": "npm:latest" + "@graphql-mesh/transform-naming-convention": "npm:latest" + "@graphql-mesh/transform-prefix": "npm:latest" "@graphql-mesh/transform-prune": "npm:latest" + "@graphql-mesh/transform-rename": "npm:latest" + "@graphql-mesh/transform-replace-field": "npm:latest" "@graphql-mesh/types": "npm:latest" "@graphql-mesh/utils": "npm:latest" "@graphql-tools/utils": "npm:^10.0.12" @@ -5060,6 +5066,22 @@ __metadata: languageName: node linkType: hard +"@graphql-mesh/transform-encapsulate@npm:latest": + version: 0.96.3 + resolution: "@graphql-mesh/transform-encapsulate@npm:0.96.3" + dependencies: + "@graphql-tools/delegate": "npm:^10.0.3" + "@graphql-tools/wrap": "npm:^10.0.1" + peerDependencies: + "@graphql-mesh/types": ^0.96.3 + "@graphql-mesh/utils": ^0.96.3 + "@graphql-tools/utils": ^9.2.1 || ^10.0.0 + graphql: "*" + tslib: ^2.4.0 + checksum: 28ec7d4b375fb9533bf4612542250729dce99e9c59caf4bf3dc07dd6c04dba08e90017a995ebc1a1a37fa92e0d7c0233c215f214abc65817645b4728d110ac9f + languageName: node + linkType: hard + "@graphql-mesh/transform-filter-schema@npm:latest": version: 0.96.3 resolution: "@graphql-mesh/transform-filter-schema@npm:0.96.3" @@ -5077,6 +5099,58 @@ __metadata: languageName: node linkType: hard +"@graphql-mesh/transform-hoist-field@npm:latest": + version: 0.96.3 + resolution: "@graphql-mesh/transform-hoist-field@npm:0.96.3" + dependencies: + "@graphql-tools/delegate": "npm:^10.0.0" + "@graphql-tools/wrap": "npm:^10.0.0" + peerDependencies: + "@graphql-mesh/types": ^0.96.3 + "@graphql-mesh/utils": ^0.96.3 + "@graphql-tools/utils": ^9.2.1 || ^10.0.0 + graphql: "*" + checksum: 474032723aff262ef058795d79b8b1a07faa352f5fbb4a40b2cac839b8667260fe0622c5b2633123f3a5e0781374d946c4c3cb12c242eb003c5ef2b31f9374fa + languageName: node + linkType: hard + +"@graphql-mesh/transform-naming-convention@npm:latest": + version: 0.96.3 + resolution: "@graphql-mesh/transform-naming-convention@npm:0.96.3" + dependencies: + "@graphql-tools/delegate": "npm:^10.0.0" + "@graphql-tools/wrap": "npm:^10.0.0" + change-case: "npm:^4.1.2" + graphql-scalars: "npm:^1.22.4" + lower-case: "npm:^2.0.2" + upper-case: "npm:^2.0.2" + peerDependencies: + "@graphql-mesh/types": ^0.96.3 + "@graphql-mesh/utils": ^0.96.3 + "@graphql-tools/utils": ^9.2.1 || ^10.0.0 + graphql: "*" + tslib: ^2.5.0 + checksum: 55304749b1cb1545df81423e53573c923e04cd44012bda42d2f4e9f0645b68ab969046c138cb0a9577ad5c887bd3ea94de22add94dcba3138e7aecd0a7e00a3d + languageName: node + linkType: hard + +"@graphql-mesh/transform-prefix@npm:latest": + version: 0.96.3 + resolution: "@graphql-mesh/transform-prefix@npm:0.96.3" + dependencies: + "@graphql-tools/delegate": "npm:^10.0.0" + "@graphql-tools/wrap": "npm:^10.0.0" + graphql-scalars: "npm:^1.22.4" + peerDependencies: + "@graphql-mesh/types": ^0.96.3 + "@graphql-mesh/utils": ^0.96.3 + "@graphql-tools/utils": ^9.2.1 || ^10.0.0 + graphql: "*" + tslib: ^2.4.0 + checksum: 377cfa87f89c312d38ae7bb29556f655fb075880576849536af5ae9335cc899a28d09c54d69bb379d43ddba7c50e4fb63bd997187cb618cab3a41a5722a509c4 + languageName: node + linkType: hard + "@graphql-mesh/transform-prune@npm:latest": version: 0.96.3 resolution: "@graphql-mesh/transform-prune@npm:0.96.3" @@ -5089,6 +5163,40 @@ __metadata: languageName: node linkType: hard +"@graphql-mesh/transform-rename@npm:latest": + version: 0.96.4 + resolution: "@graphql-mesh/transform-rename@npm:0.96.4" + dependencies: + "@graphql-tools/delegate": "npm:^10.0.0" + "@graphql-tools/wrap": "npm:^10.0.0" + graphql-scalars: "npm:^1.22.4" + peerDependencies: + "@graphql-mesh/types": ^0.96.3 + "@graphql-mesh/utils": ^0.96.3 + "@graphql-tools/utils": ^9.2.1 || ^10.0.0 + graphql: "*" + tslib: ^2.4.0 + checksum: 29e9bf4246f10b7942c2bc0fdcce20790d29498b58a7a8d965d68c309b0d001a49335fa04a517aee5e21bd338fdb11f9c4f4f46f86342fade00d5d52df0c36a1 + languageName: node + linkType: hard + +"@graphql-mesh/transform-replace-field@npm:latest": + version: 0.96.3 + resolution: "@graphql-mesh/transform-replace-field@npm:0.96.3" + dependencies: + "@graphql-tools/code-file-loader": "npm:^8.0.0" + "@graphql-tools/graphql-file-loader": "npm:^8.0.0" + "@graphql-tools/load": "npm:^8.0.0" + peerDependencies: + "@graphql-mesh/types": ^0.96.3 + "@graphql-mesh/utils": ^0.96.3 + "@graphql-tools/utils": ^9.2.1 || ^10.0.0 + graphql: "*" + tslib: ^2.4.0 + checksum: ada933730ef507b27814e015bbc32da5a94e3e1adbc18fe1247b889efb164143b4139ad38ea02ece7ed9370ff23d5865f20e2480653656e598610d2e9e1fba65 + languageName: node + linkType: hard + "@graphql-mesh/types@npm:^0.96.3, @graphql-mesh/types@npm:latest": version: 0.96.3 resolution: "@graphql-mesh/types@npm:0.96.3" @@ -5586,7 +5694,7 @@ __metadata: languageName: node linkType: hard -"@graphql-tools/wrap@npm:^10.0.0": +"@graphql-tools/wrap@npm:^10.0.0, @graphql-tools/wrap@npm:^10.0.1": version: 10.0.1 resolution: "@graphql-tools/wrap@npm:10.0.1" dependencies: @@ -12010,6 +12118,17 @@ __metadata: languageName: node linkType: hard +"graphql-scalars@npm:^1.22.4": + version: 1.22.4 + resolution: "graphql-scalars@npm:1.22.4" + dependencies: + tslib: "npm:^2.5.0" + peerDependencies: + graphql: ^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 + checksum: d7df28c7bcd274049ee2b93536036b22bc2591bdb86a627a46d4557161965df96c8da6c4f7dc01684d46580d75c7b2fbba7fc5042b763b5b6cba879dc79e010e + languageName: node + linkType: hard + "graphql-tag@npm:^2.11.0, graphql-tag@npm:^2.12.6": version: 2.12.6 resolution: "graphql-tag@npm:2.12.6" From 93595ac9e03cf9b88eb69b94926c065320467c12 Mon Sep 17 00:00:00 2001 From: Paul Hachmang Date: Mon, 22 Jul 2024 13:39:11 +0200 Subject: [PATCH 12/33] Move Hygraph components back --- .../magento-graphcms}/components/Blog/BlogAuthor.graphql | 0 .../magento-graphcms}/components/Blog/BlogAuthor.tsx | 0 .../magento-graphcms}/components/Blog/BlogHeader.tsx | 2 +- .../magento-graphcms}/components/Blog/BlogItem.graphql | 0 .../magento-graphcms}/components/Blog/BlogItem.tsx | 2 +- .../magento-graphcms}/components/Blog/BlogList.graphql | 0 .../magento-graphcms}/components/Blog/BlogList.tsx | 0 .../magento-graphcms}/components/Blog/BlogListTagged.graphql | 0 .../magento-graphcms}/components/Blog/BlogPaths.graphql | 0 .../magento-graphcms}/components/Blog/BlogPostPaths.graphql | 0 .../components/Blog/BlogPostTaggedPaths.graphql | 0 .../magento-graphcms}/components/Blog/BlogTags.graphql | 0 .../magento-graphcms}/components/Blog/BlogTags.tsx | 0 .../magento-graphcms}/components/Blog/RowBlogContent.graphql | 0 .../magento-graphcms}/components/Blog/RowBlogContent.tsx | 0 .../magento-graphcms}/components/Blog/index.ts | 0 .../components/GraphCMS}/Asset/AssetWithAlt.graphql | 0 .../components/GraphCMS}/FooterQueryFragment.graphql | 0 .../components/GraphCMS}/PageContentQueryFragment.graphql | 0 .../magento-graphcms/components/GraphCMS}/RichText/RichText.tsx | 0 .../components/GraphCMS}/RichText/defaultRenderers.tsx | 0 .../components/GraphCMS}/RichText/defaultSxRenderer.ts | 0 .../components/GraphCMS}/RichText/getNodeLength.tsx | 0 .../magento-graphcms/components/GraphCMS}/RichText/index.ts | 0 .../magento-graphcms/components/GraphCMS}/RichText/types.ts | 0 .../GraphCMS}/RowButtonLinkList/RowButtonLinkList.graphql | 0 .../GraphCMS}/RowButtonLinkList/RowButtonLinkList.tsx | 0 .../components/GraphCMS}/RowColumnOne/RowColumnOne.graphql | 0 .../components/GraphCMS}/RowColumnOne/RowColumnOne.tsx | 0 .../components/GraphCMS}/RowColumnOne/RowColumnOneBoxed.tsx | 0 .../components/GraphCMS}/RowColumnOne/RowColumnOneCentered.tsx | 0 .../GraphCMS}/RowColumnOne/RowColumnOneDoubleSpread.tsx | 0 .../components/GraphCMS}/RowColumnOne/RowColumnOneSpread.tsx | 0 .../components/GraphCMS}/RowColumnOne/variant/Default.tsx | 0 .../components/GraphCMS}/RowColumnOne/variant/Message.tsx | 0 .../components/GraphCMS}/RowColumnOne/variant/index.tsx | 0 .../components/GraphCMS}/RowColumnThree/RowColumnThree.graphql | 0 .../components/GraphCMS}/RowColumnThree/RowColumnThree.tsx | 0 .../components/GraphCMS}/RowColumnTwo/RowColumnTwo.graphql | 0 .../components/GraphCMS}/RowColumnTwo/RowColumnTwo.tsx | 0 .../components/GraphCMS}/RowColumnTwo/RowColumnTwoSpread.tsx | 0 .../GraphCMS}/RowContentLinks/RowContentLinks.graphql | 0 .../components/GraphCMS}/RowContentLinks/RowContentLinks.tsx | 0 .../components/GraphCMS}/RowHeroBanner/RowHeroBanner.graphql | 0 .../components/GraphCMS}/RowHeroBanner/RowHeroBanner.tsx | 0 .../components/GraphCMS}/RowLinks/RowLinks.graphql | 0 .../magento-graphcms/components/GraphCMS}/RowLinks/RowLinks.tsx | 0 .../components/GraphCMS}/RowLinks/variant/ImageLabelSwiper.tsx | 0 .../components/GraphCMS}/RowLinks/variant/Inline.tsx | 0 .../components/GraphCMS}/RowLinks/variant/LogoSwiper.tsx | 0 .../components/GraphCMS}/RowLinks/variant/Usps.tsx | 0 .../components/GraphCMS}/RowLinks/variant/index.tsx | 0 .../components/GraphCMS}/RowProduct/RowProduct.graphql | 0 .../components/GraphCMS}/RowProduct/RowProduct.tsx | 0 .../components/GraphCMS}/RowProduct/variant/Backstory.tsx | 0 .../components/GraphCMS}/RowProduct/variant/Feature.tsx | 0 .../components/GraphCMS}/RowProduct/variant/FeatureBoxed.tsx | 0 .../components/GraphCMS}/RowProduct/variant/Grid.tsx | 0 .../GraphCMS}/RowProduct/variant/ProductFeatureMedia.graphql | 0 .../RowProduct/variant/ProductFeatureMediaBoxed.graphql | 0 .../components/GraphCMS}/RowProduct/variant/Related.tsx | 0 .../components/GraphCMS}/RowProduct/variant/Reviews.tsx | 0 .../components/GraphCMS}/RowProduct/variant/Specs.tsx | 0 .../components/GraphCMS}/RowProduct/variant/Swipeable.tsx | 0 .../components/GraphCMS}/RowProduct/variant/Upsells.tsx | 0 .../components/GraphCMS}/RowProduct/variant/index.tsx | 0 .../components/GraphCMS}/RowQuote/RowQuote.graphql | 0 .../magento-graphcms/components/GraphCMS}/RowQuote/RowQuote.tsx | 0 .../magento-graphcms/components/GraphCMS}/RowRenderer.graphql | 0 .../magento-graphcms/components/GraphCMS}/RowRenderer.tsx | 0 .../GraphCMS}/RowServiceOptions/RowServiceOptions.graphql | 0 .../GraphCMS}/RowServiceOptions/RowServiceOptions.tsx | 0 .../GraphCMS}/RowSpecialBanner/RowSpecialBanner.graphql | 0 .../components/GraphCMS}/RowSpecialBanner/RowSpecialBanner.tsx | 0 .../magento-graphcms/components/GraphCMS}/Usps/Usps.graphql | 0 .../magento-graphcms/components/GraphCMS}/Usps/Usps.tsx | 0 .../components/GraphCMS}/Usps/UspsQueryFragment.graphql | 0 .../magento-graphcms/components/GraphCMS}/index.ts | 0 78 files changed, 2 insertions(+), 2 deletions(-) rename {packages/hygraph-ui => examples/magento-graphcms}/components/Blog/BlogAuthor.graphql (100%) rename {packages/hygraph-ui => examples/magento-graphcms}/components/Blog/BlogAuthor.tsx (100%) rename {packages/hygraph-ui => examples/magento-graphcms}/components/Blog/BlogHeader.tsx (76%) rename {packages/hygraph-ui => examples/magento-graphcms}/components/Blog/BlogItem.graphql (100%) rename {packages/hygraph-ui => examples/magento-graphcms}/components/Blog/BlogItem.tsx (92%) rename {packages/hygraph-ui => examples/magento-graphcms}/components/Blog/BlogList.graphql (100%) rename {packages/hygraph-ui => examples/magento-graphcms}/components/Blog/BlogList.tsx (100%) rename {packages/hygraph-ui => examples/magento-graphcms}/components/Blog/BlogListTagged.graphql (100%) rename {packages/hygraph-ui => examples/magento-graphcms}/components/Blog/BlogPaths.graphql (100%) rename {packages/hygraph-ui => examples/magento-graphcms}/components/Blog/BlogPostPaths.graphql (100%) rename {packages/hygraph-ui => examples/magento-graphcms}/components/Blog/BlogPostTaggedPaths.graphql (100%) rename {packages/hygraph-ui => examples/magento-graphcms}/components/Blog/BlogTags.graphql (100%) rename {packages/hygraph-ui => examples/magento-graphcms}/components/Blog/BlogTags.tsx (100%) rename {packages/hygraph-ui => examples/magento-graphcms}/components/Blog/RowBlogContent.graphql (100%) rename {packages/hygraph-ui => examples/magento-graphcms}/components/Blog/RowBlogContent.tsx (100%) rename {packages/hygraph-ui => examples/magento-graphcms}/components/Blog/index.ts (100%) rename {packages/hygraph-ui/components => examples/magento-graphcms/components/GraphCMS}/Asset/AssetWithAlt.graphql (100%) rename {packages/hygraph-ui/components => examples/magento-graphcms/components/GraphCMS}/FooterQueryFragment.graphql (100%) rename {packages/hygraph-ui/components => examples/magento-graphcms/components/GraphCMS}/PageContentQueryFragment.graphql (100%) rename {packages/hygraph-ui/components => examples/magento-graphcms/components/GraphCMS}/RichText/RichText.tsx (100%) rename {packages/hygraph-ui/components => examples/magento-graphcms/components/GraphCMS}/RichText/defaultRenderers.tsx (100%) rename {packages/hygraph-ui/components => examples/magento-graphcms/components/GraphCMS}/RichText/defaultSxRenderer.ts (100%) rename {packages/hygraph-ui/components => examples/magento-graphcms/components/GraphCMS}/RichText/getNodeLength.tsx (100%) rename {packages/hygraph-ui/components => examples/magento-graphcms/components/GraphCMS}/RichText/index.ts (100%) rename {packages/hygraph-ui/components => examples/magento-graphcms/components/GraphCMS}/RichText/types.ts (100%) rename {packages/hygraph-ui/components => examples/magento-graphcms/components/GraphCMS}/RowButtonLinkList/RowButtonLinkList.graphql (100%) rename {packages/hygraph-ui/components => examples/magento-graphcms/components/GraphCMS}/RowButtonLinkList/RowButtonLinkList.tsx (100%) rename {packages/hygraph-ui/components => examples/magento-graphcms/components/GraphCMS}/RowColumnOne/RowColumnOne.graphql (100%) rename {packages/hygraph-ui/components => examples/magento-graphcms/components/GraphCMS}/RowColumnOne/RowColumnOne.tsx (100%) rename {packages/hygraph-ui/components => examples/magento-graphcms/components/GraphCMS}/RowColumnOne/RowColumnOneBoxed.tsx (100%) rename {packages/hygraph-ui/components => examples/magento-graphcms/components/GraphCMS}/RowColumnOne/RowColumnOneCentered.tsx (100%) rename {packages/hygraph-ui/components => examples/magento-graphcms/components/GraphCMS}/RowColumnOne/RowColumnOneDoubleSpread.tsx (100%) rename {packages/hygraph-ui/components => examples/magento-graphcms/components/GraphCMS}/RowColumnOne/RowColumnOneSpread.tsx (100%) rename {packages/hygraph-ui/components => examples/magento-graphcms/components/GraphCMS}/RowColumnOne/variant/Default.tsx (100%) rename {packages/hygraph-ui/components => examples/magento-graphcms/components/GraphCMS}/RowColumnOne/variant/Message.tsx (100%) rename {packages/hygraph-ui/components => examples/magento-graphcms/components/GraphCMS}/RowColumnOne/variant/index.tsx (100%) rename {packages/hygraph-ui/components => examples/magento-graphcms/components/GraphCMS}/RowColumnThree/RowColumnThree.graphql (100%) rename {packages/hygraph-ui/components => examples/magento-graphcms/components/GraphCMS}/RowColumnThree/RowColumnThree.tsx (100%) rename {packages/hygraph-ui/components => examples/magento-graphcms/components/GraphCMS}/RowColumnTwo/RowColumnTwo.graphql (100%) rename {packages/hygraph-ui/components => examples/magento-graphcms/components/GraphCMS}/RowColumnTwo/RowColumnTwo.tsx (100%) rename {packages/hygraph-ui/components => examples/magento-graphcms/components/GraphCMS}/RowColumnTwo/RowColumnTwoSpread.tsx (100%) rename {packages/hygraph-ui/components => examples/magento-graphcms/components/GraphCMS}/RowContentLinks/RowContentLinks.graphql (100%) rename {packages/hygraph-ui/components => examples/magento-graphcms/components/GraphCMS}/RowContentLinks/RowContentLinks.tsx (100%) rename {packages/hygraph-ui/components => examples/magento-graphcms/components/GraphCMS}/RowHeroBanner/RowHeroBanner.graphql (100%) rename {packages/hygraph-ui/components => examples/magento-graphcms/components/GraphCMS}/RowHeroBanner/RowHeroBanner.tsx (100%) rename {packages/hygraph-ui/components => examples/magento-graphcms/components/GraphCMS}/RowLinks/RowLinks.graphql (100%) rename {packages/hygraph-ui/components => examples/magento-graphcms/components/GraphCMS}/RowLinks/RowLinks.tsx (100%) rename {packages/hygraph-ui/components => examples/magento-graphcms/components/GraphCMS}/RowLinks/variant/ImageLabelSwiper.tsx (100%) rename {packages/hygraph-ui/components => examples/magento-graphcms/components/GraphCMS}/RowLinks/variant/Inline.tsx (100%) rename {packages/hygraph-ui/components => examples/magento-graphcms/components/GraphCMS}/RowLinks/variant/LogoSwiper.tsx (100%) rename {packages/hygraph-ui/components => examples/magento-graphcms/components/GraphCMS}/RowLinks/variant/Usps.tsx (100%) rename {packages/hygraph-ui/components => examples/magento-graphcms/components/GraphCMS}/RowLinks/variant/index.tsx (100%) rename {packages/hygraph-ui/components => examples/magento-graphcms/components/GraphCMS}/RowProduct/RowProduct.graphql (100%) rename {packages/hygraph-ui/components => examples/magento-graphcms/components/GraphCMS}/RowProduct/RowProduct.tsx (100%) rename {packages/hygraph-ui/components => examples/magento-graphcms/components/GraphCMS}/RowProduct/variant/Backstory.tsx (100%) rename {packages/hygraph-ui/components => examples/magento-graphcms/components/GraphCMS}/RowProduct/variant/Feature.tsx (100%) rename {packages/hygraph-ui/components => examples/magento-graphcms/components/GraphCMS}/RowProduct/variant/FeatureBoxed.tsx (100%) rename {packages/hygraph-ui/components => examples/magento-graphcms/components/GraphCMS}/RowProduct/variant/Grid.tsx (100%) rename {packages/hygraph-ui/components => examples/magento-graphcms/components/GraphCMS}/RowProduct/variant/ProductFeatureMedia.graphql (100%) rename {packages/hygraph-ui/components => examples/magento-graphcms/components/GraphCMS}/RowProduct/variant/ProductFeatureMediaBoxed.graphql (100%) rename {packages/hygraph-ui/components => examples/magento-graphcms/components/GraphCMS}/RowProduct/variant/Related.tsx (100%) rename {packages/hygraph-ui/components => examples/magento-graphcms/components/GraphCMS}/RowProduct/variant/Reviews.tsx (100%) rename {packages/hygraph-ui/components => examples/magento-graphcms/components/GraphCMS}/RowProduct/variant/Specs.tsx (100%) rename {packages/hygraph-ui/components => examples/magento-graphcms/components/GraphCMS}/RowProduct/variant/Swipeable.tsx (100%) rename {packages/hygraph-ui/components => examples/magento-graphcms/components/GraphCMS}/RowProduct/variant/Upsells.tsx (100%) rename {packages/hygraph-ui/components => examples/magento-graphcms/components/GraphCMS}/RowProduct/variant/index.tsx (100%) rename {packages/hygraph-ui/components => examples/magento-graphcms/components/GraphCMS}/RowQuote/RowQuote.graphql (100%) rename {packages/hygraph-ui/components => examples/magento-graphcms/components/GraphCMS}/RowQuote/RowQuote.tsx (100%) rename {packages/hygraph-ui/components => examples/magento-graphcms/components/GraphCMS}/RowRenderer.graphql (100%) rename {packages/hygraph-ui/components => examples/magento-graphcms/components/GraphCMS}/RowRenderer.tsx (100%) rename {packages/hygraph-ui/components => examples/magento-graphcms/components/GraphCMS}/RowServiceOptions/RowServiceOptions.graphql (100%) rename {packages/hygraph-ui/components => examples/magento-graphcms/components/GraphCMS}/RowServiceOptions/RowServiceOptions.tsx (100%) rename {packages/hygraph-ui/components => examples/magento-graphcms/components/GraphCMS}/RowSpecialBanner/RowSpecialBanner.graphql (100%) rename {packages/hygraph-ui/components => examples/magento-graphcms/components/GraphCMS}/RowSpecialBanner/RowSpecialBanner.tsx (100%) rename {packages/hygraph-ui/components => examples/magento-graphcms/components/GraphCMS}/Usps/Usps.graphql (100%) rename {packages/hygraph-ui/components => examples/magento-graphcms/components/GraphCMS}/Usps/Usps.tsx (100%) rename {packages/hygraph-ui/components => examples/magento-graphcms/components/GraphCMS}/Usps/UspsQueryFragment.graphql (100%) rename {packages/hygraph-ui/components => examples/magento-graphcms/components/GraphCMS}/index.ts (100%) diff --git a/packages/hygraph-ui/components/Blog/BlogAuthor.graphql b/examples/magento-graphcms/components/Blog/BlogAuthor.graphql similarity index 100% rename from packages/hygraph-ui/components/Blog/BlogAuthor.graphql rename to examples/magento-graphcms/components/Blog/BlogAuthor.graphql diff --git a/packages/hygraph-ui/components/Blog/BlogAuthor.tsx b/examples/magento-graphcms/components/Blog/BlogAuthor.tsx similarity index 100% rename from packages/hygraph-ui/components/Blog/BlogAuthor.tsx rename to examples/magento-graphcms/components/Blog/BlogAuthor.tsx diff --git a/packages/hygraph-ui/components/Blog/BlogHeader.tsx b/examples/magento-graphcms/components/Blog/BlogHeader.tsx similarity index 76% rename from packages/hygraph-ui/components/Blog/BlogHeader.tsx rename to examples/magento-graphcms/components/Blog/BlogHeader.tsx index 945b454b5e9..4f26508f892 100644 --- a/packages/hygraph-ui/components/Blog/BlogHeader.tsx +++ b/examples/magento-graphcms/components/Blog/BlogHeader.tsx @@ -1,5 +1,5 @@ import { BlogHeader as NextBlogHeader } from '@graphcommerce/next-ui' -import { Asset, AssetFragment } from '../Asset/Asset' +import { Asset, AssetFragment } from '@graphcommerce/graphcms-ui/components/Asset/Asset' export function BlogHeader(props: { asset?: AssetFragment }) { const { asset } = props diff --git a/packages/hygraph-ui/components/Blog/BlogItem.graphql b/examples/magento-graphcms/components/Blog/BlogItem.graphql similarity index 100% rename from packages/hygraph-ui/components/Blog/BlogItem.graphql rename to examples/magento-graphcms/components/Blog/BlogItem.graphql diff --git a/packages/hygraph-ui/components/Blog/BlogItem.tsx b/examples/magento-graphcms/components/Blog/BlogItem.tsx similarity index 92% rename from packages/hygraph-ui/components/Blog/BlogItem.tsx rename to examples/magento-graphcms/components/Blog/BlogItem.tsx index f29b1d3f414..78d12e9ab2d 100644 --- a/packages/hygraph-ui/components/Blog/BlogItem.tsx +++ b/examples/magento-graphcms/components/Blog/BlogItem.tsx @@ -2,7 +2,7 @@ import { BlogListItem } from '@graphcommerce/next-ui' import { Trans } from '@lingui/react' import { Typography, useTheme } from '@mui/material' import { BlogItemFragment } from './BlogItem.gql' -import { Asset } from '../Asset/Asset' +import { Asset } from '@graphcommerce/graphcms-ui/components/Asset/Asset' type BlogItemProps = BlogItemFragment diff --git a/packages/hygraph-ui/components/Blog/BlogList.graphql b/examples/magento-graphcms/components/Blog/BlogList.graphql similarity index 100% rename from packages/hygraph-ui/components/Blog/BlogList.graphql rename to examples/magento-graphcms/components/Blog/BlogList.graphql diff --git a/packages/hygraph-ui/components/Blog/BlogList.tsx b/examples/magento-graphcms/components/Blog/BlogList.tsx similarity index 100% rename from packages/hygraph-ui/components/Blog/BlogList.tsx rename to examples/magento-graphcms/components/Blog/BlogList.tsx diff --git a/packages/hygraph-ui/components/Blog/BlogListTagged.graphql b/examples/magento-graphcms/components/Blog/BlogListTagged.graphql similarity index 100% rename from packages/hygraph-ui/components/Blog/BlogListTagged.graphql rename to examples/magento-graphcms/components/Blog/BlogListTagged.graphql diff --git a/packages/hygraph-ui/components/Blog/BlogPaths.graphql b/examples/magento-graphcms/components/Blog/BlogPaths.graphql similarity index 100% rename from packages/hygraph-ui/components/Blog/BlogPaths.graphql rename to examples/magento-graphcms/components/Blog/BlogPaths.graphql diff --git a/packages/hygraph-ui/components/Blog/BlogPostPaths.graphql b/examples/magento-graphcms/components/Blog/BlogPostPaths.graphql similarity index 100% rename from packages/hygraph-ui/components/Blog/BlogPostPaths.graphql rename to examples/magento-graphcms/components/Blog/BlogPostPaths.graphql diff --git a/packages/hygraph-ui/components/Blog/BlogPostTaggedPaths.graphql b/examples/magento-graphcms/components/Blog/BlogPostTaggedPaths.graphql similarity index 100% rename from packages/hygraph-ui/components/Blog/BlogPostTaggedPaths.graphql rename to examples/magento-graphcms/components/Blog/BlogPostTaggedPaths.graphql diff --git a/packages/hygraph-ui/components/Blog/BlogTags.graphql b/examples/magento-graphcms/components/Blog/BlogTags.graphql similarity index 100% rename from packages/hygraph-ui/components/Blog/BlogTags.graphql rename to examples/magento-graphcms/components/Blog/BlogTags.graphql diff --git a/packages/hygraph-ui/components/Blog/BlogTags.tsx b/examples/magento-graphcms/components/Blog/BlogTags.tsx similarity index 100% rename from packages/hygraph-ui/components/Blog/BlogTags.tsx rename to examples/magento-graphcms/components/Blog/BlogTags.tsx diff --git a/packages/hygraph-ui/components/Blog/RowBlogContent.graphql b/examples/magento-graphcms/components/Blog/RowBlogContent.graphql similarity index 100% rename from packages/hygraph-ui/components/Blog/RowBlogContent.graphql rename to examples/magento-graphcms/components/Blog/RowBlogContent.graphql diff --git a/packages/hygraph-ui/components/Blog/RowBlogContent.tsx b/examples/magento-graphcms/components/Blog/RowBlogContent.tsx similarity index 100% rename from packages/hygraph-ui/components/Blog/RowBlogContent.tsx rename to examples/magento-graphcms/components/Blog/RowBlogContent.tsx diff --git a/packages/hygraph-ui/components/Blog/index.ts b/examples/magento-graphcms/components/Blog/index.ts similarity index 100% rename from packages/hygraph-ui/components/Blog/index.ts rename to examples/magento-graphcms/components/Blog/index.ts diff --git a/packages/hygraph-ui/components/Asset/AssetWithAlt.graphql b/examples/magento-graphcms/components/GraphCMS/Asset/AssetWithAlt.graphql similarity index 100% rename from packages/hygraph-ui/components/Asset/AssetWithAlt.graphql rename to examples/magento-graphcms/components/GraphCMS/Asset/AssetWithAlt.graphql diff --git a/packages/hygraph-ui/components/FooterQueryFragment.graphql b/examples/magento-graphcms/components/GraphCMS/FooterQueryFragment.graphql similarity index 100% rename from packages/hygraph-ui/components/FooterQueryFragment.graphql rename to examples/magento-graphcms/components/GraphCMS/FooterQueryFragment.graphql diff --git a/packages/hygraph-ui/components/PageContentQueryFragment.graphql b/examples/magento-graphcms/components/GraphCMS/PageContentQueryFragment.graphql similarity index 100% rename from packages/hygraph-ui/components/PageContentQueryFragment.graphql rename to examples/magento-graphcms/components/GraphCMS/PageContentQueryFragment.graphql diff --git a/packages/hygraph-ui/components/RichText/RichText.tsx b/examples/magento-graphcms/components/GraphCMS/RichText/RichText.tsx similarity index 100% rename from packages/hygraph-ui/components/RichText/RichText.tsx rename to examples/magento-graphcms/components/GraphCMS/RichText/RichText.tsx diff --git a/packages/hygraph-ui/components/RichText/defaultRenderers.tsx b/examples/magento-graphcms/components/GraphCMS/RichText/defaultRenderers.tsx similarity index 100% rename from packages/hygraph-ui/components/RichText/defaultRenderers.tsx rename to examples/magento-graphcms/components/GraphCMS/RichText/defaultRenderers.tsx diff --git a/packages/hygraph-ui/components/RichText/defaultSxRenderer.ts b/examples/magento-graphcms/components/GraphCMS/RichText/defaultSxRenderer.ts similarity index 100% rename from packages/hygraph-ui/components/RichText/defaultSxRenderer.ts rename to examples/magento-graphcms/components/GraphCMS/RichText/defaultSxRenderer.ts diff --git a/packages/hygraph-ui/components/RichText/getNodeLength.tsx b/examples/magento-graphcms/components/GraphCMS/RichText/getNodeLength.tsx similarity index 100% rename from packages/hygraph-ui/components/RichText/getNodeLength.tsx rename to examples/magento-graphcms/components/GraphCMS/RichText/getNodeLength.tsx diff --git a/packages/hygraph-ui/components/RichText/index.ts b/examples/magento-graphcms/components/GraphCMS/RichText/index.ts similarity index 100% rename from packages/hygraph-ui/components/RichText/index.ts rename to examples/magento-graphcms/components/GraphCMS/RichText/index.ts diff --git a/packages/hygraph-ui/components/RichText/types.ts b/examples/magento-graphcms/components/GraphCMS/RichText/types.ts similarity index 100% rename from packages/hygraph-ui/components/RichText/types.ts rename to examples/magento-graphcms/components/GraphCMS/RichText/types.ts diff --git a/packages/hygraph-ui/components/RowButtonLinkList/RowButtonLinkList.graphql b/examples/magento-graphcms/components/GraphCMS/RowButtonLinkList/RowButtonLinkList.graphql similarity index 100% rename from packages/hygraph-ui/components/RowButtonLinkList/RowButtonLinkList.graphql rename to examples/magento-graphcms/components/GraphCMS/RowButtonLinkList/RowButtonLinkList.graphql diff --git a/packages/hygraph-ui/components/RowButtonLinkList/RowButtonLinkList.tsx b/examples/magento-graphcms/components/GraphCMS/RowButtonLinkList/RowButtonLinkList.tsx similarity index 100% rename from packages/hygraph-ui/components/RowButtonLinkList/RowButtonLinkList.tsx rename to examples/magento-graphcms/components/GraphCMS/RowButtonLinkList/RowButtonLinkList.tsx diff --git a/packages/hygraph-ui/components/RowColumnOne/RowColumnOne.graphql b/examples/magento-graphcms/components/GraphCMS/RowColumnOne/RowColumnOne.graphql similarity index 100% rename from packages/hygraph-ui/components/RowColumnOne/RowColumnOne.graphql rename to examples/magento-graphcms/components/GraphCMS/RowColumnOne/RowColumnOne.graphql diff --git a/packages/hygraph-ui/components/RowColumnOne/RowColumnOne.tsx b/examples/magento-graphcms/components/GraphCMS/RowColumnOne/RowColumnOne.tsx similarity index 100% rename from packages/hygraph-ui/components/RowColumnOne/RowColumnOne.tsx rename to examples/magento-graphcms/components/GraphCMS/RowColumnOne/RowColumnOne.tsx diff --git a/packages/hygraph-ui/components/RowColumnOne/RowColumnOneBoxed.tsx b/examples/magento-graphcms/components/GraphCMS/RowColumnOne/RowColumnOneBoxed.tsx similarity index 100% rename from packages/hygraph-ui/components/RowColumnOne/RowColumnOneBoxed.tsx rename to examples/magento-graphcms/components/GraphCMS/RowColumnOne/RowColumnOneBoxed.tsx diff --git a/packages/hygraph-ui/components/RowColumnOne/RowColumnOneCentered.tsx b/examples/magento-graphcms/components/GraphCMS/RowColumnOne/RowColumnOneCentered.tsx similarity index 100% rename from packages/hygraph-ui/components/RowColumnOne/RowColumnOneCentered.tsx rename to examples/magento-graphcms/components/GraphCMS/RowColumnOne/RowColumnOneCentered.tsx diff --git a/packages/hygraph-ui/components/RowColumnOne/RowColumnOneDoubleSpread.tsx b/examples/magento-graphcms/components/GraphCMS/RowColumnOne/RowColumnOneDoubleSpread.tsx similarity index 100% rename from packages/hygraph-ui/components/RowColumnOne/RowColumnOneDoubleSpread.tsx rename to examples/magento-graphcms/components/GraphCMS/RowColumnOne/RowColumnOneDoubleSpread.tsx diff --git a/packages/hygraph-ui/components/RowColumnOne/RowColumnOneSpread.tsx b/examples/magento-graphcms/components/GraphCMS/RowColumnOne/RowColumnOneSpread.tsx similarity index 100% rename from packages/hygraph-ui/components/RowColumnOne/RowColumnOneSpread.tsx rename to examples/magento-graphcms/components/GraphCMS/RowColumnOne/RowColumnOneSpread.tsx diff --git a/packages/hygraph-ui/components/RowColumnOne/variant/Default.tsx b/examples/magento-graphcms/components/GraphCMS/RowColumnOne/variant/Default.tsx similarity index 100% rename from packages/hygraph-ui/components/RowColumnOne/variant/Default.tsx rename to examples/magento-graphcms/components/GraphCMS/RowColumnOne/variant/Default.tsx diff --git a/packages/hygraph-ui/components/RowColumnOne/variant/Message.tsx b/examples/magento-graphcms/components/GraphCMS/RowColumnOne/variant/Message.tsx similarity index 100% rename from packages/hygraph-ui/components/RowColumnOne/variant/Message.tsx rename to examples/magento-graphcms/components/GraphCMS/RowColumnOne/variant/Message.tsx diff --git a/packages/hygraph-ui/components/RowColumnOne/variant/index.tsx b/examples/magento-graphcms/components/GraphCMS/RowColumnOne/variant/index.tsx similarity index 100% rename from packages/hygraph-ui/components/RowColumnOne/variant/index.tsx rename to examples/magento-graphcms/components/GraphCMS/RowColumnOne/variant/index.tsx diff --git a/packages/hygraph-ui/components/RowColumnThree/RowColumnThree.graphql b/examples/magento-graphcms/components/GraphCMS/RowColumnThree/RowColumnThree.graphql similarity index 100% rename from packages/hygraph-ui/components/RowColumnThree/RowColumnThree.graphql rename to examples/magento-graphcms/components/GraphCMS/RowColumnThree/RowColumnThree.graphql diff --git a/packages/hygraph-ui/components/RowColumnThree/RowColumnThree.tsx b/examples/magento-graphcms/components/GraphCMS/RowColumnThree/RowColumnThree.tsx similarity index 100% rename from packages/hygraph-ui/components/RowColumnThree/RowColumnThree.tsx rename to examples/magento-graphcms/components/GraphCMS/RowColumnThree/RowColumnThree.tsx diff --git a/packages/hygraph-ui/components/RowColumnTwo/RowColumnTwo.graphql b/examples/magento-graphcms/components/GraphCMS/RowColumnTwo/RowColumnTwo.graphql similarity index 100% rename from packages/hygraph-ui/components/RowColumnTwo/RowColumnTwo.graphql rename to examples/magento-graphcms/components/GraphCMS/RowColumnTwo/RowColumnTwo.graphql diff --git a/packages/hygraph-ui/components/RowColumnTwo/RowColumnTwo.tsx b/examples/magento-graphcms/components/GraphCMS/RowColumnTwo/RowColumnTwo.tsx similarity index 100% rename from packages/hygraph-ui/components/RowColumnTwo/RowColumnTwo.tsx rename to examples/magento-graphcms/components/GraphCMS/RowColumnTwo/RowColumnTwo.tsx diff --git a/packages/hygraph-ui/components/RowColumnTwo/RowColumnTwoSpread.tsx b/examples/magento-graphcms/components/GraphCMS/RowColumnTwo/RowColumnTwoSpread.tsx similarity index 100% rename from packages/hygraph-ui/components/RowColumnTwo/RowColumnTwoSpread.tsx rename to examples/magento-graphcms/components/GraphCMS/RowColumnTwo/RowColumnTwoSpread.tsx diff --git a/packages/hygraph-ui/components/RowContentLinks/RowContentLinks.graphql b/examples/magento-graphcms/components/GraphCMS/RowContentLinks/RowContentLinks.graphql similarity index 100% rename from packages/hygraph-ui/components/RowContentLinks/RowContentLinks.graphql rename to examples/magento-graphcms/components/GraphCMS/RowContentLinks/RowContentLinks.graphql diff --git a/packages/hygraph-ui/components/RowContentLinks/RowContentLinks.tsx b/examples/magento-graphcms/components/GraphCMS/RowContentLinks/RowContentLinks.tsx similarity index 100% rename from packages/hygraph-ui/components/RowContentLinks/RowContentLinks.tsx rename to examples/magento-graphcms/components/GraphCMS/RowContentLinks/RowContentLinks.tsx diff --git a/packages/hygraph-ui/components/RowHeroBanner/RowHeroBanner.graphql b/examples/magento-graphcms/components/GraphCMS/RowHeroBanner/RowHeroBanner.graphql similarity index 100% rename from packages/hygraph-ui/components/RowHeroBanner/RowHeroBanner.graphql rename to examples/magento-graphcms/components/GraphCMS/RowHeroBanner/RowHeroBanner.graphql diff --git a/packages/hygraph-ui/components/RowHeroBanner/RowHeroBanner.tsx b/examples/magento-graphcms/components/GraphCMS/RowHeroBanner/RowHeroBanner.tsx similarity index 100% rename from packages/hygraph-ui/components/RowHeroBanner/RowHeroBanner.tsx rename to examples/magento-graphcms/components/GraphCMS/RowHeroBanner/RowHeroBanner.tsx diff --git a/packages/hygraph-ui/components/RowLinks/RowLinks.graphql b/examples/magento-graphcms/components/GraphCMS/RowLinks/RowLinks.graphql similarity index 100% rename from packages/hygraph-ui/components/RowLinks/RowLinks.graphql rename to examples/magento-graphcms/components/GraphCMS/RowLinks/RowLinks.graphql diff --git a/packages/hygraph-ui/components/RowLinks/RowLinks.tsx b/examples/magento-graphcms/components/GraphCMS/RowLinks/RowLinks.tsx similarity index 100% rename from packages/hygraph-ui/components/RowLinks/RowLinks.tsx rename to examples/magento-graphcms/components/GraphCMS/RowLinks/RowLinks.tsx diff --git a/packages/hygraph-ui/components/RowLinks/variant/ImageLabelSwiper.tsx b/examples/magento-graphcms/components/GraphCMS/RowLinks/variant/ImageLabelSwiper.tsx similarity index 100% rename from packages/hygraph-ui/components/RowLinks/variant/ImageLabelSwiper.tsx rename to examples/magento-graphcms/components/GraphCMS/RowLinks/variant/ImageLabelSwiper.tsx diff --git a/packages/hygraph-ui/components/RowLinks/variant/Inline.tsx b/examples/magento-graphcms/components/GraphCMS/RowLinks/variant/Inline.tsx similarity index 100% rename from packages/hygraph-ui/components/RowLinks/variant/Inline.tsx rename to examples/magento-graphcms/components/GraphCMS/RowLinks/variant/Inline.tsx diff --git a/packages/hygraph-ui/components/RowLinks/variant/LogoSwiper.tsx b/examples/magento-graphcms/components/GraphCMS/RowLinks/variant/LogoSwiper.tsx similarity index 100% rename from packages/hygraph-ui/components/RowLinks/variant/LogoSwiper.tsx rename to examples/magento-graphcms/components/GraphCMS/RowLinks/variant/LogoSwiper.tsx diff --git a/packages/hygraph-ui/components/RowLinks/variant/Usps.tsx b/examples/magento-graphcms/components/GraphCMS/RowLinks/variant/Usps.tsx similarity index 100% rename from packages/hygraph-ui/components/RowLinks/variant/Usps.tsx rename to examples/magento-graphcms/components/GraphCMS/RowLinks/variant/Usps.tsx diff --git a/packages/hygraph-ui/components/RowLinks/variant/index.tsx b/examples/magento-graphcms/components/GraphCMS/RowLinks/variant/index.tsx similarity index 100% rename from packages/hygraph-ui/components/RowLinks/variant/index.tsx rename to examples/magento-graphcms/components/GraphCMS/RowLinks/variant/index.tsx diff --git a/packages/hygraph-ui/components/RowProduct/RowProduct.graphql b/examples/magento-graphcms/components/GraphCMS/RowProduct/RowProduct.graphql similarity index 100% rename from packages/hygraph-ui/components/RowProduct/RowProduct.graphql rename to examples/magento-graphcms/components/GraphCMS/RowProduct/RowProduct.graphql diff --git a/packages/hygraph-ui/components/RowProduct/RowProduct.tsx b/examples/magento-graphcms/components/GraphCMS/RowProduct/RowProduct.tsx similarity index 100% rename from packages/hygraph-ui/components/RowProduct/RowProduct.tsx rename to examples/magento-graphcms/components/GraphCMS/RowProduct/RowProduct.tsx diff --git a/packages/hygraph-ui/components/RowProduct/variant/Backstory.tsx b/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Backstory.tsx similarity index 100% rename from packages/hygraph-ui/components/RowProduct/variant/Backstory.tsx rename to examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Backstory.tsx diff --git a/packages/hygraph-ui/components/RowProduct/variant/Feature.tsx b/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Feature.tsx similarity index 100% rename from packages/hygraph-ui/components/RowProduct/variant/Feature.tsx rename to examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Feature.tsx diff --git a/packages/hygraph-ui/components/RowProduct/variant/FeatureBoxed.tsx b/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/FeatureBoxed.tsx similarity index 100% rename from packages/hygraph-ui/components/RowProduct/variant/FeatureBoxed.tsx rename to examples/magento-graphcms/components/GraphCMS/RowProduct/variant/FeatureBoxed.tsx diff --git a/packages/hygraph-ui/components/RowProduct/variant/Grid.tsx b/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Grid.tsx similarity index 100% rename from packages/hygraph-ui/components/RowProduct/variant/Grid.tsx rename to examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Grid.tsx diff --git a/packages/hygraph-ui/components/RowProduct/variant/ProductFeatureMedia.graphql b/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/ProductFeatureMedia.graphql similarity index 100% rename from packages/hygraph-ui/components/RowProduct/variant/ProductFeatureMedia.graphql rename to examples/magento-graphcms/components/GraphCMS/RowProduct/variant/ProductFeatureMedia.graphql diff --git a/packages/hygraph-ui/components/RowProduct/variant/ProductFeatureMediaBoxed.graphql b/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/ProductFeatureMediaBoxed.graphql similarity index 100% rename from packages/hygraph-ui/components/RowProduct/variant/ProductFeatureMediaBoxed.graphql rename to examples/magento-graphcms/components/GraphCMS/RowProduct/variant/ProductFeatureMediaBoxed.graphql diff --git a/packages/hygraph-ui/components/RowProduct/variant/Related.tsx b/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Related.tsx similarity index 100% rename from packages/hygraph-ui/components/RowProduct/variant/Related.tsx rename to examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Related.tsx diff --git a/packages/hygraph-ui/components/RowProduct/variant/Reviews.tsx b/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Reviews.tsx similarity index 100% rename from packages/hygraph-ui/components/RowProduct/variant/Reviews.tsx rename to examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Reviews.tsx diff --git a/packages/hygraph-ui/components/RowProduct/variant/Specs.tsx b/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Specs.tsx similarity index 100% rename from packages/hygraph-ui/components/RowProduct/variant/Specs.tsx rename to examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Specs.tsx diff --git a/packages/hygraph-ui/components/RowProduct/variant/Swipeable.tsx b/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Swipeable.tsx similarity index 100% rename from packages/hygraph-ui/components/RowProduct/variant/Swipeable.tsx rename to examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Swipeable.tsx diff --git a/packages/hygraph-ui/components/RowProduct/variant/Upsells.tsx b/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Upsells.tsx similarity index 100% rename from packages/hygraph-ui/components/RowProduct/variant/Upsells.tsx rename to examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Upsells.tsx diff --git a/packages/hygraph-ui/components/RowProduct/variant/index.tsx b/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/index.tsx similarity index 100% rename from packages/hygraph-ui/components/RowProduct/variant/index.tsx rename to examples/magento-graphcms/components/GraphCMS/RowProduct/variant/index.tsx diff --git a/packages/hygraph-ui/components/RowQuote/RowQuote.graphql b/examples/magento-graphcms/components/GraphCMS/RowQuote/RowQuote.graphql similarity index 100% rename from packages/hygraph-ui/components/RowQuote/RowQuote.graphql rename to examples/magento-graphcms/components/GraphCMS/RowQuote/RowQuote.graphql diff --git a/packages/hygraph-ui/components/RowQuote/RowQuote.tsx b/examples/magento-graphcms/components/GraphCMS/RowQuote/RowQuote.tsx similarity index 100% rename from packages/hygraph-ui/components/RowQuote/RowQuote.tsx rename to examples/magento-graphcms/components/GraphCMS/RowQuote/RowQuote.tsx diff --git a/packages/hygraph-ui/components/RowRenderer.graphql b/examples/magento-graphcms/components/GraphCMS/RowRenderer.graphql similarity index 100% rename from packages/hygraph-ui/components/RowRenderer.graphql rename to examples/magento-graphcms/components/GraphCMS/RowRenderer.graphql diff --git a/packages/hygraph-ui/components/RowRenderer.tsx b/examples/magento-graphcms/components/GraphCMS/RowRenderer.tsx similarity index 100% rename from packages/hygraph-ui/components/RowRenderer.tsx rename to examples/magento-graphcms/components/GraphCMS/RowRenderer.tsx diff --git a/packages/hygraph-ui/components/RowServiceOptions/RowServiceOptions.graphql b/examples/magento-graphcms/components/GraphCMS/RowServiceOptions/RowServiceOptions.graphql similarity index 100% rename from packages/hygraph-ui/components/RowServiceOptions/RowServiceOptions.graphql rename to examples/magento-graphcms/components/GraphCMS/RowServiceOptions/RowServiceOptions.graphql diff --git a/packages/hygraph-ui/components/RowServiceOptions/RowServiceOptions.tsx b/examples/magento-graphcms/components/GraphCMS/RowServiceOptions/RowServiceOptions.tsx similarity index 100% rename from packages/hygraph-ui/components/RowServiceOptions/RowServiceOptions.tsx rename to examples/magento-graphcms/components/GraphCMS/RowServiceOptions/RowServiceOptions.tsx diff --git a/packages/hygraph-ui/components/RowSpecialBanner/RowSpecialBanner.graphql b/examples/magento-graphcms/components/GraphCMS/RowSpecialBanner/RowSpecialBanner.graphql similarity index 100% rename from packages/hygraph-ui/components/RowSpecialBanner/RowSpecialBanner.graphql rename to examples/magento-graphcms/components/GraphCMS/RowSpecialBanner/RowSpecialBanner.graphql diff --git a/packages/hygraph-ui/components/RowSpecialBanner/RowSpecialBanner.tsx b/examples/magento-graphcms/components/GraphCMS/RowSpecialBanner/RowSpecialBanner.tsx similarity index 100% rename from packages/hygraph-ui/components/RowSpecialBanner/RowSpecialBanner.tsx rename to examples/magento-graphcms/components/GraphCMS/RowSpecialBanner/RowSpecialBanner.tsx diff --git a/packages/hygraph-ui/components/Usps/Usps.graphql b/examples/magento-graphcms/components/GraphCMS/Usps/Usps.graphql similarity index 100% rename from packages/hygraph-ui/components/Usps/Usps.graphql rename to examples/magento-graphcms/components/GraphCMS/Usps/Usps.graphql diff --git a/packages/hygraph-ui/components/Usps/Usps.tsx b/examples/magento-graphcms/components/GraphCMS/Usps/Usps.tsx similarity index 100% rename from packages/hygraph-ui/components/Usps/Usps.tsx rename to examples/magento-graphcms/components/GraphCMS/Usps/Usps.tsx diff --git a/packages/hygraph-ui/components/Usps/UspsQueryFragment.graphql b/examples/magento-graphcms/components/GraphCMS/Usps/UspsQueryFragment.graphql similarity index 100% rename from packages/hygraph-ui/components/Usps/UspsQueryFragment.graphql rename to examples/magento-graphcms/components/GraphCMS/Usps/UspsQueryFragment.graphql diff --git a/packages/hygraph-ui/components/index.ts b/examples/magento-graphcms/components/GraphCMS/index.ts similarity index 100% rename from packages/hygraph-ui/components/index.ts rename to examples/magento-graphcms/components/GraphCMS/index.ts From 53ecd6a741a63f875941c71042db94fe08f7ad99 Mon Sep 17 00:00:00 2001 From: Paul Hachmang Date: Mon, 22 Jul 2024 13:49:57 +0200 Subject: [PATCH 13/33] Move RichText back --- .../GraphCMS/RowColumnOne/RowColumnOne.tsx | 2 +- .../RowColumnOne/RowColumnOneBoxed.tsx | 2 +- .../RowColumnOne/RowColumnOneCentered.tsx | 2 +- .../RowColumnOne/RowColumnOneDoubleSpread.tsx | 2 +- .../RowColumnOne/RowColumnOneSpread.tsx | 2 +- .../GraphCMS/RowColumnOne/variant/Default.tsx | 2 +- .../GraphCMS/RowColumnOne/variant/Message.tsx | 2 +- .../RowColumnThree/RowColumnThree.tsx | 2 +- .../GraphCMS/RowColumnTwo/RowColumnTwo.tsx | 2 +- .../RowColumnTwo/RowColumnTwoSpread.tsx | 2 +- .../GraphCMS/RowHeroBanner/RowHeroBanner.tsx | 2 +- .../components/GraphCMS/RowQuote/RowQuote.tsx | 2 +- .../RowServiceOptions/RowServiceOptions.tsx | 2 +- .../RowSpecialBanner/RowSpecialBanner.tsx | 2 +- .../components/GraphCMS/Usps/Usps.tsx | 2 +- .../components/GraphCMS/index.ts | 3 --- examples/magento-graphcms/package.json | 1 + .../queries/UniversalPage.graphql | 6 +++-- .../UniversalPage.graphqls} | 0 .../components}/RichText/RichText.tsx | 0 .../components}/RichText/defaultRenderers.tsx | 0 .../components}/RichText/defaultSxRenderer.ts | 0 .../components}/RichText/getNodeLength.tsx | 0 .../hygraph-ui/components}/RichText/index.ts | 0 .../hygraph-ui/components}/RichText/types.ts | 0 packages/hygraph-ui/components/index.ts | 3 +++ yarn.lock | 22 +++++++++++++++++++ 27 files changed, 45 insertions(+), 20 deletions(-) rename packages/content-areas/{schema.graphqls => schema/UniversalPage.graphqls} (100%) rename {examples/magento-graphcms/components/GraphCMS => packages/hygraph-ui/components}/RichText/RichText.tsx (100%) rename {examples/magento-graphcms/components/GraphCMS => packages/hygraph-ui/components}/RichText/defaultRenderers.tsx (100%) rename {examples/magento-graphcms/components/GraphCMS => packages/hygraph-ui/components}/RichText/defaultSxRenderer.ts (100%) rename {examples/magento-graphcms/components/GraphCMS => packages/hygraph-ui/components}/RichText/getNodeLength.tsx (100%) rename {examples/magento-graphcms/components/GraphCMS => packages/hygraph-ui/components}/RichText/index.ts (100%) rename {examples/magento-graphcms/components/GraphCMS => packages/hygraph-ui/components}/RichText/types.ts (100%) create mode 100644 packages/hygraph-ui/components/index.ts diff --git a/examples/magento-graphcms/components/GraphCMS/RowColumnOne/RowColumnOne.tsx b/examples/magento-graphcms/components/GraphCMS/RowColumnOne/RowColumnOne.tsx index 72d619bb619..738b143683e 100644 --- a/examples/magento-graphcms/components/GraphCMS/RowColumnOne/RowColumnOne.tsx +++ b/examples/magento-graphcms/components/GraphCMS/RowColumnOne/RowColumnOne.tsx @@ -1,4 +1,4 @@ -import { RichTextProps } from '../RichText' +import { RichTextProps } from '@graphcommerce/graphcms-ui' import type { RowColumnOneFragment } from './RowColumnOne.gql' import { Default, Message } from './variant' diff --git a/examples/magento-graphcms/components/GraphCMS/RowColumnOne/RowColumnOneBoxed.tsx b/examples/magento-graphcms/components/GraphCMS/RowColumnOne/RowColumnOneBoxed.tsx index acec494d734..70a383abc31 100644 --- a/examples/magento-graphcms/components/GraphCMS/RowColumnOne/RowColumnOneBoxed.tsx +++ b/examples/magento-graphcms/components/GraphCMS/RowColumnOne/RowColumnOneBoxed.tsx @@ -1,6 +1,6 @@ import { ColumnOneBoxed } from '@graphcommerce/next-ui' import { RowColumnOneProps } from './RowColumnOne' -import { RichText } from '../RichText' +import { RichText } from '@graphcommerce/graphcms-ui' export function RowColumnOneBoxed(props: RowColumnOneProps) { const { colOne, richTextOne } = props diff --git a/examples/magento-graphcms/components/GraphCMS/RowColumnOne/RowColumnOneCentered.tsx b/examples/magento-graphcms/components/GraphCMS/RowColumnOne/RowColumnOneCentered.tsx index 96a123d15bb..65eb5fd271a 100644 --- a/examples/magento-graphcms/components/GraphCMS/RowColumnOne/RowColumnOneCentered.tsx +++ b/examples/magento-graphcms/components/GraphCMS/RowColumnOne/RowColumnOneCentered.tsx @@ -1,6 +1,6 @@ import { ColumnOneCentered } from '@graphcommerce/next-ui' import { RowColumnOneProps } from './RowColumnOne' -import { RichText } from '../RichText' +import { RichText } from '@graphcommerce/graphcms-ui' export function RowColumnOneCentered(props: RowColumnOneProps) { const { colOne, richTextOne } = props diff --git a/examples/magento-graphcms/components/GraphCMS/RowColumnOne/RowColumnOneDoubleSpread.tsx b/examples/magento-graphcms/components/GraphCMS/RowColumnOne/RowColumnOneDoubleSpread.tsx index a1e27f7bdb1..bffd8502615 100644 --- a/examples/magento-graphcms/components/GraphCMS/RowColumnOne/RowColumnOneDoubleSpread.tsx +++ b/examples/magento-graphcms/components/GraphCMS/RowColumnOne/RowColumnOneDoubleSpread.tsx @@ -1,6 +1,6 @@ import { ColumnOne } from '@graphcommerce/next-ui' import { RowColumnOneFragment } from './RowColumnOne.gql' -import { RichText } from '../RichText' +import { RichText } from '@graphcommerce/graphcms-ui' type RowColumnOneDoubleSpreadProps = RowColumnOneFragment diff --git a/examples/magento-graphcms/components/GraphCMS/RowColumnOne/RowColumnOneSpread.tsx b/examples/magento-graphcms/components/GraphCMS/RowColumnOne/RowColumnOneSpread.tsx index 0571c50c759..c4a96ca362a 100644 --- a/examples/magento-graphcms/components/GraphCMS/RowColumnOne/RowColumnOneSpread.tsx +++ b/examples/magento-graphcms/components/GraphCMS/RowColumnOne/RowColumnOneSpread.tsx @@ -1,6 +1,6 @@ import { ColumnOne } from '@graphcommerce/next-ui' import { RowColumnOneFragment } from './RowColumnOne.gql' -import { RichText } from '../RichText' +import { RichText } from '@graphcommerce/graphcms-ui' export function RowColumnOneSpread(props: RowColumnOneFragment) { const { colOne } = props diff --git a/examples/magento-graphcms/components/GraphCMS/RowColumnOne/variant/Default.tsx b/examples/magento-graphcms/components/GraphCMS/RowColumnOne/variant/Default.tsx index e2876c50768..42545ecfd01 100644 --- a/examples/magento-graphcms/components/GraphCMS/RowColumnOne/variant/Default.tsx +++ b/examples/magento-graphcms/components/GraphCMS/RowColumnOne/variant/Default.tsx @@ -1,6 +1,6 @@ import { ColumnOne } from '@graphcommerce/next-ui' import type { RowColumnOneFragment } from '../RowColumnOne.gql' -import { RichTextProps, RichText } from '../../RichText' +import { RichText, RichTextProps } from '@graphcommerce/graphcms-ui' type RowColumnOneProps = RowColumnOneFragment & { richTextOne?: Omit diff --git a/examples/magento-graphcms/components/GraphCMS/RowColumnOne/variant/Message.tsx b/examples/magento-graphcms/components/GraphCMS/RowColumnOne/variant/Message.tsx index a9e823f5df0..32608e136cb 100644 --- a/examples/magento-graphcms/components/GraphCMS/RowColumnOne/variant/Message.tsx +++ b/examples/magento-graphcms/components/GraphCMS/RowColumnOne/variant/Message.tsx @@ -1,6 +1,6 @@ import { VariantMessage } from '@graphcommerce/next-ui' import type { RowColumnOneFragment } from '../RowColumnOne.gql' -import { RichTextProps, RichText } from '../../RichText' +import { RichText } from '@graphcommerce/graphcms-ui' type RowColumnOneProps = RowColumnOneFragment & { richTextOne?: Omit diff --git a/examples/magento-graphcms/components/GraphCMS/RowColumnThree/RowColumnThree.tsx b/examples/magento-graphcms/components/GraphCMS/RowColumnThree/RowColumnThree.tsx index 38ed584bced..919f89dd212 100644 --- a/examples/magento-graphcms/components/GraphCMS/RowColumnThree/RowColumnThree.tsx +++ b/examples/magento-graphcms/components/GraphCMS/RowColumnThree/RowColumnThree.tsx @@ -1,6 +1,6 @@ import { ColumnThree } from '@graphcommerce/next-ui' import { RowColumnThreeFragment } from './RowColumnThree.gql' -import { RichText } from '../RichText' +import { RichText } from '@graphcommerce/graphcms-ui' export function RowColumnThree(props: RowColumnThreeFragment) { const { colOne, colTwo, colThree } = props diff --git a/examples/magento-graphcms/components/GraphCMS/RowColumnTwo/RowColumnTwo.tsx b/examples/magento-graphcms/components/GraphCMS/RowColumnTwo/RowColumnTwo.tsx index 93b861a408e..eac55cfbef6 100644 --- a/examples/magento-graphcms/components/GraphCMS/RowColumnTwo/RowColumnTwo.tsx +++ b/examples/magento-graphcms/components/GraphCMS/RowColumnTwo/RowColumnTwo.tsx @@ -1,6 +1,6 @@ import { ColumnTwo } from '@graphcommerce/next-ui' import { RowColumnTwoFragment } from './RowColumnTwo.gql' -import { RichText } from '../RichText' +import { RichText } from '@graphcommerce/graphcms-ui' export function RowColumnTwo(props: RowColumnTwoFragment) { const { colOne, colTwo } = props diff --git a/examples/magento-graphcms/components/GraphCMS/RowColumnTwo/RowColumnTwoSpread.tsx b/examples/magento-graphcms/components/GraphCMS/RowColumnTwo/RowColumnTwoSpread.tsx index c1a64d2ab80..96890785730 100644 --- a/examples/magento-graphcms/components/GraphCMS/RowColumnTwo/RowColumnTwoSpread.tsx +++ b/examples/magento-graphcms/components/GraphCMS/RowColumnTwo/RowColumnTwoSpread.tsx @@ -1,5 +1,5 @@ import { ColumnTwoSpread } from '@graphcommerce/next-ui' -import { RichText } from '../RichText' +import { RichText } from '@graphcommerce/graphcms-ui' import { getNodeLength } from '../RichText/getNodeLength' import { ElementOrTextNode } from '../RichText/types' import { RowColumnTwoFragment } from './RowColumnTwo.gql' diff --git a/examples/magento-graphcms/components/GraphCMS/RowHeroBanner/RowHeroBanner.tsx b/examples/magento-graphcms/components/GraphCMS/RowHeroBanner/RowHeroBanner.tsx index 87d1d9ede22..9f54092e719 100644 --- a/examples/magento-graphcms/components/GraphCMS/RowHeroBanner/RowHeroBanner.tsx +++ b/examples/magento-graphcms/components/GraphCMS/RowHeroBanner/RowHeroBanner.tsx @@ -1,7 +1,7 @@ import { breakpointVal, HeroBanner } from '@graphcommerce/next-ui' import { Button } from '@mui/material' import { RowHeroBannerFragment } from './RowHeroBanner.gql' -import { RichText } from '../RichText' +import { RichText } from '@graphcommerce/graphcms-ui' export function RowHeroBanner(props: RowHeroBannerFragment) { const { copy, heroAsset, pageLinks } = props diff --git a/examples/magento-graphcms/components/GraphCMS/RowQuote/RowQuote.tsx b/examples/magento-graphcms/components/GraphCMS/RowQuote/RowQuote.tsx index a26bcf69f94..77de199bf53 100644 --- a/examples/magento-graphcms/components/GraphCMS/RowQuote/RowQuote.tsx +++ b/examples/magento-graphcms/components/GraphCMS/RowQuote/RowQuote.tsx @@ -1,6 +1,6 @@ import { Quote } from '@graphcommerce/next-ui' import React from 'react' -import { RichText } from '../RichText' +import { RichText } from '@graphcommerce/graphcms-ui' import { RowQuoteFragment } from './RowQuote.gql' type RowQuoteProps = RowQuoteFragment diff --git a/examples/magento-graphcms/components/GraphCMS/RowServiceOptions/RowServiceOptions.tsx b/examples/magento-graphcms/components/GraphCMS/RowServiceOptions/RowServiceOptions.tsx index 504c2c611d0..a7d4547739d 100644 --- a/examples/magento-graphcms/components/GraphCMS/RowServiceOptions/RowServiceOptions.tsx +++ b/examples/magento-graphcms/components/GraphCMS/RowServiceOptions/RowServiceOptions.tsx @@ -7,7 +7,7 @@ import { IconSvg, } from '@graphcommerce/next-ui' import { RowServiceOptionsFragment } from './RowServiceOptions.gql' -import { RichText } from '../RichText' +import { RichText } from '@graphcommerce/graphcms-ui' type RowServiceOptionsProps = RowServiceOptionsFragment diff --git a/examples/magento-graphcms/components/GraphCMS/RowSpecialBanner/RowSpecialBanner.tsx b/examples/magento-graphcms/components/GraphCMS/RowSpecialBanner/RowSpecialBanner.tsx index 884b4080b2e..b76bff5abaa 100644 --- a/examples/magento-graphcms/components/GraphCMS/RowSpecialBanner/RowSpecialBanner.tsx +++ b/examples/magento-graphcms/components/GraphCMS/RowSpecialBanner/RowSpecialBanner.tsx @@ -2,7 +2,7 @@ import { breakpointVal, SpecialBanner } from '@graphcommerce/next-ui' import { Link } from '@mui/material' import { RowSpecialBannerFragment } from './RowSpecialBanner.gql' import { Asset } from '../Asset/Asset' -import { RichText } from '../RichText' +import { RichText } from '@graphcommerce/graphcms-ui' type RowSpecialBannerProps = RowSpecialBannerFragment diff --git a/examples/magento-graphcms/components/GraphCMS/Usps/Usps.tsx b/examples/magento-graphcms/components/GraphCMS/Usps/Usps.tsx index 038c44669d5..c5f49a0dc4e 100644 --- a/examples/magento-graphcms/components/GraphCMS/Usps/Usps.tsx +++ b/examples/magento-graphcms/components/GraphCMS/Usps/Usps.tsx @@ -1,6 +1,6 @@ import { UspList, UspListItem, UspListProps } from '@graphcommerce/next-ui' import { Asset } from '../Asset/Asset' -import { RichText } from '../RichText' +import { RichText } from '@graphcommerce/graphcms-ui' import { UspsQueryFragment } from './UspsQueryFragment.gql' export type ProductUspsProps = UspsQueryFragment & Pick diff --git a/examples/magento-graphcms/components/GraphCMS/index.ts b/examples/magento-graphcms/components/GraphCMS/index.ts index 3201a9e1413..925e70dccdf 100644 --- a/examples/magento-graphcms/components/GraphCMS/index.ts +++ b/examples/magento-graphcms/components/GraphCMS/index.ts @@ -1,6 +1,3 @@ -export * from './RichText' -export * from './Asset/Asset' - export * from './RowProduct/RowProduct' // The actual renderer diff --git a/examples/magento-graphcms/package.json b/examples/magento-graphcms/package.json index 85c8181bc53..d5436deed4a 100644 --- a/examples/magento-graphcms/package.json +++ b/examples/magento-graphcms/package.json @@ -23,6 +23,7 @@ "@apollo/client": "~3.10.8", "@ducanh2912/next-pwa": "9.7.2", "@graphcommerce/cli": "9.0.0-canary.62", + "@graphcommerce/content-areas": "9.0.0-canary.62", "@graphcommerce/demo-magento-graphcommerce": "9.0.0-canary.62", "@graphcommerce/ecommerce-ui": "9.0.0-canary.62", "@graphcommerce/framer-next-pages": "9.0.0-canary.62", diff --git a/packages/content-areas/queries/UniversalPage.graphql b/packages/content-areas/queries/UniversalPage.graphql index 8f6b39c733e..19b2c1a12b7 100644 --- a/packages/content-areas/queries/UniversalPage.graphql +++ b/packages/content-areas/queries/UniversalPage.graphql @@ -1,5 +1,7 @@ query UniversalPage($input: UniversalPageInput!) { - pageContent(input: $input) { - ...UniversalPage_Data + common { + pageContent(input: $input) { + ...UniversalPage_Data + } } } diff --git a/packages/content-areas/schema.graphqls b/packages/content-areas/schema/UniversalPage.graphqls similarity index 100% rename from packages/content-areas/schema.graphqls rename to packages/content-areas/schema/UniversalPage.graphqls diff --git a/examples/magento-graphcms/components/GraphCMS/RichText/RichText.tsx b/packages/hygraph-ui/components/RichText/RichText.tsx similarity index 100% rename from examples/magento-graphcms/components/GraphCMS/RichText/RichText.tsx rename to packages/hygraph-ui/components/RichText/RichText.tsx diff --git a/examples/magento-graphcms/components/GraphCMS/RichText/defaultRenderers.tsx b/packages/hygraph-ui/components/RichText/defaultRenderers.tsx similarity index 100% rename from examples/magento-graphcms/components/GraphCMS/RichText/defaultRenderers.tsx rename to packages/hygraph-ui/components/RichText/defaultRenderers.tsx diff --git a/examples/magento-graphcms/components/GraphCMS/RichText/defaultSxRenderer.ts b/packages/hygraph-ui/components/RichText/defaultSxRenderer.ts similarity index 100% rename from examples/magento-graphcms/components/GraphCMS/RichText/defaultSxRenderer.ts rename to packages/hygraph-ui/components/RichText/defaultSxRenderer.ts diff --git a/examples/magento-graphcms/components/GraphCMS/RichText/getNodeLength.tsx b/packages/hygraph-ui/components/RichText/getNodeLength.tsx similarity index 100% rename from examples/magento-graphcms/components/GraphCMS/RichText/getNodeLength.tsx rename to packages/hygraph-ui/components/RichText/getNodeLength.tsx diff --git a/examples/magento-graphcms/components/GraphCMS/RichText/index.ts b/packages/hygraph-ui/components/RichText/index.ts similarity index 100% rename from examples/magento-graphcms/components/GraphCMS/RichText/index.ts rename to packages/hygraph-ui/components/RichText/index.ts diff --git a/examples/magento-graphcms/components/GraphCMS/RichText/types.ts b/packages/hygraph-ui/components/RichText/types.ts similarity index 100% rename from examples/magento-graphcms/components/GraphCMS/RichText/types.ts rename to packages/hygraph-ui/components/RichText/types.ts diff --git a/packages/hygraph-ui/components/index.ts b/packages/hygraph-ui/components/index.ts new file mode 100644 index 00000000000..f7a6dc99a8e --- /dev/null +++ b/packages/hygraph-ui/components/index.ts @@ -0,0 +1,3 @@ +export * from './Asset/Asset' +export * from './Asset/Asset.gql' +export * from './RichText/index' diff --git a/yarn.lock b/yarn.lock index 4e022b1c6ca..8869eb6e1e3 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2933,6 +2933,28 @@ __metadata: languageName: unknown linkType: soft +"@graphcommerce/content-areas@workspace:packages/content-areas": + version: 0.0.0-use.local + resolution: "@graphcommerce/content-areas@workspace:packages/content-areas" + peerDependencies: + "@graphcommerce/eslint-config-pwa": ^8.0.0-canary.95 + "@graphcommerce/graphql": ^8.0.0-canary.95 + "@graphcommerce/magento-product": ^8.0.0-canary.95 + "@graphcommerce/next-ui": ^8.0.0-canary.95 + "@graphcommerce/prettier-config-pwa": ^8.0.0-canary.95 + "@graphcommerce/react-hook-form": ^8.0.0-canary.95 + "@graphcommerce/typescript-config-pwa": ^8.0.0-canary.95 + "@lingui/core": ^4.2.1 + "@lingui/macro": ^4.2.1 + "@lingui/react": ^4.2.1 + "@mui/material": ^5.10.16 + framer-motion: ^10.0.0 + next: "*" + react: ^18.2.0 + react-dom: ^18.2.0 + languageName: unknown + linkType: soft + "@graphcommerce/demo-magento-graphcommerce@npm:9.0.0-canary.62, @graphcommerce/demo-magento-graphcommerce@workspace:packages/demo-magento-graphcommerce": version: 0.0.0-use.local resolution: "@graphcommerce/demo-magento-graphcommerce@workspace:packages/demo-magento-graphcommerce" From 1f9c69dc1518251c3dfd2a22d61cc12e54f1edcc Mon Sep 17 00:00:00 2001 From: Paul Hachmang Date: Mon, 22 Jul 2024 14:03:16 +0200 Subject: [PATCH 14/33] Move imports --- .../components/GraphCMS/RowColumnOne/RowColumnOneBoxed.tsx | 2 +- .../components/GraphCMS/RowColumnOne/RowColumnOneCentered.tsx | 2 +- .../GraphCMS/RowColumnOne/RowColumnOneDoubleSpread.tsx | 2 +- .../components/GraphCMS/RowColumnOne/RowColumnOneSpread.tsx | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/magento-graphcms/components/GraphCMS/RowColumnOne/RowColumnOneBoxed.tsx b/examples/magento-graphcms/components/GraphCMS/RowColumnOne/RowColumnOneBoxed.tsx index 70a383abc31..8805fb51c96 100644 --- a/examples/magento-graphcms/components/GraphCMS/RowColumnOne/RowColumnOneBoxed.tsx +++ b/examples/magento-graphcms/components/GraphCMS/RowColumnOne/RowColumnOneBoxed.tsx @@ -1,6 +1,6 @@ +import { RichText } from '@graphcommerce/graphcms-ui' import { ColumnOneBoxed } from '@graphcommerce/next-ui' import { RowColumnOneProps } from './RowColumnOne' -import { RichText } from '@graphcommerce/graphcms-ui' export function RowColumnOneBoxed(props: RowColumnOneProps) { const { colOne, richTextOne } = props diff --git a/examples/magento-graphcms/components/GraphCMS/RowColumnOne/RowColumnOneCentered.tsx b/examples/magento-graphcms/components/GraphCMS/RowColumnOne/RowColumnOneCentered.tsx index 65eb5fd271a..5f8342af2e3 100644 --- a/examples/magento-graphcms/components/GraphCMS/RowColumnOne/RowColumnOneCentered.tsx +++ b/examples/magento-graphcms/components/GraphCMS/RowColumnOne/RowColumnOneCentered.tsx @@ -1,6 +1,6 @@ +import { RichText } from '@graphcommerce/graphcms-ui' import { ColumnOneCentered } from '@graphcommerce/next-ui' import { RowColumnOneProps } from './RowColumnOne' -import { RichText } from '@graphcommerce/graphcms-ui' export function RowColumnOneCentered(props: RowColumnOneProps) { const { colOne, richTextOne } = props diff --git a/examples/magento-graphcms/components/GraphCMS/RowColumnOne/RowColumnOneDoubleSpread.tsx b/examples/magento-graphcms/components/GraphCMS/RowColumnOne/RowColumnOneDoubleSpread.tsx index bffd8502615..14426d0beac 100644 --- a/examples/magento-graphcms/components/GraphCMS/RowColumnOne/RowColumnOneDoubleSpread.tsx +++ b/examples/magento-graphcms/components/GraphCMS/RowColumnOne/RowColumnOneDoubleSpread.tsx @@ -1,6 +1,6 @@ +import { RichText } from '@graphcommerce/graphcms-ui' import { ColumnOne } from '@graphcommerce/next-ui' import { RowColumnOneFragment } from './RowColumnOne.gql' -import { RichText } from '@graphcommerce/graphcms-ui' type RowColumnOneDoubleSpreadProps = RowColumnOneFragment diff --git a/examples/magento-graphcms/components/GraphCMS/RowColumnOne/RowColumnOneSpread.tsx b/examples/magento-graphcms/components/GraphCMS/RowColumnOne/RowColumnOneSpread.tsx index c4a96ca362a..e27b553d6e6 100644 --- a/examples/magento-graphcms/components/GraphCMS/RowColumnOne/RowColumnOneSpread.tsx +++ b/examples/magento-graphcms/components/GraphCMS/RowColumnOne/RowColumnOneSpread.tsx @@ -1,6 +1,6 @@ +import { RichText } from '@graphcommerce/graphcms-ui' import { ColumnOne } from '@graphcommerce/next-ui' import { RowColumnOneFragment } from './RowColumnOne.gql' -import { RichText } from '@graphcommerce/graphcms-ui' export function RowColumnOneSpread(props: RowColumnOneFragment) { const { colOne } = props From 5cdfbe0521da69c825428c5f21a8f5ededd02b87 Mon Sep 17 00:00:00 2001 From: Paul Hachmang Date: Mon, 22 Jul 2024 14:07:58 +0200 Subject: [PATCH 15/33] Move imports around to reduce diff --- .../components/GraphCMS/RowColumnOne/variant/Default.tsx | 2 +- .../components/GraphCMS/RowColumnOne/variant/Message.tsx | 2 +- .../components/GraphCMS/RowColumnThree/RowColumnThree.tsx | 2 +- .../components/GraphCMS/RowColumnTwo/RowColumnTwo.tsx | 2 +- .../GraphCMS/RowColumnTwo/RowColumnTwoSpread.tsx | 5 ++--- .../components/GraphCMS/RowHeroBanner/RowHeroBanner.tsx | 2 +- .../components/GraphCMS/RowProduct/RowProduct.tsx | 7 +++++-- .../components/GraphCMS/RowQuote/RowQuote.tsx | 3 +-- .../GraphCMS/RowServiceOptions/RowServiceOptions.tsx | 2 +- .../GraphCMS/RowSpecialBanner/RowSpecialBanner.tsx | 3 +-- .../magento-graphcms/components/GraphCMS/Usps/Usps.tsx | 3 +-- 11 files changed, 16 insertions(+), 17 deletions(-) diff --git a/examples/magento-graphcms/components/GraphCMS/RowColumnOne/variant/Default.tsx b/examples/magento-graphcms/components/GraphCMS/RowColumnOne/variant/Default.tsx index 42545ecfd01..36d419506ba 100644 --- a/examples/magento-graphcms/components/GraphCMS/RowColumnOne/variant/Default.tsx +++ b/examples/magento-graphcms/components/GraphCMS/RowColumnOne/variant/Default.tsx @@ -1,6 +1,6 @@ +import { RichText, RichTextProps } from '@graphcommerce/graphcms-ui' import { ColumnOne } from '@graphcommerce/next-ui' import type { RowColumnOneFragment } from '../RowColumnOne.gql' -import { RichText, RichTextProps } from '@graphcommerce/graphcms-ui' type RowColumnOneProps = RowColumnOneFragment & { richTextOne?: Omit diff --git a/examples/magento-graphcms/components/GraphCMS/RowColumnOne/variant/Message.tsx b/examples/magento-graphcms/components/GraphCMS/RowColumnOne/variant/Message.tsx index 32608e136cb..4d03327457c 100644 --- a/examples/magento-graphcms/components/GraphCMS/RowColumnOne/variant/Message.tsx +++ b/examples/magento-graphcms/components/GraphCMS/RowColumnOne/variant/Message.tsx @@ -1,6 +1,6 @@ +import { RichText, RichTextProps } from '@graphcommerce/graphcms-ui' import { VariantMessage } from '@graphcommerce/next-ui' import type { RowColumnOneFragment } from '../RowColumnOne.gql' -import { RichText } from '@graphcommerce/graphcms-ui' type RowColumnOneProps = RowColumnOneFragment & { richTextOne?: Omit diff --git a/examples/magento-graphcms/components/GraphCMS/RowColumnThree/RowColumnThree.tsx b/examples/magento-graphcms/components/GraphCMS/RowColumnThree/RowColumnThree.tsx index 919f89dd212..898cd46e2f9 100644 --- a/examples/magento-graphcms/components/GraphCMS/RowColumnThree/RowColumnThree.tsx +++ b/examples/magento-graphcms/components/GraphCMS/RowColumnThree/RowColumnThree.tsx @@ -1,6 +1,6 @@ +import { RichText } from '@graphcommerce/graphcms-ui' import { ColumnThree } from '@graphcommerce/next-ui' import { RowColumnThreeFragment } from './RowColumnThree.gql' -import { RichText } from '@graphcommerce/graphcms-ui' export function RowColumnThree(props: RowColumnThreeFragment) { const { colOne, colTwo, colThree } = props diff --git a/examples/magento-graphcms/components/GraphCMS/RowColumnTwo/RowColumnTwo.tsx b/examples/magento-graphcms/components/GraphCMS/RowColumnTwo/RowColumnTwo.tsx index eac55cfbef6..cafb4eabf13 100644 --- a/examples/magento-graphcms/components/GraphCMS/RowColumnTwo/RowColumnTwo.tsx +++ b/examples/magento-graphcms/components/GraphCMS/RowColumnTwo/RowColumnTwo.tsx @@ -1,6 +1,6 @@ +import { RichText } from '@graphcommerce/graphcms-ui' import { ColumnTwo } from '@graphcommerce/next-ui' import { RowColumnTwoFragment } from './RowColumnTwo.gql' -import { RichText } from '@graphcommerce/graphcms-ui' export function RowColumnTwo(props: RowColumnTwoFragment) { const { colOne, colTwo } = props diff --git a/examples/magento-graphcms/components/GraphCMS/RowColumnTwo/RowColumnTwoSpread.tsx b/examples/magento-graphcms/components/GraphCMS/RowColumnTwo/RowColumnTwoSpread.tsx index 96890785730..8293653ee8f 100644 --- a/examples/magento-graphcms/components/GraphCMS/RowColumnTwo/RowColumnTwoSpread.tsx +++ b/examples/magento-graphcms/components/GraphCMS/RowColumnTwo/RowColumnTwoSpread.tsx @@ -1,7 +1,6 @@ +import { getNodeLength, RichText } from '@graphcommerce/graphcms-ui' +import { ElementOrTextNode } from '@graphcommerce/graphcms-ui/components/RichText/types' import { ColumnTwoSpread } from '@graphcommerce/next-ui' -import { RichText } from '@graphcommerce/graphcms-ui' -import { getNodeLength } from '../RichText/getNodeLength' -import { ElementOrTextNode } from '../RichText/types' import { RowColumnTwoFragment } from './RowColumnTwo.gql' const getColumnCount = (props: RowColumnTwoFragment, columnId: number) => { diff --git a/examples/magento-graphcms/components/GraphCMS/RowHeroBanner/RowHeroBanner.tsx b/examples/magento-graphcms/components/GraphCMS/RowHeroBanner/RowHeroBanner.tsx index 9f54092e719..ce590c163d2 100644 --- a/examples/magento-graphcms/components/GraphCMS/RowHeroBanner/RowHeroBanner.tsx +++ b/examples/magento-graphcms/components/GraphCMS/RowHeroBanner/RowHeroBanner.tsx @@ -1,7 +1,7 @@ +import { RichText } from '@graphcommerce/graphcms-ui' import { breakpointVal, HeroBanner } from '@graphcommerce/next-ui' import { Button } from '@mui/material' import { RowHeroBannerFragment } from './RowHeroBanner.gql' -import { RichText } from '@graphcommerce/graphcms-ui' export function RowHeroBanner(props: RowHeroBannerFragment) { const { copy, heroAsset, pageLinks } = props diff --git a/examples/magento-graphcms/components/GraphCMS/RowProduct/RowProduct.tsx b/examples/magento-graphcms/components/GraphCMS/RowProduct/RowProduct.tsx index ad0850f8831..0489ba6ac64 100644 --- a/examples/magento-graphcms/components/GraphCMS/RowProduct/RowProduct.tsx +++ b/examples/magento-graphcms/components/GraphCMS/RowProduct/RowProduct.tsx @@ -1,6 +1,9 @@ -import { ProductListItemRenderer } from '@graphcommerce/magento-product' import { InContextMaskProvider, useInContextQuery } from '@graphcommerce/graphql' -import { ProductListDocument, ProductListItemsFragment } from '@graphcommerce/magento-product' +import { + ProductListItemRenderer, + ProductListDocument, + ProductListItemsFragment, +} from '@graphcommerce/magento-product' import { ProductSpecsFragment } from '@graphcommerce/magento-product/components/ProductSpecs/ProductSpecs.gql' import { filterNonNullableKeys } from '@graphcommerce/next-ui' import { RowProductFragment } from './RowProduct.gql' diff --git a/examples/magento-graphcms/components/GraphCMS/RowQuote/RowQuote.tsx b/examples/magento-graphcms/components/GraphCMS/RowQuote/RowQuote.tsx index 77de199bf53..81e01dfb727 100644 --- a/examples/magento-graphcms/components/GraphCMS/RowQuote/RowQuote.tsx +++ b/examples/magento-graphcms/components/GraphCMS/RowQuote/RowQuote.tsx @@ -1,6 +1,5 @@ -import { Quote } from '@graphcommerce/next-ui' -import React from 'react' import { RichText } from '@graphcommerce/graphcms-ui' +import { Quote } from '@graphcommerce/next-ui' import { RowQuoteFragment } from './RowQuote.gql' type RowQuoteProps = RowQuoteFragment diff --git a/examples/magento-graphcms/components/GraphCMS/RowServiceOptions/RowServiceOptions.tsx b/examples/magento-graphcms/components/GraphCMS/RowServiceOptions/RowServiceOptions.tsx index a7d4547739d..cade4920302 100644 --- a/examples/magento-graphcms/components/GraphCMS/RowServiceOptions/RowServiceOptions.tsx +++ b/examples/magento-graphcms/components/GraphCMS/RowServiceOptions/RowServiceOptions.tsx @@ -1,3 +1,4 @@ +import { RichText } from '@graphcommerce/graphcms-ui' import { IconBlock, IconBlocks, @@ -7,7 +8,6 @@ import { IconSvg, } from '@graphcommerce/next-ui' import { RowServiceOptionsFragment } from './RowServiceOptions.gql' -import { RichText } from '@graphcommerce/graphcms-ui' type RowServiceOptionsProps = RowServiceOptionsFragment diff --git a/examples/magento-graphcms/components/GraphCMS/RowSpecialBanner/RowSpecialBanner.tsx b/examples/magento-graphcms/components/GraphCMS/RowSpecialBanner/RowSpecialBanner.tsx index b76bff5abaa..b2e97fec07d 100644 --- a/examples/magento-graphcms/components/GraphCMS/RowSpecialBanner/RowSpecialBanner.tsx +++ b/examples/magento-graphcms/components/GraphCMS/RowSpecialBanner/RowSpecialBanner.tsx @@ -1,8 +1,7 @@ +import { Asset, RichText } from '@graphcommerce/graphcms-ui' import { breakpointVal, SpecialBanner } from '@graphcommerce/next-ui' import { Link } from '@mui/material' import { RowSpecialBannerFragment } from './RowSpecialBanner.gql' -import { Asset } from '../Asset/Asset' -import { RichText } from '@graphcommerce/graphcms-ui' type RowSpecialBannerProps = RowSpecialBannerFragment diff --git a/examples/magento-graphcms/components/GraphCMS/Usps/Usps.tsx b/examples/magento-graphcms/components/GraphCMS/Usps/Usps.tsx index c5f49a0dc4e..7379f3b6462 100644 --- a/examples/magento-graphcms/components/GraphCMS/Usps/Usps.tsx +++ b/examples/magento-graphcms/components/GraphCMS/Usps/Usps.tsx @@ -1,6 +1,5 @@ +import { Asset, RichText } from '@graphcommerce/graphcms-ui' import { UspList, UspListItem, UspListProps } from '@graphcommerce/next-ui' -import { Asset } from '../Asset/Asset' -import { RichText } from '@graphcommerce/graphcms-ui' import { UspsQueryFragment } from './UspsQueryFragment.gql' export type ProductUspsProps = UspsQueryFragment & Pick From 868692b211d09636166c04b1f4a3a07868501bef Mon Sep 17 00:00:00 2001 From: Paul Hachmang Date: Tue, 23 Jul 2024 09:25:53 +0200 Subject: [PATCH 16/33] Refactor --- .../GraphCMS/ExtendRowRenderer.graphql | 5 -- .../RowLinks/variant/ImageLabelSwiper.tsx | 3 +- .../GraphCMS/RowLinks/variant/LogoSwiper.tsx | 2 +- .../GraphCMS/RowLinks/variant/Usps.tsx | 3 +- .../GraphCMS/RowProduct/RowProduct.graphql | 1 + .../GraphCMS/RowProduct/RowProduct.tsx | 27 ++------ .../GraphCMS/RowProduct/variant/Backstory.tsx | 3 +- .../GraphCMS/RowProduct/variant/Feature.tsx | 5 +- .../RowProduct/variant/FeatureBoxed.tsx | 4 +- .../components/GraphCMS/RowRenderer.tsx | 4 +- .../{GraphCMS => }/Usps/Usps.graphql | 0 .../components/{GraphCMS => }/Usps/Usps.tsx | 0 .../Usps/UspsQueryFragment.graphql | 0 examples/magento-graphcms/pages/[...url].tsx | 11 ++-- examples/magento-graphcms/pages/index.tsx | 18 ++---- .../plugins/ExtendRowRenderer.tsx | 22 ------- .../plugins/hygraph/HygraphContentArea.tsx | 20 ++++++ packages/cli/dist/bin/mesh.js | 14 ---- packages/cli/src/bin/mesh.ts | 17 ----- .../components/ContentArea/ContentArea.tsx | 9 +-- packages/content-areas/index.ts | 5 +- packages/content-areas/package.json | 17 ++--- packages/content-areas/queries/GcPage.graphql | 5 ++ .../content-areas/queries/GcPage_Data.graphql | 9 +++ .../queries/UniversalPage.graphql | 7 -- .../queries/UniversalPage_Data.graphql | 7 -- .../schema/Query_gcPage.graphqls | 27 ++++++++ .../schema/UniversalPage.graphqls | 28 -------- packages/content-areas/server.ts | 1 + packages/hygraph-ui/components/index.ts | 3 +- .../hygraph-ui/graphql/GCPage_Hygraph.graphql | 3 + .../hygraph-ui/graphql/HygraphPages.graphql | 7 -- .../graphql/UniversalPage_Hygraph.graphql | 5 -- packages/hygraph-ui/graphql/index.ts | 2 +- packages/hygraph-ui/mesh.ts | 64 ------------------- packages/hygraph-ui/mesh/resolvers.ts | 51 +++++++++++++++ .../hygraph-ui/plugins/HygraphContentArea.tsx | 26 -------- .../hygraph-ui/plugins/meshConfigHygraph.ts | 23 +++++++ packages/hygraph-ui/schema.graphqls | 39 ----------- .../hygraph-ui/schema/Query_gcPage.graphqls | 19 ++++++ .../schema/RowProduct_category.graphqls | 11 ++++ packages/hygraph-ui/types.ts | 14 ---- packagesDev/next-config/src/index.ts | 2 +- yarn.lock | 18 +++--- 44 files changed, 225 insertions(+), 336 deletions(-) delete mode 100644 examples/magento-graphcms/components/GraphCMS/ExtendRowRenderer.graphql rename examples/magento-graphcms/components/{GraphCMS => }/Usps/Usps.graphql (100%) rename examples/magento-graphcms/components/{GraphCMS => }/Usps/Usps.tsx (100%) rename examples/magento-graphcms/components/{GraphCMS => }/Usps/UspsQueryFragment.graphql (100%) delete mode 100644 examples/magento-graphcms/plugins/ExtendRowRenderer.tsx create mode 100644 examples/magento-graphcms/plugins/hygraph/HygraphContentArea.tsx create mode 100644 packages/content-areas/queries/GcPage.graphql create mode 100644 packages/content-areas/queries/GcPage_Data.graphql delete mode 100644 packages/content-areas/queries/UniversalPage.graphql delete mode 100644 packages/content-areas/queries/UniversalPage_Data.graphql create mode 100644 packages/content-areas/schema/Query_gcPage.graphqls delete mode 100644 packages/content-areas/schema/UniversalPage.graphqls create mode 100644 packages/content-areas/server.ts create mode 100644 packages/hygraph-ui/graphql/GCPage_Hygraph.graphql delete mode 100644 packages/hygraph-ui/graphql/HygraphPages.graphql delete mode 100644 packages/hygraph-ui/graphql/UniversalPage_Hygraph.graphql delete mode 100644 packages/hygraph-ui/mesh.ts create mode 100644 packages/hygraph-ui/mesh/resolvers.ts delete mode 100644 packages/hygraph-ui/plugins/HygraphContentArea.tsx create mode 100644 packages/hygraph-ui/plugins/meshConfigHygraph.ts delete mode 100644 packages/hygraph-ui/schema.graphqls create mode 100644 packages/hygraph-ui/schema/Query_gcPage.graphqls create mode 100644 packages/hygraph-ui/schema/RowProduct_category.graphqls delete mode 100644 packages/hygraph-ui/types.ts diff --git a/examples/magento-graphcms/components/GraphCMS/ExtendRowRenderer.graphql b/examples/magento-graphcms/components/GraphCMS/ExtendRowRenderer.graphql deleted file mode 100644 index 899a4014be1..00000000000 --- a/examples/magento-graphcms/components/GraphCMS/ExtendRowRenderer.graphql +++ /dev/null @@ -1,5 +0,0 @@ -# fragment ExtendRowRenderer on Page @inject(into: ["HygraphPage"]) { -# content { -# ...CustomRow -# } -# } diff --git a/examples/magento-graphcms/components/GraphCMS/RowLinks/variant/ImageLabelSwiper.tsx b/examples/magento-graphcms/components/GraphCMS/RowLinks/variant/ImageLabelSwiper.tsx index a16dbd7f3f4..9447f6a5373 100644 --- a/examples/magento-graphcms/components/GraphCMS/RowLinks/variant/ImageLabelSwiper.tsx +++ b/examples/magento-graphcms/components/GraphCMS/RowLinks/variant/ImageLabelSwiper.tsx @@ -1,8 +1,7 @@ +import { Asset, RichText } from '@graphcommerce/graphcms-ui' import { responsiveVal, VariantImageLabelSwiper } from '@graphcommerce/next-ui' import { Box, ButtonBase, Typography } from '@mui/material' import { RowLinksFragment } from '../RowLinks.gql' -import { Asset } from '../../Asset/Asset' -import { RichText } from '../../RichText' export function ImageLabelSwiper(props: RowLinksFragment) { const { title, rowLinksCopy, pageLinks } = props diff --git a/examples/magento-graphcms/components/GraphCMS/RowLinks/variant/LogoSwiper.tsx b/examples/magento-graphcms/components/GraphCMS/RowLinks/variant/LogoSwiper.tsx index ba1a1953050..1b87a158a9b 100644 --- a/examples/magento-graphcms/components/GraphCMS/RowLinks/variant/LogoSwiper.tsx +++ b/examples/magento-graphcms/components/GraphCMS/RowLinks/variant/LogoSwiper.tsx @@ -1,7 +1,7 @@ +import { Asset } from '@graphcommerce/graphcms-ui' import { VariantLogoSwiper } from '@graphcommerce/next-ui' import { Link } from '@mui/material' import { RowLinksFragment } from '../RowLinks.gql' -import { Asset } from '../../Asset/Asset' export function LogoSwiper(props: RowLinksFragment) { const { title, pageLinks } = props diff --git a/examples/magento-graphcms/components/GraphCMS/RowLinks/variant/Usps.tsx b/examples/magento-graphcms/components/GraphCMS/RowLinks/variant/Usps.tsx index 7fc6ac33c87..7cc5520c749 100644 --- a/examples/magento-graphcms/components/GraphCMS/RowLinks/variant/Usps.tsx +++ b/examples/magento-graphcms/components/GraphCMS/RowLinks/variant/Usps.tsx @@ -1,8 +1,7 @@ +import { RichText } from '@graphcommerce/graphcms-ui' import { iconCheckmark, IconSvg, VariantUsps } from '@graphcommerce/next-ui' import { Box } from '@mui/material' - import { RowLinksFragment } from '../RowLinks.gql' -import { RichText } from '../../RichText' export function Usps(props: RowLinksFragment) { const { title, pageLinks } = props diff --git a/examples/magento-graphcms/components/GraphCMS/RowProduct/RowProduct.graphql b/examples/magento-graphcms/components/GraphCMS/RowProduct/RowProduct.graphql index bca10ed90cb..250c209cdab 100644 --- a/examples/magento-graphcms/components/GraphCMS/RowProduct/RowProduct.graphql +++ b/examples/magento-graphcms/components/GraphCMS/RowProduct/RowProduct.graphql @@ -14,6 +14,7 @@ fragment RowProduct on RowProduct { category { uid + name products { items { __typename diff --git a/examples/magento-graphcms/components/GraphCMS/RowProduct/RowProduct.tsx b/examples/magento-graphcms/components/GraphCMS/RowProduct/RowProduct.tsx index 0489ba6ac64..dc9c5f1a3c4 100644 --- a/examples/magento-graphcms/components/GraphCMS/RowProduct/RowProduct.tsx +++ b/examples/magento-graphcms/components/GraphCMS/RowProduct/RowProduct.tsx @@ -1,10 +1,5 @@ import { InContextMaskProvider, useInContextQuery } from '@graphcommerce/graphql' -import { - ProductListItemRenderer, - ProductListDocument, - ProductListItemsFragment, -} from '@graphcommerce/magento-product' -import { ProductSpecsFragment } from '@graphcommerce/magento-product/components/ProductSpecs/ProductSpecs.gql' +import { ProductListItemRenderer, ProductListDocument } from '@graphcommerce/magento-product' import { filterNonNullableKeys } from '@graphcommerce/next-ui' import { RowProductFragment } from './RowProduct.gql' import { @@ -21,16 +16,13 @@ import { type VariantRenderer = Record< NonNullable, - React.FC< - RowProductFragment & - ProductListItemsFragment & { productListItemRenderer: ProductListItemRenderer } - > + React.FC > type RowProductProps = RowProductFragment & { renderer?: Partial productListItemRenderer: ProductListItemRenderer -} & ProductSpecsFragment & { sku?: string | null | undefined } & ProductListItemsFragment +} & { sku?: string | null | undefined } const defaultRenderer: Partial = { Specs, @@ -45,24 +37,17 @@ const defaultRenderer: Partial = { } export function RowProduct(props: RowProductProps) { - const { renderer, productListItemRenderer, items, ...rest } = props + const { renderer, productListItemRenderer, category, ...rest } = props let { variant } = props const mergedRenderer = { ...defaultRenderer, ...renderer } as VariantRenderer - const urlKeys = filterNonNullableKeys(items).map((item) => item.url_key) + const urlKeys = filterNonNullableKeys(category?.products?.items).map((item) => item.url_key) const scoped = useInContextQuery( ProductListDocument, { variables: { onlyItems: true, filters: { url_key: { in: urlKeys } } } }, - { products: { items } }, + { products: { items: category?.products?.items } }, ) - const { products } = scoped.data - const urlKeys = filterNonNullableKeys(items).map((item) => item.url_key) - const scoped = useInContextQuery( - ProductListDocument, - { variables: { onlyItems: true, filters: { url_key: { in: urlKeys } } } }, - { products: { items } }, - ) const { products } = scoped.data if (!variant) variant = 'Related' diff --git a/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Backstory.tsx b/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Backstory.tsx index 331f4bd298a..138d4b9adc9 100644 --- a/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Backstory.tsx +++ b/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Backstory.tsx @@ -1,8 +1,7 @@ +import { Asset, RichText } from '@graphcommerce/graphcms-ui' import { AddProductsToCartForm, ProductListItemRenderer } from '@graphcommerce/magento-product' import { ParagraphWithSidebarSlide, RenderType } from '@graphcommerce/next-ui' import { useTheme } from '@mui/material' -import { Asset } from '../../Asset/Asset' -import { RichText } from '../../RichText' import { RowProductFragment } from '../RowProduct.gql' type BackstoryProps = RowProductFragment & { productListItemRenderer: ProductListItemRenderer } diff --git a/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Feature.tsx b/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Feature.tsx index 3dd55fc845e..4ca09a2d12f 100644 --- a/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Feature.tsx +++ b/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Feature.tsx @@ -1,10 +1,9 @@ +import { RichText } from '@graphcommerce/graphcms-ui' import { Image } from '@graphcommerce/image' +import { ProductListItemRenderer } from '@graphcommerce/magento-product' import { ImageText } from '@graphcommerce/next-ui' import { Typography, useTheme } from '@mui/material' import { RowProductFragment } from '../RowProduct.gql' -import { ProductFeatureMediaFragment } from './ProductFeatureMedia.gql' -import { RichText } from '../../RichText' -import { ProductListItemRenderer } from '@graphcommerce/magento-product' type FeatureProps = RowProductFragment & { productListItemRenderer: ProductListItemRenderer } diff --git a/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/FeatureBoxed.tsx b/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/FeatureBoxed.tsx index ee616ecb67b..2c984c0d9c6 100644 --- a/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/FeatureBoxed.tsx +++ b/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/FeatureBoxed.tsx @@ -1,10 +1,10 @@ import { Image } from '@graphcommerce/image' +import { ProductListItemRenderer } from '@graphcommerce/magento-product' import { ImageTextBoxed, responsiveVal } from '@graphcommerce/next-ui' import { Typography, useTheme } from '@mui/material' import { RowProductFragment } from '../RowProduct.gql' import { ProductFeatureMediaBoxedFragment } from './ProductFeatureMediaBoxed.gql' -import { RichText } from '../../RichText' -import { ProductListItemRenderer } from '@graphcommerce/magento-product' +import { RichText } from '@graphcommerce/graphcms-ui' type FeatureBoxedProps = RowProductFragment & ProductFeatureMediaBoxedFragment & { productListItemRenderer: ProductListItemRenderer } diff --git a/examples/magento-graphcms/components/GraphCMS/RowRenderer.tsx b/examples/magento-graphcms/components/GraphCMS/RowRenderer.tsx index de213883bf5..de3931572f8 100644 --- a/examples/magento-graphcms/components/GraphCMS/RowRenderer.tsx +++ b/examples/magento-graphcms/components/GraphCMS/RowRenderer.tsx @@ -1,8 +1,8 @@ +import { GCPage_DataFragment } from '@graphcommerce/content-areas' import { ProductListItemRenderer } from '@graphcommerce/magento-product' import { LazyHydrate, RenderType, TypeRenderer } from '@graphcommerce/next-ui' import { memo } from 'react' import { RowBlogContent } from '../Blog' -import { PageContentQueryFragment } from './PageContentQueryFragment.gql' import { RowButtonLinkList } from './RowButtonLinkList/RowButtonLinkList' import { RowColumnOne } from './RowColumnOne/RowColumnOne' import { RowColumnThree } from './RowColumnThree/RowColumnThree' @@ -16,7 +16,7 @@ import { RowRendererFragment } from './RowRenderer.gql' import { RowServiceOptions } from './RowServiceOptions/RowServiceOptions' import { RowSpecialBanner } from './RowSpecialBanner/RowSpecialBanner' -export type ContentTypeRenderer = TypeRenderer +export type ContentTypeRenderer = TypeRenderer export const defaultRenderer: { [key: string]: (props) => React.ReactElement } = { RowColumnOne, diff --git a/examples/magento-graphcms/components/GraphCMS/Usps/Usps.graphql b/examples/magento-graphcms/components/Usps/Usps.graphql similarity index 100% rename from examples/magento-graphcms/components/GraphCMS/Usps/Usps.graphql rename to examples/magento-graphcms/components/Usps/Usps.graphql diff --git a/examples/magento-graphcms/components/GraphCMS/Usps/Usps.tsx b/examples/magento-graphcms/components/Usps/Usps.tsx similarity index 100% rename from examples/magento-graphcms/components/GraphCMS/Usps/Usps.tsx rename to examples/magento-graphcms/components/Usps/Usps.tsx diff --git a/examples/magento-graphcms/components/GraphCMS/Usps/UspsQueryFragment.graphql b/examples/magento-graphcms/components/Usps/UspsQueryFragment.graphql similarity index 100% rename from examples/magento-graphcms/components/GraphCMS/Usps/UspsQueryFragment.graphql rename to examples/magento-graphcms/components/Usps/UspsQueryFragment.graphql diff --git a/examples/magento-graphcms/pages/[...url].tsx b/examples/magento-graphcms/pages/[...url].tsx index ce94df8f62f..dffa8d892e0 100644 --- a/examples/magento-graphcms/pages/[...url].tsx +++ b/examples/magento-graphcms/pages/[...url].tsx @@ -1,8 +1,7 @@ import { ContentAreaCategoryPage, ContentAreaCategoryPageBefore, - pageContent, - PageContent, + UniversalPage_DataFragment, } from '@graphcommerce/content-areas' import { PageOptions } from '@graphcommerce/framer-next-pages' import { cacheFirst, flushMeasurePerf, InContextMaskProvider } from '@graphcommerce/graphql' @@ -42,6 +41,8 @@ import { LayoutNavigation, LayoutNavigationProps, productListRenderer, + RowProduct, + RowRenderer, } from '../components' import { CategoryPageDocument, CategoryPageQuery } from '../graphql/CategoryPage.gql' import { graphqlSharedClient, graphqlSsrClient } from '../lib/graphql/graphqlSsrClient' @@ -51,7 +52,7 @@ export type CategoryProps = CategoryPageQuery & ProductFiltersQuery & { filterTypes?: FilterTypes params?: ProductListParams - content: PageContent + content: UniversalPage_DataFragment } export type CategoryRoute = { url: string[] } @@ -59,7 +60,7 @@ type GetPageStaticPaths = GetStaticPaths type GetPageStaticProps = GetStaticProps function CategoryPage(props: CategoryProps) { - const { content, categories, pages, ...rest } = props + const { content, categories, ...rest } = props const productList = useProductList({ ...rest, category: categories?.items?.[0], @@ -71,7 +72,7 @@ function CategoryPage(props: CategoryProps) { return ( - + diff --git a/examples/magento-graphcms/pages/index.tsx b/examples/magento-graphcms/pages/index.tsx index 5240c279a3f..eefd153731e 100644 --- a/examples/magento-graphcms/pages/index.tsx +++ b/examples/magento-graphcms/pages/index.tsx @@ -1,9 +1,6 @@ -import { - ContentAreaHome, - UniversalPageDocument, - UniversalPageQuery, -} from '@graphcommerce/content-areas' +import { ContentAreaHome, GcPageDocument, GcPageQuery } from '@graphcommerce/content-areas' import { PageOptions } from '@graphcommerce/framer-next-pages' +import { cacheFirst } from '@graphcommerce/graphql' import { StoreConfigDocument } from '@graphcommerce/magento-store' import { GetStaticProps, LayoutHeader } from '@graphcommerce/next-ui' import { @@ -14,19 +11,19 @@ import { } from '../components' import { graphqlSharedClient, graphqlSsrClient } from '../lib/graphql/graphqlSsrClient' -type Props = UniversalPageQuery +type Props = GcPageQuery type RouteProps = { url: string } type GetPageStaticProps = GetStaticProps function CmsPage(props: Props) { - const { pageContent } = props + const { gcPage } = props return ( <> {/* */} - + ) } @@ -42,10 +39,7 @@ export const getStaticProps: GetPageStaticProps = async (context) => { const staticClient = graphqlSsrClient(context) const conf = client.query({ query: StoreConfigDocument }) - const page = client.query({ - query: UniversalPageDocument, - variables: { input: { url: 'page/home' } }, - }) + const page = client.query({ query: GcPageDocument, variables: { input: { url: 'page/home' } } }) const layout = staticClient.query({ query: LayoutDocument, diff --git a/examples/magento-graphcms/plugins/ExtendRowRenderer.tsx b/examples/magento-graphcms/plugins/ExtendRowRenderer.tsx deleted file mode 100644 index 1d46d6b0285..00000000000 --- a/examples/magento-graphcms/plugins/ExtendRowRenderer.tsx +++ /dev/null @@ -1,22 +0,0 @@ -import { PageProps, defaultRenderer } from '@graphcommerce/graphcms-ui' -import { PluginProps } from '@graphcommerce/next-config' - -export const component = 'RowRenderer' -export const exported = '@graphcommerce/graphcms-ui/components/RowRenderer' - -const extendedRenderer: { [key: string]: (props) => React.ReactElement } = { - // CustomRow, -} - -function ExtendRowRendererPlugin(props: PluginProps) { - const { Prev, renderer, ...rest } = props - - const mergedRenderer = { - ...renderer, - ...extendedRenderer, - } - - return -} - -export const Plugin = ExtendRowRendererPlugin diff --git a/examples/magento-graphcms/plugins/hygraph/HygraphContentArea.tsx b/examples/magento-graphcms/plugins/hygraph/HygraphContentArea.tsx new file mode 100644 index 00000000000..07bbe5df1b6 --- /dev/null +++ b/examples/magento-graphcms/plugins/hygraph/HygraphContentArea.tsx @@ -0,0 +1,20 @@ +import type { ContentAreaProps } from '@graphcommerce/content-areas' +import type { PluginConfig, PluginProps } from '@graphcommerce/next-config' +import { RowRenderer } from '../../components/GraphCMS' + +export const config: PluginConfig = { + type: 'component', + module: '@graphcommerce/content-areas', +} + +export const ContentArea = (props: PluginProps) => { + const { Prev, ...rest } = props + const { gcPage } = rest + + return ( + <> + + {gcPage && } + + ) +} diff --git a/packages/cli/dist/bin/mesh.js b/packages/cli/dist/bin/mesh.js index aea6466a1d6..cbefd4d7c9d 100755 --- a/packages/cli/dist/bin/mesh.js +++ b/packages/cli/dist/bin/mesh.js @@ -119,8 +119,6 @@ const main = async () => { }); // Scan the current working directory to also read all graphqls files. conf.additionalTypeDefs.push('**/*.graphqls'); - conf.additionalResolvers = []; - // conf.additionalResolvers.push('**/resolvers/**/*.ts') const deps = (0, next_config_1.resolveDependenciesSync)(); const packages = [...deps.values()].filter((p) => p !== '.'); const mV = graphCommerce.magentoVersion ?? 246; @@ -131,18 +129,6 @@ const main = async () => { conf.additionalTypeDefs.push(`${r}/*/schema/**/*.graphqls`); conf.additionalTypeDefs.push(...alsoScan); }); - const meshScan = [...deps.values()].map(async (r) => { - const resolver = `${r}/mesh.ts`; - const hasResolver = await node_fs_1.promises - .stat(resolver) - .then(() => true) - .catch(() => false); - if (!conf.additionalResolvers) - conf.additionalResolvers = []; - if (hasResolver) - conf.additionalResolvers.push(resolver); - }); - await Promise.all(meshScan); if (!conf.serve) conf.serve = {}; if (!conf.serve.playgroundTitle) diff --git a/packages/cli/src/bin/mesh.ts b/packages/cli/src/bin/mesh.ts index bbadc1793e2..5ad46c03a53 100755 --- a/packages/cli/src/bin/mesh.ts +++ b/packages/cli/src/bin/mesh.ts @@ -119,10 +119,6 @@ const main = async () => { // Scan the current working directory to also read all graphqls files. conf.additionalTypeDefs.push('**/*.graphqls') - conf.additionalResolvers = [] - - // conf.additionalResolvers.push('**/resolvers/**/*.ts') - const deps = resolveDependenciesSync() const packages = [...deps.values()].filter((p) => p !== '.') @@ -136,19 +132,6 @@ const main = async () => { conf.additionalTypeDefs.push(...alsoScan) }) - const meshScan = [...deps.values()].map(async (r) => { - const resolver = `${r}/mesh.ts` - - const hasResolver = await fs - .stat(resolver) - .then(() => true) - .catch(() => false) - - if (!conf.additionalResolvers) conf.additionalResolvers = [] - if (hasResolver) conf.additionalResolvers.push(resolver) - }) - await Promise.all(meshScan) - if (!conf.serve) conf.serve = {} if (!conf.serve.playgroundTitle) conf.serve.playgroundTitle = 'GraphCommerce® Mesh' diff --git a/packages/content-areas/components/ContentArea/ContentArea.tsx b/packages/content-areas/components/ContentArea/ContentArea.tsx index 5932a075b63..733fb266a9c 100644 --- a/packages/content-areas/components/ContentArea/ContentArea.tsx +++ b/packages/content-areas/components/ContentArea/ContentArea.tsx @@ -1,11 +1,8 @@ -import { ProductListItemRenderer } from '@graphcommerce/magento-product' -import { UniversalPageQuery } from '../../queries/UniversalPage.gql' +import { GcPageQuery } from '../../queries/GcPage.gql' -type ContentAreaProps = UniversalPageQuery & { - productListRenderer: ProductListItemRenderer -} +export type ContentAreaProps = GcPageQuery export function ContentArea(props: ContentAreaProps) { - const { pageContent } = props + const { gcPage } = props return
} diff --git a/packages/content-areas/index.ts b/packages/content-areas/index.ts index abaf242e687..7eaa9d0fc75 100644 --- a/packages/content-areas/index.ts +++ b/packages/content-areas/index.ts @@ -1,4 +1,3 @@ export * from './components' -// export * from './server/resolveMetadata' -export * from './queries/UniversalPage.gql' -export * from './queries/UniversalPage_Data.gql' +export * from './queries/GcPage_Data.gql' +export * from './queries/GcPage.gql' diff --git a/packages/content-areas/package.json b/packages/content-areas/package.json index 27003f1d9f6..0e43d078c77 100644 --- a/packages/content-areas/package.json +++ b/packages/content-areas/package.json @@ -2,7 +2,7 @@ "name": "@graphcommerce/content-areas", "homepage": "https://www.graphcommerce.org/", "repository": "github:graphcommerce-org/graphcommerce", - "version": "8.0.0-canary.95", + "version": "9.0.0-canary.62", "sideEffects": false, "prettier": "@graphcommerce/prettier-config-pwa", "eslintConfig": { @@ -12,13 +12,14 @@ } }, "peerDependencies": { - "@graphcommerce/eslint-config-pwa": "^8.0.0-canary.95", - "@graphcommerce/graphql": "^8.0.0-canary.95", - "@graphcommerce/magento-product": "^8.0.0-canary.95", - "@graphcommerce/next-ui": "^8.0.0-canary.95", - "@graphcommerce/prettier-config-pwa": "^8.0.0-canary.95", - "@graphcommerce/react-hook-form": "^8.0.0-canary.95", - "@graphcommerce/typescript-config-pwa": "^8.0.0-canary.95", + "@graphcommerce/eslint-config-pwa": "^9.0.0-canary.62", + "@graphcommerce/graphql": "^9.0.0-canary.62", + "@graphcommerce/graphql-mesh": "^9.0.0-canary.62", + "@graphcommerce/magento-product": "^9.0.0-canary.62", + "@graphcommerce/next-ui": "^9.0.0-canary.62", + "@graphcommerce/prettier-config-pwa": "^9.0.0-canary.62", + "@graphcommerce/react-hook-form": "^9.0.0-canary.62", + "@graphcommerce/typescript-config-pwa": "^9.0.0-canary.62", "@lingui/core": "^4.2.1", "@lingui/macro": "^4.2.1", "@lingui/react": "^4.2.1", diff --git a/packages/content-areas/queries/GcPage.graphql b/packages/content-areas/queries/GcPage.graphql new file mode 100644 index 00000000000..91c9ded9e20 --- /dev/null +++ b/packages/content-areas/queries/GcPage.graphql @@ -0,0 +1,5 @@ +query GcPage($input: GCPageInput!) { + gcPage(input: $input) { + ...GCPage_Data + } +} diff --git a/packages/content-areas/queries/GcPage_Data.graphql b/packages/content-areas/queries/GcPage_Data.graphql new file mode 100644 index 00000000000..160c5b26546 --- /dev/null +++ b/packages/content-areas/queries/GcPage_Data.graphql @@ -0,0 +1,9 @@ +fragment GCPage_Data on GCPageInterface { + id + title + metaTitle + metaDescription + metaRobots + canonicalUrl + someField +} diff --git a/packages/content-areas/queries/UniversalPage.graphql b/packages/content-areas/queries/UniversalPage.graphql deleted file mode 100644 index 19b2c1a12b7..00000000000 --- a/packages/content-areas/queries/UniversalPage.graphql +++ /dev/null @@ -1,7 +0,0 @@ -query UniversalPage($input: UniversalPageInput!) { - common { - pageContent(input: $input) { - ...UniversalPage_Data - } - } -} diff --git a/packages/content-areas/queries/UniversalPage_Data.graphql b/packages/content-areas/queries/UniversalPage_Data.graphql deleted file mode 100644 index 234f0ced482..00000000000 --- a/packages/content-areas/queries/UniversalPage_Data.graphql +++ /dev/null @@ -1,7 +0,0 @@ -fragment UniversalPage_Data on UniversalPage @injectable { - title - meta { - title - description - } -} diff --git a/packages/content-areas/schema/Query_gcPage.graphqls b/packages/content-areas/schema/Query_gcPage.graphqls new file mode 100644 index 00000000000..15abefe56ff --- /dev/null +++ b/packages/content-areas/schema/Query_gcPage.graphqls @@ -0,0 +1,27 @@ +interface GCPageInterface { + id: ID! + title: String + metaTitle: String + metaDescription: String + metaRobots: String + canonicalUrl: String + someField: String! +} + +# type GCPageNotFound implements GCPageInterface { +# id: ID! +# title: String +# metaTitle: String +# metaDescription: String +# metaRobots: String +# canonicalUrl: String +# someField: String! +# } + +input GCPageInput { + url: String! +} + +extend type Query { + gcPage(input: GCPageInput!): GCPageInterface +} diff --git a/packages/content-areas/schema/UniversalPage.graphqls b/packages/content-areas/schema/UniversalPage.graphqls deleted file mode 100644 index c2282faf587..00000000000 --- a/packages/content-areas/schema/UniversalPage.graphqls +++ /dev/null @@ -1,28 +0,0 @@ -type UniSeo { - """ - Meta title - """ - title: String - - """ - A description of the product for usage in search engine results. - """ - description: String -} - -type UniversalPage { - title: String - meta: Seo -} - -input UniversalPageInput { - url: String! -} - -type UniversalApi { - pageContent(input: UniversalPageInput!): UniversalPage -} - -extend type Query { - common: UniversalApi -} diff --git a/packages/content-areas/server.ts b/packages/content-areas/server.ts new file mode 100644 index 00000000000..336ce12bb91 --- /dev/null +++ b/packages/content-areas/server.ts @@ -0,0 +1 @@ +export {} diff --git a/packages/hygraph-ui/components/index.ts b/packages/hygraph-ui/components/index.ts index f7a6dc99a8e..e8d874cff84 100644 --- a/packages/hygraph-ui/components/index.ts +++ b/packages/hygraph-ui/components/index.ts @@ -1,3 +1,2 @@ -export * from './Asset/Asset' -export * from './Asset/Asset.gql' export * from './RichText/index' +export * from './Asset/Asset' diff --git a/packages/hygraph-ui/graphql/GCPage_Hygraph.graphql b/packages/hygraph-ui/graphql/GCPage_Hygraph.graphql new file mode 100644 index 00000000000..f09ce4a453b --- /dev/null +++ b/packages/hygraph-ui/graphql/GCPage_Hygraph.graphql @@ -0,0 +1,3 @@ +fragment GCPage_Hygraph on GCPageInterface @inject(into: ["GCPage_Data"]) { + ...HygraphPage +} diff --git a/packages/hygraph-ui/graphql/HygraphPages.graphql b/packages/hygraph-ui/graphql/HygraphPages.graphql deleted file mode 100644 index 535515a9c45..00000000000 --- a/packages/hygraph-ui/graphql/HygraphPages.graphql +++ /dev/null @@ -1,7 +0,0 @@ -query HygraphPages($url: String!) { - pages(where: { url: $url }) { - id - __typename - ...HygraphPage - } -} diff --git a/packages/hygraph-ui/graphql/UniversalPage_Hygraph.graphql b/packages/hygraph-ui/graphql/UniversalPage_Hygraph.graphql deleted file mode 100644 index 12b654a846c..00000000000 --- a/packages/hygraph-ui/graphql/UniversalPage_Hygraph.graphql +++ /dev/null @@ -1,5 +0,0 @@ -fragment UniversalPage_Hygraph on UniversalPage @inject(into: ["UniversalPage_Data"]) { - hygraphPage { - ...HygraphPage - } -} diff --git a/packages/hygraph-ui/graphql/index.ts b/packages/hygraph-ui/graphql/index.ts index e245b1dc74d..3c557f0cece 100644 --- a/packages/hygraph-ui/graphql/index.ts +++ b/packages/hygraph-ui/graphql/index.ts @@ -1,5 +1,5 @@ export * from './HygraphAllPages.gql' export * from './HygraphPage.gql' -export * from './HygraphPages.gql' +export * from './GCPage_Hygraph.gql' export * from './PageLink.gql' export * from './PagesStaticPaths.gql' diff --git a/packages/hygraph-ui/mesh.ts b/packages/hygraph-ui/mesh.ts deleted file mode 100644 index 8bca87ff128..00000000000 --- a/packages/hygraph-ui/mesh.ts +++ /dev/null @@ -1,64 +0,0 @@ -/* eslint-disable import/no-extraneous-dependencies */ -import type { Resolvers } from '@graphcommerce/graphql-mesh' -import { parseSelectionSet } from '@graphql-tools/utils' -import { Kind, FieldNode, SelectionSetNode } from 'graphql' - -function selectionSetFromPath(path: string[], selectionSet: SelectionSetNode) { - const [fieldName, ...rest] = path - - const selection = selectionSet.selections.find( - (s) => s.kind === Kind.FIELD && s.name.value === fieldName, - ) as FieldNode - - if (!selection.selectionSet) return undefined - if (rest.length === 0) return selection.selectionSet - - return selectionSetFromPath(rest, selection.selectionSet) -} - -function mergeSelectionSetNodes( - node1: SelectionSetNode | undefined, - node2: SelectionSetNode | undefined, -): SelectionSetNode { - const selections = [...(node1?.selections ?? []), ...(node2?.selections ?? [])] - - return { - kind: Kind.SELECTION_SET, - selections, - } -} - -export const resolvers: Resolvers = { - Query: { - pageContent: async (root, { input }, context, info) => { - const selectionSet = mergeSelectionSetNodes( - selectionSetFromPath(['pageContent', 'hygraphPage'], info.operation.selectionSet), - parseSelectionSet(`{ title metaTitle metaDescription }`, { noLocation: true }), - ) - - const pages = await context.hygraph.Query.pages({ - root, - args: { where: input }, - context, - info, - selectionSet, - }) - const hygraphPage = pages?.[0] - if (!hygraphPage) return null - const { title, metaTitle, metaDescription } = hygraphPage - return { - title, - meta: { title: metaTitle, description: metaDescription }, - hygraphPage, - } - }, - }, - - RowProduct: { - category: async (root, _args, context, info) => { - // This resolver should be called as a RowProduct is returned by the resolver below. - console.log('Called') - return null - }, - }, -} diff --git a/packages/hygraph-ui/mesh/resolvers.ts b/packages/hygraph-ui/mesh/resolvers.ts new file mode 100644 index 00000000000..725c845fe6d --- /dev/null +++ b/packages/hygraph-ui/mesh/resolvers.ts @@ -0,0 +1,51 @@ +/* eslint-disable import/no-extraneous-dependencies */ +import type { Resolvers } from '@graphcommerce/graphql-mesh' +import { Kind, FieldNode, SelectionSetNode } from 'graphql' + +function selectionSetFromPath(path: string[], selectionSet?: SelectionSetNode) { + const [fieldName, ...rest] = path + + const selection = selectionSet?.selections.find( + (s) => s.kind === Kind.FIELD && s.name.value === fieldName, + ) as FieldNode + + if (!selection?.selectionSet) return undefined + if (rest.length === 0) return selection.selectionSet + + return selectionSetFromPath(rest, selection.selectionSet) +} + +function mergeSelectionSetNodes( + node1: SelectionSetNode | undefined, + node2: SelectionSetNode | undefined, +): SelectionSetNode { + const selections = [...(node1?.selections ?? []), ...(node2?.selections ?? [])] + + return { + kind: Kind.SELECTION_SET, + selections, + } +} + +export const resolvers: Resolvers = { + // Query: { + // gcPage: async (root, { input }, context, info) => { + // const pages = await context.hygraph.Query.pages({ + // root, + // args: { where: input }, + // context, + // info, + // }) + + // const page = pages[0] + // return { id: page.id } + // }, + // }, + + Page: { + someField: { + selectionSet: '{ id }', + resolve: (root) => root.id, + }, + }, +} diff --git a/packages/hygraph-ui/plugins/HygraphContentArea.tsx b/packages/hygraph-ui/plugins/HygraphContentArea.tsx deleted file mode 100644 index 067fc474be3..00000000000 --- a/packages/hygraph-ui/plugins/HygraphContentArea.tsx +++ /dev/null @@ -1,26 +0,0 @@ -import type { ContentArea } from '@graphcommerce/content-areas' -import type { ReactPlugin } from '@graphcommerce/next-config' -import { RowRenderer } from '../components' - -export const component = 'ContentArea' -export const exported = '@graphcommerce/content-areas/components/ContentArea/ContentArea' - -const HygraphContentArea: ReactPlugin = (props) => { - const { Prev, ...rest } = props - const { pageContent, renderer, productListRenderer } = props - - return ( - <> - - {pageContent?.hygraphPage && ( - - )} - - ) -} - -export const Plugin = HygraphContentArea diff --git a/packages/hygraph-ui/plugins/meshConfigHygraph.ts b/packages/hygraph-ui/plugins/meshConfigHygraph.ts new file mode 100644 index 00000000000..d47164280c0 --- /dev/null +++ b/packages/hygraph-ui/plugins/meshConfigHygraph.ts @@ -0,0 +1,23 @@ +import type { meshConfig as meshConfigBase } from '@graphcommerce/graphql-mesh/meshConfig' +import type { FunctionPlugin, PluginConfig } from '@graphcommerce/next-config' + +export const config: PluginConfig = { + module: '@graphcommerce/graphql-mesh/meshConfig', + type: 'function', +} + +export const meshConfig: FunctionPlugin = ( + prev, + baseConfig, + graphCommerceConfig, +) => + prev( + { + ...baseConfig, + additionalResolvers: [ + ...(baseConfig.additionalResolvers ?? []), + '@graphcommerce/graphcms-ui/mesh/resolvers', + ], + }, + graphCommerceConfig, + ) diff --git a/packages/hygraph-ui/schema.graphqls b/packages/hygraph-ui/schema.graphqls deleted file mode 100644 index 8f45ffa1d5f..00000000000 --- a/packages/hygraph-ui/schema.graphqls +++ /dev/null @@ -1,39 +0,0 @@ -extend type UniversalPage { - hygraphPage: Page -} - -extend type Query { - pageContent(input: UniversalPageInput!): UniversalPage - @resolveTo( - sourceName: "hygraph" - sourceTypeName: "Query" - sourceFieldName: "categories" - # Regular resolver - requiredSelectionSet: "{ identity }" - sourceArgs: { where: { url: "{args.input.url}" } } - result: "[0]" - - # Batching resolver (requires all values to resolve, so nothing will be returned if any of the values are missing) - # keyField: "identity" - # keysArg: "filters.url_key.in" - # result: "items" - ) -} - -extend type RowProduct { - category: CategoryTree - @resolveTo( - sourceName: "m2" - sourceTypeName: "Query" - sourceFieldName: "categories" - # Regular resolver - requiredSelectionSet: "{ identity }" - sourceArgs: { filters: { url_key: { eq: "{root.identity}" } } } - result: "items[0]" - - # Batching resolver (requires all values to resolve, so nothing will be returned if any of the values are missing) - # keyField: "identity" - # keysArg: "filters.url_key.in" - # result: "items" - ) -} diff --git a/packages/hygraph-ui/schema/Query_gcPage.graphqls b/packages/hygraph-ui/schema/Query_gcPage.graphqls new file mode 100644 index 00000000000..54914d9ac27 --- /dev/null +++ b/packages/hygraph-ui/schema/Query_gcPage.graphqls @@ -0,0 +1,19 @@ +type Page implements GCPageInterface { + title: String + metaTitle: String + metaDescription: String + metaRobots: String + canonicalUrl: String + someField: String! +} + +extend type Query { + gcPage(input: GCPageInput!): GCPageInterface + @resolveTo( + sourceName: "hygraph" + sourceTypeName: "Query" + sourceFieldName: "pagesConnection" + sourceArgs: { where: { url: "{args.input.url}" } } + result: "edges[0].node" + ) +} diff --git a/packages/hygraph-ui/schema/RowProduct_category.graphqls b/packages/hygraph-ui/schema/RowProduct_category.graphqls new file mode 100644 index 00000000000..c3aaf855908 --- /dev/null +++ b/packages/hygraph-ui/schema/RowProduct_category.graphqls @@ -0,0 +1,11 @@ +extend type RowProduct { + category: CategoryTree + @resolveTo( + sourceName: "m2" + sourceTypeName: "Query" + sourceFieldName: "categories" + requiredSelectionSet: "{ identity }" + sourceArgs: { filters: { url_key: { eq: "{root.identity}" } } } + result: "items[0]" + ) +} diff --git a/packages/hygraph-ui/types.ts b/packages/hygraph-ui/types.ts deleted file mode 100644 index a7f62224835..00000000000 --- a/packages/hygraph-ui/types.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { ContentTypeRenderer } from './components' -import { HygraphPageFragment } from './graphql' - -declare module '@graphcommerce/content-areas/components/ContentArea' { - export interface ContentAreaProps { - renderer: Partial - } -} - -declare module '@graphcommerce/content-areas/types' { - export interface PageContent { - hygraphPage?: HygraphPageFragment | null | undefined - } -} diff --git a/packagesDev/next-config/src/index.ts b/packagesDev/next-config/src/index.ts index be5a1c50300..f91eb2285de 100644 --- a/packagesDev/next-config/src/index.ts +++ b/packagesDev/next-config/src/index.ts @@ -11,7 +11,7 @@ export * from './config' export * from './runtimeCachingOptimizations' export * from './interceptors/commands/codegenInterceptors' -export type PluginProps

= Record> = P & { +export type PluginProps

> = P & { Prev: React.FC

} diff --git a/yarn.lock b/yarn.lock index 659ebf705c3..b0d5440a613 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2915,17 +2915,18 @@ __metadata: languageName: unknown linkType: soft -"@graphcommerce/content-areas@workspace:packages/content-areas": +"@graphcommerce/content-areas@npm:9.0.0-canary.62, @graphcommerce/content-areas@workspace:packages/content-areas": version: 0.0.0-use.local resolution: "@graphcommerce/content-areas@workspace:packages/content-areas" peerDependencies: - "@graphcommerce/eslint-config-pwa": ^8.0.0-canary.95 - "@graphcommerce/graphql": ^8.0.0-canary.95 - "@graphcommerce/magento-product": ^8.0.0-canary.95 - "@graphcommerce/next-ui": ^8.0.0-canary.95 - "@graphcommerce/prettier-config-pwa": ^8.0.0-canary.95 - "@graphcommerce/react-hook-form": ^8.0.0-canary.95 - "@graphcommerce/typescript-config-pwa": ^8.0.0-canary.95 + "@graphcommerce/eslint-config-pwa": ^9.0.0-canary.62 + "@graphcommerce/graphql": ^9.0.0-canary.62 + "@graphcommerce/graphql-mesh": ^9.0.0-canary.62 + "@graphcommerce/magento-product": ^9.0.0-canary.62 + "@graphcommerce/next-ui": ^9.0.0-canary.62 + "@graphcommerce/prettier-config-pwa": ^9.0.0-canary.62 + "@graphcommerce/react-hook-form": ^9.0.0-canary.62 + "@graphcommerce/typescript-config-pwa": ^9.0.0-canary.62 "@lingui/core": ^4.2.1 "@lingui/macro": ^4.2.1 "@lingui/react": ^4.2.1 @@ -3934,6 +3935,7 @@ __metadata: "@apollo/client": "npm:~3.10.8" "@ducanh2912/next-pwa": "npm:9.7.2" "@graphcommerce/cli": "npm:9.0.0-canary.62" + "@graphcommerce/content-areas": "npm:9.0.0-canary.62" "@graphcommerce/demo-magento-graphcommerce": "npm:9.0.0-canary.62" "@graphcommerce/ecommerce-ui": "npm:9.0.0-canary.62" "@graphcommerce/eslint-config-pwa": "npm:9.0.0-canary.62" From 41186986529ae1b50cca8fe1dbf649366bc163de Mon Sep 17 00:00:00 2001 From: Paul Hachmang Date: Tue, 23 Jul 2024 09:28:10 +0200 Subject: [PATCH 17/33] Cleanup --- examples/magento-graphcms/.meshrc.yml | 8 -------- examples/magento-graphcms/components/Blog/BlogHeader.tsx | 2 +- examples/magento-graphcms/components/Blog/BlogItem.tsx | 2 +- packages/next-ui/Blog/BlogHeader/BlogHeader.tsx | 2 +- 4 files changed, 3 insertions(+), 11 deletions(-) diff --git a/examples/magento-graphcms/.meshrc.yml b/examples/magento-graphcms/.meshrc.yml index 8a9ab90b647..716dce965c8 100644 --- a/examples/magento-graphcms/.meshrc.yml +++ b/examples/magento-graphcms/.meshrc.yml @@ -18,14 +18,6 @@ sources: - '*.*.!{after,before,last,forceParentLocale,locales,stage}' # Remove type any input or type fields: `input MyInput {}` or `type MyType { anyfield }` - '*.!{localizations,scheduledIn,documentInStages*,createdAt*,updatedAt*,publishedAt*,createdBy,updatedBy,publishedBy,history,scheduledIn*}' - # - prefix: - # includeRootOperations: true - # includeTypes: false - # value: 'hygraph_' - # - prefix: - # includeRootOperations: false - # includeTypes: true - # value: 'Hygraph' - prune: skipPruning: [] - name: m2 diff --git a/examples/magento-graphcms/components/Blog/BlogHeader.tsx b/examples/magento-graphcms/components/Blog/BlogHeader.tsx index 4f26508f892..68c2b6da2b6 100644 --- a/examples/magento-graphcms/components/Blog/BlogHeader.tsx +++ b/examples/magento-graphcms/components/Blog/BlogHeader.tsx @@ -1,5 +1,5 @@ +import { Asset, AssetFragment } from '@graphcommerce/graphcms-ui' import { BlogHeader as NextBlogHeader } from '@graphcommerce/next-ui' -import { Asset, AssetFragment } from '@graphcommerce/graphcms-ui/components/Asset/Asset' export function BlogHeader(props: { asset?: AssetFragment }) { const { asset } = props diff --git a/examples/magento-graphcms/components/Blog/BlogItem.tsx b/examples/magento-graphcms/components/Blog/BlogItem.tsx index 78d12e9ab2d..8629246d7ca 100644 --- a/examples/magento-graphcms/components/Blog/BlogItem.tsx +++ b/examples/magento-graphcms/components/Blog/BlogItem.tsx @@ -1,8 +1,8 @@ +import { Asset } from '@graphcommerce/graphcms-ui' import { BlogListItem } from '@graphcommerce/next-ui' import { Trans } from '@lingui/react' import { Typography, useTheme } from '@mui/material' import { BlogItemFragment } from './BlogItem.gql' -import { Asset } from '@graphcommerce/graphcms-ui/components/Asset/Asset' type BlogItemProps = BlogItemFragment diff --git a/packages/next-ui/Blog/BlogHeader/BlogHeader.tsx b/packages/next-ui/Blog/BlogHeader/BlogHeader.tsx index 4dbd89f12c7..9f3eb114399 100644 --- a/packages/next-ui/Blog/BlogHeader/BlogHeader.tsx +++ b/packages/next-ui/Blog/BlogHeader/BlogHeader.tsx @@ -8,7 +8,7 @@ export type BlogHeaderProps = { asset?: React.ReactNode } -const name = 'BlogHeader' as const +const name = 'BlogHeader' const parts = ['header', 'asset'] as const const { classes } = extendableComponent(name, parts) From 90232457fd91ac3c758a503baaa55b5d8b3d6854 Mon Sep 17 00:00:00 2001 From: Paul Hachmang Date: Tue, 23 Jul 2024 17:03:05 +0200 Subject: [PATCH 18/33] Refactor and make homepage work --- .../RowProduct/GetRowProductCategory.graphql | 7 +++++++ .../GraphCMS/RowProduct/RowProduct.graphql | 11 +--------- .../GraphCMS/RowProduct/RowProduct.tsx | 20 ++++++++++--------- .../RowProduct/RowProductCategory.graphql | 11 ++++++++++ .../GraphCMS/RowProduct/variant/Feature.tsx | 6 +++--- .../components/GraphCMS/RowRenderer.tsx | 14 +++---------- examples/magento-graphcms/pages/[...url].tsx | 10 ++++++---- examples/magento-graphcms/pages/index.tsx | 7 +------ packages/content-areas/README.md | 4 ++++ 9 files changed, 47 insertions(+), 43 deletions(-) create mode 100644 examples/magento-graphcms/components/GraphCMS/RowProduct/GetRowProductCategory.graphql create mode 100644 examples/magento-graphcms/components/GraphCMS/RowProduct/RowProductCategory.graphql create mode 100644 packages/content-areas/README.md diff --git a/examples/magento-graphcms/components/GraphCMS/RowProduct/GetRowProductCategory.graphql b/examples/magento-graphcms/components/GraphCMS/RowProduct/GetRowProductCategory.graphql new file mode 100644 index 00000000000..679f77ecd91 --- /dev/null +++ b/examples/magento-graphcms/components/GraphCMS/RowProduct/GetRowProductCategory.graphql @@ -0,0 +1,7 @@ +query GetRowProductCategory($category_uid: String!) { + categories(filters: { category_uid: { eq: $category_uid } }) { + items { + ...RowProductCategory + } + } +} diff --git a/examples/magento-graphcms/components/GraphCMS/RowProduct/RowProduct.graphql b/examples/magento-graphcms/components/GraphCMS/RowProduct/RowProduct.graphql index 250c209cdab..180c3c96b27 100644 --- a/examples/magento-graphcms/components/GraphCMS/RowProduct/RowProduct.graphql +++ b/examples/magento-graphcms/components/GraphCMS/RowProduct/RowProduct.graphql @@ -11,16 +11,7 @@ fragment RowProduct on RowProduct { pageLinks { ...PageLink } - category { - uid - name - products { - items { - __typename - uid - ...ProductListItem - } - } + ...RowProductCategory } } diff --git a/examples/magento-graphcms/components/GraphCMS/RowProduct/RowProduct.tsx b/examples/magento-graphcms/components/GraphCMS/RowProduct/RowProduct.tsx index dc9c5f1a3c4..7be8be23d79 100644 --- a/examples/magento-graphcms/components/GraphCMS/RowProduct/RowProduct.tsx +++ b/examples/magento-graphcms/components/GraphCMS/RowProduct/RowProduct.tsx @@ -1,6 +1,7 @@ import { InContextMaskProvider, useInContextQuery } from '@graphcommerce/graphql' import { ProductListItemRenderer, ProductListDocument } from '@graphcommerce/magento-product' import { filterNonNullableKeys } from '@graphcommerce/next-ui' +import { productListRenderer } from '../../ProductListItems' import { RowProductFragment } from './RowProduct.gql' import { Backstory, @@ -13,6 +14,7 @@ import { Swipeable, Upsells, } from './variant' +import { GetRowProductCategoryDocument } from './GetRowProductCategory.gql' type VariantRenderer = Record< NonNullable, @@ -21,7 +23,6 @@ type VariantRenderer = Record< type RowProductProps = RowProductFragment & { renderer?: Partial - productListItemRenderer: ProductListItemRenderer } & { sku?: string | null | undefined } const defaultRenderer: Partial = { @@ -37,19 +38,16 @@ const defaultRenderer: Partial = { } export function RowProduct(props: RowProductProps) { - const { renderer, productListItemRenderer, category, ...rest } = props + const { renderer, category } = props let { variant } = props const mergedRenderer = { ...defaultRenderer, ...renderer } as VariantRenderer - const urlKeys = filterNonNullableKeys(category?.products?.items).map((item) => item.url_key) const scoped = useInContextQuery( - ProductListDocument, - { variables: { onlyItems: true, filters: { url_key: { in: urlKeys } } } }, - { products: { items: category?.products?.items } }, + GetRowProductCategoryDocument, + { variables: { category_uid: category?.uid ?? '' }, skip: !category?.uid }, + { categories: { items: category ? [category] : [] } }, ) - const { products } = scoped.data - if (!variant) variant = 'Related' const RenderType = @@ -61,7 +59,11 @@ export function RowProduct(props: RowProductProps) { return ( - + ) } diff --git a/examples/magento-graphcms/components/GraphCMS/RowProduct/RowProductCategory.graphql b/examples/magento-graphcms/components/GraphCMS/RowProduct/RowProductCategory.graphql new file mode 100644 index 00000000000..292f39e9414 --- /dev/null +++ b/examples/magento-graphcms/components/GraphCMS/RowProduct/RowProductCategory.graphql @@ -0,0 +1,11 @@ +fragment RowProductCategory on CategoryTree { + uid + name + products(pageSize: 8) { + items { + __typename + uid + ...ProductListItem + } + } +} diff --git a/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Feature.tsx b/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Feature.tsx index 4ca09a2d12f..ad3d7d24d94 100644 --- a/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Feature.tsx +++ b/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Feature.tsx @@ -8,16 +8,16 @@ import { RowProductFragment } from '../RowProduct.gql' type FeatureProps = RowProductFragment & { productListItemRenderer: ProductListItemRenderer } export function Feature(props: FeatureProps) { - const { productCopy, title, media_gallery } = props + const { productCopy, title, category } = props const theme = useTheme() - const item = media_gallery?.[2] ?? media_gallery?.[0] + const firstProduct = category?.products?.items?.[0] + const item = firstProduct?.small_image if (!item) return null return ( React.ReactElement } = RowHeroBanner, RowSpecialBanner, RowQuote, - // RowBlogContent, + // // RowBlogContent, RowButtonLinkList, RowServiceOptions, RowContentLinks, @@ -36,25 +36,17 @@ export const defaultRenderer: { [key: string]: (props) => React.ReactElement } = export type PageProps = RowRendererFragment & { renderer?: Partial loadingEager?: number - productListItemRenderer?: ProductListItemRenderer } export const RowRenderer = memo((props) => { - const { content, renderer, productListItemRenderer, loadingEager = 2 } = props + const { content, renderer, loadingEager = 2 } = props const mergedRenderer = { ...defaultRenderer, ...renderer } as ContentTypeRenderer return ( <> {content?.map((item, index) => ( - {item.__typename === 'RowProduct' && ( - - )} - {item.__typename !== 'RowProduct' && } + ))} diff --git a/examples/magento-graphcms/pages/[...url].tsx b/examples/magento-graphcms/pages/[...url].tsx index dffa8d892e0..0a70cf682f1 100644 --- a/examples/magento-graphcms/pages/[...url].tsx +++ b/examples/magento-graphcms/pages/[...url].tsx @@ -1,7 +1,8 @@ import { ContentAreaCategoryPage, ContentAreaCategoryPageBefore, - UniversalPage_DataFragment, + GCPage_DataFragment, + GcPageQuery, } from '@graphcommerce/content-areas' import { PageOptions } from '@graphcommerce/framer-next-pages' import { cacheFirst, flushMeasurePerf, InContextMaskProvider } from '@graphcommerce/graphql' @@ -47,20 +48,21 @@ import { import { CategoryPageDocument, CategoryPageQuery } from '../graphql/CategoryPage.gql' import { graphqlSharedClient, graphqlSsrClient } from '../lib/graphql/graphqlSsrClient' -export type CategoryProps = CategoryPageQuery & +export type CategoryProps = GcPageQuery & + CategoryPageQuery & ProductListQuery & ProductFiltersQuery & { filterTypes?: FilterTypes params?: ProductListParams - content: UniversalPage_DataFragment } + export type CategoryRoute = { url: string[] } type GetPageStaticPaths = GetStaticPaths type GetPageStaticProps = GetStaticProps function CategoryPage(props: CategoryProps) { - const { content, categories, ...rest } = props + const { gcPage, categories, ...rest } = props const productList = useProductList({ ...rest, category: categories?.items?.[0], diff --git a/examples/magento-graphcms/pages/index.tsx b/examples/magento-graphcms/pages/index.tsx index eefd153731e..fced474343b 100644 --- a/examples/magento-graphcms/pages/index.tsx +++ b/examples/magento-graphcms/pages/index.tsx @@ -3,12 +3,7 @@ import { PageOptions } from '@graphcommerce/framer-next-pages' import { cacheFirst } from '@graphcommerce/graphql' import { StoreConfigDocument } from '@graphcommerce/magento-store' import { GetStaticProps, LayoutHeader } from '@graphcommerce/next-ui' -import { - LayoutDocument, - LayoutNavigation, - LayoutNavigationProps, - productListRenderer, -} from '../components' +import { LayoutDocument, LayoutNavigation, LayoutNavigationProps } from '../components' import { graphqlSharedClient, graphqlSsrClient } from '../lib/graphql/graphqlSsrClient' type Props = GcPageQuery diff --git a/packages/content-areas/README.md b/packages/content-areas/README.md new file mode 100644 index 00000000000..18da56b36de --- /dev/null +++ b/packages/content-areas/README.md @@ -0,0 +1,4 @@ +# GraphCommerce CMS API + +This package serves as an API extension point to integrate different CMS +solutions. From 131a63c1c472a860ae17cdd9c4d4ba5e2f34144b Mon Sep 17 00:00:00 2001 From: Paul Hachmang Date: Tue, 23 Jul 2024 17:11:16 +0200 Subject: [PATCH 19/33] Cleanup RowLinks --- .../components/GraphCMS/RowLinks/RowLinks.tsx | 5 ++--- .../GraphCMS/RowLinks/variant/Usps.tsx | 1 + .../GraphCMS/RowProduct/RowProduct.tsx | 18 +++++------------- .../GraphCMS/RowProduct/variant/Backstory.tsx | 9 +++++---- .../GraphCMS/RowProduct/variant/Feature.tsx | 3 +-- .../RowProduct/variant/FeatureBoxed.tsx | 6 ++---- .../GraphCMS/RowProduct/variant/Grid.tsx | 9 +++++---- .../GraphCMS/RowProduct/variant/Related.tsx | 15 +++++---------- .../GraphCMS/RowProduct/variant/Reviews.tsx | 4 +--- .../GraphCMS/RowProduct/variant/Specs.tsx | 5 ++--- .../GraphCMS/RowProduct/variant/Swipeable.tsx | 10 +++++----- .../GraphCMS/RowProduct/variant/Upsells.tsx | 15 +++++---------- 12 files changed, 39 insertions(+), 61 deletions(-) diff --git a/examples/magento-graphcms/components/GraphCMS/RowLinks/RowLinks.tsx b/examples/magento-graphcms/components/GraphCMS/RowLinks/RowLinks.tsx index 5cd9ffe552c..a5c723020f3 100644 --- a/examples/magento-graphcms/components/GraphCMS/RowLinks/RowLinks.tsx +++ b/examples/magento-graphcms/components/GraphCMS/RowLinks/RowLinks.tsx @@ -18,12 +18,11 @@ const defaultRenderer: Partial = { } export function RowLinks(props: RowLinksProps) { - const { renderer, ...RowLinksProps } = props + const { renderer, linksVariant, ...RowLinksProps } = props - let { linksVariant } = props const mergedRenderer = { ...defaultRenderer, ...renderer } as VariantRenderer - if (!linksVariant) linksVariant = 'Inline' + if (!linksVariant) return null const RenderType = mergedRenderer?.[linksVariant] ?? diff --git a/examples/magento-graphcms/components/GraphCMS/RowLinks/variant/Usps.tsx b/examples/magento-graphcms/components/GraphCMS/RowLinks/variant/Usps.tsx index 7cc5520c749..77df6834346 100644 --- a/examples/magento-graphcms/components/GraphCMS/RowLinks/variant/Usps.tsx +++ b/examples/magento-graphcms/components/GraphCMS/RowLinks/variant/Usps.tsx @@ -1,6 +1,7 @@ import { RichText } from '@graphcommerce/graphcms-ui' import { iconCheckmark, IconSvg, VariantUsps } from '@graphcommerce/next-ui' import { Box } from '@mui/material' + import { RowLinksFragment } from '../RowLinks.gql' export function Usps(props: RowLinksFragment) { diff --git a/examples/magento-graphcms/components/GraphCMS/RowProduct/RowProduct.tsx b/examples/magento-graphcms/components/GraphCMS/RowProduct/RowProduct.tsx index 7be8be23d79..afa2859729d 100644 --- a/examples/magento-graphcms/components/GraphCMS/RowProduct/RowProduct.tsx +++ b/examples/magento-graphcms/components/GraphCMS/RowProduct/RowProduct.tsx @@ -1,7 +1,5 @@ import { InContextMaskProvider, useInContextQuery } from '@graphcommerce/graphql' -import { ProductListItemRenderer, ProductListDocument } from '@graphcommerce/magento-product' -import { filterNonNullableKeys } from '@graphcommerce/next-ui' -import { productListRenderer } from '../../ProductListItems' +import { GetRowProductCategoryDocument } from './GetRowProductCategory.gql' import { RowProductFragment } from './RowProduct.gql' import { Backstory, @@ -14,11 +12,10 @@ import { Swipeable, Upsells, } from './variant' -import { GetRowProductCategoryDocument } from './GetRowProductCategory.gql' type VariantRenderer = Record< NonNullable, - React.FC + React.FC > type RowProductProps = RowProductFragment & { @@ -38,8 +35,7 @@ const defaultRenderer: Partial = { } export function RowProduct(props: RowProductProps) { - const { renderer, category } = props - let { variant } = props + const { renderer, variant, category, ...rest } = props const mergedRenderer = { ...defaultRenderer, ...renderer } as VariantRenderer const scoped = useInContextQuery( @@ -48,7 +44,7 @@ export function RowProduct(props: RowProductProps) { { categories: { items: category ? [category] : [] } }, ) - if (!variant) variant = 'Related' + if (!variant) return null const RenderType = mergedRenderer?.[variant] ?? @@ -59,11 +55,7 @@ export function RowProduct(props: RowProductProps) { return ( - + ) } diff --git a/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Backstory.tsx b/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Backstory.tsx index 138d4b9adc9..11efd88e3f5 100644 --- a/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Backstory.tsx +++ b/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Backstory.tsx @@ -1,13 +1,14 @@ import { Asset, RichText } from '@graphcommerce/graphcms-ui' -import { AddProductsToCartForm, ProductListItemRenderer } from '@graphcommerce/magento-product' +import { AddProductsToCartForm } from '@graphcommerce/magento-product' import { ParagraphWithSidebarSlide, RenderType } from '@graphcommerce/next-ui' import { useTheme } from '@mui/material' +import { productListRenderer } from '../../../ProductListItems' import { RowProductFragment } from '../RowProduct.gql' -type BackstoryProps = RowProductFragment & { productListItemRenderer: ProductListItemRenderer } +type BackstoryProps = RowProductFragment export function Backstory(props: BackstoryProps) { - const { productCopy, asset, category, productListItemRenderer } = props + const { productCopy, asset, category } = props const theme = useTheme() const singleItem = category?.products?.items?.[(category?.products?.items?.length ?? 1) - 1] @@ -23,7 +24,7 @@ export function Backstory(props: BackstoryProps) { } slidingItems={ diff --git a/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Feature.tsx b/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Feature.tsx index ad3d7d24d94..e030a2ad499 100644 --- a/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Feature.tsx +++ b/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Feature.tsx @@ -1,11 +1,10 @@ import { RichText } from '@graphcommerce/graphcms-ui' import { Image } from '@graphcommerce/image' -import { ProductListItemRenderer } from '@graphcommerce/magento-product' import { ImageText } from '@graphcommerce/next-ui' import { Typography, useTheme } from '@mui/material' import { RowProductFragment } from '../RowProduct.gql' -type FeatureProps = RowProductFragment & { productListItemRenderer: ProductListItemRenderer } +type FeatureProps = RowProductFragment export function Feature(props: FeatureProps) { const { productCopy, title, category } = props diff --git a/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/FeatureBoxed.tsx b/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/FeatureBoxed.tsx index 2c984c0d9c6..64f064d578d 100644 --- a/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/FeatureBoxed.tsx +++ b/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/FeatureBoxed.tsx @@ -1,13 +1,11 @@ +import { RichText } from '@graphcommerce/graphcms-ui' import { Image } from '@graphcommerce/image' -import { ProductListItemRenderer } from '@graphcommerce/magento-product' import { ImageTextBoxed, responsiveVal } from '@graphcommerce/next-ui' import { Typography, useTheme } from '@mui/material' import { RowProductFragment } from '../RowProduct.gql' import { ProductFeatureMediaBoxedFragment } from './ProductFeatureMediaBoxed.gql' -import { RichText } from '@graphcommerce/graphcms-ui' -type FeatureBoxedProps = RowProductFragment & - ProductFeatureMediaBoxedFragment & { productListItemRenderer: ProductListItemRenderer } +type FeatureBoxedProps = RowProductFragment & ProductFeatureMediaBoxedFragment export function FeatureBoxed(props: FeatureBoxedProps) { const { productCopy, title, media_gallery } = props diff --git a/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Grid.tsx b/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Grid.tsx index 8f62a5a0d1c..6fa0e35914b 100644 --- a/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Grid.tsx +++ b/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Grid.tsx @@ -1,12 +1,13 @@ -import { ProductListItemRenderer, ProductListItemsBase } from '@graphcommerce/magento-product' +import { ProductListItemsBase } from '@graphcommerce/magento-product' import { ContainerWithHeader } from '@graphcommerce/next-ui' import { Link } from '@mui/material' +import { productListRenderer } from '../../../ProductListItems' import { RowProductFragment } from '../RowProduct.gql' -type GridProps = RowProductFragment & { productListItemRenderer: ProductListItemRenderer } +type GridProps = RowProductFragment export function Grid(props: GridProps) { - const { title, pageLinks, productListItemRenderer, category } = props + const { title, pageLinks, category } = props return ( & { productListItemRenderer: ProductListItemRenderer } +type RelatedProps = RowProductFragment & RelatedProductsFragment & Pick export function Related(props: RelatedProps) { - const { title, related_products, productListItemRenderer, sx } = props + const { title, related_products, sx } = props if (!related_products || related_products.length === 0) return null @@ -28,7 +23,7 @@ export function Related(props: RelatedProps) { item ? ( & { productListItemRenderer: ProductListItemRenderer } +type ReviewsProps = RowProductFragment & Partial export function Reviews(props: ReviewsProps) { const { title, reviews, url_key, review_count, sku } = props diff --git a/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Specs.tsx b/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Specs.tsx index 210e815dfac..dce125cd2b5 100644 --- a/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Specs.tsx +++ b/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Specs.tsx @@ -1,9 +1,8 @@ -import { ProductListItemRenderer, ProductSpecs } from '@graphcommerce/magento-product' +import { ProductSpecs } from '@graphcommerce/magento-product' import { ProductSpecsFragment } from '@graphcommerce/magento-product/components/ProductSpecs/ProductSpecs.gql' import { RowProductFragment } from '../RowProduct.gql' -type SpecsProps = RowProductFragment & - ProductSpecsFragment & { productListItemRenderer: ProductListItemRenderer } +type SpecsProps = RowProductFragment & ProductSpecsFragment export function Specs(props: SpecsProps) { const { title, aggregations } = props diff --git a/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Swipeable.tsx b/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Swipeable.tsx index 0a00b05f1d8..e5086d718d3 100644 --- a/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Swipeable.tsx +++ b/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Swipeable.tsx @@ -1,4 +1,4 @@ -import { AddProductsToCartForm, ProductListItemRenderer } from '@graphcommerce/magento-product' +import { AddProductsToCartForm } from '@graphcommerce/magento-product' import { filterNonNullableKeys, RenderType, @@ -7,13 +7,13 @@ import { SidebarSliderProps, } from '@graphcommerce/next-ui' import { Typography } from '@mui/material' +import { productListRenderer } from '../../../ProductListItems' import { RowProductFragment } from '../RowProduct.gql' -type SwipeableProps = RowProductFragment & - Pick & { productListItemRenderer: ProductListItemRenderer } +type SwipeableProps = RowProductFragment & Pick export function Swipeable(props: SwipeableProps) { - const { title, category, productListItemRenderer, sx = [] } = props + const { title, category, sx = [] } = props const items = filterNonNullableKeys(category?.products?.items) if (items.length === 0) return null @@ -38,7 +38,7 @@ export function Swipeable(props: SwipeableProps) { {items.map((item) => ( & { productListItemRenderer: ProductListItemRenderer } +type UpsellsProps = RowProductFragment & UpsellProductsFragment & Pick export function Upsells(props: UpsellsProps) { - const { title, upsell_products, productListItemRenderer, sx } = props + const { title, upsell_products, sx } = props if (!upsell_products || upsell_products.length === 0) return null @@ -28,7 +23,7 @@ export function Upsells(props: UpsellsProps) { item ? ( Date: Tue, 23 Jul 2024 17:15:26 +0200 Subject: [PATCH 20/33] Cleanup --- .../GraphCMS/RowProduct/variant/Grid.tsx | 6 ++--- .../GraphCMS/RowProduct/variant/Swipeable.tsx | 25 +++++++++++-------- .../GraphCMS/RowProduct/variant/Upsells.tsx | 2 +- .../components/GraphCMS/RowQuote/RowQuote.tsx | 1 + 4 files changed, 18 insertions(+), 16 deletions(-) diff --git a/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Grid.tsx b/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Grid.tsx index 6fa0e35914b..1fe333e98c3 100644 --- a/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Grid.tsx +++ b/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Grid.tsx @@ -1,7 +1,6 @@ -import { ProductListItemsBase } from '@graphcommerce/magento-product' import { ContainerWithHeader } from '@graphcommerce/next-ui' import { Link } from '@mui/material' -import { productListRenderer } from '../../../ProductListItems' +import { ProductListItems } from '../../../ProductListItems' import { RowProductFragment } from '../RowProduct.gql' type GridProps = RowProductFragment @@ -18,8 +17,7 @@ export function Grid(props: GridProps) { ))} > - export function Swipeable(props: SwipeableProps) { const { title, category, sx = [] } = props - const items = filterNonNullableKeys(category?.products?.items) - if (items.length === 0) return null + const items = category?.products?.items + if (!items || items.length === 0) return null return ( @@ -35,15 +35,18 @@ export function Swipeable(props: SwipeableProps) { } > - {items.map((item) => ( - - ))} + {items.map((item) => { + if (!item) return null + return ( + + ) + })} ) diff --git a/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Upsells.tsx b/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Upsells.tsx index 9f5136be2a8..ab1a496cbed 100644 --- a/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Upsells.tsx +++ b/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Upsells.tsx @@ -6,7 +6,7 @@ import { SidebarSliderProps, } from '@graphcommerce/next-ui' import { Typography } from '@mui/material' -import { productListRenderer } from '../../../ProductListItems' +import { productListRenderer } from '../../../ProductListItems/productListRenderer' import { RowProductFragment } from '../RowProduct.gql' type UpsellsProps = RowProductFragment & UpsellProductsFragment & Pick diff --git a/examples/magento-graphcms/components/GraphCMS/RowQuote/RowQuote.tsx b/examples/magento-graphcms/components/GraphCMS/RowQuote/RowQuote.tsx index 81e01dfb727..b41a13822b8 100644 --- a/examples/magento-graphcms/components/GraphCMS/RowQuote/RowQuote.tsx +++ b/examples/magento-graphcms/components/GraphCMS/RowQuote/RowQuote.tsx @@ -1,5 +1,6 @@ import { RichText } from '@graphcommerce/graphcms-ui' import { Quote } from '@graphcommerce/next-ui' +import React from 'react' import { RowQuoteFragment } from './RowQuote.gql' type RowQuoteProps = RowQuoteFragment From 4304444f39bc18700349a5684234e2c2269b06a7 Mon Sep 17 00:00:00 2001 From: Paul Hachmang Date: Tue, 23 Jul 2024 17:19:58 +0200 Subject: [PATCH 21/33] Cleanup --- .../components/GraphCMS/RowLinks/RowLinks.tsx | 2 +- .../components/GraphCMS/RowRenderer.tsx | 7 +++---- .../GraphCMS/RowSpecialBanner/RowSpecialBanner.tsx | 2 +- .../ProductListItems/CategoryFilterLayout.tsx | 11 +---------- examples/magento-graphcms/components/Usps/Usps.tsx | 2 +- 5 files changed, 7 insertions(+), 17 deletions(-) diff --git a/examples/magento-graphcms/components/GraphCMS/RowLinks/RowLinks.tsx b/examples/magento-graphcms/components/GraphCMS/RowLinks/RowLinks.tsx index a5c723020f3..ae1170169d4 100644 --- a/examples/magento-graphcms/components/GraphCMS/RowLinks/RowLinks.tsx +++ b/examples/magento-graphcms/components/GraphCMS/RowLinks/RowLinks.tsx @@ -1,3 +1,4 @@ +import {} from '@graphcommerce/graphcms-ui' import { RowLinksFragment } from './RowLinks.gql' import { LogoSwiper, ImageLabelSwiper, Inline, Usps } from './variant' @@ -19,7 +20,6 @@ const defaultRenderer: Partial = { export function RowLinks(props: RowLinksProps) { const { renderer, linksVariant, ...RowLinksProps } = props - const mergedRenderer = { ...defaultRenderer, ...renderer } as VariantRenderer if (!linksVariant) return null diff --git a/examples/magento-graphcms/components/GraphCMS/RowRenderer.tsx b/examples/magento-graphcms/components/GraphCMS/RowRenderer.tsx index 8c8ebfbe719..d8d4dcc79b4 100644 --- a/examples/magento-graphcms/components/GraphCMS/RowRenderer.tsx +++ b/examples/magento-graphcms/components/GraphCMS/RowRenderer.tsx @@ -1,5 +1,4 @@ import { GCPage_DataFragment } from '@graphcommerce/content-areas' -import { ProductListItemRenderer } from '@graphcommerce/magento-product' import { LazyHydrate, RenderType, TypeRenderer } from '@graphcommerce/next-ui' import { memo } from 'react' import { RowBlogContent } from '../Blog' @@ -16,16 +15,16 @@ import { RowRendererFragment } from './RowRenderer.gql' import { RowServiceOptions } from './RowServiceOptions/RowServiceOptions' import { RowSpecialBanner } from './RowSpecialBanner/RowSpecialBanner' -export type ContentTypeRenderer = TypeRenderer +type ContentTypeRenderer = TypeRenderer -export const defaultRenderer: { [key: string]: (props) => React.ReactElement } = { +const defaultRenderer: Partial = { RowColumnOne, RowColumnTwo, RowColumnThree, RowHeroBanner, RowSpecialBanner, RowQuote, - // // RowBlogContent, + RowBlogContent, RowButtonLinkList, RowServiceOptions, RowContentLinks, diff --git a/examples/magento-graphcms/components/GraphCMS/RowSpecialBanner/RowSpecialBanner.tsx b/examples/magento-graphcms/components/GraphCMS/RowSpecialBanner/RowSpecialBanner.tsx index b2e97fec07d..6bde87c3b32 100644 --- a/examples/magento-graphcms/components/GraphCMS/RowSpecialBanner/RowSpecialBanner.tsx +++ b/examples/magento-graphcms/components/GraphCMS/RowSpecialBanner/RowSpecialBanner.tsx @@ -1,4 +1,4 @@ -import { Asset, RichText } from '@graphcommerce/graphcms-ui' +import { RichText, Asset } from '@graphcommerce/graphcms-ui' import { breakpointVal, SpecialBanner } from '@graphcommerce/next-ui' import { Link } from '@mui/material' import { RowSpecialBannerFragment } from './RowSpecialBanner.gql' diff --git a/examples/magento-graphcms/components/ProductListItems/CategoryFilterLayout.tsx b/examples/magento-graphcms/components/ProductListItems/CategoryFilterLayout.tsx index 4017df069e2..a912fa13089 100644 --- a/examples/magento-graphcms/components/ProductListItems/CategoryFilterLayout.tsx +++ b/examples/magento-graphcms/components/ProductListItems/CategoryFilterLayout.tsx @@ -12,7 +12,6 @@ import { ProductListCount, ProductListFilters, ProductListFiltersContainer, - ProductListItemsBase, ProductListPagination, ProductListParams, ProductListParamsProvider, @@ -22,7 +21,6 @@ import { import { StickyBelowHeader } from '@graphcommerce/next-ui' import { Container } from '@mui/material' import { ProductListItems } from './ProductListItems' -import { productListRenderer } from './productListRenderer' export type ProductListFilterLayoutProps = ProductListQuery & ProductFiltersQuery & { @@ -39,14 +37,7 @@ export function CategoryFilterLayout(props: ProductListFilterLayoutProps) { const { total_count, sort_fields, page_info } = products - const items = ( - - ) + const items = if (import.meta.graphCommerce.productFiltersPro) { const horizontalFilters = ( diff --git a/examples/magento-graphcms/components/Usps/Usps.tsx b/examples/magento-graphcms/components/Usps/Usps.tsx index 7379f3b6462..f517692acd6 100644 --- a/examples/magento-graphcms/components/Usps/Usps.tsx +++ b/examples/magento-graphcms/components/Usps/Usps.tsx @@ -1,4 +1,4 @@ -import { Asset, RichText } from '@graphcommerce/graphcms-ui' +import { RichText, Asset } from '@graphcommerce/graphcms-ui' import { UspList, UspListItem, UspListProps } from '@graphcommerce/next-ui' import { UspsQueryFragment } from './UspsQueryFragment.gql' From 67ce3af3ae2fc6143856519184b50e21e43c685e Mon Sep 17 00:00:00 2001 From: Paul Hachmang Date: Mon, 29 Jul 2024 17:03:11 +0200 Subject: [PATCH 22/33] wi[ --- docs/framework/config.md | 24 +++ .../RowCategory/GetMagentoRowCategory.graphql | 7 + .../RowCategory/MagentoRowCategory.graphql | 15 ++ .../GraphCMS/RowCategory/RowCategory.graphql | 7 + .../GraphCMS/RowCategory/RowCategory.tsx | 50 ++++++ .../RowCategory/RowCategory_category.graphqls | 11 ++ .../GraphCMS/RowCategory/variant/Grid.tsx | 34 ++++ .../variant/Swipeable.tsx | 36 ++-- .../RowProduct/GetMagentoRowProduct.graphql | 8 + .../RowProduct/GetRowProductCategory.graphql | 7 - .../GraphCMS/RowProduct/RowProduct.graphql | 5 +- .../GraphCMS/RowProduct/RowProduct.tsx | 46 ++--- .../RowProduct/RowProductCategory.graphql | 11 -- .../RowProduct/RowProduct_product.graphqls | 6 +- .../GraphCMS/RowProduct/variant/Backstory.tsx | 8 +- .../GraphCMS/RowProduct/variant/Feature.tsx | 6 +- .../RowProduct/variant/FeatureBoxed.tsx | 7 +- .../GraphCMS/RowProduct/variant/Grid.tsx | 28 --- .../variant/ProductFeatureMedia.graphql | 9 - .../GraphCMS/RowProduct/variant/index.tsx | 2 - .../components/GraphCMS/RowRenderer.graphql | 1 + .../components/GraphCMS/RowRenderer.tsx | 4 +- examples/magento-graphcms/package.json | 2 +- examples/magento-graphcms/pages/[...url].tsx | 7 +- .../pages/blog/page/[page].tsx | 2 +- .../pages/blog/tagged/[url].tsx | 2 +- examples/magento-graphcms/pages/index.tsx | 18 +- .../magento-graphcms/pages/modal/[...url].tsx | 2 +- examples/magento-graphcms/pages/p/[url].tsx | 2 +- .../pages/service/[[...url]].tsx | 2 +- .../plugins/hygraph/HygraphContentArea.tsx | 4 +- packages/content-areas/queries/GcPage.graphql | 5 - .../content-areas/queries/GcPage_Data.graphql | 9 - .../schema/Query_gcPage.graphqls | 27 --- .../components/PreviewMode/PreviewMode.tsx | 1 - .../README.md | 0 .../components/ContentArea/Areas.tsx | 0 .../components/ContentArea/ContentArea.tsx | 0 .../components/ContentArea/index.ts | 0 .../components/GcPageMeta/GcPageHead.graphql | 32 ++++ .../components/GcPageMeta/GcPageHead.tsx | 57 ++++++ .../components/GcPageMeta/index.ts | 2 + .../components/index.ts | 0 .../index.ts | 1 + .../package.json | 2 +- .../graphql-gc-api/queries/GcPage.graphql | 5 + .../queries/GcPage_Data.graphql | 4 + .../graphql-gc-api/schema/GcPageHead.graphqls | 70 ++++++++ .../schema/GcPageInterface.graphqls | 14 ++ .../schema/Query_gcCanonicals.graphqls | 14 ++ .../schema/Query_gcPage.graphqls | 7 + .../server.ts | 0 packages/graphql-mesh/directive/mesh.graphqls | 5 + packages/graphql-mesh/index.ts | 2 + packages/graphql-mesh/package.json | 1 + packages/graphql-mesh/utils/executeMesh.ts | 166 ++++++++++++++++++ packages/graphql-mesh/utils/meshCache.ts | 35 ++++ packages/graphql/apollo-client.graphql | 5 - .../graphql/AllDynamicRows.graphql | 23 +-- .../lib/hygraphDynamicRows.ts | 57 +++--- .../hygraph-dynamic-rows/mesh/resolvers.ts | 60 +++++++ packages/hygraph-dynamic-rows/package.json | 1 + .../plugins/meshConfigDynamicRows.ts | 18 ++ .../hygraph-ui/components/Asset/Asset.tsx | 2 +- .../hygraph-ui/graphql/GCPage_Hygraph.graphql | 2 +- .../hygraph-ui/graphql/GcPage_Hygraph.graphql | 3 + .../hygraph-ui/graphql/HygraphPage.graphql | 3 - .../plugins/HygraphPreviewModeToolbar.tsx | 2 +- .../hygraph-ui/schema/Query_gcPage.graphqls | 19 +- .../components/CategoryMeta/CategoryMeta.tsx | 84 ++++----- .../link/xMagentoCacheIdHeader.ts | 9 +- .../Api/ProductListItem.graphql | 9 +- packages/magento-store/PageMeta.tsx | 28 +-- packages/next-ui/PageMeta/PageMeta.tsx | 17 +- packages/next-ui/PageMeta/PageMetaNew.tsx | 59 ------- packages/next-ui/PageMeta/canonicalize.ts | 5 + .../dist/index.js | 1 + .../src/index.ts | 1 + .../next-config/dist/generated/config.js | 5 + .../next-config/src/generated/config.ts | 23 +++ yarn.lock | 68 ++++--- 81 files changed, 929 insertions(+), 407 deletions(-) create mode 100644 examples/magento-graphcms/components/GraphCMS/RowCategory/GetMagentoRowCategory.graphql create mode 100644 examples/magento-graphcms/components/GraphCMS/RowCategory/MagentoRowCategory.graphql create mode 100644 examples/magento-graphcms/components/GraphCMS/RowCategory/RowCategory.graphql create mode 100644 examples/magento-graphcms/components/GraphCMS/RowCategory/RowCategory.tsx create mode 100644 examples/magento-graphcms/components/GraphCMS/RowCategory/RowCategory_category.graphqls create mode 100644 examples/magento-graphcms/components/GraphCMS/RowCategory/variant/Grid.tsx rename examples/magento-graphcms/components/GraphCMS/{RowProduct => RowCategory}/variant/Swipeable.tsx (57%) create mode 100644 examples/magento-graphcms/components/GraphCMS/RowProduct/GetMagentoRowProduct.graphql delete mode 100644 examples/magento-graphcms/components/GraphCMS/RowProduct/GetRowProductCategory.graphql delete mode 100644 examples/magento-graphcms/components/GraphCMS/RowProduct/RowProductCategory.graphql rename packages/hygraph-ui/schema/RowProduct_category.graphqls => examples/magento-graphcms/components/GraphCMS/RowProduct/RowProduct_product.graphqls (54%) delete mode 100644 examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Grid.tsx delete mode 100644 examples/magento-graphcms/components/GraphCMS/RowProduct/variant/ProductFeatureMedia.graphql delete mode 100644 packages/content-areas/queries/GcPage.graphql delete mode 100644 packages/content-areas/queries/GcPage_Data.graphql delete mode 100644 packages/content-areas/schema/Query_gcPage.graphqls rename packages/{content-areas => graphql-gc-api}/README.md (100%) rename packages/{content-areas => graphql-gc-api}/components/ContentArea/Areas.tsx (100%) rename packages/{content-areas => graphql-gc-api}/components/ContentArea/ContentArea.tsx (100%) rename packages/{content-areas => graphql-gc-api}/components/ContentArea/index.ts (100%) create mode 100644 packages/graphql-gc-api/components/GcPageMeta/GcPageHead.graphql create mode 100644 packages/graphql-gc-api/components/GcPageMeta/GcPageHead.tsx create mode 100644 packages/graphql-gc-api/components/GcPageMeta/index.ts rename packages/{content-areas => graphql-gc-api}/components/index.ts (100%) rename packages/{content-areas => graphql-gc-api}/index.ts (72%) rename packages/{content-areas => graphql-gc-api}/package.json (96%) create mode 100644 packages/graphql-gc-api/queries/GcPage.graphql create mode 100644 packages/graphql-gc-api/queries/GcPage_Data.graphql create mode 100644 packages/graphql-gc-api/schema/GcPageHead.graphqls create mode 100644 packages/graphql-gc-api/schema/GcPageInterface.graphqls create mode 100644 packages/graphql-gc-api/schema/Query_gcCanonicals.graphqls create mode 100644 packages/graphql-gc-api/schema/Query_gcPage.graphqls rename packages/{content-areas => graphql-gc-api}/server.ts (100%) create mode 100644 packages/graphql-mesh/utils/executeMesh.ts create mode 100644 packages/graphql-mesh/utils/meshCache.ts create mode 100644 packages/hygraph-dynamic-rows/mesh/resolvers.ts create mode 100644 packages/hygraph-dynamic-rows/plugins/meshConfigDynamicRows.ts create mode 100644 packages/hygraph-ui/graphql/GcPage_Hygraph.graphql delete mode 100644 packages/next-ui/PageMeta/PageMetaNew.tsx diff --git a/docs/framework/config.md b/docs/framework/config.md index 3d080536580..864a3d1d5d6 100644 --- a/docs/framework/config.md +++ b/docs/framework/config.md @@ -85,6 +85,22 @@ Below is a list of all possible configurations that can be set by GraphCommerce. ### GraphCommerceConfig +#### algoliaApplicationId: string (required) + +Configure your Algolia application ID. + +Stores > Configuration > Algolia Search > Credentials and Basic Setup > Application ID + +#### algoliaIndexNamePrefix: string (required) + +Stores > Configuration > Algolia Search > Credentials and Basic Setup > Index name prefix + +#### algoliaSearchOnlyApiKey: string (required) + +Configure your Algolia Search Only API Key. + +Stores > Configuration > Algolia Search > Credentials and Basic Setup > Search-only (public) API key + #### canonicalBaseUrl: string (required) The canonical base URL is used for SEO purposes. @@ -119,6 +135,10 @@ Values: 245, 246, 247 for Magento 2.4.5, 2.4.6, 2.4.7 respectively. All storefront configuration for the project +#### algoliaCatalogEnabled: boolean + +By default the catalog will not use algolia. Set this to true to enable Algolia for the catalog. + #### breadcrumbs: boolean = `false` Configuration for the SidebarGallery component @@ -390,6 +410,10 @@ Examples: - en-us - b2b-us +#### algoliaIndexNamePrefix: string + +Stores > Configuration > Algolia Search > Credentials and Basic Setup > Index name prefix + #### canonicalBaseUrl: string The canonical base URL is used for SEO purposes. diff --git a/examples/magento-graphcms/components/GraphCMS/RowCategory/GetMagentoRowCategory.graphql b/examples/magento-graphcms/components/GraphCMS/RowCategory/GetMagentoRowCategory.graphql new file mode 100644 index 00000000000..3255de759d4 --- /dev/null +++ b/examples/magento-graphcms/components/GraphCMS/RowCategory/GetMagentoRowCategory.graphql @@ -0,0 +1,7 @@ +query GetMagentoRowCategory($uid: String!) { + categories(filters: { category_uid: { eq: $uid } }) { + items { + ...MagentoRowCategory + } + } +} diff --git a/examples/magento-graphcms/components/GraphCMS/RowCategory/MagentoRowCategory.graphql b/examples/magento-graphcms/components/GraphCMS/RowCategory/MagentoRowCategory.graphql new file mode 100644 index 00000000000..d42cfe757fc --- /dev/null +++ b/examples/magento-graphcms/components/GraphCMS/RowCategory/MagentoRowCategory.graphql @@ -0,0 +1,15 @@ +fragment MagentoRowCategory on CategoryTree { + uid + name + url_path + include_in_menu + available_sort_by + ...CategoryDescription + products(pageSize: 8) { + items { + __typename + uid + ...ProductListItem + } + } +} diff --git a/examples/magento-graphcms/components/GraphCMS/RowCategory/RowCategory.graphql b/examples/magento-graphcms/components/GraphCMS/RowCategory/RowCategory.graphql new file mode 100644 index 00000000000..f8d9bfc3681 --- /dev/null +++ b/examples/magento-graphcms/components/GraphCMS/RowCategory/RowCategory.graphql @@ -0,0 +1,7 @@ +fragment RowCategory on RowCategory { + categoryUrl + rowCategoryVariant: variant + category { + ...MagentoRowCategory + } +} diff --git a/examples/magento-graphcms/components/GraphCMS/RowCategory/RowCategory.tsx b/examples/magento-graphcms/components/GraphCMS/RowCategory/RowCategory.tsx new file mode 100644 index 00000000000..93283c75e2a --- /dev/null +++ b/examples/magento-graphcms/components/GraphCMS/RowCategory/RowCategory.tsx @@ -0,0 +1,50 @@ +import { InContextMaskProvider, useInContextQuery } from '@graphcommerce/graphql' +import { GetMagentoRowCategoryDocument } from './GetMagentoRowCategory.gql' +import { RowCategoryFragment } from './RowCategory.gql' +import { Grid } from './variant/Grid' +import { Swipeable } from './variant/Swipeable' + +type VariantRenderer = Record< + NonNullable, + React.FC +> + +type RowCategoryProps = RowCategoryFragment & { + renderer?: Partial +} & { sku?: string | null | undefined } + +const defaultRenderer: Partial = { + Grid, + Swipeable, +} + +export function RowCategory(props: RowCategoryProps) { + const { renderer, rowCategoryVariant, category, ...rest } = props + const mergedRenderer = { ...defaultRenderer, ...renderer } as VariantRenderer + + const scoped = useInContextQuery( + GetMagentoRowCategoryDocument, + { variables: { uid: category?.uid ?? '' }, skip: !category?.uid }, + { categories: { items: category ? [category] : [] } }, + ) + + if (!rowCategoryVariant) return null + + const RenderType = + mergedRenderer?.[rowCategoryVariant] ?? + (() => { + if (process.env.NODE_ENV !== 'production') + return <>renderer for {rowCategoryVariant} not found + return null + }) + + return ( + + + + ) +} diff --git a/examples/magento-graphcms/components/GraphCMS/RowCategory/RowCategory_category.graphqls b/examples/magento-graphcms/components/GraphCMS/RowCategory/RowCategory_category.graphqls new file mode 100644 index 00000000000..42b2cdc5283 --- /dev/null +++ b/examples/magento-graphcms/components/GraphCMS/RowCategory/RowCategory_category.graphqls @@ -0,0 +1,11 @@ +extend type RowCategory { + category: CategoryTree + @resolveTo( + sourceName: "m2" + sourceTypeName: "Query" + sourceFieldName: "categories" + requiredSelectionSet: "{ categoryUrl }" + sourceArgs: { filters: { url_key: { eq: "{root.categoryUrl}" } } } + result: "items[0]" + ) +} diff --git a/examples/magento-graphcms/components/GraphCMS/RowCategory/variant/Grid.tsx b/examples/magento-graphcms/components/GraphCMS/RowCategory/variant/Grid.tsx new file mode 100644 index 00000000000..8678a836823 --- /dev/null +++ b/examples/magento-graphcms/components/GraphCMS/RowCategory/variant/Grid.tsx @@ -0,0 +1,34 @@ +import { productListLink } from '@graphcommerce/magento-product' +import { ContainerWithHeader } from '@graphcommerce/next-ui' +import { Link } from '@mui/material' +import { ProductListItems } from '../../../ProductListItems' +import { RowCategoryFragment } from '../RowCategory.gql' + +type GridProps = RowCategoryFragment + +export function Grid(props: GridProps) { + const { category } = props + + if (!category?.name) return null + const { name, include_in_menu, url_path, products } = category + + return ( + + {name} + + ) + } + > + + + ) +} diff --git a/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Swipeable.tsx b/examples/magento-graphcms/components/GraphCMS/RowCategory/variant/Swipeable.tsx similarity index 57% rename from examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Swipeable.tsx rename to examples/magento-graphcms/components/GraphCMS/RowCategory/variant/Swipeable.tsx index c4bae36e096..c5294e57075 100644 --- a/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Swipeable.tsx +++ b/examples/magento-graphcms/components/GraphCMS/RowCategory/variant/Swipeable.tsx @@ -8,15 +8,18 @@ import { } from '@graphcommerce/next-ui' import { Typography } from '@mui/material' import { productListRenderer } from '../../../ProductListItems' -import { RowProductFragment } from '../RowProduct.gql' +import { RowCategoryFragment } from '../RowCategory.gql' -type SwipeableProps = RowProductFragment & Pick +type SwipeableProps = RowCategoryFragment & Pick export function Swipeable(props: SwipeableProps) { - const { title, category, sx = [] } = props + const { category, sx = [] } = props - const items = category?.products?.items - if (!items || items.length === 0) return null + // const items = category?.products?.items + if (!category || !category.products?.items) return null + + const { name } = category + const items = filterNonNullableKeys(category.products.items) return ( @@ -31,22 +34,19 @@ export function Swipeable(props: SwipeableProps) { ]} sidebar={ - {title} + {name} } > - {items.map((item) => { - if (!item) return null - return ( - - ) - })} + {items.map((item) => ( + + ))} ) diff --git a/examples/magento-graphcms/components/GraphCMS/RowProduct/GetMagentoRowProduct.graphql b/examples/magento-graphcms/components/GraphCMS/RowProduct/GetMagentoRowProduct.graphql new file mode 100644 index 00000000000..b09efb07cca --- /dev/null +++ b/examples/magento-graphcms/components/GraphCMS/RowProduct/GetMagentoRowProduct.graphql @@ -0,0 +1,8 @@ +query GetMagentoRowProduct($urlKey: String!) { + products(filter: { url_key: { eq: $urlKey } }, pageSize: 1) { + items { + ...ProductListItem + ...ProductFeatureMediaBoxed + } + } +} diff --git a/examples/magento-graphcms/components/GraphCMS/RowProduct/GetRowProductCategory.graphql b/examples/magento-graphcms/components/GraphCMS/RowProduct/GetRowProductCategory.graphql deleted file mode 100644 index 679f77ecd91..00000000000 --- a/examples/magento-graphcms/components/GraphCMS/RowProduct/GetRowProductCategory.graphql +++ /dev/null @@ -1,7 +0,0 @@ -query GetRowProductCategory($category_uid: String!) { - categories(filters: { category_uid: { eq: $category_uid } }) { - items { - ...RowProductCategory - } - } -} diff --git a/examples/magento-graphcms/components/GraphCMS/RowProduct/RowProduct.graphql b/examples/magento-graphcms/components/GraphCMS/RowProduct/RowProduct.graphql index 180c3c96b27..94ce025b4f6 100644 --- a/examples/magento-graphcms/components/GraphCMS/RowProduct/RowProduct.graphql +++ b/examples/magento-graphcms/components/GraphCMS/RowProduct/RowProduct.graphql @@ -11,7 +11,8 @@ fragment RowProduct on RowProduct { pageLinks { ...PageLink } - category { - ...RowProductCategory + product { + ...ProductListItem + ...ProductFeatureMediaBoxed } } diff --git a/examples/magento-graphcms/components/GraphCMS/RowProduct/RowProduct.tsx b/examples/magento-graphcms/components/GraphCMS/RowProduct/RowProduct.tsx index afa2859729d..09823813d48 100644 --- a/examples/magento-graphcms/components/GraphCMS/RowProduct/RowProduct.tsx +++ b/examples/magento-graphcms/components/GraphCMS/RowProduct/RowProduct.tsx @@ -1,47 +1,49 @@ import { InContextMaskProvider, useInContextQuery } from '@graphcommerce/graphql' -import { GetRowProductCategoryDocument } from './GetRowProductCategory.gql' +import { ProductListItemRenderer } from '@graphcommerce/magento-product' +import { Box } from '@mui/material' +import { productListRenderer } from '../../ProductListItems' +import { GetMagentoRowProductDocument } from './GetMagentoRowProduct.gql' import { RowProductFragment } from './RowProduct.gql' -import { - Backstory, - Feature, - FeatureBoxed, - Grid, - Related, - Reviews, - Specs, - Swipeable, - Upsells, -} from './variant' +import { Backstory, Feature, FeatureBoxed, Related, Reviews, Specs, Upsells } from './variant' type VariantRenderer = Record< NonNullable, - React.FC + React.FC > type RowProductProps = RowProductFragment & { renderer?: Partial } & { sku?: string | null | undefined } +function Migrate(props: RowProductFragment) { + const { variant, identity } = props + return ( + + NOT FOUND: Please migrate `{identity}` with variant {variant} to a RowCategory component + + ) +} + const defaultRenderer: Partial = { Specs, Backstory, Feature, FeatureBoxed, - Grid, Related, Reviews, Upsells, - Swipeable, + Grid: Migrate, + Swipeable: Migrate, } export function RowProduct(props: RowProductProps) { - const { renderer, variant, category, ...rest } = props + const { renderer, variant, product } = props const mergedRenderer = { ...defaultRenderer, ...renderer } as VariantRenderer const scoped = useInContextQuery( - GetRowProductCategoryDocument, - { variables: { category_uid: category?.uid ?? '' }, skip: !category?.uid }, - { categories: { items: category ? [category] : [] } }, + GetMagentoRowProductDocument, + { variables: { urlKey: product?.url_key ?? '' }, skip: !product?.url_key }, + { products: { items: [product!] } }, ) if (!variant) return null @@ -55,7 +57,11 @@ export function RowProduct(props: RowProductProps) { return ( - + ) } diff --git a/examples/magento-graphcms/components/GraphCMS/RowProduct/RowProductCategory.graphql b/examples/magento-graphcms/components/GraphCMS/RowProduct/RowProductCategory.graphql deleted file mode 100644 index 292f39e9414..00000000000 --- a/examples/magento-graphcms/components/GraphCMS/RowProduct/RowProductCategory.graphql +++ /dev/null @@ -1,11 +0,0 @@ -fragment RowProductCategory on CategoryTree { - uid - name - products(pageSize: 8) { - items { - __typename - uid - ...ProductListItem - } - } -} diff --git a/packages/hygraph-ui/schema/RowProduct_category.graphqls b/examples/magento-graphcms/components/GraphCMS/RowProduct/RowProduct_product.graphqls similarity index 54% rename from packages/hygraph-ui/schema/RowProduct_category.graphqls rename to examples/magento-graphcms/components/GraphCMS/RowProduct/RowProduct_product.graphqls index c3aaf855908..b03d5c7c235 100644 --- a/packages/hygraph-ui/schema/RowProduct_category.graphqls +++ b/examples/magento-graphcms/components/GraphCMS/RowProduct/RowProduct_product.graphqls @@ -1,11 +1,11 @@ extend type RowProduct { - category: CategoryTree + product: ProductInterface @resolveTo( sourceName: "m2" sourceTypeName: "Query" - sourceFieldName: "categories" + sourceFieldName: "products" requiredSelectionSet: "{ identity }" - sourceArgs: { filters: { url_key: { eq: "{root.identity}" } } } + sourceArgs: { filter: { url_key: { eq: "{root.identity}" } }, pageSize: 1 } result: "items[0]" ) } diff --git a/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Backstory.tsx b/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Backstory.tsx index 11efd88e3f5..6e819f01b44 100644 --- a/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Backstory.tsx +++ b/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Backstory.tsx @@ -8,11 +8,9 @@ import { RowProductFragment } from '../RowProduct.gql' type BackstoryProps = RowProductFragment export function Backstory(props: BackstoryProps) { - const { productCopy, asset, category } = props + const { productCopy, asset, product } = props const theme = useTheme() - const singleItem = category?.products?.items?.[(category?.products?.items?.length ?? 1) - 1] - - if (!singleItem) return null + if (!product) return null return ( @@ -25,7 +23,7 @@ export function Backstory(props: BackstoryProps) { slidingItems={ } diff --git a/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Feature.tsx b/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Feature.tsx index e030a2ad499..d368abca464 100644 --- a/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Feature.tsx +++ b/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Feature.tsx @@ -7,16 +7,16 @@ import { RowProductFragment } from '../RowProduct.gql' type FeatureProps = RowProductFragment export function Feature(props: FeatureProps) { - const { productCopy, title, category } = props + const { productCopy, title, product } = props const theme = useTheme() - const firstProduct = category?.products?.items?.[0] - const item = firstProduct?.small_image + const item = product?.media_gallery?.[1] ?? product?.media_gallery?.[0] if (!item) return null return ( ( - - {pageLink.title} - - ))} - > - - - ) -} diff --git a/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/ProductFeatureMedia.graphql b/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/ProductFeatureMedia.graphql deleted file mode 100644 index 2177cbda4ad..00000000000 --- a/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/ProductFeatureMedia.graphql +++ /dev/null @@ -1,9 +0,0 @@ -fragment ProductFeatureMedia on ProductInterface { - media_gallery { - label - __typename - ... on ProductImage { - url - } - } -} diff --git a/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/index.tsx b/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/index.tsx index a7123ddae51..963541a9a69 100644 --- a/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/index.tsx +++ b/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/index.tsx @@ -1,9 +1,7 @@ export * from './Backstory' export * from './Feature' export * from './FeatureBoxed' -export * from './Grid' export * from './Related' export * from './Reviews' export * from './Specs' -export * from './Swipeable' export * from './Upsells' diff --git a/examples/magento-graphcms/components/GraphCMS/RowRenderer.graphql b/examples/magento-graphcms/components/GraphCMS/RowRenderer.graphql index 318ee2e4fc0..476015b3bfa 100644 --- a/examples/magento-graphcms/components/GraphCMS/RowRenderer.graphql +++ b/examples/magento-graphcms/components/GraphCMS/RowRenderer.graphql @@ -16,5 +16,6 @@ fragment RowRenderer on Page @inject(into: ["HygraphPage"]) { ...RowContentLinks ...RowProduct ...RowLinks + ...RowCategory } } diff --git a/examples/magento-graphcms/components/GraphCMS/RowRenderer.tsx b/examples/magento-graphcms/components/GraphCMS/RowRenderer.tsx index d8d4dcc79b4..b1904fd719b 100644 --- a/examples/magento-graphcms/components/GraphCMS/RowRenderer.tsx +++ b/examples/magento-graphcms/components/GraphCMS/RowRenderer.tsx @@ -1,8 +1,9 @@ -import { GCPage_DataFragment } from '@graphcommerce/content-areas' +import { GCPage_DataFragment } from '@graphcommerce/graphql-gc-api' import { LazyHydrate, RenderType, TypeRenderer } from '@graphcommerce/next-ui' import { memo } from 'react' import { RowBlogContent } from '../Blog' import { RowButtonLinkList } from './RowButtonLinkList/RowButtonLinkList' +import { RowCategory } from './RowCategory/RowCategory' import { RowColumnOne } from './RowColumnOne/RowColumnOne' import { RowColumnThree } from './RowColumnThree/RowColumnThree' import { RowColumnTwo } from './RowColumnTwo/RowColumnTwo' @@ -30,6 +31,7 @@ const defaultRenderer: Partial = { RowContentLinks, RowProduct, RowLinks, + RowCategory, } export type PageProps = RowRendererFragment & { diff --git a/examples/magento-graphcms/package.json b/examples/magento-graphcms/package.json index 5cbc6bdf748..3a8eca23861 100644 --- a/examples/magento-graphcms/package.json +++ b/examples/magento-graphcms/package.json @@ -23,7 +23,6 @@ "@apollo/client": "~3.10.8", "@ducanh2912/next-pwa": "9.7.2", "@graphcommerce/cli": "9.0.0-canary.62", - "@graphcommerce/content-areas": "9.0.0-canary.62", "@graphcommerce/demo-magento-graphcommerce": "9.0.0-canary.62", "@graphcommerce/ecommerce-ui": "9.0.0-canary.62", "@graphcommerce/framer-next-pages": "9.0.0-canary.62", @@ -34,6 +33,7 @@ "@graphcommerce/googletagmanager": "9.0.0-canary.62", "@graphcommerce/graphcms-ui": "9.0.0-canary.62", "@graphcommerce/graphql": "9.0.0-canary.62", + "@graphcommerce/graphql-gc-api": "9.0.0-canary.62", "@graphcommerce/graphql-mesh": "9.0.0-canary.62", "@graphcommerce/hygraph-cli": "9.0.0-canary.62", "@graphcommerce/hygraph-dynamic-rows": "9.0.0-canary.62", diff --git a/examples/magento-graphcms/pages/[...url].tsx b/examples/magento-graphcms/pages/[...url].tsx index 0a70cf682f1..4a098634497 100644 --- a/examples/magento-graphcms/pages/[...url].tsx +++ b/examples/magento-graphcms/pages/[...url].tsx @@ -1,11 +1,10 @@ +import { PageOptions } from '@graphcommerce/framer-next-pages' +import { cacheFirst, flushMeasurePerf, InContextMaskProvider } from '@graphcommerce/graphql' import { ContentAreaCategoryPage, ContentAreaCategoryPageBefore, - GCPage_DataFragment, GcPageQuery, -} from '@graphcommerce/content-areas' -import { PageOptions } from '@graphcommerce/framer-next-pages' -import { cacheFirst, flushMeasurePerf, InContextMaskProvider } from '@graphcommerce/graphql' +} from '@graphcommerce/graphql-gc-api' import { appendSiblingsAsChildren, CategoryBreadcrumbs, diff --git a/examples/magento-graphcms/pages/blog/page/[page].tsx b/examples/magento-graphcms/pages/blog/page/[page].tsx index c517a1c98f2..d8ab0ea70a2 100644 --- a/examples/magento-graphcms/pages/blog/page/[page].tsx +++ b/examples/magento-graphcms/pages/blog/page/[page].tsx @@ -1,4 +1,4 @@ -import { ContentArea, PageContent, pageContent } from '@graphcommerce/content-areas' +import { ContentArea, PageContent, pageContent } from '@graphcommerce/graphql-gc-api' import { PageOptions } from '@graphcommerce/framer-next-pages' import { StoreConfigDocument } from '@graphcommerce/magento-store' import { diff --git a/examples/magento-graphcms/pages/blog/tagged/[url].tsx b/examples/magento-graphcms/pages/blog/tagged/[url].tsx index d9347ddb305..a92b2dccf03 100644 --- a/examples/magento-graphcms/pages/blog/tagged/[url].tsx +++ b/examples/magento-graphcms/pages/blog/tagged/[url].tsx @@ -1,4 +1,4 @@ -import { ContentArea, PageContent, pageContent } from '@graphcommerce/content-areas' +import { ContentArea, PageContent, pageContent } from '@graphcommerce/graphql-gc-api' import { PageOptions } from '@graphcommerce/framer-next-pages' import { redirectOrNotFound, StoreConfigDocument } from '@graphcommerce/magento-store' import { PageMeta, GetStaticProps, Row, LayoutTitle, LayoutHeader } from '@graphcommerce/next-ui' diff --git a/examples/magento-graphcms/pages/index.tsx b/examples/magento-graphcms/pages/index.tsx index fced474343b..310f8dd103d 100644 --- a/examples/magento-graphcms/pages/index.tsx +++ b/examples/magento-graphcms/pages/index.tsx @@ -1,6 +1,11 @@ -import { ContentAreaHome, GcPageDocument, GcPageQuery } from '@graphcommerce/content-areas' import { PageOptions } from '@graphcommerce/framer-next-pages' import { cacheFirst } from '@graphcommerce/graphql' +import { + ContentAreaHome, + GcPageDocument, + GcPageMeta, + GcPageQuery, +} from '@graphcommerce/graphql-gc-api' import { StoreConfigDocument } from '@graphcommerce/magento-store' import { GetStaticProps, LayoutHeader } from '@graphcommerce/next-ui' import { LayoutDocument, LayoutNavigation, LayoutNavigationProps } from '../components' @@ -11,14 +16,13 @@ type RouteProps = { url: string } type GetPageStaticProps = GetStaticProps function CmsPage(props: Props) { - const { gcPage } = props + const { page } = props return ( <> - {/* */} - + - + ) } @@ -34,14 +38,14 @@ export const getStaticProps: GetPageStaticProps = async (context) => { const staticClient = graphqlSsrClient(context) const conf = client.query({ query: StoreConfigDocument }) - const page = client.query({ query: GcPageDocument, variables: { input: { url: 'page/home' } } }) + const page = client.query({ query: GcPageDocument, variables: { input: { href: 'page/home' } } }) const layout = staticClient.query({ query: LayoutDocument, fetchPolicy: cacheFirst(staticClient), }) - if (!(await page).data) return { notFound: true } + if (!(await page).data.page?.head) return { notFound: true } return { props: { diff --git a/examples/magento-graphcms/pages/modal/[...url].tsx b/examples/magento-graphcms/pages/modal/[...url].tsx index 23282947426..d82f85405ba 100644 --- a/examples/magento-graphcms/pages/modal/[...url].tsx +++ b/examples/magento-graphcms/pages/modal/[...url].tsx @@ -1,4 +1,4 @@ -import { ContentArea, PageContent, pageContent } from '@graphcommerce/content-areas' +import { ContentArea, PageContent, pageContent } from '@graphcommerce/graphql-gc-api' import { PageOptions } from '@graphcommerce/framer-next-pages' import { StoreConfigDocument } from '@graphcommerce/magento-store' import { GetStaticProps, LayoutOverlayHeader, LayoutTitle, PageMeta } from '@graphcommerce/next-ui' diff --git a/examples/magento-graphcms/pages/p/[url].tsx b/examples/magento-graphcms/pages/p/[url].tsx index dab598483d0..23314cb826a 100644 --- a/examples/magento-graphcms/pages/p/[url].tsx +++ b/examples/magento-graphcms/pages/p/[url].tsx @@ -4,7 +4,7 @@ import { ContentAreaProductPageSidebar, PageContent, pageContent, -} from '@graphcommerce/content-areas' +} from '@graphcommerce/graphql-gc-api' import { PageOptions } from '@graphcommerce/framer-next-pages' import { cacheFirst, diff --git a/examples/magento-graphcms/pages/service/[[...url]].tsx b/examples/magento-graphcms/pages/service/[[...url]].tsx index 8437b4bf4ed..19d7f3e9127 100644 --- a/examples/magento-graphcms/pages/service/[[...url]].tsx +++ b/examples/magento-graphcms/pages/service/[[...url]].tsx @@ -1,4 +1,4 @@ -import { ContentArea, PageContent, pageContent } from '@graphcommerce/content-areas' +import { ContentArea, PageContent, pageContent } from '@graphcommerce/graphql-gc-api' import { PageOptions } from '@graphcommerce/framer-next-pages' import { PagesStaticPathsDocument } from '@graphcommerce/graphcms-ui' import { StoreConfigDocument, redirectOrNotFound } from '@graphcommerce/magento-store' diff --git a/examples/magento-graphcms/plugins/hygraph/HygraphContentArea.tsx b/examples/magento-graphcms/plugins/hygraph/HygraphContentArea.tsx index 07bbe5df1b6..4e00229ec80 100644 --- a/examples/magento-graphcms/plugins/hygraph/HygraphContentArea.tsx +++ b/examples/magento-graphcms/plugins/hygraph/HygraphContentArea.tsx @@ -1,10 +1,10 @@ -import type { ContentAreaProps } from '@graphcommerce/content-areas' +import type { ContentAreaProps } from '@graphcommerce/graphql-gc-api' import type { PluginConfig, PluginProps } from '@graphcommerce/next-config' import { RowRenderer } from '../../components/GraphCMS' export const config: PluginConfig = { type: 'component', - module: '@graphcommerce/content-areas', + module: '@graphcommerce/graphql-gc-api', } export const ContentArea = (props: PluginProps) => { diff --git a/packages/content-areas/queries/GcPage.graphql b/packages/content-areas/queries/GcPage.graphql deleted file mode 100644 index 91c9ded9e20..00000000000 --- a/packages/content-areas/queries/GcPage.graphql +++ /dev/null @@ -1,5 +0,0 @@ -query GcPage($input: GCPageInput!) { - gcPage(input: $input) { - ...GCPage_Data - } -} diff --git a/packages/content-areas/queries/GcPage_Data.graphql b/packages/content-areas/queries/GcPage_Data.graphql deleted file mode 100644 index 160c5b26546..00000000000 --- a/packages/content-areas/queries/GcPage_Data.graphql +++ /dev/null @@ -1,9 +0,0 @@ -fragment GCPage_Data on GCPageInterface { - id - title - metaTitle - metaDescription - metaRobots - canonicalUrl - someField -} diff --git a/packages/content-areas/schema/Query_gcPage.graphqls b/packages/content-areas/schema/Query_gcPage.graphqls deleted file mode 100644 index 15abefe56ff..00000000000 --- a/packages/content-areas/schema/Query_gcPage.graphqls +++ /dev/null @@ -1,27 +0,0 @@ -interface GCPageInterface { - id: ID! - title: String - metaTitle: String - metaDescription: String - metaRobots: String - canonicalUrl: String - someField: String! -} - -# type GCPageNotFound implements GCPageInterface { -# id: ID! -# title: String -# metaTitle: String -# metaDescription: String -# metaRobots: String -# canonicalUrl: String -# someField: String! -# } - -input GCPageInput { - url: String! -} - -extend type Query { - gcPage(input: GCPageInput!): GCPageInterface -} diff --git a/packages/ecommerce-ui/components/PreviewMode/PreviewMode.tsx b/packages/ecommerce-ui/components/PreviewMode/PreviewMode.tsx index 46be1b13122..6b4597c8737 100644 --- a/packages/ecommerce-ui/components/PreviewMode/PreviewMode.tsx +++ b/packages/ecommerce-ui/components/PreviewMode/PreviewMode.tsx @@ -96,7 +96,6 @@ function PreviewModeEnabled() { - ) } diff --git a/packages/content-areas/README.md b/packages/graphql-gc-api/README.md similarity index 100% rename from packages/content-areas/README.md rename to packages/graphql-gc-api/README.md diff --git a/packages/content-areas/components/ContentArea/Areas.tsx b/packages/graphql-gc-api/components/ContentArea/Areas.tsx similarity index 100% rename from packages/content-areas/components/ContentArea/Areas.tsx rename to packages/graphql-gc-api/components/ContentArea/Areas.tsx diff --git a/packages/content-areas/components/ContentArea/ContentArea.tsx b/packages/graphql-gc-api/components/ContentArea/ContentArea.tsx similarity index 100% rename from packages/content-areas/components/ContentArea/ContentArea.tsx rename to packages/graphql-gc-api/components/ContentArea/ContentArea.tsx diff --git a/packages/content-areas/components/ContentArea/index.ts b/packages/graphql-gc-api/components/ContentArea/index.ts similarity index 100% rename from packages/content-areas/components/ContentArea/index.ts rename to packages/graphql-gc-api/components/ContentArea/index.ts diff --git a/packages/graphql-gc-api/components/GcPageMeta/GcPageHead.graphql b/packages/graphql-gc-api/components/GcPageMeta/GcPageHead.graphql new file mode 100644 index 00000000000..9dce1603b8c --- /dev/null +++ b/packages/graphql-gc-api/components/GcPageMeta/GcPageHead.graphql @@ -0,0 +1,32 @@ +fragment GcLinkRelTag on GcLinkRelTag { + rel + hreflang + href +} + +fragment GcMetaTag on GcMetaTag { + name + content +} + +fragment GcPageHead on GcPageInterface { + head { + title + description + canonical { + ...GcLinkRelTag + } + alternate { + ...GcLinkRelTag + } + robots { + ...GcMetaTag + } + meta { + ...GcMetaTag + } + link { + ...GcLinkRelTag + } + } +} diff --git a/packages/graphql-gc-api/components/GcPageMeta/GcPageHead.tsx b/packages/graphql-gc-api/components/GcPageMeta/GcPageHead.tsx new file mode 100644 index 00000000000..cbafcf7c390 --- /dev/null +++ b/packages/graphql-gc-api/components/GcPageMeta/GcPageHead.tsx @@ -0,0 +1,57 @@ +import { usePageContext } from '@graphcommerce/framer-next-pages' +import { canonicalize } from '@graphcommerce/next-ui' +import Head from 'next/head' +import { useRouter } from 'next/router' +import { GcPageHeadFragment, GcLinkRelTagFragment, GcMetaTagFragment } from './GcPageHead.gql' + +type GcPageMetaProps = GcPageHeadFragment & { + children?: React.ReactNode +} + +export function GcPageMeta(props: GcPageMetaProps) { + const { head, children } = props + + const { active } = usePageContext() + const router = useRouter() + + if (!head || !active) return null + + const allLinkRel = new Map() + const allMeta = new Map() + + const canonical = canonicalize(router, head.canonical.href) + allLinkRel.set('canonical', { rel: 'canonical', href: canonical }) + + if (head?.description) { + allMeta.set('description', { name: 'description', content: head.description }) + allMeta.set('og:description', { name: 'og:description', content: head.description }) + } + + allMeta.set('og:title', { name: 'og:title', content: head.title }) + allMeta.set('og:url', { name: 'og:url', content: canonical }) + + head.link?.forEach((link) => allLinkRel.set(link.rel, link)) + head.robots?.forEach((robot) => allMeta.set(robot.name, robot)) + head.meta?.forEach((meta) => allMeta.set(meta.name, meta)) + + return ( + + {head.title.trim()} + + {[...allLinkRel.values()].map((link) => ( + + ))} + + {[...allMeta.values()].map((meta) => ( + + ))} + + {children} + + ) +} diff --git a/packages/graphql-gc-api/components/GcPageMeta/index.ts b/packages/graphql-gc-api/components/GcPageMeta/index.ts new file mode 100644 index 00000000000..b94f812e577 --- /dev/null +++ b/packages/graphql-gc-api/components/GcPageMeta/index.ts @@ -0,0 +1,2 @@ +export * from './GcPageHead' +export * from './GcPageHead.gql' diff --git a/packages/content-areas/components/index.ts b/packages/graphql-gc-api/components/index.ts similarity index 100% rename from packages/content-areas/components/index.ts rename to packages/graphql-gc-api/components/index.ts diff --git a/packages/content-areas/index.ts b/packages/graphql-gc-api/index.ts similarity index 72% rename from packages/content-areas/index.ts rename to packages/graphql-gc-api/index.ts index 7eaa9d0fc75..b251b3c2c11 100644 --- a/packages/content-areas/index.ts +++ b/packages/graphql-gc-api/index.ts @@ -1,3 +1,4 @@ export * from './components' export * from './queries/GcPage_Data.gql' export * from './queries/GcPage.gql' +export * from './components/GcPageMeta' diff --git a/packages/content-areas/package.json b/packages/graphql-gc-api/package.json similarity index 96% rename from packages/content-areas/package.json rename to packages/graphql-gc-api/package.json index 0e43d078c77..788107a449e 100644 --- a/packages/content-areas/package.json +++ b/packages/graphql-gc-api/package.json @@ -1,5 +1,5 @@ { - "name": "@graphcommerce/content-areas", + "name": "@graphcommerce/graphql-gc-api", "homepage": "https://www.graphcommerce.org/", "repository": "github:graphcommerce-org/graphcommerce", "version": "9.0.0-canary.62", diff --git a/packages/graphql-gc-api/queries/GcPage.graphql b/packages/graphql-gc-api/queries/GcPage.graphql new file mode 100644 index 00000000000..3e0aac2d4d1 --- /dev/null +++ b/packages/graphql-gc-api/queries/GcPage.graphql @@ -0,0 +1,5 @@ +query GcPage($input: GCPageInput!) { + page: gcPage(input: $input) { + ...GcPage_Data + } +} diff --git a/packages/graphql-gc-api/queries/GcPage_Data.graphql b/packages/graphql-gc-api/queries/GcPage_Data.graphql new file mode 100644 index 00000000000..e59e11647dc --- /dev/null +++ b/packages/graphql-gc-api/queries/GcPage_Data.graphql @@ -0,0 +1,4 @@ +fragment GcPage_Data on GcPageInterface { + __typename + ...GcPageHead +} diff --git a/packages/graphql-gc-api/schema/GcPageHead.graphqls b/packages/graphql-gc-api/schema/GcPageHead.graphqls new file mode 100644 index 00000000000..afeb0bcc167 --- /dev/null +++ b/packages/graphql-gc-api/schema/GcPageHead.graphqls @@ -0,0 +1,70 @@ +""" +A meta tag that can be added to the head of the page. +""" +type GcMetaTag { + """ + Any meta tag name, see https://developers.google.com/search/docs/crawling-indexing/special-tags for documentation. + """ + name: String! + + """ + https://developers.google.com/search/docs/crawling-indexing/robots-meta-tag#directives + """ + content: String! +} + +type GcLinkRelTag { + """ + The type of link relationship. + + https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/rel + + Examples: + - canonical + - alternate + """ + rel: String! + + """ + Used to specify the language of the target URL. Usually used in conjunction with rel="alternate" + + https://developer.mozilla.org/en-US/docs/Web/HTML/Element/link#hreflang + """ + hreflang: String + + """ + A fully qualified URL + + OR + + The relative part of the canonical URL. + As defined by: [pathname](https://developer.mozilla.org/en-US/docs/Web/API/URL/pathname) + [search](https://developer.mozilla.org/en-US/docs/Web/API/URL/search) + """ + href: String! +} + +type GcPageHead { + """ + element of the page + """ + title: String! + + """ + <meta type"description" content=""> + """ + description: String + + canonical: GcLinkRelTag! + alternate: [GcLinkRelTag] + + robots: [GcMetaTag!] + + """ + Additional link rel tags that can be added to the head of the page. + """ + link: [GcLinkRelTag!] + """ + Additional meta tags that can be added to the head of the page. + """ + meta: [GcMetaTag!] +} diff --git a/packages/graphql-gc-api/schema/GcPageInterface.graphqls b/packages/graphql-gc-api/schema/GcPageInterface.graphqls new file mode 100644 index 00000000000..2ed500c9c82 --- /dev/null +++ b/packages/graphql-gc-api/schema/GcPageInterface.graphqls @@ -0,0 +1,14 @@ +""" +Defines an object to be able to be a fully valid HTML page. +""" +interface GcPageInterface { + """ + The head of the page. + """ + head: GcPageHead + + """ + When the redirect is defined the page should not be rendered and the user should be redirected to the specified URL. + """ + redirect: GcLinkRelTag +} diff --git a/packages/graphql-gc-api/schema/Query_gcCanonicals.graphqls b/packages/graphql-gc-api/schema/Query_gcCanonicals.graphqls new file mode 100644 index 00000000000..2032fc332ae --- /dev/null +++ b/packages/graphql-gc-api/schema/Query_gcCanonicals.graphqls @@ -0,0 +1,14 @@ +type GcPagesListOutput { + canonicals: [GcLinkRelTag!] +} + +input GcPagesListInput { + """ + Provide a base path to filter the list of pages. + """ + start_with: String +} + +extend type Query { + gcPageCanonicals(input: GcPagesListInput): GcPagesListOutput +} diff --git a/packages/graphql-gc-api/schema/Query_gcPage.graphqls b/packages/graphql-gc-api/schema/Query_gcPage.graphqls new file mode 100644 index 00000000000..dd1bf76b5cd --- /dev/null +++ b/packages/graphql-gc-api/schema/Query_gcPage.graphqls @@ -0,0 +1,7 @@ +input GCPageInput { + href: String! +} + +extend type Query { + gcPage(input: GCPageInput!): GcPageInterface +} diff --git a/packages/content-areas/server.ts b/packages/graphql-gc-api/server.ts similarity index 100% rename from packages/content-areas/server.ts rename to packages/graphql-gc-api/server.ts diff --git a/packages/graphql-mesh/directive/mesh.graphqls b/packages/graphql-mesh/directive/mesh.graphqls index a934c9d07ae..f609dc4ddbf 100644 --- a/packages/graphql-mesh/directive/mesh.graphqls +++ b/packages/graphql-mesh/directive/mesh.graphqls @@ -14,3 +14,8 @@ directive @resolveTo( result: String resultType: String ) on FIELD_DEFINITION + +enum CacheControlScope { + PUBLIC + PRIVATE +} diff --git a/packages/graphql-mesh/index.ts b/packages/graphql-mesh/index.ts index b39865d59bc..4aafcef977a 100644 --- a/packages/graphql-mesh/index.ts +++ b/packages/graphql-mesh/index.ts @@ -1,3 +1,5 @@ export * from './api/createEnvelop' export * from './api/apolloLink' export * from './.mesh' +export * from './utils/executeMesh' +export * from './utils/meshCache' diff --git a/packages/graphql-mesh/package.json b/packages/graphql-mesh/package.json index 31dc65fd66a..24c86e48e2b 100644 --- a/packages/graphql-mesh/package.json +++ b/packages/graphql-mesh/package.json @@ -5,6 +5,7 @@ "version": "9.0.0-canary.62", "main": "index.ts", "dependencies": { + "@envelop/response-cache": "^6.2.1", "@graphql-mesh/apollo-link": "latest", "@graphql-mesh/config": "latest", "@graphql-mesh/cross-helpers": "latest", diff --git a/packages/graphql-mesh/utils/executeMesh.ts b/packages/graphql-mesh/utils/executeMesh.ts new file mode 100644 index 00000000000..19c322b0ea7 --- /dev/null +++ b/packages/graphql-mesh/utils/executeMesh.ts @@ -0,0 +1,166 @@ +import { defaultBuildResponseCacheKey } from '@envelop/response-cache' +import type { TypedDocumentNode } from '@graphcommerce/graphql' +import type { MeshContext } from '@graphcommerce/graphql-mesh' +import { InContextSdkMethod } from '@graphql-mesh/types' +import { + Kind, + SelectionSetNode, + OperationTypeNode, + OperationDefinitionNode, + FieldNode, + print, + ValueNode, +} from 'graphql' +import type { Path } from 'react-hook-form' +import { meshCache, MeshCacheOptions } from './meshCache' + +function isNumeric(n: string) { + return !Number.isNaN(parseFloat(n)) +} + +function traverseSelectionSet<Q>(incomingSelectionSet: SelectionSetNode, path: Path<Q>) { + const pathArray = path.split(/[,[\].]+?/) + let selectionSet = incomingSelectionSet + let pathIndex = 0 + + while (pathIndex < pathArray.length) { + const currentValue = pathArray[pathIndex] + if (!isNumeric(currentValue)) { + for (const selection of selectionSet.selections) { + if (selection.kind === Kind.FIELD && selection.name.value === currentValue) { + selectionSet = { + kind: Kind.SELECTION_SET, + selections: selection.selectionSet?.selections ?? [], + } + break + } + } + } + + pathIndex++ + } + + return selectionSet +} + +type OperationType = 'Query' | 'Mutation' | 'Subscription' +function getOperationType(def: OperationDefinitionNode) { + let operationType: OperationType | undefined + switch (def.operation) { + case OperationTypeNode.QUERY: + operationType = 'Query' + break + case OperationTypeNode.MUTATION: + operationType = 'Mutation' + break + case OperationTypeNode.SUBSCRIPTION: + operationType = 'Subscription' + break + } + return operationType +} + +function traverseValueNode<V extends Record<string, unknown>>( + value: ValueNode, + variables: V, +): unknown { + switch (value.kind) { + case Kind.NULL: + return null + case Kind.VARIABLE: + return variables[value.name.value] + case Kind.LIST: + return value.values.map((v) => traverseValueNode(v, variables)) + case Kind.OBJECT: + return value.fields.map((f) => ({ + [f.name.value]: traverseValueNode(f.value, variables), + })) + default: + return value.value + } +} + +function collectArguments<V extends Record<string, unknown>>(field: FieldNode, variables: V) { + if (!field?.arguments || field?.arguments.length === 0) return {} + const args: Record<string, unknown> = {} + field.arguments?.forEach((argument) => { + args[argument.name.value] = traverseValueNode<V>(argument.value, variables) + }, field.arguments) + return args +} + +function maybeExecutor(context: MeshContext, operationType: OperationType, operationName: string) { + const possibleLocations = Object.keys(context) + + let found: InContextSdkMethod | undefined + for (const location of possibleLocations) { + const ctx = context as unknown as Record< + string, + Record<string, Record<string, InContextSdkMethod>> + > + if (ctx[location]?.[operationType]?.[operationName]) { + found = ctx[location][operationType][operationName] + } + } + + return found +} + +export async function executeMesh<Q, V extends Record<string, unknown>>( + document: TypedDocumentNode<Q, V>, + options: { variables: V }, + context: MeshContext, +): Promise<Q> { + const des = document.definitions.map(async (def) => { + if (def.kind !== Kind.OPERATION_DEFINITION) return null + + const executions = def.selectionSet.selections + .filter((s) => s.kind === Kind.FIELD) + .map( + async (field) => + [ + field.name.value, + await maybeExecutor( + context, + getOperationType(def), + field.name.value, + )?.({ + context, + selectionSet: traverseSelectionSet<Q>(def.selectionSet, field.name.value as Path<Q>), + args: collectArguments<V>(field, options.variables), + }), + ] as const, + ) + + return Promise.all(executions) + }) + + const flattenedEntries = (await Promise.all(des)).flat(1).filter((v) => !!v) + return Object.fromEntries(flattenedEntries) as Q +} + +export function createExecutor(context: MeshContext) { + const headers = (((context as any).headers ?? {}) as Record<string, unknown>) ?? {} + + return async <Q, V extends Record<string, unknown>>( + document: TypedDocumentNode<Q, V>, + options: { variables: V } & Pick<MeshCacheOptions, 'ttl'>, + ) => { + const { ttl, ...rest } = options + + const cacheKey = await defaultBuildResponseCacheKey({ + documentString: print(document), + variableValues: { + // @todo make sure we automatically select the correct headers. + ...options.variables, + 'gcms-locales': headers['gcms-locales'], + 'gcms-stage': headers['gcms-stage'], + 'X-Magento-Cache-Id': headers['x-magento-cache-id'], + Store: headers.store, + }, + sessionId: null, + }) + + return meshCache(() => executeMesh<Q, V>(document, rest, context), { ttl, context, cacheKey }) + } +} diff --git a/packages/graphql-mesh/utils/meshCache.ts b/packages/graphql-mesh/utils/meshCache.ts new file mode 100644 index 00000000000..1541a7e6886 --- /dev/null +++ b/packages/graphql-mesh/utils/meshCache.ts @@ -0,0 +1,35 @@ +import { type MeshContext } from '../.mesh' + +type CacheEntry = { + createdAt: number + value: any +} + +export type MeshCacheOptions = { + cacheKey: string + context: MeshContext + /** + * Number of seconds the cache value will remain valid. + */ + ttl: number +} + +export async function meshCache<T extends (...args: any[]) => Promise<any>>( + cb: T, + options: MeshCacheOptions, +): Promise<ReturnType<T>> { + const { cacheKey, context, ttl = 0 } = options + + const now = Date.now() / 1000 + + const { value, createdAt } = ((await context.cache.get(cacheKey)) as CacheEntry) ?? {} + + if (value && ttl && now - createdAt < ttl) return value + + const res = await cb() + if (ttl !== 0) { + // eslint-disable-next-line @typescript-eslint/no-floating-promises + context.cache.set(cacheKey, { createdAt: now, value: res }) + } + return res +} diff --git a/packages/graphql/apollo-client.graphql b/packages/graphql/apollo-client.graphql index c3a624d5349..e7b7433d647 100644 --- a/packages/graphql/apollo-client.graphql +++ b/packages/graphql/apollo-client.graphql @@ -8,11 +8,6 @@ The @connection directive allows you to specify a custom cache key for paginated """ directive @connection(key: String, filter: [String]) on FIELD -""" -This directive enables your queries to receive data for specific fields incrementally, instead of receiving all field data at the same time. This is helpful whenever some fields in a query take much longer to resolve than others. -""" -directive @defer(if: Boolean! = true, label: String) on FRAGMENT_SPREAD | INLINE_FRAGMENT - # """ # Directs the executor to stream plural fields when the `if` argument is true or undefined. # """ diff --git a/packages/hygraph-dynamic-rows/graphql/AllDynamicRows.graphql b/packages/hygraph-dynamic-rows/graphql/AllDynamicRows.graphql index 05d10a8e4df..e3c94ef5bef 100644 --- a/packages/hygraph-dynamic-rows/graphql/AllDynamicRows.graphql +++ b/packages/hygraph-dynamic-rows/graphql/AllDynamicRows.graphql @@ -1,17 +1,18 @@ query AllDynamicRows($first: Int = 100, $skip: Int) { - dynamicRows(first: $first, skip: $skip) { - id - conditions { - __typename - ...ConditionNumber - ...ConditionText - ...ConditionAnd - } - } - - pagesConnection { + dynamicRowsConnection(first: $first, skip: $skip) { aggregate { count } + edges { + node { + id + conditions { + __typename + ...ConditionNumber + ...ConditionText + ...ConditionAnd + } + } + } } } diff --git a/packages/hygraph-dynamic-rows/lib/hygraphDynamicRows.ts b/packages/hygraph-dynamic-rows/lib/hygraphDynamicRows.ts index 2653802418e..dd9f76d4a41 100644 --- a/packages/hygraph-dynamic-rows/lib/hygraphDynamicRows.ts +++ b/packages/hygraph-dynamic-rows/lib/hygraphDynamicRows.ts @@ -6,6 +6,7 @@ import { ConditionOrFragment, ConditionAndFragment, DynamicRowsDocument, + DynamicRowsQuery, } from '../graphql' import { getAllHygraphDynamicRows } from './getAllHygraphDynamicRows' @@ -13,7 +14,7 @@ import { getAllHygraphDynamicRows } from './getAllHygraphDynamicRows' * This generally works the same way as lodash get, however, when encountering an array it will * return all values. */ -function getByPath( +export function getByPath( value: unknown, query: string | Array<string | number>, ): (undefined | string | number | bigint)[] { @@ -47,7 +48,7 @@ function getByPath( } /** A recursive match function that is able to match a condition against the requested conditions. */ -function matchCondition( +export function matchCondition( condition: | ConditionTextFragment | ConditionNumberFragment @@ -81,6 +82,34 @@ function matchCondition( type Page = HygraphPagesQuery['pages'][number] +export function applyDynamicRows( + dynamicRows: DynamicRowsQuery['dynamicRows'], + incomingContent: Page['content'] = [], +) { + // Create a copy of the content array. + const content = [...incomingContent] + dynamicRows.forEach((dynamicRow) => { + const { placement, target, rows, row } = dynamicRow + if (!rows && !row) return + + const rowsToMerge = rows + if (row && rows.length === 0) rowsToMerge.push(row) + + if (!target) { + if (placement === 'BEFORE') content.unshift(...rowsToMerge) + else content.push(...rowsToMerge) + return + } + + const targetIdx = content.findIndex((c) => c.id === target.id) + if (placement === 'BEFORE') content.splice(targetIdx, 0, ...rowsToMerge) + if (placement === 'AFTER') content.splice(targetIdx + 1, 0, ...rowsToMerge) + if (placement === 'REPLACE') content.splice(targetIdx, 1, ...rowsToMerge) + }) + + return content +} + /** * Fetch the page content for the given urls. * @@ -95,7 +124,6 @@ export async function hygraphDynamicRows( additionalProperties?: Promise<object> | object, ): Promise<{ data: HygraphPagesQuery }> { const fetchPolicy = cached ? cacheFirst(client) : undefined - const allRoutes = await getAllHygraphDynamicRows(client) // Get the required rowIds from the conditions @@ -115,27 +143,10 @@ export async function hygraphDynamicRows( const page = pageResult.data.pages[0] as Page | undefined - // Create a copy of the content array. - const content = [...(page?.content ?? [])] - - dynamicResult?.data.dynamicRows.forEach((dynamicRow) => { - const { placement, target, rows, row } = dynamicRow - if (!rows && !row) return + if (!dynamicResult?.data.dynamicRows) return pageResult - const rowsToMerge = rows - if (row && rows.length === 0) rowsToMerge.push(row) - - if (!target) { - if (placement === 'BEFORE') content.unshift(...rowsToMerge) - else content.push(...rowsToMerge) - return - } - - const targetIdx = content.findIndex((c) => c.id === target.id) - if (placement === 'BEFORE') content.splice(targetIdx, 0, ...rowsToMerge) - if (placement === 'AFTER') content.splice(targetIdx + 1, 0, ...rowsToMerge) - if (placement === 'REPLACE') content.splice(targetIdx, 1, ...rowsToMerge) - }) + // Create a copy of the content array. + const content = applyDynamicRows(dynamicResult?.data.dynamicRows, page.content) if (!content.length) return pageResult diff --git a/packages/hygraph-dynamic-rows/mesh/resolvers.ts b/packages/hygraph-dynamic-rows/mesh/resolvers.ts new file mode 100644 index 00000000000..b7514ac08e1 --- /dev/null +++ b/packages/hygraph-dynamic-rows/mesh/resolvers.ts @@ -0,0 +1,60 @@ +import { createExecutor, type MeshContext, type Resolvers } from '@graphcommerce/graphql-mesh' +import { AllDynamicRowsDocument, AllDynamicRowsQuery } from '../graphql/AllDynamicRows.gql' +import { DynamicRowsDocument } from '../graphql/DynamicRows.gql' +import { applyDynamicRows, matchCondition } from '../lib/hygraphDynamicRows' + +async function getAllHygraphDynamicRows( + context: MeshContext, + options: { pageSize?: number; ttl: number }, +) { + const { pageSize = 100, ttl } = options + + const execute = createExecutor(context) + + const query = execute(AllDynamicRowsDocument, { variables: { first: 100, skip: 0 }, ttl }) + + const pages: Promise<AllDynamicRowsQuery>[] = [query] + const data = await query + const totalPages = Math.ceil(data.dynamicRowsConnection.aggregate.count / pageSize) ?? 1 + if (totalPages > 1) { + for (let i = 2; i <= totalPages; i++) { + pages.push( + execute(AllDynamicRowsDocument, { + variables: { first: pageSize, skip: pageSize * (i - 1) }, + ttl, + }), + ) + } + } + + return (await Promise.all(pages)) + .map((q) => q.dynamicRowsConnection.edges) + .flat(1) + .map(({ node }) => ({ id: node.id, conditions: node.conditions })) +} + +export const resolvers: Resolvers = { + Page: { + content: async (parent, args, context, info) => { + const execute = createExecutor(context) + const allRoutes = await getAllHygraphDynamicRows(context, { ttl: 60 * 60 }) + + const rowIds = allRoutes + .filter((availableDynamicRow) => + availableDynamicRow.conditions.some((condition) => + matchCondition(condition, { ...parent, ...args }), + ), + ) + .map((row) => row.id) + + const dynamicRows = + rowIds.length !== 0 + ? await execute(DynamicRowsDocument, { variables: { rowIds }, ttl: 60 * 60 }) + : undefined + + if (!dynamicRows?.dynamicRows) return parent.content + + return applyDynamicRows(dynamicRows.dynamicRows, parent.content) + }, + }, +} diff --git a/packages/hygraph-dynamic-rows/package.json b/packages/hygraph-dynamic-rows/package.json index e293d27553d..8b00d794741 100644 --- a/packages/hygraph-dynamic-rows/package.json +++ b/packages/hygraph-dynamic-rows/package.json @@ -15,6 +15,7 @@ "@graphcommerce/eslint-config-pwa": "^9.0.0-canary.62", "@graphcommerce/graphcms-ui": "^9.0.0-canary.62", "@graphcommerce/graphql": "^9.0.0-canary.62", + "@graphcommerce/graphql-mesh": "^9.0.0-canary.62", "@graphcommerce/image": "^9.0.0-canary.62", "@graphcommerce/next-ui": "^9.0.0-canary.62", "@graphcommerce/prettier-config-pwa": "^9.0.0-canary.62", diff --git a/packages/hygraph-dynamic-rows/plugins/meshConfigDynamicRows.ts b/packages/hygraph-dynamic-rows/plugins/meshConfigDynamicRows.ts new file mode 100644 index 00000000000..b3c3c5cd83a --- /dev/null +++ b/packages/hygraph-dynamic-rows/plugins/meshConfigDynamicRows.ts @@ -0,0 +1,18 @@ +import type { FunctionPlugin, PluginConfig } from '@graphcommerce/next-config' +import type { MeshConfigFunction } from '@graphcommerce/graphql-mesh/meshConfig' + +export const config: PluginConfig = { + module: '@graphcommerce/graphql-mesh/meshConfig', + type: 'function', +} + +export const meshConfig: FunctionPlugin<MeshConfigFunction> = (prev, conf, graphCommerceConfig) => { + const result = prev(conf, graphCommerceConfig) + return { + ...result, + additionalResolvers: [ + ...(result.additionalResolvers ?? []), + '@graphcommerce/hygraph-dynamic-rows/mesh/resolvers.ts', + ], + } +} diff --git a/packages/hygraph-ui/components/Asset/Asset.tsx b/packages/hygraph-ui/components/Asset/Asset.tsx index 06a3d67634b..a84888e4bc0 100644 --- a/packages/hygraph-ui/components/Asset/Asset.tsx +++ b/packages/hygraph-ui/components/Asset/Asset.tsx @@ -48,7 +48,7 @@ export const Asset = memo<AssetProps>((props) => { muted loop playsInline - disableRemotePlayback + // disableRemotePlayback sx={[...(Array.isArray(sx) ? sx : [sx])]} /> ) diff --git a/packages/hygraph-ui/graphql/GCPage_Hygraph.graphql b/packages/hygraph-ui/graphql/GCPage_Hygraph.graphql index f09ce4a453b..0de9550a65a 100644 --- a/packages/hygraph-ui/graphql/GCPage_Hygraph.graphql +++ b/packages/hygraph-ui/graphql/GCPage_Hygraph.graphql @@ -1,3 +1,3 @@ -fragment GCPage_Hygraph on GCPageInterface @inject(into: ["GCPage_Data"]) { +fragment GCPage_Hygraph on GcPageInterface @inject(into: ["GcPage_Data"]) { ...HygraphPage } diff --git a/packages/hygraph-ui/graphql/GcPage_Hygraph.graphql b/packages/hygraph-ui/graphql/GcPage_Hygraph.graphql new file mode 100644 index 00000000000..0de9550a65a --- /dev/null +++ b/packages/hygraph-ui/graphql/GcPage_Hygraph.graphql @@ -0,0 +1,3 @@ +fragment GCPage_Hygraph on GcPageInterface @inject(into: ["GcPage_Data"]) { + ...HygraphPage +} diff --git a/packages/hygraph-ui/graphql/HygraphPage.graphql b/packages/hygraph-ui/graphql/HygraphPage.graphql index edf19d40d10..aa34bfe8ddf 100644 --- a/packages/hygraph-ui/graphql/HygraphPage.graphql +++ b/packages/hygraph-ui/graphql/HygraphPage.graphql @@ -1,8 +1,5 @@ fragment HygraphPage on Page { title - metaTitle - metaDescription - metaRobots url author date diff --git a/packages/hygraph-ui/plugins/HygraphPreviewModeToolbar.tsx b/packages/hygraph-ui/plugins/HygraphPreviewModeToolbar.tsx index 233ef5c0211..98c331717c1 100644 --- a/packages/hygraph-ui/plugins/HygraphPreviewModeToolbar.tsx +++ b/packages/hygraph-ui/plugins/HygraphPreviewModeToolbar.tsx @@ -65,7 +65,7 @@ const HygraphConfig = React.memo(() => { } /> ), - [contentStages.data?.__type.enumValues, contentStages.loading, control], + [contentStages.data?.__type.enumValues, contentStages.loading, control, defaultValue], ) }) diff --git a/packages/hygraph-ui/schema/Query_gcPage.graphqls b/packages/hygraph-ui/schema/Query_gcPage.graphqls index 54914d9ac27..b435d3b03d3 100644 --- a/packages/hygraph-ui/schema/Query_gcPage.graphqls +++ b/packages/hygraph-ui/schema/Query_gcPage.graphqls @@ -1,14 +1,17 @@ -type Page implements GCPageInterface { - title: String - metaTitle: String - metaDescription: String - metaRobots: String - canonicalUrl: String - someField: String! +type Page implements GcPageInterface { + """ + The head of the page. + """ + head: GcPageHead + + """ + When the redirect is defined the page should not be rendered and the user should be redirected to the specified URL. + """ + redirect: GcLinkRelTag } extend type Query { - gcPage(input: GCPageInput!): GCPageInterface + gcPage(input: GCPageInput!): GcPageInterface @resolveTo( sourceName: "hygraph" sourceTypeName: "Query" diff --git a/packages/magento-category/components/CategoryMeta/CategoryMeta.tsx b/packages/magento-category/components/CategoryMeta/CategoryMeta.tsx index 10561b850d1..cf8567e70b7 100644 --- a/packages/magento-category/components/CategoryMeta/CategoryMeta.tsx +++ b/packages/magento-category/components/CategoryMeta/CategoryMeta.tsx @@ -1,29 +1,36 @@ import { ProductListParams } from '@graphcommerce/magento-product' -import { PageMetaNew, PageMetaPropsNew } from '@graphcommerce/next-ui/PageMeta/PageMetaNew' +import { PageMeta } from '@graphcommerce/magento-store' +import { PageMetaProps } from '@graphcommerce/next-ui' import { i18n } from '@lingui/core' import { CategoryMetaFragment } from './CategoryMeta.gql' -export type CategoryMetaProps = PageMetaPropsNew & { - category?: CategoryMetaFragment | null - params?: ProductListParams -} +export type CategoryMetaProps = CategoryMetaFragment & + Omit<PageMetaProps, 'title' | 'metaDescription' | 'children'> & { + params?: ProductListParams + title?: string | null + metaDescription?: string | null + } export function CategoryMeta(props: CategoryMetaProps) { - const { params, metadata, category } = props - - let title = metadata?.title?.absolute ?? '' - if (!title && category?.meta_title) title = category?.meta_title - if (!title && category?.name) title = category?.name + const { meta_title, meta_description, name, params, image, ogImageUseFallback } = props + let { title, metaDescription, metaRobots, canonical, ogImage } = props + if (!title) title = '' + if (!metaDescription) metaDescription = '' - let metaDescription = metadata?.description ?? '' - if (!metaDescription && category?.meta_description) metaDescription = category.meta_description + if (!title && meta_title) title = meta_title + if (!title && name) title = name + if (!ogImage && image) ogImage = image + if (!metaDescription && meta_description) metaDescription = meta_description - let canonical = metadata?.alternates?.canonical?.url ?? null - if (!canonical) canonical = `/${params?.url}` + if (params?.url && !canonical) canonical = `/${params.url}` const anyFilterActive = Object.keys(params?.filters ?? {}).filter((k) => k !== 'category_uid').length > 0 + const sortActive = params?.sort && Object.keys(params?.sort).length !== 0 + const limitAcitve = !!params?.pageSize + const noIndex = anyFilterActive || sortActive || limitAcitve + const currentPage = params?.currentPage ?? 1 const isPaginated = currentPage > 1 && !anyFilterActive @@ -32,43 +39,22 @@ export function CategoryMeta(props: CategoryMetaProps) { ? i18n._(/* i18n */ '{title} - Page {currentPage}', { title, currentPage }) : title - const sortActive = params?.sort && Object.keys(params?.sort).length !== 0 - const limitAcitve = !!params?.pageSize - const noIndex = anyFilterActive || sortActive || limitAcitve + const metaDescriptionTrans = + metaDescription && isPaginated + ? i18n._(/* i18n */ '{metaDescription} - Page {currentPage}', { + metaDescription, + currentPage, + }) + : metaDescription return ( - <PageMetaNew - metadata={{ - ...metadata, - robots: { - basic: noIndex ? 'noindex' : metadata?.robots?.basic ?? null, - googleBot: metadata?.robots?.googleBot ?? null, - }, - alternates: { - languages: {}, - media: {}, - types: {}, - ...metadata?.alternates, - canonical: { - ...metadata?.alternates?.canonical, - url: canonical, - }, - }, - title: { template: null, absolute: titleTrans }, - description: - metaDescription && isPaginated - ? i18n._(/* i18n */ '{metaDescription} - Page {currentPage}', { - metaDescription, - currentPage, - }) - : metaDescription, - openGraph: { - type: 'website', - url: canonical, - title: { template: null, absolute: titleTrans }, - images: category?.image ? [new URL(category?.image)] : [], - }, - }} + <PageMeta + title={titleTrans} + metaDescription={metaDescriptionTrans} + metaRobots={noIndex ? ['noindex'] : metaRobots} + canonical={isPaginated ? `${canonical}/page/${currentPage}` : canonical} + ogImage={ogImage} + ogImageUseFallback={ogImageUseFallback} /> ) } diff --git a/packages/magento-customer/link/xMagentoCacheIdHeader.ts b/packages/magento-customer/link/xMagentoCacheIdHeader.ts index feb1ab24f21..993b4dacd62 100644 --- a/packages/magento-customer/link/xMagentoCacheIdHeader.ts +++ b/packages/magento-customer/link/xMagentoCacheIdHeader.ts @@ -11,11 +11,14 @@ export const xMagentoCacheIdHeader = new ApolloLink((operation, forward) => { }) return forward(operation).map((data) => { - const cache = operation.getContext().cache + const { cache } = operation.getContext() if (!cache) return data - const xMagentoCacheId = (data.extensions as { forwardedHeaders: Record<string, string> }) - .forwardedHeaders['x-magento-cache-id'] + type Extensions = { forwardedHeaders: Record<string, string> } | null + const xMagentoCacheId = (data?.extensions as Extensions)?.forwardedHeaders?.[ + 'x-magento-cache-id' + ] + if (!xMagentoCacheId) return data const tokenResult = cache.readQuery({ query: CustomerTokenDocument }) diff --git a/packages/magento-product/Api/ProductListItem.graphql b/packages/magento-product/Api/ProductListItem.graphql index be7f7463c96..48969ce9665 100644 --- a/packages/magento-product/Api/ProductListItem.graphql +++ b/packages/magento-product/Api/ProductListItem.graphql @@ -6,9 +6,12 @@ fragment ProductListItem on ProductInterface { small_image { ...ProductImage } - price_range { - minimum_price { - ...ProductListPrice + + ... on ProductInterface @defer { + price_range { + minimum_price { + ...ProductListPrice + } } } } diff --git a/packages/magento-store/PageMeta.tsx b/packages/magento-store/PageMeta.tsx index f80c819d811..e570fc744d3 100644 --- a/packages/magento-store/PageMeta.tsx +++ b/packages/magento-store/PageMeta.tsx @@ -1,14 +1,7 @@ import { useQuery } from '@graphcommerce/graphql' -import { - PageMetaProps as NextPageMetaProps, - PageMetaOld, - isPageMetaPropsNew, -} from '@graphcommerce/next-ui' -import { PageMetaNew } from '@graphcommerce/next-ui/PageMeta/PageMetaNew' +import { PageMetaProps } from '@graphcommerce/next-ui' import { StoreConfigDocument } from './StoreConfig.gql' -type PageMetaProps = NextPageMetaProps - export function PageMeta(props: PageMetaProps) { const config = useQuery(StoreConfigDocument) @@ -25,23 +18,6 @@ export function PageMeta(props: PageMetaProps) { return pageTitle } - if (isPageMetaPropsNew(props)) { - const { metadata } = props - - return ( - <PageMetaNew - {...props} - metadata={{ - ...metadata, - title: { - absolute: addPrefix(metadata?.title?.absolute ?? ''), - template: null, - }, - }} - /> - ) - } - const { title, ...pageMetaProps } = props - return <PageMetaOld title={addPrefix(title ?? '')} {...pageMetaProps} /> + return <PageMeta title={addPrefix(title ?? '')} {...pageMetaProps} /> } diff --git a/packages/next-ui/PageMeta/PageMeta.tsx b/packages/next-ui/PageMeta/PageMeta.tsx index 694319bfb7f..d051a14daa1 100644 --- a/packages/next-ui/PageMeta/PageMeta.tsx +++ b/packages/next-ui/PageMeta/PageMeta.tsx @@ -2,7 +2,6 @@ import { usePageContext } from '@graphcommerce/framer-next-pages' import Head from 'next/head' import type {} from '@graphcommerce/next-config' import { Canonical, useCanonical } from './canonicalize' -import { PageMetaNew, PageMetaPropsNew } from './PageMetaNew' // https://developers.google.com/search/docs/advanced/robots/robots_meta_tag#directives export type MetaRobots = @@ -18,7 +17,7 @@ export type MetaRobots = | `max-video-preview:${number}` type MetaRobotsAll = ['all' | 'none'] -export type PageMetaPropsOld = { +export type PageMetaProps = { title: string canonical?: Canonical metaDescription?: string @@ -29,13 +28,7 @@ export type PageMetaPropsOld = { ogType?: string | null } -export function isPageMetaPropsNew(props: PageMetaProps): props is PageMetaPropsNew { - return 'metadata' in props -} - -export type PageMetaProps = PageMetaPropsNew | PageMetaPropsOld - -export function PageMetaOld(props: PageMetaPropsOld) { +export function PageMeta(props: PageMetaProps) { const { active } = usePageContext() const { children, @@ -53,7 +46,7 @@ export function PageMetaOld(props: PageMetaPropsOld) { if (!active) return null return ( <Head> - <title>{title} + {title.trim()} {metaDescription && ( <> @@ -73,7 +66,3 @@ export function PageMetaOld(props: PageMetaPropsOld) { ) } - -export function PageMeta(props: PageMetaProps) { - return isPageMetaPropsNew(props) ? : -} diff --git a/packages/next-ui/PageMeta/PageMetaNew.tsx b/packages/next-ui/PageMeta/PageMetaNew.tsx deleted file mode 100644 index aa3b0dd0f0d..00000000000 --- a/packages/next-ui/PageMeta/PageMetaNew.tsx +++ /dev/null @@ -1,59 +0,0 @@ -import { ResolvedMetadata } from 'next' -import { createDefaultMetadata } from 'next/dist/lib/metadata/default-metadata' -import { AlternatesMetadata } from 'next/dist/lib/metadata/generate/alternate' -import { - AppleWebAppMeta, - BasicMeta, - FormatDetectionMeta, - ItunesMeta, - VerificationMeta, -} from 'next/dist/lib/metadata/generate/basic' -import { IconsMetadata } from 'next/dist/lib/metadata/generate/icons' -import { MetaFilter } from 'next/dist/lib/metadata/generate/meta' -import { - AppLinksMeta, - OpenGraphMetadata, - TwitterMetadata, -} from 'next/dist/lib/metadata/generate/opengraph' -import Head from 'next/head' -import React from 'react' - -export type PageMetaPropsNew = { - metadata?: Partial | null - children?: React.ReactNode -} - -export function PageMetaNew(props: PageMetaPropsNew) { - const { metadata: metaIncoming, children } = props - - if (!metaIncoming) return null - - const metadata: ResolvedMetadata = { - ...createDefaultMetadata(), - ...metaIncoming, - metadataBase: new URL(import.meta.graphCommerce.canonicalBaseUrl), - } - - const elements = MetaFilter([ - BasicMeta({ metadata }), - AlternatesMetadata({ alternates: metadata.alternates }), - ItunesMeta({ itunes: metadata.itunes }), - FormatDetectionMeta({ formatDetection: metadata.formatDetection }), - VerificationMeta({ verification: metadata.verification }), - AppleWebAppMeta({ appleWebApp: metadata.appleWebApp }), - OpenGraphMetadata({ openGraph: metadata.openGraph }), - TwitterMetadata({ twitter: metadata.twitter }), - AppLinksMeta({ appLinks: metadata.appLinks }), - IconsMetadata({ icons: metadata.icons }), - ]) - - return ( - - {elements.map((el, idx) => ( - // eslint-disable-next-line react/no-array-index-key - {el} - ))} - {children} - - ) -} diff --git a/packages/next-ui/PageMeta/canonicalize.ts b/packages/next-ui/PageMeta/canonicalize.ts index 892b2a750d9..c962eda4218 100644 --- a/packages/next-ui/PageMeta/canonicalize.ts +++ b/packages/next-ui/PageMeta/canonicalize.ts @@ -12,6 +12,11 @@ type PartialNextRouter = Pick< 'pathname' | 'locale' | 'locales' | 'isLocaleDomain' | 'domainLocales' | 'defaultLocale' > +export function canonicalize(router: PartialNextRouter, incoming: Canonical): string +export function canonicalize( + router: PartialNextRouter, + incoming: Canonical | undefined, +): string | undefined export function canonicalize(router: PartialNextRouter, incoming?: Canonical) { let canonical = incoming diff --git a/packagesDev/graphql-codegen-relay-optimizer-plugin/dist/index.js b/packagesDev/graphql-codegen-relay-optimizer-plugin/dist/index.js index fb2b2bab972..243a2c9ca01 100644 --- a/packagesDev/graphql-codegen-relay-optimizer-plugin/dist/index.js +++ b/packagesDev/graphql-codegen-relay-optimizer-plugin/dist/index.js @@ -38,6 +38,7 @@ _config) => { /* GraphQL */ ` directive @connection(key: String!, filter: [String!]) on FIELD directive @client on FIELD + directive @defer(if: Boolean! = true, label: String) on FRAGMENT_SPREAD | INLINE_FRAGMENT `, ]); const documentAsts = documents.reduce((prev, v) => [...prev, ...(v.document?.definitions ?? [])], []); diff --git a/packagesDev/graphql-codegen-relay-optimizer-plugin/src/index.ts b/packagesDev/graphql-codegen-relay-optimizer-plugin/src/index.ts index b9b368187a6..1b78c02e46a 100644 --- a/packagesDev/graphql-codegen-relay-optimizer-plugin/src/index.ts +++ b/packagesDev/graphql-codegen-relay-optimizer-plugin/src/index.ts @@ -43,6 +43,7 @@ export const plugin: PluginFunction = ( /* GraphQL */ ` directive @connection(key: String!, filter: [String!]) on FIELD directive @client on FIELD + directive @defer(if: Boolean! = true, label: String) on FRAGMENT_SPREAD | INLINE_FRAGMENT `, ]) diff --git a/packagesDev/next-config/dist/generated/config.js b/packagesDev/next-config/dist/generated/config.js index ed5e13d1490..d86dfafcf99 100644 --- a/packagesDev/next-config/dist/generated/config.js +++ b/packagesDev/next-config/dist/generated/config.js @@ -75,6 +75,10 @@ function DatalayerConfigSchema() { } function GraphCommerceConfigSchema() { return _zod.z.object({ + algoliaApplicationId: _zod.z.string().min(1), + algoliaCatalogEnabled: _zod.z.boolean().nullish(), + algoliaIndexNamePrefix: _zod.z.string().min(1), + algoliaSearchOnlyApiKey: _zod.z.string().min(1), breadcrumbs: _zod.z.boolean().default(false).nullish(), canonicalBaseUrl: _zod.z.string().min(1), cartDisplayPricesInclTax: _zod.z.boolean().nullish(), @@ -126,6 +130,7 @@ function GraphCommerceDebugConfigSchema() { } function GraphCommerceStorefrontConfigSchema() { return _zod.z.object({ + algoliaIndexNamePrefix: _zod.z.string().nullish(), canonicalBaseUrl: _zod.z.string().nullish(), cartDisplayPricesInclTax: _zod.z.boolean().nullish(), customerCompanyFieldsEnable: _zod.z.boolean().nullish(), diff --git a/packagesDev/next-config/src/generated/config.ts b/packagesDev/next-config/src/generated/config.ts index 2b35e44eebd..56d890ec8c6 100644 --- a/packagesDev/next-config/src/generated/config.ts +++ b/packagesDev/next-config/src/generated/config.ts @@ -104,6 +104,22 @@ export type DatalayerConfig = { * Below is a list of all possible configurations that can be set by GraphCommerce. */ export type GraphCommerceConfig = { + /** + * Configure your Algolia application ID. + * + * Stores > Configuration > Algolia Search > Credentials and Basic Setup > Application ID + */ + algoliaApplicationId: Scalars['String']['input']; + /** By default the catalog will not use algolia. Set this to true to enable Algolia for the catalog. */ + algoliaCatalogEnabled?: InputMaybe; + /** Stores > Configuration > Algolia Search > Credentials and Basic Setup > Index name prefix */ + algoliaIndexNamePrefix: Scalars['String']['input']; + /** + * Configure your Algolia Search Only API Key. + * + * Stores > Configuration > Algolia Search > Credentials and Basic Setup > Search-only (public) API key + */ + algoliaSearchOnlyApiKey: Scalars['String']['input']; /** Configuration for the SidebarGallery component */ breadcrumbs?: InputMaybe; /** @@ -358,6 +374,8 @@ export type GraphCommerceDebugConfig = { /** All storefront configuration for the project */ export type GraphCommerceStorefrontConfig = { + /** Stores > Configuration > Algolia Search > Credentials and Basic Setup > Index name prefix */ + algoliaIndexNamePrefix?: InputMaybe; /** * The canonical base URL is used for SEO purposes. * @@ -492,6 +510,10 @@ export function DatalayerConfigSchema(): z.ZodObject export function GraphCommerceConfigSchema(): z.ZodObject> { return z.object({ + algoliaApplicationId: z.string().min(1), + algoliaCatalogEnabled: z.boolean().nullish(), + algoliaIndexNamePrefix: z.string().min(1), + algoliaSearchOnlyApiKey: z.string().min(1), breadcrumbs: z.boolean().default(false).nullish(), canonicalBaseUrl: z.string().min(1), cartDisplayPricesInclTax: z.boolean().nullish(), @@ -545,6 +567,7 @@ export function GraphCommerceDebugConfigSchema(): z.ZodObject> { return z.object({ + algoliaIndexNamePrefix: z.string().nullish(), canonicalBaseUrl: z.string().nullish(), cartDisplayPricesInclTax: z.boolean().nullish(), customerCompanyFieldsEnable: z.boolean().nullish(), diff --git a/yarn.lock b/yarn.lock index b0d5440a613..4ca70550fce 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2372,6 +2372,22 @@ __metadata: languageName: node linkType: hard +"@envelop/response-cache@npm:^6.2.1": + version: 6.2.1 + resolution: "@envelop/response-cache@npm:6.2.1" + dependencies: + "@graphql-tools/utils": "npm:^10.0.3" + "@whatwg-node/fetch": "npm:^0.9.0" + fast-json-stable-stringify: "npm:^2.1.0" + lru-cache: "npm:^10.0.0" + tslib: "npm:^2.5.0" + peerDependencies: + "@envelop/core": ^5.0.0 + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 + checksum: 10c0/2faaabd3da9fbae324c6fe916757ff9e314f9545808a17acedb9013e74f38fb5458f45bd8b9f540020607deaba22cd63e0075d1c9214a698be726ebb1e8e5ae7 + languageName: node + linkType: hard + "@envelop/types@npm:5.0.0": version: 5.0.0 resolution: "@envelop/types@npm:5.0.0" @@ -2915,29 +2931,6 @@ __metadata: languageName: unknown linkType: soft -"@graphcommerce/content-areas@npm:9.0.0-canary.62, @graphcommerce/content-areas@workspace:packages/content-areas": - version: 0.0.0-use.local - resolution: "@graphcommerce/content-areas@workspace:packages/content-areas" - peerDependencies: - "@graphcommerce/eslint-config-pwa": ^9.0.0-canary.62 - "@graphcommerce/graphql": ^9.0.0-canary.62 - "@graphcommerce/graphql-mesh": ^9.0.0-canary.62 - "@graphcommerce/magento-product": ^9.0.0-canary.62 - "@graphcommerce/next-ui": ^9.0.0-canary.62 - "@graphcommerce/prettier-config-pwa": ^9.0.0-canary.62 - "@graphcommerce/react-hook-form": ^9.0.0-canary.62 - "@graphcommerce/typescript-config-pwa": ^9.0.0-canary.62 - "@lingui/core": ^4.2.1 - "@lingui/macro": ^4.2.1 - "@lingui/react": ^4.2.1 - "@mui/material": ^5.10.16 - framer-motion: ^10.0.0 - next: "*" - react: ^18.2.0 - react-dom: ^18.2.0 - languageName: unknown - linkType: soft - "@graphcommerce/demo-magento-graphcommerce@npm:9.0.0-canary.62, @graphcommerce/demo-magento-graphcommerce@workspace:packages/demo-magento-graphcommerce": version: 0.0.0-use.local resolution: "@graphcommerce/demo-magento-graphcommerce@workspace:packages/demo-magento-graphcommerce" @@ -3303,10 +3296,34 @@ __metadata: languageName: unknown linkType: soft +"@graphcommerce/graphql-gc-api@npm:9.0.0-canary.62, @graphcommerce/graphql-gc-api@workspace:packages/graphql-gc-api": + version: 0.0.0-use.local + resolution: "@graphcommerce/graphql-gc-api@workspace:packages/graphql-gc-api" + peerDependencies: + "@graphcommerce/eslint-config-pwa": ^9.0.0-canary.62 + "@graphcommerce/graphql": ^9.0.0-canary.62 + "@graphcommerce/graphql-mesh": ^9.0.0-canary.62 + "@graphcommerce/magento-product": ^9.0.0-canary.62 + "@graphcommerce/next-ui": ^9.0.0-canary.62 + "@graphcommerce/prettier-config-pwa": ^9.0.0-canary.62 + "@graphcommerce/react-hook-form": ^9.0.0-canary.62 + "@graphcommerce/typescript-config-pwa": ^9.0.0-canary.62 + "@lingui/core": ^4.2.1 + "@lingui/macro": ^4.2.1 + "@lingui/react": ^4.2.1 + "@mui/material": ^5.10.16 + framer-motion: ^10.0.0 + next: "*" + react: ^18.2.0 + react-dom: ^18.2.0 + languageName: unknown + linkType: soft + "@graphcommerce/graphql-mesh@npm:9.0.0-canary.62, @graphcommerce/graphql-mesh@workspace:packages/graphql-mesh": version: 0.0.0-use.local resolution: "@graphcommerce/graphql-mesh@workspace:packages/graphql-mesh" dependencies: + "@envelop/response-cache": "npm:^6.2.1" "@graphql-mesh/apollo-link": "npm:latest" "@graphql-mesh/config": "npm:latest" "@graphql-mesh/cross-helpers": "npm:latest" @@ -3429,6 +3446,7 @@ __metadata: "@graphcommerce/eslint-config-pwa": ^9.0.0-canary.62 "@graphcommerce/graphcms-ui": ^9.0.0-canary.62 "@graphcommerce/graphql": ^9.0.0-canary.62 + "@graphcommerce/graphql-mesh": ^9.0.0-canary.62 "@graphcommerce/image": ^9.0.0-canary.62 "@graphcommerce/next-ui": ^9.0.0-canary.62 "@graphcommerce/prettier-config-pwa": ^9.0.0-canary.62 @@ -3935,7 +3953,6 @@ __metadata: "@apollo/client": "npm:~3.10.8" "@ducanh2912/next-pwa": "npm:9.7.2" "@graphcommerce/cli": "npm:9.0.0-canary.62" - "@graphcommerce/content-areas": "npm:9.0.0-canary.62" "@graphcommerce/demo-magento-graphcommerce": "npm:9.0.0-canary.62" "@graphcommerce/ecommerce-ui": "npm:9.0.0-canary.62" "@graphcommerce/eslint-config-pwa": "npm:9.0.0-canary.62" @@ -3947,6 +3964,7 @@ __metadata: "@graphcommerce/googletagmanager": "npm:9.0.0-canary.62" "@graphcommerce/graphcms-ui": "npm:9.0.0-canary.62" "@graphcommerce/graphql": "npm:9.0.0-canary.62" + "@graphcommerce/graphql-gc-api": "npm:9.0.0-canary.62" "@graphcommerce/graphql-mesh": "npm:9.0.0-canary.62" "@graphcommerce/hygraph-cli": "npm:9.0.0-canary.62" "@graphcommerce/hygraph-dynamic-rows": "npm:9.0.0-canary.62" @@ -6030,7 +6048,7 @@ __metadata: languageName: node linkType: hard -"@graphql-tools/utils@npm:^10.0.0, @graphql-tools/utils@npm:^10.0.13, @graphql-tools/utils@npm:^10.1.0, @graphql-tools/utils@npm:^10.1.1, @graphql-tools/utils@npm:^10.2.1, @graphql-tools/utils@npm:^10.2.3, @graphql-tools/utils@npm:^10.3.0, @graphql-tools/utils@npm:^10.3.2": +"@graphql-tools/utils@npm:^10.0.0, @graphql-tools/utils@npm:^10.0.13, @graphql-tools/utils@npm:^10.0.3, @graphql-tools/utils@npm:^10.1.0, @graphql-tools/utils@npm:^10.1.1, @graphql-tools/utils@npm:^10.2.1, @graphql-tools/utils@npm:^10.2.3, @graphql-tools/utils@npm:^10.3.0, @graphql-tools/utils@npm:^10.3.2": version: 10.3.2 resolution: "@graphql-tools/utils@npm:10.3.2" dependencies: From 9059712f8623a0a2f239ecb557b63d6f95d56d80 Mon Sep 17 00:00:00 2001 From: Paul Hachmang Date: Thu, 1 Aug 2024 13:34:53 +0200 Subject: [PATCH 23/33] Further refactoring --- examples/magento-graphcms/.meshrc.yml | 10 +- .../components/Blog/BlogAuthor.graphql | 2 +- .../components/Blog/BlogItem.graphql | 2 +- .../components/Blog/BlogTags.graphql | 2 +- .../components/Blog/RowBlogContent.graphql | 1 + .../GraphCMS/PageContentQueryFragment.graphql | 19 -- .../RowCategory/RowCategory_category.graphqls | 11 - .../RowProduct/RowProduct_product.graphqls | 11 - .../components/GraphCMS/RowRenderer.tsx | 55 --- .../GcPage_Rows_Hygraph.graphql} | 4 +- .../GraphCMS/_config/GcRow.graphqls | 14 + .../GraphCMS/_config/gcRowHygraphRenderer.ts | 30 ++ .../components/GraphCMS/index.ts | 4 - examples/magento-graphcms/components/index.ts | 1 - examples/magento-graphcms/pages/index.tsx | 4 +- .../plugins/hygraph/HygraphContentArea.tsx | 11 +- examples/magento-graphcms/resolveProduct.ts | 10 + packages/cli/package.json | 1 + packages/graphql-gc-api/README.md | 203 ++++++++++- .../components/ContentArea/ContentArea.tsx | 29 +- .../components/GcPageMeta/GcPageHead.tsx | 15 +- .../components/GcPageMeta/index.ts | 1 - packages/graphql-gc-api/index.ts | 2 +- .../graphql-gc-api/queries/GcPage.graphql | 4 +- .../queries/GcPage_Data.graphql | 4 - .../GcPage_Head.graphql} | 13 +- .../queries/GcPage_Redirect.graphql | 6 + .../queries/GcPage_Rows.graphql | 9 + ...PageInterface.graphqls => GcPage.graphqls} | 12 +- .../graphql-gc-api/schema/GcPageHead.graphqls | 23 +- .../schema/GcPageRedirect.graphqls | 16 + packages/graphql-gc-api/schema/GcRow.graphqls | 8 + .../schema/Query_gcPage.graphqls | 2 +- packages/graphql-mesh/index.ts | 5 +- packages/graphql-mesh/package.json | 1 + .../graphql-mesh/plugin/forward-headers.ts | 1 + .../utils/applySelectionSetsFromResolvers.ts | 55 +++ .../graphql-mesh/utils/delegateToSchemaSdk.ts | 79 +++++ packages/graphql-mesh/utils/executeMesh.ts | 35 +- .../utils/traverseSelectionSet.ts | 53 +++ .../lib/hygraphDynamicRows.ts | 2 + .../hygraph-ui/graphql/GCPage_Hygraph.graphql | 3 - .../hygraph-ui/graphql/GcPage_Hygraph.graphql | 3 - .../hygraph-ui/graphql/HygraphPage.graphql | 4 +- packages/hygraph-ui/graphql/index.ts | 1 - .../mesh/resolveAdditionalResolvers.ts | 131 ++++++++ packages/hygraph-ui/mesh/resolvers.ts | 143 +++++--- packages/hygraph-ui/package.json | 1 + .../hygraph-ui/schema/Query_gcPage.graphqls | 33 +- .../Api/ProductListItem.graphql | 9 +- packages/magento-store/PageMeta.tsx | 4 +- yarn.lock | 316 +++++++++++++++++- 52 files changed, 1153 insertions(+), 265 deletions(-) delete mode 100644 examples/magento-graphcms/components/GraphCMS/PageContentQueryFragment.graphql delete mode 100644 examples/magento-graphcms/components/GraphCMS/RowCategory/RowCategory_category.graphqls delete mode 100644 examples/magento-graphcms/components/GraphCMS/RowProduct/RowProduct_product.graphqls delete mode 100644 examples/magento-graphcms/components/GraphCMS/RowRenderer.tsx rename examples/magento-graphcms/components/GraphCMS/{RowRenderer.graphql => _config/GcPage_Rows_Hygraph.graphql} (80%) create mode 100644 examples/magento-graphcms/components/GraphCMS/_config/GcRow.graphqls create mode 100644 examples/magento-graphcms/components/GraphCMS/_config/gcRowHygraphRenderer.ts delete mode 100644 examples/magento-graphcms/components/GraphCMS/index.ts create mode 100644 examples/magento-graphcms/resolveProduct.ts delete mode 100644 packages/graphql-gc-api/queries/GcPage_Data.graphql rename packages/graphql-gc-api/{components/GcPageMeta/GcPageHead.graphql => queries/GcPage_Head.graphql} (73%) create mode 100644 packages/graphql-gc-api/queries/GcPage_Redirect.graphql create mode 100644 packages/graphql-gc-api/queries/GcPage_Rows.graphql rename packages/graphql-gc-api/schema/{GcPageInterface.graphqls => GcPage.graphqls} (60%) create mode 100644 packages/graphql-gc-api/schema/GcPageRedirect.graphqls create mode 100644 packages/graphql-gc-api/schema/GcRow.graphqls create mode 100644 packages/graphql-mesh/utils/applySelectionSetsFromResolvers.ts create mode 100644 packages/graphql-mesh/utils/delegateToSchemaSdk.ts create mode 100644 packages/graphql-mesh/utils/traverseSelectionSet.ts delete mode 100644 packages/hygraph-ui/graphql/GCPage_Hygraph.graphql delete mode 100644 packages/hygraph-ui/graphql/GcPage_Hygraph.graphql create mode 100644 packages/hygraph-ui/mesh/resolveAdditionalResolvers.ts diff --git a/examples/magento-graphcms/.meshrc.yml b/examples/magento-graphcms/.meshrc.yml index 716dce965c8..d36068c534a 100644 --- a/examples/magento-graphcms/.meshrc.yml +++ b/examples/magento-graphcms/.meshrc.yml @@ -17,7 +17,14 @@ sources: # Remove field arguments: `query { anyfield(after,before,last,forceParentLocale,locales) { ... } }` - '*.*.!{after,before,last,forceParentLocale,locales,stage}' # Remove type any input or type fields: `input MyInput {}` or `type MyType { anyfield }` - - '*.!{localizations,scheduledIn,documentInStages*,createdAt*,updatedAt*,publishedAt*,createdBy,updatedBy,publishedBy,history,scheduledIn*}' + - '*.!{scheduledIn,documentInStages*,createdAt*,updatedAt*,publishedAt*,createdBy,updatedBy,publishedBy,history,scheduledIn*}' + - rename: + mode: wrap + renames: + - from: + type: Page + to: + type: GcPage - prune: skipPruning: [] - name: m2 @@ -36,7 +43,6 @@ sources: X-Forwarded-For: "{context.headers['x-forwarded-for']}" serve: playground: true - plugins: - '@graphcommerce/graphql-mesh/plugin/forward-headers': forwardHeaders: diff --git a/examples/magento-graphcms/components/Blog/BlogAuthor.graphql b/examples/magento-graphcms/components/Blog/BlogAuthor.graphql index 934c0d505cb..3bef34c35e8 100644 --- a/examples/magento-graphcms/components/Blog/BlogAuthor.graphql +++ b/examples/magento-graphcms/components/Blog/BlogAuthor.graphql @@ -1,4 +1,4 @@ -fragment BlogAuthor on Page { +fragment BlogAuthor on GcPage { date author } diff --git a/examples/magento-graphcms/components/Blog/BlogItem.graphql b/examples/magento-graphcms/components/Blog/BlogItem.graphql index ee371f34d1a..790b266dfd0 100644 --- a/examples/magento-graphcms/components/Blog/BlogItem.graphql +++ b/examples/magento-graphcms/components/Blog/BlogItem.graphql @@ -1,4 +1,4 @@ -fragment BlogItem on Page { +fragment BlogItem on GcPage { title url date diff --git a/examples/magento-graphcms/components/Blog/BlogTags.graphql b/examples/magento-graphcms/components/Blog/BlogTags.graphql index f44e2e108b4..5b6a018686f 100644 --- a/examples/magento-graphcms/components/Blog/BlogTags.graphql +++ b/examples/magento-graphcms/components/Blog/BlogTags.graphql @@ -1,4 +1,4 @@ -fragment BlogTags on Page { +fragment BlogTags on GcPage { relatedPages { title url diff --git a/examples/magento-graphcms/components/Blog/RowBlogContent.graphql b/examples/magento-graphcms/components/Blog/RowBlogContent.graphql index bd169574849..c0eb872e417 100644 --- a/examples/magento-graphcms/components/Blog/RowBlogContent.graphql +++ b/examples/magento-graphcms/components/Blog/RowBlogContent.graphql @@ -1,4 +1,5 @@ fragment RowBlogContent on RowBlogContent { + id content { raw } diff --git a/examples/magento-graphcms/components/GraphCMS/PageContentQueryFragment.graphql b/examples/magento-graphcms/components/GraphCMS/PageContentQueryFragment.graphql deleted file mode 100644 index e2fcfc40073..00000000000 --- a/examples/magento-graphcms/components/GraphCMS/PageContentQueryFragment.graphql +++ /dev/null @@ -1,19 +0,0 @@ -fragment PageContentQueryFragment on Query { - pages(where: { url: $url }) { - title - metaTitle - metaDescription - metaRobots - url - author - date - relatedPages { - title - url - } - asset { - ...Asset - } - ...RowRenderer - } -} diff --git a/examples/magento-graphcms/components/GraphCMS/RowCategory/RowCategory_category.graphqls b/examples/magento-graphcms/components/GraphCMS/RowCategory/RowCategory_category.graphqls deleted file mode 100644 index 42b2cdc5283..00000000000 --- a/examples/magento-graphcms/components/GraphCMS/RowCategory/RowCategory_category.graphqls +++ /dev/null @@ -1,11 +0,0 @@ -extend type RowCategory { - category: CategoryTree - @resolveTo( - sourceName: "m2" - sourceTypeName: "Query" - sourceFieldName: "categories" - requiredSelectionSet: "{ categoryUrl }" - sourceArgs: { filters: { url_key: { eq: "{root.categoryUrl}" } } } - result: "items[0]" - ) -} diff --git a/examples/magento-graphcms/components/GraphCMS/RowProduct/RowProduct_product.graphqls b/examples/magento-graphcms/components/GraphCMS/RowProduct/RowProduct_product.graphqls deleted file mode 100644 index b03d5c7c235..00000000000 --- a/examples/magento-graphcms/components/GraphCMS/RowProduct/RowProduct_product.graphqls +++ /dev/null @@ -1,11 +0,0 @@ -extend type RowProduct { - product: ProductInterface - @resolveTo( - sourceName: "m2" - sourceTypeName: "Query" - sourceFieldName: "products" - requiredSelectionSet: "{ identity }" - sourceArgs: { filter: { url_key: { eq: "{root.identity}" } }, pageSize: 1 } - result: "items[0]" - ) -} diff --git a/examples/magento-graphcms/components/GraphCMS/RowRenderer.tsx b/examples/magento-graphcms/components/GraphCMS/RowRenderer.tsx deleted file mode 100644 index b1904fd719b..00000000000 --- a/examples/magento-graphcms/components/GraphCMS/RowRenderer.tsx +++ /dev/null @@ -1,55 +0,0 @@ -import { GCPage_DataFragment } from '@graphcommerce/graphql-gc-api' -import { LazyHydrate, RenderType, TypeRenderer } from '@graphcommerce/next-ui' -import { memo } from 'react' -import { RowBlogContent } from '../Blog' -import { RowButtonLinkList } from './RowButtonLinkList/RowButtonLinkList' -import { RowCategory } from './RowCategory/RowCategory' -import { RowColumnOne } from './RowColumnOne/RowColumnOne' -import { RowColumnThree } from './RowColumnThree/RowColumnThree' -import { RowColumnTwo } from './RowColumnTwo/RowColumnTwo' -import { RowContentLinks } from './RowContentLinks/RowContentLinks' -import { RowHeroBanner } from './RowHeroBanner/RowHeroBanner' -import { RowLinks } from './RowLinks/RowLinks' -import { RowProduct } from './RowProduct/RowProduct' -import { RowQuote } from './RowQuote/RowQuote' -import { RowRendererFragment } from './RowRenderer.gql' -import { RowServiceOptions } from './RowServiceOptions/RowServiceOptions' -import { RowSpecialBanner } from './RowSpecialBanner/RowSpecialBanner' - -type ContentTypeRenderer = TypeRenderer - -const defaultRenderer: Partial = { - RowColumnOne, - RowColumnTwo, - RowColumnThree, - RowHeroBanner, - RowSpecialBanner, - RowQuote, - RowBlogContent, - RowButtonLinkList, - RowServiceOptions, - RowContentLinks, - RowProduct, - RowLinks, - RowCategory, -} - -export type PageProps = RowRendererFragment & { - renderer?: Partial - loadingEager?: number -} - -export const RowRenderer = memo((props) => { - const { content, renderer, loadingEager = 2 } = props - const mergedRenderer = { ...defaultRenderer, ...renderer } as ContentTypeRenderer - - return ( - <> - {content?.map((item, index) => ( - - - - ))} - - ) -}) diff --git a/examples/magento-graphcms/components/GraphCMS/RowRenderer.graphql b/examples/magento-graphcms/components/GraphCMS/_config/GcPage_Rows_Hygraph.graphql similarity index 80% rename from examples/magento-graphcms/components/GraphCMS/RowRenderer.graphql rename to examples/magento-graphcms/components/GraphCMS/_config/GcPage_Rows_Hygraph.graphql index 476015b3bfa..2a8031042b6 100644 --- a/examples/magento-graphcms/components/GraphCMS/RowRenderer.graphql +++ b/examples/magento-graphcms/components/GraphCMS/_config/GcPage_Rows_Hygraph.graphql @@ -1,5 +1,5 @@ -fragment RowRenderer on Page @inject(into: ["HygraphPage"]) { - content { +fragment GcPage_Rows_Hygraph on GcPage @inject(into: ["GcPage_Rows"]) { + rows { __typename ... on Node { id diff --git a/examples/magento-graphcms/components/GraphCMS/_config/GcRow.graphqls b/examples/magento-graphcms/components/GraphCMS/_config/GcRow.graphqls new file mode 100644 index 00000000000..24043d4d648 --- /dev/null +++ b/examples/magento-graphcms/components/GraphCMS/_config/GcRow.graphqls @@ -0,0 +1,14 @@ +union GcRow = + | RowBlogContent + | RowButtonLinkList + | RowCategory + | RowColumnOne + | RowColumnThree + | RowColumnTwo + | RowContentLinks + | RowHeroBanner + | RowLinks + | RowProduct + | RowQuote + | RowServiceOptions + | RowSpecialBanner diff --git a/examples/magento-graphcms/components/GraphCMS/_config/gcRowHygraphRenderer.ts b/examples/magento-graphcms/components/GraphCMS/_config/gcRowHygraphRenderer.ts new file mode 100644 index 00000000000..7b4b4549427 --- /dev/null +++ b/examples/magento-graphcms/components/GraphCMS/_config/gcRowHygraphRenderer.ts @@ -0,0 +1,30 @@ +import { GcRowTypeRenderer } from '@graphcommerce/graphql-gc-api' +import { RowBlogContent } from '../../Blog' +import { RowButtonLinkList } from '../RowButtonLinkList/RowButtonLinkList' +import { RowCategory } from '../RowCategory/RowCategory' +import { RowColumnOne } from '../RowColumnOne/RowColumnOne' +import { RowColumnThree } from '../RowColumnThree/RowColumnThree' +import { RowColumnTwo } from '../RowColumnTwo/RowColumnTwo' +import { RowContentLinks } from '../RowContentLinks/RowContentLinks' +import { RowHeroBanner } from '../RowHeroBanner/RowHeroBanner' +import { RowLinks } from '../RowLinks/RowLinks' +import { RowProduct } from '../RowProduct/RowProduct' +import { RowQuote } from '../RowQuote/RowQuote' +import { RowServiceOptions } from '../RowServiceOptions/RowServiceOptions' +import { RowSpecialBanner } from '../RowSpecialBanner/RowSpecialBanner' + +export const gcRowHygraphRenderer: Partial = { + RowColumnOne, + RowColumnTwo, + RowColumnThree, + RowHeroBanner, + RowSpecialBanner, + RowQuote, + RowBlogContent, + RowButtonLinkList, + RowServiceOptions, + RowContentLinks, + RowProduct, + RowLinks, + RowCategory, +} diff --git a/examples/magento-graphcms/components/GraphCMS/index.ts b/examples/magento-graphcms/components/GraphCMS/index.ts deleted file mode 100644 index 925e70dccdf..00000000000 --- a/examples/magento-graphcms/components/GraphCMS/index.ts +++ /dev/null @@ -1,4 +0,0 @@ -export * from './RowProduct/RowProduct' - -// The actual renderer -export * from './RowRenderer' diff --git a/examples/magento-graphcms/components/index.ts b/examples/magento-graphcms/components/index.ts index b58f561575f..7c4be478c2a 100644 --- a/examples/magento-graphcms/components/index.ts +++ b/examples/magento-graphcms/components/index.ts @@ -1,5 +1,4 @@ export * from './Blog' -export * from './GraphCMS' export * from './Layout' export * from './ProductListItems' export * from './ProductListLayout' diff --git a/examples/magento-graphcms/pages/index.tsx b/examples/magento-graphcms/pages/index.tsx index 310f8dd103d..95e20d2ea12 100644 --- a/examples/magento-graphcms/pages/index.tsx +++ b/examples/magento-graphcms/pages/index.tsx @@ -10,6 +10,7 @@ import { StoreConfigDocument } from '@graphcommerce/magento-store' import { GetStaticProps, LayoutHeader } from '@graphcommerce/next-ui' import { LayoutDocument, LayoutNavigation, LayoutNavigationProps } from '../components' import { graphqlSharedClient, graphqlSsrClient } from '../lib/graphql/graphqlSsrClient' +import { print, stripIgnoredCharacters } from 'graphql' type Props = GcPageQuery type RouteProps = { url: string } @@ -39,12 +40,13 @@ export const getStaticProps: GetPageStaticProps = async (context) => { const conf = client.query({ query: StoreConfigDocument }) const page = client.query({ query: GcPageDocument, variables: { input: { href: 'page/home' } } }) - const layout = staticClient.query({ query: LayoutDocument, fetchPolicy: cacheFirst(staticClient), }) + console.log(stripIgnoredCharacters(print(GcPageDocument))) + if (!(await page).data.page?.head) return { notFound: true } return { diff --git a/examples/magento-graphcms/plugins/hygraph/HygraphContentArea.tsx b/examples/magento-graphcms/plugins/hygraph/HygraphContentArea.tsx index 4e00229ec80..62da90d5d5b 100644 --- a/examples/magento-graphcms/plugins/hygraph/HygraphContentArea.tsx +++ b/examples/magento-graphcms/plugins/hygraph/HygraphContentArea.tsx @@ -1,6 +1,6 @@ import type { ContentAreaProps } from '@graphcommerce/graphql-gc-api' import type { PluginConfig, PluginProps } from '@graphcommerce/next-config' -import { RowRenderer } from '../../components/GraphCMS' +import { gcRowHygraphRenderer } from '../../components/GraphCMS/_config/gcRowHygraphRenderer' export const config: PluginConfig = { type: 'component', @@ -9,12 +9,5 @@ export const config: PluginConfig = { export const ContentArea = (props: PluginProps) => { const { Prev, ...rest } = props - const { gcPage } = rest - - return ( - <> - - {gcPage && } - - ) + return } diff --git a/examples/magento-graphcms/resolveProduct.ts b/examples/magento-graphcms/resolveProduct.ts new file mode 100644 index 00000000000..f3602c916a1 --- /dev/null +++ b/examples/magento-graphcms/resolveProduct.ts @@ -0,0 +1,10 @@ +// import { resolveRootDirectiveResolver } from './.mesh/index' + +import { MeshContext } from '@graphcommerce/graphql-mesh' + +const resolveProduct = (root, context: MeshContext, info) => { + console.log('ajaja') + // return context.accounts.Query.user({ root, args: { id: root.id }, context, info }) +} + +export default resolveProduct diff --git a/packages/cli/package.json b/packages/cli/package.json index 73335c41951..048b35089ab 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -24,6 +24,7 @@ "dependencies": { "@graphql-codegen/cli": "5.0.2", "@graphql-mesh/cli": "latest", + "@graphql-mesh/compose-cli": "latest", "@graphql-mesh/cross-helpers": "latest", "@graphql-mesh/runtime": "latest", "@graphql-mesh/store": "latest", diff --git a/packages/graphql-gc-api/README.md b/packages/graphql-gc-api/README.md index 18da56b36de..c89e7ee3b9f 100644 --- a/packages/graphql-gc-api/README.md +++ b/packages/graphql-gc-api/README.md @@ -1,4 +1,201 @@ -# GraphCommerce CMS API +# Graphql Gc Api -This package serves as an API extension point to integrate different CMS -solutions. +A generic GraphQL API layer for GraphCommerce. + +## Goals + +- Reduce the Hygraph dependency in the example/magento-hygraph to a bare minumm + so that other examples like examples/magento-nocms and + examples/magento-othercms can be created. + +- Allow the API to be easily extended without having to map all sorts of data + but still have all the flexibility. + +- Offer a set of default components that can be used as extension points. + +## GraphQL Schema + +This package offers the following new queries + +```graphql +extend type Query { + gcPage(input: GCPageInput!): GcPage +} + +type GcPage { + """ + The head of the page. + """ + head: GcPageHead + + """ + When the redirect is defined the page should not be rendered and the user should be redirected to the specified URL. + """ + redirect: GcPageRedirect +} +``` + +- [Query { gcPage }](./schema/Query_gcPage.graphqls) +- [GcPage](./schema/GcPage.graphqls) +- [GcPageHead](./schema/GcPageHead.graphqls) +- [GcPageRedirect](./schema/GCPageRedirect.graphqls) + +### Creating the GraphQL schema integration + +There are a few important steps to integrate with the GraphQL schema. First we +need to make your type compatible with GcPage. We take Hygraph as an example +here. + +For example we would normally execute the following query: + +```graphql +query Pages { + pagesConnection(where: { url: "page/home" }) { + edges { + node { + url + } + head { + title + description + alternate { + rel + href + hreflang + } + } + } + } +} +``` + +And in the end we would like to have the following query working: + +```graphql +query Pages { + pagesConnection(where: { url: "page/home" }) { + edges { + node { + url + } + # This part is the GcPageHead + head { + title + description + alternate { + rel + href + hreflang + } + redirect { + href + permanent + } + } + } + } +} +``` + +### Extend your type + +RENAME your type to GcPage. + +Note: After making changines to the schema or .meshrc.yaml you always need to +run `yarn codegen` to see your changes. + +If you now run `yarn codegen` you'll in the GraphiQL interface that your Page +implements `GcPage`. When running the query you will see an empty `head` and +empty redirect. + +### Implement the `head`/`redirect` fields for your type + +1. Extend the mesh configuration with a + [plugin that references an additionalResolver](../hygraph-ui/plugins/meshConfigHygraph.ts) +2. Create the resolver in [mesh/resolvers.ts](../hygraph-ui/mesh/resolvers.ts). +3. Run `yarn codegen` to add the configuration. + +Note: when developing your resolver you do not need to run yarn codegen after +every change, only when you change the schema or the mesh configuration. + +You should now see the `head` and `redirect` fields populated with data in your +original query. + +### Resolve the gcPage query to your created type. + +Now we want to be able to resolve this query. + +```graphql +query GCPage { + gcPage(input: { href: "page/home" }) { + head { + title + canonical { + hreflang + href + } + description + alternate { + hreflang + href + } + robots { + name + content + } + } + ... on Page { + head { + __typename + } + content { + __typename + } + } + } +} +``` + +### Resolve the gcPage query to your own query + +We define a `@resolveTo` for the gcPage query in the mesh configuration. + +So in this case we want to run the earlier pagesConnection query (as mentioned +above) when the gcPage query is called. + +The pagesConnection (sourceName) Query (sourceTypeName) should be calling +hygraph (sourceName). + +We want to take the href argument (args.input.href) from the gcPage query and +pass it to the `url` input field of the pagesConnection. (sourceArgs). + +Finally when the pagesConnection has ran, we want to get the first edge and +return the node as the result. (result). + +Resulting in the following code: + +```graphql +extend type Query { + gcPage(input: GCPageInput!): GcPage + @resolveTo( + sourceName: "hygraph" + sourceTypeName: "Query" + sourceFieldName: "pagesConnection" + sourceArgs: { where: { url: "{args.input.href}" } } + result: "edges[0].node" + ) +} +``` + +Learn more about +[combining multiple sources](https://the-guild.dev/graphql/mesh/docs/getting-started/combine-multiple-sources) + +Note: Because we change the schema, we need to run `yarn codegen` again. Note: +The resolveTo directive can doesn't really give warnings configured wrongly. + +After everything is set up you should be able to run the gcPage query and get +the data from the pagesConnection query. + +## Frontend integration + +## Whats next diff --git a/packages/graphql-gc-api/components/ContentArea/ContentArea.tsx b/packages/graphql-gc-api/components/ContentArea/ContentArea.tsx index 733fb266a9c..005fd3374f8 100644 --- a/packages/graphql-gc-api/components/ContentArea/ContentArea.tsx +++ b/packages/graphql-gc-api/components/ContentArea/ContentArea.tsx @@ -1,8 +1,29 @@ +import { LazyHydrate, RenderType, type TypeRenderer } from '@graphcommerce/next-ui' +import React from 'react' import { GcPageQuery } from '../../queries/GcPage.gql' +import { GcPage_RowsFragment } from '../../queries/GcPage_Rows.gql' -export type ContentAreaProps = GcPageQuery +export type GcRowTypeRenderer = TypeRenderer[number]> -export function ContentArea(props: ContentAreaProps) { - const { gcPage } = props - return

+export type ContentAreaProps = GcPageQuery & { + renderer?: Partial + loadingEager?: number } + +export const ContentArea = React.memo((props) => { + const { renderer, page, loadingEager = 2 } = props + const mergedRenderer = { ...renderer } as GcRowTypeRenderer + + const rows = page?.rows + if (!rows) return null + + return ( + <> + {rows?.map((item, index) => ( + + + + ))} + + ) +}) diff --git a/packages/graphql-gc-api/components/GcPageMeta/GcPageHead.tsx b/packages/graphql-gc-api/components/GcPageMeta/GcPageHead.tsx index cbafcf7c390..03b08fbc6c9 100644 --- a/packages/graphql-gc-api/components/GcPageMeta/GcPageHead.tsx +++ b/packages/graphql-gc-api/components/GcPageMeta/GcPageHead.tsx @@ -2,9 +2,13 @@ import { usePageContext } from '@graphcommerce/framer-next-pages' import { canonicalize } from '@graphcommerce/next-ui' import Head from 'next/head' import { useRouter } from 'next/router' -import { GcPageHeadFragment, GcLinkRelTagFragment, GcMetaTagFragment } from './GcPageHead.gql' +import { + GcPage_HeadFragment, + GcMetaTagFragment, + GcLinkRelTagFragment, +} from '../../queries/GcPage_Head.gql' -type GcPageMetaProps = GcPageHeadFragment & { +type GcPageMetaProps = GcPage_HeadFragment & { children?: React.ReactNode } @@ -37,20 +41,17 @@ export function GcPageMeta(props: GcPageMetaProps) { return ( {head.title.trim()} - {[...allLinkRel.values()].map((link) => ( ))} - {[...allMeta.values()].map((meta) => ( - + ))} - {children} ) diff --git a/packages/graphql-gc-api/components/GcPageMeta/index.ts b/packages/graphql-gc-api/components/GcPageMeta/index.ts index b94f812e577..51189cfb357 100644 --- a/packages/graphql-gc-api/components/GcPageMeta/index.ts +++ b/packages/graphql-gc-api/components/GcPageMeta/index.ts @@ -1,2 +1 @@ export * from './GcPageHead' -export * from './GcPageHead.gql' diff --git a/packages/graphql-gc-api/index.ts b/packages/graphql-gc-api/index.ts index b251b3c2c11..0f94ab9e4ab 100644 --- a/packages/graphql-gc-api/index.ts +++ b/packages/graphql-gc-api/index.ts @@ -1,4 +1,4 @@ export * from './components' -export * from './queries/GcPage_Data.gql' +export * from './queries/GcPage_Rows.gql' export * from './queries/GcPage.gql' export * from './components/GcPageMeta' diff --git a/packages/graphql-gc-api/queries/GcPage.graphql b/packages/graphql-gc-api/queries/GcPage.graphql index 3e0aac2d4d1..b8745b83f55 100644 --- a/packages/graphql-gc-api/queries/GcPage.graphql +++ b/packages/graphql-gc-api/queries/GcPage.graphql @@ -1,5 +1,7 @@ query GcPage($input: GCPageInput!) { page: gcPage(input: $input) { - ...GcPage_Data + ...GcPage_Head + ...GcPage_Redirect + ...GcPage_Rows } } diff --git a/packages/graphql-gc-api/queries/GcPage_Data.graphql b/packages/graphql-gc-api/queries/GcPage_Data.graphql deleted file mode 100644 index e59e11647dc..00000000000 --- a/packages/graphql-gc-api/queries/GcPage_Data.graphql +++ /dev/null @@ -1,4 +0,0 @@ -fragment GcPage_Data on GcPageInterface { - __typename - ...GcPageHead -} diff --git a/packages/graphql-gc-api/components/GcPageMeta/GcPageHead.graphql b/packages/graphql-gc-api/queries/GcPage_Head.graphql similarity index 73% rename from packages/graphql-gc-api/components/GcPageMeta/GcPageHead.graphql rename to packages/graphql-gc-api/queries/GcPage_Head.graphql index 9dce1603b8c..e3a0e9592dd 100644 --- a/packages/graphql-gc-api/components/GcPageMeta/GcPageHead.graphql +++ b/packages/graphql-gc-api/queries/GcPage_Head.graphql @@ -1,7 +1,7 @@ fragment GcLinkRelTag on GcLinkRelTag { rel - hreflang href + hreflang } fragment GcMetaTag on GcMetaTag { @@ -9,18 +9,21 @@ fragment GcMetaTag on GcMetaTag { content } -fragment GcPageHead on GcPageInterface { +fragment GcPage_Head on GcPage { head { title description canonical { - ...GcLinkRelTag + hreflang + href } alternate { - ...GcLinkRelTag + hreflang + href } robots { - ...GcMetaTag + name + content } meta { ...GcMetaTag diff --git a/packages/graphql-gc-api/queries/GcPage_Redirect.graphql b/packages/graphql-gc-api/queries/GcPage_Redirect.graphql new file mode 100644 index 00000000000..5874396a959 --- /dev/null +++ b/packages/graphql-gc-api/queries/GcPage_Redirect.graphql @@ -0,0 +1,6 @@ +fragment GcPage_Redirect on GcPage { + redirect { + href + permanent + } +} diff --git a/packages/graphql-gc-api/queries/GcPage_Rows.graphql b/packages/graphql-gc-api/queries/GcPage_Rows.graphql new file mode 100644 index 00000000000..4bc3b4665fa --- /dev/null +++ b/packages/graphql-gc-api/queries/GcPage_Rows.graphql @@ -0,0 +1,9 @@ +fragment GcPage_Rows on GcPage { + __typename + rows { + __typename + ... on GcRowFake { + id + } + } +} diff --git a/packages/graphql-gc-api/schema/GcPageInterface.graphqls b/packages/graphql-gc-api/schema/GcPage.graphqls similarity index 60% rename from packages/graphql-gc-api/schema/GcPageInterface.graphqls rename to packages/graphql-gc-api/schema/GcPage.graphqls index 2ed500c9c82..8ffd4809d06 100644 --- a/packages/graphql-gc-api/schema/GcPageInterface.graphqls +++ b/packages/graphql-gc-api/schema/GcPage.graphqls @@ -1,7 +1,4 @@ -""" -Defines an object to be able to be a fully valid HTML page. -""" -interface GcPageInterface { +type GcPage { """ The head of the page. """ @@ -10,5 +7,10 @@ interface GcPageInterface { """ When the redirect is defined the page should not be rendered and the user should be redirected to the specified URL. """ - redirect: GcLinkRelTag + redirect: GcPageRedirect + + """ + Rows of the content + """ + rows: [GcRow!] } diff --git a/packages/graphql-gc-api/schema/GcPageHead.graphqls b/packages/graphql-gc-api/schema/GcPageHead.graphqls index afeb0bcc167..5f54ce1d832 100644 --- a/packages/graphql-gc-api/schema/GcPageHead.graphqls +++ b/packages/graphql-gc-api/schema/GcPageHead.graphqls @@ -13,6 +13,25 @@ type GcMetaTag { content: String! } +type GcLinkRelAlternateTag { + """ + Used to specify the language of the target URL. Usually used in conjunction with rel="alternate" + + https://developer.mozilla.org/en-US/docs/Web/HTML/Element/link#hreflang + """ + hreflang: String + + """ + A fully qualified URL + + OR + + The relative part of the canonical URL. + As defined by: [pathname](https://developer.mozilla.org/en-US/docs/Web/API/URL/pathname) + [search](https://developer.mozilla.org/en-US/docs/Web/API/URL/search) + """ + href: String! +} + type GcLinkRelTag { """ The type of link relationship. @@ -54,8 +73,8 @@ type GcPageHead { """ description: String - canonical: GcLinkRelTag! - alternate: [GcLinkRelTag] + canonical: GcLinkRelAlternateTag! + alternate: [GcLinkRelAlternateTag!] robots: [GcMetaTag!] diff --git a/packages/graphql-gc-api/schema/GcPageRedirect.graphqls b/packages/graphql-gc-api/schema/GcPageRedirect.graphqls new file mode 100644 index 00000000000..e191c47430d --- /dev/null +++ b/packages/graphql-gc-api/schema/GcPageRedirect.graphqls @@ -0,0 +1,16 @@ +type GcPageRedirect { + """ + A fully qualified URL + + OR + + The relative part of the canonical URL. + As defined by: [pathname](https://developer.mozilla.org/en-US/docs/Web/API/URL/pathname) + [search](https://developer.mozilla.org/en-US/docs/Web/API/URL/search) + """ + href: String! + + """ + Defines if the redirect is permanent or temporary. + """ + permanent: Boolean! +} diff --git a/packages/graphql-gc-api/schema/GcRow.graphqls b/packages/graphql-gc-api/schema/GcRow.graphqls new file mode 100644 index 00000000000..d15811d30b4 --- /dev/null +++ b/packages/graphql-gc-api/schema/GcRow.graphqls @@ -0,0 +1,8 @@ +""" +This type only exists to make the GcRow union not fail. +""" +type GcRowFake { + id: ID! +} + +union GcRow = GcRowFake diff --git a/packages/graphql-gc-api/schema/Query_gcPage.graphqls b/packages/graphql-gc-api/schema/Query_gcPage.graphqls index dd1bf76b5cd..36f0c013cec 100644 --- a/packages/graphql-gc-api/schema/Query_gcPage.graphqls +++ b/packages/graphql-gc-api/schema/Query_gcPage.graphqls @@ -3,5 +3,5 @@ input GCPageInput { } extend type Query { - gcPage(input: GCPageInput!): GcPageInterface + gcPage(input: GCPageInput!): GcPage } diff --git a/packages/graphql-mesh/index.ts b/packages/graphql-mesh/index.ts index 4aafcef977a..4f6ec4777ac 100644 --- a/packages/graphql-mesh/index.ts +++ b/packages/graphql-mesh/index.ts @@ -1,5 +1,8 @@ export * from './api/createEnvelop' export * from './api/apolloLink' export * from './.mesh' -export * from './utils/executeMesh' +// export * from './utils/executeMesh' export * from './utils/meshCache' +export * from './utils/traverseSelectionSet' +export * from './utils/applySelectionSetsFromResolvers' +export * from './utils/delegateToSchemaSdk' diff --git a/packages/graphql-mesh/package.json b/packages/graphql-mesh/package.json index 24c86e48e2b..190d48bff02 100644 --- a/packages/graphql-mesh/package.json +++ b/packages/graphql-mesh/package.json @@ -17,6 +17,7 @@ "@graphql-mesh/runtime": "latest", "@graphql-mesh/store": "latest", "@graphql-mesh/transform-encapsulate": "latest", + "@graphql-mesh/transform-federation": "latest", "@graphql-mesh/transform-filter-schema": "latest", "@graphql-mesh/transform-hoist-field": "latest", "@graphql-mesh/transform-naming-convention": "latest", diff --git a/packages/graphql-mesh/plugin/forward-headers.ts b/packages/graphql-mesh/plugin/forward-headers.ts index 2337f2a910c..038930996d5 100644 --- a/packages/graphql-mesh/plugin/forward-headers.ts +++ b/packages/graphql-mesh/plugin/forward-headers.ts @@ -1,6 +1,7 @@ import { isAsyncIterable } from '@envelop/core' import { MeshPlugin, MeshPluginOptions } from '@graphql-mesh/types' import type { MeshContext } from '../.mesh' +import { GraphQLSchema } from 'graphql' interface ForwardHeaderConfig { forwardHeaders?: string[] diff --git a/packages/graphql-mesh/utils/applySelectionSetsFromResolvers.ts b/packages/graphql-mesh/utils/applySelectionSetsFromResolvers.ts new file mode 100644 index 00000000000..f91a9c9d4b3 --- /dev/null +++ b/packages/graphql-mesh/utils/applySelectionSetsFromResolvers.ts @@ -0,0 +1,55 @@ +/* eslint-disable import/no-extraneous-dependencies */ +import { Resolver, selectionSetByPath, type Resolvers } from '@graphcommerce/graphql-mesh' +import { parseSelectionSet } from '@graphql-tools/utils' +import { + Kind, + FieldNode, + SelectionNode, + GraphQLResolveInfo, + GraphQLObjectType, + responsePathAsArray, +} from 'graphql' + +export function applySelectionSetsFromResolvers(info: GraphQLResolveInfo, resolvers: Resolvers) { + let name: string + if (info.returnType instanceof GraphQLObjectType) { + name = info.returnType.name + } else throw new Error('Could not determine returnType for selection set') + + const selectionSet = selectionSetByPath( + info.operation.selectionSet, + responsePathAsArray(info.path).join('.'), + ) + + // eslint-disable-next-line @typescript-eslint/no-unsafe-argument + Object.entries(resolvers[name]).forEach(([field, resolverValue]) => { + const resolver = resolverValue as Resolver + + const idx = selectionSet.selections.findIndex( + (selection) => selection.kind === Kind.FIELD && selection.name.value === field, + ) + + const currentSelectionSet = selectionSet.selections.find( + (selection) => selection.kind === Kind.FIELD && selection.name.value === field, + ) as FieldNode | undefined + + let replaceWith: readonly SelectionNode[] = [] + + if ('selectionSet' in resolver) { + if (typeof resolver.selectionSet === 'function' && currentSelectionSet) { + replaceWith = resolver.selectionSet(currentSelectionSet).selections + } + if (typeof resolver.selectionSet === 'string') { + replaceWith = parseSelectionSet(resolver.selectionSet).selections + } + } + + selectionSet.selections = [ + ...selectionSet.selections.slice(0, idx), + ...replaceWith, + ...selectionSet.selections.slice(idx + 1), + ] + }) + + return selectionSet +} diff --git a/packages/graphql-mesh/utils/delegateToSchemaSdk.ts b/packages/graphql-mesh/utils/delegateToSchemaSdk.ts new file mode 100644 index 00000000000..ec364e728fb --- /dev/null +++ b/packages/graphql-mesh/utils/delegateToSchemaSdk.ts @@ -0,0 +1,79 @@ +/* eslint-disable import/no-extraneous-dependencies */ +import { InContextSdkMethod } from '@graphql-mesh/types' +import { delegateToSchema } from '@graphql-tools/delegate' +// import { batchDelegateToSchema } from '@graphql-tools/batch-delegate' +import { GraphQLResolveInfo, OperationTypeNode } from 'graphql' +import { MeshContext } from '../.mesh' + +export function delegateToSchemaSdk< + SourceName extends keyof MeshContext, + SourceTypeName extends keyof MeshContext[SourceName], + SourceFieldName extends keyof MeshContext[SourceName][SourceTypeName], +>(options: { + context: MeshContext + info: GraphQLResolveInfo + sourceName: SourceName + sourceTypeName: SourceTypeName + sourceFieldName: SourceFieldName + sourceArgs: MeshContext[SourceName][SourceTypeName][SourceFieldName] extends InContextSdkMethod< + unknown, + infer A + > + ? A + : unknown +}): MeshContext[SourceName][SourceTypeName][SourceFieldName] extends InContextSdkMethod + ? Promise + : unknown { + const { context, info, sourceArgs, sourceFieldName, sourceTypeName } = options + + const operationMap: Record = { + Query: OperationTypeNode.QUERY, + Mutation: OperationTypeNode.MUTATION, + Subscription: OperationTypeNode.SUBSCRIPTION, + } + + return delegateToSchema({ + context, + info, + schema: info.schema, + operation: operationMap[sourceTypeName as string], + fieldName: sourceFieldName as string, + args: sourceArgs as Record, + }) +} + +// export function batchDelegateToSchemaSdk< +// SourceName extends keyof MeshContext, +// SourceTypeName extends keyof MeshContext[SourceName], +// SourceFieldName extends keyof MeshContext[SourceName][SourceTypeName], +// >(options: { +// context: MeshContext +// info: GraphQLResolveInfo +// sourceName: SourceName +// sourceTypeName: SourceTypeName +// sourceFieldName: SourceFieldName +// key: MeshContext[SourceName][SourceTypeName][SourceFieldName] extends InContextSdkMethod< +// unknown, +// infer A +// > +// ? A +// : unknown +// }): MeshContext[SourceName][SourceTypeName][SourceFieldName] extends InContextSdkMethod +// ? Promise +// : unknown { +// const { context, info, sourceArgs, sourceFieldName, sourceTypeName } = options + +// const operationMap: Record = { +// Query: OperationTypeNode.QUERY, +// Mutation: OperationTypeNode.MUTATION, +// Subscription: OperationTypeNode.SUBSCRIPTION, +// } + +// return batchDelegateToSchema({ +// context, +// info, +// schema: info.schema, +// operation: operationMap[sourceTypeName as string], +// fieldName: sourceFieldName as string, +// }) +// } diff --git a/packages/graphql-mesh/utils/executeMesh.ts b/packages/graphql-mesh/utils/executeMesh.ts index 19c322b0ea7..fb8eb9c03b0 100644 --- a/packages/graphql-mesh/utils/executeMesh.ts +++ b/packages/graphql-mesh/utils/executeMesh.ts @@ -4,7 +4,6 @@ import type { MeshContext } from '@graphcommerce/graphql-mesh' import { InContextSdkMethod } from '@graphql-mesh/types' import { Kind, - SelectionSetNode, OperationTypeNode, OperationDefinitionNode, FieldNode, @@ -13,35 +12,7 @@ import { } from 'graphql' import type { Path } from 'react-hook-form' import { meshCache, MeshCacheOptions } from './meshCache' - -function isNumeric(n: string) { - return !Number.isNaN(parseFloat(n)) -} - -function traverseSelectionSet(incomingSelectionSet: SelectionSetNode, path: Path) { - const pathArray = path.split(/[,[\].]+?/) - let selectionSet = incomingSelectionSet - let pathIndex = 0 - - while (pathIndex < pathArray.length) { - const currentValue = pathArray[pathIndex] - if (!isNumeric(currentValue)) { - for (const selection of selectionSet.selections) { - if (selection.kind === Kind.FIELD && selection.name.value === currentValue) { - selectionSet = { - kind: Kind.SELECTION_SET, - selections: selection.selectionSet?.selections ?? [], - } - break - } - } - } - - pathIndex++ - } - - return selectionSet -} +import { selectionSetByPath } from './traverseSelectionSet' type OperationType = 'Query' | 'Mutation' | 'Subscription' function getOperationType(def: OperationDefinitionNode) { @@ -106,7 +77,7 @@ function maybeExecutor(context: MeshContext, operationType: OperationType, opera return found } -export async function executeMesh>( +async function executeMesh>( document: TypedDocumentNode, options: { variables: V }, context: MeshContext, @@ -126,7 +97,7 @@ export async function executeMesh>( field.name.value, )?.({ context, - selectionSet: traverseSelectionSet(def.selectionSet, field.name.value as Path), + selectionSet: selectionSetByPath(def.selectionSet, field.name.value as Path), args: collectArguments(field, options.variables), }), ] as const, diff --git a/packages/graphql-mesh/utils/traverseSelectionSet.ts b/packages/graphql-mesh/utils/traverseSelectionSet.ts new file mode 100644 index 00000000000..eec2d8f6879 --- /dev/null +++ b/packages/graphql-mesh/utils/traverseSelectionSet.ts @@ -0,0 +1,53 @@ +import { Kind, SelectionNode, SelectionSetNode } from 'graphql' +import type { Path } from 'react-hook-form' + +function isNumeric(n: string) { + return !Number.isNaN(parseFloat(n)) +} + +/** + * + */ +export function selectionSetByPath( + incomingSelectionSet: SelectionSetNode, + path: Path, +) { + const pathArray = path.split(/[,[\].]+?/) + let selectionSet = incomingSelectionSet + let pathIndex = 0 + + while (pathIndex < pathArray.length) { + let currentValue = pathArray[pathIndex] + + const isNegation = currentValue.startsWith('!') + currentValue = isNegation ? currentValue.slice(1) : currentValue + + if (!isNumeric(currentValue)) { + const newSelections: SelectionNode[] = [] + + for (const selection of selectionSet.selections) { + // if (selection.kind === Kind.INLINE_FRAGMENT) { + // console.log(selection) + // } + if (selection.kind === Kind.FIELD) { + if (!isNegation && selection.name.value === currentValue) { + newSelections.push(...(selection.selectionSet?.selections ?? [])) + } + + if (isNegation && selection.name.value !== currentValue) { + newSelections.push(...(selection.selectionSet?.selections ?? [])) + } + } + } + + selectionSet = { + kind: Kind.SELECTION_SET, + selections: newSelections, + } + } + + pathIndex++ + } + + return selectionSet +} diff --git a/packages/hygraph-dynamic-rows/lib/hygraphDynamicRows.ts b/packages/hygraph-dynamic-rows/lib/hygraphDynamicRows.ts index dd9f76d4a41..1375444f861 100644 --- a/packages/hygraph-dynamic-rows/lib/hygraphDynamicRows.ts +++ b/packages/hygraph-dynamic-rows/lib/hygraphDynamicRows.ts @@ -115,6 +115,8 @@ export function applyDynamicRows( * * - Uses an early bailout to check to reduce hygraph calls. * - Implements an alias sytem to merge the content of multiple pages. + * + * @deprecated Please use the resolver instead. */ export async function hygraphDynamicRows( client: ApolloClient, diff --git a/packages/hygraph-ui/graphql/GCPage_Hygraph.graphql b/packages/hygraph-ui/graphql/GCPage_Hygraph.graphql deleted file mode 100644 index 0de9550a65a..00000000000 --- a/packages/hygraph-ui/graphql/GCPage_Hygraph.graphql +++ /dev/null @@ -1,3 +0,0 @@ -fragment GCPage_Hygraph on GcPageInterface @inject(into: ["GcPage_Data"]) { - ...HygraphPage -} diff --git a/packages/hygraph-ui/graphql/GcPage_Hygraph.graphql b/packages/hygraph-ui/graphql/GcPage_Hygraph.graphql deleted file mode 100644 index 0de9550a65a..00000000000 --- a/packages/hygraph-ui/graphql/GcPage_Hygraph.graphql +++ /dev/null @@ -1,3 +0,0 @@ -fragment GCPage_Hygraph on GcPageInterface @inject(into: ["GcPage_Data"]) { - ...HygraphPage -} diff --git a/packages/hygraph-ui/graphql/HygraphPage.graphql b/packages/hygraph-ui/graphql/HygraphPage.graphql index aa34bfe8ddf..e68b5b89c98 100644 --- a/packages/hygraph-ui/graphql/HygraphPage.graphql +++ b/packages/hygraph-ui/graphql/HygraphPage.graphql @@ -1,6 +1,4 @@ -fragment HygraphPage on Page { - title - url +fragment HygraphPage on GcPage @inject(into: ["GcPage_Rows"]) { author date relatedPages { diff --git a/packages/hygraph-ui/graphql/index.ts b/packages/hygraph-ui/graphql/index.ts index 3c557f0cece..36958d67013 100644 --- a/packages/hygraph-ui/graphql/index.ts +++ b/packages/hygraph-ui/graphql/index.ts @@ -1,5 +1,4 @@ export * from './HygraphAllPages.gql' export * from './HygraphPage.gql' -export * from './GCPage_Hygraph.gql' export * from './PageLink.gql' export * from './PagesStaticPaths.gql' diff --git a/packages/hygraph-ui/mesh/resolveAdditionalResolvers.ts b/packages/hygraph-ui/mesh/resolveAdditionalResolvers.ts new file mode 100644 index 00000000000..3b370f9e291 --- /dev/null +++ b/packages/hygraph-ui/mesh/resolveAdditionalResolvers.ts @@ -0,0 +1,131 @@ +import type { YamlConfig } from '@graphql-mesh/types' +import { parseSelectionSet } from '@graphql-tools/utils' +import type { + GraphQLNamedType, + GraphQLObjectType, + GraphQLSchema, + GraphQLType, + SelectionSetNode, +} from 'graphql' +import { getNamedType, isAbstractType, isInterfaceType, isObjectType, Kind } from 'graphql' +import toPath from 'lodash.topath' + +function getTypeByPath(type: GraphQLType, path: string[]): GraphQLNamedType { + if ('ofType' in type) { + return getTypeByPath(getNamedType(type), path) + } + if (path.length === 0) { + return getNamedType(type) + } + if (!('getFields' in type)) { + throw new Error(`${type} cannot have a path ${path.join('.')}`) + } + const fieldMap = type.getFields() + const currentFieldName = path[0] + // Might be an index of an array + if (!Number.isNaN(parseInt(currentFieldName))) { + return getTypeByPath(type, path.slice(1)) + } + const field = fieldMap[currentFieldName] + if (!field?.type) { + throw new Error(`${type}.${currentFieldName} is not a valid field.`) + } + return getTypeByPath(field.type, path.slice(1)) +} + +export function generateSelectionSetFactory( + schema: GraphQLSchema, + additionalResolver: + | YamlConfig.AdditionalStitchingBatchResolverObject + | YamlConfig.AdditionalStitchingResolverObject, +) { + if (additionalResolver.sourceSelectionSet) { + return () => parseSelectionSet(additionalResolver.sourceSelectionSet) + // If result path provided without a selectionSet + } + if (additionalResolver.result) { + const resultPath = toPath(additionalResolver.result) + let abstractResultTypeName: string + + const sourceType = schema.getType(additionalResolver.sourceTypeName) as GraphQLObjectType + const sourceTypeFields = sourceType.getFields() + const sourceField = sourceTypeFields[additionalResolver.sourceFieldName] + const resultFieldType = getTypeByPath(sourceField.type, resultPath) + + if (isAbstractType(resultFieldType)) { + if (additionalResolver.resultType) { + abstractResultTypeName = additionalResolver.resultType + } else { + const targetType = schema.getType(additionalResolver.targetTypeName) as GraphQLObjectType + const targetTypeFields = targetType.getFields() + const targetField = targetTypeFields[additionalResolver.targetFieldName] + const targetFieldType = getNamedType(targetField.type) + abstractResultTypeName = targetFieldType?.name + } + if (abstractResultTypeName !== resultFieldType.name) { + const abstractResultType = schema.getType(abstractResultTypeName) + if ( + (isInterfaceType(abstractResultType) || isObjectType(abstractResultType)) && + !schema.isSubType(resultFieldType, abstractResultType) + ) { + throw new Error( + `${additionalResolver.sourceTypeName}.${ + additionalResolver.sourceFieldName + }.${resultPath.join('.')} doesn't implement ${abstractResultTypeName}.}`, + ) + } + } + } + + return (subtree: SelectionSetNode) => { + let finalSelectionSet = subtree + let isLastResult = true + const resultPathReversed = [...resultPath].reverse() + for (const pathElem of resultPathReversed) { + // Ensure the path elem is not array index + if (Number.isNaN(parseInt(pathElem))) { + if ( + isLastResult && + abstractResultTypeName && + abstractResultTypeName !== resultFieldType.name + ) { + finalSelectionSet = { + kind: Kind.SELECTION_SET, + selections: [ + { + kind: Kind.INLINE_FRAGMENT, + typeCondition: { + kind: Kind.NAMED_TYPE, + name: { + kind: Kind.NAME, + value: abstractResultTypeName, + }, + }, + selectionSet: finalSelectionSet, + }, + ], + } + } + finalSelectionSet = { + kind: Kind.SELECTION_SET, + selections: [ + { + // we create a wrapping AST Field + kind: Kind.FIELD, + name: { + kind: Kind.NAME, + value: pathElem, + }, + // Inside the field selection + selectionSet: finalSelectionSet, + }, + ], + } + isLastResult = false + } + } + return finalSelectionSet + } + } + return undefined +} diff --git a/packages/hygraph-ui/mesh/resolvers.ts b/packages/hygraph-ui/mesh/resolvers.ts index 725c845fe6d..63b40e583c9 100644 --- a/packages/hygraph-ui/mesh/resolvers.ts +++ b/packages/hygraph-ui/mesh/resolvers.ts @@ -1,51 +1,114 @@ /* eslint-disable import/no-extraneous-dependencies */ -import type { Resolvers } from '@graphcommerce/graphql-mesh' -import { Kind, FieldNode, SelectionSetNode } from 'graphql' +import { + GcMetaTag, + MetaRobots, + type Resolvers, + delegateToSchemaSdk, +} from '@graphcommerce/graphql-mesh' +import { Kind } from 'graphql' -function selectionSetFromPath(path: string[], selectionSet?: SelectionSetNode) { - const [fieldName, ...rest] = path - - const selection = selectionSet?.selections.find( - (s) => s.kind === Kind.FIELD && s.name.value === fieldName, - ) as FieldNode - - if (!selection?.selectionSet) return undefined - if (rest.length === 0) return selection.selectionSet - - return selectionSetFromPath(rest, selection.selectionSet) +const normalizeUrl = (href: string) => { + const cleanedhref = href.replaceAll(/^\/|\/$/g, '') + return `/${cleanedhref === 'page/home' ? '' : cleanedhref}` } - -function mergeSelectionSetNodes( - node1: SelectionSetNode | undefined, - node2: SelectionSetNode | undefined, -): SelectionSetNode { - const selections = [...(node1?.selections ?? []), ...(node2?.selections ?? [])] - - return { - kind: Kind.SELECTION_SET, - selections, - } +const denormalizeUrl = (href: string) => { + const cleanedhref = href.replaceAll(/^\/|\/$/g, '') + return cleanedhref === '' ? 'page/home' : cleanedhref } export const resolvers: Resolvers = { - // Query: { - // gcPage: async (root, { input }, context, info) => { - // const pages = await context.hygraph.Query.pages({ - // root, - // args: { where: input }, - // context, - // info, - // }) + GcPage: { + rows: { + // Rewrite the rows field to the content field. + // Strip out product and category as they will be resolved by Magento. + selectionSet: (root) => ({ + kind: Kind.SELECTION_SET, + selections: [ + { + kind: Kind.FIELD, + name: { kind: Kind.NAME, value: 'content' }, + selectionSet: { + kind: Kind.SELECTION_SET, + selections: + root.selectionSet?.selections?.filter( + (selection) => + selection.kind !== Kind.FIELD || + !['product', 'category'].includes(selection.name.value), + ) ?? [], + }, + }, + ], + }), + resolve: (root) => root.rows ?? root.content, + }, + head: { + selectionSet: `{ + id + url + locale + metaTitle + metaDescription + metaRobots + localizations(includeCurrent: false) { + locale + url + metaRobots + } + }`, + resolve: ({ head, url, locale, metaRobots, metaDescription, metaTitle, localizations }) => { + function formatRobots(bots?: MetaRobots, name: string = 'robots'): GcMetaTag { + const robots: string[] = [] + if (bots?.includes('NOINDEX')) robots.push('noindex') + if (bots?.includes('NOFOLLOW')) robots.push('nofollow') + return { name, content: robots.length > 0 ? robots.join(', ') : 'all' } + } - // const page = pages[0] - // return { id: page.id } - // }, - // }, + return ( + head ?? { + canonical: { rel: 'canonical', href: normalizeUrl(url), hreflang: locale }, + robots: [formatRobots(metaRobots)], + alternate: localizations + ?.filter((v) => !formatRobots(v.metaRobots).content.includes('noindex')) + ?.map((loc) => ({ + rel: 'alternate', + href: normalizeUrl(loc.url), + hreflang: loc.locale, + })), + title: metaTitle, + description: metaDescription, + } + ) + }, + }, + }, + Query: { + gcPage: { + /** + * We are using delegateToSchema, because we've encountered limitations with + * `context.hygraph.Query.pages({...})`: + * + * - The above resolver are not called as we are directly resolving the + * source/subgraph/directly and these resolvers are on the final schema / supergraph. + * - Somehwere inside the resulting types inside pages we've got a few @resolveTo directives + * defined and those are not called either. + */ + resolve: async (_, args, context, info) => { + /** + * This is a wrapper around delegateToSchema, does some inferring of the return type and the arguments. + * + * Might it be an idea to have a @delegateTo directive that can be used in the schema? + */ + const result = await delegateToSchemaSdk({ + context, + info, + sourceName: 'hygraph', + sourceTypeName: 'Query', + sourceFieldName: 'pages', + sourceArgs: { where: { url: denormalizeUrl(args.input.href) } }, + }) - Page: { - someField: { - selectionSet: '{ id }', - resolve: (root) => root.id, + return result?.[0] + }, }, }, } diff --git a/packages/hygraph-ui/package.json b/packages/hygraph-ui/package.json index f23963b1920..c7f1513fd90 100644 --- a/packages/hygraph-ui/package.json +++ b/packages/hygraph-ui/package.json @@ -15,6 +15,7 @@ "@graphcommerce/ecommerce-ui": "^9.0.0-canary.62", "@graphcommerce/eslint-config-pwa": "^9.0.0-canary.62", "@graphcommerce/graphql": "^9.0.0-canary.62", + "@graphcommerce/graphql-gc-api": "^9.0.0-canary.62", "@graphcommerce/image": "^9.0.0-canary.62", "@graphcommerce/next-ui": "^9.0.0-canary.62", "@graphcommerce/prettier-config-pwa": "^9.0.0-canary.62", diff --git a/packages/hygraph-ui/schema/Query_gcPage.graphqls b/packages/hygraph-ui/schema/Query_gcPage.graphqls index b435d3b03d3..a4ad8f69577 100644 --- a/packages/hygraph-ui/schema/Query_gcPage.graphqls +++ b/packages/hygraph-ui/schema/Query_gcPage.graphqls @@ -1,22 +1,23 @@ -type Page implements GcPageInterface { - """ - The head of the page. - """ - head: GcPageHead - - """ - When the redirect is defined the page should not be rendered and the user should be redirected to the specified URL. - """ - redirect: GcLinkRelTag +type RowCategory { + category: CategoryTree + @resolveTo( + sourceName: "m2" + sourceTypeName: "Query" + sourceFieldName: "categories" + requiredSelectionSet: "{ categoryUrl }" + sourceArgs: { filters: { url_path: { eq: "{root.categoryUrl}" } } } + result: "items[0]" + ) } -extend type Query { - gcPage(input: GCPageInput!): GcPageInterface +type RowProduct { + product: ProductInterface @resolveTo( - sourceName: "hygraph" + sourceName: "m2" sourceTypeName: "Query" - sourceFieldName: "pagesConnection" - sourceArgs: { where: { url: "{args.input.url}" } } - result: "edges[0].node" + sourceFieldName: "products" + requiredSelectionSet: "{ identity }" + sourceArgs: { filter: { url_key: { eq: "{root.identity}" } }, pageSize: 1 } + result: "items[0]" ) } diff --git a/packages/magento-product/Api/ProductListItem.graphql b/packages/magento-product/Api/ProductListItem.graphql index 48969ce9665..be7f7463c96 100644 --- a/packages/magento-product/Api/ProductListItem.graphql +++ b/packages/magento-product/Api/ProductListItem.graphql @@ -6,12 +6,9 @@ fragment ProductListItem on ProductInterface { small_image { ...ProductImage } - - ... on ProductInterface @defer { - price_range { - minimum_price { - ...ProductListPrice - } + price_range { + minimum_price { + ...ProductListPrice } } } diff --git a/packages/magento-store/PageMeta.tsx b/packages/magento-store/PageMeta.tsx index e570fc744d3..b90d01deab5 100644 --- a/packages/magento-store/PageMeta.tsx +++ b/packages/magento-store/PageMeta.tsx @@ -1,5 +1,5 @@ import { useQuery } from '@graphcommerce/graphql' -import { PageMetaProps } from '@graphcommerce/next-ui' +import { PageMetaProps, PageMeta as PageMetaBase } from '@graphcommerce/next-ui' import { StoreConfigDocument } from './StoreConfig.gql' export function PageMeta(props: PageMetaProps) { @@ -19,5 +19,5 @@ export function PageMeta(props: PageMetaProps) { } const { title, ...pageMetaProps } = props - return + return } diff --git a/yarn.lock b/yarn.lock index 4ca70550fce..05c69f0a332 100644 --- a/yarn.lock +++ b/yarn.lock @@ -210,6 +210,15 @@ __metadata: languageName: node linkType: hard +"@apollo/cache-control-types@npm:^1.0.2": + version: 1.0.3 + resolution: "@apollo/cache-control-types@npm:1.0.3" + peerDependencies: + graphql: 14.x || 15.x || 16.x + checksum: 10c0/b49a9e99c7d5af6dfe12b775eb6374c8a54894e17ffa882b3d85f4501ca19ee413bdcc1a787a4b44dcc2903ce2c28f19b69116f338f88670c4f6f2e10a0bc498 + languageName: node + linkType: hard + "@apollo/client@npm:~3.10.8, @apollo/client@npm:~3.2.5 || ~3.3.0 || ~3.4.0 || ~3.5.0 || ~3.6.0 || ~3.7.0 || ~3.8.0 || ~3.9.0 || ~3.10.0": version: 3.10.8 resolution: "@apollo/client@npm:3.10.8" @@ -247,6 +256,32 @@ __metadata: languageName: node linkType: hard +"@apollo/federation-internals@npm:2.8.4": + version: 2.8.4 + resolution: "@apollo/federation-internals@npm:2.8.4" + dependencies: + "@types/uuid": "npm:^9.0.0" + chalk: "npm:^4.1.0" + js-levenshtein: "npm:^1.1.6" + uuid: "npm:^9.0.0" + peerDependencies: + graphql: ^16.5.0 + checksum: 10c0/3c3cbe56db3dbf09f152ca22fe2b9c2729aec5c3d5bf598fe82bf61219667d891e612963ca1b444a546e47cbd6f9f2c5484c482dbba5858b53b819ad5e65afcc + languageName: node + linkType: hard + +"@apollo/subgraph@npm:^2.4.1": + version: 2.8.4 + resolution: "@apollo/subgraph@npm:2.8.4" + dependencies: + "@apollo/cache-control-types": "npm:^1.0.2" + "@apollo/federation-internals": "npm:2.8.4" + peerDependencies: + graphql: ^16.5.0 + checksum: 10c0/2b40fc3227e4c06853495182b18a0809569851a5536c8159fe858a6939e8cda839cc3ac93ca0ba6b8f74e4d58dad7307c2764683b3d26980a37d70fc8ae3f61e + languageName: node + linkType: hard + "@ardatan/relay-compiler@npm:12.0.0": version: 12.0.0 resolution: "@ardatan/relay-compiler@npm:12.0.0" @@ -2112,6 +2147,15 @@ __metadata: languageName: node linkType: hard +"@commander-js/extra-typings@npm:^12.0.1": + version: 12.1.0 + resolution: "@commander-js/extra-typings@npm:12.1.0" + peerDependencies: + commander: ~12.1.0 + checksum: 10c0/5d29eaa724b577e2a52a393ad54992924d2559931b8e493ab892477b7a4e878e475c6bf771260f8585d835f7d8e17ae4a2656c191e9595d210ae0b48291c0b3d + languageName: node + linkType: hard + "@corex/deepmerge@npm:^4.0.43": version: 4.0.43 resolution: "@corex/deepmerge@npm:4.0.43" @@ -2898,6 +2942,7 @@ __metadata: dependencies: "@graphql-codegen/cli": "npm:5.0.2" "@graphql-mesh/cli": "npm:latest" + "@graphql-mesh/compose-cli": "npm:latest" "@graphql-mesh/cross-helpers": "npm:latest" "@graphql-mesh/runtime": "npm:latest" "@graphql-mesh/store": "npm:latest" @@ -3234,6 +3279,7 @@ __metadata: "@graphcommerce/ecommerce-ui": ^9.0.0-canary.62 "@graphcommerce/eslint-config-pwa": ^9.0.0-canary.62 "@graphcommerce/graphql": ^9.0.0-canary.62 + "@graphcommerce/graphql-gc-api": ^9.0.0-canary.62 "@graphcommerce/image": ^9.0.0-canary.62 "@graphcommerce/next-ui": ^9.0.0-canary.62 "@graphcommerce/prettier-config-pwa": ^9.0.0-canary.62 @@ -3335,6 +3381,7 @@ __metadata: "@graphql-mesh/runtime": "npm:latest" "@graphql-mesh/store": "npm:latest" "@graphql-mesh/transform-encapsulate": "npm:latest" + "@graphql-mesh/transform-federation": "npm:latest" "@graphql-mesh/transform-filter-schema": "npm:latest" "@graphql-mesh/transform-hoist-field": "npm:latest" "@graphql-mesh/transform-naming-convention": "npm:latest" @@ -5170,6 +5217,30 @@ __metadata: languageName: node linkType: hard +"@graphql-mesh/compose-cli@npm:latest": + version: 0.6.6 + resolution: "@graphql-mesh/compose-cli@npm:0.6.6" + dependencies: + "@commander-js/extra-typings": "npm:^12.0.1" + "@graphql-mesh/fusion-composition": "npm:^0.1.7" + "@graphql-mesh/utils": "npm:^0.99.5" + "@graphql-tools/graphql-file-loader": "npm:8.0.1" + "@graphql-tools/load": "npm:^8.0.1" + "@graphql-tools/schema": "npm:^10.0.4" + "@graphql-tools/utils": "npm:^10.2.3" + "@whatwg-node/fetch": "npm:^0.9.14" + commander: "npm:^12.0.0" + dotenv: "npm:^16.3.1" + jiti: "npm:^1.21.6" + peerDependencies: + "@graphql-mesh/types": ^0.99.5 + graphql: "*" + bin: + mesh-compose: esm/bin.js + checksum: 10c0/eb2c8aa54a6ac5e6dda3bd4fe21ec3d58c6eecdab82e28e53576d1a95227d1735a4ab1b1ca3c02779f34be92c828c2d076a1c46326ee88a6a07c33737125c79c + languageName: node + linkType: hard + "@graphql-mesh/config@npm:^0.101.1, @graphql-mesh/config@npm:latest": version: 0.101.1 resolution: "@graphql-mesh/config@npm:0.101.1" @@ -5211,6 +5282,27 @@ __metadata: languageName: node linkType: hard +"@graphql-mesh/fusion-composition@npm:^0.1.7": + version: 0.1.7 + resolution: "@graphql-mesh/fusion-composition@npm:0.1.7" + dependencies: + "@graphql-mesh/utils": "npm:^0.99.5" + "@graphql-tools/schema": "npm:^10.0.4" + "@graphql-tools/stitching-directives": "npm:^3.1.2" + "@graphql-tools/utils": "npm:^10.3.2" + "@theguild/federation-composition": "npm:^0.12.0" + change-case: "npm:^4.1.2" + graphql-scalars: "npm:^1.23.0" + minimatch: "npm:^10.0.0" + pluralize: "npm:^8.0.0" + snake-case: "npm:^3.0.0" + tslib: "npm:^2.4.0" + peerDependencies: + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + checksum: 10c0/4533f12a578252150d80ee6e48308200e386945f2f4bd02be7bd820807c71c88698a7fb39fa3d654c942300e0ecf1ea5427439f41c3e25a119d55f8272a313a7 + languageName: node + linkType: hard + "@graphql-mesh/graphql@npm:latest": version: 0.99.1 resolution: "@graphql-mesh/graphql@npm:0.99.1" @@ -5390,6 +5482,20 @@ __metadata: languageName: node linkType: hard +"@graphql-mesh/string-interpolation@npm:^0.5.5": + version: 0.5.5 + resolution: "@graphql-mesh/string-interpolation@npm:0.5.5" + dependencies: + dayjs: "npm:1.11.12" + json-pointer: "npm:0.6.2" + lodash.get: "npm:4.4.2" + peerDependencies: + graphql: "*" + tslib: ^2.4.0 + checksum: 10c0/424ed831359a8d4a9b4a06a06a07c23855a034eda15bdae4f6db9ed28884be193c1165ca709374d7b862eafb5eea188f1d4e71d0aad479dbf081aecd7f3df188 + languageName: node + linkType: hard + "@graphql-mesh/transform-encapsulate@npm:latest": version: 0.99.1 resolution: "@graphql-mesh/transform-encapsulate@npm:0.99.1" @@ -5406,6 +5512,26 @@ __metadata: languageName: node linkType: hard +"@graphql-mesh/transform-federation@npm:latest": + version: 0.99.6 + resolution: "@graphql-mesh/transform-federation@npm:0.99.6" + dependencies: + "@apollo/subgraph": "npm:^2.4.1" + "@graphql-mesh/string-interpolation": "npm:^0.5.5" + "@graphql-tools/delegate": "npm:^10.0.16" + "@graphql-tools/stitching-directives": "npm:^3.1.2" + dset: "npm:^3.1.2" + graphql-transform-federation: "npm:^2.2.0" + peerDependencies: + "@graphql-mesh/types": ^0.99.5 + "@graphql-mesh/utils": ^0.99.5 + "@graphql-tools/utils": ^10.2.3 + graphql: "*" + tslib: ^2.4.0 + checksum: 10c0/907ade7208c82d48f4f7f204b42e0b6becf90a93bae5fd52d2e7becca27cf15aa14768d2efbc39a1d63830894bc58f188ef732f42078d695a2a173f2ef4f6a03 + languageName: node + linkType: hard + "@graphql-mesh/transform-filter-schema@npm:latest": version: 0.99.1 resolution: "@graphql-mesh/transform-filter-schema@npm:0.99.1" @@ -5614,6 +5740,29 @@ __metadata: languageName: node linkType: hard +"@graphql-mesh/utils@npm:^0.99.5": + version: 0.99.5 + resolution: "@graphql-mesh/utils@npm:0.99.5" + dependencies: + "@graphql-mesh/string-interpolation": "npm:^0.5.5" + "@graphql-tools/delegate": "npm:^10.0.16" + "@whatwg-node/disposablestack": "npm:^0.0.1" + "@whatwg-node/fetch": "npm:^0.9.13" + dset: "npm:^3.1.2" + js-yaml: "npm:^4.1.0" + lodash.get: "npm:^4.4.2" + lodash.topath: "npm:^4.5.2" + tiny-lru: "npm:^11.0.0" + peerDependencies: + "@graphql-mesh/cross-helpers": ^0.4.4 + "@graphql-mesh/types": ^0.99.5 + "@graphql-tools/utils": ^10.2.3 + graphql: "*" + tslib: ^2.4.0 + checksum: 10c0/42f2c0507c29983e6f3a02199f0a74656d1a94beb0c08db89923fdeb8fedbaf9232f2ba997cc3573724af5beffc7124e32c6664968387866306dad6e066f5475 + languageName: node + linkType: hard + "@graphql-tools/apollo-engine-loader@npm:^8.0.0": version: 8.0.1 resolution: "@graphql-tools/apollo-engine-loader@npm:8.0.1" @@ -5688,6 +5837,22 @@ __metadata: languageName: node linkType: hard +"@graphql-tools/delegate@npm:^10.0.16": + version: 10.0.16 + resolution: "@graphql-tools/delegate@npm:10.0.16" + dependencies: + "@graphql-tools/batch-execute": "npm:^9.0.4" + "@graphql-tools/executor": "npm:^1.3.0" + "@graphql-tools/schema": "npm:^10.0.4" + "@graphql-tools/utils": "npm:^10.2.3" + dataloader: "npm:^2.2.2" + tslib: "npm:^2.5.0" + peerDependencies: + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + checksum: 10c0/d0d47db1faec9dd1b55bc9d5300e7c6c33bcda6d47f890a1a5af7c8440175af91cf91e29fe9c533face2743293367609ed9d8f2ebc63532b3af5ecc39a8e9121 + languageName: node + linkType: hard + "@graphql-tools/documents@npm:^1.0.0": version: 1.0.1 resolution: "@graphql-tools/documents@npm:1.0.1" @@ -5763,6 +5928,21 @@ __metadata: languageName: node linkType: hard +"@graphql-tools/executor@npm:^1.3.0": + version: 1.3.0 + resolution: "@graphql-tools/executor@npm:1.3.0" + dependencies: + "@graphql-tools/utils": "npm:^10.2.3" + "@graphql-typed-document-node/core": "npm:3.2.0" + "@repeaterjs/repeater": "npm:^3.0.4" + tslib: "npm:^2.4.0" + value-or-promise: "npm:^1.0.12" + peerDependencies: + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + checksum: 10c0/0e4ec4bcd7ba3f4d0053ae59117fa0367ee9444839f2c0568058494abfa1b4196e53aa738c88cb68a02f30d0a73827578f7f5cb7125a874063a4f1331cd98d62 + languageName: node + linkType: hard + "@graphql-tools/federation@npm:^2.1.2": version: 2.1.2 resolution: "@graphql-tools/federation@npm:2.1.2" @@ -5820,7 +6000,7 @@ __metadata: languageName: node linkType: hard -"@graphql-tools/graphql-file-loader@npm:^8.0.0": +"@graphql-tools/graphql-file-loader@npm:8.0.1, @graphql-tools/graphql-file-loader@npm:^8.0.0": version: 8.0.1 resolution: "@graphql-tools/graphql-file-loader@npm:8.0.1" dependencies: @@ -5879,7 +6059,7 @@ __metadata: languageName: node linkType: hard -"@graphql-tools/load@npm:^8.0.0": +"@graphql-tools/load@npm:^8.0.0, @graphql-tools/load@npm:^8.0.1": version: 8.0.2 resolution: "@graphql-tools/load@npm:8.0.2" dependencies: @@ -6025,6 +6205,19 @@ __metadata: languageName: node linkType: hard +"@graphql-tools/stitching-directives@npm:^3.1.2": + version: 3.1.2 + resolution: "@graphql-tools/stitching-directives@npm:3.1.2" + dependencies: + "@graphql-tools/delegate": "npm:^10.0.4" + "@graphql-tools/utils": "npm:^10.0.13" + tslib: "npm:^2.4.0" + peerDependencies: + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + checksum: 10c0/f58f5d1631f56ca391b7046d32dd00da8b82363b4d9e3dda38a5db46dca4579a2b1a309c864d23cd29eade3ff32d753057f099180adebf8b8b1fc580039d121c + languageName: node + linkType: hard + "@graphql-tools/url-loader@npm:^8.0.0, @graphql-tools/url-loader@npm:^8.0.2": version: 8.0.2 resolution: "@graphql-tools/url-loader@npm:8.0.2" @@ -7929,6 +8122,20 @@ __metadata: languageName: node linkType: hard +"@theguild/federation-composition@npm:^0.12.0": + version: 0.12.1 + resolution: "@theguild/federation-composition@npm:0.12.1" + dependencies: + constant-case: "npm:^3.0.0" + debug: "npm:4.3.4" + json5: "npm:^2.2.0" + lodash.sortby: "npm:^4.7.0" + peerDependencies: + graphql: ^16.0.0 + checksum: 10c0/a035e6d7af2cda230028a1bf9e3414607ef2eaa320395bb02d39559c0aa7136ed37143b4601e3ff0b1efea6e26a4461f67f8c46a0d6526a9894b427cc07f4ce3 + languageName: node + linkType: hard + "@tootallnate/once@npm:2": version: 2.0.0 resolution: "@tootallnate/once@npm:2.0.0" @@ -8462,6 +8669,13 @@ __metadata: languageName: node linkType: hard +"@types/uuid@npm:^9.0.0": + version: 9.0.8 + resolution: "@types/uuid@npm:9.0.8" + checksum: 10c0/b411b93054cb1d4361919579ef3508a1f12bf15b5fdd97337d3d351bece6c921b52b6daeef89b62340fd73fd60da407878432a1af777f40648cbe53a01723489 + languageName: node + linkType: hard + "@types/ws@npm:^8.0.0": version: 8.5.11 resolution: "@types/ws@npm:8.5.11" @@ -8788,6 +9002,15 @@ __metadata: languageName: node linkType: hard +"@whatwg-node/disposablestack@npm:^0.0.1": + version: 0.0.1 + resolution: "@whatwg-node/disposablestack@npm:0.0.1" + dependencies: + tslib: "npm:^2.6.3" + checksum: 10c0/8e1ecd8695bc0ea9630a4daffbaa4b461261e2421ac2ce56f95b63a38835e3d402f3c5f9be00cbb8afdcf85f0cf46105ef1cac1931c2e7ed929660e02ccd1172 + languageName: node + linkType: hard + "@whatwg-node/events@npm:^0.0.3": version: 0.0.3 resolution: "@whatwg-node/events@npm:0.0.3" @@ -8825,6 +9048,16 @@ __metadata: languageName: node linkType: hard +"@whatwg-node/fetch@npm:^0.9.14": + version: 0.9.19 + resolution: "@whatwg-node/fetch@npm:0.9.19" + dependencies: + "@whatwg-node/node-fetch": "npm:^0.5.16" + urlpattern-polyfill: "npm:^10.0.0" + checksum: 10c0/df446e2348c1ac795f6dd241f5c4c89dc303bfcc44ab27fa85c959d40b542deb6335d19bf5ad8271a40c1d2be66987932bfe83a7fce11831a33dbd97c7d5711e + languageName: node + linkType: hard + "@whatwg-node/node-fetch@npm:^0.3.6": version: 0.3.6 resolution: "@whatwg-node/node-fetch@npm:0.3.6" @@ -8838,6 +9071,18 @@ __metadata: languageName: node linkType: hard +"@whatwg-node/node-fetch@npm:^0.5.16": + version: 0.5.20 + resolution: "@whatwg-node/node-fetch@npm:0.5.20" + dependencies: + "@kamilkisiela/fast-url-parser": "npm:^1.1.4" + busboy: "npm:^1.6.0" + fast-querystring: "npm:^1.1.1" + tslib: "npm:^2.6.3" + checksum: 10c0/ce1ac9fe52afc027530755f1d09eeddd89e5199c25fa6bd6d3917d672eb2beeb39ea05638679a0581ac4a77e2ca47fc1e88dd04878c1af6b942601a8249c524d + languageName: node + linkType: hard + "@whatwg-node/node-fetch@npm:^0.5.7": version: 0.5.11 resolution: "@whatwg-node/node-fetch@npm:0.5.11" @@ -10324,6 +10569,13 @@ __metadata: languageName: node linkType: hard +"commander@npm:^12.0.0": + version: 12.1.0 + resolution: "commander@npm:12.1.0" + checksum: 10c0/6e1996680c083b3b897bfc1cfe1c58dfbcd9842fd43e1aaf8a795fbc237f65efcc860a3ef457b318e73f29a4f4a28f6403c3d653d021d960e4632dd45bde54a9 + languageName: node + linkType: hard + "commander@npm:^2.20.0": version: 2.20.3 resolution: "commander@npm:2.20.3" @@ -10393,7 +10645,7 @@ __metadata: languageName: node linkType: hard -"constant-case@npm:^3.0.4": +"constant-case@npm:^3.0.0, constant-case@npm:^3.0.4": version: 3.0.4 resolution: "constant-case@npm:3.0.4" dependencies: @@ -10740,6 +10992,13 @@ __metadata: languageName: node linkType: hard +"dayjs@npm:1.11.12": + version: 1.11.12 + resolution: "dayjs@npm:1.11.12" + checksum: 10c0/9673d37f3f9ad8a91caaeae9b3fea9a0010c81c7f58599fb9d860bc3359b86632fbff8eb7dddc86c2acaab01c5e6860bc672952f17b58c9286140c52b077c8e4 + languageName: node + linkType: hard + "debounce@npm:^1.2.0": version: 1.2.1 resolution: "debounce@npm:1.2.1" @@ -10759,6 +11018,18 @@ __metadata: languageName: node linkType: hard +"debug@npm:4.3.4": + version: 4.3.4 + resolution: "debug@npm:4.3.4" + dependencies: + ms: "npm:2.1.2" + peerDependenciesMeta: + supports-color: + optional: true + checksum: 10c0/cedbec45298dd5c501d01b92b119cd3faebe5438c3917ff11ae1bff86a6c722930ac9c8659792824013168ba6db7c4668225d845c633fbdafbbf902a6389f736 + languageName: node + linkType: hard + "debug@npm:^3.2.7": version: 3.2.7 resolution: "debug@npm:3.2.7" @@ -11082,7 +11353,7 @@ __metadata: languageName: node linkType: hard -"dotenv@npm:16.4.5, dotenv@npm:^16.0.0, dotenv@npm:^16.0.3": +"dotenv@npm:16.4.5, dotenv@npm:^16.0.0, dotenv@npm:^16.0.3, dotenv@npm:^16.3.1": version: 16.4.5 resolution: "dotenv@npm:16.4.5" checksum: 10c0/48d92870076832af0418b13acd6e5a5a3e83bb00df690d9812e94b24aff62b88ade955ac99a05501305b8dc8f1b0ee7638b18493deb6fe93d680e5220936292f @@ -12935,7 +13206,7 @@ __metadata: languageName: node linkType: hard -"graphql-scalars@npm:^1.22.4": +"graphql-scalars@npm:^1.22.4, graphql-scalars@npm:^1.23.0": version: 1.23.0 resolution: "graphql-scalars@npm:1.23.0" dependencies: @@ -12957,6 +13228,16 @@ __metadata: languageName: node linkType: hard +"graphql-transform-federation@npm:^2.2.0": + version: 2.2.0 + resolution: "graphql-transform-federation@npm:2.2.0" + peerDependencies: + "@apollo/federation": 0 + graphql: ^14.0.0 || ^15.0.0 + checksum: 10c0/96d4a9f13530b9ee7809f0eb795bfb206634ddb8c863ac1ea2e739292c99120850a9d970c4b6ba7ecde4422591fe0479a7a77d0ca7310bfafe67be556c203901 + languageName: node + linkType: hard + "graphql-type-json@npm:0.3.2": version: 0.3.2 resolution: "graphql-type-json@npm:0.3.2" @@ -14685,6 +14966,13 @@ __metadata: languageName: node linkType: hard +"js-levenshtein@npm:^1.1.6": + version: 1.1.6 + resolution: "js-levenshtein@npm:1.1.6" + checksum: 10c0/14045735325ea1fd87f434a74b11d8a14380f090f154747e613529c7cff68b5ee607f5230fa40665d5fb6125a3791f4c223f73b9feca754f989b059f5c05864f + languageName: node + linkType: hard + "js-sha256@npm:^0.10.1": version: 0.10.1 resolution: "js-sha256@npm:0.10.1" @@ -16900,6 +17188,13 @@ __metadata: languageName: node linkType: hard +"pluralize@npm:^8.0.0": + version: 8.0.0 + resolution: "pluralize@npm:8.0.0" + checksum: 10c0/2044cfc34b2e8c88b73379ea4a36fc577db04f651c2909041b054c981cd863dd5373ebd030123ab058d194ae615d3a97cfdac653991e499d10caf592e8b3dc33 + languageName: node + linkType: hard + "pofile@npm:^1.1.4": version: 1.1.4 resolution: "pofile@npm:1.1.4" @@ -18241,7 +18536,7 @@ __metadata: languageName: node linkType: hard -"snake-case@npm:^3.0.4": +"snake-case@npm:^3.0.0, snake-case@npm:^3.0.4": version: 3.0.4 resolution: "snake-case@npm:3.0.4" dependencies: @@ -19527,6 +19822,15 @@ __metadata: languageName: node linkType: hard +"uuid@npm:^9.0.0": + version: 9.0.1 + resolution: "uuid@npm:9.0.1" + bin: + uuid: dist/bin/uuid + checksum: 10c0/1607dd32ac7fc22f2d8f77051e6a64845c9bce5cd3dd8aa0070c074ec73e666a1f63c7b4e0f4bf2bc8b9d59dc85a15e17807446d9d2b17c8485fbc2147b27f9b + languageName: node + linkType: hard + "v8-compile-cache-lib@npm:^3.0.1": version: 3.0.1 resolution: "v8-compile-cache-lib@npm:3.0.1" From 2507b6de7590da4f97668a73766cc3cf12fac2e0 Mon Sep 17 00:00:00 2001 From: Paul Hachmang Date: Fri, 2 Aug 2024 10:11:03 +0200 Subject: [PATCH 24/33] Further work --- examples/magento-graphcms/pages/index.tsx | 18 +-- .../components/GcPageMeta/GcPageHead.tsx | 8 +- packages/graphql-gc-api/components/index.ts | 1 + packages/graphql-gc-api/index.ts | 5 +- .../queries/GcPage_Redirect.graphql | 2 +- .../queries/GcPage_Rows.graphql | 1 - packages/graphql-gc-api/queries/index.ts | 4 + .../graphql-gc-api/schema/GcPage.graphqls | 2 +- .../schema/GcPageRedirect.graphqls | 2 +- packages/graphql-gc-api/utils/handleResult.ts | 44 ++++++ packages/graphql-mesh/index.ts | 2 +- .../graphql-mesh/utils/delegateToSchemaSdk.ts | 60 +++----- packages/graphql-mesh/utils/executeMesh.ts | 137 ------------------ .../graphql-mesh/utils/selectionSetByPath.ts | 89 ++++++++++++ .../utils/traverseSelectionSet.ts | 53 ------- .../hygraph-ui/graphql/HygraphPage.graphql | 5 +- packages/hygraph-ui/mesh/resolvers.ts | 43 ++---- 17 files changed, 195 insertions(+), 281 deletions(-) create mode 100644 packages/graphql-gc-api/queries/index.ts create mode 100644 packages/graphql-gc-api/utils/handleResult.ts delete mode 100644 packages/graphql-mesh/utils/executeMesh.ts create mode 100644 packages/graphql-mesh/utils/selectionSetByPath.ts delete mode 100644 packages/graphql-mesh/utils/traverseSelectionSet.ts diff --git a/examples/magento-graphcms/pages/index.tsx b/examples/magento-graphcms/pages/index.tsx index 95e20d2ea12..baf1bd83626 100644 --- a/examples/magento-graphcms/pages/index.tsx +++ b/examples/magento-graphcms/pages/index.tsx @@ -3,16 +3,17 @@ import { cacheFirst } from '@graphcommerce/graphql' import { ContentAreaHome, GcPageDocument, + GcPage, GcPageMeta, - GcPageQuery, + gcPageRedirectOrNotFound, + isGcPageFound, } from '@graphcommerce/graphql-gc-api' import { StoreConfigDocument } from '@graphcommerce/magento-store' import { GetStaticProps, LayoutHeader } from '@graphcommerce/next-ui' import { LayoutDocument, LayoutNavigation, LayoutNavigationProps } from '../components' import { graphqlSharedClient, graphqlSsrClient } from '../lib/graphql/graphqlSsrClient' -import { print, stripIgnoredCharacters } from 'graphql' -type Props = GcPageQuery +type Props = GcPage type RouteProps = { url: string } type GetPageStaticProps = GetStaticProps @@ -21,7 +22,7 @@ function CmsPage(props: Props) { return ( <> - + @@ -39,19 +40,18 @@ export const getStaticProps: GetPageStaticProps = async (context) => { const staticClient = graphqlSsrClient(context) const conf = client.query({ query: StoreConfigDocument }) - const page = client.query({ query: GcPageDocument, variables: { input: { href: 'page/home' } } }) + const gcPageQuery = client.query({ query: GcPageDocument, variables: { input: { href: '' } } }) const layout = staticClient.query({ query: LayoutDocument, fetchPolicy: cacheFirst(staticClient), }) - console.log(stripIgnoredCharacters(print(GcPageDocument))) - - if (!(await page).data.page?.head) return { notFound: true } + const page = (await gcPageQuery).data + if (!isGcPageFound(page)) return gcPageRedirectOrNotFound(page) return { props: { - ...(await page).data, + ...page, ...(await layout).data, apolloState: await conf.then(() => client.cache.extract()), }, diff --git a/packages/graphql-gc-api/components/GcPageMeta/GcPageHead.tsx b/packages/graphql-gc-api/components/GcPageMeta/GcPageHead.tsx index 03b08fbc6c9..52ce43771c5 100644 --- a/packages/graphql-gc-api/components/GcPageMeta/GcPageHead.tsx +++ b/packages/graphql-gc-api/components/GcPageMeta/GcPageHead.tsx @@ -8,12 +8,16 @@ import { GcLinkRelTagFragment, } from '../../queries/GcPage_Head.gql' -type GcPageMetaProps = GcPage_HeadFragment & { +type GcPageMetaProps = { + page: GcPage_HeadFragment children?: React.ReactNode } export function GcPageMeta(props: GcPageMetaProps) { - const { head, children } = props + const { + page: { head }, + children, + } = props const { active } = usePageContext() const router = useRouter() diff --git a/packages/graphql-gc-api/components/index.ts b/packages/graphql-gc-api/components/index.ts index 0c5ef136dff..aff072ca2e8 100644 --- a/packages/graphql-gc-api/components/index.ts +++ b/packages/graphql-gc-api/components/index.ts @@ -1 +1,2 @@ export * from './ContentArea' +export * from './GcPageMeta' diff --git a/packages/graphql-gc-api/index.ts b/packages/graphql-gc-api/index.ts index 0f94ab9e4ab..164e0918400 100644 --- a/packages/graphql-gc-api/index.ts +++ b/packages/graphql-gc-api/index.ts @@ -1,4 +1,3 @@ export * from './components' -export * from './queries/GcPage_Rows.gql' -export * from './queries/GcPage.gql' -export * from './components/GcPageMeta' +export * from './queries' +export * from './utils/handleResult' diff --git a/packages/graphql-gc-api/queries/GcPage_Redirect.graphql b/packages/graphql-gc-api/queries/GcPage_Redirect.graphql index 5874396a959..3dcfcfd5bca 100644 --- a/packages/graphql-gc-api/queries/GcPage_Redirect.graphql +++ b/packages/graphql-gc-api/queries/GcPage_Redirect.graphql @@ -1,6 +1,6 @@ fragment GcPage_Redirect on GcPage { redirect { - href + destination permanent } } diff --git a/packages/graphql-gc-api/queries/GcPage_Rows.graphql b/packages/graphql-gc-api/queries/GcPage_Rows.graphql index 4bc3b4665fa..bbecc858b66 100644 --- a/packages/graphql-gc-api/queries/GcPage_Rows.graphql +++ b/packages/graphql-gc-api/queries/GcPage_Rows.graphql @@ -1,5 +1,4 @@ fragment GcPage_Rows on GcPage { - __typename rows { __typename ... on GcRowFake { diff --git a/packages/graphql-gc-api/queries/index.ts b/packages/graphql-gc-api/queries/index.ts new file mode 100644 index 00000000000..717366335a3 --- /dev/null +++ b/packages/graphql-gc-api/queries/index.ts @@ -0,0 +1,4 @@ +export * from './GcPage.gql' +export * from './GcPage_Head.gql' +export * from './GcPage_Redirect.gql' +export * from './GcPage_Rows.gql' diff --git a/packages/graphql-gc-api/schema/GcPage.graphqls b/packages/graphql-gc-api/schema/GcPage.graphqls index 8ffd4809d06..32996ca3024 100644 --- a/packages/graphql-gc-api/schema/GcPage.graphqls +++ b/packages/graphql-gc-api/schema/GcPage.graphqls @@ -12,5 +12,5 @@ type GcPage { """ Rows of the content """ - rows: [GcRow!] + rows: [GcRow] } diff --git a/packages/graphql-gc-api/schema/GcPageRedirect.graphqls b/packages/graphql-gc-api/schema/GcPageRedirect.graphqls index e191c47430d..5210e8f5f31 100644 --- a/packages/graphql-gc-api/schema/GcPageRedirect.graphqls +++ b/packages/graphql-gc-api/schema/GcPageRedirect.graphqls @@ -7,7 +7,7 @@ type GcPageRedirect { The relative part of the canonical URL. As defined by: [pathname](https://developer.mozilla.org/en-US/docs/Web/API/URL/pathname) + [search](https://developer.mozilla.org/en-US/docs/Web/API/URL/search) """ - href: String! + destination: String! """ Defines if the redirect is permanent or temporary. diff --git a/packages/graphql-gc-api/utils/handleResult.ts b/packages/graphql-gc-api/utils/handleResult.ts new file mode 100644 index 00000000000..e92d63bc6d8 --- /dev/null +++ b/packages/graphql-gc-api/utils/handleResult.ts @@ -0,0 +1,44 @@ +import type { SimplifyDeep, SetRequired } from 'type-fest' +import type { GcPageQuery } from '../queries/GcPage.gql' +import { Redirect } from 'next' + +type FoundPage = NonNullable + +export type GcPage = { + page: Omit +} + +export type GcPageRedirect = { + page: { redirect: NonNullable } +} + +export type GcPageNotFound = { page?: null | undefined } + +export function isGcPageNotFound( + query: GcPage | GcPageRedirect | GcPageNotFound | null | undefined, +): query is GcPageNotFound { + return !query?.page +} + +export function isGcPageRedirect( + query: GcPage | GcPageRedirect | GcPageNotFound | null | undefined, +): query is GcPageRedirect { + return Boolean(query?.page && 'redirect' in query.page && query.page.redirect) +} + +export function isGcPageFound( + query: GcPage | GcPageRedirect | GcPageNotFound | null | undefined, +): query is GcPage { + return !isGcPageNotFound(query) && !isGcPageRedirect(query) +} + +export function gcPageRedirectOrNotFound( + query: GcPageQuery | null | undefined, +): { redirect: Redirect; revalidate?: number | boolean } | { notFound: true } { + if (isGcPageRedirect(query)) return { redirect: query.page.redirect } + if (isGcPageNotFound(query)) return { notFound: true } + + throw Error( + 'gcPageRedirectOrNotFound should only be called when it isGcPageFound(query) returns false', + ) +} diff --git a/packages/graphql-mesh/index.ts b/packages/graphql-mesh/index.ts index 4f6ec4777ac..afd4191c1b0 100644 --- a/packages/graphql-mesh/index.ts +++ b/packages/graphql-mesh/index.ts @@ -3,6 +3,6 @@ export * from './api/apolloLink' export * from './.mesh' // export * from './utils/executeMesh' export * from './utils/meshCache' -export * from './utils/traverseSelectionSet' +export * from './utils/selectionSetByPath' export * from './utils/applySelectionSetsFromResolvers' export * from './utils/delegateToSchemaSdk' diff --git a/packages/graphql-mesh/utils/delegateToSchemaSdk.ts b/packages/graphql-mesh/utils/delegateToSchemaSdk.ts index ec364e728fb..ad7d950e1dd 100644 --- a/packages/graphql-mesh/utils/delegateToSchemaSdk.ts +++ b/packages/graphql-mesh/utils/delegateToSchemaSdk.ts @@ -2,8 +2,9 @@ import { InContextSdkMethod } from '@graphql-mesh/types' import { delegateToSchema } from '@graphql-tools/delegate' // import { batchDelegateToSchema } from '@graphql-tools/batch-delegate' -import { GraphQLResolveInfo, OperationTypeNode } from 'graphql' +import { GraphQLResolveInfo, OperationTypeNode, responsePathAsArray, print } from 'graphql' import { MeshContext } from '../.mesh' +import { renameFromAliasToRegular, selectionSetByPath } from './selectionSetByPath' export function delegateToSchemaSdk< SourceName extends keyof MeshContext, @@ -39,41 +40,26 @@ export function delegateToSchemaSdk< operation: operationMap[sourceTypeName as string], fieldName: sourceFieldName as string, args: sourceArgs as Record, + selectionSet: selectionSetByPath( + info.operation.selectionSet, + responsePathAsArray(info.path).join('.'), + ), + validateRequest: false, + transforms: [ + { + transformResult: (result) => { + renameFromAliasToRegular( + selectionSetByPath( + info.operation.selectionSet, + responsePathAsArray(info.path).join('.'), + ), + result.data[sourceFieldName], + ) + + console.dir(result.data[sourceFieldName], { depth: 5 }) + return result + }, + }, + ], }) } - -// export function batchDelegateToSchemaSdk< -// SourceName extends keyof MeshContext, -// SourceTypeName extends keyof MeshContext[SourceName], -// SourceFieldName extends keyof MeshContext[SourceName][SourceTypeName], -// >(options: { -// context: MeshContext -// info: GraphQLResolveInfo -// sourceName: SourceName -// sourceTypeName: SourceTypeName -// sourceFieldName: SourceFieldName -// key: MeshContext[SourceName][SourceTypeName][SourceFieldName] extends InContextSdkMethod< -// unknown, -// infer A -// > -// ? A -// : unknown -// }): MeshContext[SourceName][SourceTypeName][SourceFieldName] extends InContextSdkMethod -// ? Promise -// : unknown { -// const { context, info, sourceArgs, sourceFieldName, sourceTypeName } = options - -// const operationMap: Record = { -// Query: OperationTypeNode.QUERY, -// Mutation: OperationTypeNode.MUTATION, -// Subscription: OperationTypeNode.SUBSCRIPTION, -// } - -// return batchDelegateToSchema({ -// context, -// info, -// schema: info.schema, -// operation: operationMap[sourceTypeName as string], -// fieldName: sourceFieldName as string, -// }) -// } diff --git a/packages/graphql-mesh/utils/executeMesh.ts b/packages/graphql-mesh/utils/executeMesh.ts deleted file mode 100644 index fb8eb9c03b0..00000000000 --- a/packages/graphql-mesh/utils/executeMesh.ts +++ /dev/null @@ -1,137 +0,0 @@ -import { defaultBuildResponseCacheKey } from '@envelop/response-cache' -import type { TypedDocumentNode } from '@graphcommerce/graphql' -import type { MeshContext } from '@graphcommerce/graphql-mesh' -import { InContextSdkMethod } from '@graphql-mesh/types' -import { - Kind, - OperationTypeNode, - OperationDefinitionNode, - FieldNode, - print, - ValueNode, -} from 'graphql' -import type { Path } from 'react-hook-form' -import { meshCache, MeshCacheOptions } from './meshCache' -import { selectionSetByPath } from './traverseSelectionSet' - -type OperationType = 'Query' | 'Mutation' | 'Subscription' -function getOperationType(def: OperationDefinitionNode) { - let operationType: OperationType | undefined - switch (def.operation) { - case OperationTypeNode.QUERY: - operationType = 'Query' - break - case OperationTypeNode.MUTATION: - operationType = 'Mutation' - break - case OperationTypeNode.SUBSCRIPTION: - operationType = 'Subscription' - break - } - return operationType -} - -function traverseValueNode>( - value: ValueNode, - variables: V, -): unknown { - switch (value.kind) { - case Kind.NULL: - return null - case Kind.VARIABLE: - return variables[value.name.value] - case Kind.LIST: - return value.values.map((v) => traverseValueNode(v, variables)) - case Kind.OBJECT: - return value.fields.map((f) => ({ - [f.name.value]: traverseValueNode(f.value, variables), - })) - default: - return value.value - } -} - -function collectArguments>(field: FieldNode, variables: V) { - if (!field?.arguments || field?.arguments.length === 0) return {} - const args: Record = {} - field.arguments?.forEach((argument) => { - args[argument.name.value] = traverseValueNode(argument.value, variables) - }, field.arguments) - return args -} - -function maybeExecutor(context: MeshContext, operationType: OperationType, operationName: string) { - const possibleLocations = Object.keys(context) - - let found: InContextSdkMethod | undefined - for (const location of possibleLocations) { - const ctx = context as unknown as Record< - string, - Record> - > - if (ctx[location]?.[operationType]?.[operationName]) { - found = ctx[location][operationType][operationName] - } - } - - return found -} - -async function executeMesh>( - document: TypedDocumentNode, - options: { variables: V }, - context: MeshContext, -): Promise { - const des = document.definitions.map(async (def) => { - if (def.kind !== Kind.OPERATION_DEFINITION) return null - - const executions = def.selectionSet.selections - .filter((s) => s.kind === Kind.FIELD) - .map( - async (field) => - [ - field.name.value, - await maybeExecutor( - context, - getOperationType(def), - field.name.value, - )?.({ - context, - selectionSet: selectionSetByPath(def.selectionSet, field.name.value as Path), - args: collectArguments(field, options.variables), - }), - ] as const, - ) - - return Promise.all(executions) - }) - - const flattenedEntries = (await Promise.all(des)).flat(1).filter((v) => !!v) - return Object.fromEntries(flattenedEntries) as Q -} - -export function createExecutor(context: MeshContext) { - const headers = (((context as any).headers ?? {}) as Record) ?? {} - - return async >( - document: TypedDocumentNode, - options: { variables: V } & Pick, - ) => { - const { ttl, ...rest } = options - - const cacheKey = await defaultBuildResponseCacheKey({ - documentString: print(document), - variableValues: { - // @todo make sure we automatically select the correct headers. - ...options.variables, - 'gcms-locales': headers['gcms-locales'], - 'gcms-stage': headers['gcms-stage'], - 'X-Magento-Cache-Id': headers['x-magento-cache-id'], - Store: headers.store, - }, - sessionId: null, - }) - - return meshCache(() => executeMesh(document, rest, context), { ttl, context, cacheKey }) - } -} diff --git a/packages/graphql-mesh/utils/selectionSetByPath.ts b/packages/graphql-mesh/utils/selectionSetByPath.ts new file mode 100644 index 00000000000..f9d486399c2 --- /dev/null +++ b/packages/graphql-mesh/utils/selectionSetByPath.ts @@ -0,0 +1,89 @@ +import { isObjectLike } from '@graphql-tools/utils' +import { Kind, SelectionNode, SelectionSetNode, print } from 'graphql' +import type { Path } from 'react-hook-form' + +function isNumeric(n: string) { + return !Number.isNaN(parseFloat(n)) +} + +export function selectionSetByPath( + incomingSelectionSet: SelectionSetNode, + path: Path, +) { + const pathArray = path.split(/[,[\].]+?/) + let selectionSet = incomingSelectionSet + let pathIndex = 0 + + while (pathIndex < pathArray.length) { + let currentValue = pathArray[pathIndex] + + const isNegation = currentValue.startsWith('!') + currentValue = isNegation ? currentValue.slice(1) : currentValue + + if (!isNumeric(currentValue)) { + const newSelections: SelectionNode[] = [] + + for (const selection of selectionSet.selections) { + if (selection.kind === Kind.FIELD) { + const val = selection.alias?.value ?? selection.name.value + if (!isNegation && val === currentValue) { + newSelections.push(...(selection.selectionSet?.selections ?? [])) + } + + if (isNegation && val !== currentValue) { + newSelections.push(...(selection.selectionSet?.selections ?? [])) + } + } + } + + selectionSet = { + kind: Kind.SELECTION_SET, + selections: newSelections, + } + } + + pathIndex++ + } + + return selectionSet +} + +/** + * A FieldNode can have an alias field, but we want to remap the data back to its values without the aliases. + * + * This is a recursive function. + */ +export function renameFromAliasToRegular(selectionSet: SelectionSetNode, data: any): any { + if (!data) return data + + if (Array.isArray(data)) { + data.forEach((v: object) => renameFromAliasToRegular(selectionSet, v)) + } else if (isObjectLike(data)) { + for (const selection of selectionSet.selections) { + if (selection.kind === Kind.FIELD && selection.alias?.value) { + data[selection.name.value] = data[selection.alias?.value ?? selection.name.value] + delete data[selection.alias.value] + } + } + + for (const selection of selectionSet.selections) { + if (selection.kind === Kind.INLINE_FRAGMENT) { + const typeCondition = selection.typeCondition?.name.value + if ('__typename' in data) { + // console.log('ues typename', selection) + if (data.__typename === typeCondition) { + renameFromAliasToRegular(selection.selectionSet, data) + } + } else { + // We should have a typename, else we can not properly distribute the data + } + } + + if (selection.kind === Kind.FRAGMENT_SPREAD) { + // console.log(selection) + } + } + } + + return data +} diff --git a/packages/graphql-mesh/utils/traverseSelectionSet.ts b/packages/graphql-mesh/utils/traverseSelectionSet.ts deleted file mode 100644 index eec2d8f6879..00000000000 --- a/packages/graphql-mesh/utils/traverseSelectionSet.ts +++ /dev/null @@ -1,53 +0,0 @@ -import { Kind, SelectionNode, SelectionSetNode } from 'graphql' -import type { Path } from 'react-hook-form' - -function isNumeric(n: string) { - return !Number.isNaN(parseFloat(n)) -} - -/** - * - */ -export function selectionSetByPath( - incomingSelectionSet: SelectionSetNode, - path: Path, -) { - const pathArray = path.split(/[,[\].]+?/) - let selectionSet = incomingSelectionSet - let pathIndex = 0 - - while (pathIndex < pathArray.length) { - let currentValue = pathArray[pathIndex] - - const isNegation = currentValue.startsWith('!') - currentValue = isNegation ? currentValue.slice(1) : currentValue - - if (!isNumeric(currentValue)) { - const newSelections: SelectionNode[] = [] - - for (const selection of selectionSet.selections) { - // if (selection.kind === Kind.INLINE_FRAGMENT) { - // console.log(selection) - // } - if (selection.kind === Kind.FIELD) { - if (!isNegation && selection.name.value === currentValue) { - newSelections.push(...(selection.selectionSet?.selections ?? [])) - } - - if (isNegation && selection.name.value !== currentValue) { - newSelections.push(...(selection.selectionSet?.selections ?? [])) - } - } - } - - selectionSet = { - kind: Kind.SELECTION_SET, - selections: newSelections, - } - } - - pathIndex++ - } - - return selectionSet -} diff --git a/packages/hygraph-ui/graphql/HygraphPage.graphql b/packages/hygraph-ui/graphql/HygraphPage.graphql index e68b5b89c98..e2389ad4286 100644 --- a/packages/hygraph-ui/graphql/HygraphPage.graphql +++ b/packages/hygraph-ui/graphql/HygraphPage.graphql @@ -1,4 +1,4 @@ -fragment HygraphPage on GcPage @inject(into: ["GcPage_Rows"]) { +fragment HygraphPage on GcPage @inject(into: ["GcPage_Head"]) { author date relatedPages { @@ -8,4 +8,7 @@ fragment HygraphPage on GcPage @inject(into: ["GcPage_Rows"]) { asset { ...Asset } + content { + __typename + } } diff --git a/packages/hygraph-ui/mesh/resolvers.ts b/packages/hygraph-ui/mesh/resolvers.ts index 63b40e583c9..0a9fb2d5277 100644 --- a/packages/hygraph-ui/mesh/resolvers.ts +++ b/packages/hygraph-ui/mesh/resolvers.ts @@ -1,16 +1,12 @@ /* eslint-disable import/no-extraneous-dependencies */ -import { - GcMetaTag, - MetaRobots, - type Resolvers, - delegateToSchemaSdk, -} from '@graphcommerce/graphql-mesh' +import { GcMetaTag, MetaRobots, type Resolvers } from '@graphcommerce/graphql-mesh' import { Kind } from 'graphql' const normalizeUrl = (href: string) => { const cleanedhref = href.replaceAll(/^\/|\/$/g, '') return `/${cleanedhref === 'page/home' ? '' : cleanedhref}` } + const denormalizeUrl = (href: string) => { const cleanedhref = href.replaceAll(/^\/|\/$/g, '') return cleanedhref === '' ? 'page/home' : cleanedhref @@ -19,8 +15,6 @@ const denormalizeUrl = (href: string) => { export const resolvers: Resolvers = { GcPage: { rows: { - // Rewrite the rows field to the content field. - // Strip out product and category as they will be resolved by Magento. selectionSet: (root) => ({ kind: Kind.SELECTION_SET, selections: [ @@ -39,7 +33,7 @@ export const resolvers: Resolvers = { }, ], }), - resolve: (root) => root.rows ?? root.content, + resolve: (root) => root.content, }, head: { selectionSet: `{ @@ -83,32 +77,13 @@ export const resolvers: Resolvers = { }, Query: { gcPage: { - /** - * We are using delegateToSchema, because we've encountered limitations with - * `context.hygraph.Query.pages({...})`: - * - * - The above resolver are not called as we are directly resolving the - * source/subgraph/directly and these resolvers are on the final schema / supergraph. - * - Somehwere inside the resulting types inside pages we've got a few @resolveTo directives - * defined and those are not called either. - */ - resolve: async (_, args, context, info) => { - /** - * This is a wrapper around delegateToSchema, does some inferring of the return type and the arguments. - * - * Might it be an idea to have a @delegateTo directive that can be used in the schema? - */ - const result = await delegateToSchemaSdk({ - context, + resolve: async (root, args, context, info) => + context.hygraph.Query.pages({ + root, info, - sourceName: 'hygraph', - sourceTypeName: 'Query', - sourceFieldName: 'pages', - sourceArgs: { where: { url: denormalizeUrl(args.input.href) } }, - }) - - return result?.[0] - }, + context, + args: { where: { url: denormalizeUrl(args.input.href) } }, + }).then((r) => r[0]), }, }, } From 25c7a1969e37769953b693f621ee2eb9a0856307 Mon Sep 17 00:00:00 2001 From: Paul Hachmang Date: Mon, 5 Aug 2024 12:15:44 +0200 Subject: [PATCH 25/33] Cleanup RowProduct/RowCategory resolvers --- docs/framework/config.md | 24 ---- .../GraphCMS/RowCategory/RowCategory.graphql | 1 + .../GraphCMS/RowCategory/RowCategory.tsx | 26 +++- .../GraphCMS/RowProduct/RowProduct.tsx | 59 +++++--- examples/magento-graphcms/pages/index.tsx | 2 +- .../mesh/resolveAdditionalResolvers.ts | 131 ------------------ .../plugins/hygraphGraphqlConfig.ts | 8 +- .../next-config/dist/generated/config.js | 5 - .../next-config/src/generated/config.ts | 23 --- 9 files changed, 70 insertions(+), 209 deletions(-) delete mode 100644 packages/hygraph-ui/mesh/resolveAdditionalResolvers.ts diff --git a/docs/framework/config.md b/docs/framework/config.md index 864a3d1d5d6..3d080536580 100644 --- a/docs/framework/config.md +++ b/docs/framework/config.md @@ -85,22 +85,6 @@ Below is a list of all possible configurations that can be set by GraphCommerce. ### GraphCommerceConfig -#### algoliaApplicationId: string (required) - -Configure your Algolia application ID. - -Stores > Configuration > Algolia Search > Credentials and Basic Setup > Application ID - -#### algoliaIndexNamePrefix: string (required) - -Stores > Configuration > Algolia Search > Credentials and Basic Setup > Index name prefix - -#### algoliaSearchOnlyApiKey: string (required) - -Configure your Algolia Search Only API Key. - -Stores > Configuration > Algolia Search > Credentials and Basic Setup > Search-only (public) API key - #### canonicalBaseUrl: string (required) The canonical base URL is used for SEO purposes. @@ -135,10 +119,6 @@ Values: 245, 246, 247 for Magento 2.4.5, 2.4.6, 2.4.7 respectively. All storefront configuration for the project -#### algoliaCatalogEnabled: boolean - -By default the catalog will not use algolia. Set this to true to enable Algolia for the catalog. - #### breadcrumbs: boolean = `false` Configuration for the SidebarGallery component @@ -410,10 +390,6 @@ Examples: - en-us - b2b-us -#### algoliaIndexNamePrefix: string - -Stores > Configuration > Algolia Search > Credentials and Basic Setup > Index name prefix - #### canonicalBaseUrl: string The canonical base URL is used for SEO purposes. diff --git a/examples/magento-graphcms/components/GraphCMS/RowCategory/RowCategory.graphql b/examples/magento-graphcms/components/GraphCMS/RowCategory/RowCategory.graphql index f8d9bfc3681..fc0500319b7 100644 --- a/examples/magento-graphcms/components/GraphCMS/RowCategory/RowCategory.graphql +++ b/examples/magento-graphcms/components/GraphCMS/RowCategory/RowCategory.graphql @@ -1,4 +1,5 @@ fragment RowCategory on RowCategory { + id categoryUrl rowCategoryVariant: variant category { diff --git a/examples/magento-graphcms/components/GraphCMS/RowCategory/RowCategory.tsx b/examples/magento-graphcms/components/GraphCMS/RowCategory/RowCategory.tsx index 93283c75e2a..416199acdc4 100644 --- a/examples/magento-graphcms/components/GraphCMS/RowCategory/RowCategory.tsx +++ b/examples/magento-graphcms/components/GraphCMS/RowCategory/RowCategory.tsx @@ -1,4 +1,6 @@ import { InContextMaskProvider, useInContextQuery } from '@graphcommerce/graphql' +import { Box } from '@mui/material' +import { useRouter } from 'next/router' import { GetMagentoRowCategoryDocument } from './GetMagentoRowCategory.gql' import { RowCategoryFragment } from './RowCategory.gql' import { Grid } from './variant/Grid' @@ -11,13 +13,34 @@ type VariantRenderer = Record< type RowCategoryProps = RowCategoryFragment & { renderer?: Partial -} & { sku?: string | null | undefined } +} const defaultRenderer: Partial = { Grid, Swipeable, } +function RowCategoryPreview(props: RowCategoryProps) { + const { category, categoryUrl, rowCategoryVariant, renderer } = props + const router = useRouter() + const canShow = router.isPreview || process.env.NODE_ENV !== 'production' + if (category || !canShow) return null + + return ( + ({ + p: 2, + border: `3px dashed ${theme.palette.error.light}`, + m: 2, + borderRadius: 2, + })} + > + Hygraph RowCategory ({rowCategoryVariant}) was configured with Category URL " + {categoryUrl}", However Magento didn't return any results. + + ) +} + export function RowCategory(props: RowCategoryProps) { const { renderer, rowCategoryVariant, category, ...rest } = props const mergedRenderer = { ...defaultRenderer, ...renderer } as VariantRenderer @@ -40,6 +63,7 @@ export function RowCategory(props: RowCategoryProps) { return ( + -} & { sku?: string | null | undefined } +} + +function RowProductPreview(props: RowProductFragment) { + const { variant, identity, product } = props + + const router = useRouter() + const canShow = router.isPreview || process.env.NODE_ENV !== 'production' + const isWrongVariant = variant === 'Grid' || variant === 'Swipeable' + const noProduct = !product + if (!canShow) return null + if (!(noProduct || isWrongVariant)) return null -function Migrate(props: RowProductFragment) { - const { variant, identity } = props return ( - - NOT FOUND: Please migrate `{identity}` with variant {variant} to a RowCategory component + ({ + p: 2, + m: 3, + border: `3px dashed ${theme.palette.error.light}`, + borderRadius: 2, + })} + > + {isWrongVariant && ( + <> + RowProduct with identity ‘{identity}’ and variant ‘{variant}’, should be migrated in + Hygraph to a RowCategory component. + + )} + {!isWrongVariant && noProduct && ( + <> + RowProduct ({identity}) was configured with Product URL " + {identity}", However Magento didn't return any results. + + )} ) } @@ -32,8 +59,6 @@ const defaultRenderer: Partial = { Related, Reviews, Upsells, - Grid: Migrate, - Swipeable: Migrate, } export function RowProduct(props: RowProductProps) { @@ -48,20 +73,18 @@ export function RowProduct(props: RowProductProps) { if (!variant) return null - const RenderType = - mergedRenderer?.[variant] ?? - (() => { - if (process.env.NODE_ENV !== 'production') return <>renderer for {variant} not found - return null - }) + const RenderType = mergedRenderer?.[variant] return ( - + + {RenderType && ( + + )} ) } diff --git a/examples/magento-graphcms/pages/index.tsx b/examples/magento-graphcms/pages/index.tsx index baf1bd83626..05ed425028b 100644 --- a/examples/magento-graphcms/pages/index.tsx +++ b/examples/magento-graphcms/pages/index.tsx @@ -40,7 +40,7 @@ export const getStaticProps: GetPageStaticProps = async (context) => { const staticClient = graphqlSsrClient(context) const conf = client.query({ query: StoreConfigDocument }) - const gcPageQuery = client.query({ query: GcPageDocument, variables: { input: { href: '' } } }) + const gcPageQuery = client.query({ query: GcPageDocument, variables: { input: { href: '/' } } }) const layout = staticClient.query({ query: LayoutDocument, fetchPolicy: cacheFirst(staticClient), diff --git a/packages/hygraph-ui/mesh/resolveAdditionalResolvers.ts b/packages/hygraph-ui/mesh/resolveAdditionalResolvers.ts deleted file mode 100644 index 3b370f9e291..00000000000 --- a/packages/hygraph-ui/mesh/resolveAdditionalResolvers.ts +++ /dev/null @@ -1,131 +0,0 @@ -import type { YamlConfig } from '@graphql-mesh/types' -import { parseSelectionSet } from '@graphql-tools/utils' -import type { - GraphQLNamedType, - GraphQLObjectType, - GraphQLSchema, - GraphQLType, - SelectionSetNode, -} from 'graphql' -import { getNamedType, isAbstractType, isInterfaceType, isObjectType, Kind } from 'graphql' -import toPath from 'lodash.topath' - -function getTypeByPath(type: GraphQLType, path: string[]): GraphQLNamedType { - if ('ofType' in type) { - return getTypeByPath(getNamedType(type), path) - } - if (path.length === 0) { - return getNamedType(type) - } - if (!('getFields' in type)) { - throw new Error(`${type} cannot have a path ${path.join('.')}`) - } - const fieldMap = type.getFields() - const currentFieldName = path[0] - // Might be an index of an array - if (!Number.isNaN(parseInt(currentFieldName))) { - return getTypeByPath(type, path.slice(1)) - } - const field = fieldMap[currentFieldName] - if (!field?.type) { - throw new Error(`${type}.${currentFieldName} is not a valid field.`) - } - return getTypeByPath(field.type, path.slice(1)) -} - -export function generateSelectionSetFactory( - schema: GraphQLSchema, - additionalResolver: - | YamlConfig.AdditionalStitchingBatchResolverObject - | YamlConfig.AdditionalStitchingResolverObject, -) { - if (additionalResolver.sourceSelectionSet) { - return () => parseSelectionSet(additionalResolver.sourceSelectionSet) - // If result path provided without a selectionSet - } - if (additionalResolver.result) { - const resultPath = toPath(additionalResolver.result) - let abstractResultTypeName: string - - const sourceType = schema.getType(additionalResolver.sourceTypeName) as GraphQLObjectType - const sourceTypeFields = sourceType.getFields() - const sourceField = sourceTypeFields[additionalResolver.sourceFieldName] - const resultFieldType = getTypeByPath(sourceField.type, resultPath) - - if (isAbstractType(resultFieldType)) { - if (additionalResolver.resultType) { - abstractResultTypeName = additionalResolver.resultType - } else { - const targetType = schema.getType(additionalResolver.targetTypeName) as GraphQLObjectType - const targetTypeFields = targetType.getFields() - const targetField = targetTypeFields[additionalResolver.targetFieldName] - const targetFieldType = getNamedType(targetField.type) - abstractResultTypeName = targetFieldType?.name - } - if (abstractResultTypeName !== resultFieldType.name) { - const abstractResultType = schema.getType(abstractResultTypeName) - if ( - (isInterfaceType(abstractResultType) || isObjectType(abstractResultType)) && - !schema.isSubType(resultFieldType, abstractResultType) - ) { - throw new Error( - `${additionalResolver.sourceTypeName}.${ - additionalResolver.sourceFieldName - }.${resultPath.join('.')} doesn't implement ${abstractResultTypeName}.}`, - ) - } - } - } - - return (subtree: SelectionSetNode) => { - let finalSelectionSet = subtree - let isLastResult = true - const resultPathReversed = [...resultPath].reverse() - for (const pathElem of resultPathReversed) { - // Ensure the path elem is not array index - if (Number.isNaN(parseInt(pathElem))) { - if ( - isLastResult && - abstractResultTypeName && - abstractResultTypeName !== resultFieldType.name - ) { - finalSelectionSet = { - kind: Kind.SELECTION_SET, - selections: [ - { - kind: Kind.INLINE_FRAGMENT, - typeCondition: { - kind: Kind.NAMED_TYPE, - name: { - kind: Kind.NAME, - value: abstractResultTypeName, - }, - }, - selectionSet: finalSelectionSet, - }, - ], - } - } - finalSelectionSet = { - kind: Kind.SELECTION_SET, - selections: [ - { - // we create a wrapping AST Field - kind: Kind.FIELD, - name: { - kind: Kind.NAME, - value: pathElem, - }, - // Inside the field selection - selectionSet: finalSelectionSet, - }, - ], - } - isLastResult = false - } - } - return finalSelectionSet - } - } - return undefined -} diff --git a/packages/hygraph-ui/plugins/hygraphGraphqlConfig.ts b/packages/hygraph-ui/plugins/hygraphGraphqlConfig.ts index 934297fcb44..ab0e3677e3e 100644 --- a/packages/hygraph-ui/plugins/hygraphGraphqlConfig.ts +++ b/packages/hygraph-ui/plugins/hygraphGraphqlConfig.ts @@ -17,16 +17,12 @@ export const graphqlConfig: FunctionPlugin = (prev, co const locales = config.storefront.hygraphLocales - if (!locales) return prev(config) - const hygraphLink = setContext((_, context) => { if (!context.headers) context.headers = {} - context.headers['gcms-locales'] = locales.join(',') + if (locales) context.headers['gcms-locales'] = locales.join(',') const stage = config.previewData?.hygraphStage ?? 'DRAFT' - if (config.preview) { - context.headers['gcms-stage'] = stage - } + if (config.preview) context.headers['gcms-stage'] = stage return context }) diff --git a/packagesDev/next-config/dist/generated/config.js b/packagesDev/next-config/dist/generated/config.js index d86dfafcf99..ed5e13d1490 100644 --- a/packagesDev/next-config/dist/generated/config.js +++ b/packagesDev/next-config/dist/generated/config.js @@ -75,10 +75,6 @@ function DatalayerConfigSchema() { } function GraphCommerceConfigSchema() { return _zod.z.object({ - algoliaApplicationId: _zod.z.string().min(1), - algoliaCatalogEnabled: _zod.z.boolean().nullish(), - algoliaIndexNamePrefix: _zod.z.string().min(1), - algoliaSearchOnlyApiKey: _zod.z.string().min(1), breadcrumbs: _zod.z.boolean().default(false).nullish(), canonicalBaseUrl: _zod.z.string().min(1), cartDisplayPricesInclTax: _zod.z.boolean().nullish(), @@ -130,7 +126,6 @@ function GraphCommerceDebugConfigSchema() { } function GraphCommerceStorefrontConfigSchema() { return _zod.z.object({ - algoliaIndexNamePrefix: _zod.z.string().nullish(), canonicalBaseUrl: _zod.z.string().nullish(), cartDisplayPricesInclTax: _zod.z.boolean().nullish(), customerCompanyFieldsEnable: _zod.z.boolean().nullish(), diff --git a/packagesDev/next-config/src/generated/config.ts b/packagesDev/next-config/src/generated/config.ts index 56d890ec8c6..2b35e44eebd 100644 --- a/packagesDev/next-config/src/generated/config.ts +++ b/packagesDev/next-config/src/generated/config.ts @@ -104,22 +104,6 @@ export type DatalayerConfig = { * Below is a list of all possible configurations that can be set by GraphCommerce. */ export type GraphCommerceConfig = { - /** - * Configure your Algolia application ID. - * - * Stores > Configuration > Algolia Search > Credentials and Basic Setup > Application ID - */ - algoliaApplicationId: Scalars['String']['input']; - /** By default the catalog will not use algolia. Set this to true to enable Algolia for the catalog. */ - algoliaCatalogEnabled?: InputMaybe; - /** Stores > Configuration > Algolia Search > Credentials and Basic Setup > Index name prefix */ - algoliaIndexNamePrefix: Scalars['String']['input']; - /** - * Configure your Algolia Search Only API Key. - * - * Stores > Configuration > Algolia Search > Credentials and Basic Setup > Search-only (public) API key - */ - algoliaSearchOnlyApiKey: Scalars['String']['input']; /** Configuration for the SidebarGallery component */ breadcrumbs?: InputMaybe; /** @@ -374,8 +358,6 @@ export type GraphCommerceDebugConfig = { /** All storefront configuration for the project */ export type GraphCommerceStorefrontConfig = { - /** Stores > Configuration > Algolia Search > Credentials and Basic Setup > Index name prefix */ - algoliaIndexNamePrefix?: InputMaybe; /** * The canonical base URL is used for SEO purposes. * @@ -510,10 +492,6 @@ export function DatalayerConfigSchema(): z.ZodObject export function GraphCommerceConfigSchema(): z.ZodObject> { return z.object({ - algoliaApplicationId: z.string().min(1), - algoliaCatalogEnabled: z.boolean().nullish(), - algoliaIndexNamePrefix: z.string().min(1), - algoliaSearchOnlyApiKey: z.string().min(1), breadcrumbs: z.boolean().default(false).nullish(), canonicalBaseUrl: z.string().min(1), cartDisplayPricesInclTax: z.boolean().nullish(), @@ -567,7 +545,6 @@ export function GraphCommerceDebugConfigSchema(): z.ZodObject> { return z.object({ - algoliaIndexNamePrefix: z.string().nullish(), canonicalBaseUrl: z.string().nullish(), cartDisplayPricesInclTax: z.boolean().nullish(), customerCompanyFieldsEnable: z.boolean().nullish(), From 6e45a88cf6c8b10130aa0a04e731b2db0ba2114a Mon Sep 17 00:00:00 2001 From: Paul Hachmang Date: Tue, 6 Aug 2024 16:38:22 +0200 Subject: [PATCH 26/33] Resolver for gcPage on the products query --- .../graphql/ProductPage2.graphql | 5 + examples/magento-graphcms/pages/index.tsx | 4 +- examples/magento-graphcms/pages/p/[url].tsx | 14 +- .../components/ContentArea/ContentArea.tsx | 13 +- .../schema/CategoryInterface_gcPage.graphqls | 7 + .../schema/ProductInterface_gcPage.graphqls | 31 ++++ packages/graphql-mesh/index.ts | 2 +- packages/graphql-mesh/utils/executeMesh.ts | 159 ++++++++++++++++++ .../graphql/DynamicRows.graphql | 1 + .../hygraph-dynamic-rows/mesh/resolvers.ts | 71 +++++--- packages/hygraph-ui/mesh/resolvers.ts | 136 ++++++++++++++- .../hygraph-ui/schema/Query_gcPage.graphqls | 23 --- .../schema/RowCategory_category.graphqls | 3 + .../schema/RowProduct_product.graphqls | 3 + 14 files changed, 405 insertions(+), 67 deletions(-) create mode 100644 packages/graphql-gc-api/schema/CategoryInterface_gcPage.graphqls create mode 100644 packages/graphql-gc-api/schema/ProductInterface_gcPage.graphqls create mode 100644 packages/graphql-mesh/utils/executeMesh.ts delete mode 100644 packages/hygraph-ui/schema/Query_gcPage.graphqls create mode 100644 packages/hygraph-ui/schema/RowCategory_category.graphqls create mode 100644 packages/hygraph-ui/schema/RowProduct_product.graphqls diff --git a/examples/magento-graphcms/graphql/ProductPage2.graphql b/examples/magento-graphcms/graphql/ProductPage2.graphql index de6937e2564..8961ef8774e 100644 --- a/examples/magento-graphcms/graphql/ProductPage2.graphql +++ b/examples/magento-graphcms/graphql/ProductPage2.graphql @@ -16,6 +16,11 @@ query ProductPage2( ...DownloadableProductOptions ...BundleProductOptions ...GroupedProduct + page: gcPage { + ...GcPage_Head + ...GcPage_Redirect + ...GcPage_Rows + } } } # Workaround for https://github.com/magento/magento2/issues/32427 diff --git a/examples/magento-graphcms/pages/index.tsx b/examples/magento-graphcms/pages/index.tsx index 05ed425028b..c746da3d2fa 100644 --- a/examples/magento-graphcms/pages/index.tsx +++ b/examples/magento-graphcms/pages/index.tsx @@ -40,13 +40,13 @@ export const getStaticProps: GetPageStaticProps = async (context) => { const staticClient = graphqlSsrClient(context) const conf = client.query({ query: StoreConfigDocument }) - const gcPageQuery = client.query({ query: GcPageDocument, variables: { input: { href: '/' } } }) + const gcPage = client.query({ query: GcPageDocument, variables: { input: { href: '/' } } }) const layout = staticClient.query({ query: LayoutDocument, fetchPolicy: cacheFirst(staticClient), }) - const page = (await gcPageQuery).data + const page = (await gcPage).data if (!isGcPageFound(page)) return gcPageRedirectOrNotFound(page) return { diff --git a/examples/magento-graphcms/pages/p/[url].tsx b/examples/magento-graphcms/pages/p/[url].tsx index 23314cb826a..81c06a80a1d 100644 --- a/examples/magento-graphcms/pages/p/[url].tsx +++ b/examples/magento-graphcms/pages/p/[url].tsx @@ -1,10 +1,3 @@ -import { - ContentAreaProductPage, - ContentAreaProductPageBefore, - ContentAreaProductPageSidebar, - PageContent, - pageContent, -} from '@graphcommerce/graphql-gc-api' import { PageOptions } from '@graphcommerce/framer-next-pages' import { cacheFirst, @@ -12,6 +5,13 @@ import { mergeDeep, useInContextQuery, } from '@graphcommerce/graphql' +import { + ContentAreaProductPage, + ContentAreaProductPageBefore, + ContentAreaProductPageSidebar, + PageContent, + pageContent, +} from '@graphcommerce/graphql-gc-api' import { AddProductsToCartForm, AddProductsToCartFormProps, diff --git a/packages/graphql-gc-api/components/ContentArea/ContentArea.tsx b/packages/graphql-gc-api/components/ContentArea/ContentArea.tsx index 005fd3374f8..5596c9e3641 100644 --- a/packages/graphql-gc-api/components/ContentArea/ContentArea.tsx +++ b/packages/graphql-gc-api/components/ContentArea/ContentArea.tsx @@ -1,9 +1,16 @@ -import { LazyHydrate, RenderType, type TypeRenderer } from '@graphcommerce/next-ui' +import { + filterNonNullableKeys, + LazyHydrate, + RenderType, + type TypeRenderer, +} from '@graphcommerce/next-ui' import React from 'react' import { GcPageQuery } from '../../queries/GcPage.gql' import { GcPage_RowsFragment } from '../../queries/GcPage_Rows.gql' -export type GcRowTypeRenderer = TypeRenderer[number]> +export type GcRowTypeRenderer = TypeRenderer< + NonNullable>[number]> +> export type ContentAreaProps = GcPageQuery & { renderer?: Partial @@ -19,7 +26,7 @@ export const ContentArea = React.memo((props) => { return ( <> - {rows?.map((item, index) => ( + {filterNonNullableKeys(rows)?.map((item, index) => ( diff --git a/packages/graphql-gc-api/schema/CategoryInterface_gcPage.graphqls b/packages/graphql-gc-api/schema/CategoryInterface_gcPage.graphqls new file mode 100644 index 00000000000..7aa74f8cc39 --- /dev/null +++ b/packages/graphql-gc-api/schema/CategoryInterface_gcPage.graphqls @@ -0,0 +1,7 @@ +interface CategoryInterface { + gcPage: GcPage +} + +type CategoryTree { + gcPage: GcPage +} diff --git a/packages/graphql-gc-api/schema/ProductInterface_gcPage.graphqls b/packages/graphql-gc-api/schema/ProductInterface_gcPage.graphqls new file mode 100644 index 00000000000..61b73c06823 --- /dev/null +++ b/packages/graphql-gc-api/schema/ProductInterface_gcPage.graphqls @@ -0,0 +1,31 @@ +interface ProductInterface { + gcPage: GcPage +} + +type BundleProduct { + gcPage: GcPage +} + +type SimpleProduct { + gcPage: GcPage +} + +type VirtualProduct { + gcPage: GcPage +} + +type DownloadableProduct { + gcPage: GcPage +} + +type GiftCardProduct { + gcPage: GcPage +} + +type ConfigurableProduct { + gcPage: GcPage +} + +type GroupedProduct { + gcPage: GcPage +} diff --git a/packages/graphql-mesh/index.ts b/packages/graphql-mesh/index.ts index afd4191c1b0..5ed457e2597 100644 --- a/packages/graphql-mesh/index.ts +++ b/packages/graphql-mesh/index.ts @@ -1,7 +1,7 @@ export * from './api/createEnvelop' export * from './api/apolloLink' export * from './.mesh' -// export * from './utils/executeMesh' +export * from './utils/executeMesh' export * from './utils/meshCache' export * from './utils/selectionSetByPath' export * from './utils/applySelectionSetsFromResolvers' diff --git a/packages/graphql-mesh/utils/executeMesh.ts b/packages/graphql-mesh/utils/executeMesh.ts new file mode 100644 index 00000000000..daa48fc4ba2 --- /dev/null +++ b/packages/graphql-mesh/utils/executeMesh.ts @@ -0,0 +1,159 @@ +import { defaultBuildResponseCacheKey } from '@envelop/response-cache' +import type { TypedDocumentNode } from '@graphcommerce/graphql' +import type { MeshContext } from '@graphcommerce/graphql-mesh' +import { InContextSdkMethod, InContextSdkMethodRegularParams } from '@graphql-mesh/types' +import { + Kind, + OperationTypeNode, + OperationDefinitionNode, + FieldNode, + print, + ValueNode, + GraphQLResolveInfo, +} from 'graphql' +import type { Path } from 'react-hook-form' +import { meshCache, MeshCacheOptions } from './meshCache' +import { selectionSetByPath } from './selectionSetByPath' + +type OperationType = 'Query' | 'Mutation' | 'Subscription' +function getOperationType(def: OperationDefinitionNode) { + let operationType: OperationType | undefined + switch (def.operation) { + case OperationTypeNode.QUERY: + operationType = 'Query' + break + case OperationTypeNode.MUTATION: + operationType = 'Mutation' + break + case OperationTypeNode.SUBSCRIPTION: + operationType = 'Subscription' + break + } + return operationType +} + +function traverseValueNode>( + value: ValueNode, + variables: V, +): unknown { + switch (value.kind) { + case Kind.NULL: + return null + case Kind.VARIABLE: + return variables[value.name.value] + case Kind.LIST: + return value.values.map((v) => traverseValueNode(v, variables)) + case Kind.OBJECT: + return value.fields.map((f) => ({ + [f.name.value]: traverseValueNode(f.value, variables), + })) + default: + return value.value + } +} + +function collectArguments>(field: FieldNode, variables: V) { + if (!field?.arguments || field?.arguments.length === 0) return {} + const args: Record = {} + field.arguments?.forEach((argument) => { + args[argument.name.value] = traverseValueNode(argument.value, variables) + }, field.arguments) + return args +} + +function maybeExecutor( + context: MeshContext, + operationType: OperationType, + operationName: string, +): InContextSdkMethod | undefined { + const possibleLocations = Object.keys(context) + + let found: InContextSdkMethod | undefined + for (const location of possibleLocations) { + const ctx = context as unknown as Record< + string, + Record> + > + if (ctx[location]?.[operationType]?.[operationName]) { + found = ctx[location][operationType][operationName] + } + } + + if (!found) return undefined + + return (params) => { + console.warn( + '@todo executeMesh does not properly apply args', + (params as InContextSdkMethodRegularParams).args, + ) + return found(params) + } +} + +async function executeMesh>( + document: TypedDocumentNode, + options: { variables: V }, + context: MeshContext, + root: object, + info: GraphQLResolveInfo, +): Promise { + const des = document.definitions.map(async (def) => { + if (def.kind !== Kind.OPERATION_DEFINITION) return null + + const executions = def.selectionSet.selections + .filter((s) => s.kind === Kind.FIELD) + .map( + async (field) => + [ + field.name.value, + await maybeExecutor( + context, + getOperationType(def), + field.name.value, + )?.({ + root, + info, + context, + selectionSet: selectionSetByPath(def.selectionSet, field.name.value as Path), + args: collectArguments(field, options.variables), + }), + ] as const, + ) + + return Promise.all(executions) + }) + + const flattenedEntries = (await Promise.all(des)).flat(1).filter((v) => !!v) + return Object.fromEntries(flattenedEntries) as Q +} + +export function createDocumentExecutor( + context: MeshContext, + root: object, + info: GraphQLResolveInfo, +) { + const headers = (((context as any).headers ?? {}) as Record) ?? {} + + return async >( + document: TypedDocumentNode, + options: { variables: V; headers: string[] } & Pick, + ) => { + const { ttl, ...rest } = options + + const cacheKey = await defaultBuildResponseCacheKey({ + documentString: print(document), + variableValues: { + // @todo make sure we automatically select the correct headers. + ...options.variables, + ...Object.fromEntries(options.headers.map((h) => [h, headers[h]])), + }, + sessionId: headers?.authorization ? String(headers?.authorization) : null, + }) + + return meshCache(() => executeMesh(document, rest, context, root, info), { + ttl, + context, + cacheKey, + }) + } +} diff --git a/packages/hygraph-dynamic-rows/graphql/DynamicRows.graphql b/packages/hygraph-dynamic-rows/graphql/DynamicRows.graphql index fd457770d6e..cf8d7512b88 100644 --- a/packages/hygraph-dynamic-rows/graphql/DynamicRows.graphql +++ b/packages/hygraph-dynamic-rows/graphql/DynamicRows.graphql @@ -1,5 +1,6 @@ query DynamicRows($rowIds: [ID!]!) { dynamicRows(where: { id_in: $rowIds }) { + id ...DynamicRow } } diff --git a/packages/hygraph-dynamic-rows/mesh/resolvers.ts b/packages/hygraph-dynamic-rows/mesh/resolvers.ts index b7514ac08e1..5a89931ac5a 100644 --- a/packages/hygraph-dynamic-rows/mesh/resolvers.ts +++ b/packages/hygraph-dynamic-rows/mesh/resolvers.ts @@ -1,4 +1,11 @@ -import { createExecutor, type MeshContext, type Resolvers } from '@graphcommerce/graphql-mesh' +/* eslint-disable @typescript-eslint/require-await */ +import { getProduct } from '@graphcommerce/graphcms-ui/mesh/resolvers' +import { + createDocumentExecutor, + type MeshContext, + type Resolvers, +} from '@graphcommerce/graphql-mesh' +import type { GraphQLResolveInfo } from 'graphql' import { AllDynamicRowsDocument, AllDynamicRowsQuery } from '../graphql/AllDynamicRows.gql' import { DynamicRowsDocument } from '../graphql/DynamicRows.gql' import { applyDynamicRows, matchCondition } from '../lib/hygraphDynamicRows' @@ -6,12 +13,18 @@ import { applyDynamicRows, matchCondition } from '../lib/hygraphDynamicRows' async function getAllHygraphDynamicRows( context: MeshContext, options: { pageSize?: number; ttl: number }, + parent: object, + info: GraphQLResolveInfo, ) { const { pageSize = 100, ttl } = options - const execute = createExecutor(context) + const execute = createDocumentExecutor(context, parent, info) - const query = execute(AllDynamicRowsDocument, { variables: { first: 100, skip: 0 }, ttl }) + const query = execute(AllDynamicRowsDocument, { + variables: { first: 100, skip: 0 }, + ttl, + headers: ['gcms-stage', 'gcms-locale'], + }) const pages: Promise[] = [query] const data = await query @@ -22,6 +35,7 @@ async function getAllHygraphDynamicRows( execute(AllDynamicRowsDocument, { variables: { first: pageSize, skip: pageSize * (i - 1) }, ttl, + headers: ['gcms-stage', 'gcms-locale'], }), ) } @@ -34,27 +48,36 @@ async function getAllHygraphDynamicRows( } export const resolvers: Resolvers = { - Page: { - content: async (parent, args, context, info) => { - const execute = createExecutor(context) - const allRoutes = await getAllHygraphDynamicRows(context, { ttl: 60 * 60 }) - - const rowIds = allRoutes - .filter((availableDynamicRow) => - availableDynamicRow.conditions.some((condition) => - matchCondition(condition, { ...parent, ...args }), - ), - ) - .map((row) => row.id) - - const dynamicRows = - rowIds.length !== 0 - ? await execute(DynamicRowsDocument, { variables: { rowIds }, ttl: 60 * 60 }) - : undefined - - if (!dynamicRows?.dynamicRows) return parent.content - - return applyDynamicRows(dynamicRows.dynamicRows, parent.content) + GcPage: { + rows: { + resolve: async (parent, args, context, info) => { + const execute = createDocumentExecutor(context, parent, info) + const allRoutes = await getAllHygraphDynamicRows(context, { ttl: 60 * 60 }, parent, info) + + const rowIds = allRoutes + .filter((availableDynamicRow) => + availableDynamicRow.conditions.some((condition) => + matchCondition(condition, { + ...parent, + // ...args, + ...getProduct(context, parent.url.slice(2)), + }), + ), + ) + .map((row) => row.id) + + if (rowIds.length === 0) return parent.content + const dynamicRows = await execute(DynamicRowsDocument, { + variables: { rowIds }, + ttl: 60 * 60, + headers: ['gcms-stage', 'gcms-locale'], + }) + + const rows = dynamicRows.dynamicRows.filter((row) => rowIds.includes(row.id)) + + if (rows.length === 0) return parent.content + return applyDynamicRows(rows, parent.content) + }, }, }, } diff --git a/packages/hygraph-ui/mesh/resolvers.ts b/packages/hygraph-ui/mesh/resolvers.ts index 0a9fb2d5277..dec7ca0050e 100644 --- a/packages/hygraph-ui/mesh/resolvers.ts +++ b/packages/hygraph-ui/mesh/resolvers.ts @@ -1,5 +1,14 @@ /* eslint-disable import/no-extraneous-dependencies */ -import { GcMetaTag, MetaRobots, type Resolvers } from '@graphcommerce/graphql-mesh' +import { + GcMetaTag, + MeshContext, + MetaRobots, + PageContent, + ProductInterface, + ResolversTypes, + RowProduct, + type Resolvers, +} from '@graphcommerce/graphql-mesh' import { Kind } from 'graphql' const normalizeUrl = (href: string) => { @@ -12,7 +21,78 @@ const denormalizeUrl = (href: string) => { return cleanedhref === '' ? 'page/home' : cleanedhref } +type GCPageResolver = NonNullable['gcPage'] + +export const contextData = new WeakMap>() + +function initContextData(context: MeshContext) { + let value = contextData.get(context) + if (!value) { + value = {} + contextData.set(context, value) + } + return value +} + +export function setProduct(context: MeshContext, key: string, entity: ProductInterface) { + const value = initContextData(context) + value[key] = entity +} +export function getProduct(context: MeshContext, key: string): ProductInterface | undefined { + const value = initContextData(context) + return value[key] +} + +function isRowProduct(row: PageContent): row is RowProduct { + return '__typename' in row && row.__typename === 'RowProduct' +} + +const gcPageProductResolver: GCPageResolver = { + selectionSet: `{url_key}`, + resolve: async (root, args, context, info) => { + setProduct(context, root.url_key!, root) + const page = ( + await context.hygraph.Query.pages({ + context, + info, + root, + key: root.url_key, + argsFromKeys: (keys) => ({ + where: { url_in: ['product/global', ...keys.map((key) => `p/${key}`)] }, + }), + valuesFromResults: (results, keys) => + keys.map((key) => [ + results.find((r) => r.url === `p/${key}`) ?? + results.find((r) => r.url === 'product/global') ?? + null, + ]), + }) + )?.[0] + + // Since the RowProduct is a child of the current product, we replace the identity with the current product's URL key. + if (page?.content) + page.content = page.content.map((row) => + isRowProduct(row) ? { ...row, identity: root.url_key ?? row.identity } : row, + ) + + return page + }, +} + export const resolvers: Resolvers = { + // Resolve the query `gcPage` to a page with the given URL + Query: { + gcPage: { + resolve: async (root, args, context, info) => + context.hygraph.Query.pages({ + root, + info, + context, + args: { where: { url: denormalizeUrl(args.input.href) } }, + }).then((r) => r[0]), + }, + }, + GcPage: { rows: { selectionSet: (root) => ({ @@ -75,15 +155,57 @@ export const resolvers: Resolvers = { }, }, }, - Query: { - gcPage: { - resolve: async (root, args, context, info) => - context.hygraph.Query.pages({ + + SimpleProduct: { gcPage: gcPageProductResolver }, + ConfigurableProduct: { gcPage: gcPageProductResolver }, + BundleProduct: { gcPage: gcPageProductResolver }, + VirtualProduct: { gcPage: gcPageProductResolver }, + DownloadableProduct: { gcPage: gcPageProductResolver }, + GroupedProduct: { gcPage: gcPageProductResolver }, + + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore GiftCardProduct is only available in Commerce + GiftCardProduct: { gcPage: gcPageProductResolver }, + + RowProduct: { + product: { + selectionSet: `{ identity }`, + resolve: async (root, args, context, info) => { + const storedProduct = getProduct(context, root.identity) + if (storedProduct) return storedProduct as ResolversTypes['ProductInterface'] + + const result = await context.m2.Query.products({ root, info, context, - args: { where: { url: denormalizeUrl(args.input.href) } }, - }).then((r) => r[0]), + key: root.identity, + argsFromKeys: (keys) => ({ + filter: { url_key: { in: keys } }, + }), + valuesFromResults: (results, keys) => + keys.map((key) => results?.items?.find((r) => r?.url_key === key) ?? null), + }) + + const product = (result ?? null) as ResolversTypes['ProductInterface'] + + return product + }, + }, + }, + + RowCategory: { + category: { + selectionSet: `{ categoryUrl }`, + resolve: async (root, args, context, info) => { + const result = await context.m2.Query.categories({ + root, + info, + context, + args: { filters: { url_path: { eq: root.categoryUrl } }, pageSize: 1 }, + }) + const category = result?.items?.[0] ?? null + return category as ResolversTypes['CategoryTree'] + }, }, }, } diff --git a/packages/hygraph-ui/schema/Query_gcPage.graphqls b/packages/hygraph-ui/schema/Query_gcPage.graphqls deleted file mode 100644 index a4ad8f69577..00000000000 --- a/packages/hygraph-ui/schema/Query_gcPage.graphqls +++ /dev/null @@ -1,23 +0,0 @@ -type RowCategory { - category: CategoryTree - @resolveTo( - sourceName: "m2" - sourceTypeName: "Query" - sourceFieldName: "categories" - requiredSelectionSet: "{ categoryUrl }" - sourceArgs: { filters: { url_path: { eq: "{root.categoryUrl}" } } } - result: "items[0]" - ) -} - -type RowProduct { - product: ProductInterface - @resolveTo( - sourceName: "m2" - sourceTypeName: "Query" - sourceFieldName: "products" - requiredSelectionSet: "{ identity }" - sourceArgs: { filter: { url_key: { eq: "{root.identity}" } }, pageSize: 1 } - result: "items[0]" - ) -} diff --git a/packages/hygraph-ui/schema/RowCategory_category.graphqls b/packages/hygraph-ui/schema/RowCategory_category.graphqls new file mode 100644 index 00000000000..0b356ad39f5 --- /dev/null +++ b/packages/hygraph-ui/schema/RowCategory_category.graphqls @@ -0,0 +1,3 @@ +type RowCategory { + category: CategoryTree +} diff --git a/packages/hygraph-ui/schema/RowProduct_product.graphqls b/packages/hygraph-ui/schema/RowProduct_product.graphqls new file mode 100644 index 00000000000..e71a44433fb --- /dev/null +++ b/packages/hygraph-ui/schema/RowProduct_product.graphqls @@ -0,0 +1,3 @@ +type RowProduct { + product: ProductInterface +} From 0e00efa5cb73bb1f9050e613dce544f5118734b3 Mon Sep 17 00:00:00 2001 From: Paul Hachmang Date: Wed, 7 Aug 2024 12:10:15 +0200 Subject: [PATCH 27/33] Creating a RowProductPage --- .../{ => Footer}/FooterQueryFragment.graphql | 2 +- .../{_config => }/GcPage_Rows_Hygraph.graphql | 0 .../GraphCMS/{_config => }/GcRow.graphqls | 0 .../GraphCMS/RowProduct/variant/Related.tsx | 2 +- .../GraphCMS/RowProduct/variant/Reviews.tsx | 2 +- .../GraphCMS/RowProduct/variant/Specs.tsx | 2 +- .../GraphCMS/RowProduct/variant/Upsells.tsx | 2 +- .../GetMagentoRowProductPage.graphql | 14 +++ .../RowProductPage/RowProductPage.graphql | 19 ++++ .../RowProductPage/RowProductPage.tsx | 87 +++++++++++++++++++ .../RowProductPage/variant/Related.tsx | 37 ++++++++ .../RowProductPage/variant/Reviews.tsx | 52 +++++++++++ .../GraphCMS/RowProductPage/variant/Specs.tsx | 13 +++ .../RowProductPage/variant/Upsells.tsx | 37 ++++++++ .../GraphCMS/RowProductPage/variant/index.tsx | 4 + .../GraphCMS/_config/gcRowHygraphRenderer.ts | 30 ------- .../components/Layout/Layout.graphql | 5 +- .../components/Layout/LayoutFragment.graphql | 6 ++ .../graphql/ProductPage2.graphql | 1 - .../lib/graphql/graphqlSsrClient.ts | 2 +- examples/magento-graphcms/pages/[...url].tsx | 8 +- examples/magento-graphcms/pages/p/[url].tsx | 57 ++++++------ .../plugins/hygraph/HygraphContentArea.tsx | 13 --- .../plugins/hygraph/HygraphGcPageRows.tsx | 41 +++++++++ .../components/ContentArea/Areas.tsx | 14 +-- .../{ContentArea.tsx => GcPageRows.tsx} | 16 ++-- .../components/ContentArea/index.ts | 2 +- packages/graphql-gc-api/package.json | 2 +- .../schema/Query_gcLayout.graphqls | 11 +++ .../lib/getAllHygraphDynamicRows.ts | 44 ---------- .../lib/hygraphDynamicRows.ts | 65 -------------- packages/hygraph-ui/mesh/resolvers.ts | 5 +- .../ProductPageMeta/ProductPageMeta.tsx | 4 +- yarn.lock | 24 +---- 34 files changed, 382 insertions(+), 241 deletions(-) rename examples/magento-graphcms/components/GraphCMS/{ => Footer}/FooterQueryFragment.graphql (67%) rename examples/magento-graphcms/components/GraphCMS/{_config => }/GcPage_Rows_Hygraph.graphql (100%) rename examples/magento-graphcms/components/GraphCMS/{_config => }/GcRow.graphqls (100%) create mode 100644 examples/magento-graphcms/components/GraphCMS/RowProductPage/GetMagentoRowProductPage.graphql create mode 100644 examples/magento-graphcms/components/GraphCMS/RowProductPage/RowProductPage.graphql create mode 100644 examples/magento-graphcms/components/GraphCMS/RowProductPage/RowProductPage.tsx create mode 100644 examples/magento-graphcms/components/GraphCMS/RowProductPage/variant/Related.tsx create mode 100644 examples/magento-graphcms/components/GraphCMS/RowProductPage/variant/Reviews.tsx create mode 100644 examples/magento-graphcms/components/GraphCMS/RowProductPage/variant/Specs.tsx create mode 100644 examples/magento-graphcms/components/GraphCMS/RowProductPage/variant/Upsells.tsx create mode 100644 examples/magento-graphcms/components/GraphCMS/RowProductPage/variant/index.tsx delete mode 100644 examples/magento-graphcms/components/GraphCMS/_config/gcRowHygraphRenderer.ts create mode 100644 examples/magento-graphcms/components/Layout/LayoutFragment.graphql delete mode 100644 examples/magento-graphcms/plugins/hygraph/HygraphContentArea.tsx create mode 100644 examples/magento-graphcms/plugins/hygraph/HygraphGcPageRows.tsx rename packages/graphql-gc-api/components/ContentArea/{ContentArea.tsx => GcPageRows.tsx} (57%) create mode 100644 packages/graphql-gc-api/schema/Query_gcLayout.graphqls delete mode 100644 packages/hygraph-dynamic-rows/lib/getAllHygraphDynamicRows.ts diff --git a/examples/magento-graphcms/components/GraphCMS/FooterQueryFragment.graphql b/examples/magento-graphcms/components/GraphCMS/Footer/FooterQueryFragment.graphql similarity index 67% rename from examples/magento-graphcms/components/GraphCMS/FooterQueryFragment.graphql rename to examples/magento-graphcms/components/GraphCMS/Footer/FooterQueryFragment.graphql index b4041bd54ae..c22a477a9fb 100644 --- a/examples/magento-graphcms/components/GraphCMS/FooterQueryFragment.graphql +++ b/examples/magento-graphcms/components/GraphCMS/Footer/FooterQueryFragment.graphql @@ -1,4 +1,4 @@ -fragment FooterQueryFragment on Query { +fragment FooterQueryFragment on Query @inject(into: ["LayoutFragment"]) { footer(where: { identity: "footer" }) { id socialLinks { diff --git a/examples/magento-graphcms/components/GraphCMS/_config/GcPage_Rows_Hygraph.graphql b/examples/magento-graphcms/components/GraphCMS/GcPage_Rows_Hygraph.graphql similarity index 100% rename from examples/magento-graphcms/components/GraphCMS/_config/GcPage_Rows_Hygraph.graphql rename to examples/magento-graphcms/components/GraphCMS/GcPage_Rows_Hygraph.graphql diff --git a/examples/magento-graphcms/components/GraphCMS/_config/GcRow.graphqls b/examples/magento-graphcms/components/GraphCMS/GcRow.graphqls similarity index 100% rename from examples/magento-graphcms/components/GraphCMS/_config/GcRow.graphqls rename to examples/magento-graphcms/components/GraphCMS/GcRow.graphqls diff --git a/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Related.tsx b/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Related.tsx index 0b08cd8f7bf..08043235e83 100644 --- a/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Related.tsx +++ b/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Related.tsx @@ -9,7 +9,7 @@ import { Typography } from '@mui/material' import { productListRenderer } from '../../../ProductListItems' import { RowProductFragment } from '../RowProduct.gql' -type RelatedProps = RowProductFragment & RelatedProductsFragment & Pick +type RelatedProps = RowProductFragment & Pick export function Related(props: RelatedProps) { const { title, related_products, sx } = props diff --git a/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Reviews.tsx b/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Reviews.tsx index ccc56e3d012..c8a91e79aa7 100644 --- a/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Reviews.tsx +++ b/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Reviews.tsx @@ -5,7 +5,7 @@ import { Row } from '@graphcommerce/next-ui' import { Box, Typography } from '@mui/material' import { RowProductFragment } from '../RowProduct.gql' -type ReviewsProps = RowProductFragment & Partial +type ReviewsProps = RowProductFragment export function Reviews(props: ReviewsProps) { const { title, reviews, url_key, review_count, sku } = props diff --git a/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Specs.tsx b/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Specs.tsx index dce125cd2b5..33f6b038f06 100644 --- a/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Specs.tsx +++ b/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Specs.tsx @@ -2,7 +2,7 @@ import { ProductSpecs } from '@graphcommerce/magento-product' import { ProductSpecsFragment } from '@graphcommerce/magento-product/components/ProductSpecs/ProductSpecs.gql' import { RowProductFragment } from '../RowProduct.gql' -type SpecsProps = RowProductFragment & ProductSpecsFragment +type SpecsProps = RowProductFragment export function Specs(props: SpecsProps) { const { title, aggregations } = props diff --git a/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Upsells.tsx b/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Upsells.tsx index ab1a496cbed..bc07b3b3c52 100644 --- a/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Upsells.tsx +++ b/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Upsells.tsx @@ -9,7 +9,7 @@ import { Typography } from '@mui/material' import { productListRenderer } from '../../../ProductListItems/productListRenderer' import { RowProductFragment } from '../RowProduct.gql' -type UpsellsProps = RowProductFragment & UpsellProductsFragment & Pick +type UpsellsProps = RowProductFragment & Pick export function Upsells(props: UpsellsProps) { const { title, upsell_products, sx } = props diff --git a/examples/magento-graphcms/components/GraphCMS/RowProductPage/GetMagentoRowProductPage.graphql b/examples/magento-graphcms/components/GraphCMS/RowProductPage/GetMagentoRowProductPage.graphql new file mode 100644 index 00000000000..471d7238748 --- /dev/null +++ b/examples/magento-graphcms/components/GraphCMS/RowProductPage/GetMagentoRowProductPage.graphql @@ -0,0 +1,14 @@ +query GetMagentoRowProductPage( + $urlKey: String! + $reviewPageSize: Int = 3 + $reviewPage: Int = 1 + $context: InContextInput +) { + products(filter: { url_key: { eq: $urlKey } }, pageSize: 1) @inContext(context: $context) { + items { + ...UpsellProducts + ...RelatedProducts + ...ProductReviews + } + } +} diff --git a/examples/magento-graphcms/components/GraphCMS/RowProductPage/RowProductPage.graphql b/examples/magento-graphcms/components/GraphCMS/RowProductPage/RowProductPage.graphql new file mode 100644 index 00000000000..6eb33686472 --- /dev/null +++ b/examples/magento-graphcms/components/GraphCMS/RowProductPage/RowProductPage.graphql @@ -0,0 +1,19 @@ +fragment RowProductPage on RowProduct { + variant + identity + asset { + ...Asset + } + title + productCopy { + raw + } + pageLinks { + ...PageLink + } + product { + ...UpsellProducts + ...RelatedProducts + ...ProductReviews + } +} diff --git a/examples/magento-graphcms/components/GraphCMS/RowProductPage/RowProductPage.tsx b/examples/magento-graphcms/components/GraphCMS/RowProductPage/RowProductPage.tsx new file mode 100644 index 00000000000..da345073a16 --- /dev/null +++ b/examples/magento-graphcms/components/GraphCMS/RowProductPage/RowProductPage.tsx @@ -0,0 +1,87 @@ +import { InContextMaskProvider, useInContextQuery } from '@graphcommerce/graphql' +import { ProductListItemRenderer } from '@graphcommerce/magento-product' +import { Box } from '@mui/material' +import { useRouter } from 'next/router' +import { productListRenderer } from '../../ProductListItems' +import { GetMagentoRowProductPageDocument } from './GetMagentoRowProductPage.gql' +import { RowProductPageFragment } from './RowProductPage.gql' +import { Related, Reviews, Specs, Upsells } from './variant' + +type VariantRenderer = Record< + NonNullable, + React.FC +> + +type RowProductPageProps = RowProductPageFragment & { + renderer?: Partial +} + +function RowProductPreview(props: RowProductPageFragment) { + const { variant, identity, product } = props + + const router = useRouter() + const canShow = router.isPreview || process.env.NODE_ENV !== 'production' + const isWrongVariant = variant === 'Grid' || variant === 'Swipeable' + const noProduct = !product + if (!canShow) return null + if (!(noProduct || isWrongVariant)) return null + + return ( + ({ + p: 2, + m: 3, + border: `3px dashed ${theme.palette.error.light}`, + borderRadius: 2, + })} + > + {isWrongVariant && ( + <> + RowProduct with identity ‘{identity}’ and variant ‘{variant}’, should be migrated in + Hygraph to a RowCategory component. + + )} + {!isWrongVariant && noProduct && ( + <> + RowProduct ({identity}) was configured with Product URL " + {identity}", However Magento didn't return any results. + + )} + + ) +} + +const defaultRenderer: Partial = { + Specs, + Related, + Reviews, + Upsells, +} + +export function RowProduct(props: RowProductPageProps) { + const { renderer, variant, product } = props + const mergedRenderer = { ...defaultRenderer, ...renderer } as VariantRenderer + + const scoped = useInContextQuery( + GetMagentoRowProductPageDocument, + { variables: { urlKey: product?.url_key ?? '' }, skip: !product?.url_key }, + { products: { items: [product!] } }, + ) + + if (!variant) return null + + const RenderType = mergedRenderer?.[variant] + + return ( + + + {RenderType && ( + + )} + + ) +} diff --git a/examples/magento-graphcms/components/GraphCMS/RowProductPage/variant/Related.tsx b/examples/magento-graphcms/components/GraphCMS/RowProductPage/variant/Related.tsx new file mode 100644 index 00000000000..e72b6a5e6f4 --- /dev/null +++ b/examples/magento-graphcms/components/GraphCMS/RowProductPage/variant/Related.tsx @@ -0,0 +1,37 @@ +import { AddProductsToCartForm, RelatedProductsFragment } from '@graphcommerce/magento-product' +import { + SidebarSlider, + RenderType, + responsiveVal, + SidebarSliderProps, +} from '@graphcommerce/next-ui' +import { Typography } from '@mui/material' +import { productListRenderer } from '../../../ProductListItems' +import { RowProductPageFragment } from '../RowProductPage.gql' + +type RelatedProps = RowProductPageFragment & Pick + +export function Related(props: RelatedProps) { + const { title, product, sx } = props + const { related_products } = product ?? {} + + if (!related_products || related_products.length === 0) return null + + return ( + + {title}}> + {related_products?.map((item) => + item ? ( + + ) : null, + )} + + + ) +} diff --git a/examples/magento-graphcms/components/GraphCMS/RowProductPage/variant/Reviews.tsx b/examples/magento-graphcms/components/GraphCMS/RowProductPage/variant/Reviews.tsx new file mode 100644 index 00000000000..2ac3d46bc9c --- /dev/null +++ b/examples/magento-graphcms/components/GraphCMS/RowProductPage/variant/Reviews.tsx @@ -0,0 +1,52 @@ +import { useQuery } from '@graphcommerce/graphql' +import { ProductReviews } from '@graphcommerce/magento-review' +import { StoreConfigDocument } from '@graphcommerce/magento-store' +import { Row } from '@graphcommerce/next-ui' +import { Box, Typography } from '@mui/material' +import { RowProductPageFragment } from '../RowProductPage.gql' + +type ReviewsProps = RowProductPageFragment + +export function Reviews(props: ReviewsProps) { + const { title, product, sx } = props + const { reviews, review_count, url_key, sku } = product ?? {} + + const { data, loading } = useQuery(StoreConfigDocument) + + if (!reviews || loading) return null + + if (!data?.storeConfig?.product_reviews_enabled) return null + + return ( + + ({ + position: 'relative', + '&:focus': { + outline: 'none', + }, + display: 'flex', + justifyContent: 'space-between', + alignItems: 'center', + marginTop: theme.spacings.sm, + marginBottom: theme.spacings.xxs, + paddingBottom: theme.spacings.xxs, + borderBottom: `1px solid ${theme.palette.divider}`, + }), + ]} + > + + {title} ({review_count}) + + + + + + ) +} diff --git a/examples/magento-graphcms/components/GraphCMS/RowProductPage/variant/Specs.tsx b/examples/magento-graphcms/components/GraphCMS/RowProductPage/variant/Specs.tsx new file mode 100644 index 00000000000..33f6b038f06 --- /dev/null +++ b/examples/magento-graphcms/components/GraphCMS/RowProductPage/variant/Specs.tsx @@ -0,0 +1,13 @@ +import { ProductSpecs } from '@graphcommerce/magento-product' +import { ProductSpecsFragment } from '@graphcommerce/magento-product/components/ProductSpecs/ProductSpecs.gql' +import { RowProductFragment } from '../RowProduct.gql' + +type SpecsProps = RowProductFragment + +export function Specs(props: SpecsProps) { + const { title, aggregations } = props + + if (!aggregations) return null + + return +} diff --git a/examples/magento-graphcms/components/GraphCMS/RowProductPage/variant/Upsells.tsx b/examples/magento-graphcms/components/GraphCMS/RowProductPage/variant/Upsells.tsx new file mode 100644 index 00000000000..e04d18a8690 --- /dev/null +++ b/examples/magento-graphcms/components/GraphCMS/RowProductPage/variant/Upsells.tsx @@ -0,0 +1,37 @@ +import { AddProductsToCartForm } from '@graphcommerce/magento-product' +import { + SidebarSlider, + RenderType, + responsiveVal, + SidebarSliderProps, +} from '@graphcommerce/next-ui' +import { Typography } from '@mui/material' +import { productListRenderer } from '../../../ProductListItems/productListRenderer' +import { RowProductPageFragment } from '../RowProductPage.gql' + +type UpsellsProps = RowProductPageFragment & Pick + +export function Upsells(props: UpsellsProps) { + const { title, product, sx } = props + const { upsell_products } = product ?? {} + + if (!upsell_products || upsell_products.length === 0) return null + + return ( + + {title}}> + {upsell_products?.map((item) => + item ? ( + + ) : null, + )} + + + ) +} diff --git a/examples/magento-graphcms/components/GraphCMS/RowProductPage/variant/index.tsx b/examples/magento-graphcms/components/GraphCMS/RowProductPage/variant/index.tsx new file mode 100644 index 00000000000..6529f24c8a5 --- /dev/null +++ b/examples/magento-graphcms/components/GraphCMS/RowProductPage/variant/index.tsx @@ -0,0 +1,4 @@ +export * from './Related' +export * from './Reviews' +export * from './Specs' +export * from './Upsells' diff --git a/examples/magento-graphcms/components/GraphCMS/_config/gcRowHygraphRenderer.ts b/examples/magento-graphcms/components/GraphCMS/_config/gcRowHygraphRenderer.ts deleted file mode 100644 index 7b4b4549427..00000000000 --- a/examples/magento-graphcms/components/GraphCMS/_config/gcRowHygraphRenderer.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { GcRowTypeRenderer } from '@graphcommerce/graphql-gc-api' -import { RowBlogContent } from '../../Blog' -import { RowButtonLinkList } from '../RowButtonLinkList/RowButtonLinkList' -import { RowCategory } from '../RowCategory/RowCategory' -import { RowColumnOne } from '../RowColumnOne/RowColumnOne' -import { RowColumnThree } from '../RowColumnThree/RowColumnThree' -import { RowColumnTwo } from '../RowColumnTwo/RowColumnTwo' -import { RowContentLinks } from '../RowContentLinks/RowContentLinks' -import { RowHeroBanner } from '../RowHeroBanner/RowHeroBanner' -import { RowLinks } from '../RowLinks/RowLinks' -import { RowProduct } from '../RowProduct/RowProduct' -import { RowQuote } from '../RowQuote/RowQuote' -import { RowServiceOptions } from '../RowServiceOptions/RowServiceOptions' -import { RowSpecialBanner } from '../RowSpecialBanner/RowSpecialBanner' - -export const gcRowHygraphRenderer: Partial = { - RowColumnOne, - RowColumnTwo, - RowColumnThree, - RowHeroBanner, - RowSpecialBanner, - RowQuote, - RowBlogContent, - RowButtonLinkList, - RowServiceOptions, - RowContentLinks, - RowProduct, - RowLinks, - RowCategory, -} diff --git a/examples/magento-graphcms/components/Layout/Layout.graphql b/examples/magento-graphcms/components/Layout/Layout.graphql index 018d5dc9531..cc241ae200c 100644 --- a/examples/magento-graphcms/components/Layout/Layout.graphql +++ b/examples/magento-graphcms/components/Layout/Layout.graphql @@ -1,6 +1,3 @@ query Layout { - menu: categories { - __typename - } - ...MenuQueryFragment + ...LayoutFragment } diff --git a/examples/magento-graphcms/components/Layout/LayoutFragment.graphql b/examples/magento-graphcms/components/Layout/LayoutFragment.graphql new file mode 100644 index 00000000000..7f0af5f1e8f --- /dev/null +++ b/examples/magento-graphcms/components/Layout/LayoutFragment.graphql @@ -0,0 +1,6 @@ +fragment LayoutFragment on Query { + menu: categories { + __typename + } + ...MenuQueryFragment +} diff --git a/examples/magento-graphcms/graphql/ProductPage2.graphql b/examples/magento-graphcms/graphql/ProductPage2.graphql index 8961ef8774e..50c1be0e99b 100644 --- a/examples/magento-graphcms/graphql/ProductPage2.graphql +++ b/examples/magento-graphcms/graphql/ProductPage2.graphql @@ -5,7 +5,6 @@ query ProductPage2( $context: InContextInput ) { products(filter: { url_key: { eq: $urlKey } }) @inContext(context: $context) { - ...ProductSpecs items { __typename uid diff --git a/examples/magento-graphcms/lib/graphql/graphqlSsrClient.ts b/examples/magento-graphcms/lib/graphql/graphqlSsrClient.ts index bd3f968e2d0..2213c1e1086 100644 --- a/examples/magento-graphcms/lib/graphql/graphqlSsrClient.ts +++ b/examples/magento-graphcms/lib/graphql/graphqlSsrClient.ts @@ -37,7 +37,7 @@ function client(context: GetStaticPropsContext, fetchPolicy: FetchPolicy = 'no-c name: 'ssr', defaultOptions: { preview: context as PreviewConfig, - query: { errorPolicy: 'all', fetchPolicy }, + query: { fetchPolicy }, } as DefaultOptions, }) } diff --git a/examples/magento-graphcms/pages/[...url].tsx b/examples/magento-graphcms/pages/[...url].tsx index 4a098634497..abb34ff0a5b 100644 --- a/examples/magento-graphcms/pages/[...url].tsx +++ b/examples/magento-graphcms/pages/[...url].tsx @@ -1,8 +1,8 @@ import { PageOptions } from '@graphcommerce/framer-next-pages' import { cacheFirst, flushMeasurePerf, InContextMaskProvider } from '@graphcommerce/graphql' import { - ContentAreaCategoryPage, - ContentAreaCategoryPageBefore, + GcPageRowsCategory, + GcPageRowsCategoryBefore, GcPageQuery, } from '@graphcommerce/graphql-gc-api' import { @@ -75,7 +75,7 @@ function CategoryPage(props: CategoryProps) { - + @@ -144,7 +144,7 @@ function CategoryPage(props: CategoryProps) { )} - + {page && ( & { - content: PageContent - } & { urlKey: string } + Pick & { urlKey: string } type RouteProps = { url: string } type GetPageStaticPaths = GetStaticPaths type GetPageStaticProps = GetStaticProps function ProductPage(props: Props) { - const { content, usps, sidebarUsps, defaultValues, urlKey } = props + const { usps, sidebarUsps, defaultValues, urlKey } = props const scopedQuery = useInContextQuery(ProductPage2Document, { variables: { urlKey } }, props) const { products, relatedUpsells } = scopedQuery.data @@ -73,7 +70,7 @@ function ProductPage(props: Props) { if (!product?.sku || !product.url_key) return null return ( - + <> @@ -93,7 +90,7 @@ function ProductPage(props: Props) { - + {/* */} {import.meta.graphCommerce.breadcrumbs && ( - - + {/* */} - + {/* */} + } + right={<>hoi} + // right={} fontSize='responsive' /> - + {/* ({ mb: theme.spacings.xxl })} /> - + ) } @@ -206,33 +201,31 @@ export const getStaticProps: GetPageStaticProps = async (context) => { const urlKey = params?.url ?? '??' const conf = client.query({ query: StoreConfigDocument }) - const productPage = staticClient.query({ query: ProductPage2Document, variables: { urlKey } }) const layout = staticClient.query({ query: LayoutDocument, fetchPolicy: cacheFirst(staticClient), }) - const product = productPage.then((pp) => - pp.data.products?.items?.find((p) => p?.url_key === urlKey), - ) + const productQuery = await staticClient.query({ + query: ProductPage2Document, + variables: { urlKey }, + }) + const product = productQuery.data.products?.items?.find((p) => p?.url_key === urlKey) - const content = pageContent(staticClient, 'product/global', product, true) - if (!(await product)) return redirectOrNotFound(staticClient, conf, params, locale) + if (!product) return { notFound: true } + //return redirectOrNotFound(staticClient, conf, params, locale) - const category = productPageCategory(await product) + const category = productPageCategory(product) const up = category?.url_path && category?.name ? { href: `/${category.url_path}`, title: category.name } : { href: `/`, title: i18n._(/* i18n */ 'Home') } - const usps = staticClient.query({ query: UspsDocument, fetchPolicy: cacheFirst(staticClient) }) return { props: { - content: await content, urlKey, - ...defaultConfigurableOptionsSelection(urlKey, client, (await productPage).data), + ...defaultConfigurableOptionsSelection(urlKey, client, productQuery.data), ...(await layout).data, - ...(await usps).data, apolloState: await conf.then(() => client.cache.extract()), up, }, diff --git a/examples/magento-graphcms/plugins/hygraph/HygraphContentArea.tsx b/examples/magento-graphcms/plugins/hygraph/HygraphContentArea.tsx deleted file mode 100644 index 62da90d5d5b..00000000000 --- a/examples/magento-graphcms/plugins/hygraph/HygraphContentArea.tsx +++ /dev/null @@ -1,13 +0,0 @@ -import type { ContentAreaProps } from '@graphcommerce/graphql-gc-api' -import type { PluginConfig, PluginProps } from '@graphcommerce/next-config' -import { gcRowHygraphRenderer } from '../../components/GraphCMS/_config/gcRowHygraphRenderer' - -export const config: PluginConfig = { - type: 'component', - module: '@graphcommerce/graphql-gc-api', -} - -export const ContentArea = (props: PluginProps) => { - const { Prev, ...rest } = props - return -} diff --git a/examples/magento-graphcms/plugins/hygraph/HygraphGcPageRows.tsx b/examples/magento-graphcms/plugins/hygraph/HygraphGcPageRows.tsx new file mode 100644 index 00000000000..49caaac8388 --- /dev/null +++ b/examples/magento-graphcms/plugins/hygraph/HygraphGcPageRows.tsx @@ -0,0 +1,41 @@ +import type { GcPageRowsProps, GcRowTypeRenderer } from '@graphcommerce/graphql-gc-api' +import type { PluginConfig, PluginProps } from '@graphcommerce/next-config' +import { RowBlogContent } from '../../components' +import { RowButtonLinkList } from '../../components/GraphCMS/RowButtonLinkList/RowButtonLinkList' +import { RowCategory } from '../../components/GraphCMS/RowCategory/RowCategory' +import { RowColumnOne } from '../../components/GraphCMS/RowColumnOne/RowColumnOne' +import { RowColumnThree } from '../../components/GraphCMS/RowColumnThree/RowColumnThree' +import { RowColumnTwo } from '../../components/GraphCMS/RowColumnTwo/RowColumnTwo' +import { RowContentLinks } from '../../components/GraphCMS/RowContentLinks/RowContentLinks' +import { RowHeroBanner } from '../../components/GraphCMS/RowHeroBanner/RowHeroBanner' +import { RowLinks } from '../../components/GraphCMS/RowLinks/RowLinks' +import { RowProduct } from '../../components/GraphCMS/RowProduct/RowProduct' +import { RowQuote } from '../../components/GraphCMS/RowQuote/RowQuote' +import { RowServiceOptions } from '../../components/GraphCMS/RowServiceOptions/RowServiceOptions' +import { RowSpecialBanner } from '../../components/GraphCMS/RowSpecialBanner/RowSpecialBanner' + +export const config: PluginConfig = { + type: 'component', + module: '@graphcommerce/graphql-gc-api', +} + +const gcRowHygraphRenderer: Partial = { + RowColumnOne, + RowColumnTwo, + RowColumnThree, + RowHeroBanner, + RowSpecialBanner, + RowQuote, + RowBlogContent, + RowButtonLinkList, + RowServiceOptions, + RowContentLinks, + RowProduct, + RowLinks, + RowCategory, +} + +export const GcPageRows = (props: PluginProps) => { + const { Prev, ...rest } = props + return +} diff --git a/packages/graphql-gc-api/components/ContentArea/Areas.tsx b/packages/graphql-gc-api/components/ContentArea/Areas.tsx index e230026127e..7d15fec0b06 100644 --- a/packages/graphql-gc-api/components/ContentArea/Areas.tsx +++ b/packages/graphql-gc-api/components/ContentArea/Areas.tsx @@ -1,8 +1,8 @@ -import { ContentArea } from './ContentArea' +import { GcPageRows } from './GcPageRows' -export const ContentAreaHome = ContentArea -export const ContentAreaProductPageBefore = ContentArea -export const ContentAreaProductPageSidebar = ContentArea -export const ContentAreaProductPage = ContentArea -export const ContentAreaCategoryPageBefore = ContentArea -export const ContentAreaCategoryPage = ContentArea +export const ContentAreaHome = GcPageRows +export const GcPageRowsProduct = GcPageRows +export const GcPageRowsProductBefore = GcPageRows +export const GcPageRowsProductSidebar = GcPageRows +export const GcPageRowsCategory = GcPageRows +export const GcPageRowsCategoryBefore = GcPageRows diff --git a/packages/graphql-gc-api/components/ContentArea/ContentArea.tsx b/packages/graphql-gc-api/components/ContentArea/GcPageRows.tsx similarity index 57% rename from packages/graphql-gc-api/components/ContentArea/ContentArea.tsx rename to packages/graphql-gc-api/components/ContentArea/GcPageRows.tsx index 5596c9e3641..f65f654ea4c 100644 --- a/packages/graphql-gc-api/components/ContentArea/ContentArea.tsx +++ b/packages/graphql-gc-api/components/ContentArea/GcPageRows.tsx @@ -12,23 +12,19 @@ export type GcRowTypeRenderer = TypeRenderer< NonNullable>[number]> > -export type ContentAreaProps = GcPageQuery & { - renderer?: Partial +export type GcPageRowsProps = GcPageQuery & { + rowRenderer?: Partial loadingEager?: number } -export const ContentArea = React.memo((props) => { - const { renderer, page, loadingEager = 2 } = props - const mergedRenderer = { ...renderer } as GcRowTypeRenderer - - const rows = page?.rows - if (!rows) return null +export const GcPageRows = React.memo((props) => { + const { rowRenderer, page, loadingEager = 2 } = props return ( <> - {filterNonNullableKeys(rows)?.map((item, index) => ( + {filterNonNullableKeys(page?.rows)?.map((item, index) => ( - + ))} diff --git a/packages/graphql-gc-api/components/ContentArea/index.ts b/packages/graphql-gc-api/components/ContentArea/index.ts index 7a44ba31b63..4f1822fc548 100644 --- a/packages/graphql-gc-api/components/ContentArea/index.ts +++ b/packages/graphql-gc-api/components/ContentArea/index.ts @@ -1,2 +1,2 @@ export * from './Areas' -export * from './ContentArea' +export * from './GcPageRows' diff --git a/packages/graphql-gc-api/package.json b/packages/graphql-gc-api/package.json index 788107a449e..5674f147385 100644 --- a/packages/graphql-gc-api/package.json +++ b/packages/graphql-gc-api/package.json @@ -2,7 +2,7 @@ "name": "@graphcommerce/graphql-gc-api", "homepage": "https://www.graphcommerce.org/", "repository": "github:graphcommerce-org/graphcommerce", - "version": "9.0.0-canary.62", + "version": "9.0.0-canary.70", "sideEffects": false, "prettier": "@graphcommerce/prettier-config-pwa", "eslintConfig": { diff --git a/packages/graphql-gc-api/schema/Query_gcLayout.graphqls b/packages/graphql-gc-api/schema/Query_gcLayout.graphqls new file mode 100644 index 00000000000..93a57a34a99 --- /dev/null +++ b/packages/graphql-gc-api/schema/Query_gcLayout.graphqls @@ -0,0 +1,11 @@ +input GCLayoutInput { + scope: String! +} + +type GcLayout { + menu: GcMenu +} + +extend type Query { + gcLayout(input: GCLayoutInput!): GcLayout +} diff --git a/packages/hygraph-dynamic-rows/lib/getAllHygraphDynamicRows.ts b/packages/hygraph-dynamic-rows/lib/getAllHygraphDynamicRows.ts deleted file mode 100644 index 0d54e61c942..00000000000 --- a/packages/hygraph-dynamic-rows/lib/getAllHygraphDynamicRows.ts +++ /dev/null @@ -1,44 +0,0 @@ -import type { ApolloClient, NormalizedCacheObject, ApolloQueryResult } from '@apollo/client' -import { cacheFirst } from '@graphcommerce/graphql' -import { AllDynamicRowsDocument, AllDynamicRowsQuery } from '../graphql' - -type DynamicRows = AllDynamicRowsQuery['dynamicRows'] - -export async function getAllHygraphDynamicRows( - client: ApolloClient, - options: { pageSize?: number } = {}, -) { - const { pageSize = 100 } = options - - const query = client.query({ - query: AllDynamicRowsDocument, - variables: { first: pageSize }, - fetchPolicy: cacheFirst(client), - }) - - const pages: Promise>[] = [query] - - const { data } = await query - const totalPages = Math.ceil(data.pagesConnection.aggregate.count / pageSize) ?? 1 - if (totalPages > 1) { - for (let i = 2; i <= totalPages; i++) { - pages.push( - client.query({ - query: AllDynamicRowsDocument, - variables: { first: pageSize, skip: pageSize * (i - 1) }, - fetchPolicy: cacheFirst(client), - }), - ) - } - } - - const dynamicRows: DynamicRows = (await Promise.all(pages)) - .map((q) => q.data.dynamicRows) - .flat(1) - .map((row) => ({ - id: row.id, - conditions: row.conditions, - })) - - return dynamicRows -} diff --git a/packages/hygraph-dynamic-rows/lib/hygraphDynamicRows.ts b/packages/hygraph-dynamic-rows/lib/hygraphDynamicRows.ts index 1375444f861..a61991657b6 100644 --- a/packages/hygraph-dynamic-rows/lib/hygraphDynamicRows.ts +++ b/packages/hygraph-dynamic-rows/lib/hygraphDynamicRows.ts @@ -1,14 +1,11 @@ import { HygraphPagesQuery } from '@graphcommerce/graphcms-ui' -import { ApolloClient, NormalizedCacheObject, cacheFirst } from '@graphcommerce/graphql' import { ConditionTextFragment, ConditionNumberFragment, ConditionOrFragment, ConditionAndFragment, - DynamicRowsDocument, DynamicRowsQuery, } from '../graphql' -import { getAllHygraphDynamicRows } from './getAllHygraphDynamicRows' /** * This generally works the same way as lodash get, however, when encountering an array it will @@ -109,65 +106,3 @@ export function applyDynamicRows( return content } - -/** - * Fetch the page content for the given urls. - * - * - Uses an early bailout to check to reduce hygraph calls. - * - Implements an alias sytem to merge the content of multiple pages. - * - * @deprecated Please use the resolver instead. - */ -export async function hygraphDynamicRows( - client: ApolloClient, - pageQuery: Promise<{ data: HygraphPagesQuery }>, - url: string, - cached: boolean, - additionalProperties?: Promise | object, -): Promise<{ data: HygraphPagesQuery }> { - const fetchPolicy = cached ? cacheFirst(client) : undefined - const allRoutes = await getAllHygraphDynamicRows(client) - - // Get the required rowIds from the conditions - const properties = { ...(await additionalProperties), url } - - const rowIds = allRoutes - .filter((availableDynamicRow) => - availableDynamicRow.conditions.some((condition) => matchCondition(condition, properties)), - ) - .map((row) => row.id) - const dynamicRows = - rowIds.length !== 0 - ? client.query({ query: DynamicRowsDocument, variables: { rowIds }, fetchPolicy }) - : undefined - - const [pageResult, dynamicResult] = await Promise.all([pageQuery, dynamicRows]) - - const page = pageResult.data.pages[0] as Page | undefined - - if (!dynamicResult?.data.dynamicRows) return pageResult - - // Create a copy of the content array. - const content = applyDynamicRows(dynamicResult?.data.dynamicRows, page.content) - - if (!content.length) return pageResult - - const dynamicPage: Page = { - id: 'dynamic-page', - __typename: 'Page', - metaRobots: 'INDEX_FOLLOW', - metaTitle: '', - metaDescription: '', - url: '', - content: [], - relatedPages: [], - } - - // Return the merged page result. - return { - data: { - ...pageResult.data, - pages: [{ ...dynamicPage, ...page, content }], - }, - } -} diff --git a/packages/hygraph-ui/mesh/resolvers.ts b/packages/hygraph-ui/mesh/resolvers.ts index dec7ca0050e..4ec674949b1 100644 --- a/packages/hygraph-ui/mesh/resolvers.ts +++ b/packages/hygraph-ui/mesh/resolvers.ts @@ -83,7 +83,7 @@ export const resolvers: Resolvers = { // Resolve the query `gcPage` to a page with the given URL Query: { gcPage: { - resolve: async (root, args, context, info) => + resolve: (root, args, context, info) => context.hygraph.Query.pages({ root, info, @@ -197,12 +197,15 @@ export const resolvers: Resolvers = { category: { selectionSet: `{ categoryUrl }`, resolve: async (root, args, context, info) => { + console.log(root.categoryUrl) const result = await context.m2.Query.categories({ root, info, context, args: { filters: { url_path: { eq: root.categoryUrl } }, pageSize: 1 }, }) + + console.log(result) const category = result?.items?.[0] ?? null return category as ResolversTypes['CategoryTree'] }, diff --git a/packages/magento-product/components/ProductPageMeta/ProductPageMeta.tsx b/packages/magento-product/components/ProductPageMeta/ProductPageMeta.tsx index 2c579bbcaf6..3675a67a124 100644 --- a/packages/magento-product/components/ProductPageMeta/ProductPageMeta.tsx +++ b/packages/magento-product/components/ProductPageMeta/ProductPageMeta.tsx @@ -1,10 +1,10 @@ import { PageMeta } from '@graphcommerce/magento-store' +import { PageMetaProps } from '@graphcommerce/next-ui' import { productLink } from '../../hooks/useProductLink' import { ProductPageMetaFragment } from './ProductPageMeta.gql' -import { PageMetaPropsOld } from '@graphcommerce/next-ui' export type ProductPageMetaProps = { product: ProductPageMetaFragment } & Pick< - PageMetaPropsOld, + PageMetaProps, 'children' | 'ogImage' | 'ogImageUseFallback' > diff --git a/yarn.lock b/yarn.lock index 34b65e7b046..4b24e6a3bba 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5839,25 +5839,9 @@ __metadata: languageName: node linkType: hard -"@graphql-tools/delegate@npm:^10.0.11, @graphql-tools/delegate@npm:^10.0.12, @graphql-tools/delegate@npm:^10.0.14, @graphql-tools/delegate@npm:^10.0.4": - version: 10.0.14 - resolution: "@graphql-tools/delegate@npm:10.0.14" - dependencies: - "@graphql-tools/batch-execute": "npm:^9.0.4" - "@graphql-tools/executor": "npm:^1.2.8" - "@graphql-tools/schema": "npm:^10.0.4" - "@graphql-tools/utils": "npm:^10.2.3" - dataloader: "npm:^2.2.2" - tslib: "npm:^2.5.0" - peerDependencies: - graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 - checksum: 10c0/266931e142a74af12e687a5da05a16125896d6d909fb231bf6addd0fb9e05dbecbaa0a453a637e94ebec68d96a4c4568538046dd5b0e0d3d8e4fb232d5dc164a - languageName: node - linkType: hard - -"@graphql-tools/delegate@npm:^10.0.16": - version: 10.0.16 - resolution: "@graphql-tools/delegate@npm:10.0.16" +"@graphql-tools/delegate@npm:^10.0.11, @graphql-tools/delegate@npm:^10.0.12, @graphql-tools/delegate@npm:^10.0.14, @graphql-tools/delegate@npm:^10.0.16, @graphql-tools/delegate@npm:^10.0.4": + version: 10.0.17 + resolution: "@graphql-tools/delegate@npm:10.0.17" dependencies: "@graphql-tools/batch-execute": "npm:^9.0.4" "@graphql-tools/executor": "npm:^1.3.0" @@ -5867,7 +5851,7 @@ __metadata: tslib: "npm:^2.5.0" peerDependencies: graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 - checksum: 10c0/d0d47db1faec9dd1b55bc9d5300e7c6c33bcda6d47f890a1a5af7c8440175af91cf91e29fe9c533face2743293367609ed9d8f2ebc63532b3af5ecc39a8e9121 + checksum: 10c0/c136026d328ce29d542077305a639d8f84c254b8ef40a9d187b410b3b5d93bbd1c51c424c4318c2df02e8e8a03bea1cf336268010b59d6c28168b3e5c0fa847d languageName: node linkType: hard From 38876f825700e7cda76a38eeafc569f961751d4f Mon Sep 17 00:00:00 2001 From: Paul Hachmang Date: Wed, 7 Aug 2024 14:29:26 +0200 Subject: [PATCH 28/33] Introduce a RowProductPage model --- .../GraphCMS/RowProduct/RowProduct.tsx | 22 +- .../GraphCMS/RowProduct/variant/Related.tsx | 36 --- .../GraphCMS/RowProduct/variant/Reviews.tsx | 51 ---- .../GraphCMS/RowProduct/variant/Specs.tsx | 13 -- .../GraphCMS/RowProduct/variant/Upsells.tsx | 36 --- .../RowProductPage/RowProductPage.graphql | 1 + .../GraphCMS/RowProductPage/variant/Specs.tsx | 13 +- .../graphql/ProductPage2.graphql | 17 +- examples/magento-graphcms/pages/p/[url].tsx | 27 +-- .../hygraph-dynamic-rows/mesh/resolvers.ts | 60 +++-- packages/hygraph-ui/mesh/resolvers.ts | 66 +++--- .../ConfigurableProductPage.graphql | 3 - ...oductPageConfigurableQueryFragment.graphql | 10 - .../ProductPageQueryFragment.graphql | 11 - .../ProductSpecs/ProductSpecs.graphql | 37 +-- .../components/ProductSpecs/ProductSpecs.tsx | 45 +++- .../ProductSpecs/ProductSpecsAggregations.tsx | 34 --- .../ProductSpecsCustomAttributes.tsx | 18 +- .../next-config/dist/generated/config.js | 219 +++++++----------- 19 files changed, 227 insertions(+), 492 deletions(-) delete mode 100644 examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Related.tsx delete mode 100644 examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Reviews.tsx delete mode 100644 examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Specs.tsx delete mode 100644 examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Upsells.tsx delete mode 100644 packages/magento-product-configurable/ConfigurableProductPage.graphql delete mode 100644 packages/magento-product-configurable/ProductPageConfigurableQueryFragment.graphql delete mode 100644 packages/magento-product/components/ProductPage/ProductPageQueryFragment.graphql delete mode 100644 packages/magento-product/components/ProductSpecs/ProductSpecsAggregations.tsx diff --git a/examples/magento-graphcms/components/GraphCMS/RowProduct/RowProduct.tsx b/examples/magento-graphcms/components/GraphCMS/RowProduct/RowProduct.tsx index 793ad280bab..ab3085c53d0 100644 --- a/examples/magento-graphcms/components/GraphCMS/RowProduct/RowProduct.tsx +++ b/examples/magento-graphcms/components/GraphCMS/RowProduct/RowProduct.tsx @@ -5,7 +5,7 @@ import { useRouter } from 'next/router' import { productListRenderer } from '../../ProductListItems' import { GetMagentoRowProductDocument } from './GetMagentoRowProduct.gql' import { RowProductFragment } from './RowProduct.gql' -import { Backstory, Feature, FeatureBoxed, Related, Reviews, Specs, Upsells } from './variant' +import { Backstory, Feature, FeatureBoxed } from './variant' type VariantRenderer = Record< NonNullable, @@ -21,10 +21,12 @@ function RowProductPreview(props: RowProductFragment) { const router = useRouter() const canShow = router.isPreview || process.env.NODE_ENV !== 'production' - const isWrongVariant = variant === 'Grid' || variant === 'Swipeable' + const shouldBeRowCategory = variant === 'Grid' || variant === 'Swipeable' + const shouldBeRowProductPage = + variant === 'Reviews' || variant === 'Upsells' || variant === 'Related' || variant === 'Specs' const noProduct = !product if (!canShow) return null - if (!(noProduct || isWrongVariant)) return null + if (!(noProduct || shouldBeRowCategory || shouldBeRowProductPage)) return null return ( - {isWrongVariant && ( + {shouldBeRowCategory && ( <> RowProduct with identity ‘{identity}’ and variant ‘{variant}’, should be migrated in Hygraph to a RowCategory component. )} - {!isWrongVariant && noProduct && ( + {shouldBeRowProductPage && ( + <> + RowProduct with identity ‘{identity}’ and variant ‘{variant}’, should be migrated in + Hygraph to a RowProductPage component. + + )} + {!(shouldBeRowCategory || shouldBeRowProductPage) && noProduct && ( <> RowProduct ({identity}) was configured with Product URL " {identity}", However Magento didn't return any results. @@ -52,13 +60,9 @@ function RowProductPreview(props: RowProductFragment) { } const defaultRenderer: Partial = { - Specs, Backstory, Feature, FeatureBoxed, - Related, - Reviews, - Upsells, } export function RowProduct(props: RowProductProps) { diff --git a/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Related.tsx b/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Related.tsx deleted file mode 100644 index 08043235e83..00000000000 --- a/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Related.tsx +++ /dev/null @@ -1,36 +0,0 @@ -import { AddProductsToCartForm, RelatedProductsFragment } from '@graphcommerce/magento-product' -import { - SidebarSlider, - RenderType, - responsiveVal, - SidebarSliderProps, -} from '@graphcommerce/next-ui' -import { Typography } from '@mui/material' -import { productListRenderer } from '../../../ProductListItems' -import { RowProductFragment } from '../RowProduct.gql' - -type RelatedProps = RowProductFragment & Pick - -export function Related(props: RelatedProps) { - const { title, related_products, sx } = props - - if (!related_products || related_products.length === 0) return null - - return ( - - {title}}> - {related_products?.map((item) => - item ? ( - - ) : null, - )} - - - ) -} diff --git a/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Reviews.tsx b/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Reviews.tsx deleted file mode 100644 index c8a91e79aa7..00000000000 --- a/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Reviews.tsx +++ /dev/null @@ -1,51 +0,0 @@ -import { useQuery } from '@graphcommerce/graphql' -import { ProductReviews, ProductReviewsProps } from '@graphcommerce/magento-review' -import { StoreConfigDocument } from '@graphcommerce/magento-store' -import { Row } from '@graphcommerce/next-ui' -import { Box, Typography } from '@mui/material' -import { RowProductFragment } from '../RowProduct.gql' - -type ReviewsProps = RowProductFragment - -export function Reviews(props: ReviewsProps) { - const { title, reviews, url_key, review_count, sku } = props - - const { data, loading } = useQuery(StoreConfigDocument) - - if (!reviews || loading) return null - - if (!data?.storeConfig?.product_reviews_enabled) return null - - return ( - - ({ - position: 'relative', - '&:focus': { - outline: 'none', - }, - display: 'flex', - justifyContent: 'space-between', - alignItems: 'center', - marginTop: theme.spacings.sm, - marginBottom: theme.spacings.xxs, - paddingBottom: theme.spacings.xxs, - borderBottom: `1px solid ${theme.palette.divider}`, - }), - ]} - > - - {title} ({review_count}) - - - - - - ) -} diff --git a/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Specs.tsx b/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Specs.tsx deleted file mode 100644 index e1a2f78b39e..00000000000 --- a/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Specs.tsx +++ /dev/null @@ -1,13 +0,0 @@ -import { ProductSpecs } from '@graphcommerce/magento-product' -import { ProductSpecsFragment } from '@graphcommerce/magento-product/components/ProductSpecs/ProductSpecs.gql' -import { RowProductFragment } from '../RowProduct.gql' - -type SpecsProps = RowProductFragment - -export function Specs(props: SpecsProps) { - const { title, aggregations, items } = props - - if (!aggregations && !items) return null - - return -} diff --git a/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Upsells.tsx b/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Upsells.tsx deleted file mode 100644 index bc07b3b3c52..00000000000 --- a/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Upsells.tsx +++ /dev/null @@ -1,36 +0,0 @@ -import { AddProductsToCartForm, UpsellProductsFragment } from '@graphcommerce/magento-product' -import { - SidebarSlider, - RenderType, - responsiveVal, - SidebarSliderProps, -} from '@graphcommerce/next-ui' -import { Typography } from '@mui/material' -import { productListRenderer } from '../../../ProductListItems/productListRenderer' -import { RowProductFragment } from '../RowProduct.gql' - -type UpsellsProps = RowProductFragment & Pick - -export function Upsells(props: UpsellsProps) { - const { title, upsell_products, sx } = props - - if (!upsell_products || upsell_products.length === 0) return null - - return ( - - {title}}> - {upsell_products?.map((item) => - item ? ( - - ) : null, - )} - - - ) -} diff --git a/examples/magento-graphcms/components/GraphCMS/RowProductPage/RowProductPage.graphql b/examples/magento-graphcms/components/GraphCMS/RowProductPage/RowProductPage.graphql index 6eb33686472..780f9c37c9b 100644 --- a/examples/magento-graphcms/components/GraphCMS/RowProductPage/RowProductPage.graphql +++ b/examples/magento-graphcms/components/GraphCMS/RowProductPage/RowProductPage.graphql @@ -15,5 +15,6 @@ fragment RowProductPage on RowProduct { ...UpsellProducts ...RelatedProducts ...ProductReviews + ...ProductSpecs } } diff --git a/examples/magento-graphcms/components/GraphCMS/RowProductPage/variant/Specs.tsx b/examples/magento-graphcms/components/GraphCMS/RowProductPage/variant/Specs.tsx index 33f6b038f06..f5bd5dcdb3a 100644 --- a/examples/magento-graphcms/components/GraphCMS/RowProductPage/variant/Specs.tsx +++ b/examples/magento-graphcms/components/GraphCMS/RowProductPage/variant/Specs.tsx @@ -1,13 +1,10 @@ import { ProductSpecs } from '@graphcommerce/magento-product' -import { ProductSpecsFragment } from '@graphcommerce/magento-product/components/ProductSpecs/ProductSpecs.gql' -import { RowProductFragment } from '../RowProduct.gql' +import { RowProductPageFragment } from '../RowProductPage.gql' -type SpecsProps = RowProductFragment +type SpecsProps = RowProductPageFragment export function Specs(props: SpecsProps) { - const { title, aggregations } = props - - if (!aggregations) return null - - return + const { title, product } = props + if (!product) return null + return } diff --git a/examples/magento-graphcms/graphql/ProductPage2.graphql b/examples/magento-graphcms/graphql/ProductPage2.graphql index 6469976461c..b6c9c7e877c 100644 --- a/examples/magento-graphcms/graphql/ProductPage2.graphql +++ b/examples/magento-graphcms/graphql/ProductPage2.graphql @@ -1,10 +1,4 @@ -query ProductPage2( - $urlKey: String! - $reviewPageSize: Int = 3 - $reviewPage: Int = 1 - $context: InContextInput - $useCustomAttributes: Boolean = false -) { +query ProductPage2($urlKey: String!, $context: InContextInput) { products(filter: { url_key: { eq: $urlKey } }) @inContext(context: $context) { items { __typename @@ -23,13 +17,4 @@ query ProductPage2( } } } - # Workaround for https://github.com/magento/magento2/issues/32427 - relatedUpsells: products(filter: { url_key: { eq: $urlKey } }) @inContext(context: $context) { - items { - uid - ...UpsellProducts - ...RelatedProducts - ...ProductReviews - } - } } diff --git a/examples/magento-graphcms/pages/p/[url].tsx b/examples/magento-graphcms/pages/p/[url].tsx index 8f09f4e8c3f..6d27b33796e 100644 --- a/examples/magento-graphcms/pages/p/[url].tsx +++ b/examples/magento-graphcms/pages/p/[url].tsx @@ -59,17 +59,10 @@ type GetPageStaticProps = GetStaticProps= 247 } }, - props, - ) - const { products, relatedUpsells } = scopedQuery.data + const scopedQuery = useInContextQuery(ProductPage2Document, { variables: { urlKey } }, props) + const { products } = scopedQuery.data - const product = mergeDeep( - products?.items?.[0], - relatedUpsells?.items?.find((item) => item?.uid === products?.items?.[0]?.uid), - ) + const product = products?.items?.[0] if (!product?.sku || !product.url_key) return null @@ -158,20 +151,6 @@ function ProductPage(props: Props) { - {/* ( - - ), - }} - /> */} - } exclude={[product.sku]} diff --git a/packages/hygraph-dynamic-rows/mesh/resolvers.ts b/packages/hygraph-dynamic-rows/mesh/resolvers.ts index 5a89931ac5a..0fb03bf6397 100644 --- a/packages/hygraph-dynamic-rows/mesh/resolvers.ts +++ b/packages/hygraph-dynamic-rows/mesh/resolvers.ts @@ -48,36 +48,32 @@ async function getAllHygraphDynamicRows( } export const resolvers: Resolvers = { - GcPage: { - rows: { - resolve: async (parent, args, context, info) => { - const execute = createDocumentExecutor(context, parent, info) - const allRoutes = await getAllHygraphDynamicRows(context, { ttl: 60 * 60 }, parent, info) - - const rowIds = allRoutes - .filter((availableDynamicRow) => - availableDynamicRow.conditions.some((condition) => - matchCondition(condition, { - ...parent, - // ...args, - ...getProduct(context, parent.url.slice(2)), - }), - ), - ) - .map((row) => row.id) - - if (rowIds.length === 0) return parent.content - const dynamicRows = await execute(DynamicRowsDocument, { - variables: { rowIds }, - ttl: 60 * 60, - headers: ['gcms-stage', 'gcms-locale'], - }) - - const rows = dynamicRows.dynamicRows.filter((row) => rowIds.includes(row.id)) - - if (rows.length === 0) return parent.content - return applyDynamicRows(rows, parent.content) - }, - }, - }, + // GcPage: { + // rows: { + // resolve: async (parent, args, context, info) => { + // const execute = createDocumentExecutor(context, parent, info) + // const allRoutes = await getAllHygraphDynamicRows(context, { ttl: 60 * 60 }, parent, info) + // const rowIds = allRoutes + // .filter((availableDynamicRow) => + // availableDynamicRow.conditions.some((condition) => + // matchCondition(condition, { + // ...parent, + // // ...args, + // ...getProduct(context, parent.url?.slice(2)), + // }), + // ), + // ) + // .map((row) => row.id) + // if (rowIds.length === 0) return parent.content + // const dynamicRows = await execute(DynamicRowsDocument, { + // variables: { rowIds }, + // ttl: 60 * 60, + // headers: ['gcms-stage', 'gcms-locale'], + // }) + // const rows = dynamicRows.dynamicRows.filter((row) => rowIds.includes(row.id)) + // if (rows.length === 0) return parent.content + // return applyDynamicRows(rows, parent.content) + // }, + // }, + // }, } diff --git a/packages/hygraph-ui/mesh/resolvers.ts b/packages/hygraph-ui/mesh/resolvers.ts index 4ec674949b1..8da3c819132 100644 --- a/packages/hygraph-ui/mesh/resolvers.ts +++ b/packages/hygraph-ui/mesh/resolvers.ts @@ -9,7 +9,7 @@ import { RowProduct, type Resolvers, } from '@graphcommerce/graphql-mesh' -import { Kind } from 'graphql' +import { Kind, print } from 'graphql' const normalizeUrl = (href: string) => { const cleanedhref = href.replaceAll(/^\/|\/$/g, '') @@ -43,10 +43,6 @@ export function getProduct(context: MeshContext, key: string): ProductInterface return value[key] } -function isRowProduct(row: PageContent): row is RowProduct { - return '__typename' in row && row.__typename === 'RowProduct' -} - const gcPageProductResolver: GCPageResolver = { selectionSet: `{url_key}`, resolve: async (root, args, context, info) => { @@ -69,12 +65,6 @@ const gcPageProductResolver: GCPageResolver = { }) )?.[0] - // Since the RowProduct is a child of the current product, we replace the identity with the current product's URL key. - if (page?.content) - page.content = page.content.map((row) => - isRowProduct(row) ? { ...row, identity: root.url_key ?? row.identity } : row, - ) - return page }, } @@ -171,24 +161,33 @@ export const resolvers: Resolvers = { product: { selectionSet: `{ identity }`, resolve: async (root, args, context, info) => { - const storedProduct = getProduct(context, root.identity) - if (storedProduct) return storedProduct as ResolversTypes['ProductInterface'] - const result = await context.m2.Query.products({ root, info, context, - key: root.identity, - argsFromKeys: (keys) => ({ - filter: { url_key: { in: keys } }, + selectionSet: (subtree) => ({ + kind: Kind.SELECTION_SET, + selections: [ + { + kind: Kind.FIELD, + name: { kind: Kind.NAME, value: 'items' }, + selectionSet: { + kind: Kind.SELECTION_SET, + selections: [ + { kind: Kind.FIELD, name: { kind: Kind.NAME, value: 'url_key' } }, + ...subtree.selections, + ], + }, + }, + ], }), + key: root.identity, + argsFromKeys: (keys) => ({ filter: { url_key: { in: keys } } }), valuesFromResults: (results, keys) => keys.map((key) => results?.items?.find((r) => r?.url_key === key) ?? null), }) - const product = (result ?? null) as ResolversTypes['ProductInterface'] - - return product + return (result ?? null) as ResolversTypes['ProductInterface'] | null }, }, }, @@ -197,17 +196,32 @@ export const resolvers: Resolvers = { category: { selectionSet: `{ categoryUrl }`, resolve: async (root, args, context, info) => { - console.log(root.categoryUrl) const result = await context.m2.Query.categories({ root, info, context, - args: { filters: { url_path: { eq: root.categoryUrl } }, pageSize: 1 }, + key: root.categoryUrl, + selectionSet: (subtree) => ({ + kind: Kind.SELECTION_SET, + selections: [ + { + kind: Kind.FIELD, + name: { kind: Kind.NAME, value: 'items' }, + selectionSet: { + kind: Kind.SELECTION_SET, + selections: [ + { kind: Kind.FIELD, name: { kind: Kind.NAME, value: 'url_path' } }, + ...subtree.selections, + ], + }, + }, + ], + }), + argsFromKeys: (keys) => ({ filters: { url_path: { in: keys } } }), + valuesFromResults: (results, keys) => + results?.items?.find((r) => r?.url_path === keys[0]) ?? null, }) - - console.log(result) - const category = result?.items?.[0] ?? null - return category as ResolversTypes['CategoryTree'] + return (result ?? null) as ResolversTypes['CategoryTree'] | null }, }, }, diff --git a/packages/magento-product-configurable/ConfigurableProductPage.graphql b/packages/magento-product-configurable/ConfigurableProductPage.graphql deleted file mode 100644 index 717701fd9d9..00000000000 --- a/packages/magento-product-configurable/ConfigurableProductPage.graphql +++ /dev/null @@ -1,3 +0,0 @@ -query ConfigurableProductPage($urlKey: String, $useCustomAttributes: Boolean = false) { - ...ProductPageConfigurableQueryFragment -} diff --git a/packages/magento-product-configurable/ProductPageConfigurableQueryFragment.graphql b/packages/magento-product-configurable/ProductPageConfigurableQueryFragment.graphql deleted file mode 100644 index 5548af258da..00000000000 --- a/packages/magento-product-configurable/ProductPageConfigurableQueryFragment.graphql +++ /dev/null @@ -1,10 +0,0 @@ -fragment ProductPageConfigurableQueryFragment on Query { - typeProducts: products(filter: { url_key: { eq: $urlKey } }) { - ...ProductSpecs - items { - __typename - uid - ...ConfigurableProductForm - } - } -} diff --git a/packages/magento-product/components/ProductPage/ProductPageQueryFragment.graphql b/packages/magento-product/components/ProductPage/ProductPageQueryFragment.graphql deleted file mode 100644 index 5065212fa21..00000000000 --- a/packages/magento-product/components/ProductPage/ProductPageQueryFragment.graphql +++ /dev/null @@ -1,11 +0,0 @@ -fragment ProductPageQueryFragment on Query { - products(filter: { url_key: { eq: $urlKey } }) { - ...ProductSpecs - items { - __typename - uid - ...ProductWeight - ...ProductPageItem - } - } -} diff --git a/packages/magento-product/components/ProductSpecs/ProductSpecs.graphql b/packages/magento-product/components/ProductSpecs/ProductSpecs.graphql index 130f93aba23..787f8025073 100644 --- a/packages/magento-product/components/ProductSpecs/ProductSpecs.graphql +++ b/packages/magento-product/components/ProductSpecs/ProductSpecs.graphql @@ -1,31 +1,16 @@ -fragment ProductSpecs on Products { - aggregations @skip(if: $useCustomAttributes) { - attribute_code - count - label - options { - count - label - value - } - } - items { - __typename - uid - ...ProductListItem - custom_attributesV2(filters: { is_visible_on_front: true }) @include(if: $useCustomAttributes) { - items { - code - __typename - ... on AttributeValue { +fragment ProductSpecs on ProductInterface { + custom_attributesV2(filters: { is_visible_on_front: true }) @include(if: $useCustomAttributes) { + items { + code + __typename + ... on AttributeValue { + value + } + ... on AttributeSelectedOptions { + selected_options { + label value } - ... on AttributeSelectedOptions { - selected_options { - label - value - } - } } } } diff --git a/packages/magento-product/components/ProductSpecs/ProductSpecs.tsx b/packages/magento-product/components/ProductSpecs/ProductSpecs.tsx index 46cf82e37e1..acb2c13278b 100644 --- a/packages/magento-product/components/ProductSpecs/ProductSpecs.tsx +++ b/packages/magento-product/components/ProductSpecs/ProductSpecs.tsx @@ -1,27 +1,25 @@ +import { useQuery } from '@graphcommerce/graphql' import { responsiveVal, Row, SectionContainer, extendableComponent } from '@graphcommerce/next-ui' import { Box, SxProps, Theme } from '@mui/material' import { ProductSpecsFragment } from './ProductSpecs.gql' -import { ProductSpecsAggregations } from './ProductSpecsAggregations' -import { ProductSpecsCustomAttributes } from './ProductSpecsCustomAttributes' +import { ProductSpecsTypesDocument } from './ProductSpecsTypes.gql' -export type ProductSpecsProps = ProductSpecsFragment & { +export type ProductSpecsProps = { title?: string sx?: SxProps children?: React.ReactNode + product: ProductSpecsFragment } -const name = 'ProductSpecs' as const +const name = 'ProductSpecs' const parts = ['root', 'specs', 'options'] as const const { classes } = extendableComponent(name, parts) export function ProductSpecs(props: ProductSpecsProps) { - const { aggregations, items, title, children, sx = [] } = props - const filter = ['price', 'category_id', 'size', 'new', 'sale', 'color'] - const specs = aggregations?.filter( - (attr) => !filter.includes(attr?.attribute_code ?? '') && attr?.options?.[0]?.value !== '0', - ) + const { title, children, sx = [], product } = props - if (specs?.length === 0) return null + const specs = product.custom_attributesV2?.items + const productSpecsTypes = useQuery(ProductSpecsTypesDocument) return ( - {aggregations && } - {items && } + {specs?.map((item) => ( +
  • +
    + { + productSpecsTypes?.data?.attributesList?.items?.find( + (type) => type?.code === item?.code, + )?.label + } +
    + + {item?.__typename === 'AttributeSelectedOptions' && ( + <> + {item?.selected_options?.map((option) => ( + + {option?.label === '1' ? 'Yes' : option?.label} + + ))} + + )} + {item?.__typename === 'AttributeValue' && ( + {item.value} + )} + +
  • + ))}
    {children} diff --git a/packages/magento-product/components/ProductSpecs/ProductSpecsAggregations.tsx b/packages/magento-product/components/ProductSpecs/ProductSpecsAggregations.tsx deleted file mode 100644 index 7f813b68ff8..00000000000 --- a/packages/magento-product/components/ProductSpecs/ProductSpecsAggregations.tsx +++ /dev/null @@ -1,34 +0,0 @@ -import { extendableComponent } from '@graphcommerce/next-ui' -import { Box } from '@mui/material' -import { ProductSpecsFragment } from './ProductSpecs.gql' - -const name = 'ProductSpecs' as const -const parts = ['root', 'specs', 'options'] as const -const { classes } = extendableComponent(name, parts) - -export type ProductSpecsAggregationsProps = Pick - -export function ProductSpecsAggregations(props: ProductSpecsAggregationsProps) { - const { aggregations } = props - const filter = ['price', 'category_id', 'size', 'new', 'sale', 'color'] - const specs = aggregations?.filter( - (attr) => !filter.includes(attr?.attribute_code ?? '') && attr?.options?.[0]?.value !== '0', - ) - - if (specs?.length === 0) return null - - return ( - <> - {specs?.map((aggregation) => ( -
  • -
    {aggregation?.label}
    - - {aggregation?.options?.map((option) => ( - {option?.label === '1' ? 'Yes' : option?.label} - ))} - -
  • - ))} - - ) -} diff --git a/packages/magento-product/components/ProductSpecs/ProductSpecsCustomAttributes.tsx b/packages/magento-product/components/ProductSpecs/ProductSpecsCustomAttributes.tsx index 21002f0a09e..bb1752b7dc5 100644 --- a/packages/magento-product/components/ProductSpecs/ProductSpecsCustomAttributes.tsx +++ b/packages/magento-product/components/ProductSpecs/ProductSpecsCustomAttributes.tsx @@ -1,24 +1,22 @@ import { useQuery } from '@graphcommerce/graphql' import { extendableComponent } from '@graphcommerce/next-ui' import { Box } from '@mui/material' -import { ProductSpecsFragment } from './ProductSpecs.gql' +import { ProductSpecsCustomAttributesFragment } from './ProductSpecs.gql' import { ProductSpecsTypesDocument } from './ProductSpecsTypes.gql' -const name = 'ProductSpecs' as const +const name = 'ProductSpecs' const parts = ['root', 'specs', 'options'] as const const { classes } = extendableComponent(name, parts) -export type ProductSpecsCustomAttributesProps = Pick - -export function ProductSpecsCustomAttributes(props: ProductSpecsCustomAttributesProps) { - const { items } = props - - const specs = items?.[0]?.custom_attributesV2?.items +export type ProductSpecsCustomAttributesProps = { + product: ProductSpecsCustomAttributesFragment +} +export function ProductSpecs(props: ProductSpecsCustomAttributesProps) { + const { product } = props + const specs = product.custom_attributesV2?.items const productSpecsTypes = useQuery(ProductSpecsTypesDocument) - if (items?.length === 0) return null - return ( <> {specs?.map((item) => ( diff --git a/packagesDev/next-config/dist/generated/config.js b/packagesDev/next-config/dist/generated/config.js index ed5e13d1490..3242b348232 100644 --- a/packagesDev/next-config/dist/generated/config.js +++ b/packagesDev/next-config/dist/generated/config.js @@ -1,161 +1,110 @@ -/* eslint-disable */ "use strict"; -Object.defineProperty(exports, "__esModule", { - value: true -}); -function _export(target, all) { - for(var name in all)Object.defineProperty(target, name, { - enumerable: true, - get: all[name] - }); -} -_export(exports, { - CompareVariantSchema: function() { - return CompareVariantSchema; - }, - DatalayerConfigSchema: function() { - return DatalayerConfigSchema; - }, - GraphCommerceConfigSchema: function() { - return GraphCommerceConfigSchema; - }, - GraphCommerceDebugConfigSchema: function() { - return GraphCommerceDebugConfigSchema; - }, - GraphCommerceStorefrontConfigSchema: function() { - return GraphCommerceStorefrontConfigSchema; - }, - MagentoConfigurableVariantValuesSchema: function() { - return MagentoConfigurableVariantValuesSchema; - }, - PaginationVariantSchema: function() { - return PaginationVariantSchema; - }, - ProductFiltersLayoutSchema: function() { - return ProductFiltersLayoutSchema; - }, - RecentlyViewedProductsConfigSchema: function() { - return RecentlyViewedProductsConfigSchema; - }, - SidebarGalleryConfigSchema: function() { - return SidebarGalleryConfigSchema; - }, - SidebarGalleryPaginationVariantSchema: function() { - return SidebarGalleryPaginationVariantSchema; - }, - definedNonNullAnySchema: function() { - return definedNonNullAnySchema; - }, - isDefinedNonNullAny: function() { - return isDefinedNonNullAny; - } -}); -const _zod = require("zod"); -const isDefinedNonNullAny = (v)=>v !== undefined && v !== null; -const definedNonNullAnySchema = _zod.z.any().refine((v)=>isDefinedNonNullAny(v)); -const CompareVariantSchema = _zod.z.enum([ - 'CHECKBOX', - 'ICON' -]); -const PaginationVariantSchema = _zod.z.enum([ - 'COMPACT', - 'EXTENDED' -]); -const ProductFiltersLayoutSchema = _zod.z.enum([ - 'DEFAULT', - 'SIDEBAR' -]); -const SidebarGalleryPaginationVariantSchema = _zod.z.enum([ - 'DOTS', - 'THUMBNAILS_BOTTOM' -]); +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.SidebarGalleryPaginationVariantSchema = exports.ProductFiltersLayoutSchema = exports.PaginationVariantSchema = exports.CompareVariantSchema = exports.definedNonNullAnySchema = exports.isDefinedNonNullAny = void 0; +exports.DatalayerConfigSchema = DatalayerConfigSchema; +exports.GraphCommerceConfigSchema = GraphCommerceConfigSchema; +exports.GraphCommerceDebugConfigSchema = GraphCommerceDebugConfigSchema; +exports.GraphCommerceStorefrontConfigSchema = GraphCommerceStorefrontConfigSchema; +exports.MagentoConfigurableVariantValuesSchema = MagentoConfigurableVariantValuesSchema; +exports.RecentlyViewedProductsConfigSchema = RecentlyViewedProductsConfigSchema; +exports.SidebarGalleryConfigSchema = SidebarGalleryConfigSchema; +/* eslint-disable */ +const zod_1 = require("zod"); +const isDefinedNonNullAny = (v) => v !== undefined && v !== null; +exports.isDefinedNonNullAny = isDefinedNonNullAny; +exports.definedNonNullAnySchema = zod_1.z.any().refine((v) => (0, exports.isDefinedNonNullAny)(v)); +exports.CompareVariantSchema = zod_1.z.enum(['CHECKBOX', 'ICON']); +exports.PaginationVariantSchema = zod_1.z.enum(['COMPACT', 'EXTENDED']); +exports.ProductFiltersLayoutSchema = zod_1.z.enum(['DEFAULT', 'SIDEBAR']); +exports.SidebarGalleryPaginationVariantSchema = zod_1.z.enum(['DOTS', 'THUMBNAILS_BOTTOM']); function DatalayerConfigSchema() { - return _zod.z.object({ - coreWebVitals: _zod.z.boolean().nullish() + return zod_1.z.object({ + coreWebVitals: zod_1.z.boolean().nullish() }); } function GraphCommerceConfigSchema() { - return _zod.z.object({ - breadcrumbs: _zod.z.boolean().default(false).nullish(), - canonicalBaseUrl: _zod.z.string().min(1), - cartDisplayPricesInclTax: _zod.z.boolean().nullish(), - compare: _zod.z.boolean().nullish(), - compareVariant: CompareVariantSchema.default("ICON").nullish(), - configurableVariantForSimple: _zod.z.boolean().default(false).nullish(), + return zod_1.z.object({ + breadcrumbs: zod_1.z.boolean().default(false).nullish(), + canonicalBaseUrl: zod_1.z.string().min(1), + cartDisplayPricesInclTax: zod_1.z.boolean().nullish(), + compare: zod_1.z.boolean().nullish(), + compareVariant: exports.CompareVariantSchema.default("ICON").nullish(), + configurableVariantForSimple: zod_1.z.boolean().default(false).nullish(), configurableVariantValues: MagentoConfigurableVariantValuesSchema().nullish(), - crossSellsHideCartItems: _zod.z.boolean().default(false).nullish(), - crossSellsRedirectItems: _zod.z.boolean().default(false).nullish(), - customerAddressNoteEnable: _zod.z.boolean().nullish(), - customerCompanyFieldsEnable: _zod.z.boolean().nullish(), - customerDeleteEnabled: _zod.z.boolean().nullish(), - customerXMagentoCacheIdDisable: _zod.z.boolean().nullish(), + crossSellsHideCartItems: zod_1.z.boolean().default(false).nullish(), + crossSellsRedirectItems: zod_1.z.boolean().default(false).nullish(), + customerAddressNoteEnable: zod_1.z.boolean().nullish(), + customerCompanyFieldsEnable: zod_1.z.boolean().nullish(), + customerDeleteEnabled: zod_1.z.boolean().nullish(), + customerXMagentoCacheIdDisable: zod_1.z.boolean().nullish(), dataLayer: DatalayerConfigSchema().nullish(), debug: GraphCommerceDebugConfigSchema().nullish(), - demoMode: _zod.z.boolean().default(true).nullish(), - enableGuestCheckoutLogin: _zod.z.boolean().nullish(), - googleAnalyticsId: _zod.z.string().nullish(), - googleRecaptchaKey: _zod.z.string().nullish(), - googleTagmanagerId: _zod.z.string().nullish(), - hygraphEndpoint: _zod.z.string().min(1), - hygraphManagementApi: _zod.z.string().nullish(), - hygraphProjectId: _zod.z.string().nullish(), - hygraphWriteAccessEndpoint: _zod.z.string().nullish(), - hygraphWriteAccessToken: _zod.z.string().nullish(), - limitSsg: _zod.z.boolean().nullish(), - magentoEndpoint: _zod.z.string().min(1), - magentoVersion: _zod.z.number(), - previewSecret: _zod.z.string().nullish(), - productFiltersLayout: ProductFiltersLayoutSchema.default("DEFAULT").nullish(), - productFiltersPro: _zod.z.boolean().nullish(), - productListPaginationVariant: PaginationVariantSchema.default("COMPACT").nullish(), - productRoute: _zod.z.string().nullish(), + demoMode: zod_1.z.boolean().default(true).nullish(), + enableGuestCheckoutLogin: zod_1.z.boolean().nullish(), + googleAnalyticsId: zod_1.z.string().nullish(), + googleRecaptchaKey: zod_1.z.string().nullish(), + googleTagmanagerId: zod_1.z.string().nullish(), + hygraphEndpoint: zod_1.z.string().min(1), + hygraphManagementApi: zod_1.z.string().nullish(), + hygraphProjectId: zod_1.z.string().nullish(), + hygraphWriteAccessEndpoint: zod_1.z.string().nullish(), + hygraphWriteAccessToken: zod_1.z.string().nullish(), + limitSsg: zod_1.z.boolean().nullish(), + magentoEndpoint: zod_1.z.string().min(1), + magentoVersion: zod_1.z.number(), + previewSecret: zod_1.z.string().nullish(), + productFiltersLayout: exports.ProductFiltersLayoutSchema.default("DEFAULT").nullish(), + productFiltersPro: zod_1.z.boolean().nullish(), + productListPaginationVariant: exports.PaginationVariantSchema.default("COMPACT").nullish(), + productRoute: zod_1.z.string().nullish(), recentlyViewedProducts: RecentlyViewedProductsConfigSchema().nullish(), - robotsAllow: _zod.z.boolean().nullish(), + robotsAllow: zod_1.z.boolean().nullish(), sidebarGallery: SidebarGalleryConfigSchema().nullish(), - storefront: _zod.z.array(GraphCommerceStorefrontConfigSchema()), - wishlistHideForGuests: _zod.z.boolean().nullish(), - wishlistShowFeedbackMessage: _zod.z.boolean().nullish() + storefront: zod_1.z.array(GraphCommerceStorefrontConfigSchema()), + wishlistHideForGuests: zod_1.z.boolean().nullish(), + wishlistShowFeedbackMessage: zod_1.z.boolean().nullish() }); } function GraphCommerceDebugConfigSchema() { - return _zod.z.object({ - pluginStatus: _zod.z.boolean().nullish(), - sessions: _zod.z.boolean().nullish(), - webpackCircularDependencyPlugin: _zod.z.boolean().nullish(), - webpackDuplicatesPlugin: _zod.z.boolean().nullish() + return zod_1.z.object({ + pluginStatus: zod_1.z.boolean().nullish(), + sessions: zod_1.z.boolean().nullish(), + webpackCircularDependencyPlugin: zod_1.z.boolean().nullish(), + webpackDuplicatesPlugin: zod_1.z.boolean().nullish() }); } function GraphCommerceStorefrontConfigSchema() { - return _zod.z.object({ - canonicalBaseUrl: _zod.z.string().nullish(), - cartDisplayPricesInclTax: _zod.z.boolean().nullish(), - customerCompanyFieldsEnable: _zod.z.boolean().nullish(), - defaultLocale: _zod.z.boolean().nullish(), - domain: _zod.z.string().nullish(), - googleAnalyticsId: _zod.z.string().nullish(), - googleRecaptchaKey: _zod.z.string().nullish(), - googleTagmanagerId: _zod.z.string().nullish(), - hygraphLocales: _zod.z.array(_zod.z.string().min(1)).nullish(), - linguiLocale: _zod.z.string().nullish(), - locale: _zod.z.string().min(1), - magentoStoreCode: _zod.z.string().min(1), - robotsAllow: _zod.z.boolean().nullish() + return zod_1.z.object({ + canonicalBaseUrl: zod_1.z.string().nullish(), + cartDisplayPricesInclTax: zod_1.z.boolean().nullish(), + customerCompanyFieldsEnable: zod_1.z.boolean().nullish(), + defaultLocale: zod_1.z.boolean().nullish(), + domain: zod_1.z.string().nullish(), + googleAnalyticsId: zod_1.z.string().nullish(), + googleRecaptchaKey: zod_1.z.string().nullish(), + googleTagmanagerId: zod_1.z.string().nullish(), + hygraphLocales: zod_1.z.array(zod_1.z.string().min(1)).nullish(), + linguiLocale: zod_1.z.string().nullish(), + locale: zod_1.z.string().min(1), + magentoStoreCode: zod_1.z.string().min(1), + robotsAllow: zod_1.z.boolean().nullish() }); } function MagentoConfigurableVariantValuesSchema() { - return _zod.z.object({ - content: _zod.z.boolean().nullish(), - gallery: _zod.z.boolean().nullish(), - url: _zod.z.boolean().nullish() + return zod_1.z.object({ + content: zod_1.z.boolean().nullish(), + gallery: zod_1.z.boolean().nullish(), + url: zod_1.z.boolean().nullish() }); } function RecentlyViewedProductsConfigSchema() { - return _zod.z.object({ - enabled: _zod.z.boolean().nullish(), - maxCount: _zod.z.number().nullish() + return zod_1.z.object({ + enabled: zod_1.z.boolean().nullish(), + maxCount: zod_1.z.number().nullish() }); } function SidebarGalleryConfigSchema() { - return _zod.z.object({ - paginationVariant: SidebarGalleryPaginationVariantSchema.nullish() + return zod_1.z.object({ + paginationVariant: exports.SidebarGalleryPaginationVariantSchema.nullish() }); } From fcde483956312714dda732dabcd446b688bbbf86 Mon Sep 17 00:00:00 2001 From: Paul Hachmang Date: Wed, 7 Aug 2024 15:21:11 +0200 Subject: [PATCH 29/33] Added Row Product Page to Hygraph --- packages/hygraph-cli/Config.graphqls | 8 - .../dist/migrations/graphcommerce8to9.js | 56 ++++- packages/hygraph-cli/dist/utils/getConfig.js | 2 +- .../src/migrations/graphcommerce8to9.ts | 74 +++++- packages/hygraph-cli/src/utils/getConfig.ts | 2 +- .../__snapshots__/mergeEnvIntoConfig.ts.snap | 1 - .../next-config/dist/generated/config.js | 217 +++++++++++------- .../next-config/src/generated/config.ts | 8 - 8 files changed, 261 insertions(+), 107 deletions(-) diff --git a/packages/hygraph-cli/Config.graphqls b/packages/hygraph-cli/Config.graphqls index b44c3dbb15b..916454f9194 100644 --- a/packages/hygraph-cli/Config.graphqls +++ b/packages/hygraph-cli/Config.graphqls @@ -38,12 +38,4 @@ extend input GraphCommerceConfig { API', this field is not required. """ hygraphProjectId: String - - """ - Hygraph Management API. **Only used for migrations.** - - Optional: If the hygraphEndpoint is configured with the 'High Performance Content - API', this field is not required. - """ - hygraphManagementApi: String } diff --git a/packages/hygraph-cli/dist/migrations/graphcommerce8to9.js b/packages/hygraph-cli/dist/migrations/graphcommerce8to9.js index 45cd2866f87..1396ab4a800 100644 --- a/packages/hygraph-cli/dist/migrations/graphcommerce8to9.js +++ b/packages/hygraph-cli/dist/migrations/graphcommerce8to9.js @@ -16,12 +16,11 @@ const graphcommerce8to9 = async (schema, client) => { }); } const hasRowCategory = schema.models.some((m) => m.apiId === 'RowCategory'); - // if (!hasRowCategory) { migrationAction(schema, 'model', 'create', { apiId: 'RowCategory', displayName: 'Row Category', - apiIdPlural: 'RowProductLists', + apiIdPlural: 'RowCategories', description: 'A model that displays a category', }); migrationAction(schema, 'simpleField', 'create', { @@ -63,6 +62,59 @@ const graphcommerce8to9 = async (schema, client) => { isRequired: true, }, 'RowCategory', 'model'); } + const hasRowProductPage = schema.models.some((m) => m.apiId === 'RowProductPage'); + if (!hasRowProductPage) { + migrationAction(schema, 'model', 'create', { + apiId: 'RowProductPage', + apiIdPlural: 'RowProductPageItems', + displayName: 'Row Product Page', + description: 'A model to display related product information on the product page', + }); + migrationAction(schema, 'enumeration', 'create', { + displayName: 'Row Product Page Variant', + apiId: 'RowProductPageVariant', + values: [ + { displayName: 'Reviews', apiId: 'Reviews' }, + { displayName: 'Upsells', apiId: 'Upsells' }, + { displayName: 'Related', apiId: 'Related' }, + { displayName: 'Specs', apiId: 'Specs' }, + { displayName: 'Usps', apiId: 'Usps' }, + ], + }); + migrationAction(schema, 'enumerableField', 'create', { + displayName: 'Variant', + apiId: 'variant', + parentApiId: 'RowProductPage', + enumerationApiId: 'RowProductPageVariant', + description: 'As what variant wil the RowProductPage be displayed', + isRequired: true, + }, 'RowProductPage', 'model'); + migrationAction(schema, 'unionField', 'update', { + apiId: 'content', + displayName: 'Content', + modelApiId: 'Page', + reverseField: { + modelApiIds: [ + 'RowLinks', + 'RowServiceOptions', + 'RowSpecialBanner', + 'RowQuote', + 'RowProduct', + 'RowColumnOne', + 'RowColumnTwo', + 'RowColumnThree', + 'RowHeroBanner', + 'RowBlogContent', + 'RowButtonList', + 'RowContentLinks', + 'RowButtonLinkList', + 'RowCategory', + 'RowProductPage', + ], + // visibility: VisibilityTypes.Hidden, => Currently not supported for updateUnionField | https://github.com/hygraph/management-sdk/issues/34 + }, + }, 'Page', 'model'); + } return client.run(true); }; exports.graphcommerce8to9 = graphcommerce8to9; diff --git a/packages/hygraph-cli/dist/utils/getConfig.js b/packages/hygraph-cli/dist/utils/getConfig.js index 3279435dc73..b2b543b6b95 100644 --- a/packages/hygraph-cli/dist/utils/getConfig.js +++ b/packages/hygraph-cli/dist/utils/getConfig.js @@ -7,7 +7,7 @@ function getConfig(config) { throw new Error('Please provide GC_HYGRAPH_WRITE_ACCESS_TOKEN in your env file.'); } if (!projectId) { - projectId = new URL(hygraphEndpoint).pathname.split('/')?.[1]; + throw new Error('Please provide GC_HYGRAPH_PROJECT_ID in your env file.'); } if (!uri) { const endpoint = new URL(hygraphEndpoint); diff --git a/packages/hygraph-cli/src/migrations/graphcommerce8to9.ts b/packages/hygraph-cli/src/migrations/graphcommerce8to9.ts index 7f274e6d4b5..23de6684fc9 100644 --- a/packages/hygraph-cli/src/migrations/graphcommerce8to9.ts +++ b/packages/hygraph-cli/src/migrations/graphcommerce8to9.ts @@ -26,12 +26,11 @@ export const graphcommerce8to9: MigrationFunction = async (schema, client) => { const hasRowCategory = schema.models.some((m) => m.apiId === 'RowCategory') - // if (!hasRowCategory) { migrationAction(schema, 'model', 'create', { apiId: 'RowCategory', displayName: 'Row Category', - apiIdPlural: 'RowProductLists', + apiIdPlural: 'RowCategories', description: 'A model that displays a category', } satisfies BatchMigrationCreateModelInput) @@ -91,5 +90,76 @@ export const graphcommerce8to9: MigrationFunction = async (schema, client) => { ) } + const hasRowProductPage = schema.models.some((m) => m.apiId === 'RowProductPage') + if (!hasRowProductPage) { + migrationAction(schema, 'model', 'create', { + apiId: 'RowProductPage', + apiIdPlural: 'RowProductPageItems', + displayName: 'Row Product Page', + description: 'A model to display related product information on the product page', + } satisfies BatchMigrationCreateModelInput) + + migrationAction(schema, 'enumeration', 'create', { + displayName: 'Row Product Page Variant', + apiId: 'RowProductPageVariant', + values: [ + { displayName: 'Reviews', apiId: 'Reviews' }, + { displayName: 'Upsells', apiId: 'Upsells' }, + { displayName: 'Related', apiId: 'Related' }, + { displayName: 'Specs', apiId: 'Specs' }, + { displayName: 'Usps', apiId: 'Usps' }, + ], + } satisfies BatchMigrationCreateEnumerationInput) + + migrationAction( + schema, + 'enumerableField', + 'create', + { + displayName: 'Variant', + apiId: 'variant', + parentApiId: 'RowProductPage', + enumerationApiId: 'RowProductPageVariant', + description: 'As what variant wil the RowProductPage be displayed', + isRequired: true, + } satisfies BatchMigrationCreateEnumerableFieldInput, + 'RowProductPage', + 'model', + ) + + migrationAction( + schema, + 'unionField', + 'update', + { + apiId: 'content', + displayName: 'Content', + modelApiId: 'Page', + reverseField: { + modelApiIds: [ + 'RowLinks', + 'RowServiceOptions', + 'RowSpecialBanner', + 'RowQuote', + 'RowProduct', + 'RowColumnOne', + 'RowColumnTwo', + 'RowColumnThree', + 'RowHeroBanner', + 'RowBlogContent', + 'RowButtonList', + 'RowContentLinks', + 'RowButtonLinkList', + 'RowCategory', + 'RowProductPage', + ], + // visibility: VisibilityTypes.Hidden, => Currently not supported for updateUnionField | https://github.com/hygraph/management-sdk/issues/34 + }, + }, + 'Page', + 'model', + ) + } + return client.run(true) } diff --git a/packages/hygraph-cli/src/utils/getConfig.ts b/packages/hygraph-cli/src/utils/getConfig.ts index b93059ece47..7da0449fe1b 100644 --- a/packages/hygraph-cli/src/utils/getConfig.ts +++ b/packages/hygraph-cli/src/utils/getConfig.ts @@ -19,7 +19,7 @@ export function getConfig(config: GraphCommerceConfig) { } if (!projectId) { - projectId = new URL(hygraphEndpoint).pathname.split('/')?.[1] + throw new Error('Please provide GC_HYGRAPH_PROJECT_ID in your env file.') } if (!uri) { diff --git a/packagesDev/next-config/__tests__/config/utils/__snapshots__/mergeEnvIntoConfig.ts.snap b/packagesDev/next-config/__tests__/config/utils/__snapshots__/mergeEnvIntoConfig.ts.snap index daa2373815c..69ffe1f65dc 100644 --- a/packagesDev/next-config/__tests__/config/utils/__snapshots__/mergeEnvIntoConfig.ts.snap +++ b/packagesDev/next-config/__tests__/config/utils/__snapshots__/mergeEnvIntoConfig.ts.snap @@ -54,7 +54,6 @@ exports[`traverses a schema and returns a list of env variables that match 1`] = "GC_GOOGLE_RECAPTCHA_KEY", "GC_GOOGLE_TAGMANAGER_ID", "GC_HYGRAPH_ENDPOINT", - "GC_HYGRAPH_MANAGEMENT_API", "GC_HYGRAPH_PROJECT_ID", "GC_HYGRAPH_WRITE_ACCESS_TOKEN", "GC_LIMIT_SSG", diff --git a/packagesDev/next-config/dist/generated/config.js b/packagesDev/next-config/dist/generated/config.js index 3242b348232..50d56ccfdea 100644 --- a/packagesDev/next-config/dist/generated/config.js +++ b/packagesDev/next-config/dist/generated/config.js @@ -1,110 +1,159 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.SidebarGalleryPaginationVariantSchema = exports.ProductFiltersLayoutSchema = exports.PaginationVariantSchema = exports.CompareVariantSchema = exports.definedNonNullAnySchema = exports.isDefinedNonNullAny = void 0; -exports.DatalayerConfigSchema = DatalayerConfigSchema; -exports.GraphCommerceConfigSchema = GraphCommerceConfigSchema; -exports.GraphCommerceDebugConfigSchema = GraphCommerceDebugConfigSchema; -exports.GraphCommerceStorefrontConfigSchema = GraphCommerceStorefrontConfigSchema; -exports.MagentoConfigurableVariantValuesSchema = MagentoConfigurableVariantValuesSchema; -exports.RecentlyViewedProductsConfigSchema = RecentlyViewedProductsConfigSchema; -exports.SidebarGalleryConfigSchema = SidebarGalleryConfigSchema; -/* eslint-disable */ -const zod_1 = require("zod"); -const isDefinedNonNullAny = (v) => v !== undefined && v !== null; -exports.isDefinedNonNullAny = isDefinedNonNullAny; -exports.definedNonNullAnySchema = zod_1.z.any().refine((v) => (0, exports.isDefinedNonNullAny)(v)); -exports.CompareVariantSchema = zod_1.z.enum(['CHECKBOX', 'ICON']); -exports.PaginationVariantSchema = zod_1.z.enum(['COMPACT', 'EXTENDED']); -exports.ProductFiltersLayoutSchema = zod_1.z.enum(['DEFAULT', 'SIDEBAR']); -exports.SidebarGalleryPaginationVariantSchema = zod_1.z.enum(['DOTS', 'THUMBNAILS_BOTTOM']); +/* eslint-disable */ "use strict"; +Object.defineProperty(exports, "__esModule", { + value: true +}); +function _export(target, all) { + for(var name in all)Object.defineProperty(target, name, { + enumerable: true, + get: all[name] + }); +} +_export(exports, { + CompareVariantSchema: function() { + return CompareVariantSchema; + }, + DatalayerConfigSchema: function() { + return DatalayerConfigSchema; + }, + GraphCommerceConfigSchema: function() { + return GraphCommerceConfigSchema; + }, + GraphCommerceDebugConfigSchema: function() { + return GraphCommerceDebugConfigSchema; + }, + GraphCommerceStorefrontConfigSchema: function() { + return GraphCommerceStorefrontConfigSchema; + }, + MagentoConfigurableVariantValuesSchema: function() { + return MagentoConfigurableVariantValuesSchema; + }, + PaginationVariantSchema: function() { + return PaginationVariantSchema; + }, + ProductFiltersLayoutSchema: function() { + return ProductFiltersLayoutSchema; + }, + RecentlyViewedProductsConfigSchema: function() { + return RecentlyViewedProductsConfigSchema; + }, + SidebarGalleryConfigSchema: function() { + return SidebarGalleryConfigSchema; + }, + SidebarGalleryPaginationVariantSchema: function() { + return SidebarGalleryPaginationVariantSchema; + }, + definedNonNullAnySchema: function() { + return definedNonNullAnySchema; + }, + isDefinedNonNullAny: function() { + return isDefinedNonNullAny; + } +}); +const _zod = require("zod"); +const isDefinedNonNullAny = (v)=>v !== undefined && v !== null; +const definedNonNullAnySchema = _zod.z.any().refine((v)=>isDefinedNonNullAny(v)); +const CompareVariantSchema = _zod.z.enum([ + 'CHECKBOX', + 'ICON' +]); +const PaginationVariantSchema = _zod.z.enum([ + 'COMPACT', + 'EXTENDED' +]); +const ProductFiltersLayoutSchema = _zod.z.enum([ + 'DEFAULT', + 'SIDEBAR' +]); +const SidebarGalleryPaginationVariantSchema = _zod.z.enum([ + 'DOTS', + 'THUMBNAILS_BOTTOM' +]); function DatalayerConfigSchema() { - return zod_1.z.object({ - coreWebVitals: zod_1.z.boolean().nullish() + return _zod.z.object({ + coreWebVitals: _zod.z.boolean().nullish() }); } function GraphCommerceConfigSchema() { - return zod_1.z.object({ - breadcrumbs: zod_1.z.boolean().default(false).nullish(), - canonicalBaseUrl: zod_1.z.string().min(1), - cartDisplayPricesInclTax: zod_1.z.boolean().nullish(), - compare: zod_1.z.boolean().nullish(), - compareVariant: exports.CompareVariantSchema.default("ICON").nullish(), - configurableVariantForSimple: zod_1.z.boolean().default(false).nullish(), + return _zod.z.object({ + breadcrumbs: _zod.z.boolean().default(false).nullish(), + canonicalBaseUrl: _zod.z.string().min(1), + cartDisplayPricesInclTax: _zod.z.boolean().nullish(), + compare: _zod.z.boolean().nullish(), + compareVariant: CompareVariantSchema.default("ICON").nullish(), + configurableVariantForSimple: _zod.z.boolean().default(false).nullish(), configurableVariantValues: MagentoConfigurableVariantValuesSchema().nullish(), - crossSellsHideCartItems: zod_1.z.boolean().default(false).nullish(), - crossSellsRedirectItems: zod_1.z.boolean().default(false).nullish(), - customerAddressNoteEnable: zod_1.z.boolean().nullish(), - customerCompanyFieldsEnable: zod_1.z.boolean().nullish(), - customerDeleteEnabled: zod_1.z.boolean().nullish(), - customerXMagentoCacheIdDisable: zod_1.z.boolean().nullish(), + crossSellsHideCartItems: _zod.z.boolean().default(false).nullish(), + crossSellsRedirectItems: _zod.z.boolean().default(false).nullish(), + customerAddressNoteEnable: _zod.z.boolean().nullish(), + customerCompanyFieldsEnable: _zod.z.boolean().nullish(), + customerDeleteEnabled: _zod.z.boolean().nullish(), + customerXMagentoCacheIdDisable: _zod.z.boolean().nullish(), dataLayer: DatalayerConfigSchema().nullish(), debug: GraphCommerceDebugConfigSchema().nullish(), - demoMode: zod_1.z.boolean().default(true).nullish(), - enableGuestCheckoutLogin: zod_1.z.boolean().nullish(), - googleAnalyticsId: zod_1.z.string().nullish(), - googleRecaptchaKey: zod_1.z.string().nullish(), - googleTagmanagerId: zod_1.z.string().nullish(), - hygraphEndpoint: zod_1.z.string().min(1), - hygraphManagementApi: zod_1.z.string().nullish(), - hygraphProjectId: zod_1.z.string().nullish(), - hygraphWriteAccessEndpoint: zod_1.z.string().nullish(), - hygraphWriteAccessToken: zod_1.z.string().nullish(), - limitSsg: zod_1.z.boolean().nullish(), - magentoEndpoint: zod_1.z.string().min(1), - magentoVersion: zod_1.z.number(), - previewSecret: zod_1.z.string().nullish(), - productFiltersLayout: exports.ProductFiltersLayoutSchema.default("DEFAULT").nullish(), - productFiltersPro: zod_1.z.boolean().nullish(), - productListPaginationVariant: exports.PaginationVariantSchema.default("COMPACT").nullish(), - productRoute: zod_1.z.string().nullish(), + demoMode: _zod.z.boolean().default(true).nullish(), + enableGuestCheckoutLogin: _zod.z.boolean().nullish(), + googleAnalyticsId: _zod.z.string().nullish(), + googleRecaptchaKey: _zod.z.string().nullish(), + googleTagmanagerId: _zod.z.string().nullish(), + hygraphEndpoint: _zod.z.string().min(1), + hygraphProjectId: _zod.z.string().nullish(), + hygraphWriteAccessToken: _zod.z.string().nullish(), + limitSsg: _zod.z.boolean().nullish(), + magentoEndpoint: _zod.z.string().min(1), + magentoVersion: _zod.z.number(), + previewSecret: _zod.z.string().nullish(), + productFiltersLayout: ProductFiltersLayoutSchema.default("DEFAULT").nullish(), + productFiltersPro: _zod.z.boolean().nullish(), + productListPaginationVariant: PaginationVariantSchema.default("COMPACT").nullish(), + productRoute: _zod.z.string().nullish(), recentlyViewedProducts: RecentlyViewedProductsConfigSchema().nullish(), - robotsAllow: zod_1.z.boolean().nullish(), + robotsAllow: _zod.z.boolean().nullish(), sidebarGallery: SidebarGalleryConfigSchema().nullish(), - storefront: zod_1.z.array(GraphCommerceStorefrontConfigSchema()), - wishlistHideForGuests: zod_1.z.boolean().nullish(), - wishlistShowFeedbackMessage: zod_1.z.boolean().nullish() + storefront: _zod.z.array(GraphCommerceStorefrontConfigSchema()), + wishlistHideForGuests: _zod.z.boolean().nullish(), + wishlistShowFeedbackMessage: _zod.z.boolean().nullish() }); } function GraphCommerceDebugConfigSchema() { - return zod_1.z.object({ - pluginStatus: zod_1.z.boolean().nullish(), - sessions: zod_1.z.boolean().nullish(), - webpackCircularDependencyPlugin: zod_1.z.boolean().nullish(), - webpackDuplicatesPlugin: zod_1.z.boolean().nullish() + return _zod.z.object({ + pluginStatus: _zod.z.boolean().nullish(), + sessions: _zod.z.boolean().nullish(), + webpackCircularDependencyPlugin: _zod.z.boolean().nullish(), + webpackDuplicatesPlugin: _zod.z.boolean().nullish() }); } function GraphCommerceStorefrontConfigSchema() { - return zod_1.z.object({ - canonicalBaseUrl: zod_1.z.string().nullish(), - cartDisplayPricesInclTax: zod_1.z.boolean().nullish(), - customerCompanyFieldsEnable: zod_1.z.boolean().nullish(), - defaultLocale: zod_1.z.boolean().nullish(), - domain: zod_1.z.string().nullish(), - googleAnalyticsId: zod_1.z.string().nullish(), - googleRecaptchaKey: zod_1.z.string().nullish(), - googleTagmanagerId: zod_1.z.string().nullish(), - hygraphLocales: zod_1.z.array(zod_1.z.string().min(1)).nullish(), - linguiLocale: zod_1.z.string().nullish(), - locale: zod_1.z.string().min(1), - magentoStoreCode: zod_1.z.string().min(1), - robotsAllow: zod_1.z.boolean().nullish() + return _zod.z.object({ + canonicalBaseUrl: _zod.z.string().nullish(), + cartDisplayPricesInclTax: _zod.z.boolean().nullish(), + customerCompanyFieldsEnable: _zod.z.boolean().nullish(), + defaultLocale: _zod.z.boolean().nullish(), + domain: _zod.z.string().nullish(), + googleAnalyticsId: _zod.z.string().nullish(), + googleRecaptchaKey: _zod.z.string().nullish(), + googleTagmanagerId: _zod.z.string().nullish(), + hygraphLocales: _zod.z.array(_zod.z.string().min(1)).nullish(), + linguiLocale: _zod.z.string().nullish(), + locale: _zod.z.string().min(1), + magentoStoreCode: _zod.z.string().min(1), + robotsAllow: _zod.z.boolean().nullish() }); } function MagentoConfigurableVariantValuesSchema() { - return zod_1.z.object({ - content: zod_1.z.boolean().nullish(), - gallery: zod_1.z.boolean().nullish(), - url: zod_1.z.boolean().nullish() + return _zod.z.object({ + content: _zod.z.boolean().nullish(), + gallery: _zod.z.boolean().nullish(), + url: _zod.z.boolean().nullish() }); } function RecentlyViewedProductsConfigSchema() { - return zod_1.z.object({ - enabled: zod_1.z.boolean().nullish(), - maxCount: zod_1.z.number().nullish() + return _zod.z.object({ + enabled: _zod.z.boolean().nullish(), + maxCount: _zod.z.number().nullish() }); } function SidebarGalleryConfigSchema() { - return zod_1.z.object({ - paginationVariant: exports.SidebarGalleryPaginationVariantSchema.nullish() + return _zod.z.object({ + paginationVariant: SidebarGalleryPaginationVariantSchema.nullish() }); } diff --git a/packagesDev/next-config/src/generated/config.ts b/packagesDev/next-config/src/generated/config.ts index b2b61aaccdc..ab5075117ac 100644 --- a/packagesDev/next-config/src/generated/config.ts +++ b/packagesDev/next-config/src/generated/config.ts @@ -229,13 +229,6 @@ export type GraphCommerceConfig = { * Project settings -> API Access -> High Performance Read-only Content API */ hygraphEndpoint: Scalars['String']['input']; - /** - * Hygraph Management API. **Only used for migrations.** - * - * Optional: If the hygraphEndpoint is configured with the 'High Performance Content - * API', this field is not required. - */ - hygraphManagementApi?: InputMaybe; /** * Hygraph Project ID. **Only used for migrations.** * @@ -514,7 +507,6 @@ export function GraphCommerceConfigSchema(): z.ZodObject Date: Thu, 8 Aug 2024 13:05:53 +0200 Subject: [PATCH 30/33] Futher refactoring --- docs/framework/config.md | 7 -- docs/hygraph/cli.md | 26 ++---- ...ph.graphql => GcPage_Data_Hygraph.graphql} | 3 +- .../RowProduct/GetMagentoRowProduct.graphql | 4 +- .../GraphCMS/RowProduct/RowProduct.tsx | 20 ++--- .../GraphCMS/RowProduct/RowProductPage.tsx | 40 +++++++++ .../GcPageProductRows_RowProduct.graphql | 7 ++ .../graphql/GcPageProduct_RowProduct.graphql | 6 ++ .../graphql/GcPageRows_RowProduct.graphql | 4 + .../graphql/GcPage_RowProduct.graphql | 6 ++ .../{ => graphql}/RowProduct.graphql | 3 +- .../graphql/RowProduct_ProductPage.graphql | 6 ++ .../GraphCMS/RowProduct/variant/Backstory.tsx | 2 +- .../GraphCMS/RowProduct/variant/Feature.tsx | 4 +- .../RowProduct/variant/FeatureBoxed.tsx | 2 +- .../variant/Related.tsx | 6 +- .../variant/Reviews.tsx | 6 +- .../variant/Specs.tsx | 4 +- .../variant/Upsells.tsx | 4 +- .../GetMagentoRowProductPage.graphql | 14 --- .../RowProductPage/RowProductPage.graphql | 20 ----- .../RowProductPage/RowProductPage.tsx | 87 ------------------- .../GraphCMS/RowProductPage/variant/index.tsx | 4 - .../graphql/ProductPage2.graphql | 13 +-- examples/magento-graphcms/pages/p/[url].tsx | 23 ++--- .../plugins/hygraph/HygraphGcPageRows.tsx | 45 +++++++++- .../components/PreviewMode/PreviewMode.tsx | 9 +- .../components/ContentArea/Areas.tsx | 8 -- .../components/ContentArea/index.ts | 2 - .../GcPage}/GcPage.graphql | 3 +- .../{ContentArea => GcPage}/GcPageRows.tsx | 17 ++-- .../GcPage/GcPage_Data.graphql} | 3 +- .../GcPage/GcPage_Product_Data.graphql | 4 + .../graphql-gc-api/components/GcPage/index.ts | 4 + .../components/GcPageMeta/GcPageHead.tsx | 6 +- .../GcPageMeta}/GcPage_Head.graphql | 0 .../GcPageProduct/GcPageProduct.graphql | 7 ++ .../GcPageProduct/GcPageProductRows.tsx | 38 ++++++++ .../GcPageProduct/GcPageProduct_Data.graphql | 4 + .../GcPageProduct_Product_Data.graphql | 4 + .../components/GcPageProduct/index.ts | 2 + packages/graphql-gc-api/components/index.ts | 3 +- packages/graphql-gc-api/index.ts | 3 +- packages/graphql-gc-api/queries/index.ts | 4 - .../GcPage_Redirect.graphql | 0 ...eResult.ts => gcPageRedirectOrNotFound.ts} | 2 +- packages/graphql-gc-api/utils/index.ts | 2 + .../GraphQLProvider/measurePerformanceLink.ts | 77 +++++++++------- packages/graphql/hooks/useInContextQuery.ts | 2 +- .../dist/migrations/graphcommerce8to9.js | 53 ----------- .../src/migrations/graphcommerce8to9.ts | 71 --------------- packages/hygraph-ui/mesh/resolvers.ts | 53 +++++++---- .../magento-product-configurable/index.ts | 1 - .../ProductSpecs/ProductSpecs.graphql | 2 +- .../ProductSpecsCustomAttributes.tsx | 45 ---------- .../ProductReviews/ProductReviews.graphql | 2 +- 56 files changed, 329 insertions(+), 468 deletions(-) rename examples/magento-graphcms/components/GraphCMS/{GcPage_Rows_Hygraph.graphql => GcPage_Data_Hygraph.graphql} (77%) create mode 100644 examples/magento-graphcms/components/GraphCMS/RowProduct/RowProductPage.tsx create mode 100644 examples/magento-graphcms/components/GraphCMS/RowProduct/graphql/GcPageProductRows_RowProduct.graphql create mode 100644 examples/magento-graphcms/components/GraphCMS/RowProduct/graphql/GcPageProduct_RowProduct.graphql create mode 100644 examples/magento-graphcms/components/GraphCMS/RowProduct/graphql/GcPageRows_RowProduct.graphql create mode 100644 examples/magento-graphcms/components/GraphCMS/RowProduct/graphql/GcPage_RowProduct.graphql rename examples/magento-graphcms/components/GraphCMS/RowProduct/{ => graphql}/RowProduct.graphql (75%) create mode 100644 examples/magento-graphcms/components/GraphCMS/RowProduct/graphql/RowProduct_ProductPage.graphql rename examples/magento-graphcms/components/GraphCMS/{RowProductPage => RowProduct}/variant/Related.tsx (79%) rename examples/magento-graphcms/components/GraphCMS/{RowProductPage => RowProduct}/variant/Reviews.tsx (89%) rename examples/magento-graphcms/components/GraphCMS/{RowProductPage => RowProduct}/variant/Specs.tsx (64%) rename examples/magento-graphcms/components/GraphCMS/{RowProductPage => RowProduct}/variant/Upsells.tsx (86%) delete mode 100644 examples/magento-graphcms/components/GraphCMS/RowProductPage/GetMagentoRowProductPage.graphql delete mode 100644 examples/magento-graphcms/components/GraphCMS/RowProductPage/RowProductPage.graphql delete mode 100644 examples/magento-graphcms/components/GraphCMS/RowProductPage/RowProductPage.tsx delete mode 100644 examples/magento-graphcms/components/GraphCMS/RowProductPage/variant/index.tsx delete mode 100644 packages/graphql-gc-api/components/ContentArea/Areas.tsx delete mode 100644 packages/graphql-gc-api/components/ContentArea/index.ts rename packages/graphql-gc-api/{queries => components/GcPage}/GcPage.graphql (72%) rename packages/graphql-gc-api/components/{ContentArea => GcPage}/GcPageRows.tsx (50%) rename packages/graphql-gc-api/{queries/GcPage_Rows.graphql => components/GcPage/GcPage_Data.graphql} (57%) create mode 100644 packages/graphql-gc-api/components/GcPage/GcPage_Product_Data.graphql create mode 100644 packages/graphql-gc-api/components/GcPage/index.ts rename packages/graphql-gc-api/{queries => components/GcPageMeta}/GcPage_Head.graphql (100%) create mode 100644 packages/graphql-gc-api/components/GcPageProduct/GcPageProduct.graphql create mode 100644 packages/graphql-gc-api/components/GcPageProduct/GcPageProductRows.tsx create mode 100644 packages/graphql-gc-api/components/GcPageProduct/GcPageProduct_Data.graphql create mode 100644 packages/graphql-gc-api/components/GcPageProduct/GcPageProduct_Product_Data.graphql create mode 100644 packages/graphql-gc-api/components/GcPageProduct/index.ts delete mode 100644 packages/graphql-gc-api/queries/index.ts rename packages/graphql-gc-api/{queries => utils}/GcPage_Redirect.graphql (100%) rename packages/graphql-gc-api/utils/{handleResult.ts => gcPageRedirectOrNotFound.ts} (95%) create mode 100644 packages/graphql-gc-api/utils/index.ts delete mode 100644 packages/magento-product/components/ProductSpecs/ProductSpecsCustomAttributes.tsx diff --git a/docs/framework/config.md b/docs/framework/config.md index 223cdf4dc54..4973a884bed 100644 --- a/docs/framework/config.md +++ b/docs/framework/config.md @@ -239,13 +239,6 @@ The Google Tagmanager ID to be used on the site. This value is required even if you are configuring different values for each locale. -#### hygraphManagementApi: string - -Hygraph Management API. **Only used for migrations.** - -Optional: If the hygraphEndpoint is configured with the 'High Performance Content -API', this field is not required. - #### hygraphProjectId: string Hygraph Project ID. **Only used for migrations.** diff --git a/docs/hygraph/cli.md b/docs/hygraph/cli.md index 25e6e241739..0321c72f9c8 100644 --- a/docs/hygraph/cli.md +++ b/docs/hygraph/cli.md @@ -50,24 +50,10 @@ The following steps are needed to utilize this tool: - Can see schema view 5. Add this new token to your env file: `GC_HYGRAPH_WRITE_ACCESS_TOKEN="{YOUR_WRITE_ACCESS_TOKEN}"` -2. Run `yarn graphcommerce hygraph-migrate` -3. Select the migration you want to run and press enter. -4. The migrations should now be applied, check your Hygraph Schema if changes +2. Add your hygraphProjectId to your env file like this: + 1. Settings > Project > Id + 2. `GC_HYGRAPH_PROJECT_ID="{YOUR_PROJECT_ID}"` +3. Run `yarn graphcommerce hygraph-migrate` +4. Select the migration you want to run and press enter. +5. The migrations should now be applied, check your Hygraph Schema if changes are made. - -### Addtional config - -These configurations should not be necessary and can be deduced from the -hygraphEndpoint URL. This allows you to override them in case something goes -wrong. - -Before adding these make sure you've configure the 'High Performance Content -API' als your hygraphEndpoint. - -- Add your hygraphProjectId to your env file like this: - 1. Settings > Project > Id - 2. Add the project ID to your env file: - `GC_HYGRAPH_PROJECT_ID="{YOUR_PROJECT_ID}"` -- Add your hygraphManagementApi to your env file like this: - 1. Copy the Management API URL and add to your env file: - `GC_HYGRAPH_MANAGEMENT_API="{YOUR_MANAGEMENT_API}"` diff --git a/examples/magento-graphcms/components/GraphCMS/GcPage_Rows_Hygraph.graphql b/examples/magento-graphcms/components/GraphCMS/GcPage_Data_Hygraph.graphql similarity index 77% rename from examples/magento-graphcms/components/GraphCMS/GcPage_Rows_Hygraph.graphql rename to examples/magento-graphcms/components/GraphCMS/GcPage_Data_Hygraph.graphql index 2a8031042b6..f4ab9f8dda0 100644 --- a/examples/magento-graphcms/components/GraphCMS/GcPage_Rows_Hygraph.graphql +++ b/examples/magento-graphcms/components/GraphCMS/GcPage_Data_Hygraph.graphql @@ -1,4 +1,4 @@ -fragment GcPage_Rows_Hygraph on GcPage @inject(into: ["GcPage_Rows"]) { +fragment GcPage_Data_Hygraph on GcPage @inject(into: ["GcPage_Data"]) { rows { __typename ... on Node { @@ -14,7 +14,6 @@ fragment GcPage_Rows_Hygraph on GcPage @inject(into: ["GcPage_Rows"]) { ...RowButtonLinkList ...RowServiceOptions ...RowContentLinks - ...RowProduct ...RowLinks ...RowCategory } diff --git a/examples/magento-graphcms/components/GraphCMS/RowProduct/GetMagentoRowProduct.graphql b/examples/magento-graphcms/components/GraphCMS/RowProduct/GetMagentoRowProduct.graphql index b09efb07cca..b5028245c08 100644 --- a/examples/magento-graphcms/components/GraphCMS/RowProduct/GetMagentoRowProduct.graphql +++ b/examples/magento-graphcms/components/GraphCMS/RowProduct/GetMagentoRowProduct.graphql @@ -1,8 +1,8 @@ query GetMagentoRowProduct($urlKey: String!) { products(filter: { url_key: { eq: $urlKey } }, pageSize: 1) { items { - ...ProductListItem - ...ProductFeatureMediaBoxed + uid + ...GcPage_Product_Data } } } diff --git a/examples/magento-graphcms/components/GraphCMS/RowProduct/RowProduct.tsx b/examples/magento-graphcms/components/GraphCMS/RowProduct/RowProduct.tsx index ab3085c53d0..0b3bc16defd 100644 --- a/examples/magento-graphcms/components/GraphCMS/RowProduct/RowProduct.tsx +++ b/examples/magento-graphcms/components/GraphCMS/RowProduct/RowProduct.tsx @@ -4,7 +4,7 @@ import { Box } from '@mui/material' import { useRouter } from 'next/router' import { productListRenderer } from '../../ProductListItems' import { GetMagentoRowProductDocument } from './GetMagentoRowProduct.gql' -import { RowProductFragment } from './RowProduct.gql' +import { RowProductFragment } from './graphql/RowProduct.gql' import { Backstory, Feature, FeatureBoxed } from './variant' type VariantRenderer = Record< @@ -16,17 +16,15 @@ type RowProductProps = RowProductFragment & { renderer?: Partial } -function RowProductPreview(props: RowProductFragment) { +function RowProductPreview(props: RowProductProps) { const { variant, identity, product } = props const router = useRouter() const canShow = router.isPreview || process.env.NODE_ENV !== 'production' const shouldBeRowCategory = variant === 'Grid' || variant === 'Swipeable' - const shouldBeRowProductPage = - variant === 'Reviews' || variant === 'Upsells' || variant === 'Related' || variant === 'Specs' const noProduct = !product if (!canShow) return null - if (!(noProduct || shouldBeRowCategory || shouldBeRowProductPage)) return null + if (!(noProduct || shouldBeRowCategory)) return null return ( )} - {shouldBeRowProductPage && ( - <> - RowProduct with identity ‘{identity}’ and variant ‘{variant}’, should be migrated in - Hygraph to a RowProductPage component. - - )} - {!(shouldBeRowCategory || shouldBeRowProductPage) && noProduct && ( + {!shouldBeRowCategory && noProduct && ( <> RowProduct ({identity}) was configured with Product URL " {identity}", However Magento didn't return any results. @@ -63,6 +55,10 @@ const defaultRenderer: Partial = { Backstory, Feature, FeatureBoxed, + Related: () => <>Only available on the product page, + Reviews: () => <>Only available on the product page, + Specs: () => <>Only available on the product page, + Upsells: () => <>Only available on the product page, } export function RowProduct(props: RowProductProps) { diff --git a/examples/magento-graphcms/components/GraphCMS/RowProduct/RowProductPage.tsx b/examples/magento-graphcms/components/GraphCMS/RowProduct/RowProductPage.tsx new file mode 100644 index 00000000000..e5d1a58424e --- /dev/null +++ b/examples/magento-graphcms/components/GraphCMS/RowProduct/RowProductPage.tsx @@ -0,0 +1,40 @@ +import { ProductListItemRenderer } from '@graphcommerce/magento-product' +import { productListRenderer } from '../../ProductListItems' +import { GcPageProduct_RowProductFragment } from './graphql/GcPageProduct_RowProduct.gql' +import { Backstory, Feature, FeatureBoxed, Related, Reviews, Specs, Upsells } from './variant' + +type RowProductPageType = Extract< + NonNullable>[number], + { __typename: 'RowProduct' } +> + +type VariantRenderer = Record< + NonNullable, + React.FC +> + +export type RowProductPageProps = RowProductPageType & { + renderer?: Partial +} + +const defaultRenderer: Partial = { + Backstory, + Feature, + FeatureBoxed, + Specs, + Related, + Reviews, + Upsells, +} + +export function RowProductPage(props: RowProductPageProps) { + const { renderer, variant, product } = props + const mergedRenderer = { ...defaultRenderer, ...renderer } as VariantRenderer + + if (!variant) return null + + const RenderType = mergedRenderer?.[variant] + if (!variant) return null + + return +} diff --git a/examples/magento-graphcms/components/GraphCMS/RowProduct/graphql/GcPageProductRows_RowProduct.graphql b/examples/magento-graphcms/components/GraphCMS/RowProduct/graphql/GcPageProductRows_RowProduct.graphql new file mode 100644 index 00000000000..ad43c2c8744 --- /dev/null +++ b/examples/magento-graphcms/components/GraphCMS/RowProduct/graphql/GcPageProductRows_RowProduct.graphql @@ -0,0 +1,7 @@ +fragment GcPageProductRows_RowProduct on ProductInterface +@inject(into: ["GcPageProduct_Product_Data"]) { + ...UpsellProducts + ...RelatedProducts + ...ProductReviews + ...ProductSpecs +} diff --git a/examples/magento-graphcms/components/GraphCMS/RowProduct/graphql/GcPageProduct_RowProduct.graphql b/examples/magento-graphcms/components/GraphCMS/RowProduct/graphql/GcPageProduct_RowProduct.graphql new file mode 100644 index 00000000000..d3e6ce44046 --- /dev/null +++ b/examples/magento-graphcms/components/GraphCMS/RowProduct/graphql/GcPageProduct_RowProduct.graphql @@ -0,0 +1,6 @@ +fragment GcPageProduct_RowProduct on GcPage @inject(into: ["GcPageProduct_Data"]) { + rows { + __typename + ...RowProduct_ProductPage + } +} diff --git a/examples/magento-graphcms/components/GraphCMS/RowProduct/graphql/GcPageRows_RowProduct.graphql b/examples/magento-graphcms/components/GraphCMS/RowProduct/graphql/GcPageRows_RowProduct.graphql new file mode 100644 index 00000000000..655499b146d --- /dev/null +++ b/examples/magento-graphcms/components/GraphCMS/RowProduct/graphql/GcPageRows_RowProduct.graphql @@ -0,0 +1,4 @@ +fragment GcPage_Product_RowProduct on ProductInterface @inject(into: ["GcPage_Product_Data"]) { + ...ProductListItem + ...ProductFeatureMediaBoxed +} diff --git a/examples/magento-graphcms/components/GraphCMS/RowProduct/graphql/GcPage_RowProduct.graphql b/examples/magento-graphcms/components/GraphCMS/RowProduct/graphql/GcPage_RowProduct.graphql new file mode 100644 index 00000000000..2fac0b309db --- /dev/null +++ b/examples/magento-graphcms/components/GraphCMS/RowProduct/graphql/GcPage_RowProduct.graphql @@ -0,0 +1,6 @@ +fragment GcPage_RowProduct on GcPage @inject(into: ["GcPage_Data"]) { + rows { + __typename + ...RowProduct + } +} diff --git a/examples/magento-graphcms/components/GraphCMS/RowProduct/RowProduct.graphql b/examples/magento-graphcms/components/GraphCMS/RowProduct/graphql/RowProduct.graphql similarity index 75% rename from examples/magento-graphcms/components/GraphCMS/RowProduct/RowProduct.graphql rename to examples/magento-graphcms/components/GraphCMS/RowProduct/graphql/RowProduct.graphql index 94ce025b4f6..6303197638c 100644 --- a/examples/magento-graphcms/components/GraphCMS/RowProduct/RowProduct.graphql +++ b/examples/magento-graphcms/components/GraphCMS/RowProduct/graphql/RowProduct.graphql @@ -12,7 +12,6 @@ fragment RowProduct on RowProduct { ...PageLink } product { - ...ProductListItem - ...ProductFeatureMediaBoxed + ...GcPage_Product_Data } } diff --git a/examples/magento-graphcms/components/GraphCMS/RowProduct/graphql/RowProduct_ProductPage.graphql b/examples/magento-graphcms/components/GraphCMS/RowProduct/graphql/RowProduct_ProductPage.graphql new file mode 100644 index 00000000000..049f9993da2 --- /dev/null +++ b/examples/magento-graphcms/components/GraphCMS/RowProduct/graphql/RowProduct_ProductPage.graphql @@ -0,0 +1,6 @@ +fragment RowProduct_ProductPage on RowProduct { + ...RowProduct + product { + ...GcPageProductRows_RowProduct + } +} diff --git a/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Backstory.tsx b/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Backstory.tsx index 6e819f01b44..a7ed991a364 100644 --- a/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Backstory.tsx +++ b/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Backstory.tsx @@ -3,7 +3,7 @@ import { AddProductsToCartForm } from '@graphcommerce/magento-product' import { ParagraphWithSidebarSlide, RenderType } from '@graphcommerce/next-ui' import { useTheme } from '@mui/material' import { productListRenderer } from '../../../ProductListItems' -import { RowProductFragment } from '../RowProduct.gql' +import { RowProductFragment } from '../graphql/RowProduct.gql' type BackstoryProps = RowProductFragment diff --git a/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Feature.tsx b/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Feature.tsx index d368abca464..7b0eeeebbba 100644 --- a/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Feature.tsx +++ b/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Feature.tsx @@ -2,14 +2,14 @@ import { RichText } from '@graphcommerce/graphcms-ui' import { Image } from '@graphcommerce/image' import { ImageText } from '@graphcommerce/next-ui' import { Typography, useTheme } from '@mui/material' -import { RowProductFragment } from '../RowProduct.gql' +import { RowProductFragment } from '../graphql/RowProduct.gql' type FeatureProps = RowProductFragment export function Feature(props: FeatureProps) { const { productCopy, title, product } = props const theme = useTheme() - const item = product?.media_gallery?.[1] ?? product?.media_gallery?.[0] + const item = product?.media_gallery?.[2] ?? product?.media_gallery?.[0] if (!item) return null diff --git a/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/FeatureBoxed.tsx b/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/FeatureBoxed.tsx index 62259d54057..a252fa25c96 100644 --- a/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/FeatureBoxed.tsx +++ b/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/FeatureBoxed.tsx @@ -2,7 +2,7 @@ import { RichText } from '@graphcommerce/graphcms-ui' import { Image } from '@graphcommerce/image' import { ImageTextBoxed, responsiveVal } from '@graphcommerce/next-ui' import { Typography, useTheme } from '@mui/material' -import { RowProductFragment } from '../RowProduct.gql' +import { RowProductFragment } from '../graphql/RowProduct.gql' type FeatureBoxedProps = RowProductFragment diff --git a/examples/magento-graphcms/components/GraphCMS/RowProductPage/variant/Related.tsx b/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Related.tsx similarity index 79% rename from examples/magento-graphcms/components/GraphCMS/RowProductPage/variant/Related.tsx rename to examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Related.tsx index e72b6a5e6f4..e5c81d45ebd 100644 --- a/examples/magento-graphcms/components/GraphCMS/RowProductPage/variant/Related.tsx +++ b/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Related.tsx @@ -1,4 +1,4 @@ -import { AddProductsToCartForm, RelatedProductsFragment } from '@graphcommerce/magento-product' +import { AddProductsToCartForm } from '@graphcommerce/magento-product' import { SidebarSlider, RenderType, @@ -7,9 +7,9 @@ import { } from '@graphcommerce/next-ui' import { Typography } from '@mui/material' import { productListRenderer } from '../../../ProductListItems' -import { RowProductPageFragment } from '../RowProductPage.gql' +import type { RowProductPageProps } from '../RowProductPage' -type RelatedProps = RowProductPageFragment & Pick +type RelatedProps = Omit & Pick export function Related(props: RelatedProps) { const { title, product, sx } = props diff --git a/examples/magento-graphcms/components/GraphCMS/RowProductPage/variant/Reviews.tsx b/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Reviews.tsx similarity index 89% rename from examples/magento-graphcms/components/GraphCMS/RowProductPage/variant/Reviews.tsx rename to examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Reviews.tsx index 2ac3d46bc9c..a20163e235f 100644 --- a/examples/magento-graphcms/components/GraphCMS/RowProductPage/variant/Reviews.tsx +++ b/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Reviews.tsx @@ -3,12 +3,12 @@ import { ProductReviews } from '@graphcommerce/magento-review' import { StoreConfigDocument } from '@graphcommerce/magento-store' import { Row } from '@graphcommerce/next-ui' import { Box, Typography } from '@mui/material' -import { RowProductPageFragment } from '../RowProductPage.gql' +import type { RowProductPageProps } from '../RowProductPage' -type ReviewsProps = RowProductPageFragment +type ReviewsProps = Omit export function Reviews(props: ReviewsProps) { - const { title, product, sx } = props + const { title, product } = props const { reviews, review_count, url_key, sku } = product ?? {} const { data, loading } = useQuery(StoreConfigDocument) diff --git a/examples/magento-graphcms/components/GraphCMS/RowProductPage/variant/Specs.tsx b/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Specs.tsx similarity index 64% rename from examples/magento-graphcms/components/GraphCMS/RowProductPage/variant/Specs.tsx rename to examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Specs.tsx index f5bd5dcdb3a..d56599a05fc 100644 --- a/examples/magento-graphcms/components/GraphCMS/RowProductPage/variant/Specs.tsx +++ b/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Specs.tsx @@ -1,7 +1,7 @@ import { ProductSpecs } from '@graphcommerce/magento-product' -import { RowProductPageFragment } from '../RowProductPage.gql' +import type { RowProductPageProps } from '../RowProductPage' -type SpecsProps = RowProductPageFragment +type SpecsProps = Omit export function Specs(props: SpecsProps) { const { title, product } = props diff --git a/examples/magento-graphcms/components/GraphCMS/RowProductPage/variant/Upsells.tsx b/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Upsells.tsx similarity index 86% rename from examples/magento-graphcms/components/GraphCMS/RowProductPage/variant/Upsells.tsx rename to examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Upsells.tsx index e04d18a8690..26660a94d6c 100644 --- a/examples/magento-graphcms/components/GraphCMS/RowProductPage/variant/Upsells.tsx +++ b/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Upsells.tsx @@ -7,9 +7,9 @@ import { } from '@graphcommerce/next-ui' import { Typography } from '@mui/material' import { productListRenderer } from '../../../ProductListItems/productListRenderer' -import { RowProductPageFragment } from '../RowProductPage.gql' +import type { RowProductPageProps } from '../RowProductPage' -type UpsellsProps = RowProductPageFragment & Pick +type UpsellsProps = Omit & Pick export function Upsells(props: UpsellsProps) { const { title, product, sx } = props diff --git a/examples/magento-graphcms/components/GraphCMS/RowProductPage/GetMagentoRowProductPage.graphql b/examples/magento-graphcms/components/GraphCMS/RowProductPage/GetMagentoRowProductPage.graphql deleted file mode 100644 index 471d7238748..00000000000 --- a/examples/magento-graphcms/components/GraphCMS/RowProductPage/GetMagentoRowProductPage.graphql +++ /dev/null @@ -1,14 +0,0 @@ -query GetMagentoRowProductPage( - $urlKey: String! - $reviewPageSize: Int = 3 - $reviewPage: Int = 1 - $context: InContextInput -) { - products(filter: { url_key: { eq: $urlKey } }, pageSize: 1) @inContext(context: $context) { - items { - ...UpsellProducts - ...RelatedProducts - ...ProductReviews - } - } -} diff --git a/examples/magento-graphcms/components/GraphCMS/RowProductPage/RowProductPage.graphql b/examples/magento-graphcms/components/GraphCMS/RowProductPage/RowProductPage.graphql deleted file mode 100644 index 780f9c37c9b..00000000000 --- a/examples/magento-graphcms/components/GraphCMS/RowProductPage/RowProductPage.graphql +++ /dev/null @@ -1,20 +0,0 @@ -fragment RowProductPage on RowProduct { - variant - identity - asset { - ...Asset - } - title - productCopy { - raw - } - pageLinks { - ...PageLink - } - product { - ...UpsellProducts - ...RelatedProducts - ...ProductReviews - ...ProductSpecs - } -} diff --git a/examples/magento-graphcms/components/GraphCMS/RowProductPage/RowProductPage.tsx b/examples/magento-graphcms/components/GraphCMS/RowProductPage/RowProductPage.tsx deleted file mode 100644 index da345073a16..00000000000 --- a/examples/magento-graphcms/components/GraphCMS/RowProductPage/RowProductPage.tsx +++ /dev/null @@ -1,87 +0,0 @@ -import { InContextMaskProvider, useInContextQuery } from '@graphcommerce/graphql' -import { ProductListItemRenderer } from '@graphcommerce/magento-product' -import { Box } from '@mui/material' -import { useRouter } from 'next/router' -import { productListRenderer } from '../../ProductListItems' -import { GetMagentoRowProductPageDocument } from './GetMagentoRowProductPage.gql' -import { RowProductPageFragment } from './RowProductPage.gql' -import { Related, Reviews, Specs, Upsells } from './variant' - -type VariantRenderer = Record< - NonNullable, - React.FC -> - -type RowProductPageProps = RowProductPageFragment & { - renderer?: Partial -} - -function RowProductPreview(props: RowProductPageFragment) { - const { variant, identity, product } = props - - const router = useRouter() - const canShow = router.isPreview || process.env.NODE_ENV !== 'production' - const isWrongVariant = variant === 'Grid' || variant === 'Swipeable' - const noProduct = !product - if (!canShow) return null - if (!(noProduct || isWrongVariant)) return null - - return ( - ({ - p: 2, - m: 3, - border: `3px dashed ${theme.palette.error.light}`, - borderRadius: 2, - })} - > - {isWrongVariant && ( - <> - RowProduct with identity ‘{identity}’ and variant ‘{variant}’, should be migrated in - Hygraph to a RowCategory component. - - )} - {!isWrongVariant && noProduct && ( - <> - RowProduct ({identity}) was configured with Product URL " - {identity}", However Magento didn't return any results. - - )} - - ) -} - -const defaultRenderer: Partial = { - Specs, - Related, - Reviews, - Upsells, -} - -export function RowProduct(props: RowProductPageProps) { - const { renderer, variant, product } = props - const mergedRenderer = { ...defaultRenderer, ...renderer } as VariantRenderer - - const scoped = useInContextQuery( - GetMagentoRowProductPageDocument, - { variables: { urlKey: product?.url_key ?? '' }, skip: !product?.url_key }, - { products: { items: [product!] } }, - ) - - if (!variant) return null - - const RenderType = mergedRenderer?.[variant] - - return ( - - - {RenderType && ( - - )} - - ) -} diff --git a/examples/magento-graphcms/components/GraphCMS/RowProductPage/variant/index.tsx b/examples/magento-graphcms/components/GraphCMS/RowProductPage/variant/index.tsx deleted file mode 100644 index 6529f24c8a5..00000000000 --- a/examples/magento-graphcms/components/GraphCMS/RowProductPage/variant/index.tsx +++ /dev/null @@ -1,4 +0,0 @@ -export * from './Related' -export * from './Reviews' -export * from './Specs' -export * from './Upsells' diff --git a/examples/magento-graphcms/graphql/ProductPage2.graphql b/examples/magento-graphcms/graphql/ProductPage2.graphql index b6c9c7e877c..7b81b745caf 100644 --- a/examples/magento-graphcms/graphql/ProductPage2.graphql +++ b/examples/magento-graphcms/graphql/ProductPage2.graphql @@ -1,4 +1,9 @@ -query ProductPage2($urlKey: String!, $context: InContextInput) { +query ProductPage2( + $urlKey: String! + $reviewPageSize: Int = 5 + $reviewPage: Int = 1 + $context: InContextInput +) { products(filter: { url_key: { eq: $urlKey } }) @inContext(context: $context) { items { __typename @@ -10,11 +15,7 @@ query ProductPage2($urlKey: String!, $context: InContextInput) { ...DownloadableProductOptions ...BundleProductOptions ...GroupedProduct - page: gcPage { - ...GcPage_Head - ...GcPage_Redirect - ...GcPage_Rows - } + ...GcPageProduct } } } diff --git a/examples/magento-graphcms/pages/p/[url].tsx b/examples/magento-graphcms/pages/p/[url].tsx index 6d27b33796e..f3327541506 100644 --- a/examples/magento-graphcms/pages/p/[url].tsx +++ b/examples/magento-graphcms/pages/p/[url].tsx @@ -1,15 +1,6 @@ import { PageOptions } from '@graphcommerce/framer-next-pages' -import { - cacheFirst, - InContextMaskProvider, - mergeDeep, - useInContextQuery, -} from '@graphcommerce/graphql' -import { - GcPageRowsProduct, - GcPageRowsProductBefore, - GcPageRowsProductSidebar, -} from '@graphcommerce/graphql-gc-api' +import { cacheFirst, InContextMaskProvider, useInContextQuery } from '@graphcommerce/graphql' +import { GcPageProductRows } from '@graphcommerce/graphql-gc-api' import { AddProductsToCartForm, AddProductsToCartFormProps, @@ -67,7 +58,7 @@ function ProductPage(props: Props) { if (!product?.sku || !product.url_key) return null return ( - <> + @@ -87,8 +78,6 @@ function ProductPage(props: Props) { - {/* */} - {import.meta.graphCommerce.breadcrumbs && ( */} - {/* */} + {/* */} - + } @@ -157,7 +146,7 @@ function ProductPage(props: Props) { productListRenderer={productListRenderer} sx={(theme) => ({ mb: theme.spacings.xxl })} /> - + ) } diff --git a/examples/magento-graphcms/plugins/hygraph/HygraphGcPageRows.tsx b/examples/magento-graphcms/plugins/hygraph/HygraphGcPageRows.tsx index 49caaac8388..d1175d8d1a3 100644 --- a/examples/magento-graphcms/plugins/hygraph/HygraphGcPageRows.tsx +++ b/examples/magento-graphcms/plugins/hygraph/HygraphGcPageRows.tsx @@ -1,4 +1,9 @@ -import type { GcPageRowsProps, GcRowTypeRenderer } from '@graphcommerce/graphql-gc-api' +import type { + GcPageProduct_Product_DataFragment, + GcPageProductRowsProps, + GcPage_Product_DataFragment, + GcPageRowsProps, +} from '@graphcommerce/graphql-gc-api' import type { PluginConfig, PluginProps } from '@graphcommerce/next-config' import { RowBlogContent } from '../../components' import { RowButtonLinkList } from '../../components/GraphCMS/RowButtonLinkList/RowButtonLinkList' @@ -10,6 +15,7 @@ import { RowContentLinks } from '../../components/GraphCMS/RowContentLinks/RowCo import { RowHeroBanner } from '../../components/GraphCMS/RowHeroBanner/RowHeroBanner' import { RowLinks } from '../../components/GraphCMS/RowLinks/RowLinks' import { RowProduct } from '../../components/GraphCMS/RowProduct/RowProduct' +import { RowProductPage } from '../../components/GraphCMS/RowProduct/RowProductPage' import { RowQuote } from '../../components/GraphCMS/RowQuote/RowQuote' import { RowServiceOptions } from '../../components/GraphCMS/RowServiceOptions/RowServiceOptions' import { RowSpecialBanner } from '../../components/GraphCMS/RowSpecialBanner/RowSpecialBanner' @@ -19,7 +25,8 @@ export const config: PluginConfig = { module: '@graphcommerce/graphql-gc-api', } -const gcRowHygraphRenderer: Partial = { +const renderers = { + GcRowFake: () => null, RowColumnOne, RowColumnTwo, RowColumnThree, @@ -35,7 +42,37 @@ const gcRowHygraphRenderer: Partial = { RowCategory, } -export const GcPageRows = (props: PluginProps) => { +export const GcPageRows = ( + props: PluginProps & { + rowRenderer?: Partial + }, +) => { const { Prev, ...rest } = props - return + return +} + +export function GcPageProductRows< + P extends GcPageProduct_Product_DataFragment & GcPage_Product_DataFragment, +>( + props: PluginProps> & { + rowRenderer?: Partial['rowRenderer']> + }, +) { + const { Prev, page, product, ...rest } = props + + const newPage = page && { + ...page, + rows: page?.rows?.map((row) => + row?.__typename === 'RowProduct' && !row.product ? { ...row, product } : row, + ), + } + + return ( + + ) } diff --git a/packages/ecommerce-ui/components/PreviewMode/PreviewMode.tsx b/packages/ecommerce-ui/components/PreviewMode/PreviewMode.tsx index 6b4597c8737..ab25aa88171 100644 --- a/packages/ecommerce-ui/components/PreviewMode/PreviewMode.tsx +++ b/packages/ecommerce-ui/components/PreviewMode/PreviewMode.tsx @@ -101,7 +101,14 @@ function PreviewModeEnabled() { } function PreviewModeDisabled() { - const form = useForm<{ secret: string }>({}) + const form = useForm<{ secret: string }>({ + defaultValues: { + secret: + process.env.NODE_ENV !== 'production' && import.meta.graphCommerce.previewSecret + ? import.meta.graphCommerce.previewSecret + : '', + }, + }) const submit = form.handleSubmit((formValues) => { const url = getPreviewUrl() diff --git a/packages/graphql-gc-api/components/ContentArea/Areas.tsx b/packages/graphql-gc-api/components/ContentArea/Areas.tsx deleted file mode 100644 index 7d15fec0b06..00000000000 --- a/packages/graphql-gc-api/components/ContentArea/Areas.tsx +++ /dev/null @@ -1,8 +0,0 @@ -import { GcPageRows } from './GcPageRows' - -export const ContentAreaHome = GcPageRows -export const GcPageRowsProduct = GcPageRows -export const GcPageRowsProductBefore = GcPageRows -export const GcPageRowsProductSidebar = GcPageRows -export const GcPageRowsCategory = GcPageRows -export const GcPageRowsCategoryBefore = GcPageRows diff --git a/packages/graphql-gc-api/components/ContentArea/index.ts b/packages/graphql-gc-api/components/ContentArea/index.ts deleted file mode 100644 index 4f1822fc548..00000000000 --- a/packages/graphql-gc-api/components/ContentArea/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from './Areas' -export * from './GcPageRows' diff --git a/packages/graphql-gc-api/queries/GcPage.graphql b/packages/graphql-gc-api/components/GcPage/GcPage.graphql similarity index 72% rename from packages/graphql-gc-api/queries/GcPage.graphql rename to packages/graphql-gc-api/components/GcPage/GcPage.graphql index b8745b83f55..c57c00fd7b8 100644 --- a/packages/graphql-gc-api/queries/GcPage.graphql +++ b/packages/graphql-gc-api/components/GcPage/GcPage.graphql @@ -1,7 +1,6 @@ query GcPage($input: GCPageInput!) { page: gcPage(input: $input) { - ...GcPage_Head ...GcPage_Redirect - ...GcPage_Rows + ...GcPage_Data } } diff --git a/packages/graphql-gc-api/components/ContentArea/GcPageRows.tsx b/packages/graphql-gc-api/components/GcPage/GcPageRows.tsx similarity index 50% rename from packages/graphql-gc-api/components/ContentArea/GcPageRows.tsx rename to packages/graphql-gc-api/components/GcPage/GcPageRows.tsx index f65f654ea4c..be69ac1f17a 100644 --- a/packages/graphql-gc-api/components/ContentArea/GcPageRows.tsx +++ b/packages/graphql-gc-api/components/GcPage/GcPageRows.tsx @@ -5,26 +5,27 @@ import { type TypeRenderer, } from '@graphcommerce/next-ui' import React from 'react' -import { GcPageQuery } from '../../queries/GcPage.gql' -import { GcPage_RowsFragment } from '../../queries/GcPage_Rows.gql' +import { GcPage_DataFragment } from './GcPage_Data.gql' -export type GcRowTypeRenderer = TypeRenderer< - NonNullable>[number]> +type GcRowTypeRenderer = TypeRenderer< + NonNullable>[number]> > -export type GcPageRowsProps = GcPageQuery & { - rowRenderer?: Partial +export type GcPageRowsProps = { + page: GcPage_DataFragment | null | undefined + rowRenderer?: GcRowTypeRenderer loadingEager?: number } -export const GcPageRows = React.memo((props) => { +export const GcPageRows = React.memo((props: GcPageRowsProps) => { const { rowRenderer, page, loadingEager = 2 } = props + if (!rowRenderer || !page) return null return ( <> {filterNonNullableKeys(page?.rows)?.map((item, index) => ( - + ))} diff --git a/packages/graphql-gc-api/queries/GcPage_Rows.graphql b/packages/graphql-gc-api/components/GcPage/GcPage_Data.graphql similarity index 57% rename from packages/graphql-gc-api/queries/GcPage_Rows.graphql rename to packages/graphql-gc-api/components/GcPage/GcPage_Data.graphql index bbecc858b66..4674f604c9e 100644 --- a/packages/graphql-gc-api/queries/GcPage_Rows.graphql +++ b/packages/graphql-gc-api/components/GcPage/GcPage_Data.graphql @@ -1,4 +1,5 @@ -fragment GcPage_Rows on GcPage { +fragment GcPage_Data on GcPage { + ...GcPage_Head rows { __typename ... on GcRowFake { diff --git a/packages/graphql-gc-api/components/GcPage/GcPage_Product_Data.graphql b/packages/graphql-gc-api/components/GcPage/GcPage_Product_Data.graphql new file mode 100644 index 00000000000..8356c6de1d2 --- /dev/null +++ b/packages/graphql-gc-api/components/GcPage/GcPage_Product_Data.graphql @@ -0,0 +1,4 @@ +fragment GcPage_Product_Data on ProductInterface { + uid + __typename +} diff --git a/packages/graphql-gc-api/components/GcPage/index.ts b/packages/graphql-gc-api/components/GcPage/index.ts new file mode 100644 index 00000000000..37d2633822e --- /dev/null +++ b/packages/graphql-gc-api/components/GcPage/index.ts @@ -0,0 +1,4 @@ +export * from './GcPageRows' +export * from './GcPage_Data.gql' +export * from './GcPage_Product_Data.gql' +export * from './GcPage.gql' diff --git a/packages/graphql-gc-api/components/GcPageMeta/GcPageHead.tsx b/packages/graphql-gc-api/components/GcPageMeta/GcPageHead.tsx index 52ce43771c5..3068b2e0d6e 100644 --- a/packages/graphql-gc-api/components/GcPageMeta/GcPageHead.tsx +++ b/packages/graphql-gc-api/components/GcPageMeta/GcPageHead.tsx @@ -2,11 +2,7 @@ import { usePageContext } from '@graphcommerce/framer-next-pages' import { canonicalize } from '@graphcommerce/next-ui' import Head from 'next/head' import { useRouter } from 'next/router' -import { - GcPage_HeadFragment, - GcMetaTagFragment, - GcLinkRelTagFragment, -} from '../../queries/GcPage_Head.gql' +import { GcPage_HeadFragment, GcMetaTagFragment, GcLinkRelTagFragment } from './GcPage_Head.gql' type GcPageMetaProps = { page: GcPage_HeadFragment diff --git a/packages/graphql-gc-api/queries/GcPage_Head.graphql b/packages/graphql-gc-api/components/GcPageMeta/GcPage_Head.graphql similarity index 100% rename from packages/graphql-gc-api/queries/GcPage_Head.graphql rename to packages/graphql-gc-api/components/GcPageMeta/GcPage_Head.graphql diff --git a/packages/graphql-gc-api/components/GcPageProduct/GcPageProduct.graphql b/packages/graphql-gc-api/components/GcPageProduct/GcPageProduct.graphql new file mode 100644 index 00000000000..14b4f50ba4f --- /dev/null +++ b/packages/graphql-gc-api/components/GcPageProduct/GcPageProduct.graphql @@ -0,0 +1,7 @@ +fragment GcPageProduct on ProductInterface { + page: gcPage { + ...GcPageProduct_Data + } + ...GcPage_Product_Data + ...GcPageProduct_Product_Data +} diff --git a/packages/graphql-gc-api/components/GcPageProduct/GcPageProductRows.tsx b/packages/graphql-gc-api/components/GcPageProduct/GcPageProductRows.tsx new file mode 100644 index 00000000000..7367e59fed6 --- /dev/null +++ b/packages/graphql-gc-api/components/GcPageProduct/GcPageProductRows.tsx @@ -0,0 +1,38 @@ +import { + TypeRenderer, + filterNonNullableKeys, + LazyHydrate, + RenderType, +} from '@graphcommerce/next-ui' +import { GcPage_Product_DataFragment } from '../GcPage/GcPage_Product_Data.gql' +import { GcPageProduct_DataFragment } from './GcPageProduct_Data.gql' +import { GcPageProduct_Product_DataFragment } from './GcPageProduct_Product_Data.gql' + +type GcRowTypeRenderer = TypeRenderer< + NonNullable>[number]> +> + +export type GcPageProductRowsProps

    = { + page: GcPageProduct_DataFragment | null | undefined + rowRenderer?: GcRowTypeRenderer + loadingEager?: number + product: P +} + +export function GcPageProductRows< + P extends GcPageProduct_Product_DataFragment & GcPage_Product_DataFragment, +>(props: GcPageProductRowsProps

    ) { + const { rowRenderer, page, loadingEager = 2 } = props + + if (!rowRenderer || !page) return null + + return ( + <> + {filterNonNullableKeys(page?.rows)?.map((item, index) => ( + + + + ))} + + ) +} diff --git a/packages/graphql-gc-api/components/GcPageProduct/GcPageProduct_Data.graphql b/packages/graphql-gc-api/components/GcPageProduct/GcPageProduct_Data.graphql new file mode 100644 index 00000000000..d574c3d3e87 --- /dev/null +++ b/packages/graphql-gc-api/components/GcPageProduct/GcPageProduct_Data.graphql @@ -0,0 +1,4 @@ +fragment GcPageProduct_Data on GcPage { + ...GcPage_Head + ...GcPage_Data +} diff --git a/packages/graphql-gc-api/components/GcPageProduct/GcPageProduct_Product_Data.graphql b/packages/graphql-gc-api/components/GcPageProduct/GcPageProduct_Product_Data.graphql new file mode 100644 index 00000000000..81e52d1da66 --- /dev/null +++ b/packages/graphql-gc-api/components/GcPageProduct/GcPageProduct_Product_Data.graphql @@ -0,0 +1,4 @@ +fragment GcPageProduct_Product_Data on ProductInterface { + uid + __typename +} diff --git a/packages/graphql-gc-api/components/GcPageProduct/index.ts b/packages/graphql-gc-api/components/GcPageProduct/index.ts new file mode 100644 index 00000000000..67a54fd3124 --- /dev/null +++ b/packages/graphql-gc-api/components/GcPageProduct/index.ts @@ -0,0 +1,2 @@ +export * from './GcPageProductRows' +export * from './GcPageProduct_Product_Data.gql' diff --git a/packages/graphql-gc-api/components/index.ts b/packages/graphql-gc-api/components/index.ts index aff072ca2e8..0c368110900 100644 --- a/packages/graphql-gc-api/components/index.ts +++ b/packages/graphql-gc-api/components/index.ts @@ -1,2 +1,3 @@ -export * from './ContentArea' +export * from './GcPage' +export * from './GcPageProduct' export * from './GcPageMeta' diff --git a/packages/graphql-gc-api/index.ts b/packages/graphql-gc-api/index.ts index 164e0918400..1464f012256 100644 --- a/packages/graphql-gc-api/index.ts +++ b/packages/graphql-gc-api/index.ts @@ -1,3 +1,2 @@ export * from './components' -export * from './queries' -export * from './utils/handleResult' +export * from './utils' diff --git a/packages/graphql-gc-api/queries/index.ts b/packages/graphql-gc-api/queries/index.ts deleted file mode 100644 index 717366335a3..00000000000 --- a/packages/graphql-gc-api/queries/index.ts +++ /dev/null @@ -1,4 +0,0 @@ -export * from './GcPage.gql' -export * from './GcPage_Head.gql' -export * from './GcPage_Redirect.gql' -export * from './GcPage_Rows.gql' diff --git a/packages/graphql-gc-api/queries/GcPage_Redirect.graphql b/packages/graphql-gc-api/utils/GcPage_Redirect.graphql similarity index 100% rename from packages/graphql-gc-api/queries/GcPage_Redirect.graphql rename to packages/graphql-gc-api/utils/GcPage_Redirect.graphql diff --git a/packages/graphql-gc-api/utils/handleResult.ts b/packages/graphql-gc-api/utils/gcPageRedirectOrNotFound.ts similarity index 95% rename from packages/graphql-gc-api/utils/handleResult.ts rename to packages/graphql-gc-api/utils/gcPageRedirectOrNotFound.ts index e92d63bc6d8..9f689d081c9 100644 --- a/packages/graphql-gc-api/utils/handleResult.ts +++ b/packages/graphql-gc-api/utils/gcPageRedirectOrNotFound.ts @@ -1,5 +1,5 @@ import type { SimplifyDeep, SetRequired } from 'type-fest' -import type { GcPageQuery } from '../queries/GcPage.gql' +import type { GcPageQuery } from '../components/GcPage/GcPage.gql' import { Redirect } from 'next' type FoundPage = NonNullable diff --git a/packages/graphql-gc-api/utils/index.ts b/packages/graphql-gc-api/utils/index.ts new file mode 100644 index 00000000000..cdace8a1791 --- /dev/null +++ b/packages/graphql-gc-api/utils/index.ts @@ -0,0 +1,2 @@ +export * from './GcPage_Redirect.gql' +export * from './gcPageRedirectOrNotFound' diff --git a/packages/graphql/components/GraphQLProvider/measurePerformanceLink.ts b/packages/graphql/components/GraphQLProvider/measurePerformanceLink.ts index ceaae13c6dd..03297dea662 100644 --- a/packages/graphql/components/GraphQLProvider/measurePerformanceLink.ts +++ b/packages/graphql/components/GraphQLProvider/measurePerformanceLink.ts @@ -1,9 +1,9 @@ /* eslint-disable no-console */ import { ApolloLink } from '@apollo/client' -import type { MeshFetchHTTPInformation } from '@graphql-mesh/plugin-http-details-extensions' import { print } from '@apollo/client/utilities' +import type { MeshFetchHTTPInformation } from '@graphql-mesh/plugin-http-details-extensions' import { cliHyperlink } from '../../lib/hyperlinker' - +import { responsePathAsArray, stripIgnoredCharacters } from 'graphql' const running = new Map< string, { @@ -109,12 +109,9 @@ export const flushMeasurePerf = () => { // padd the items to the max length items.forEach((item) => { item.forEach((_, index) => { - const [str] = (Array.isArray(item[index]) ? item[index] : [item[index], item[index]]) as [ - string, - string, - ] + const [str] = Array.isArray(item[index]) ? item[index] : [item[index], item[index]] - const val = (Array.isArray(item[index]) ? item[index][1] : item[index]) as string + const val = Array.isArray(item[index]) ? item[index][1] : item[index] const padLength = colWidths[index] + (val.length - str.length) @@ -123,8 +120,16 @@ export const flushMeasurePerf = () => { }) // render the items to a string + + const jajajaj = [[''], ...items].map((item) => item.join(' ')) + // console.log(jajajaj) + + jajajaj.forEach((item) => { + console.log(item) + }) + const output = [[''], ...items].map((item) => item.join(' ')).join('\n') - console.log(output) + // console.log(output) running.clear() } @@ -157,43 +162,55 @@ export const measurePerformanceLink = new ApolloLink((operation, forward) => { const httpDetails: MeshFetchHTTPInformation[] | undefined = data.extensions?.httpDetails let additional = [``, ``] as [string, string] - if (httpDetails) { - httpDetails.forEach((d) => { - const requestUrl = new URL(d.request.url) - requestUrl.searchParams.delete('extensions') - const title = `${d.sourceName} ${d.responseTime}ms` - additional = [ - `${additional[0]} ${title}`, - `${additional[1]} ${cliHyperlink(title, requestUrl.toString().replace(/\+/g, '%20'))}`, - ] - }) - } // Called after server responds const query = [ `# Variables: ${JSON.stringify(operation.variables)}`, `# Headers: ${JSON.stringify(operation.getContext().headers)}`, - print(operation.query), + stripIgnoredCharacters(print(operation.query)), ].join('\n') - const meshUrl = new URL(`${import.meta.graphCommerce.canonicalBaseUrl}/api/graphql`) + const meshUrl = new URL( + process.env.NODE_ENV === 'production' + ? `${import.meta.graphCommerce.canonicalBaseUrl}/api/graphql` + : 'http://localhost:3000/api/graphql', + ) + meshUrl.searchParams.set('query', query) running.set(operationString, { start: operation.getContext().measurePerformanceLinkStart as Date, end: new Date(), - operationName: [operation.operationName, operation.operationName], + operationName: [ + operation.operationName, + operation.operationName, + // cliHyperlink(operation.operationName, meshUrl.toString()), + ], additional, - // [ - // operation.operationName, - // cliHyperlink(operation.operationName, meshUrl.toString()), - // ], - // additional: [ - // `🔗 ${additional[0]}`, - // `${cliHyperlink('🔗', meshUrl.toString())} ${additional[1]}`, - // ], }) + if (httpDetails) { + // running.delete(operationString) + + httpDetails.forEach((d) => { + const requestUrl = new URL(d.request.url) + requestUrl.searchParams.delete('extensions') + const title = `${d.sourceName} ${d.responseTime}ms` + + const key = `${operationString}.${responsePathAsArray(d.path).join('.')}` + const name = `${operation.operationName}.${responsePathAsArray(d.path).join('.')}` + running.set(key, { + start: new Date(d.request.timestamp), + end: new Date(d.response.timestamp), + operationName: [name, name], + additional: [ + `${title}`, + `${cliHyperlink(d.sourceName, requestUrl.toString().replace(/\+/g, '%20'))}`, + ], + }) + }) + } + markTimeout() return data diff --git a/packages/graphql/hooks/useInContextQuery.ts b/packages/graphql/hooks/useInContextQuery.ts index def9b1be590..0783edbb945 100644 --- a/packages/graphql/hooks/useInContextQuery.ts +++ b/packages/graphql/hooks/useInContextQuery.ts @@ -41,7 +41,7 @@ export function useInContextQuery< const clientQuery = useQuery(document, { ...options, variables: { ...options.variables, context } as V, - skip: skip && !context, + skip: skip || !context, }) let { data } = clientQuery diff --git a/packages/hygraph-cli/dist/migrations/graphcommerce8to9.js b/packages/hygraph-cli/dist/migrations/graphcommerce8to9.js index 1396ab4a800..319f297e9c7 100644 --- a/packages/hygraph-cli/dist/migrations/graphcommerce8to9.js +++ b/packages/hygraph-cli/dist/migrations/graphcommerce8to9.js @@ -62,59 +62,6 @@ const graphcommerce8to9 = async (schema, client) => { isRequired: true, }, 'RowCategory', 'model'); } - const hasRowProductPage = schema.models.some((m) => m.apiId === 'RowProductPage'); - if (!hasRowProductPage) { - migrationAction(schema, 'model', 'create', { - apiId: 'RowProductPage', - apiIdPlural: 'RowProductPageItems', - displayName: 'Row Product Page', - description: 'A model to display related product information on the product page', - }); - migrationAction(schema, 'enumeration', 'create', { - displayName: 'Row Product Page Variant', - apiId: 'RowProductPageVariant', - values: [ - { displayName: 'Reviews', apiId: 'Reviews' }, - { displayName: 'Upsells', apiId: 'Upsells' }, - { displayName: 'Related', apiId: 'Related' }, - { displayName: 'Specs', apiId: 'Specs' }, - { displayName: 'Usps', apiId: 'Usps' }, - ], - }); - migrationAction(schema, 'enumerableField', 'create', { - displayName: 'Variant', - apiId: 'variant', - parentApiId: 'RowProductPage', - enumerationApiId: 'RowProductPageVariant', - description: 'As what variant wil the RowProductPage be displayed', - isRequired: true, - }, 'RowProductPage', 'model'); - migrationAction(schema, 'unionField', 'update', { - apiId: 'content', - displayName: 'Content', - modelApiId: 'Page', - reverseField: { - modelApiIds: [ - 'RowLinks', - 'RowServiceOptions', - 'RowSpecialBanner', - 'RowQuote', - 'RowProduct', - 'RowColumnOne', - 'RowColumnTwo', - 'RowColumnThree', - 'RowHeroBanner', - 'RowBlogContent', - 'RowButtonList', - 'RowContentLinks', - 'RowButtonLinkList', - 'RowCategory', - 'RowProductPage', - ], - // visibility: VisibilityTypes.Hidden, => Currently not supported for updateUnionField | https://github.com/hygraph/management-sdk/issues/34 - }, - }, 'Page', 'model'); - } return client.run(true); }; exports.graphcommerce8to9 = graphcommerce8to9; diff --git a/packages/hygraph-cli/src/migrations/graphcommerce8to9.ts b/packages/hygraph-cli/src/migrations/graphcommerce8to9.ts index 23de6684fc9..20d1d19cbb0 100644 --- a/packages/hygraph-cli/src/migrations/graphcommerce8to9.ts +++ b/packages/hygraph-cli/src/migrations/graphcommerce8to9.ts @@ -90,76 +90,5 @@ export const graphcommerce8to9: MigrationFunction = async (schema, client) => { ) } - const hasRowProductPage = schema.models.some((m) => m.apiId === 'RowProductPage') - if (!hasRowProductPage) { - migrationAction(schema, 'model', 'create', { - apiId: 'RowProductPage', - apiIdPlural: 'RowProductPageItems', - displayName: 'Row Product Page', - description: 'A model to display related product information on the product page', - } satisfies BatchMigrationCreateModelInput) - - migrationAction(schema, 'enumeration', 'create', { - displayName: 'Row Product Page Variant', - apiId: 'RowProductPageVariant', - values: [ - { displayName: 'Reviews', apiId: 'Reviews' }, - { displayName: 'Upsells', apiId: 'Upsells' }, - { displayName: 'Related', apiId: 'Related' }, - { displayName: 'Specs', apiId: 'Specs' }, - { displayName: 'Usps', apiId: 'Usps' }, - ], - } satisfies BatchMigrationCreateEnumerationInput) - - migrationAction( - schema, - 'enumerableField', - 'create', - { - displayName: 'Variant', - apiId: 'variant', - parentApiId: 'RowProductPage', - enumerationApiId: 'RowProductPageVariant', - description: 'As what variant wil the RowProductPage be displayed', - isRequired: true, - } satisfies BatchMigrationCreateEnumerableFieldInput, - 'RowProductPage', - 'model', - ) - - migrationAction( - schema, - 'unionField', - 'update', - { - apiId: 'content', - displayName: 'Content', - modelApiId: 'Page', - reverseField: { - modelApiIds: [ - 'RowLinks', - 'RowServiceOptions', - 'RowSpecialBanner', - 'RowQuote', - 'RowProduct', - 'RowColumnOne', - 'RowColumnTwo', - 'RowColumnThree', - 'RowHeroBanner', - 'RowBlogContent', - 'RowButtonList', - 'RowContentLinks', - 'RowButtonLinkList', - 'RowCategory', - 'RowProductPage', - ], - // visibility: VisibilityTypes.Hidden, => Currently not supported for updateUnionField | https://github.com/hygraph/management-sdk/issues/34 - }, - }, - 'Page', - 'model', - ) - } - return client.run(true) } diff --git a/packages/hygraph-ui/mesh/resolvers.ts b/packages/hygraph-ui/mesh/resolvers.ts index 8da3c819132..9fe3f717bc8 100644 --- a/packages/hygraph-ui/mesh/resolvers.ts +++ b/packages/hygraph-ui/mesh/resolvers.ts @@ -9,7 +9,7 @@ import { RowProduct, type Resolvers, } from '@graphcommerce/graphql-mesh' -import { Kind, print } from 'graphql' +import { Kind, responsePathAsArray } from 'graphql' const normalizeUrl = (href: string) => { const cleanedhref = href.replaceAll(/^\/|\/$/g, '') @@ -43,29 +43,40 @@ export function getProduct(context: MeshContext, key: string): ProductInterface return value[key] } +function isRowProduct(row: PageContent): row is RowProduct { + return '__typename' in row && row.__typename === 'RowProduct' +} + const gcPageProductResolver: GCPageResolver = { selectionSet: `{url_key}`, resolve: async (root, args, context, info) => { - setProduct(context, root.url_key!, root) - const page = ( - await context.hygraph.Query.pages({ - context, - info, - root, - key: root.url_key, - argsFromKeys: (keys) => ({ - where: { url_in: ['product/global', ...keys.map((key) => `p/${key}`)] }, - }), - valuesFromResults: (results, keys) => - keys.map((key) => [ + if (!root.url_key) return null + + setProduct(context, root.url_key, root) + + // console.log(root) + return context.hygraph.Query.pages({ + context, + info, + root, + key: root.url_key, + argsFromKeys: (keys) => ({ + where: { url_in: ['product/global', ...keys.map((key) => `p/${key}`)] }, + }), + valuesFromResults: (results, keys) => + keys.map((key) => { + const page = results.find((r) => r.url === `p/${key}`) ?? - results.find((r) => r.url === 'product/global') ?? - null, - ]), - }) - )?.[0] + results.find((r) => r.url === 'product/global') + if (!page) return null - return page + page.content.forEach((row) => { + if (isRowProduct(row)) row.identity = key + }) + + return page + }), + }) }, } @@ -161,6 +172,10 @@ export const resolvers: Resolvers = { product: { selectionSet: `{ identity }`, resolve: async (root, args, context, info) => { + // When the RowProduct is request as part of a product query, we expect the product to be + // already resolved and available in the context + if (responsePathAsArray(info.path)[0] === 'products') return null + const result = await context.m2.Query.products({ root, info, diff --git a/packages/magento-product-configurable/index.ts b/packages/magento-product-configurable/index.ts index 53675bc6984..a04bf43a934 100644 --- a/packages/magento-product-configurable/index.ts +++ b/packages/magento-product-configurable/index.ts @@ -2,7 +2,6 @@ export * from './components' export * from './ConfigurableCartItem/ConfigurableCartItem' export * from './ConfigurableContext/ConfigurableContext' export * from './ConfigurableProductAddToCart/ConfigurableProductAddToCart' -export * from './ConfigurableProductPage.gql' export * from './graphql' export * from './hooks' export * from './utils' diff --git a/packages/magento-product/components/ProductSpecs/ProductSpecs.graphql b/packages/magento-product/components/ProductSpecs/ProductSpecs.graphql index 787f8025073..1734a5ae5bc 100644 --- a/packages/magento-product/components/ProductSpecs/ProductSpecs.graphql +++ b/packages/magento-product/components/ProductSpecs/ProductSpecs.graphql @@ -1,5 +1,5 @@ fragment ProductSpecs on ProductInterface { - custom_attributesV2(filters: { is_visible_on_front: true }) @include(if: $useCustomAttributes) { + custom_attributesV2(filters: { is_visible_on_front: true }) { items { code __typename diff --git a/packages/magento-product/components/ProductSpecs/ProductSpecsCustomAttributes.tsx b/packages/magento-product/components/ProductSpecs/ProductSpecsCustomAttributes.tsx deleted file mode 100644 index bb1752b7dc5..00000000000 --- a/packages/magento-product/components/ProductSpecs/ProductSpecsCustomAttributes.tsx +++ /dev/null @@ -1,45 +0,0 @@ -import { useQuery } from '@graphcommerce/graphql' -import { extendableComponent } from '@graphcommerce/next-ui' -import { Box } from '@mui/material' -import { ProductSpecsCustomAttributesFragment } from './ProductSpecs.gql' -import { ProductSpecsTypesDocument } from './ProductSpecsTypes.gql' - -const name = 'ProductSpecs' -const parts = ['root', 'specs', 'options'] as const -const { classes } = extendableComponent(name, parts) - -export type ProductSpecsCustomAttributesProps = { - product: ProductSpecsCustomAttributesFragment -} - -export function ProductSpecs(props: ProductSpecsCustomAttributesProps) { - const { product } = props - const specs = product.custom_attributesV2?.items - const productSpecsTypes = useQuery(ProductSpecsTypesDocument) - - return ( - <> - {specs?.map((item) => ( -

  • -
    - { - productSpecsTypes?.data?.attributesList?.items?.find( - (type) => type?.code === item?.code, - )?.label - } -
    - - {item?.__typename === 'AttributeSelectedOptions' && ( - <> - {item?.selected_options?.map((option) => ( - {option?.label === '1' ? 'Yes' : option?.label} - ))} - - )} - {item?.__typename === 'AttributeValue' && {item.value}} - -
  • - ))} - - ) -} diff --git a/packages/magento-review/components/ProductReviews/ProductReviews.graphql b/packages/magento-review/components/ProductReviews/ProductReviews.graphql index e433b42b08e..d9a523a4519 100644 --- a/packages/magento-review/components/ProductReviews/ProductReviews.graphql +++ b/packages/magento-review/components/ProductReviews/ProductReviews.graphql @@ -1,5 +1,5 @@ fragment ProductReviews on ProductInterface { - reviews(pageSize: $reviewPageSize, currentPage: $reviewPage) { + reviews(pageSize: 3, currentPage: 1) { page_info { total_pages current_page From 2bcfaf18b71c33e4970114cd9a78b5ff70fb6b4d Mon Sep 17 00:00:00 2001 From: Paul Hachmang Date: Thu, 8 Aug 2024 13:28:37 +0200 Subject: [PATCH 31/33] More --- .../GraphCMS/RowProduct/RowProductPage.tsx | 13 ++++--------- .../graphql/GcPageProduct_RowProduct.graphql | 1 + .../graphql/GcPage_RowProduct.graphql | 2 ++ .../variant/ProductFeatureMedia.graphql | 9 +++++++++ .../GraphCMS/RowProduct/variant/Related.tsx | 2 +- .../GraphCMS/RowProduct/variant/Reviews.tsx | 2 +- .../GraphCMS/RowProduct/variant/Specs.tsx | 2 +- .../GraphCMS/RowProduct/variant/Upsells.tsx | 2 +- .../plugins/hygraph/HygraphGcPageRows.tsx | 19 +++++++------------ .../components/GcPage/GcPageRows.tsx | 8 ++++---- .../components/GcPage/GcPage_Data.graphql | 1 + .../GcPageProduct/GcPageProduct.graphql | 1 - .../GcPageProduct/GcPageProductRows.tsx | 8 ++++---- .../GcPageProduct/GcPageProduct_Data.graphql | 1 + .../GcPageProduct_Product_Data.graphql | 3 +-- .../GraphQLProvider/measurePerformanceLink.ts | 10 +++------- 16 files changed, 41 insertions(+), 43 deletions(-) create mode 100644 examples/magento-graphcms/components/GraphCMS/RowProduct/variant/ProductFeatureMedia.graphql diff --git a/examples/magento-graphcms/components/GraphCMS/RowProduct/RowProductPage.tsx b/examples/magento-graphcms/components/GraphCMS/RowProduct/RowProductPage.tsx index e5d1a58424e..6a07f5a4f7b 100644 --- a/examples/magento-graphcms/components/GraphCMS/RowProduct/RowProductPage.tsx +++ b/examples/magento-graphcms/components/GraphCMS/RowProduct/RowProductPage.tsx @@ -1,19 +1,14 @@ import { ProductListItemRenderer } from '@graphcommerce/magento-product' import { productListRenderer } from '../../ProductListItems' -import { GcPageProduct_RowProductFragment } from './graphql/GcPageProduct_RowProduct.gql' +import { RowProduct_ProductPageFragment } from './graphql/RowProduct_ProductPage.gql' import { Backstory, Feature, FeatureBoxed, Related, Reviews, Specs, Upsells } from './variant' -type RowProductPageType = Extract< - NonNullable>[number], - { __typename: 'RowProduct' } -> - type VariantRenderer = Record< - NonNullable, - React.FC + NonNullable, + React.FC > -export type RowProductPageProps = RowProductPageType & { +export type RowProductPageProps = RowProduct_ProductPageFragment & { renderer?: Partial } diff --git a/examples/magento-graphcms/components/GraphCMS/RowProduct/graphql/GcPageProduct_RowProduct.graphql b/examples/magento-graphcms/components/GraphCMS/RowProduct/graphql/GcPageProduct_RowProduct.graphql index d3e6ce44046..034a2ed71f9 100644 --- a/examples/magento-graphcms/components/GraphCMS/RowProduct/graphql/GcPageProduct_RowProduct.graphql +++ b/examples/magento-graphcms/components/GraphCMS/RowProduct/graphql/GcPageProduct_RowProduct.graphql @@ -1,3 +1,4 @@ +# When we're requesting a **product page** also request the RowProduct_ProductPage fragment fragment GcPageProduct_RowProduct on GcPage @inject(into: ["GcPageProduct_Data"]) { rows { __typename diff --git a/examples/magento-graphcms/components/GraphCMS/RowProduct/graphql/GcPage_RowProduct.graphql b/examples/magento-graphcms/components/GraphCMS/RowProduct/graphql/GcPage_RowProduct.graphql index 2fac0b309db..0f90e80f26c 100644 --- a/examples/magento-graphcms/components/GraphCMS/RowProduct/graphql/GcPage_RowProduct.graphql +++ b/examples/magento-graphcms/components/GraphCMS/RowProduct/graphql/GcPage_RowProduct.graphql @@ -1,3 +1,5 @@ +# When we're requesting a **non-product page** also request the RowProduct fragments. +# For data specifc to the product page, see GcPageProduct_RowProduct.graphql fragment GcPage_RowProduct on GcPage @inject(into: ["GcPage_Data"]) { rows { __typename diff --git a/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/ProductFeatureMedia.graphql b/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/ProductFeatureMedia.graphql new file mode 100644 index 00000000000..2177cbda4ad --- /dev/null +++ b/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/ProductFeatureMedia.graphql @@ -0,0 +1,9 @@ +fragment ProductFeatureMedia on ProductInterface { + media_gallery { + label + __typename + ... on ProductImage { + url + } + } +} diff --git a/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Related.tsx b/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Related.tsx index e5c81d45ebd..78b6a31389d 100644 --- a/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Related.tsx +++ b/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Related.tsx @@ -9,7 +9,7 @@ import { Typography } from '@mui/material' import { productListRenderer } from '../../../ProductListItems' import type { RowProductPageProps } from '../RowProductPage' -type RelatedProps = Omit & Pick +type RelatedProps = RowProductPageProps & Pick export function Related(props: RelatedProps) { const { title, product, sx } = props diff --git a/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Reviews.tsx b/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Reviews.tsx index a20163e235f..b8207d8c28c 100644 --- a/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Reviews.tsx +++ b/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Reviews.tsx @@ -5,7 +5,7 @@ import { Row } from '@graphcommerce/next-ui' import { Box, Typography } from '@mui/material' import type { RowProductPageProps } from '../RowProductPage' -type ReviewsProps = Omit +type ReviewsProps = RowProductPageProps export function Reviews(props: ReviewsProps) { const { title, product } = props diff --git a/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Specs.tsx b/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Specs.tsx index d56599a05fc..4cf82887ffe 100644 --- a/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Specs.tsx +++ b/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Specs.tsx @@ -1,7 +1,7 @@ import { ProductSpecs } from '@graphcommerce/magento-product' import type { RowProductPageProps } from '../RowProductPage' -type SpecsProps = Omit +type SpecsProps = RowProductPageProps export function Specs(props: SpecsProps) { const { title, product } = props diff --git a/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Upsells.tsx b/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Upsells.tsx index 26660a94d6c..ed3bad295c2 100644 --- a/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Upsells.tsx +++ b/examples/magento-graphcms/components/GraphCMS/RowProduct/variant/Upsells.tsx @@ -9,7 +9,7 @@ import { Typography } from '@mui/material' import { productListRenderer } from '../../../ProductListItems/productListRenderer' import type { RowProductPageProps } from '../RowProductPage' -type UpsellsProps = Omit & Pick +type UpsellsProps = RowProductPageProps & Pick export function Upsells(props: UpsellsProps) { const { title, product, sx } = props diff --git a/examples/magento-graphcms/plugins/hygraph/HygraphGcPageRows.tsx b/examples/magento-graphcms/plugins/hygraph/HygraphGcPageRows.tsx index d1175d8d1a3..15d105659f2 100644 --- a/examples/magento-graphcms/plugins/hygraph/HygraphGcPageRows.tsx +++ b/examples/magento-graphcms/plugins/hygraph/HygraphGcPageRows.tsx @@ -25,7 +25,7 @@ export const config: PluginConfig = { module: '@graphcommerce/graphql-gc-api', } -const renderers = { +const renderer = { GcRowFake: () => null, RowColumnOne, RowColumnTwo, @@ -44,18 +44,20 @@ const renderers = { export const GcPageRows = ( props: PluginProps & { - rowRenderer?: Partial + renderer?: Partial }, ) => { const { Prev, ...rest } = props - return + return } +const rendererProduct = { ...renderer, RowProduct: RowProductPage } + export function GcPageProductRows< P extends GcPageProduct_Product_DataFragment & GcPage_Product_DataFragment, >( props: PluginProps> & { - rowRenderer?: Partial['rowRenderer']> + renderer?: Partial['renderer']> }, ) { const { Prev, page, product, ...rest } = props @@ -67,12 +69,5 @@ export function GcPageProductRows< ), } - return ( - - ) + return } diff --git a/packages/graphql-gc-api/components/GcPage/GcPageRows.tsx b/packages/graphql-gc-api/components/GcPage/GcPageRows.tsx index be69ac1f17a..3584d27e7ff 100644 --- a/packages/graphql-gc-api/components/GcPage/GcPageRows.tsx +++ b/packages/graphql-gc-api/components/GcPage/GcPageRows.tsx @@ -13,19 +13,19 @@ type GcRowTypeRenderer = TypeRenderer< export type GcPageRowsProps = { page: GcPage_DataFragment | null | undefined - rowRenderer?: GcRowTypeRenderer + renderer?: GcRowTypeRenderer loadingEager?: number } export const GcPageRows = React.memo((props: GcPageRowsProps) => { - const { rowRenderer, page, loadingEager = 2 } = props + const { renderer, page, loadingEager = 2 } = props - if (!rowRenderer || !page) return null + if (!renderer || !page) return null return ( <> {filterNonNullableKeys(page?.rows)?.map((item, index) => ( - + ))} diff --git a/packages/graphql-gc-api/components/GcPage/GcPage_Data.graphql b/packages/graphql-gc-api/components/GcPage/GcPage_Data.graphql index 4674f604c9e..31ddb77437d 100644 --- a/packages/graphql-gc-api/components/GcPage/GcPage_Data.graphql +++ b/packages/graphql-gc-api/components/GcPage/GcPage_Data.graphql @@ -1,3 +1,4 @@ +# This fragment is used in the GcPage query to retrieve the data for a page. fragment GcPage_Data on GcPage { ...GcPage_Head rows { diff --git a/packages/graphql-gc-api/components/GcPageProduct/GcPageProduct.graphql b/packages/graphql-gc-api/components/GcPageProduct/GcPageProduct.graphql index 14b4f50ba4f..d0a7b078649 100644 --- a/packages/graphql-gc-api/components/GcPageProduct/GcPageProduct.graphql +++ b/packages/graphql-gc-api/components/GcPageProduct/GcPageProduct.graphql @@ -2,6 +2,5 @@ fragment GcPageProduct on ProductInterface { page: gcPage { ...GcPageProduct_Data } - ...GcPage_Product_Data ...GcPageProduct_Product_Data } diff --git a/packages/graphql-gc-api/components/GcPageProduct/GcPageProductRows.tsx b/packages/graphql-gc-api/components/GcPageProduct/GcPageProductRows.tsx index 7367e59fed6..ff369ce3818 100644 --- a/packages/graphql-gc-api/components/GcPageProduct/GcPageProductRows.tsx +++ b/packages/graphql-gc-api/components/GcPageProduct/GcPageProductRows.tsx @@ -14,7 +14,7 @@ type GcRowTypeRenderer = TypeRenderer< export type GcPageProductRowsProps

    = { page: GcPageProduct_DataFragment | null | undefined - rowRenderer?: GcRowTypeRenderer + renderer?: GcRowTypeRenderer loadingEager?: number product: P } @@ -22,15 +22,15 @@ export type GcPageProductRowsProps

    export function GcPageProductRows< P extends GcPageProduct_Product_DataFragment & GcPage_Product_DataFragment, >(props: GcPageProductRowsProps

    ) { - const { rowRenderer, page, loadingEager = 2 } = props + const { renderer, page, loadingEager = 2 } = props - if (!rowRenderer || !page) return null + if (!renderer || !page) return null return ( <> {filterNonNullableKeys(page?.rows)?.map((item, index) => ( - + ))} diff --git a/packages/graphql-gc-api/components/GcPageProduct/GcPageProduct_Data.graphql b/packages/graphql-gc-api/components/GcPageProduct/GcPageProduct_Data.graphql index d574c3d3e87..26f64bc09ab 100644 --- a/packages/graphql-gc-api/components/GcPageProduct/GcPageProduct_Data.graphql +++ b/packages/graphql-gc-api/components/GcPageProduct/GcPageProduct_Data.graphql @@ -1,3 +1,4 @@ +# This fragment is added to the ProductPage2 query when the product page is loaded. fragment GcPageProduct_Data on GcPage { ...GcPage_Head ...GcPage_Data diff --git a/packages/graphql-gc-api/components/GcPageProduct/GcPageProduct_Product_Data.graphql b/packages/graphql-gc-api/components/GcPageProduct/GcPageProduct_Product_Data.graphql index 81e52d1da66..8437240770b 100644 --- a/packages/graphql-gc-api/components/GcPageProduct/GcPageProduct_Product_Data.graphql +++ b/packages/graphql-gc-api/components/GcPageProduct/GcPageProduct_Product_Data.graphql @@ -1,4 +1,3 @@ fragment GcPageProduct_Product_Data on ProductInterface { - uid - __typename + ...GcPage_Product_Data } diff --git a/packages/graphql/components/GraphQLProvider/measurePerformanceLink.ts b/packages/graphql/components/GraphQLProvider/measurePerformanceLink.ts index 03297dea662..65d273a2777 100644 --- a/packages/graphql/components/GraphQLProvider/measurePerformanceLink.ts +++ b/packages/graphql/components/GraphQLProvider/measurePerformanceLink.ts @@ -178,6 +178,7 @@ export const measurePerformanceLink = new ApolloLink((operation, forward) => { meshUrl.searchParams.set('query', query) + running.delete(operationString) running.set(operationString, { start: operation.getContext().measurePerformanceLinkStart as Date, end: new Date(), @@ -190,23 +191,18 @@ export const measurePerformanceLink = new ApolloLink((operation, forward) => { }) if (httpDetails) { - // running.delete(operationString) + running.delete(operationString) httpDetails.forEach((d) => { const requestUrl = new URL(d.request.url) requestUrl.searchParams.delete('extensions') - const title = `${d.sourceName} ${d.responseTime}ms` const key = `${operationString}.${responsePathAsArray(d.path).join('.')}` - const name = `${operation.operationName}.${responsePathAsArray(d.path).join('.')}` + const name = `${operation.operationName}.${responsePathAsArray(d.path).join('.')} (${d.sourceName})` running.set(key, { start: new Date(d.request.timestamp), end: new Date(d.response.timestamp), operationName: [name, name], - additional: [ - `${title}`, - `${cliHyperlink(d.sourceName, requestUrl.toString().replace(/\+/g, '%20'))}`, - ], }) }) } From 705bff02c19ab05a55bf8157e02597ebf9406898 Mon Sep 17 00:00:00 2001 From: Paul Hachmang Date: Thu, 8 Aug 2024 13:41:00 +0200 Subject: [PATCH 32/33] Rename GcPage to Page --- examples/magento-graphcms/.meshrc.yml | 9 +--- .../components/Blog/BlogAuthor.graphql | 2 +- .../components/Blog/BlogItem.graphql | 2 +- .../components/Blog/BlogTags.graphql | 2 +- .../GraphCMS/GcPage_Data_Hygraph.graphql | 2 +- .../components/GraphCMS/GcRow.graphqls | 2 +- .../RowProduct/GetMagentoRowProduct.graphql | 2 +- .../GcPageProductRows_RowProduct.graphql | 7 --- .../graphql/GcPageRows_RowProduct.graphql | 4 -- .../graphql/GcPage_RowProduct.graphql | 8 ---- .../PageProductRows_RowProduct.graphql | 7 +++ ...graphql => PageProduct_RowProduct.graphql} | 2 +- .../graphql/PageRows_RowProduct.graphql | 4 ++ .../graphql/Page_RowProduct.graphql | 8 ++++ .../RowProduct/graphql/RowProduct.graphql | 2 +- .../graphql/RowProduct_ProductPage.graphql | 2 +- .../graphql/ProductPage2.graphql | 2 +- examples/magento-graphcms/pages/[...url].tsx | 14 ++---- examples/magento-graphcms/pages/index.tsx | 20 ++++---- examples/magento-graphcms/pages/p/[url].tsx | 6 +-- .../plugins/hygraph/HygraphGcPageRows.tsx | 24 +++++----- packages/graphql-gc-api/README.md | 47 +++++++++---------- .../components/GcPage/GcPage.graphql | 6 --- .../components/GcPage/GcPage_Data.graphql | 10 ---- .../GcPage/GcPage_Product_Data.graphql | 4 -- .../graphql-gc-api/components/GcPage/index.ts | 4 -- .../components/GcPageMeta/index.ts | 1 - .../GcPageProduct/GcPageProduct.graphql | 6 --- .../GcPageProduct/GcPageProductRows.tsx | 38 --------------- .../GcPageProduct_Product_Data.graphql | 3 -- .../components/GcPageProduct/index.ts | 2 - .../components/Page/Page.graphql | 6 +++ .../GcPageRows.tsx => Page/PageRows.tsx} | 14 +++--- .../components/Page/Page_Data.graphql | 10 ++++ .../components/Page/Page_Product_Data.graphql | 4 ++ .../graphql-gc-api/components/Page/index.ts | 4 ++ .../GcPageHead.tsx => PageHead/PageHead.tsx} | 8 ++-- .../Page_Head.graphql} | 2 +- .../components/PageHead/index.ts | 1 + .../PageProduct/PageProduct.graphql | 6 +++ .../PageProduct/PageProductRows.tsx | 38 +++++++++++++++ .../PageProduct_Data.graphql} | 6 +-- .../PageProduct_Product_Data.graphql | 3 ++ .../components/PageProduct/index.ts | 2 + packages/graphql-gc-api/components/index.ts | 6 +-- .../schema/CategoryInterface_gcPage.graphqls | 4 +- packages/graphql-gc-api/schema/GcRow.graphqls | 8 ---- .../schema/{GcPage.graphqls => Page.graphqls} | 17 +++++-- ...{GcPageHead.graphqls => PageHead.graphqls} | 2 +- ...edirect.graphqls => PageRedirect.graphqls} | 2 +- .../schema/ProductInterface_gcPage.graphqls | 16 +++---- .../schema/Query_gcLayout.graphqls | 11 ----- ...ry_gcPage.graphqls => Query_page.graphqls} | 2 +- ...graphqls => Query_pageCanonicals.graphqls} | 6 +-- .../schema/Query_pageLayout.graphqls | 11 +++++ .../utils/GcPage_Redirect.graphql | 2 +- .../utils/gcPageRedirectOrNotFound.ts | 40 ++++++++-------- packages/graphql-gc-api/utils/index.ts | 4 +- .../hygraph-dynamic-rows/mesh/resolvers.ts | 2 +- .../hygraph-ui/graphql/HygraphPage.graphql | 2 +- packages/hygraph-ui/mesh/resolvers.ts | 24 +++++----- 61 files changed, 252 insertions(+), 263 deletions(-) delete mode 100644 examples/magento-graphcms/components/GraphCMS/RowProduct/graphql/GcPageProductRows_RowProduct.graphql delete mode 100644 examples/magento-graphcms/components/GraphCMS/RowProduct/graphql/GcPageRows_RowProduct.graphql delete mode 100644 examples/magento-graphcms/components/GraphCMS/RowProduct/graphql/GcPage_RowProduct.graphql create mode 100644 examples/magento-graphcms/components/GraphCMS/RowProduct/graphql/PageProductRows_RowProduct.graphql rename examples/magento-graphcms/components/GraphCMS/RowProduct/graphql/{GcPageProduct_RowProduct.graphql => PageProduct_RowProduct.graphql} (64%) create mode 100644 examples/magento-graphcms/components/GraphCMS/RowProduct/graphql/PageRows_RowProduct.graphql create mode 100644 examples/magento-graphcms/components/GraphCMS/RowProduct/graphql/Page_RowProduct.graphql delete mode 100644 packages/graphql-gc-api/components/GcPage/GcPage.graphql delete mode 100644 packages/graphql-gc-api/components/GcPage/GcPage_Data.graphql delete mode 100644 packages/graphql-gc-api/components/GcPage/GcPage_Product_Data.graphql delete mode 100644 packages/graphql-gc-api/components/GcPage/index.ts delete mode 100644 packages/graphql-gc-api/components/GcPageMeta/index.ts delete mode 100644 packages/graphql-gc-api/components/GcPageProduct/GcPageProduct.graphql delete mode 100644 packages/graphql-gc-api/components/GcPageProduct/GcPageProductRows.tsx delete mode 100644 packages/graphql-gc-api/components/GcPageProduct/GcPageProduct_Product_Data.graphql delete mode 100644 packages/graphql-gc-api/components/GcPageProduct/index.ts create mode 100644 packages/graphql-gc-api/components/Page/Page.graphql rename packages/graphql-gc-api/components/{GcPage/GcPageRows.tsx => Page/PageRows.tsx} (61%) create mode 100644 packages/graphql-gc-api/components/Page/Page_Data.graphql create mode 100644 packages/graphql-gc-api/components/Page/Page_Product_Data.graphql create mode 100644 packages/graphql-gc-api/components/Page/index.ts rename packages/graphql-gc-api/components/{GcPageMeta/GcPageHead.tsx => PageHead/PageHead.tsx} (89%) rename packages/graphql-gc-api/components/{GcPageMeta/GcPage_Head.graphql => PageHead/Page_Head.graphql} (91%) create mode 100644 packages/graphql-gc-api/components/PageHead/index.ts create mode 100644 packages/graphql-gc-api/components/PageProduct/PageProduct.graphql create mode 100644 packages/graphql-gc-api/components/PageProduct/PageProductRows.tsx rename packages/graphql-gc-api/components/{GcPageProduct/GcPageProduct_Data.graphql => PageProduct/PageProduct_Data.graphql} (53%) create mode 100644 packages/graphql-gc-api/components/PageProduct/PageProduct_Product_Data.graphql create mode 100644 packages/graphql-gc-api/components/PageProduct/index.ts delete mode 100644 packages/graphql-gc-api/schema/GcRow.graphqls rename packages/graphql-gc-api/schema/{GcPage.graphqls => Page.graphqls} (50%) rename packages/graphql-gc-api/schema/{GcPageHead.graphqls => PageHead.graphqls} (99%) rename packages/graphql-gc-api/schema/{GcPageRedirect.graphqls => PageRedirect.graphqls} (94%) delete mode 100644 packages/graphql-gc-api/schema/Query_gcLayout.graphqls rename packages/graphql-gc-api/schema/{Query_gcPage.graphqls => Query_page.graphqls} (61%) rename packages/graphql-gc-api/schema/{Query_gcCanonicals.graphqls => Query_pageCanonicals.graphqls} (55%) create mode 100644 packages/graphql-gc-api/schema/Query_pageLayout.graphqls diff --git a/examples/magento-graphcms/.meshrc.yml b/examples/magento-graphcms/.meshrc.yml index d36068c534a..426ee0362da 100644 --- a/examples/magento-graphcms/.meshrc.yml +++ b/examples/magento-graphcms/.meshrc.yml @@ -13,18 +13,11 @@ sources: # Remove mutations: `mutation { * }` - 'Mutation.!*' # Remove queries: `query { node, row*, asset*, scheduled*, *Version, user* }` - - 'Query.!{node,asset*,scheduled*,*Version,user*}' + - 'Query.!{node,asset*,scheduled*,*Version,user*,page}' # Remove field arguments: `query { anyfield(after,before,last,forceParentLocale,locales) { ... } }` - '*.*.!{after,before,last,forceParentLocale,locales,stage}' # Remove type any input or type fields: `input MyInput {}` or `type MyType { anyfield }` - '*.!{scheduledIn,documentInStages*,createdAt*,updatedAt*,publishedAt*,createdBy,updatedBy,publishedBy,history,scheduledIn*}' - - rename: - mode: wrap - renames: - - from: - type: Page - to: - type: GcPage - prune: skipPruning: [] - name: m2 diff --git a/examples/magento-graphcms/components/Blog/BlogAuthor.graphql b/examples/magento-graphcms/components/Blog/BlogAuthor.graphql index 3bef34c35e8..934c0d505cb 100644 --- a/examples/magento-graphcms/components/Blog/BlogAuthor.graphql +++ b/examples/magento-graphcms/components/Blog/BlogAuthor.graphql @@ -1,4 +1,4 @@ -fragment BlogAuthor on GcPage { +fragment BlogAuthor on Page { date author } diff --git a/examples/magento-graphcms/components/Blog/BlogItem.graphql b/examples/magento-graphcms/components/Blog/BlogItem.graphql index 790b266dfd0..ee371f34d1a 100644 --- a/examples/magento-graphcms/components/Blog/BlogItem.graphql +++ b/examples/magento-graphcms/components/Blog/BlogItem.graphql @@ -1,4 +1,4 @@ -fragment BlogItem on GcPage { +fragment BlogItem on Page { title url date diff --git a/examples/magento-graphcms/components/Blog/BlogTags.graphql b/examples/magento-graphcms/components/Blog/BlogTags.graphql index 5b6a018686f..f44e2e108b4 100644 --- a/examples/magento-graphcms/components/Blog/BlogTags.graphql +++ b/examples/magento-graphcms/components/Blog/BlogTags.graphql @@ -1,4 +1,4 @@ -fragment BlogTags on GcPage { +fragment BlogTags on Page { relatedPages { title url diff --git a/examples/magento-graphcms/components/GraphCMS/GcPage_Data_Hygraph.graphql b/examples/magento-graphcms/components/GraphCMS/GcPage_Data_Hygraph.graphql index f4ab9f8dda0..2e5614c523c 100644 --- a/examples/magento-graphcms/components/GraphCMS/GcPage_Data_Hygraph.graphql +++ b/examples/magento-graphcms/components/GraphCMS/GcPage_Data_Hygraph.graphql @@ -1,4 +1,4 @@ -fragment GcPage_Data_Hygraph on GcPage @inject(into: ["GcPage_Data"]) { +fragment Page_Data_Hygraph on Page @inject(into: ["Page_Data"]) { rows { __typename ... on Node { diff --git a/examples/magento-graphcms/components/GraphCMS/GcRow.graphqls b/examples/magento-graphcms/components/GraphCMS/GcRow.graphqls index 24043d4d648..1cf24c5e133 100644 --- a/examples/magento-graphcms/components/GraphCMS/GcRow.graphqls +++ b/examples/magento-graphcms/components/GraphCMS/GcRow.graphqls @@ -1,4 +1,4 @@ -union GcRow = +union PageRow = | RowBlogContent | RowButtonLinkList | RowCategory diff --git a/examples/magento-graphcms/components/GraphCMS/RowProduct/GetMagentoRowProduct.graphql b/examples/magento-graphcms/components/GraphCMS/RowProduct/GetMagentoRowProduct.graphql index b5028245c08..2f0d42d9ec8 100644 --- a/examples/magento-graphcms/components/GraphCMS/RowProduct/GetMagentoRowProduct.graphql +++ b/examples/magento-graphcms/components/GraphCMS/RowProduct/GetMagentoRowProduct.graphql @@ -2,7 +2,7 @@ query GetMagentoRowProduct($urlKey: String!) { products(filter: { url_key: { eq: $urlKey } }, pageSize: 1) { items { uid - ...GcPage_Product_Data + ...Page_Product_Data } } } diff --git a/examples/magento-graphcms/components/GraphCMS/RowProduct/graphql/GcPageProductRows_RowProduct.graphql b/examples/magento-graphcms/components/GraphCMS/RowProduct/graphql/GcPageProductRows_RowProduct.graphql deleted file mode 100644 index ad43c2c8744..00000000000 --- a/examples/magento-graphcms/components/GraphCMS/RowProduct/graphql/GcPageProductRows_RowProduct.graphql +++ /dev/null @@ -1,7 +0,0 @@ -fragment GcPageProductRows_RowProduct on ProductInterface -@inject(into: ["GcPageProduct_Product_Data"]) { - ...UpsellProducts - ...RelatedProducts - ...ProductReviews - ...ProductSpecs -} diff --git a/examples/magento-graphcms/components/GraphCMS/RowProduct/graphql/GcPageRows_RowProduct.graphql b/examples/magento-graphcms/components/GraphCMS/RowProduct/graphql/GcPageRows_RowProduct.graphql deleted file mode 100644 index 655499b146d..00000000000 --- a/examples/magento-graphcms/components/GraphCMS/RowProduct/graphql/GcPageRows_RowProduct.graphql +++ /dev/null @@ -1,4 +0,0 @@ -fragment GcPage_Product_RowProduct on ProductInterface @inject(into: ["GcPage_Product_Data"]) { - ...ProductListItem - ...ProductFeatureMediaBoxed -} diff --git a/examples/magento-graphcms/components/GraphCMS/RowProduct/graphql/GcPage_RowProduct.graphql b/examples/magento-graphcms/components/GraphCMS/RowProduct/graphql/GcPage_RowProduct.graphql deleted file mode 100644 index 0f90e80f26c..00000000000 --- a/examples/magento-graphcms/components/GraphCMS/RowProduct/graphql/GcPage_RowProduct.graphql +++ /dev/null @@ -1,8 +0,0 @@ -# When we're requesting a **non-product page** also request the RowProduct fragments. -# For data specifc to the product page, see GcPageProduct_RowProduct.graphql -fragment GcPage_RowProduct on GcPage @inject(into: ["GcPage_Data"]) { - rows { - __typename - ...RowProduct - } -} diff --git a/examples/magento-graphcms/components/GraphCMS/RowProduct/graphql/PageProductRows_RowProduct.graphql b/examples/magento-graphcms/components/GraphCMS/RowProduct/graphql/PageProductRows_RowProduct.graphql new file mode 100644 index 00000000000..15a9ce3c113 --- /dev/null +++ b/examples/magento-graphcms/components/GraphCMS/RowProduct/graphql/PageProductRows_RowProduct.graphql @@ -0,0 +1,7 @@ +fragment PageProductRows_RowProduct on ProductInterface +@inject(into: ["PageProduct_Product_Data"]) { + ...UpsellProducts + ...RelatedProducts + ...ProductReviews + ...ProductSpecs +} diff --git a/examples/magento-graphcms/components/GraphCMS/RowProduct/graphql/GcPageProduct_RowProduct.graphql b/examples/magento-graphcms/components/GraphCMS/RowProduct/graphql/PageProduct_RowProduct.graphql similarity index 64% rename from examples/magento-graphcms/components/GraphCMS/RowProduct/graphql/GcPageProduct_RowProduct.graphql rename to examples/magento-graphcms/components/GraphCMS/RowProduct/graphql/PageProduct_RowProduct.graphql index 034a2ed71f9..908f286a94c 100644 --- a/examples/magento-graphcms/components/GraphCMS/RowProduct/graphql/GcPageProduct_RowProduct.graphql +++ b/examples/magento-graphcms/components/GraphCMS/RowProduct/graphql/PageProduct_RowProduct.graphql @@ -1,5 +1,5 @@ # When we're requesting a **product page** also request the RowProduct_ProductPage fragment -fragment GcPageProduct_RowProduct on GcPage @inject(into: ["GcPageProduct_Data"]) { +fragment PageProduct_RowProduct on Page @inject(into: ["PageProduct_Data"]) { rows { __typename ...RowProduct_ProductPage diff --git a/examples/magento-graphcms/components/GraphCMS/RowProduct/graphql/PageRows_RowProduct.graphql b/examples/magento-graphcms/components/GraphCMS/RowProduct/graphql/PageRows_RowProduct.graphql new file mode 100644 index 00000000000..2c707592034 --- /dev/null +++ b/examples/magento-graphcms/components/GraphCMS/RowProduct/graphql/PageRows_RowProduct.graphql @@ -0,0 +1,4 @@ +fragment Page_Product_RowProduct on ProductInterface @inject(into: ["Page_Product_Data"]) { + ...ProductListItem + ...ProductFeatureMediaBoxed +} diff --git a/examples/magento-graphcms/components/GraphCMS/RowProduct/graphql/Page_RowProduct.graphql b/examples/magento-graphcms/components/GraphCMS/RowProduct/graphql/Page_RowProduct.graphql new file mode 100644 index 00000000000..fe50c632c4d --- /dev/null +++ b/examples/magento-graphcms/components/GraphCMS/RowProduct/graphql/Page_RowProduct.graphql @@ -0,0 +1,8 @@ +# When we're requesting a **non-product page** also request the RowProduct fragments. +# For data specifc to the product page, see PageProduct_RowProduct.graphql +fragment Page_RowProduct on Page @inject(into: ["Page_Data"]) { + rows { + __typename + ...RowProduct + } +} diff --git a/examples/magento-graphcms/components/GraphCMS/RowProduct/graphql/RowProduct.graphql b/examples/magento-graphcms/components/GraphCMS/RowProduct/graphql/RowProduct.graphql index 6303197638c..a2406973285 100644 --- a/examples/magento-graphcms/components/GraphCMS/RowProduct/graphql/RowProduct.graphql +++ b/examples/magento-graphcms/components/GraphCMS/RowProduct/graphql/RowProduct.graphql @@ -12,6 +12,6 @@ fragment RowProduct on RowProduct { ...PageLink } product { - ...GcPage_Product_Data + ...Page_Product_Data } } diff --git a/examples/magento-graphcms/components/GraphCMS/RowProduct/graphql/RowProduct_ProductPage.graphql b/examples/magento-graphcms/components/GraphCMS/RowProduct/graphql/RowProduct_ProductPage.graphql index 049f9993da2..496a4fd6f99 100644 --- a/examples/magento-graphcms/components/GraphCMS/RowProduct/graphql/RowProduct_ProductPage.graphql +++ b/examples/magento-graphcms/components/GraphCMS/RowProduct/graphql/RowProduct_ProductPage.graphql @@ -1,6 +1,6 @@ fragment RowProduct_ProductPage on RowProduct { ...RowProduct product { - ...GcPageProductRows_RowProduct + ...PageProductRows_RowProduct } } diff --git a/examples/magento-graphcms/graphql/ProductPage2.graphql b/examples/magento-graphcms/graphql/ProductPage2.graphql index 7b81b745caf..205b3aacc97 100644 --- a/examples/magento-graphcms/graphql/ProductPage2.graphql +++ b/examples/magento-graphcms/graphql/ProductPage2.graphql @@ -15,7 +15,7 @@ query ProductPage2( ...DownloadableProductOptions ...BundleProductOptions ...GroupedProduct - ...GcPageProduct + ...PageProduct } } } diff --git a/examples/magento-graphcms/pages/[...url].tsx b/examples/magento-graphcms/pages/[...url].tsx index abb34ff0a5b..1329412e77f 100644 --- a/examples/magento-graphcms/pages/[...url].tsx +++ b/examples/magento-graphcms/pages/[...url].tsx @@ -1,10 +1,6 @@ import { PageOptions } from '@graphcommerce/framer-next-pages' import { cacheFirst, flushMeasurePerf, InContextMaskProvider } from '@graphcommerce/graphql' -import { - GcPageRowsCategory, - GcPageRowsCategoryBefore, - GcPageQuery, -} from '@graphcommerce/graphql-gc-api' +import { PageRowsCategory, PageRowsCategoryBefore, PageQuery } from '@graphcommerce/graphql-gc-api' import { appendSiblingsAsChildren, CategoryBreadcrumbs, @@ -47,7 +43,7 @@ import { import { CategoryPageDocument, CategoryPageQuery } from '../graphql/CategoryPage.gql' import { graphqlSharedClient, graphqlSsrClient } from '../lib/graphql/graphqlSsrClient' -export type CategoryProps = GcPageQuery & +export type CategoryProps = PageQuery & CategoryPageQuery & ProductListQuery & ProductFiltersQuery & { @@ -61,7 +57,7 @@ type GetPageStaticPaths = GetStaticPaths type GetPageStaticProps = GetStaticProps function CategoryPage(props: CategoryProps) { - const { gcPage, categories, ...rest } = props + const { page, categories, ...rest } = props const productList = useProductList({ ...rest, category: categories?.items?.[0], @@ -75,7 +71,7 @@ function CategoryPage(props: CategoryProps) { - + @@ -144,7 +140,7 @@ function CategoryPage(props: CategoryProps) { )} - + {page && ( @@ -22,7 +22,7 @@ function CmsPage(props: Props) { return ( <> - + @@ -40,14 +40,14 @@ export const getStaticProps: GetPageStaticProps = async (context) => { const staticClient = graphqlSsrClient(context) const conf = client.query({ query: StoreConfigDocument }) - const gcPage = client.query({ query: GcPageDocument, variables: { input: { href: '/' } } }) + const page = client.query({ query: PageDocument, variables: { input: { href: '/' } } }) const layout = staticClient.query({ query: LayoutDocument, fetchPolicy: cacheFirst(staticClient), }) - const page = (await gcPage).data - if (!isGcPageFound(page)) return gcPageRedirectOrNotFound(page) + const page = (await page).data + if (!isPageFound(page)) return pageRedirectOrNotFound(page) return { props: { diff --git a/examples/magento-graphcms/pages/p/[url].tsx b/examples/magento-graphcms/pages/p/[url].tsx index f3327541506..523710a5326 100644 --- a/examples/magento-graphcms/pages/p/[url].tsx +++ b/examples/magento-graphcms/pages/p/[url].tsx @@ -1,6 +1,6 @@ import { PageOptions } from '@graphcommerce/framer-next-pages' import { cacheFirst, InContextMaskProvider, useInContextQuery } from '@graphcommerce/graphql' -import { GcPageProductRows } from '@graphcommerce/graphql-gc-api' +import { PageProductRows } from '@graphcommerce/graphql-gc-api' import { AddProductsToCartForm, AddProductsToCartFormProps, @@ -127,7 +127,7 @@ function ProductPage(props: Props) { {/* */} - {/* */} + {/* */} - + } diff --git a/examples/magento-graphcms/plugins/hygraph/HygraphGcPageRows.tsx b/examples/magento-graphcms/plugins/hygraph/HygraphGcPageRows.tsx index 15d105659f2..b8f0148bdce 100644 --- a/examples/magento-graphcms/plugins/hygraph/HygraphGcPageRows.tsx +++ b/examples/magento-graphcms/plugins/hygraph/HygraphGcPageRows.tsx @@ -1,8 +1,8 @@ import type { - GcPageProduct_Product_DataFragment, - GcPageProductRowsProps, - GcPage_Product_DataFragment, - GcPageRowsProps, + PageProduct_Product_DataFragment, + PageProductRowsProps, + Page_Product_DataFragment, + PageRowsProps, } from '@graphcommerce/graphql-gc-api' import type { PluginConfig, PluginProps } from '@graphcommerce/next-config' import { RowBlogContent } from '../../components' @@ -26,7 +26,7 @@ export const config: PluginConfig = { } const renderer = { - GcRowFake: () => null, + PageRowFake: () => null, RowColumnOne, RowColumnTwo, RowColumnThree, @@ -42,9 +42,9 @@ const renderer = { RowCategory, } -export const GcPageRows = ( - props: PluginProps & { - renderer?: Partial +export const PageRows = ( + props: PluginProps & { + renderer?: Partial }, ) => { const { Prev, ...rest } = props @@ -53,11 +53,11 @@ export const GcPageRows = ( const rendererProduct = { ...renderer, RowProduct: RowProductPage } -export function GcPageProductRows< - P extends GcPageProduct_Product_DataFragment & GcPage_Product_DataFragment, +export function PageProductRows< + P extends PageProduct_Product_DataFragment & Page_Product_DataFragment, >( - props: PluginProps> & { - renderer?: Partial['renderer']> + props: PluginProps> & { + renderer?: Partial['renderer']> }, ) { const { Prev, page, product, ...rest } = props diff --git a/packages/graphql-gc-api/README.md b/packages/graphql-gc-api/README.md index c89e7ee3b9f..3a924255e12 100644 --- a/packages/graphql-gc-api/README.md +++ b/packages/graphql-gc-api/README.md @@ -19,32 +19,31 @@ This package offers the following new queries ```graphql extend type Query { - gcPage(input: GCPageInput!): GcPage + page(input: GCPageInput!): Page } -type GcPage { +type Page { """ The head of the page. """ - head: GcPageHead + head: PageHead """ When the redirect is defined the page should not be rendered and the user should be redirected to the specified URL. """ - redirect: GcPageRedirect + redirect: PageRedirect } ``` -- [Query { gcPage }](./schema/Query_gcPage.graphqls) -- [GcPage](./schema/GcPage.graphqls) -- [GcPageHead](./schema/GcPageHead.graphqls) -- [GcPageRedirect](./schema/GCPageRedirect.graphqls) +- [Query { page }](./schema/Query_page.graphqls) +- [Page](./schema/Page.graphqls) +- [PageHead](./schema/PageHead.graphqls) +- [PageRedirect](./schema/GCPageRedirect.graphqls) ### Creating the GraphQL schema integration There are a few important steps to integrate with the GraphQL schema. First we -need to make your type compatible with GcPage. We take Hygraph as an example -here. +need to make your type compatible with Page. We take Hygraph as an example here. For example we would normally execute the following query: @@ -78,7 +77,7 @@ query Pages { node { url } - # This part is the GcPageHead + # This part is the PageHead head { title description @@ -99,14 +98,14 @@ query Pages { ### Extend your type -RENAME your type to GcPage. +RENAME your type to Page. Note: After making changines to the schema or .meshrc.yaml you always need to run `yarn codegen` to see your changes. If you now run `yarn codegen` you'll in the GraphiQL interface that your Page -implements `GcPage`. When running the query you will see an empty `head` and -empty redirect. +implements `Page`. When running the query you will see an empty `head` and empty +redirect. ### Implement the `head`/`redirect` fields for your type @@ -121,13 +120,13 @@ every change, only when you change the schema or the mesh configuration. You should now see the `head` and `redirect` fields populated with data in your original query. -### Resolve the gcPage query to your created type. +### Resolve the page query to your created type. Now we want to be able to resolve this query. ```graphql query GCPage { - gcPage(input: { href: "page/home" }) { + page(input: { href: "page/home" }) { head { title canonical { @@ -156,18 +155,18 @@ query GCPage { } ``` -### Resolve the gcPage query to your own query +### Resolve the page query to your own query -We define a `@resolveTo` for the gcPage query in the mesh configuration. +We define a `@resolveTo` for the page query in the mesh configuration. So in this case we want to run the earlier pagesConnection query (as mentioned -above) when the gcPage query is called. +above) when the page query is called. The pagesConnection (sourceName) Query (sourceTypeName) should be calling hygraph (sourceName). -We want to take the href argument (args.input.href) from the gcPage query and -pass it to the `url` input field of the pagesConnection. (sourceArgs). +We want to take the href argument (args.input.href) from the page query and pass +it to the `url` input field of the pagesConnection. (sourceArgs). Finally when the pagesConnection has ran, we want to get the first edge and return the node as the result. (result). @@ -176,7 +175,7 @@ Resulting in the following code: ```graphql extend type Query { - gcPage(input: GCPageInput!): GcPage + page(input: GCPageInput!): Page @resolveTo( sourceName: "hygraph" sourceTypeName: "Query" @@ -193,8 +192,8 @@ Learn more about Note: Because we change the schema, we need to run `yarn codegen` again. Note: The resolveTo directive can doesn't really give warnings configured wrongly. -After everything is set up you should be able to run the gcPage query and get -the data from the pagesConnection query. +After everything is set up you should be able to run the page query and get the +data from the pagesConnection query. ## Frontend integration diff --git a/packages/graphql-gc-api/components/GcPage/GcPage.graphql b/packages/graphql-gc-api/components/GcPage/GcPage.graphql deleted file mode 100644 index c57c00fd7b8..00000000000 --- a/packages/graphql-gc-api/components/GcPage/GcPage.graphql +++ /dev/null @@ -1,6 +0,0 @@ -query GcPage($input: GCPageInput!) { - page: gcPage(input: $input) { - ...GcPage_Redirect - ...GcPage_Data - } -} diff --git a/packages/graphql-gc-api/components/GcPage/GcPage_Data.graphql b/packages/graphql-gc-api/components/GcPage/GcPage_Data.graphql deleted file mode 100644 index 31ddb77437d..00000000000 --- a/packages/graphql-gc-api/components/GcPage/GcPage_Data.graphql +++ /dev/null @@ -1,10 +0,0 @@ -# This fragment is used in the GcPage query to retrieve the data for a page. -fragment GcPage_Data on GcPage { - ...GcPage_Head - rows { - __typename - ... on GcRowFake { - id - } - } -} diff --git a/packages/graphql-gc-api/components/GcPage/GcPage_Product_Data.graphql b/packages/graphql-gc-api/components/GcPage/GcPage_Product_Data.graphql deleted file mode 100644 index 8356c6de1d2..00000000000 --- a/packages/graphql-gc-api/components/GcPage/GcPage_Product_Data.graphql +++ /dev/null @@ -1,4 +0,0 @@ -fragment GcPage_Product_Data on ProductInterface { - uid - __typename -} diff --git a/packages/graphql-gc-api/components/GcPage/index.ts b/packages/graphql-gc-api/components/GcPage/index.ts deleted file mode 100644 index 37d2633822e..00000000000 --- a/packages/graphql-gc-api/components/GcPage/index.ts +++ /dev/null @@ -1,4 +0,0 @@ -export * from './GcPageRows' -export * from './GcPage_Data.gql' -export * from './GcPage_Product_Data.gql' -export * from './GcPage.gql' diff --git a/packages/graphql-gc-api/components/GcPageMeta/index.ts b/packages/graphql-gc-api/components/GcPageMeta/index.ts deleted file mode 100644 index 51189cfb357..00000000000 --- a/packages/graphql-gc-api/components/GcPageMeta/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './GcPageHead' diff --git a/packages/graphql-gc-api/components/GcPageProduct/GcPageProduct.graphql b/packages/graphql-gc-api/components/GcPageProduct/GcPageProduct.graphql deleted file mode 100644 index d0a7b078649..00000000000 --- a/packages/graphql-gc-api/components/GcPageProduct/GcPageProduct.graphql +++ /dev/null @@ -1,6 +0,0 @@ -fragment GcPageProduct on ProductInterface { - page: gcPage { - ...GcPageProduct_Data - } - ...GcPageProduct_Product_Data -} diff --git a/packages/graphql-gc-api/components/GcPageProduct/GcPageProductRows.tsx b/packages/graphql-gc-api/components/GcPageProduct/GcPageProductRows.tsx deleted file mode 100644 index ff369ce3818..00000000000 --- a/packages/graphql-gc-api/components/GcPageProduct/GcPageProductRows.tsx +++ /dev/null @@ -1,38 +0,0 @@ -import { - TypeRenderer, - filterNonNullableKeys, - LazyHydrate, - RenderType, -} from '@graphcommerce/next-ui' -import { GcPage_Product_DataFragment } from '../GcPage/GcPage_Product_Data.gql' -import { GcPageProduct_DataFragment } from './GcPageProduct_Data.gql' -import { GcPageProduct_Product_DataFragment } from './GcPageProduct_Product_Data.gql' - -type GcRowTypeRenderer = TypeRenderer< - NonNullable>[number]> -> - -export type GcPageProductRowsProps

    = { - page: GcPageProduct_DataFragment | null | undefined - renderer?: GcRowTypeRenderer - loadingEager?: number - product: P -} - -export function GcPageProductRows< - P extends GcPageProduct_Product_DataFragment & GcPage_Product_DataFragment, ->(props: GcPageProductRowsProps

    ) { - const { renderer, page, loadingEager = 2 } = props - - if (!renderer || !page) return null - - return ( - <> - {filterNonNullableKeys(page?.rows)?.map((item, index) => ( - - - - ))} - - ) -} diff --git a/packages/graphql-gc-api/components/GcPageProduct/GcPageProduct_Product_Data.graphql b/packages/graphql-gc-api/components/GcPageProduct/GcPageProduct_Product_Data.graphql deleted file mode 100644 index 8437240770b..00000000000 --- a/packages/graphql-gc-api/components/GcPageProduct/GcPageProduct_Product_Data.graphql +++ /dev/null @@ -1,3 +0,0 @@ -fragment GcPageProduct_Product_Data on ProductInterface { - ...GcPage_Product_Data -} diff --git a/packages/graphql-gc-api/components/GcPageProduct/index.ts b/packages/graphql-gc-api/components/GcPageProduct/index.ts deleted file mode 100644 index 67a54fd3124..00000000000 --- a/packages/graphql-gc-api/components/GcPageProduct/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from './GcPageProductRows' -export * from './GcPageProduct_Product_Data.gql' diff --git a/packages/graphql-gc-api/components/Page/Page.graphql b/packages/graphql-gc-api/components/Page/Page.graphql new file mode 100644 index 00000000000..a35675e17ae --- /dev/null +++ b/packages/graphql-gc-api/components/Page/Page.graphql @@ -0,0 +1,6 @@ +query Page($input: GCPageInput!) { + page(input: $input) { + ...Page_Redirect + ...Page_Data + } +} diff --git a/packages/graphql-gc-api/components/GcPage/GcPageRows.tsx b/packages/graphql-gc-api/components/Page/PageRows.tsx similarity index 61% rename from packages/graphql-gc-api/components/GcPage/GcPageRows.tsx rename to packages/graphql-gc-api/components/Page/PageRows.tsx index 3584d27e7ff..26ce0e462ff 100644 --- a/packages/graphql-gc-api/components/GcPage/GcPageRows.tsx +++ b/packages/graphql-gc-api/components/Page/PageRows.tsx @@ -5,19 +5,19 @@ import { type TypeRenderer, } from '@graphcommerce/next-ui' import React from 'react' -import { GcPage_DataFragment } from './GcPage_Data.gql' +import { Page_DataFragment } from './Page_Data.gql' -type GcRowTypeRenderer = TypeRenderer< - NonNullable>[number]> +type PageRowTypeRenderer = TypeRenderer< + NonNullable>[number]> > -export type GcPageRowsProps = { - page: GcPage_DataFragment | null | undefined - renderer?: GcRowTypeRenderer +export type PageRowsProps = { + page: Page_DataFragment | null | undefined + renderer?: PageRowTypeRenderer loadingEager?: number } -export const GcPageRows = React.memo((props: GcPageRowsProps) => { +export const PageRows = React.memo((props: PageRowsProps) => { const { renderer, page, loadingEager = 2 } = props if (!renderer || !page) return null diff --git a/packages/graphql-gc-api/components/Page/Page_Data.graphql b/packages/graphql-gc-api/components/Page/Page_Data.graphql new file mode 100644 index 00000000000..363dbef7bc1 --- /dev/null +++ b/packages/graphql-gc-api/components/Page/Page_Data.graphql @@ -0,0 +1,10 @@ +# This fragment is used in the Page query to retrieve the data for a page. +fragment Page_Data on Page { + ...Page_Head + rows { + __typename + ... on PageRowFake { + id + } + } +} diff --git a/packages/graphql-gc-api/components/Page/Page_Product_Data.graphql b/packages/graphql-gc-api/components/Page/Page_Product_Data.graphql new file mode 100644 index 00000000000..c2d7322c451 --- /dev/null +++ b/packages/graphql-gc-api/components/Page/Page_Product_Data.graphql @@ -0,0 +1,4 @@ +fragment Page_Product_Data on ProductInterface { + uid + __typename +} diff --git a/packages/graphql-gc-api/components/Page/index.ts b/packages/graphql-gc-api/components/Page/index.ts new file mode 100644 index 00000000000..92ddd5a6aab --- /dev/null +++ b/packages/graphql-gc-api/components/Page/index.ts @@ -0,0 +1,4 @@ +export * from './PageRows' +export * from './Page_Data.gql' +export * from './Page_Product_Data.gql' +export * from './Page.gql' diff --git a/packages/graphql-gc-api/components/GcPageMeta/GcPageHead.tsx b/packages/graphql-gc-api/components/PageHead/PageHead.tsx similarity index 89% rename from packages/graphql-gc-api/components/GcPageMeta/GcPageHead.tsx rename to packages/graphql-gc-api/components/PageHead/PageHead.tsx index 3068b2e0d6e..95361bc82c8 100644 --- a/packages/graphql-gc-api/components/GcPageMeta/GcPageHead.tsx +++ b/packages/graphql-gc-api/components/PageHead/PageHead.tsx @@ -2,14 +2,14 @@ import { usePageContext } from '@graphcommerce/framer-next-pages' import { canonicalize } from '@graphcommerce/next-ui' import Head from 'next/head' import { useRouter } from 'next/router' -import { GcPage_HeadFragment, GcMetaTagFragment, GcLinkRelTagFragment } from './GcPage_Head.gql' +import { Page_HeadFragment, GcMetaTagFragment, GcLinkRelTagFragment } from './Page_Head.gql' -type GcPageMetaProps = { - page: GcPage_HeadFragment +type PageMetaProps = { + page: Page_HeadFragment children?: React.ReactNode } -export function GcPageMeta(props: GcPageMetaProps) { +export function PageMeta(props: PageMetaProps) { const { page: { head }, children, diff --git a/packages/graphql-gc-api/components/GcPageMeta/GcPage_Head.graphql b/packages/graphql-gc-api/components/PageHead/Page_Head.graphql similarity index 91% rename from packages/graphql-gc-api/components/GcPageMeta/GcPage_Head.graphql rename to packages/graphql-gc-api/components/PageHead/Page_Head.graphql index e3a0e9592dd..9cd7f5a3ccf 100644 --- a/packages/graphql-gc-api/components/GcPageMeta/GcPage_Head.graphql +++ b/packages/graphql-gc-api/components/PageHead/Page_Head.graphql @@ -9,7 +9,7 @@ fragment GcMetaTag on GcMetaTag { content } -fragment GcPage_Head on GcPage { +fragment Page_Head on Page { head { title description diff --git a/packages/graphql-gc-api/components/PageHead/index.ts b/packages/graphql-gc-api/components/PageHead/index.ts new file mode 100644 index 00000000000..1ebba80ec24 --- /dev/null +++ b/packages/graphql-gc-api/components/PageHead/index.ts @@ -0,0 +1 @@ +export * from './PageHead' diff --git a/packages/graphql-gc-api/components/PageProduct/PageProduct.graphql b/packages/graphql-gc-api/components/PageProduct/PageProduct.graphql new file mode 100644 index 00000000000..34b72839175 --- /dev/null +++ b/packages/graphql-gc-api/components/PageProduct/PageProduct.graphql @@ -0,0 +1,6 @@ +fragment PageProduct on ProductInterface { + page { + ...PageProduct_Data + } + ...PageProduct_Product_Data +} diff --git a/packages/graphql-gc-api/components/PageProduct/PageProductRows.tsx b/packages/graphql-gc-api/components/PageProduct/PageProductRows.tsx new file mode 100644 index 00000000000..a3514088934 --- /dev/null +++ b/packages/graphql-gc-api/components/PageProduct/PageProductRows.tsx @@ -0,0 +1,38 @@ +import { + TypeRenderer, + filterNonNullableKeys, + LazyHydrate, + RenderType, +} from '@graphcommerce/next-ui' +import { Page_Product_DataFragment } from '../Page/Page_Product_Data.gql' +import { PageProduct_DataFragment } from './PageProduct_Data' +import { PageProduct_Product_DataFragment } from './PageProduct_Product_Data' + +type PageRowTypeRenderer = TypeRenderer< + NonNullable>[number]> +> + +export type PageProductRowsProps

    = { + page: PageProduct_DataFragment | null | undefined + renderer?: PageRowTypeRenderer + loadingEager?: number + product: P +} + +export function PageProductRows< + P extends PageProduct_Product_DataFragment & Page_Product_DataFragment, +>(props: PageProductRowsProps

    ) { + const { renderer, page, loadingEager = 2 } = props + + if (!renderer || !page) return null + + return ( + <> + {filterNonNullableKeys(page?.rows)?.map((item, index) => ( + + + + ))} + + ) +} diff --git a/packages/graphql-gc-api/components/GcPageProduct/GcPageProduct_Data.graphql b/packages/graphql-gc-api/components/PageProduct/PageProduct_Data.graphql similarity index 53% rename from packages/graphql-gc-api/components/GcPageProduct/GcPageProduct_Data.graphql rename to packages/graphql-gc-api/components/PageProduct/PageProduct_Data.graphql index 26f64bc09ab..fc6e37809f0 100644 --- a/packages/graphql-gc-api/components/GcPageProduct/GcPageProduct_Data.graphql +++ b/packages/graphql-gc-api/components/PageProduct/PageProduct_Data.graphql @@ -1,5 +1,5 @@ # This fragment is added to the ProductPage2 query when the product page is loaded. -fragment GcPageProduct_Data on GcPage { - ...GcPage_Head - ...GcPage_Data +fragment PageProduct_Data on Page { + ...Page_Head + ...Page_Data } diff --git a/packages/graphql-gc-api/components/PageProduct/PageProduct_Product_Data.graphql b/packages/graphql-gc-api/components/PageProduct/PageProduct_Product_Data.graphql new file mode 100644 index 00000000000..bb3f9b404c5 --- /dev/null +++ b/packages/graphql-gc-api/components/PageProduct/PageProduct_Product_Data.graphql @@ -0,0 +1,3 @@ +fragment PageProduct_Product_Data on ProductInterface { + ...Page_Product_Data +} diff --git a/packages/graphql-gc-api/components/PageProduct/index.ts b/packages/graphql-gc-api/components/PageProduct/index.ts new file mode 100644 index 00000000000..6a492a6783c --- /dev/null +++ b/packages/graphql-gc-api/components/PageProduct/index.ts @@ -0,0 +1,2 @@ +export * from './PageProductRows' +export * from './PageProduct_Product_Data.gql' diff --git a/packages/graphql-gc-api/components/index.ts b/packages/graphql-gc-api/components/index.ts index 0c368110900..4cab92fad69 100644 --- a/packages/graphql-gc-api/components/index.ts +++ b/packages/graphql-gc-api/components/index.ts @@ -1,3 +1,3 @@ -export * from './GcPage' -export * from './GcPageProduct' -export * from './GcPageMeta' +export * from './Page' +export * from './PageProduct' +export * from './PageHead' diff --git a/packages/graphql-gc-api/schema/CategoryInterface_gcPage.graphqls b/packages/graphql-gc-api/schema/CategoryInterface_gcPage.graphqls index 7aa74f8cc39..a1d6589e020 100644 --- a/packages/graphql-gc-api/schema/CategoryInterface_gcPage.graphqls +++ b/packages/graphql-gc-api/schema/CategoryInterface_gcPage.graphqls @@ -1,7 +1,7 @@ interface CategoryInterface { - gcPage: GcPage + page: Page } type CategoryTree { - gcPage: GcPage + page: Page } diff --git a/packages/graphql-gc-api/schema/GcRow.graphqls b/packages/graphql-gc-api/schema/GcRow.graphqls deleted file mode 100644 index d15811d30b4..00000000000 --- a/packages/graphql-gc-api/schema/GcRow.graphqls +++ /dev/null @@ -1,8 +0,0 @@ -""" -This type only exists to make the GcRow union not fail. -""" -type GcRowFake { - id: ID! -} - -union GcRow = GcRowFake diff --git a/packages/graphql-gc-api/schema/GcPage.graphqls b/packages/graphql-gc-api/schema/Page.graphqls similarity index 50% rename from packages/graphql-gc-api/schema/GcPage.graphqls rename to packages/graphql-gc-api/schema/Page.graphqls index 32996ca3024..4947748cfa5 100644 --- a/packages/graphql-gc-api/schema/GcPage.graphqls +++ b/packages/graphql-gc-api/schema/Page.graphqls @@ -1,16 +1,25 @@ -type GcPage { +""" +This type only exists to make the PageRow union not fail. +""" +type PageRowFake { + id: ID! +} + +union PageRow = PageRowFake + +type Page { """ The head of the page. """ - head: GcPageHead + head: PageHead """ When the redirect is defined the page should not be rendered and the user should be redirected to the specified URL. """ - redirect: GcPageRedirect + redirect: PageRedirect """ Rows of the content """ - rows: [GcRow] + rows: [PageRow] } diff --git a/packages/graphql-gc-api/schema/GcPageHead.graphqls b/packages/graphql-gc-api/schema/PageHead.graphqls similarity index 99% rename from packages/graphql-gc-api/schema/GcPageHead.graphqls rename to packages/graphql-gc-api/schema/PageHead.graphqls index 5f54ce1d832..2e5669df19c 100644 --- a/packages/graphql-gc-api/schema/GcPageHead.graphqls +++ b/packages/graphql-gc-api/schema/PageHead.graphqls @@ -62,7 +62,7 @@ type GcLinkRelTag { href: String! } -type GcPageHead { +type PageHead { """ element of the page """ diff --git a/packages/graphql-gc-api/schema/GcPageRedirect.graphqls b/packages/graphql-gc-api/schema/PageRedirect.graphqls similarity index 94% rename from packages/graphql-gc-api/schema/GcPageRedirect.graphqls rename to packages/graphql-gc-api/schema/PageRedirect.graphqls index 5210e8f5f31..e3299ba41e3 100644 --- a/packages/graphql-gc-api/schema/GcPageRedirect.graphqls +++ b/packages/graphql-gc-api/schema/PageRedirect.graphqls @@ -1,4 +1,4 @@ -type GcPageRedirect { +type PageRedirect { """ A fully qualified URL diff --git a/packages/graphql-gc-api/schema/ProductInterface_gcPage.graphqls b/packages/graphql-gc-api/schema/ProductInterface_gcPage.graphqls index 61b73c06823..9d11801afaa 100644 --- a/packages/graphql-gc-api/schema/ProductInterface_gcPage.graphqls +++ b/packages/graphql-gc-api/schema/ProductInterface_gcPage.graphqls @@ -1,31 +1,31 @@ interface ProductInterface { - gcPage: GcPage + page: Page } type BundleProduct { - gcPage: GcPage + page: Page } type SimpleProduct { - gcPage: GcPage + page: Page } type VirtualProduct { - gcPage: GcPage + page: Page } type DownloadableProduct { - gcPage: GcPage + page: Page } type GiftCardProduct { - gcPage: GcPage + page: Page } type ConfigurableProduct { - gcPage: GcPage + page: Page } type GroupedProduct { - gcPage: GcPage + page: Page } diff --git a/packages/graphql-gc-api/schema/Query_gcLayout.graphqls b/packages/graphql-gc-api/schema/Query_gcLayout.graphqls deleted file mode 100644 index 93a57a34a99..00000000000 --- a/packages/graphql-gc-api/schema/Query_gcLayout.graphqls +++ /dev/null @@ -1,11 +0,0 @@ -input GCLayoutInput { - scope: String! -} - -type GcLayout { - menu: GcMenu -} - -extend type Query { - gcLayout(input: GCLayoutInput!): GcLayout -} diff --git a/packages/graphql-gc-api/schema/Query_gcPage.graphqls b/packages/graphql-gc-api/schema/Query_page.graphqls similarity index 61% rename from packages/graphql-gc-api/schema/Query_gcPage.graphqls rename to packages/graphql-gc-api/schema/Query_page.graphqls index 36f0c013cec..a3fc2ef6d18 100644 --- a/packages/graphql-gc-api/schema/Query_gcPage.graphqls +++ b/packages/graphql-gc-api/schema/Query_page.graphqls @@ -3,5 +3,5 @@ input GCPageInput { } extend type Query { - gcPage(input: GCPageInput!): GcPage + page(input: GCPageInput!): Page } diff --git a/packages/graphql-gc-api/schema/Query_gcCanonicals.graphqls b/packages/graphql-gc-api/schema/Query_pageCanonicals.graphqls similarity index 55% rename from packages/graphql-gc-api/schema/Query_gcCanonicals.graphqls rename to packages/graphql-gc-api/schema/Query_pageCanonicals.graphqls index 2032fc332ae..53585f3013f 100644 --- a/packages/graphql-gc-api/schema/Query_gcCanonicals.graphqls +++ b/packages/graphql-gc-api/schema/Query_pageCanonicals.graphqls @@ -1,8 +1,8 @@ -type GcPagesListOutput { +type PagesListOutput { canonicals: [GcLinkRelTag!] } -input GcPagesListInput { +input PagesListInput { """ Provide a base path to filter the list of pages. """ @@ -10,5 +10,5 @@ input GcPagesListInput { } extend type Query { - gcPageCanonicals(input: GcPagesListInput): GcPagesListOutput + pageCanonicals(input: PagesListInput): PagesListOutput } diff --git a/packages/graphql-gc-api/schema/Query_pageLayout.graphqls b/packages/graphql-gc-api/schema/Query_pageLayout.graphqls new file mode 100644 index 00000000000..0d13ed9506a --- /dev/null +++ b/packages/graphql-gc-api/schema/Query_pageLayout.graphqls @@ -0,0 +1,11 @@ +input PageLayoutInput { + scope: String! +} + +type PageLayout { + menu: GcMenu +} + +extend type Query { + pageLayout(input: PageLayoutInput!): PageLayout +} diff --git a/packages/graphql-gc-api/utils/GcPage_Redirect.graphql b/packages/graphql-gc-api/utils/GcPage_Redirect.graphql index 3dcfcfd5bca..32dedc1357d 100644 --- a/packages/graphql-gc-api/utils/GcPage_Redirect.graphql +++ b/packages/graphql-gc-api/utils/GcPage_Redirect.graphql @@ -1,4 +1,4 @@ -fragment GcPage_Redirect on GcPage { +fragment Page_Redirect on Page { redirect { destination permanent diff --git a/packages/graphql-gc-api/utils/gcPageRedirectOrNotFound.ts b/packages/graphql-gc-api/utils/gcPageRedirectOrNotFound.ts index 9f689d081c9..8240ce6fe79 100644 --- a/packages/graphql-gc-api/utils/gcPageRedirectOrNotFound.ts +++ b/packages/graphql-gc-api/utils/gcPageRedirectOrNotFound.ts @@ -1,44 +1,44 @@ import type { SimplifyDeep, SetRequired } from 'type-fest' -import type { GcPageQuery } from '../components/GcPage/GcPage.gql' +import type { PageQuery } from '../components/Page/Page.gql' import { Redirect } from 'next' -type FoundPage = NonNullable<GcPageQuery['page']> +type FoundPage = NonNullable<PageQuery['page']> -export type GcPage = { +export type Page = { page: Omit<FoundPage, 'redirect'> } -export type GcPageRedirect = { +export type PageRedirect = { page: { redirect: NonNullable<FoundPage['redirect']> } } -export type GcPageNotFound = { page?: null | undefined } +export type PageNotFound = { page?: null | undefined } -export function isGcPageNotFound( - query: GcPage | GcPageRedirect | GcPageNotFound | null | undefined, -): query is GcPageNotFound { +export function isPageNotFound( + query: Page | PageRedirect | PageNotFound | null | undefined, +): query is PageNotFound { return !query?.page } -export function isGcPageRedirect( - query: GcPage | GcPageRedirect | GcPageNotFound | null | undefined, -): query is GcPageRedirect { +export function isPageRedirect( + query: Page | PageRedirect | PageNotFound | null | undefined, +): query is PageRedirect { return Boolean(query?.page && 'redirect' in query.page && query.page.redirect) } -export function isGcPageFound( - query: GcPage | GcPageRedirect | GcPageNotFound | null | undefined, -): query is GcPage { - return !isGcPageNotFound(query) && !isGcPageRedirect(query) +export function isPageFound( + query: Page | PageRedirect | PageNotFound | null | undefined, +): query is Page { + return !isPageNotFound(query) && !isPageRedirect(query) } -export function gcPageRedirectOrNotFound( - query: GcPageQuery | null | undefined, +export function pageRedirectOrNotFound( + query: PageQuery | null | undefined, ): { redirect: Redirect; revalidate?: number | boolean } | { notFound: true } { - if (isGcPageRedirect(query)) return { redirect: query.page.redirect } - if (isGcPageNotFound(query)) return { notFound: true } + if (isPageRedirect(query)) return { redirect: query.page.redirect } + if (isPageNotFound(query)) return { notFound: true } throw Error( - 'gcPageRedirectOrNotFound should only be called when it isGcPageFound(query) returns false', + 'pageRedirectOrNotFound should only be called when it isPageFound(query) returns false', ) } diff --git a/packages/graphql-gc-api/utils/index.ts b/packages/graphql-gc-api/utils/index.ts index cdace8a1791..f30597ff500 100644 --- a/packages/graphql-gc-api/utils/index.ts +++ b/packages/graphql-gc-api/utils/index.ts @@ -1,2 +1,2 @@ -export * from './GcPage_Redirect.gql' -export * from './gcPageRedirectOrNotFound' +export * from './Page_Redirect.gql' +export * from './pageRedirectOrNotFound' diff --git a/packages/hygraph-dynamic-rows/mesh/resolvers.ts b/packages/hygraph-dynamic-rows/mesh/resolvers.ts index 0fb03bf6397..c7d6af56e23 100644 --- a/packages/hygraph-dynamic-rows/mesh/resolvers.ts +++ b/packages/hygraph-dynamic-rows/mesh/resolvers.ts @@ -48,7 +48,7 @@ async function getAllHygraphDynamicRows( } export const resolvers: Resolvers = { - // GcPage: { + // Page: { // rows: { // resolve: async (parent, args, context, info) => { // const execute = createDocumentExecutor(context, parent, info) diff --git a/packages/hygraph-ui/graphql/HygraphPage.graphql b/packages/hygraph-ui/graphql/HygraphPage.graphql index e2389ad4286..61c19e7a5a3 100644 --- a/packages/hygraph-ui/graphql/HygraphPage.graphql +++ b/packages/hygraph-ui/graphql/HygraphPage.graphql @@ -1,4 +1,4 @@ -fragment HygraphPage on GcPage @inject(into: ["GcPage_Head"]) { +fragment HygraphPage on Page @inject(into: ["Page_Head"]) { author date relatedPages { diff --git a/packages/hygraph-ui/mesh/resolvers.ts b/packages/hygraph-ui/mesh/resolvers.ts index 9fe3f717bc8..f58f75bb22f 100644 --- a/packages/hygraph-ui/mesh/resolvers.ts +++ b/packages/hygraph-ui/mesh/resolvers.ts @@ -21,7 +21,7 @@ const denormalizeUrl = (href: string) => { return cleanedhref === '' ? 'page/home' : cleanedhref } -type GCPageResolver = NonNullable<Resolvers['SimpleProduct']>['gcPage'] +type GCPageResolver = NonNullable<Resolvers['SimpleProduct']>['page'] export const contextData = new WeakMap<MeshContext, Record<string, ProductInterface>>() @@ -47,7 +47,7 @@ function isRowProduct(row: PageContent): row is RowProduct { return '__typename' in row && row.__typename === 'RowProduct' } -const gcPageProductResolver: GCPageResolver = { +const pageProductResolver: GCPageResolver = { selectionSet: `{url_key}`, resolve: async (root, args, context, info) => { if (!root.url_key) return null @@ -81,9 +81,9 @@ const gcPageProductResolver: GCPageResolver = { } export const resolvers: Resolvers = { - // Resolve the query `gcPage` to a page with the given URL + // Resolve the query `page` to a page with the given URL Query: { - gcPage: { + page: { resolve: (root, args, context, info) => context.hygraph.Query.pages({ root, @@ -94,7 +94,7 @@ export const resolvers: Resolvers = { }, }, - GcPage: { + Page: { rows: { selectionSet: (root) => ({ kind: Kind.SELECTION_SET, @@ -157,16 +157,16 @@ export const resolvers: Resolvers = { }, }, - SimpleProduct: { gcPage: gcPageProductResolver }, - ConfigurableProduct: { gcPage: gcPageProductResolver }, - BundleProduct: { gcPage: gcPageProductResolver }, - VirtualProduct: { gcPage: gcPageProductResolver }, - DownloadableProduct: { gcPage: gcPageProductResolver }, - GroupedProduct: { gcPage: gcPageProductResolver }, + SimpleProduct: { page: pageProductResolver }, + ConfigurableProduct: { page: pageProductResolver }, + BundleProduct: { page: pageProductResolver }, + VirtualProduct: { page: pageProductResolver }, + DownloadableProduct: { page: pageProductResolver }, + GroupedProduct: { page: pageProductResolver }, // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore GiftCardProduct is only available in Commerce - GiftCardProduct: { gcPage: gcPageProductResolver }, + GiftCardProduct: { page: pageProductResolver }, RowProduct: { product: { From 8accbfd6e1ca4fab5a6d666e18a66edf9a609809 Mon Sep 17 00:00:00 2001 From: Paul Hachmang <paul@reachdigital.nl> Date: Fri, 9 Aug 2024 10:41:19 +0200 Subject: [PATCH 33/33] Wip products --- .../GraphCMS/GcPage_Data_Hygraph.graphql | 2 +- .../RowProduct/GetMagentoRowProduct.graphql | 2 +- .../GraphCMS/RowProduct/RowProduct.tsx | 42 +-- .../RowProduct/RowProductDeprecated.tsx | 19 ++ .../GraphCMS/RowProduct/RowProductPage.tsx | 3 + .../PageProductRows_RowProduct.graphql | 2 +- .../graphql/PageProduct_RowProduct.graphql | 11 +- .../graphql/PageRows_RowProduct.graphql | 2 +- .../graphql/Page_RowProduct.graphql | 2 +- .../RowProduct/graphql/RowProduct.graphql | 2 +- .../graphql/ProductPage2.graphql | 2 +- examples/magento-graphcms/pages/[...url].tsx | 286 ++++++++++-------- examples/magento-graphcms/pages/index.tsx | 11 +- .../plugins/hygraph/HygraphGcPageRows.tsx | 6 +- .../components/Page/Page.graphql | 3 +- .../components/Page/Page_Product_Data.graphql | 4 - .../graphql-gc-api/components/Page/index.ts | 3 - .../PageCategory/PageCategoryRows.tsx | 37 +++ .../PageCategory/PageCategory_Data.graphql | 5 + .../PageCategory/PageProduct.graphql | 6 + .../{Page_Head.graphql => PageHead.graphql} | 3 +- .../components/PageHead/PageHead.tsx | 4 +- .../PageProduct/PageProduct.graphql | 6 - .../PageProduct/PageProduct_Data.graphql | 5 - .../PageProduct_Product_Data.graphql | 3 - .../PageProduct/ProductPageRows.graphql | 7 + ...ageProductRows.tsx => ProductPageRows.tsx} | 16 +- .../ProductPageRows_ProductData.graphql | 3 + .../components/PageProduct/index.ts | 4 +- .../PageRows.graphql} | 3 +- .../{Page => PageRows}/PageRows.tsx | 6 +- .../PageRows/PageRows_CategoryData.graphql | 5 + .../PageRows/PageRows_ProductData.graphql | 5 + .../components/PageRows/index.ts | 2 + packages/graphql-gc-api/components/index.ts | 3 +- ...Redirect.graphql => Page_Redirect.graphql} | 0 ...rNotFound.ts => pageRedirectOrNotFound.ts} | 8 + .../hygraph-ui/graphql/HygraphPage.graphql | 2 +- packages/hygraph-ui/mesh/resolvers.ts | 57 +++- .../utils/findParentBreadcrumbItem.ts | 6 +- 40 files changed, 360 insertions(+), 238 deletions(-) create mode 100644 examples/magento-graphcms/components/GraphCMS/RowProduct/RowProductDeprecated.tsx delete mode 100644 packages/graphql-gc-api/components/Page/Page_Product_Data.graphql create mode 100644 packages/graphql-gc-api/components/PageCategory/PageCategoryRows.tsx create mode 100644 packages/graphql-gc-api/components/PageCategory/PageCategory_Data.graphql create mode 100644 packages/graphql-gc-api/components/PageCategory/PageProduct.graphql rename packages/graphql-gc-api/components/PageHead/{Page_Head.graphql => PageHead.graphql} (83%) delete mode 100644 packages/graphql-gc-api/components/PageProduct/PageProduct.graphql delete mode 100644 packages/graphql-gc-api/components/PageProduct/PageProduct_Data.graphql delete mode 100644 packages/graphql-gc-api/components/PageProduct/PageProduct_Product_Data.graphql create mode 100644 packages/graphql-gc-api/components/PageProduct/ProductPageRows.graphql rename packages/graphql-gc-api/components/PageProduct/{PageProductRows.tsx => ProductPageRows.tsx} (53%) create mode 100644 packages/graphql-gc-api/components/PageProduct/ProductPageRows_ProductData.graphql rename packages/graphql-gc-api/components/{Page/Page_Data.graphql => PageRows/PageRows.graphql} (76%) rename packages/graphql-gc-api/components/{Page => PageRows}/PageRows.tsx (80%) create mode 100644 packages/graphql-gc-api/components/PageRows/PageRows_CategoryData.graphql create mode 100644 packages/graphql-gc-api/components/PageRows/PageRows_ProductData.graphql create mode 100644 packages/graphql-gc-api/components/PageRows/index.ts rename packages/graphql-gc-api/utils/{GcPage_Redirect.graphql => Page_Redirect.graphql} (100%) rename packages/graphql-gc-api/utils/{gcPageRedirectOrNotFound.ts => pageRedirectOrNotFound.ts} (81%) diff --git a/examples/magento-graphcms/components/GraphCMS/GcPage_Data_Hygraph.graphql b/examples/magento-graphcms/components/GraphCMS/GcPage_Data_Hygraph.graphql index 2e5614c523c..8bfb0c3a5ee 100644 --- a/examples/magento-graphcms/components/GraphCMS/GcPage_Data_Hygraph.graphql +++ b/examples/magento-graphcms/components/GraphCMS/GcPage_Data_Hygraph.graphql @@ -1,4 +1,4 @@ -fragment Page_Data_Hygraph on Page @inject(into: ["Page_Data"]) { +fragment PageRows_Hygraph on Page @inject(into: ["PageRows"]) { rows { __typename ... on Node { diff --git a/examples/magento-graphcms/components/GraphCMS/RowProduct/GetMagentoRowProduct.graphql b/examples/magento-graphcms/components/GraphCMS/RowProduct/GetMagentoRowProduct.graphql index 2f0d42d9ec8..b1fb3eade1a 100644 --- a/examples/magento-graphcms/components/GraphCMS/RowProduct/GetMagentoRowProduct.graphql +++ b/examples/magento-graphcms/components/GraphCMS/RowProduct/GetMagentoRowProduct.graphql @@ -2,7 +2,7 @@ query GetMagentoRowProduct($urlKey: String!) { products(filter: { url_key: { eq: $urlKey } }, pageSize: 1) { items { uid - ...Page_Product_Data + ...PageRows_CategoryData } } } diff --git a/examples/magento-graphcms/components/GraphCMS/RowProduct/RowProduct.tsx b/examples/magento-graphcms/components/GraphCMS/RowProduct/RowProduct.tsx index 0b3bc16defd..25bdcdb6073 100644 --- a/examples/magento-graphcms/components/GraphCMS/RowProduct/RowProduct.tsx +++ b/examples/magento-graphcms/components/GraphCMS/RowProduct/RowProduct.tsx @@ -1,9 +1,8 @@ import { InContextMaskProvider, useInContextQuery } from '@graphcommerce/graphql' import { ProductListItemRenderer } from '@graphcommerce/magento-product' -import { Box } from '@mui/material' -import { useRouter } from 'next/router' import { productListRenderer } from '../../ProductListItems' import { GetMagentoRowProductDocument } from './GetMagentoRowProduct.gql' +import { RowProductDeprecated } from './RowProductDeprecated' import { RowProductFragment } from './graphql/RowProduct.gql' import { Backstory, Feature, FeatureBoxed } from './variant' @@ -16,41 +15,6 @@ type RowProductProps = RowProductFragment & { renderer?: Partial<VariantRenderer> } -function RowProductPreview(props: RowProductProps) { - const { variant, identity, product } = props - - const router = useRouter() - const canShow = router.isPreview || process.env.NODE_ENV !== 'production' - const shouldBeRowCategory = variant === 'Grid' || variant === 'Swipeable' - const noProduct = !product - if (!canShow) return null - if (!(noProduct || shouldBeRowCategory)) return null - - return ( - <Box - sx={(theme) => ({ - p: 2, - m: 3, - border: `3px dashed ${theme.palette.error.light}`, - borderRadius: 2, - })} - > - {shouldBeRowCategory && ( - <> - RowProduct with identity ‘{identity}’ and variant ‘{variant}’, should be migrated in - Hygraph to a RowCategory component. - </> - )} - {!shouldBeRowCategory && noProduct && ( - <> - RowProduct ({identity}) was configured with Product URL " - <code>{identity}</code>", However Magento didn't return any results. - </> - )} - </Box> - ) -} - const defaultRenderer: Partial<VariantRenderer> = { Backstory, Feature, @@ -59,6 +23,8 @@ const defaultRenderer: Partial<VariantRenderer> = { Reviews: () => <>Only available on the product page</>, Specs: () => <>Only available on the product page</>, Upsells: () => <>Only available on the product page</>, + Grid: RowProductDeprecated, + Swipeable: RowProductDeprecated, } export function RowProduct(props: RowProductProps) { @@ -77,7 +43,7 @@ export function RowProduct(props: RowProductProps) { return ( <InContextMaskProvider mask={scoped.mask}> - <RowProductPreview {...props} /> + {/* <RowProductDeprecated {...props} /> */} {RenderType && ( <RenderType {...props} diff --git a/examples/magento-graphcms/components/GraphCMS/RowProduct/RowProductDeprecated.tsx b/examples/magento-graphcms/components/GraphCMS/RowProduct/RowProductDeprecated.tsx new file mode 100644 index 00000000000..6ce6fa4aa8a --- /dev/null +++ b/examples/magento-graphcms/components/GraphCMS/RowProduct/RowProductDeprecated.tsx @@ -0,0 +1,19 @@ +import { Box } from '@mui/material' +import { RowProductFragment } from './graphql/RowProduct.gql' + +export function RowProductDeprecated(props: RowProductFragment) { + const { variant, identity } = props + return process.env.NODE_ENV === 'development' ? ( + <Box + sx={(theme) => ({ + p: 2, + m: 3, + border: `3px dashed ${theme.palette.error.light}`, + borderRadius: 2, + })} + > + RowProduct with identity ‘{identity}’ and variant ‘{variant}’, should be migrated in Hygraph + to a RowCategory component. + </Box> + ) : null +} diff --git a/examples/magento-graphcms/components/GraphCMS/RowProduct/RowProductPage.tsx b/examples/magento-graphcms/components/GraphCMS/RowProduct/RowProductPage.tsx index 6a07f5a4f7b..2dee4c7042d 100644 --- a/examples/magento-graphcms/components/GraphCMS/RowProduct/RowProductPage.tsx +++ b/examples/magento-graphcms/components/GraphCMS/RowProduct/RowProductPage.tsx @@ -1,5 +1,6 @@ import { ProductListItemRenderer } from '@graphcommerce/magento-product' import { productListRenderer } from '../../ProductListItems' +import { RowProductDeprecated } from './RowProductDeprecated' import { RowProduct_ProductPageFragment } from './graphql/RowProduct_ProductPage.gql' import { Backstory, Feature, FeatureBoxed, Related, Reviews, Specs, Upsells } from './variant' @@ -20,6 +21,8 @@ const defaultRenderer: Partial<VariantRenderer> = { Related, Reviews, Upsells, + Grid: RowProductDeprecated, + Swipeable: RowProductDeprecated, } export function RowProductPage(props: RowProductPageProps) { diff --git a/examples/magento-graphcms/components/GraphCMS/RowProduct/graphql/PageProductRows_RowProduct.graphql b/examples/magento-graphcms/components/GraphCMS/RowProduct/graphql/PageProductRows_RowProduct.graphql index 15a9ce3c113..52b3c507032 100644 --- a/examples/magento-graphcms/components/GraphCMS/RowProduct/graphql/PageProductRows_RowProduct.graphql +++ b/examples/magento-graphcms/components/GraphCMS/RowProduct/graphql/PageProductRows_RowProduct.graphql @@ -1,5 +1,5 @@ fragment PageProductRows_RowProduct on ProductInterface -@inject(into: ["PageProduct_Product_Data"]) { +@inject(into: ["ProductPageRows_ProductData"]) { ...UpsellProducts ...RelatedProducts ...ProductReviews diff --git a/examples/magento-graphcms/components/GraphCMS/RowProduct/graphql/PageProduct_RowProduct.graphql b/examples/magento-graphcms/components/GraphCMS/RowProduct/graphql/PageProduct_RowProduct.graphql index 908f286a94c..de7834b170e 100644 --- a/examples/magento-graphcms/components/GraphCMS/RowProduct/graphql/PageProduct_RowProduct.graphql +++ b/examples/magento-graphcms/components/GraphCMS/RowProduct/graphql/PageProduct_RowProduct.graphql @@ -1,7 +1,8 @@ -# When we're requesting a **product page** also request the RowProduct_ProductPage fragment -fragment PageProduct_RowProduct on Page @inject(into: ["PageProduct_Data"]) { - rows { - __typename - ...RowProduct_ProductPage +fragment PageProduct_RowProduct on ProductInterface @inject(into: ["ProductPageRows"]) { + page { + rows { + __typename + ...RowProduct_ProductPage + } } } diff --git a/examples/magento-graphcms/components/GraphCMS/RowProduct/graphql/PageRows_RowProduct.graphql b/examples/magento-graphcms/components/GraphCMS/RowProduct/graphql/PageRows_RowProduct.graphql index 2c707592034..ffd014a0dee 100644 --- a/examples/magento-graphcms/components/GraphCMS/RowProduct/graphql/PageRows_RowProduct.graphql +++ b/examples/magento-graphcms/components/GraphCMS/RowProduct/graphql/PageRows_RowProduct.graphql @@ -1,4 +1,4 @@ -fragment Page_Product_RowProduct on ProductInterface @inject(into: ["Page_Product_Data"]) { +fragment Page_Product_RowProduct on ProductInterface @inject(into: ["PageRows_CategoryData"]) { ...ProductListItem ...ProductFeatureMediaBoxed } diff --git a/examples/magento-graphcms/components/GraphCMS/RowProduct/graphql/Page_RowProduct.graphql b/examples/magento-graphcms/components/GraphCMS/RowProduct/graphql/Page_RowProduct.graphql index fe50c632c4d..257a0dfd219 100644 --- a/examples/magento-graphcms/components/GraphCMS/RowProduct/graphql/Page_RowProduct.graphql +++ b/examples/magento-graphcms/components/GraphCMS/RowProduct/graphql/Page_RowProduct.graphql @@ -1,6 +1,6 @@ # When we're requesting a **non-product page** also request the RowProduct fragments. # For data specifc to the product page, see PageProduct_RowProduct.graphql -fragment Page_RowProduct on Page @inject(into: ["Page_Data"]) { +fragment Page_RowProduct on Page @inject(into: ["PageRows"]) { rows { __typename ...RowProduct diff --git a/examples/magento-graphcms/components/GraphCMS/RowProduct/graphql/RowProduct.graphql b/examples/magento-graphcms/components/GraphCMS/RowProduct/graphql/RowProduct.graphql index a2406973285..cb94b08d190 100644 --- a/examples/magento-graphcms/components/GraphCMS/RowProduct/graphql/RowProduct.graphql +++ b/examples/magento-graphcms/components/GraphCMS/RowProduct/graphql/RowProduct.graphql @@ -12,6 +12,6 @@ fragment RowProduct on RowProduct { ...PageLink } product { - ...Page_Product_Data + ...PageRows_CategoryData } } diff --git a/examples/magento-graphcms/graphql/ProductPage2.graphql b/examples/magento-graphcms/graphql/ProductPage2.graphql index 205b3aacc97..6238681583c 100644 --- a/examples/magento-graphcms/graphql/ProductPage2.graphql +++ b/examples/magento-graphcms/graphql/ProductPage2.graphql @@ -15,7 +15,7 @@ query ProductPage2( ...DownloadableProductOptions ...BundleProductOptions ...GroupedProduct - ...PageProduct + ...ProductPageRows } } } diff --git a/examples/magento-graphcms/pages/[...url].tsx b/examples/magento-graphcms/pages/[...url].tsx index 1329412e77f..0f6670ed79a 100644 --- a/examples/magento-graphcms/pages/[...url].tsx +++ b/examples/magento-graphcms/pages/[...url].tsx @@ -1,6 +1,16 @@ import { PageOptions } from '@graphcommerce/framer-next-pages' +import { Asset } from '@graphcommerce/graphcms-ui' import { cacheFirst, flushMeasurePerf, InContextMaskProvider } from '@graphcommerce/graphql' -import { PageRowsCategory, PageRowsCategoryBefore, PageQuery } from '@graphcommerce/graphql-gc-api' +import { + PageQuery, + PageDocument, + isPageRedirect, + pageRedirect, + PageRows, + isPageNotFound, + pageRedirectOrNotFound, + isPageFound, +} from '@graphcommerce/graphql-gc-api' import { appendSiblingsAsChildren, CategoryBreadcrumbs, @@ -36,130 +46,142 @@ import { LayoutDocument, LayoutNavigation, LayoutNavigationProps, - productListRenderer, - RowProduct, - RowRenderer, } from '../components' import { CategoryPageDocument, CategoryPageQuery } from '../graphql/CategoryPage.gql' import { graphqlSharedClient, graphqlSsrClient } from '../lib/graphql/graphqlSsrClient' -export type CategoryProps = PageQuery & - CategoryPageQuery & +export type CategoryProps = CategoryPageProps | RegularPageProps + +type CategoryPageProps = PageQuery & ProductListQuery & ProductFiltersQuery & { + category: NonNullable<NonNullable<NonNullable<CategoryPageQuery['categories']>['items']>[0]> filterTypes?: FilterTypes params?: ProductListParams } +type RegularPageProps = { page: NonNullable<PageQuery['page']> } + export type CategoryRoute = { url: string[] } type GetPageStaticPaths = GetStaticPaths<CategoryRoute> type GetPageStaticProps = GetStaticProps<LayoutNavigationProps, CategoryProps, CategoryRoute> -function CategoryPage(props: CategoryProps) { - const { page, categories, ...rest } = props - const productList = useProductList({ - ...rest, - category: categories?.items?.[0], - }) - const { products, params, category } = productList +function isCategoryPage(props: CategoryProps): props is CategoryPageProps { + return (props as CategoryPageProps).category !== undefined +} - const isLanding = category?.display_mode === 'PAGE' - const isCategory = params && category && products?.items +function CategoryLanding(props: CategoryPageProps) { + const { page, ...rest } = props + const productList = useProductList(rest) + const { params, category } = productList return ( <InContextMaskProvider mask={productList.mask}> - <CategoryMeta metadata={content.meta} params={params} category={category} /> + <CategoryMeta params={params} {...category} /> + <LayoutHeader floatingMd> + <LayoutTitle size='small' component='span'> + {category.name} + </LayoutTitle> + </LayoutHeader> + + {import.meta.graphCommerce.breadcrumbs && ( + <CategoryBreadcrumbs + category={category} + sx={(theme) => ({ + mx: theme.page.horizontal, + height: 0, + [theme.breakpoints.down('md')]: { + '& .MuiBreadcrumbs-ol': { justifyContent: 'center' }, + }, + })} + /> + )} + <CategoryHeroNav + {...category} + asset={page?.asset && <Asset asset={page.asset} loading='eager' />} + title={<CategoryHeroNavTitle>{category?.name}</CategoryHeroNavTitle>} + /> - <PageRowsCategoryBefore content={content} productListRenderer={productListRenderer} /> + <PageRows page={page} /> + </InContextMaskProvider> + ) +} +function CategoryProductList(props: CategoryPageProps) { + const { page, ...rest } = props + const productList = useProductList(rest) + const { params, category } = productList + + return ( + <InContextMaskProvider mask={productList.mask}> + <CategoryMeta params={params} {...category} /> <LayoutHeader floatingMd> <LayoutTitle size='small' component='span'> - {category?.name ?? content.title} + {category.name} </LayoutTitle> </LayoutHeader> - {!isCategory && !isLanding && ( - <Container maxWidth={false}> - <LayoutTitle variant='h1' gutterTop gutterBottom> - {page.title} - </LayoutTitle> - </Container> - )} - {isCategory && isLanding && ( - <> - {import.meta.graphCommerce.breadcrumbs && ( - <CategoryBreadcrumbs - category={category} - sx={(theme) => ({ - mx: theme.page.horizontal, - height: 0, - [theme.breakpoints.down('md')]: { - '& .MuiBreadcrumbs-ol': { justifyContent: 'center' }, - }, - })} - /> - )} - <CategoryHeroNav - {...category} - asset={pages?.[0]?.asset && <Asset asset={pages[0].asset} loading='eager' />} - title={<CategoryHeroNavTitle>{category?.name}</CategoryHeroNavTitle>} - /> - </> - )} - {isCategory && !isLanding && ( - <> - {import.meta.graphCommerce.productFiltersPro && - import.meta.graphCommerce.productFiltersLayout === 'SIDEBAR' && ( - <ProductListLayoutSidebar - {...productList} - key={category.uid} - title={category.name ?? page.title ?? ''} - id={category.uid} - category={category} - /> - )} - {import.meta.graphCommerce.productFiltersPro && - import.meta.graphCommerce.productFiltersLayout !== 'SIDEBAR' && ( - <ProductListLayoutDefault - {...productList} - key={category.uid} - title={category.name ?? page.title ?? ''} - id={category.uid} - category={category} - /> - )} - {!import.meta.graphCommerce.productFiltersPro && ( - <ProductListLayoutClassic - {...productList} - key={category.uid} - title={category.name ?? page.title ?? ''} - id={category.uid} - category={category} - /> - )} - </> - )} - <PageRowsCategory content={content} productListRenderer={productListRenderer} /> - - {page && ( - <RowRenderer - content={page.content} - renderer={{ - RowProduct: (rowProps) => ( - <RowProduct - {...rowProps} - {...products?.items?.[0]} - items={products?.items?.slice(0, 8)} - /> - ), - }} + {import.meta.graphCommerce.productFiltersPro && + import.meta.graphCommerce.productFiltersLayout === 'SIDEBAR' && ( + <ProductListLayoutSidebar + {...productList} + key={category.uid} + title={category.name ?? ''} + id={category.uid} + category={category} + /> + )} + {import.meta.graphCommerce.productFiltersPro && + import.meta.graphCommerce.productFiltersLayout !== 'SIDEBAR' && ( + <ProductListLayoutDefault + {...productList} + key={category.uid} + title={category.name ?? ''} + id={category.uid} + category={category} + /> + )} + {!import.meta.graphCommerce.productFiltersPro && ( + <ProductListLayoutClassic + {...productList} + key={category.uid} + title={category.name ?? ''} + id={category.uid} + category={category} /> )} + + <PageRows page={page} /> </InContextMaskProvider> ) } +function RegularPage(props: RegularPageProps) { + const { page } = props + return ( + <> + <Container maxWidth={false}> + <LayoutTitle variant='h1' gutterTop gutterBottom> + {page.title} + </LayoutTitle> + </Container> + + <PageRows page={page} /> + </> + ) +} + +function CategoryPage(props: CategoryProps) { + if (isCategoryPage(props)) { + const { category } = props + if (category.display_mode === 'PAGE') return <CategoryLanding {...props} /> + return <CategoryProductList {...props} /> + } + + return <RegularPage {...props} /> +} + const pageOptions: PageOptions<LayoutNavigationProps> = { Layout: LayoutNavigation, } @@ -177,44 +199,37 @@ export const getStaticPaths: GetPageStaticPaths = async ({ locales = [] }) => { } export const getStaticProps: GetPageStaticProps = async (context) => { - const { params, locale } = context - const [url, query] = extractUrlQuery(params) + const [url, query] = extractUrlQuery(context.params) if (!url || !query) return { notFound: true } const client = graphqlSharedClient(context) + const staticClient = graphqlSsrClient(context) + const conf = client.query({ query: StoreConfigDocument }) + const pageQuery = client.query({ query: PageDocument, variables: { input: { href: `/${url}` } } }) + const categoryPage = staticClient.query({ query: CategoryPageDocument, variables: { url } }) + const layout = staticClient.query({ query: LayoutDocument }) const filterTypes = getFilterTypes(client) + const params = parseParams(url, query, await filterTypes) - const staticClient = graphqlSsrClient(context) - - const categoryPage = staticClient.query({ - query: CategoryPageDocument, - variables: { url }, - }) - const layout = staticClient.query({ - query: LayoutDocument, - fetchPolicy: cacheFirst(staticClient), - }) + const filteredCategoryUid = params && params.filters.category_uid?.in?.[0] - const productListParams = parseParams(url, query, await filterTypes) - const filteredCategoryUid = productListParams && productListParams.filters.category_uid?.in?.[0] + const categoryPromise = categoryPage.then((res) => res.data.categories?.items?.[0]) + const waitForSiblings = appendSiblingsAsChildren(categoryPromise, staticClient) - const category = categoryPage.then((res) => res.data.categories?.items?.[0]) - const waitForSiblings = appendSiblingsAsChildren(category, staticClient) let categoryUid = filteredCategoryUid if (!categoryUid) { - categoryUid = (await category)?.uid ?? '' - if (productListParams) productListParams.filters.category_uid = { in: [categoryUid] } + categoryUid = (await categoryPromise)?.uid ?? '' + if (params) params.filters.category_uid = { in: [categoryUid] } } - const content = pageContent(staticClient, url, category) - const hasCategory = !!productListParams && categoryUid + const hasCategory = !!params && categoryUid const filters = hasCategory ? staticClient.query({ query: ProductFiltersDocument, variables: categoryDefaultsToProductListFilters( - await productListApplyCategoryDefaults(productListParams, (await conf).data, category), + await productListApplyCategoryDefaults(params, (await conf).data, categoryPromise), ), }) : undefined @@ -223,35 +238,52 @@ export const getStaticProps: GetPageStaticProps = async (context) => { ? staticClient.query({ query: ProductListDocument, variables: await productListApplyCategoryDefaults( - productListParams, + params, (await conf).data, - category, + categoryPromise, ), }) : undefined - const hasPage = filteredCategoryUid ? false : (await content).notFound !== false - if (!hasCategory && !hasPage) return redirectOrNotFound(staticClient, conf, params, locale) + const parent = findParentBreadcrumbItem(await categoryPromise) + const up = parent + ? { href: `/${parent.category_url_path}`, title: parent.category_name } + : { href: `/`, title: i18n._(/* i18n */ 'Home') } - if ((await products)?.errors) return { notFound: true } + const pageResult = (await pageQuery).data + const category = await categoryPromise - const { category_url_path, category_name } = findParentBreadcrumbItem(await category) ?? {} + if (!category && pageResult) { + if (isPageRedirect(pageResult)) return pageRedirect(pageResult) - const up = - category_url_path && category_name - ? { href: `/${category_url_path}`, title: category_name } - : { href: `/`, title: i18n._(/* i18n */ 'Home') } + const result = { + props: { + page: pageResult.page, + apolloState: await conf.then(() => client.cache.extract()), + }, + revalidate: 60 * 20, + } + flushMeasurePerf() + return result + } + + if (!pageResult.page && !category) { + return redirectOrNotFound(staticClient, conf, context.params) + } + + if ((await products)?.errors) return { notFound: true } await waitForSiblings const result = { props: { - content: await content, - ...(await categoryPage).data, + category, + page: pageResult.page, + ...(await products)?.data, ...(await filters)?.data, ...(await layout).data, filterTypes: await filterTypes, - params: productListParams, + params, apolloState: await conf.then(() => client.cache.extract()), up, }, diff --git a/examples/magento-graphcms/pages/index.tsx b/examples/magento-graphcms/pages/index.tsx index 86899e60e02..b961a35b3ac 100644 --- a/examples/magento-graphcms/pages/index.tsx +++ b/examples/magento-graphcms/pages/index.tsx @@ -1,12 +1,12 @@ import { PageOptions } from '@graphcommerce/framer-next-pages' import { cacheFirst } from '@graphcommerce/graphql' import { - ContentAreaHome, PageDocument, Page, PageMeta, pageRedirectOrNotFound, isPageFound, + PageRows, } from '@graphcommerce/graphql-gc-api' import { StoreConfigDocument } from '@graphcommerce/magento-store' import { GetStaticProps, LayoutHeader } from '@graphcommerce/next-ui' @@ -24,7 +24,7 @@ function CmsPage(props: Props) { <> <PageMeta page={page} /> <LayoutHeader floatingMd floatingSm /> - <ContentAreaHome page={page} /> + <PageRows page={page} /> </> ) } @@ -40,18 +40,17 @@ export const getStaticProps: GetPageStaticProps = async (context) => { const staticClient = graphqlSsrClient(context) const conf = client.query({ query: StoreConfigDocument }) - const page = client.query({ query: PageDocument, variables: { input: { href: '/' } } }) const layout = staticClient.query({ query: LayoutDocument, fetchPolicy: cacheFirst(staticClient), }) - const page = (await page).data - if (!isPageFound(page)) return pageRedirectOrNotFound(page) + const page = client.query({ query: PageDocument, variables: { input: { href: '/' } } }) + if (!isPageFound((await page).data)) return pageRedirectOrNotFound((await page).data) return { props: { - ...page, + ...(await page).data, ...(await layout).data, apolloState: await conf.then(() => client.cache.extract()), }, diff --git a/examples/magento-graphcms/plugins/hygraph/HygraphGcPageRows.tsx b/examples/magento-graphcms/plugins/hygraph/HygraphGcPageRows.tsx index b8f0148bdce..a7433b9f030 100644 --- a/examples/magento-graphcms/plugins/hygraph/HygraphGcPageRows.tsx +++ b/examples/magento-graphcms/plugins/hygraph/HygraphGcPageRows.tsx @@ -1,7 +1,7 @@ import type { - PageProduct_Product_DataFragment, + ProductPageRows_ProductDataFragment, PageProductRowsProps, - Page_Product_DataFragment, + PageRows_CategoryDataFragment, PageRowsProps, } from '@graphcommerce/graphql-gc-api' import type { PluginConfig, PluginProps } from '@graphcommerce/next-config' @@ -54,7 +54,7 @@ export const PageRows = ( const rendererProduct = { ...renderer, RowProduct: RowProductPage } export function PageProductRows< - P extends PageProduct_Product_DataFragment & Page_Product_DataFragment, + P extends ProductPageRows_ProductDataFragment & PageRows_CategoryDataFragment, >( props: PluginProps<PageProductRowsProps<P>> & { renderer?: Partial<PageProductRowsProps<P>['renderer']> diff --git a/packages/graphql-gc-api/components/Page/Page.graphql b/packages/graphql-gc-api/components/Page/Page.graphql index a35675e17ae..4a3b7b12169 100644 --- a/packages/graphql-gc-api/components/Page/Page.graphql +++ b/packages/graphql-gc-api/components/Page/Page.graphql @@ -1,6 +1,7 @@ query Page($input: GCPageInput!) { page(input: $input) { ...Page_Redirect - ...Page_Data + ...PageHead + ...PageRows } } diff --git a/packages/graphql-gc-api/components/Page/Page_Product_Data.graphql b/packages/graphql-gc-api/components/Page/Page_Product_Data.graphql deleted file mode 100644 index c2d7322c451..00000000000 --- a/packages/graphql-gc-api/components/Page/Page_Product_Data.graphql +++ /dev/null @@ -1,4 +0,0 @@ -fragment Page_Product_Data on ProductInterface { - uid - __typename -} diff --git a/packages/graphql-gc-api/components/Page/index.ts b/packages/graphql-gc-api/components/Page/index.ts index 92ddd5a6aab..619a6d5a2bf 100644 --- a/packages/graphql-gc-api/components/Page/index.ts +++ b/packages/graphql-gc-api/components/Page/index.ts @@ -1,4 +1 @@ -export * from './PageRows' -export * from './Page_Data.gql' -export * from './Page_Product_Data.gql' export * from './Page.gql' diff --git a/packages/graphql-gc-api/components/PageCategory/PageCategoryRows.tsx b/packages/graphql-gc-api/components/PageCategory/PageCategoryRows.tsx new file mode 100644 index 00000000000..51c07c34fa7 --- /dev/null +++ b/packages/graphql-gc-api/components/PageCategory/PageCategoryRows.tsx @@ -0,0 +1,37 @@ +import { + TypeRenderer, + filterNonNullableKeys, + LazyHydrate, + RenderType, +} from '@graphcommerce/next-ui' +import { PageCategory_DataFragment } from './PageCategory_Data.gql' +import { PageRows_CategoryDataFragment } from './PageRows_CategoryData.gql' + +type PageRowTypeRenderer = TypeRenderer< + NonNullable<NonNullable<NonNullable<PageCategory_DataFragment['rows']>>[number]> +> + +export type PageProductRowsProps<P extends PageRows_CategoryDataFragment> = { + page: PageCategory_DataFragment | null | undefined + renderer?: PageRowTypeRenderer + loadingEager?: number + category: P +} + +export function PageCategoryRows<P extends PageRows_CategoryDataFragment>( + props: PageProductRowsProps<P>, +) { + const { renderer, page, loadingEager = 2 } = props + + if (!renderer || !page) return null + + return ( + <> + {filterNonNullableKeys(page?.rows)?.map((item, index) => ( + <LazyHydrate key={item.id} hydrated={index < loadingEager ? true : undefined} height={500}> + <RenderType renderer={renderer} {...item} /> + </LazyHydrate> + ))} + </> + ) +} diff --git a/packages/graphql-gc-api/components/PageCategory/PageCategory_Data.graphql b/packages/graphql-gc-api/components/PageCategory/PageCategory_Data.graphql new file mode 100644 index 00000000000..ee9e692f047 --- /dev/null +++ b/packages/graphql-gc-api/components/PageCategory/PageCategory_Data.graphql @@ -0,0 +1,5 @@ +# This fragment is added to the CategoryPAge query when the product page is loaded. +fragment PageCategory_Data on Page { + ...PageHead + ...PageRows +} diff --git a/packages/graphql-gc-api/components/PageCategory/PageProduct.graphql b/packages/graphql-gc-api/components/PageCategory/PageProduct.graphql new file mode 100644 index 00000000000..af3148fcac0 --- /dev/null +++ b/packages/graphql-gc-api/components/PageCategory/PageProduct.graphql @@ -0,0 +1,6 @@ +fragment PageCategory on CategoryTree { + page { + ...PageCategory_Data + } + ...PageRows_CategoryData +} diff --git a/packages/graphql-gc-api/components/PageHead/Page_Head.graphql b/packages/graphql-gc-api/components/PageHead/PageHead.graphql similarity index 83% rename from packages/graphql-gc-api/components/PageHead/Page_Head.graphql rename to packages/graphql-gc-api/components/PageHead/PageHead.graphql index 9cd7f5a3ccf..eff744d6ef4 100644 --- a/packages/graphql-gc-api/components/PageHead/Page_Head.graphql +++ b/packages/graphql-gc-api/components/PageHead/PageHead.graphql @@ -9,7 +9,8 @@ fragment GcMetaTag on GcMetaTag { content } -fragment Page_Head on Page { +# Data fragment used for the PageHead component. +fragment PageHead on Page { head { title description diff --git a/packages/graphql-gc-api/components/PageHead/PageHead.tsx b/packages/graphql-gc-api/components/PageHead/PageHead.tsx index 95361bc82c8..80346ae75e6 100644 --- a/packages/graphql-gc-api/components/PageHead/PageHead.tsx +++ b/packages/graphql-gc-api/components/PageHead/PageHead.tsx @@ -2,10 +2,10 @@ import { usePageContext } from '@graphcommerce/framer-next-pages' import { canonicalize } from '@graphcommerce/next-ui' import Head from 'next/head' import { useRouter } from 'next/router' -import { Page_HeadFragment, GcMetaTagFragment, GcLinkRelTagFragment } from './Page_Head.gql' +import { PageHeadFragment, GcMetaTagFragment, GcLinkRelTagFragment } from './PageHead.gql' type PageMetaProps = { - page: Page_HeadFragment + page: PageHeadFragment children?: React.ReactNode } diff --git a/packages/graphql-gc-api/components/PageProduct/PageProduct.graphql b/packages/graphql-gc-api/components/PageProduct/PageProduct.graphql deleted file mode 100644 index 34b72839175..00000000000 --- a/packages/graphql-gc-api/components/PageProduct/PageProduct.graphql +++ /dev/null @@ -1,6 +0,0 @@ -fragment PageProduct on ProductInterface { - page { - ...PageProduct_Data - } - ...PageProduct_Product_Data -} diff --git a/packages/graphql-gc-api/components/PageProduct/PageProduct_Data.graphql b/packages/graphql-gc-api/components/PageProduct/PageProduct_Data.graphql deleted file mode 100644 index fc6e37809f0..00000000000 --- a/packages/graphql-gc-api/components/PageProduct/PageProduct_Data.graphql +++ /dev/null @@ -1,5 +0,0 @@ -# This fragment is added to the ProductPage2 query when the product page is loaded. -fragment PageProduct_Data on Page { - ...Page_Head - ...Page_Data -} diff --git a/packages/graphql-gc-api/components/PageProduct/PageProduct_Product_Data.graphql b/packages/graphql-gc-api/components/PageProduct/PageProduct_Product_Data.graphql deleted file mode 100644 index bb3f9b404c5..00000000000 --- a/packages/graphql-gc-api/components/PageProduct/PageProduct_Product_Data.graphql +++ /dev/null @@ -1,3 +0,0 @@ -fragment PageProduct_Product_Data on ProductInterface { - ...Page_Product_Data -} diff --git a/packages/graphql-gc-api/components/PageProduct/ProductPageRows.graphql b/packages/graphql-gc-api/components/PageProduct/ProductPageRows.graphql new file mode 100644 index 00000000000..2f7352b9c11 --- /dev/null +++ b/packages/graphql-gc-api/components/PageProduct/ProductPageRows.graphql @@ -0,0 +1,7 @@ +fragment ProductPageRows on ProductInterface { + page { + ...PageHead + ...PageRows + } + ...ProductPageRows_ProductData +} diff --git a/packages/graphql-gc-api/components/PageProduct/PageProductRows.tsx b/packages/graphql-gc-api/components/PageProduct/ProductPageRows.tsx similarity index 53% rename from packages/graphql-gc-api/components/PageProduct/PageProductRows.tsx rename to packages/graphql-gc-api/components/PageProduct/ProductPageRows.tsx index a3514088934..d2d071992a2 100644 --- a/packages/graphql-gc-api/components/PageProduct/PageProductRows.tsx +++ b/packages/graphql-gc-api/components/PageProduct/ProductPageRows.tsx @@ -4,23 +4,23 @@ import { LazyHydrate, RenderType, } from '@graphcommerce/next-ui' -import { Page_Product_DataFragment } from '../Page/Page_Product_Data.gql' -import { PageProduct_DataFragment } from './PageProduct_Data' -import { PageProduct_Product_DataFragment } from './PageProduct_Product_Data' +import { PageRows_CategoryDataFragment } from './PageRows_CategoryData.gql' +import { ProductPageRowsFragment } from './ProductPageRows.gql' +import { ProductPageRows_ProductDataFragment } from './ProductPageRows_ProductData.gql' type PageRowTypeRenderer = TypeRenderer< - NonNullable<NonNullable<NonNullable<PageProduct_DataFragment['rows']>>[number]> + NonNullable<NonNullable<NonNullable<ProductPageRowsFragment['rows']>>[number]> > -export type PageProductRowsProps<P extends PageProduct_Product_DataFragment> = { - page: PageProduct_DataFragment | null | undefined +export type PageProductRowsProps<P extends ProductPageRows_ProductDataFragment> = { + page: ProductPageRowsFragment | null | undefined renderer?: PageRowTypeRenderer loadingEager?: number product: P } -export function PageProductRows< - P extends PageProduct_Product_DataFragment & Page_Product_DataFragment, +export function ProductPageRows< + P extends ProductPageRows_ProductDataFragment & PageRows_CategoryDataFragment, >(props: PageProductRowsProps<P>) { const { renderer, page, loadingEager = 2 } = props diff --git a/packages/graphql-gc-api/components/PageProduct/ProductPageRows_ProductData.graphql b/packages/graphql-gc-api/components/PageProduct/ProductPageRows_ProductData.graphql new file mode 100644 index 00000000000..3a1b111a436 --- /dev/null +++ b/packages/graphql-gc-api/components/PageProduct/ProductPageRows_ProductData.graphql @@ -0,0 +1,3 @@ +fragment ProductPageRows_ProductData on ProductInterface { + ...PageRows_CategoryData +} diff --git a/packages/graphql-gc-api/components/PageProduct/index.ts b/packages/graphql-gc-api/components/PageProduct/index.ts index 6a492a6783c..9aa750b8257 100644 --- a/packages/graphql-gc-api/components/PageProduct/index.ts +++ b/packages/graphql-gc-api/components/PageProduct/index.ts @@ -1,2 +1,2 @@ -export * from './PageProductRows' -export * from './PageProduct_Product_Data.gql' +export * from './ProductPageRows' +export * from './ProductPageRows_ProductData.gql' diff --git a/packages/graphql-gc-api/components/Page/Page_Data.graphql b/packages/graphql-gc-api/components/PageRows/PageRows.graphql similarity index 76% rename from packages/graphql-gc-api/components/Page/Page_Data.graphql rename to packages/graphql-gc-api/components/PageRows/PageRows.graphql index 363dbef7bc1..83512165d29 100644 --- a/packages/graphql-gc-api/components/Page/Page_Data.graphql +++ b/packages/graphql-gc-api/components/PageRows/PageRows.graphql @@ -1,6 +1,5 @@ # This fragment is used in the Page query to retrieve the data for a page. -fragment Page_Data on Page { - ...Page_Head +fragment PageRows on Page { rows { __typename ... on PageRowFake { diff --git a/packages/graphql-gc-api/components/Page/PageRows.tsx b/packages/graphql-gc-api/components/PageRows/PageRows.tsx similarity index 80% rename from packages/graphql-gc-api/components/Page/PageRows.tsx rename to packages/graphql-gc-api/components/PageRows/PageRows.tsx index 26ce0e462ff..420da31c41c 100644 --- a/packages/graphql-gc-api/components/Page/PageRows.tsx +++ b/packages/graphql-gc-api/components/PageRows/PageRows.tsx @@ -5,14 +5,14 @@ import { type TypeRenderer, } from '@graphcommerce/next-ui' import React from 'react' -import { Page_DataFragment } from './Page_Data.gql' +import { PageRowsFragment } from '../Page/PageRows.gql' type PageRowTypeRenderer = TypeRenderer< - NonNullable<NonNullable<NonNullable<Page_DataFragment['rows']>>[number]> + NonNullable<NonNullable<NonNullable<PageRowsFragment['rows']>>[number]> > export type PageRowsProps = { - page: Page_DataFragment | null | undefined + page: PageRowsFragment | null | undefined renderer?: PageRowTypeRenderer loadingEager?: number } diff --git a/packages/graphql-gc-api/components/PageRows/PageRows_CategoryData.graphql b/packages/graphql-gc-api/components/PageRows/PageRows_CategoryData.graphql new file mode 100644 index 00000000000..7cda1538fda --- /dev/null +++ b/packages/graphql-gc-api/components/PageRows/PageRows_CategoryData.graphql @@ -0,0 +1,5 @@ +# When a category related component +fragment PageRows_CategoryData on CategoryTree { + uid + __typename +} diff --git a/packages/graphql-gc-api/components/PageRows/PageRows_ProductData.graphql b/packages/graphql-gc-api/components/PageRows/PageRows_ProductData.graphql new file mode 100644 index 00000000000..7cda1538fda --- /dev/null +++ b/packages/graphql-gc-api/components/PageRows/PageRows_ProductData.graphql @@ -0,0 +1,5 @@ +# When a category related component +fragment PageRows_CategoryData on CategoryTree { + uid + __typename +} diff --git a/packages/graphql-gc-api/components/PageRows/index.ts b/packages/graphql-gc-api/components/PageRows/index.ts new file mode 100644 index 00000000000..eabe927b4ab --- /dev/null +++ b/packages/graphql-gc-api/components/PageRows/index.ts @@ -0,0 +1,2 @@ +export * from './PageRows' +export * from './PageRows.gql' diff --git a/packages/graphql-gc-api/components/index.ts b/packages/graphql-gc-api/components/index.ts index 4cab92fad69..cf92646c29e 100644 --- a/packages/graphql-gc-api/components/index.ts +++ b/packages/graphql-gc-api/components/index.ts @@ -1,3 +1,4 @@ export * from './Page' -export * from './PageProduct' export * from './PageHead' +export * from './PageProduct' +export * from './PageRows' diff --git a/packages/graphql-gc-api/utils/GcPage_Redirect.graphql b/packages/graphql-gc-api/utils/Page_Redirect.graphql similarity index 100% rename from packages/graphql-gc-api/utils/GcPage_Redirect.graphql rename to packages/graphql-gc-api/utils/Page_Redirect.graphql diff --git a/packages/graphql-gc-api/utils/gcPageRedirectOrNotFound.ts b/packages/graphql-gc-api/utils/pageRedirectOrNotFound.ts similarity index 81% rename from packages/graphql-gc-api/utils/gcPageRedirectOrNotFound.ts rename to packages/graphql-gc-api/utils/pageRedirectOrNotFound.ts index 8240ce6fe79..eeabc57941c 100644 --- a/packages/graphql-gc-api/utils/gcPageRedirectOrNotFound.ts +++ b/packages/graphql-gc-api/utils/pageRedirectOrNotFound.ts @@ -32,6 +32,14 @@ export function isPageFound( return !isPageNotFound(query) && !isPageRedirect(query) } +export function pageRedirect(query: PageQuery | null | undefined): { + redirect: Redirect + revalidate?: number | boolean +} { + if (isPageRedirect(query)) return { redirect: query.page.redirect } + throw Error('pageRedirect should only be called when it isPageRedirect(query) returns true') +} + export function pageRedirectOrNotFound( query: PageQuery | null | undefined, ): { redirect: Redirect; revalidate?: number | boolean } | { notFound: true } { diff --git a/packages/hygraph-ui/graphql/HygraphPage.graphql b/packages/hygraph-ui/graphql/HygraphPage.graphql index 61c19e7a5a3..a6cd6b418c9 100644 --- a/packages/hygraph-ui/graphql/HygraphPage.graphql +++ b/packages/hygraph-ui/graphql/HygraphPage.graphql @@ -1,4 +1,4 @@ -fragment HygraphPage on Page @inject(into: ["Page_Head"]) { +fragment HygraphPage on Page @inject(into: ["PageHead"]) { author date relatedPages { diff --git a/packages/hygraph-ui/mesh/resolvers.ts b/packages/hygraph-ui/mesh/resolvers.ts index f58f75bb22f..a46acbf0563 100644 --- a/packages/hygraph-ui/mesh/resolvers.ts +++ b/packages/hygraph-ui/mesh/resolvers.ts @@ -6,6 +6,7 @@ import { PageContent, ProductInterface, ResolversTypes, + RowCategory, RowProduct, type Resolvers, } from '@graphcommerce/graphql-mesh' @@ -61,12 +62,17 @@ const pageProductResolver: GCPageResolver = { root, key: root.url_key, argsFromKeys: (keys) => ({ - where: { url_in: ['product/global', ...keys.map((key) => `p/${key}`)] }, + where: { + url_in: [ + 'product/global', + // ...keys.map((key) => `p/${key}`) + ], + }, }), valuesFromResults: (results, keys) => keys.map((key) => { const page = - results.find((r) => r.url === `p/${key}`) ?? + // results.find((r) => r.url === `p/${key}`) ?? results.find((r) => r.url === 'product/global') if (!page) return null @@ -84,17 +90,48 @@ export const resolvers: Resolvers = { // Resolve the query `page` to a page with the given URL Query: { page: { - resolve: (root, args, context, info) => - context.hygraph.Query.pages({ + resolve: async (root, args, context, info) => { + const page = await context.hygraph.Query.pages({ root, info, context, args: { where: { url: denormalizeUrl(args.input.href) } }, - }).then((r) => r[0]), + }).then((r) => r[0]) + + console.log('oage') + + function mapRowProduct(row: RowProduct): RowCategory & { __typename: 'RowCategory' } { + const newRow: Partial<RowCategory & { __typename: 'RowCategory' }> = { + __typename: 'RowCategory', + } + if (row.id) newRow.id = row.id + if (row.locale) newRow.locale = row.locale + if (row.stage) newRow.stage = row.stage + if (row.localizations) newRow.localizations = row.localizations.map(mapRowProduct) + if (row.identity) newRow.categoryUrl = row.identity + if (row.pages) newRow.pages = row.pages + if (row.variant) newRow.variant = row.variant as 'Swipeable' | 'Grid' + return newRow as RowCategory & { __typename: 'RowCategory' } + } + + page.content = page.content.map((row) => + isRowProduct(row) && row.variant && ['Swipeable', 'Grid'].includes(row.variant) + ? mapRowProduct(row) + : row, + ) + + return page + }, }, }, Page: { + content: { + resolve: (root) => { + console.log('content') + return root.content + }, + }, rows: { selectionSet: (root) => ({ kind: Kind.SELECTION_SET, @@ -114,7 +151,10 @@ export const resolvers: Resolvers = { }, ], }), - resolve: (root) => root.content, + resolve: (root) => { + console.log('rows') + return root.content + }, }, head: { selectionSet: `{ @@ -176,6 +216,8 @@ export const resolvers: Resolvers = { // already resolved and available in the context if (responsePathAsArray(info.path)[0] === 'products') return null + console.log('RowProduct', root.identity, responsePathAsArray(info.path)) + const result = await context.m2.Query.products({ root, info, @@ -211,6 +253,9 @@ export const resolvers: Resolvers = { category: { selectionSet: `{ categoryUrl }`, resolve: async (root, args, context, info) => { + if (responsePathAsArray(info.path)[0] === 'products') return null + console.log('RowCategory', root.categoryUrl, responsePathAsArray(info.path)) + const result = await context.m2.Query.categories({ root, info, diff --git a/packages/magento-category/utils/findParentBreadcrumbItem.ts b/packages/magento-category/utils/findParentBreadcrumbItem.ts index 63b6a4240db..49c3554f95d 100644 --- a/packages/magento-category/utils/findParentBreadcrumbItem.ts +++ b/packages/magento-category/utils/findParentBreadcrumbItem.ts @@ -1,12 +1,10 @@ import { filterNonNullableKeys } from '@graphcommerce/next-ui' import { CategoryBreadcrumbFragment } from '../components/CategoryBreadcrumb' -export function findParentBreadcrumbItem( - category: CategoryBreadcrumbFragment | null | undefined, -): NonNullable<CategoryBreadcrumbFragment['breadcrumbs']>[number] | undefined { +export function findParentBreadcrumbItem(category: CategoryBreadcrumbFragment | null | undefined) { const parentCategoryPath = category?.url_path?.split('/').slice(0, -1).join('/') - return filterNonNullableKeys(category?.breadcrumbs, ['category_url_path']).find( + return filterNonNullableKeys(category?.breadcrumbs, ['category_url_path', 'category_name']).find( (c) => parentCategoryPath === c.category_url_path, ) }