Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Added
- Add `ProductPrice` component with bundleOptions and customOptions prices - @gibkigonzo (#3978)
- Add lazy create cart token - @gibkigonzo (#3994)

### Changed / Improved
- Set cache tag when loading a category - @haelbichalex (#3940)
Expand All @@ -33,6 +34,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Fixed sku attribute is missing on compare page - @gibkigonzo (#4036)
- Fixed z-index for aside in compare list - @gibkigonzo (#4037)
- Disable checking max quantity when manage stock is set to false - @gibkigonzo (#4038)
- Add products quantity only when token is created - @gibkigonzo (#4017)
- Revert init filters in Vue app - add storeView to global/store and pass it to filters - @gibkigonzo (#3929)
- Fix v-model not working in BaseRadioButton - @lukeromanowicz (#4035)

## [1.11.0] - 2019.12.20
Expand Down
1 change: 0 additions & 1 deletion config/default.json
Original file line number Diff line number Diff line change
Expand Up @@ -270,7 +270,6 @@
"width": 150,
"height": 150
},
"bypassCartLoaderForAuthorizedUsers": true,
"serverMergeByDefault": true,
"serverSyncCanRemoveLocalItems": false,
"serverSyncCanModifyLocalItems": false,
Expand Down
10 changes: 0 additions & 10 deletions core/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,16 +77,6 @@ const createApp = async (ssrContext, config, storeCode = null): Promise<{app: Vu
})
})

// @todo remove this part when we'll get rid of global multistore mixin
if (isServer) {
Object.defineProperty(ssrContext, 'helpers', {
value: {
currentStoreView
},
writable: true
})
}

let vueOptions = {
router: routerProxy,
store,
Expand Down
7 changes: 4 additions & 3 deletions core/filters/date.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,10 @@ once('__VUE_EXTEND_DAYJS_LOCALIZED_FORMAT__', () => {
* @param {String} date
* @param {String} format
*/
export function date (date, format) {
const displayFormat = format || currentStoreView().i18n.dateFormat
let storeLocale = currentStoreView().i18n.defaultLocale.toLocaleLowerCase()
export function date (date, format, storeView) {
const _storeView = storeView || currentStoreView()
const displayFormat = format || _storeView.i18n.dateFormat
let storeLocale = _storeView.i18n.defaultLocale.toLocaleLowerCase()
const separatorIndex = storeLocale.indexOf('-')
const languageCode = (separatorIndex > -1) ? storeLocale.substr(0, separatorIndex) : storeLocale

Expand Down
8 changes: 4 additions & 4 deletions core/filters/price.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,15 @@ const applyCurrencySign = (formattedPrice, { currencySign, priceFormat }) => {
* Converts number to price string
* @param {Number} value
*/
export function price (value) {
export function price (value, storeView) {
if (isNaN(value)) {
return value;
}
const storeView = currentStoreView();
if (!storeView.i18n) {
const _storeView = storeView || currentStoreView();
if (!_storeView.i18n) {
return value;
}
const { defaultLocale, currencySign, priceFormat } = storeView.i18n
const { defaultLocale, currencySign, priceFormat } = _storeView.i18n

const formattedValue = formatValue(value, defaultLocale);
const valueWithSign = applyCurrencySign(formattedValue, { currencySign, priceFormat })
Expand Down
36 changes: 26 additions & 10 deletions core/lib/multistore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ import { coreHooksExecutors } from '@vue-storefront/core/hooks'
import { StorageManager } from '@vue-storefront/core/lib/storage-manager'
import { LocalizedRoute, StoreView } from './types'
import storeCodeFromRoute from './storeCodeFromRoute'
import cloneDeep from 'lodash-es/cloneDeep'
import get from 'lodash-es/get'
import { isServer } from '@vue-storefront/core/helpers'

function getExtendedStoreviewConfig (storeView: StoreView): StoreView {
if (storeView.extend) {
Expand All @@ -30,20 +33,28 @@ function getExtendedStoreviewConfig (storeView: StoreView): StoreView {
return storeView
}

/**
* Returns base storeView object that can be created without storeCode
*/
function buildBaseStoreView (): StoreView {
return cloneDeep({
tax: config.tax,
i18n: config.i18n,
elasticsearch: config.elasticsearch,
storeCode: null,
storeId: config.defaultStoreCode && config.defaultStoreCode !== '' ? config.storeViews[config.defaultStoreCode].storeId : 1,
seo: config.seo
})
}

export function currentStoreView (): StoreView {
// TODO: Change to getter all along our code
return rootStore.state.storeView
const serverStoreView = get(global, 'process.storeView', undefined)
const clientStoreView = get(rootStore, 'state.storeView', undefined)
return (isServer ? serverStoreView : clientStoreView) || buildBaseStoreView()
}

export async function prepareStoreView (storeCode: string): Promise<StoreView> {
let storeView: StoreView = { // current, default store
tax: Object.assign({}, config.tax),
i18n: Object.assign({}, config.i18n),
elasticsearch: Object.assign({}, config.elasticsearch),
storeCode: null,
storeId: config.defaultStoreCode && config.defaultStoreCode !== '' ? config.storeViews[config.defaultStoreCode].storeId : 1,
seo: Object.assign({}, config.seo)
}
let storeView: StoreView = buildBaseStoreView() // current, default store

if (config.storeViews.multistore === true) {
storeView.storeCode = storeCode || config.defaultStoreCode || ''
Expand All @@ -61,6 +72,11 @@ export async function prepareStoreView (storeCode: string): Promise<StoreView> {
if (storeViewHasChanged) {
storeView = coreHooksExecutors.beforeStoreViewChanged(storeView)
rootStore.state.storeView = storeView

if (global && isServer) {
(global.process as any).storeView = storeView
}

await loadLanguageAsync(storeView.i18n.defaultLocale)
}
if (storeViewHasChanged || StorageManager.currentStoreCode !== storeCode) {
Expand Down
16 changes: 2 additions & 14 deletions core/mixins/multistore.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,7 @@ export const multistore = {
* @param {Int} height
*/
localizedRoute (routeObj) {
let storeView

if (isServer) {
storeView = this.$ssrContext.helpers.currentStoreView()
} else {
storeView = currentStoreView()
}
const storeView = currentStoreView()

return localizedRouteHelper(routeObj, storeView.storeCode)
},
Expand All @@ -27,13 +21,7 @@ export const multistore = {
* @param {Int} height
*/
localizedDispatcherRoute (routeObj) {
let storeView

if (isServer) {
storeView = this.$ssrContext.helpers.currentStoreView()
} else {
storeView = currentStoreView()
}
const storeView = currentStoreView()

return localizedDispatcherRouteHelper(routeObj, storeView.storeCode)
}
Expand Down
4 changes: 2 additions & 2 deletions core/modules/cart/helpers/createCartItemForUpdate.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import config from 'config'
import CartItem from '@vue-storefront/core/modules/cart/types/CartItem';

const createCartItemForUpdate = (clientItem: CartItem, serverItem: any, updateIds: boolean = false): CartItem => {
const createCartItemForUpdate = (clientItem: CartItem, serverItem: any, updateIds: boolean = false, mergeQty: boolean = false): CartItem => {
const sku = clientItem.parentSku && config.cart.setConfigurableProductOptions ? clientItem.parentSku : clientItem.sku
const cartItem = {
sku,
qty: clientItem.qty,
qty: mergeQty ? (clientItem.qty + serverItem.qty) : clientItem.qty,
product_option: clientItem.product_option
} as any as CartItem

Expand Down
35 changes: 19 additions & 16 deletions core/modules/cart/store/actions/connectActions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,28 +9,20 @@ const connectActions = {
toggleMicrocart ({ commit }) {
commit(types.CART_TOGGLE_MICROCART)
},
async clear ({ commit, dispatch, getters }, options = { recreateAndSyncCart: true }) {
async clear ({ commit, dispatch, getters }) {
await commit(types.CART_LOAD_CART, [])
if (options.recreateAndSyncCart && getters.isCartSyncEnabled) {
await commit(types.CART_LOAD_CART_SERVER_TOKEN, null)
await commit(types.CART_SET_ITEMS_HASH, null)
await dispatch('connect', { guestCart: !config.orders.directBackendSync }) // guest cart when not using directBackendSync because when the order hasn't been passed to Magento yet it will repopulate your cart
}
await commit(types.CART_LOAD_CART_SERVER_TOKEN, null)
await commit(types.CART_SET_ITEMS_HASH, null)
},
async disconnect ({ commit }) {
commit(types.CART_LOAD_CART_SERVER_TOKEN, null)
},
async authorize ({ dispatch, getters }) {
const coupon = getters.getCoupon.code
const lastCartBypassTs = await StorageManager.get('user').getItem('last-cart-bypass-ts')
const timeBypassCart = config.orders.directBackendSync || (Date.now() - lastCartBypassTs) >= (1000 * 60 * 24)

if (!config.cart.bypassCartLoaderForAuthorizedUsers || timeBypassCart) {
await dispatch('connect', { guestCart: false })
await dispatch('connect', { guestCart: false })

if (!getters.getCoupon) {
await dispatch('applyCoupon', coupon)
}
const coupon = getters.getCoupon.code
if (!getters.getCoupon) {
await dispatch('applyCoupon', coupon)
}
},
async connect ({ getters, dispatch, commit }, { guestCart = false, forceClientState = false }) {
Expand All @@ -41,7 +33,7 @@ const connectActions = {
Logger.info('Server cart token created.', 'cart', result)()
commit(types.CART_LOAD_CART_SERVER_TOKEN, result)

return dispatch('sync', { forceClientState, dryRun: !config.cart.serverMergeByDefault })
return dispatch('sync', { forceClientState, dryRun: !config.cart.serverMergeByDefault, mergeQty: true })
}

if (resultCode === 401 && getters.bypassCounter < config.queues.maxCartBypassAttempts) {
Expand All @@ -53,6 +45,17 @@ const connectActions = {

Logger.warn('Cart sync is disabled by the config', 'cart')()
return createDiffLog()
},
/**
* Create cart token when there are products in cart and we don't have token already
*/
async create ({ dispatch, getters }) {
const storedItems = getters['getCartItems'] || []
const cartToken = getters['getCartToken']
if (storedItems.length && !cartToken) {
Logger.info('Creating server cart token', 'cart')()
await dispatch('connect', { guestCart: false })
}
}
}

Expand Down
1 change: 1 addition & 0 deletions core/modules/cart/store/actions/itemActions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ const itemActions = {
productIndex++
}
}
await dispatch('create')
if (getters.isCartSyncEnabled && getters.isCartConnected && !forceServerSilence) {
return dispatch('sync', { forceClientState: true })
}
Expand Down
23 changes: 12 additions & 11 deletions core/modules/cart/store/actions/mergeActions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,9 @@ const mergeActions = {
await dispatch('updateItem', { product })
EventBus.$emit('cart-after-itemchanged', { item: cartItem })
},
async updateServerItem ({ getters, rootGetters, commit, dispatch }, { clientItem, serverItem, updateIds }) {
async updateServerItem ({ getters, rootGetters, commit, dispatch }, { clientItem, serverItem, updateIds, mergeQty }) {
const diffLog = createDiffLog()
const cartItem = createCartItemForUpdate(clientItem, serverItem, updateIds)
const cartItem = createCartItemForUpdate(clientItem, serverItem, updateIds, mergeQty)
const event = await CartService.updateItem(getters.getCartToken, cartItem)
const wasUpdatedSuccessfully = event.resultCode === 200
Logger.debug('Cart item server sync' + event, 'cart')()
Expand Down Expand Up @@ -65,7 +65,7 @@ const mergeActions = {

return diffLog
},
async synchronizeServerItem ({ dispatch }, { serverItem, clientItem, forceClientState, dryRun }) {
async synchronizeServerItem ({ dispatch }, { serverItem, clientItem, forceClientState, dryRun, mergeQty }) {
const diffLog = createDiffLog()

if (!serverItem) {
Expand All @@ -82,12 +82,12 @@ const mergeActions = {
return diffLog
}

if (serverItem.qty !== clientItem.qty) {
if (serverItem.qty !== clientItem.qty || mergeQty) {
Logger.log('Wrong qty for ' + clientItem.sku, clientItem.qty, serverItem.qty)()
diffLog.pushServerParty({ sku: clientItem.sku, status: 'wrong-qty', 'client-qty': clientItem.qty, 'server-qty': serverItem.qty })
if (dryRun) return diffLog
if (forceClientState || !config.cart.serverSyncCanModifyLocalItems) {
const updateServerItemDiffLog = await dispatch('updateServerItem', { clientItem, serverItem, updateIds: true })
const updateServerItemDiffLog = await dispatch('updateServerItem', { clientItem, serverItem, updateIds: true, mergeQty })

return diffLog.merge(updateServerItemDiffLog)
}
Expand All @@ -97,9 +97,9 @@ const mergeActions = {

return diffLog
},
async mergeClientItem ({ dispatch }, { clientItem, serverItems, forceClientState, dryRun }) {
async mergeClientItem ({ dispatch }, { clientItem, serverItems, forceClientState, dryRun, mergeQty }) {
const serverItem = serverItems.find(itm => productsEquals(itm, clientItem))
const diffLog = await dispatch('synchronizeServerItem', { serverItem, clientItem, forceClientState, dryRun })
const diffLog = await dispatch('synchronizeServerItem', { serverItem, clientItem, forceClientState, dryRun, mergeQty })

if (!diffLog.isEmpty()) return diffLog

Expand All @@ -118,12 +118,12 @@ const mergeActions = {

return diffLog
},
async mergeClientItems ({ dispatch }, { clientItems, serverItems, forceClientState, dryRun }) {
async mergeClientItems ({ dispatch }, { clientItems, serverItems, forceClientState, dryRun, mergeQty }) {
const diffLog = createDiffLog()

for (const clientItem of clientItems) {
try {
const mergeClientItemDiffLog = await dispatch('mergeClientItem', { clientItem, serverItems, forceClientState, dryRun })
const mergeClientItemDiffLog = await dispatch('mergeClientItem', { clientItem, serverItems, forceClientState, dryRun, mergeQty })
diffLog.merge(mergeClientItemDiffLog)
} catch (e) {
Logger.debug('Problem syncing clientItem', 'cart', clientItem)()
Expand Down Expand Up @@ -186,15 +186,16 @@ const mergeActions = {

commit(types.CART_SET_ITEMS_HASH, getters.getCurrentCartHash)
},
async merge ({ getters, dispatch }, { serverItems, clientItems, dryRun = false, forceClientState = false }) {
async merge ({ getters, dispatch }, { serverItems, clientItems, dryRun = false, forceClientState = false, mergeQty = false }) {
const hookResult = cartHooksExecutors.beforeSync({ clientItems, serverItems })

const diffLog = createDiffLog()
const mergeParameters = {
clientItems: hookResult.clientItems,
serverItems: hookResult.serverItems,
forceClientState,
dryRun
dryRun,
mergeQty
}
const mergeClientItemsDiffLog = await dispatch('mergeClientItems', mergeParameters)
const mergeServerItemsDiffLog = await dispatch('mergeServerItems', mergeParameters)
Expand Down
9 changes: 4 additions & 5 deletions core/modules/cart/store/actions/synchronizeActions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,17 +36,15 @@ const synchronizeActions = {
Logger.info('Cart token received from cache.', 'cache', token)()
Logger.info('Syncing cart with the server.', 'cart')()
dispatch('sync', { forceClientState, dryRun: !serverMergeByDefault })
} else {
Logger.info('Creating server cart token', 'cart')()
await dispatch('connect', { guestCart: false })
}
await dispatch('create')
},
/** @deprecated backward compatibility only */
async serverPull ({ dispatch }, { forceClientState = false, dryRun = false }) {
Logger.warn('The "cart/serverPull" action is deprecated and will not be supported with the Vue Storefront 1.11', 'cart')()
return dispatch('sync', { forceClientState, dryRun })
},
async sync ({ getters, rootGetters, commit, dispatch, state }, { forceClientState = false, dryRun = false }) {
async sync ({ getters, rootGetters, commit, dispatch, state }, { forceClientState = false, dryRun = false, mergeQty = false }) {
const shouldUpdateClientState = rootGetters['checkout/isUserInCheckout'] || forceClientState
const { getCartItems, canUpdateMethods, isSyncRequired, bypassCounter } = getters
if (!canUpdateMethods || !isSyncRequired) return createDiffLog()
Expand All @@ -59,7 +57,8 @@ const synchronizeActions = {
dryRun,
serverItems,
clientItems,
forceClientState: shouldUpdateClientState
forceClientState: shouldUpdateClientState,
mergeQty
})
cartHooksExecutors.afterSync(diffLog)
return diffLog
Expand Down
Loading