From 46e003196ff9a7a352294afc090a512c3691d90f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Meyer?= Date: Mon, 17 Jul 2023 15:56:32 +0200 Subject: [PATCH] feat(poc): seoUrls yes or no env --- .env.example | 1 + components/carousel.tsx | 6 ++- components/grid/three-items.tsx | 6 ++- lib/shopware/api.ts | 26 +-------- lib/shopware/index.ts | 93 +++++++++++++++++++++------------ lib/shopware/transform.ts | 65 +++++++++++++++-------- 6 files changed, 115 insertions(+), 82 deletions(-) diff --git a/.env.example b/.env.example index a4666dd31..46d641d54 100644 --- a/.env.example +++ b/.env.example @@ -4,3 +4,4 @@ SITE_NAME="Next.js Commerce with Shopware Composable Frontends" SHOPWARE_STORE_DOMAIN="" SHOPWARE_API_TYPE="store-api" SHOPWARE_ACCESS_TOKEN="" +SHOPWARE_USE_SEO_URLS="false" diff --git a/components/carousel.tsx b/components/carousel.tsx index 45b845ef5..d30ac01a9 100644 --- a/components/carousel.tsx +++ b/components/carousel.tsx @@ -3,8 +3,12 @@ import Image from 'next/image'; import Link from 'next/link'; export async function Carousel() { + const collectionName = + `${process.env.SHOPWARE_USE_SEO_URLS}` === 'true' + ? 'Summer-BBQ/Hidden-Carousel-Category' + : 'ff7bf3c59f1342a685844fbf8fdf9dc8'; const { products } = await getCollectionProducts({ - collection: 'Summer-BBQ/Hidden-Carousel-Category' + collection: collectionName }); if (!products?.length) return null; diff --git a/components/grid/three-items.tsx b/components/grid/three-items.tsx index a7d2b9010..723bc3095 100644 --- a/components/grid/three-items.tsx +++ b/components/grid/three-items.tsx @@ -37,8 +37,12 @@ function ThreeItemGridItem({ export async function ThreeItemGrid() { // Collections that start with `hidden-*` are hidden from the search page. + const collectionName = + `${process.env.SHOPWARE_USE_SEO_URLS}` === 'true' + ? 'Summer-BBQ/Hidden-Category' + : '4ab73c06d90d4a5cb312209a64480d87'; const { products: homepageItems } = await getCollectionProducts({ - collection: 'Summer-BBQ/Hidden-Category' + collection: collectionName }); if (!homepageItems[0] || !homepageItems[1] || !homepageItems[2]) return null; diff --git a/lib/shopware/api.ts b/lib/shopware/api.ts index 46d924035..193cf5af8 100644 --- a/lib/shopware/api.ts +++ b/lib/shopware/api.ts @@ -168,15 +168,13 @@ export async function requestSeoUrl( page: number = 1, limit: number = 1 ): Promise { - console.log(handle); try { - const FirstCriteria = { + const criteriaSeoUrls = { page: page, limit: limit, filter: [ { type: 'multi', - // @ts-ignore operator: 'or', queries: [ { @@ -194,27 +192,7 @@ export async function requestSeoUrl( ] }; // @ts-ignore - const firstResult = await apiInstance.invoke('readSeoUrl post /seo-url', FirstCriteria); - if (firstResult.total && firstResult.total > 0) { - return firstResult; - } - - const lastPart = handle.split('/').pop() + ''; - console.log(lastPart); - - const SecondCriteria = { - page: page, - limit: limit, - filter: [ - { - type: 'contains', - field: 'seoPathInfo', - value: lastPart - } - ] - }; - - return await apiInstance.invoke('readSeoUrl post /seo-url', SecondCriteria); + return await apiInstance.invoke('readSeoUrl post /seo-url', criteriaSeoUrls); } catch (error) { if (error instanceof ApiClientError) { console.error(error); diff --git a/lib/shopware/index.ts b/lib/shopware/index.ts index 7858d9fa5..a35478929 100644 --- a/lib/shopware/index.ts +++ b/lib/shopware/index.ts @@ -40,6 +40,7 @@ import { ProductListingCriteria, StoreNavigationTypeSW } from './types'; +const useSeoUrls = `${process.env.SHOPWARE_USE_SEO_URLS}` === 'true'; export async function getMenu(params?: { type?: StoreNavigationTypeSW; @@ -53,21 +54,26 @@ export async function getMenu(params?: { } export async function getPage(handle: string | []): Promise { - const pageHandle = decodeURIComponent(transformHandle(handle)); - const seoUrlElement = await getFirstSeoUrlElement(pageHandle); - if (seoUrlElement) { - const category = await getCategory(seoUrlElement); + let seoUrlElement; + let pageIdOrHandle = decodeURIComponent(transformHandle(handle)).replace('cms/', ''); - if (!category) { - console.log('[getPage] Did not found any category with page handle:', pageHandle); + if (useSeoUrls) { + seoUrlElement = await getFirstSeoUrlElement(pageIdOrHandle); + if (seoUrlElement) { + pageIdOrHandle = seoUrlElement.foreignKey; } - return category ? transformPage(seoUrlElement, category) : undefined; + if (!seoUrlElement) { + console.log('[getPage] Did not found any seoUrl element with page handle:', pageIdOrHandle); + } } - if (!seoUrlElement) { - console.log('[getPage] Did not found any seoUrl element with page handle:', pageHandle); + const category = await getCategory(pageIdOrHandle); + if (!category) { + console.log('[getPage] Did not found any category with handle:', pageIdOrHandle); } + + return category ? transformPage(category, seoUrlElement) : undefined; } export async function getFirstSeoUrlElement( @@ -91,17 +97,22 @@ export async function getFirstProduct(productId: string): Promise { const criteria = cms ? getDefaultCategoryWithCmsCriteria() : getDefaultCategoryCriteria(); - return await requestCategory(seoUrl.foreignKey, criteria); + return await requestCategory(categoryId, criteria); } // This function is only used for generateMetadata at app/search/(collection)/[...collection]/page.tsx export async function getCollection(handle: string | []) { - const collectionName = decodeURIComponent(transformHandle(handle)); - const seoUrlElement = await getFirstSeoUrlElement(collectionName); - if (seoUrlElement) { - const category = await getCategory(seoUrlElement); - const path = seoUrlElement.seoPathInfo ?? ''; - if (category) { - const collection = transformCollection(seoUrlElement, category); + let path; + let seoUrlElement; + let categoryIdOrHandle = decodeURIComponent(transformHandle(handle)); - return { - ...collection, - path: `/search/${path}` - }; + if (useSeoUrls) { + seoUrlElement = await getFirstSeoUrlElement(categoryIdOrHandle); + if (seoUrlElement) { + categoryIdOrHandle = seoUrlElement.foreignKey; + path = seoUrlElement.seoPathInfo ?? ''; } } + + const category = await getCategory(categoryIdOrHandle); + if (category) { + const collection = transformCollection(category, seoUrlElement); + path = path ?? category.id ?? ''; + + return { + ...collection, + path: `/search/${path}` + }; + } } export async function getProductSeoUrls() { @@ -236,15 +259,19 @@ export async function getProduct(handle: string | []): Promise 0 && item.seoUrls[0] && item.seoUrls[0].seoPathInfo + ? type === 'footer-navigation' + ? '/cms/' + item.seoUrls[0].seoPathInfo + : '/search/' + item.seoUrls[0].seoPathInfo + : '' + : type === 'footer-navigation' + ? '/cms/' + item.id ?? '' + : '/search/' + item.id ?? ''; + // @ToDo: currently only footer-navigation is used for cms pages, this need to be more dynamic (shoud depending on the item) return { id: item.id ?? '', title: item.name, children: item.children?.map((item) => transformMenuItem(item, type)) ?? [], - path: - item.seoUrls && item.seoUrls.length > 0 && item.seoUrls[0] && item.seoUrls[0].seoPathInfo - ? type === 'footer-navigation' - ? '/cms/' + item.seoUrls[0].seoPathInfo - : '/search/' + item.seoUrls[0].seoPathInfo - : '', + path: path, type: item.children && item.children.length > 0 ? 'headline' : 'link' }; } export function transformPage( - seoUrlElement: ApiSchemas['SeoUrl'], - category: ExtendedCategory + category: ExtendedCategory, + seoUrlElement?: ApiSchemas['SeoUrl'] ): Page { let plainHtmlContent; if (category.cmsPage) { @@ -51,20 +57,20 @@ export function transformPage( } return { - id: seoUrlElement.id ?? '', + id: seoUrlElement?.id ?? category.id ?? '', title: category.translated?.metaTitle ?? category.name ?? '', - handle: seoUrlElement.seoPathInfo, + handle: seoUrlElement?.seoPathInfo ?? category.id ?? '', body: plainHtmlContent ?? category.description ?? '', bodySummary: category.translated?.metaDescription ?? category.description ?? '', seo: { title: category.translated?.metaTitle ?? category.name ?? '', description: category.translated?.metaDescription ?? category.description ?? '' }, - createdAt: seoUrlElement.createdAt ?? '', - updatedAt: seoUrlElement.updatedAt ?? '', - routeName: seoUrlElement.routeName, + createdAt: seoUrlElement?.createdAt ?? category.createdAt ?? '', + updatedAt: seoUrlElement?.updatedAt ?? category.updatedAt ?? '', + routeName: seoUrlElement?.routeName, originalCmsPage: category.cmsPage, - foreignKey: seoUrlElement.foreignKey + foreignKey: seoUrlElement?.foreignKey ?? category.id }; } @@ -89,18 +95,22 @@ export function transformToPlainHtmlContent(cmsPage: ExtendedCmsPage): string { } export function transformCollection( - seoUrlElement: ApiSchemas['SeoUrl'], - resCategory: ExtendedCategory + resCategory: ExtendedCategory, + seoUrlElement?: ApiSchemas['SeoUrl'] ) { return { - handle: seoUrlElement.seoPathInfo, + handle: seoUrlElement?.seoPathInfo ?? resCategory.id ?? '', title: resCategory.translated?.metaTitle ?? resCategory.name ?? '', description: resCategory.description ?? '', seo: { title: resCategory.translated?.metaTitle ?? resCategory.name ?? '', description: resCategory.translated?.metaDescription ?? resCategory.description ?? '' }, - updatedAt: seoUrlElement.updatedAt ?? seoUrlElement.createdAt ?? '' + updatedAt: + seoUrlElement?.updatedAt ?? + seoUrlElement?.createdAt ?? + resCategory.updatedAt ?? + resCategory.createdAt }; } @@ -116,7 +126,10 @@ export function transformSubCollection( .filter((item) => item.visible) .filter((item) => item.type !== 'link') .map((item) => { - const handle = item.seoUrls ? findHandle(item.seoUrls, parentCollectionName) : undefined; + const handle = + item.seoUrls && `${process.env.SHOPWARE_USE_SEO_URLS}` === 'true' + ? findHandle(item.seoUrls, parentCollectionName) + : item.id; if (handle) { collection.push({ handle: handle, @@ -183,15 +196,21 @@ export function transformProducts(res: ExtendedProductListingResult): Product[] } export function transformProduct(item: ExtendedProduct): Product { + const useSeoUrls = `${process.env.SHOPWARE_USE_SEO_URLS}` === 'true'; const productOptions = transformOptions(item); const productVariants = transformVariants(item); - return { - id: item.id ?? '', - path: + let path = item.id ? item.id : ''; + if (useSeoUrls) { + path = item.seoUrls && item.seoUrls.length > 0 && item.seoUrls[0] && item.seoUrls[0].seoPathInfo ? item.seoUrls[0].seoPathInfo - : '', + : ''; + } + + return { + id: item.id ?? '', + path: path, availableForSale: item.available ?? false, title: item.translated ? item.translated.name ?? '' : item.name, description: item.translated?.metaDescription