From 9b2c63f1e375ddad73101b4e30da6db62b95c93a Mon Sep 17 00:00:00 2001 From: tkostuch Date: Wed, 20 May 2020 09:17:43 +0200 Subject: [PATCH 1/5] add redirection in component for simple product related to configurable product --- core/modules/catalog/events.ts | 20 ++++++++++++++++++++ src/themes/default/pages/Product.vue | 2 ++ 2 files changed, 22 insertions(+) diff --git a/core/modules/catalog/events.ts b/core/modules/catalog/events.ts index fe2f0ded64..93dae4ee65 100644 --- a/core/modules/catalog/events.ts +++ b/core/modules/catalog/events.ts @@ -2,6 +2,10 @@ import EventBus from '@vue-storefront/core/compatibility/plugins/event-bus' import { PRODUCT_SET_CURRENT_CONFIGURATION, PRODUCT_SET_CURRENT } from './store/product/mutation-types' import omit from 'lodash-es/omit' import config from 'config' +import { AsyncDataLoader } from '@vue-storefront/core/lib/async-data-loader'; +import { currentStoreView } from '@vue-storefront/core/lib/multistore'; +import { formatProductLink } from '@vue-storefront/core/modules/url/helpers'; +import { Logger } from '@vue-storefront/core/lib/logger'; // Listeners moved from Product.js @@ -110,3 +114,19 @@ export const onUserPricesRefreshed = async (store, router) => { }, { root: true }) } } + +export const checkConfigurableParent = (store) => { + const parentProduct = store.getters['product/getParentProduct'] + const currentProduct = store.getters['product/getCurrentProduct'] + if (parentProduct && parentProduct.id !== currentProduct.id && config.products.preventConfigurableChildrenDirectAccess) { + Logger.log('Redirecting to parent, configurable product', parentProduct.sku)() + const parentUrl = formatProductLink(parentProduct, currentStoreView().storeCode) + AsyncDataLoader.push({ + execute: async ({ context }) => { + if (context && !context.url.includes(parentUrl)) { + context.server.response.redirect(301, parentUrl) + } + } + }) + } +} diff --git a/src/themes/default/pages/Product.vue b/src/themes/default/pages/Product.vue index 95d040e8a2..9ef307a6d9 100644 --- a/src/themes/default/pages/Product.vue +++ b/src/themes/default/pages/Product.vue @@ -225,6 +225,7 @@ import { registerModule, isModuleRegistered } from '@vue-storefront/core/lib/mod import { onlineHelper, isServer } from '@vue-storefront/core/helpers' import { catalogHooksExecutors } from '@vue-storefront/core/modules/catalog-next/hooks' import ProductPrice from 'theme/components/core/ProductPrice.vue' +import { checkConfigurableParent } from '@vue-storefront/core/modules/catalog/events' export default { components: { @@ -337,6 +338,7 @@ export default { const loadBreadcrumbsPromise = store.dispatch('product/loadProductBreadcrumbs', { product }) if (isServer) await loadBreadcrumbsPromise catalogHooksExecutors.productPageVisited(product) + checkConfigurableParent(store) }, beforeRouteEnter (to, from, next) { if (isServer) { From 5b89b8ef721ff0ae8b1431721285e28d802adc78 Mon Sep 17 00:00:00 2001 From: tkostuch Date: Wed, 20 May 2020 09:18:16 +0200 Subject: [PATCH 2/5] update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index adfd4b2fe2..a7d5f828f5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,6 +23,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Blank order details page - @mdanilowicz (#4382) - upadate cart hash after sync with backend - @gibkigonzo (#4387) - exit from errorHandler after redirection - @gibkigonzo (#4246) +- add redirection in component for simple product related to configurable product - @gibkigonzo (#4359) ## [1.11.3] - 2020.04.27 From 9b427c26679998cb529f7e0e017ff7ff35ce0802 Mon Sep 17 00:00:00 2001 From: tkostuch Date: Wed, 20 May 2020 10:28:45 +0200 Subject: [PATCH 3/5] check parent only if product isn't visible --- core/modules/catalog/events.ts | 22 +++++++++++-------- core/modules/catalog/store/product/actions.ts | 15 +++++++------ src/themes/default/pages/Product.vue | 2 -- 3 files changed, 21 insertions(+), 18 deletions(-) diff --git a/core/modules/catalog/events.ts b/core/modules/catalog/events.ts index 93dae4ee65..a924bb6be7 100644 --- a/core/modules/catalog/events.ts +++ b/core/modules/catalog/events.ts @@ -6,6 +6,8 @@ import { AsyncDataLoader } from '@vue-storefront/core/lib/async-data-loader'; import { currentStoreView } from '@vue-storefront/core/lib/multistore'; import { formatProductLink } from '@vue-storefront/core/modules/url/helpers'; import { Logger } from '@vue-storefront/core/lib/logger'; +import { isServer } from '@vue-storefront/core/helpers'; +import { router } from '@vue-storefront/core/app' // Listeners moved from Product.js @@ -115,18 +117,20 @@ export const onUserPricesRefreshed = async (store, router) => { } } -export const checkConfigurableParent = (store) => { - const parentProduct = store.getters['product/getParentProduct'] - const currentProduct = store.getters['product/getCurrentProduct'] +export const checkParentRedirection = (currentProduct, parentProduct) => { if (parentProduct && parentProduct.id !== currentProduct.id && config.products.preventConfigurableChildrenDirectAccess) { Logger.log('Redirecting to parent, configurable product', parentProduct.sku)() const parentUrl = formatProductLink(parentProduct, currentStoreView().storeCode) - AsyncDataLoader.push({ - execute: async ({ context }) => { - if (context && !context.url.includes(parentUrl)) { - context.server.response.redirect(301, parentUrl) + if (isServer) { + AsyncDataLoader.push({ + execute: async ({ context }) => { + if (context && !context.url.includes(parentUrl)) { + context.server.response.redirect(301, parentUrl) + } } - } - }) + }) + } else { + router.replace(parentUrl as string) + } } } diff --git a/core/modules/catalog/store/product/actions.ts b/core/modules/catalog/store/product/actions.ts index 26a1363af7..b8fbd4b32d 100644 --- a/core/modules/catalog/store/product/actions.ts +++ b/core/modules/catalog/store/product/actions.ts @@ -32,6 +32,7 @@ import EventBus from '@vue-storefront/core/compatibility/plugins/event-bus' import { StorageManager } from '@vue-storefront/core/lib/storage-manager' import { quickSearchByQuery } from '@vue-storefront/core/lib/search' import { formatProductLink } from 'core/modules/url/helpers' +import { checkParentRedirection } from '@vue-storefront/core/modules/catalog/events' const PRODUCT_REENTER_TIMEOUT = 20000 @@ -212,6 +213,7 @@ const actions: ActionTree = { if (resp.items.length >= 1) { const parentProduct = resp.items[0] context.commit(types.PRODUCT_SET_PARENT, parentProduct) + return parentProduct } }).catch((err) => { Logger.error(err)() @@ -640,7 +642,12 @@ const actions: ActionTree = { throw new Error(`Product query returned empty result product status = ${product.status}`) } if (product.visibility === 1) { // not visible individually (https://magento.stackexchange.com/questions/171584/magento-2-table-name-for-product-visibility) - throw new Error(`Product query returned empty result product visibility = ${product.visibility}`) + if (config.products.preventConfigurableChildrenDirectAccess) { + const parentProduct = await dispatch('checkConfigurableParent', { product }) + checkParentRedirection(product, parentProduct) + } else { + throw new Error(`Product query returned empty result product visibility = ${product.visibility}`) + } } await dispatch('loadProductAttributes', { product }) @@ -651,12 +658,6 @@ const actions: ActionTree = { syncPromises.push(variantsFilter) syncPromises.push(gallerySetup) } - if (config.products.preventConfigurableChildrenDirectAccess) { - const parentChecker = dispatch('checkConfigurableParent', { product }) - if (isServer) { - syncPromises.push(parentChecker) - } - } await Promise.all(syncPromises) await EventBus.$emitFilter('product-after-load', { store: rootStore, route: route }) return product diff --git a/src/themes/default/pages/Product.vue b/src/themes/default/pages/Product.vue index 9ef307a6d9..95d040e8a2 100644 --- a/src/themes/default/pages/Product.vue +++ b/src/themes/default/pages/Product.vue @@ -225,7 +225,6 @@ import { registerModule, isModuleRegistered } from '@vue-storefront/core/lib/mod import { onlineHelper, isServer } from '@vue-storefront/core/helpers' import { catalogHooksExecutors } from '@vue-storefront/core/modules/catalog-next/hooks' import ProductPrice from 'theme/components/core/ProductPrice.vue' -import { checkConfigurableParent } from '@vue-storefront/core/modules/catalog/events' export default { components: { @@ -338,7 +337,6 @@ export default { const loadBreadcrumbsPromise = store.dispatch('product/loadProductBreadcrumbs', { product }) if (isServer) await loadBreadcrumbsPromise catalogHooksExecutors.productPageVisited(product) - checkConfigurableParent(store) }, beforeRouteEnter (to, from, next) { if (isServer) { From 41c791b59939fbe4b86fa908ec0000aa95cfda9a Mon Sep 17 00:00:00 2001 From: tkostuch Date: Wed, 20 May 2020 10:32:34 +0200 Subject: [PATCH 4/5] use findConfigurableParent instead of checkConfigurableParent --- core/modules/catalog/store/product/actions.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/core/modules/catalog/store/product/actions.ts b/core/modules/catalog/store/product/actions.ts index b8fbd4b32d..0f0c7e9fef 100644 --- a/core/modules/catalog/store/product/actions.ts +++ b/core/modules/catalog/store/product/actions.ts @@ -213,7 +213,6 @@ const actions: ActionTree = { if (resp.items.length >= 1) { const parentProduct = resp.items[0] context.commit(types.PRODUCT_SET_PARENT, parentProduct) - return parentProduct } }).catch((err) => { Logger.error(err)() @@ -643,7 +642,7 @@ const actions: ActionTree = { } if (product.visibility === 1) { // not visible individually (https://magento.stackexchange.com/questions/171584/magento-2-table-name-for-product-visibility) if (config.products.preventConfigurableChildrenDirectAccess) { - const parentProduct = await dispatch('checkConfigurableParent', { product }) + const parentProduct = await dispatch('findConfigurableParent', { product }) checkParentRedirection(product, parentProduct) } else { throw new Error(`Product query returned empty result product visibility = ${product.visibility}`) From 68b0a4b567a131853b6adc1d5d2ef54d8105e4d4 Mon Sep 17 00:00:00 2001 From: tkostuch Date: Wed, 20 May 2020 10:39:14 +0200 Subject: [PATCH 5/5] change skus to add proper configuration --- core/modules/catalog/events.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/core/modules/catalog/events.ts b/core/modules/catalog/events.ts index a924bb6be7..f99f03716b 100644 --- a/core/modules/catalog/events.ts +++ b/core/modules/catalog/events.ts @@ -120,6 +120,8 @@ export const onUserPricesRefreshed = async (store, router) => { export const checkParentRedirection = (currentProduct, parentProduct) => { if (parentProduct && parentProduct.id !== currentProduct.id && config.products.preventConfigurableChildrenDirectAccess) { Logger.log('Redirecting to parent, configurable product', parentProduct.sku)() + parentProduct.parentSku = parentProduct.sku + parentProduct.sku = currentProduct.sku const parentUrl = formatProductLink(parentProduct, currentStoreView().storeCode) if (isServer) { AsyncDataLoader.push({