diff --git a/core/app.ts b/core/app.ts index 3cebe3d209..eca83b5f0f 100755 --- a/core/app.ts +++ b/core/app.ts @@ -29,6 +29,10 @@ declare var global: any if (!global.$VS) global.$VS = {} store.state.version = '1.3' +store.state.__DEMO_MODE__ = (config.demomode === true) ? true : false +store.state.config = config +global.$VS.i18n = i18n +global.$VS.eventBus = EventBus const storeModules = Object.assign(coreModules, themeModules || {}) @@ -37,7 +41,7 @@ for (const moduleName of Object.keys(storeModules)) { store.registerModule(moduleName, storeModules[moduleName]) } -const storeView = prepareStoreView(null, config, i18n, EventBus) // prepare the default storeView +const storeView = prepareStoreView(null) // prepare the default storeView store.state.storeView = storeView store.state.shipping.methods = shippingMethods @@ -83,11 +87,5 @@ export function createApp (): { app: Vue, router: any, store: any } { app.$emit('application-after-init', app) - if (config.demomode === true) { - global.$VS.__DEMO_MODE__ = true - } else { - global.$VS.__DEMO_MODE__ = false - } - return { app, router, store } } diff --git a/core/client-entry.ts b/core/client-entry.ts index 128b82d9d6..950ac7e3cd 100755 --- a/core/client-entry.ts +++ b/core/client-entry.ts @@ -1,12 +1,10 @@ import * as localForage from 'localforage' import { union } from 'lodash-es' import sizeof from 'object-sizeof' -import config from 'config' import { createApp } from '@vue-storefront/core/app' import EventBus from '@vue-storefront/core/plugins/event-bus' -import rootStore from '@vue-storefront/store' import { execute } from '@vue-storefront/store/lib/task' import UniversalStorage from '@vue-storefront/store/lib/storage' import i18n from '@vue-storefront/core/lib/i18n' @@ -20,13 +18,15 @@ declare var window: any const { app, router, store } = createApp() +const config = store.state.config + let storeCode = null // select the storeView by prefetched vuex store state (prefetched serverside) if (window.__INITIAL_STATE__) { store.replaceState(window.__INITIAL_STATE__) } if (config.storeViews.multistore === true) { - if ((storeCode = rootStore.state.user.current_storecode)) { - prepareStoreView(storeCode, config) + if ((storeCode = store.state.user.current_storecode)) { + prepareStoreView(storeCode) } } @@ -74,7 +74,7 @@ router.onReady(() => { if (storeCode !== currentStore.storeCode) { document.location = to.path // full reload } else { - prepareStoreView(storeCode, config) + prepareStoreView(storeCode) } } } @@ -314,8 +314,8 @@ EventBus.$on('user-before-logout', () => { } }) -rootStore.dispatch('cart/load') -rootStore.dispatch('compare/load') -rootStore.dispatch('user/startSession') +store.dispatch('cart/load') +store.dispatch('compare/load') +store.dispatch('user/startSession') window.addEventListener('online', () => { onNetworkStatusChange(store) }) diff --git a/core/lib/i18n.ts b/core/lib/i18n.ts index 9aa601bdb2..04d6c32121 100644 --- a/core/lib/i18n.ts +++ b/core/lib/i18n.ts @@ -7,19 +7,12 @@ Vue.use(VueI18n) const loadedLanguages = ['en-US'] const i18n = new VueI18n({ locale: 'en-US', // set locale - fallbackLocale: 'en-US' + fallbackLocale: 'en-US', + messages: { + 'en-US': require('../resource/i18n/en-US.json') + } }) -i18n.setLocaleMessage('en-US', require('../resource/i18n/en-US.json')) - -declare var global: any - -if (!global.$VS) { - global.$VS = { i18n: i18n } -} else { - global.$VS.i18n = i18n -} - function setI18nLanguage (lang: string): string { i18n.locale = lang return lang @@ -32,6 +25,9 @@ export function loadLanguageAsync (lang: string): Promise { i18n.setLocaleMessage(lang, msgs.default) loadedLanguages.push(lang) return setI18nLanguage(lang) + }).catch(err => { + console.debug('Unable to load translation') + return '' }) } return Promise.resolve(setI18nLanguage(lang)) @@ -41,4 +37,4 @@ export function loadLanguageAsync (lang: string): Promise { loadLanguageAsync(config.i18n.defaultLocale) -export default global.$VS.i18n +export default i18n diff --git a/core/package.json b/core/package.json index 7167c11e19..5bf4f159d9 100644 --- a/core/package.json +++ b/core/package.json @@ -10,7 +10,7 @@ "dependencies": { "@vue-storefront/store": "^1.1.0", "app-root-path": "^2.0.1", - "bodybuilder": "^2.2.1", + "bodybuilder": "^2.2.13", "config": "^1.30.0", "d3-dsv": "^1.0.8", "detect-installed": "^2.0.4", @@ -26,7 +26,7 @@ "url-parse": "^1.2.0", "vue": "^2.5.2", "vue-carousel": "^0.6.9", - "vue-i18n": "^7.4.2", + "vue-i18n": "^8.0.0", "vue-lazyload": "^1.2.6", "vue-meta": "^1.4.3", "vue-observe-visibility": "^0.3.1", diff --git a/core/server-entry.ts b/core/server-entry.ts index c0eb2ae7c8..54807dd780 100755 --- a/core/server-entry.ts +++ b/core/server-entry.ts @@ -1,4 +1,3 @@ -import config from 'config' import { union } from 'lodash-es' import { createApp } from '@vue-storefront/core/app' @@ -37,13 +36,13 @@ export default context => { router.push(context.url) context.meta = meta router.onReady(() => { - if (config.storeViews.multistore === true) { + if (store.state.config.storeViews.multistore === true) { let storeCode = context.storeCode // this is from http header or env variable if (router.currentRoute) { // this is from url storeCode = storeCodeFromRoute(router.currentRoute) } if (storeCode !== '' && storeCode !== null) { - prepareStoreView(storeCode, config) + prepareStoreView(storeCode) } } const matchedComponents = router.getMatchedComponents() diff --git a/core/store/helpers/index.js b/core/store/helpers/index.ts similarity index 85% rename from core/store/helpers/index.js rename to core/store/helpers/index.ts index bf4771bb21..a8df742a04 100644 --- a/core/store/helpers/index.js +++ b/core/store/helpers/index.ts @@ -1,5 +1,5 @@ -import builder from 'bodybuilder' -import config from '../lib/config' +import rootStore from '../' +import bodybuilder from 'bodybuilder' /** * Create slugify -> "create-slugify" permalink of text @@ -21,7 +21,7 @@ export function slugify (text) { */ export function getThumbnailPath (relativeUrl, width, height) { - return relativeUrl && relativeUrl.indexOf('no_selection') < 0 ? `${config.images.baseUrl}${parseInt(width)}/${parseInt(height)}/resize${relativeUrl}` : config.images.productPlaceholder || '' + return relativeUrl && relativeUrl.indexOf('no_selection') < 0 ? `${rootStore.state.config.images.baseUrl}${parseInt(width)}/${parseInt(height)}/resize${relativeUrl}` : rootStore.state.config.images.productPlaceholder || '' } /** @@ -33,7 +33,7 @@ export function breadCrumbRoutes (categoryPath) { for (let sc of categoryPath) { tmpRts.push({ name: sc.name, - route_link: (config.products.useShortCatalogUrls ? '/' : '/c/') + sc.slug + route_link: (rootStore.state.config.products.useShortCatalogUrls ? '/' : '/c/') + sc.slug }) } @@ -65,7 +65,7 @@ export function productThumbnailPath (product, ignoreConfig = false) { } export function buildFilterProductsQuery (currentCategory, chosenFilters, defaultFilters = null) { - let filterQr = baseFilterProductsQuery(currentCategory, defaultFilters == null ? config.products.defaultFilters : defaultFilters) + let filterQr = baseFilterProductsQuery(currentCategory, defaultFilters == null ? rootStore.state.config.products.defaultFilters : defaultFilters) let attrFilterBuilder = (filterQr, attrPostfix = '') => { for (let code of Object.keys(chosenFilters)) { const filter = chosenFilters[code] @@ -91,8 +91,8 @@ export function buildFilterProductsQuery (currentCategory, chosenFilters, defaul } export function baseFilterProductsQuery (parentCategory, filters = []) { // TODO add aggregation of color_options and size_options fields - let searchProductQuery = builder().andFilter('range', 'status', { 'gte': 0, 'lt': 2 }/* 2 = disabled, 4 = out of stock */).andFilter('range', 'visibility', { 'gte': 2, 'lte': 4 }/** Magento visibility in search & categories */) - if (config.products.listOutOfStockProducts === false) { + let searchProductQuery = bodybuilder().andFilter('range', 'status', { 'gte': 0, 'lt': 2 }/* 2 = disabled, 4 = out of stock */).andFilter('range', 'visibility', { 'gte': 2, 'lte': 4 }/** Magento visibility in search & categories */) + if (rootStore.state.config.products.listOutOfStockProducts === false) { searchProductQuery = searchProductQuery.andFilter('match', 'stock.is_in_stock', true) } // add filters to query diff --git a/core/store/index.ts b/core/store/index.ts index 113217093c..27410b932a 100644 --- a/core/store/index.ts +++ b/core/store/index.ts @@ -1,5 +1,6 @@ import Vue from 'vue' import Vuex from 'vuex' +import { Plugin } from 'vuex' import * as types from './mutation-types' import * as localForage from 'localforage' import UniversalStorage from './lib/storage' @@ -13,18 +14,36 @@ Vue.use(Vuex) const state = { version: '', + __DEMO_MODE__: false, + config: {}, + cart: {}, + checkout: {}, + cms: {}, + compare: {}, + product: {}, + shipping: {}, + user: {}, + wishlist: {}, attribute: '', category: { current_path: '', + current_product_query: {}, current: { slug: '', name: '' - } + }, + filters: {} }, stock: { cache: [] }, - storeView: {} + storeView: {}, + twoStageCachingDelta1: 0, + twoStageCachingDelta2: 0, + twoStageCachingDisabled: false, + userTokenInvalidated: null, + userTokenInvalidateAttemptsCount: 0, + userTokenInvalidateLock: 0 } const mutations = { @@ -41,7 +60,7 @@ const mutations = { } } -const plugins = [ +const plugins: Plugin[] = [ store => { store.subscribe((mutation, state) => { let nameArray = mutation.type.split('/') @@ -127,38 +146,12 @@ let rootStore = new Vuex.Store({ state, mutations, plugins -}) as any +}) -rootStore.i18n = { - t: function (key) { - return key - } -} -rootStore.eventBus = new Vue() - -rootStore.init = function (config, i18n = null, eventBus = null) { // TODO: init sub modules "context" with i18n + eventBus - if (config !== null) { - console.debug('Vuex VS store - using external config') - this.config = config - global.$VS.config = Object.assign(global.$VS.config, config) - } - if (i18n !== null) { - console.debug('Vuex VS store - using external i18n') - this.i18n = i18n - global.$VS.i18n = Object.assign(global.$VS.i18n, i18n) - } else { - global.$VS.i18n = { - t: function (key) { - return key - } - } - } - if (eventBus !== null) { - console.debug('Vuex VS store - using external event-bus') - this.eventBus = eventBus - global.$VS.eventBus = Object.assign(global.$VS.eventBus, eventBus) - } +export default rootStore +export function initStore () { + const config = rootStore.state.config const storeView = currentStoreView() const dbNamePrefix = storeView.storeCode ? storeView.storeCode + '-' : '' Vue.prototype.$db = { @@ -238,5 +231,4 @@ rootStore.init = function (config, i18n = null, eventBus = null) { // TODO: init })) } global.$VS.db = Vue.prototype.$db // localForage instance -} -export default rootStore +} \ No newline at end of file diff --git a/core/store/lib/config.js b/core/store/lib/config.js deleted file mode 100644 index 866e04d5ea..0000000000 --- a/core/store/lib/config.js +++ /dev/null @@ -1,5 +0,0 @@ -global.$VS = (global.$VS ? global.$VS : {}) -if (!global.$VS.config) { - global.$VS.config = {} -} -export default global.$VS.config diff --git a/core/store/lib/multistore.js b/core/store/lib/multistore.js index 963d387146..74b2673f4b 100644 --- a/core/store/lib/multistore.js +++ b/core/store/lib/multistore.js @@ -1,13 +1,12 @@ -import config from 'config' -import store from '../' -import EventBus from './event-bus' +import rootStore, { initStore } from '../' import { loadLanguageAsync } from '@vue-storefront/core/lib/i18n' export function currentStoreView () { - return store.state.storeView + return rootStore.state.storeView } -export function prepareStoreView (storeCode, config, i18n = null, eventBus = null) { +export function prepareStoreView (storeCode) { + const config = rootStore.state.config let storeView = { // current, default store tax: config.tax, i18n: config.i18n, @@ -18,23 +17,23 @@ export function prepareStoreView (storeCode, config, i18n = null, eventBus = nul if (storeCode) { // current store code if ((storeView = config.storeViews[storeCode])) { storeView.storeCode = storeCode - store.state.user.current_storecode = storeCode + rootStore.state.user.current_storecode = storeCode } } else { storeView.storeCode = config.defaultStoreCode || '' - store.state.user.current_storecode = config.defaultStoreCode || '' + rootStore.state.user.current_storecode = config.defaultStoreCode || '' } - if (!store.state.storeView || store.state.storeView.storeCode !== storeCode) { - store.state.storeView = storeView - loadLanguageAsync(storeView.i18n.defaultLocale) - store.init(config, i18n || global.$VS.i18n, eventBus || EventBus) + loadLanguageAsync(storeView.i18n.defaultLocale) + if (!rootStore.state.storeView || rootStore.state.storeView.storeCode !== storeCode) { + rootStore.state.storeView = storeView + initStore() } return storeView } export function storeCodeFromRoute (matchedRoute) { if (matchedRoute) { - for (const storeCode of config.storeViews.mapStoreUrlsFor) { + for (const storeCode of rootStore.state.config.storeViews.mapStoreUrlsFor) { if (matchedRoute.path.indexOf('/' + storeCode + '/') === 0 || matchedRoute.path === '/' + storeCode) { return storeCode } @@ -55,7 +54,7 @@ export function adjustMultistoreApiUrl (url) { } export function localizedRoute (routeObj, storeCode) { - if (storeCode && routeObj && config.defaultStoreCode !== storeCode) { + if (storeCode && routeObj && rootStore.state.config.defaultStoreCode !== storeCode) { if (typeof routeObj === 'object') { if (routeObj.name) { routeObj.name = storeCode + '-' + routeObj.name diff --git a/core/store/lib/search.js b/core/store/lib/search.js index e88b61899d..f0ef4ec356 100644 --- a/core/store/lib/search.js +++ b/core/store/lib/search.js @@ -2,7 +2,6 @@ import map from 'lodash-es/map' import { slugify } from '../helpers' import { currentStoreView } from './multistore' import hash from 'object-hash' -import config from 'config' import fetch from 'isomorphic-fetch' import rootStore from '../' @@ -69,7 +68,7 @@ function _handleEsResult (resp, start = 0, size = 50) { if (resp.hasOwnProperty('hits')) { return { items: map(resp.hits.hits, (hit) => { - return Object.assign(hit._source, { _score: hit._score, slug: (hit._source.hasOwnProperty('url_key') && config.products.useMagentoUrlKeys) ? hit._source.url_key : (hit._source.hasOwnProperty('name') ? slugify(hit._source.name) + '-' + hit._source.id : '') }) // TODO: assign slugs server side + return Object.assign(hit._source, { _score: hit._score, slug: (hit._source.hasOwnProperty('url_key') && rootStore.state.config.products.useMagentoUrlKeys) ? hit._source.url_key : (hit._source.hasOwnProperty('name') ? slugify(hit._source.name) + '-' + hit._source.id : '') }) // TODO: assign slugs server side }), // TODO: add scoring information total: resp.hits.total, start: start, @@ -112,7 +111,7 @@ export function quickSearchByQuery ({ query, start = 0, size = 50, entityType = if (excludeFields) esQuery._sourceExclude = excludeFields if (includeFields) esQuery._sourceInclude = includeFields - if (config.usePriceTiers && (entityType === 'product') && rootStore.state.user.groupId) { + if (rootStore.state.config.usePriceTiers && (entityType === 'product') && rootStore.state.user.groupId) { esQuery.body.groupId = rootStore.state.user.groupId } @@ -156,7 +155,7 @@ export function quickSearchByQuery ({ query, start = 0, size = 50, entityType = delete esQuery.body.groupId } - if (config.usePriceTiers && rootStore.state.user.groupToken) { + if (rootStore.state.config.usePriceTiers && rootStore.state.user.groupToken) { esQuery.body.groupToken = rootStore.state.user.groupToken } diff --git a/core/store/lib/storage.js b/core/store/lib/storage.js index ea42a00389..dbee02738a 100644 --- a/core/store/lib/storage.js +++ b/core/store/lib/storage.js @@ -9,11 +9,11 @@ class LocalForageCacheDriver { constructor (collection, useLocalCacheByDefault = true) { const collectionName = collection._config.storeName const dbName = collection._config.name - if (typeof global.$VS.cacheErrorsCount === 'undefined') { - global.$VS.cacheErrorsCount = {} + if (typeof this.cacheErrorsCount === 'undefined') { + this.cacheErrorsCount = {} } - if (typeof global.$VS.cacheErrorsCount[collectionName] === 'undefined') { - global.$VS.cacheErrorsCount[collectionName] = 0 + if (typeof this.cacheErrorsCount[collectionName] === 'undefined') { + this.cacheErrorsCount[collectionName] = 0 } if (typeof global.$VS.localCache === 'undefined') { global.$VS.localCache = {} @@ -72,7 +72,7 @@ class LocalForageCacheDriver { } if (!Vue.prototype.$isServer) { - if (global.$VS.cacheErrorsCount[this._collectionName] >= DISABLE_PERSISTANCE_AFTER && this._useLocalCacheByDefault) { + if (this.cacheErrorsCount[this._collectionName] >= DISABLE_PERSISTANCE_AFTER && this._useLocalCacheByDefault) { if (!this._persistenceErrorNotified) { console.error('Persistent cache disabled becasue of previous errors [get]', key) this._persistenceErrorNotified = true @@ -113,11 +113,11 @@ class LocalForageCacheDriver { setTimeout(() => { if (!isResolved) { // this is cache time out check if (!this._persistenceErrorNotified) { - console.error('Cache not responding within ' + CACHE_TIMEOUT + ' ms for [get]', key, global.$VS.cacheErrorsCount[this._collectionName]) + console.error('Cache not responding within ' + CACHE_TIMEOUT + ' ms for [get]', key, this.cacheErrorsCount[this._collectionName]) this._persistenceErrorNotified = true this.recreateDb() } - global.$VS.cacheErrorsCount[this._collectionName] = global.$VS.cacheErrorsCount[this._collectionName] ? global.$VS.cacheErrorsCount[this._collectionName] + 1 : 1 + this.cacheErrorsCount[this._collectionName] = this.cacheErrorsCount[this._collectionName] ? this.cacheErrorsCount[this._collectionName] + 1 : 1 if (isCallbackCallable) callback(null, typeof this._localCache[key] !== 'undefined' ? this._localCache[key] : null) } }, CACHE_TIMEOUT) @@ -175,11 +175,11 @@ class LocalForageCacheDriver { setTimeout(() => { if (!isResolved) { // this is cache time out check if (!this._persistenceErrorNotified) { - console.error('Cache not responding within ' + CACHE_TIMEOUT_ITERATE + ' ms for [iterate]', global.$VS.cacheErrorsCount[this._collectionName]) + console.error('Cache not responding within ' + CACHE_TIMEOUT_ITERATE + ' ms for [iterate]', this.cacheErrorsCount[this._collectionName]) this._persistenceErrorNotified = true this.recreateDb() } - global.$VS.cacheErrorsCount[this._collectionName] = global.$VS.cacheErrorsCount[this._collectionName] ? global.$VS.cacheErrorsCount[this._collectionName] + 1 : 1 + this.cacheErrorsCount[this._collectionName] = this.cacheErrorsCount[this._collectionName] ? this.cacheErrorsCount[this._collectionName] + 1 : 1 if (isCallbackCallable) callback(null, null) } }, CACHE_TIMEOUT_ITERATE) @@ -216,7 +216,7 @@ class LocalForageCacheDriver { const isCallbackCallable = (typeof callback !== 'undefined' && callback) this._localCache[key] = value if (!Vue.prototype.$isServer) { - if (global.$VS.cacheErrorsCount[this._collectionName] >= DISABLE_PERSISTANCE_AFTER && this._useLocalCacheByDefault) { + if (this.cacheErrorsCount[this._collectionName] >= DISABLE_PERSISTANCE_AFTER && this._useLocalCacheByDefault) { if (!this._persistenceErrorNotified) { console.error('Persistent cache disabled becasue of previous errors [set]', key) this._persistenceErrorNotified = true @@ -239,11 +239,11 @@ class LocalForageCacheDriver { setTimeout(() => { if (!isResolved) { // this is cache time out check if (!this._persistenceErrorNotified) { - console.error('Cache not responding within ' + CACHE_TIMEOUT + ' ms for [set]', key, global.$VS.cacheErrorsCount[this._collectionName]) + console.error('Cache not responding within ' + CACHE_TIMEOUT + ' ms for [set]', key, this.cacheErrorsCount[this._collectionName]) this._persistenceErrorNotified = true this.recreateDb() } - global.$VS.cacheErrorsCount[this._collectionName] = global.$VS.cacheErrorsCount[this._collectionName] ? global.$VS.cacheErrorsCount[this._collectionName] + 1 : 1 + this.cacheErrorsCount[this._collectionName] = this.cacheErrorsCount[this._collectionName] ? this.cacheErrorsCount[this._collectionName] + 1 : 1 if (isCallbackCallable) callback(null, null) } }, CACHE_TIMEOUT) diff --git a/core/store/lib/task.js b/core/store/lib/task.js index 217af14b4e..d95e64ffe0 100644 --- a/core/store/lib/task.js +++ b/core/store/lib/task.js @@ -5,8 +5,8 @@ import isUndefined from 'lodash-es/isUndefined' import toString from 'lodash-es/toString' import fetch from 'isomorphic-fetch' import rootStore from '../' -import config from './config' import { adjustMultistoreApiUrl } from '@vue-storefront/store/lib/multistore' + const AUTO_REFRESH_MAX_ATTEMPTS = 20 function _sleep (time) { @@ -14,25 +14,25 @@ function _sleep (time) { } function _internalExecute (resolve, reject, task, currentToken, currentCartId) { - if (currentToken !== null && global.$VS.userTokenInvalidateLock > 0) { // invalidate lock set - console.log('Waiting for global.$VS.userTokenInvalidateLock to release for', task.url) + if (currentToken !== null && rootStore.state.userTokenInvalidateLock > 0) { // invalidate lock set + console.log('Waiting for rootStore.state.userTokenInvalidateLock to release for', task.url) _sleep(1000).then(() => { - console.log('Another try for global.$VS.userTokenInvalidateLock for ', task.url) + console.log('Another try for rootStore.state.userTokenInvalidateLock for ', task.url) _internalExecute(resolve, reject, task, currentToken, currentCartId) }) return // return but not resolve - } else if (global.$VS.userTokenInvalidateLock < 0) { - console.error('Aborting the network task', task.url, global.$VS.userTokenInvalidateLock) + } else if (rootStore.state.userTokenInvalidateLock < 0) { + console.error('Aborting the network task', task.url, rootStore.state.userTokenInvalidateLock) resolve({ code: 401, message: i18n.t('Error refreshing user token. User is not authorized to access the resource') }) return } else { - if (global.$VS.userTokenInvalidated) { - console.log('Using new user token', global.$VS.userTokenInvalidated) - currentToken = global.$VS.userTokenInvalidated + if (rootStore.state.userTokenInvalidated) { + console.log('Using new user token', rootStore.state.userTokenInvalidated) + currentToken = rootStore.state.userTokenInvalidated } } let url = task.url.replace('{{token}}', (currentToken == null) ? '' : currentToken).replace('{{cartId}}', (currentCartId == null) ? '' : currentCartId) - if (config.storeViews.multistore) { + if (rootStore.state.config.storeViews.multistore) { url = adjustMultistoreApiUrl(url) } let silentMode = false @@ -50,17 +50,17 @@ function _internalExecute (resolve, reject, task, currentToken, currentCartId) { if (parseInt(jsonResponse.code) !== 200) { let resultString = jsonResponse.result ? toString(jsonResponse.result) : null if (resultString && (resultString.indexOf(i18n.t('not authorized')) >= 0 || resultString.indexOf('not authorized')) >= 0 && currentToken !== null) { // the token is no longer valid, try to invalidate it - console.error('Invalid token - need to be revalidated', currentToken, task.url, global.$VS.userTokenInvalidateLock) - if (isNaN(global.$VS.userTokenInvalidateAttemptsCount) || isUndefined(global.$VS.userTokenInvalidateAttemptsCount)) global.$VS.userTokenInvalidateAttemptsCount = 0 - if (isNaN(global.$VS.userTokenInvalidateLock) || isUndefined(global.$VS.userTokenInvalidateLock)) global.$VS.userTokenInvalidateLock = 0 + console.error('Invalid token - need to be revalidated', currentToken, task.url, rootStore.state.userTokenInvalidateLock) + if (isNaN(rootStore.state.userTokenInvalidateAttemptsCount) || isUndefined(rootStore.state.userTokenInvalidateAttemptsCount)) rootStore.state.userTokenInvalidateAttemptsCount = 0 + if (isNaN(rootStore.state.userTokenInvalidateLock) || isUndefined(rootStore.state.userTokenInvalidateLock)) rootStore.state.userTokenInvalidateLock = 0 silentMode = true - if (config.users.autoRefreshTokens) { - if (!global.$VS.userTokenInvalidateLock) { - global.$VS.userTokenInvalidateLock++ - if (global.$VS.userTokenInvalidateAttemptsCount >= AUTO_REFRESH_MAX_ATTEMPTS) { + if (rootStore.state.config.users.autoRefreshTokens) { + if (!rootStore.state.userTokenInvalidateLock) { + rootStore.state.userTokenInvalidateLock++ + if (rootStore.state.userTokenInvalidateAttemptsCount >= AUTO_REFRESH_MAX_ATTEMPTS) { console.error('Internal Application error while refreshing the tokens. Please clear the storage and refresh page.') - global.$VS.userTokenInvalidateLock = -1 + rootStore.state.userTokenInvalidateLock = -1 rootStore.dispatch('user/logout', { silent: true }) rootStore.dispatch('sync/clearNotTransmited') EventBus.$emit('modal-show', 'modal-signup') @@ -69,24 +69,24 @@ function _internalExecute (resolve, reject, task, currentToken, currentCartId) { message: i18n.t('Internal Application error while refreshing the tokens. Please clear the storage and refresh page.'), action1: { label: i18n.t('OK'), action: 'close' } }) - global.$VS.userTokenInvalidateAttemptsCount = 0 + rootStore.state.userTokenInvalidateAttemptsCount = 0 } else { - console.info('Invalidation process in progress (autoRefreshTokens is set to true)', global.$VS.userTokenInvalidateAttemptsCount, global.$VS.userTokenInvalidateLock) - global.$VS.userTokenInvalidateAttemptsCount++ + console.info('Invalidation process in progress (autoRefreshTokens is set to true)', rootStore.state.userTokenInvalidateAttemptsCount, rootStore.state.userTokenInvalidateLock) + rootStore.state.userTokenInvalidateAttemptsCount++ rootStore.dispatch('user/refresh').then((resp) => { if (resp.code === 200) { - global.$VS.userTokenInvalidateLock = 0 - global.$VS.userTokenInvalidated = resp.result + rootStore.state.userTokenInvalidateLock = 0 + rootStore.state.userTokenInvalidated = resp.result console.info('User token refreshed successfully', resp.result) } else { - global.$VS.userTokenInvalidateLock = -1 + rootStore.state.userTokenInvalidateLock = -1 rootStore.dispatch('user/logout', { silent: true }) EventBus.$emit('modal-show', 'modal-signup') rootStore.dispatch('sync/clearNotTransmited') console.error('Error refreshing user token', resp.result) } }).catch((excp) => { - global.$VS.userTokenInvalidateLock = -1 + rootStore.state.userTokenInvalidateLock = -1 rootStore.dispatch('user/logout', { silent: true }) EventBus.$emit('modal-show', 'modal-signup') rootStore.dispatch('sync/clearNotTransmited') @@ -94,7 +94,7 @@ function _internalExecute (resolve, reject, task, currentToken, currentCartId) { }) } } - if (global.$VS.userTokenInvalidateAttemptsCount <= AUTO_REFRESH_MAX_ATTEMPTS) _internalExecute(resolve, reject, task, currentToken, currentCartId) // retry + if (rootStore.state.userTokenInvalidateAttemptsCount <= AUTO_REFRESH_MAX_ATTEMPTS) _internalExecute(resolve, reject, task, currentToken, currentCartId) // retry } else { console.info('Invalidation process is disabled (autoRefreshTokens is set to false)') rootStore.dispatch('user/logout', { silent: true }) @@ -120,7 +120,7 @@ function _internalExecute (resolve, reject, task, currentToken, currentCartId) { if (task.callback_event) { EventBus.$emit(task.callback_event, task) } - if (!global.$VS.userTokenInvalidateLock) { // in case we're revalidaing the token - user must wait for it + if (!rootStore.state.userTokenInvalidateLock) { // in case we're revalidaing the token - user must wait for it resolve(task) } } else { diff --git a/core/store/modules/attribute/actions.ts b/core/store/modules/attribute/actions.ts index ede53a2a1f..904398e0c0 100644 --- a/core/store/modules/attribute/actions.ts +++ b/core/store/modules/attribute/actions.ts @@ -1,10 +1,10 @@ import * as types from '../../mutation-types' import { quickSearchByQuery } from '../../lib/search' -import config from '../../lib/config' +import rootStore from '../../' import AttributeState from './types/AttributeState' import RootState from '../../types/RootState' import { ActionTree } from 'vuex' -const bodybuilder = require('bodybuilder') +import bodybuilder from 'bodybuilder' const actions: ActionTree = { /** @@ -12,7 +12,7 @@ const actions: ActionTree = { * @param {Object} context * @param {Array} attrCodes attribute codes to load */ - list (context, { filterValues = null, filterField = 'attribute_code', size = 150, start = 0, includeFields = config.entities.optimize ? config.entities.attribute.includeFields : null }) { + list (context, { filterValues = null, filterField = 'attribute_code', size = 150, start = 0, includeFields = rootStore.state.config.entities.optimize ? rootStore.state.config.entities.attribute.includeFields : null }) { const commit = context.commit let qrObj = bodybuilder() diff --git a/core/store/modules/cart/actions.ts b/core/store/modules/cart/actions.ts index 2ea8dba896..1159a3c354 100644 --- a/core/store/modules/cart/actions.ts +++ b/core/store/modules/cart/actions.ts @@ -1,6 +1,5 @@ import Vue from 'vue' import { ActionTree } from 'vuex' -import config from '../../lib/config' import * as types from '../../mutation-types' import rootStore from '../../' import EventBus from '../../lib/event-bus' @@ -25,7 +24,7 @@ const actions: ActionTree = { clear (context) { context.commit(types.CART_LOAD_CART, []) context.commit(types.CART_LOAD_CART_SERVER_TOKEN, null) - if (config.cart.synchronize) { + if (rootStore.state.config.cart.synchronize) { rootStore.dispatch('cart/serverCreate', { guestCart: true }, {root: true}) // guest cart because when the order hasn't been passed to magento yet it will repopulate your cart } }, @@ -33,12 +32,12 @@ const actions: ActionTree = { context.commit(types.CART_SAVE) }, serverPull (context, { forceClientState = false, dryRun = false }) { // pull current cart FROM the server - if (config.cart.synchronize && !Vue.prototype.$isServer) { + if (rootStore.state.config.cart.synchronize && !Vue.prototype.$isServer) { const newItemsHash = sha1({ items: context.state.cartItems, token: context.state.cartServerToken }) if ((Date.now() - context.state.cartServerPullAt) >= CART_PULL_INTERVAL_MS || (newItemsHash !== context.state.cartItemsHash)) { context.state.cartServerPullAt = Date.now() context.state.cartItemsHash = newItemsHash - context.dispatch('sync/execute', { url: config.cart.pull_endpoint, // sync the cart + context.dispatch('sync/execute', { url: rootStore.state.config.cart.pull_endpoint, // sync the cart payload: { method: 'GET', headers: { 'Content-Type': 'application/json' }, @@ -68,10 +67,10 @@ const actions: ActionTree = { } }, serverTotals (context, { forceClientState = false }) { // pull current cart FROM the server - if (config.cart.synchronize_totals && !Vue.prototype.$isServer) { + if (rootStore.state.config.cart.synchronize_totals && !Vue.prototype.$isServer) { if ((Date.now() - context.state.cartServerTotalsAt) >= CART_TOTALS_INTERVAL_MS) { context.state.cartServerPullAt = Date.now() - context.dispatch('sync/execute', { url: config.cart.totals_endpoint, // sync the cart + context.dispatch('sync/execute', { url: rootStore.state.config.cart.totals_endpoint, // sync the cart payload: { method: 'GET', headers: { 'Content-Type': 'application/json' }, @@ -89,12 +88,12 @@ const actions: ActionTree = { } }, serverCreate (context, { guestCart = false }) { - if (config.cart.synchronize && !Vue.prototype.$isServer) { + if (rootStore.state.config.cart.synchronize && !Vue.prototype.$isServer) { if ((Date.now() - context.state.cartServerCreatedAt) >= CART_CREATE_INTERVAL_MS) { if (guestCart) { global.$VS.db.usersCollection.setItem('last-cart-bypass-ts', new Date().getTime()) } - const task = { url: guestCart ? config.cart.create_endpoint.replace('{{token}}', '') : config.cart.create_endpoint, // sync the cart + const task = { url: guestCart ? rootStore.state.config.cart.create_endpoint.replace('{{token}}', '') : rootStore.state.config.cart.create_endpoint, // sync the cart payload: { method: 'POST', headers: { 'Content-Type': 'application/json' }, @@ -112,7 +111,7 @@ const actions: ActionTree = { if (!cartItem.quoteId) { cartItem = Object.assign(cartItem, { quoteId: context.state.cartServerToken }) } - return context.dispatch('sync/execute', { url: config.cart.updateitem_endpoint, // sync the cart + return context.dispatch('sync/execute', { url: rootStore.state.config.cart.updateitem_endpoint, // sync the cart payload: { method: 'POST', headers: { 'Content-Type': 'application/json' }, @@ -124,7 +123,7 @@ const actions: ActionTree = { callback_event: 'servercart-after-itemupdated' }, { root: true }).then(task => { // eslint-disable-next-line no-useless-return - if (config.cart.synchronize_totals && context.state.cartItems.length > 0) { + if (rootStore.state.config.cart.synchronize_totals && context.state.cartItems.length > 0) { context.dispatch('refreshTotals') } return task @@ -135,7 +134,7 @@ const actions: ActionTree = { cartItem = Object.assign(cartItem, { quoteId: context.state.cartServerToken }) } cartItem = Object.assign(cartItem, { quoteId: context.state.cartServerToken }) - return context.dispatch('sync/execute', { url: config.cart.deleteitem_endpoint, // sync the cart + return context.dispatch('sync/execute', { url: rootStore.state.config.cart.deleteitem_endpoint, // sync the cart payload: { method: 'POST', headers: { 'Content-Type': 'application/json' }, @@ -148,7 +147,7 @@ const actions: ActionTree = { callback_event: 'servercart-after-itemdeleted' }, { root: true }).then(task => { // eslint-disable-next-line no-useless-return - if (config.cart.synchronize_totals && context.state.cartItems.length > 0) { + if (rootStore.state.config.cart.synchronize_totals && context.state.cartItems.length > 0) { context.dispatch('refreshTotals') } return task @@ -172,14 +171,14 @@ const actions: ActionTree = { global.$VS.db.cartsCollection.getItem('current-cart', (err, storedItems) => { if (err) throw new Error(err) - if (config.cart.synchronize) { + if (rootStore.state.config.cart.synchronize) { global.$VS.db.cartsCollection.getItem('current-cart-token', (err, token) => { if (err) throw new Error(err) // TODO: if token is null create cart server side and store the token! if (token) { // previously set token commit(types.CART_LOAD_CART_SERVER_TOKEN, token) console.log('Existing cart token = ' + token) - context.dispatch('serverPull', { forceClientState: false, dryRun: !config.cart.server_merge_by_default }) + context.dispatch('serverPull', { forceClientState: false, dryRun: !rootStore.state.config.cart.server_merge_by_default }) } else { console.log('Creating server cart ...') context.dispatch('serverCreate', { guestCart: false }) @@ -215,7 +214,7 @@ const actions: ActionTree = { }) continue } - if (config.entities.optimize && config.entities.optimizeShoppingCart) { + if (rootStore.state.config.entities.optimize && rootStore.state.config.entities.optimizeShoppingCart) { product = omit(product, ['configurable_children', 'configurable_options', 'media_gallery', 'description', 'category', 'category_ids', 'product_links', 'stock', 'description']) } if (product.errors !== null && typeof product.errors !== 'undefined') { @@ -262,11 +261,11 @@ const actions: ActionTree = { action1: { label: i18n.t('OK'), action: 'close' }, action2: null } - if (!config.externalCheckout) { // if there is externalCheckout enabled we don't offer action to go to checkout as it can generate cart desync + if (!rootStore.state.config.externalCheckout) { // if there is externalCheckout enabled we don't offer action to go to checkout as it can generate cart desync notificationData.action2 = { label: i18n.t('Proceed to checkout'), action: 'goToCheckout' } } EventBus.$emit('notification', notificationData) - if (config.cart.synchronize && !forceServerSilence) { + if (rootStore.state.config.cart.synchronize && !forceServerSilence) { dispatch('serverPull', { forceClientState: true }) } } @@ -276,7 +275,7 @@ const actions: ActionTree = { }, removeItem ({ commit, dispatch }, product) { commit(types.CART_DEL_ITEM, { product }) - if (config.cart.synchronize && product.server_item_id) { + if (rootStore.state.config.cart.synchronize && product.server_item_id) { /* dispatch('serverDeleteItem', { sku: product.sku, item_id: product.server_item_id @@ -286,7 +285,7 @@ const actions: ActionTree = { }, updateQuantity ({ commit, dispatch }, { product, qty, forceServerSilence = false }) { commit(types.CART_UPD_ITEM, { product, qty }) - if (config.cart.synchronize && product.server_item_id && !forceServerSilence) { + if (rootStore.state.config.cart.synchronize && product.server_item_id && !forceServerSilence) { /* dispatch('serverUpdateItem', { sku: product.sku, item_id: product.server_item_id, @@ -299,8 +298,8 @@ const actions: ActionTree = { commit(types.CART_UPD_ITEM_PROPS, { product }) }, getPaymentMethods (context) { - if (config.cart.synchronize_totals && (typeof navigator !== 'undefined' ? navigator.onLine : true)) { - context.dispatch('sync/execute', { url: config.cart.paymentmethods_endpoint, + if (rootStore.state.config.cart.synchronize_totals && (typeof navigator !== 'undefined' ? navigator.onLine : true)) { + context.dispatch('sync/execute', { url: rootStore.state.config.cart.paymentmethods_endpoint, payload: { method: 'GET', headers: { 'Content-Type': 'application/json' }, @@ -328,8 +327,8 @@ const actions: ActionTree = { } }, getShippingMethods (context, address) { - if (config.cart.synchronize_totals && (typeof navigator !== 'undefined' ? navigator.onLine : true)) { - context.dispatch('sync/execute', { url: config.cart.shippingmethods_endpoint, + if (rootStore.state.config.cart.synchronize_totals && (typeof navigator !== 'undefined' ? navigator.onLine : true)) { + context.dispatch('sync/execute', { url: rootStore.state.config.cart.shippingmethods_endpoint, payload: { method: 'POST', headers: { 'Content-Type': 'application/json' }, @@ -350,7 +349,7 @@ const actions: ActionTree = { }, refreshTotals (context, methodsData) { const storeView = currentStoreView() - if (config.cart.synchronize_totals && (typeof navigator !== 'undefined' ? navigator.onLine : true)) { + if (rootStore.state.config.cart.synchronize_totals && (typeof navigator !== 'undefined' ? navigator.onLine : true)) { if (!methodsData) { let country = rootStore.state.checkout.shippingDetails.country ? rootStore.state.checkout.shippingDetails.country : storeView.tax.defaultCountry const shippingMethods = context.rootGetters['shipping/shippingMethods'] @@ -371,7 +370,7 @@ const actions: ActionTree = { } } if (methodsData.country && methodsData.carrier_code) { - context.dispatch('sync/execute', { url: config.cart.shippinginfo_endpoint, + context.dispatch('sync/execute', { url: rootStore.state.config.cart.shippinginfo_endpoint, payload: { method: 'POST', headers: { 'Content-Type': 'application/json' }, @@ -397,8 +396,8 @@ const actions: ActionTree = { } }, removeCoupon (context) { - if (config.cart.synchronize_totals && (typeof navigator !== 'undefined' ? navigator.onLine : true)) { - context.dispatch('sync/execute', { url: config.cart.deletecoupon_endpoint, + if (rootStore.state.config.cart.synchronize_totals && (typeof navigator !== 'undefined' ? navigator.onLine : true)) { + context.dispatch('sync/execute', { url: rootStore.state.config.cart.deletecoupon_endpoint, payload: { method: 'POST', headers: { 'Content-Type': 'application/json' }, @@ -415,8 +414,8 @@ const actions: ActionTree = { } }, applyCoupon (context, couponCode) { - if (config.cart.synchronize_totals && (typeof navigator !== 'undefined' ? navigator.onLine : true)) { - context.dispatch('sync/execute', { url: config.cart.applycoupon_endpoint.replace('{{coupon}}', couponCode), + if (rootStore.state.config.cart.synchronize_totals && (typeof navigator !== 'undefined' ? navigator.onLine : true)) { + context.dispatch('sync/execute', { url: rootStore.state.config.cart.applycoupon_endpoint.replace('{{coupon}}', couponCode), payload: { method: 'POST', headers: { 'Content-Type': 'application/json' }, diff --git a/core/store/modules/cart/index.ts b/core/store/modules/cart/index.ts index e6fca26da8..de7ebb2c5f 100644 --- a/core/store/modules/cart/index.ts +++ b/core/store/modules/cart/index.ts @@ -8,7 +8,6 @@ import * as types from '../../mutation-types' import i18n from '../../lib/i18n' import isString from 'lodash-es/isString' import toString from 'lodash-es/toString' -import config from '../../lib/config' import RootState from '../../types/RootState' import CartState from './types/CartState' @@ -21,7 +20,7 @@ EventBus.$on('servercart-after-created', (event) => { // example stock check cal if (event.resultCode === 200) { console.log(`Server cart token after created = ${cartToken}`) rootStore.commit(types.SN_CART + '/' + types.CART_LOAD_CART_SERVER_TOKEN, cartToken) - rootStore.dispatch('cart/serverPull', { forceClientState: false, dryRun: !config.cart.server_merge_by_default }, { root: true }) + rootStore.dispatch('cart/serverPull', { forceClientState: false, dryRun: !rootStore.state.config.cart.server_merge_by_default }, { root: true }) } else { let resultString = event.result ? toString(event.result) : null if (resultString && (resultString.indexOf(i18n.t('not authorized')) < 0 && resultString.indexOf('not authorized')) < 0) { // not respond to unathorized errors here @@ -108,7 +107,7 @@ EventBus.$on('servercart-after-pulled', (event) => { // example stock check call diffLog.push({ 'party': 'server', 'sku': clientItem.sku, 'status': 'no_item' }) if (!event.dry_run) { rootStore.dispatch('cart/serverUpdateItem', { - sku: clientItem.parentSku && config.cart.setConfigurableProductOptions ? clientItem.parentSku : clientItem.sku, + sku: clientItem.parentSku && rootStore.state.config.cart.setConfigurableProductOptions ? clientItem.parentSku : clientItem.sku, qty: clientItem.qty, product_option: clientItem.product_option }, { root: true }).then((event) => { @@ -121,7 +120,7 @@ EventBus.$on('servercart-after-pulled', (event) => { // example stock check call diffLog.push({ 'party': 'server', 'sku': clientItem.sku, 'status': 'wrong_qty', 'client_qty': clientItem.qty, 'server_qty': serverItem.qty }) if (!event.dry_run) { rootStore.dispatch('cart/serverUpdateItem', { - sku: clientItem.parentSku && config.cart.setConfigurableProductOptions ? clientItem.parentSku : clientItem.sku, + sku: clientItem.parentSku && rootStore.state.config.cart.setConfigurableProductOptions ? clientItem.parentSku : clientItem.sku, qty: clientItem.qty, item_id: serverItem.item_id, quoteId: serverItem.quote_id, diff --git a/core/store/modules/cart/mutations.ts b/core/store/modules/cart/mutations.ts index 0442d374b8..b5cde74df1 100644 --- a/core/store/modules/cart/mutations.ts +++ b/core/store/modules/cart/mutations.ts @@ -1,7 +1,7 @@ import { MutationTree } from 'vuex' +import rootStore from '../../' import * as types from '../../mutation-types' import EventBus from '../../lib/event-bus' -import config from '../../lib/config' import CartState from './types/CartState' const mutations: MutationTree = { @@ -60,8 +60,8 @@ const mutations: MutationTree = { state.cartIsLoaded = true state.cartSavedAt = Date.now() - EventBus.$emit('order/PROCESS_QUEUE', { config: config }) // process checkout queue - EventBus.$emit('sync/PROCESS_QUEUE', { config: config }) // process checkout queue + EventBus.$emit('order/PROCESS_QUEUE', { config: rootStore.state.config }) // process checkout queue + EventBus.$emit('sync/PROCESS_QUEUE', { config: rootStore.state.config }) // process checkout queue EventBus.$emit('application-after-loaded') EventBus.$emit('cart-after-loaded') }, diff --git a/core/store/modules/category/actions.ts b/core/store/modules/category/actions.ts index 8831a9178b..58b80e5799 100644 --- a/core/store/modules/category/actions.ts +++ b/core/store/modules/category/actions.ts @@ -4,7 +4,6 @@ import * as types from '../../mutation-types' import { quickSearchByQuery } from '../../lib/search' import { entityKeyName } from '../../lib/entities' import EventBus from '../../lib/event-bus' -import config from '../../lib/config' import rootStore from '../../' import i18n from '../../lib/i18n' import chunk from 'lodash-es/chunk' @@ -13,7 +12,7 @@ import toString from 'lodash-es/toString' import { optionLabel } from '../attribute/helpers' import RootState from '../../types/RootState' import CategoryState from './types/CategoryState' -const bodybuilder = require('bodybuilder') +import bodybuilder from 'bodybuilder' declare var global: any @@ -33,7 +32,7 @@ const actions: ActionTree = { * @param {Object} commit promise * @param {Object} parent parent category */ - list (context, { parent = null, onlyActive = true, onlyNotEmpty = false, size = 4000, start = 0, sort = 'position:asc', includeFields = config.entities.optimize ? config.entities.category.includeFields : null, skipCache = false }) { + list (context, { parent = null, onlyActive = true, onlyNotEmpty = false, size = 4000, start = 0, sort = 'position:asc', includeFields = rootStore.state.config.entities.optimize ? rootStore.state.config.entities.category.includeFields : null, skipCache = false }) { const commit = context.commit let qrObj = bodybuilder() if (parent && typeof parent !== 'undefined') { @@ -159,14 +158,14 @@ const actions: ActionTree = { } let prefetchGroupProducts = true - if (config.entities.twoStageCaching && config.entities.optimize && !Vue.prototype.$isServer && !global.$VS.twoStageCachingDisabled) { // only client side, only when two stage caching enabled - includeFields = config.entities.productListWithChildren.includeFields // we need configurable_children for filters to work - excludeFields = config.entities.productListWithChildren.excludeFields + if (rootStore.state.config.entities.twoStageCaching && rootStore.state.config.entities.optimize && !Vue.prototype.$isServer && !rootStore.state.twoStageCachingDisabled) { // only client side, only when two stage caching enabled + includeFields = rootStore.state.config.entities.productListWithChildren.includeFields // we need configurable_children for filters to work + excludeFields = rootStore.state.config.entities.productListWithChildren.excludeFields prefetchGroupProducts = false console.log('Using two stage caching for performance optimization - executing first stage product pre-fetching') } else { prefetchGroupProducts = true - if (global.$VS.twoStageCachingDisabled) { + if (rootStore.state.twoStageCachingDisabled) { console.log('Two stage caching is disabled runtime because of no performance gain') } else { console.log('Two stage caching is disabled by the config') @@ -187,7 +186,7 @@ const actions: ActionTree = { prefetchGroupProducts: prefetchGroupProducts }).then((res) => { let t1 = new Date().getTime() - global.$VS.twoStageCachingDelta1 = t1 - t0 + rootStore.state.twoStageCachingDelta1 = t1 - t0 let subloaders = [] if (!res || (res.noresults)) { @@ -200,12 +199,12 @@ const actions: ActionTree = { rootStore.state.product.list = { items: [] } // no products to show TODO: refactor to rootStore.state.category.reset() and rootStore.state.product.reset() // rootStore.state.category.filters = { color: [], size: [], price: [] } } else { - if (config.products.filterUnavailableVariants && config.products.configurableChildrenStockPrefetchStatic) { // prefetch the stock items + if (rootStore.state.config.products.filterUnavailableVariants && rootStore.state.config.products.configurableChildrenStockPrefetchStatic) { // prefetch the stock items const skus = [] let prefetchIndex = 0 res.items.map(i => { - if (config.products.configurableChildrenStockPrefetchStaticPrefetchCount > 0) { - if (prefetchIndex > config.products.configurableChildrenStockPrefetchStaticPrefetchCount) return + if (rootStore.state.config.products.configurableChildrenStockPrefetchStaticPrefetchCount > 0) { + if (prefetchIndex > rootStore.state.config.products.configurableChildrenStockPrefetchStaticPrefetchCount) return } skus.push(i.sku) // main product sku to be checked anyway if (i.type_id === 'configurable' && i.configurable_children && i.configurable_children.length > 0) { @@ -276,7 +275,7 @@ const actions: ActionTree = { }) }) - if (config.entities.twoStageCaching && config.entities.optimize && !Vue.prototype.$isServer && !global.$VS.twoStageCachingDisabled) { // second stage - request for caching entities + if (rootStore.state.config.entities.twoStageCaching && rootStore.state.config.entities.optimize && !Vue.prototype.$isServer && !rootStore.state.twoStageCachingDisabled) { // second stage - request for caching entities console.log('Using two stage caching for performance optimization - executing second stage product caching') // TODO: in this case we can pre-fetch products in advance getting more products than set by pageSize rootStore.dispatch('product/list', { query: precachedQuery, @@ -290,10 +289,10 @@ const actions: ActionTree = { console.info(err) }).then((res) => { let t2 = new Date().getTime() - global.$VS.twoStageCachingDelta2 = t2 - t0 - console.log('Using two stage caching for performance optimization - Time comparison stage1 vs stage2', global.$VS.twoStageCachingDelta1, global.$VS.twoStageCachingDelta2) - if (global.$VS.twoStageCachingDelta1 > global.$VS.twoStageCachingDelta2) { // two stage caching is not making any good - global.$VS.twoStageCachingDisabled = true + rootStore.state.twoStageCachingDelta2 = t2 - t0 + console.log('Using two stage caching for performance optimization - Time comparison stage1 vs stage2', rootStore.state.twoStageCachingDelta1, rootStore.state.twoStageCachingDelta2) + if (rootStore.state.twoStageCachingDelta1 > rootStore.state.twoStageCachingDelta2) { // two stage caching is not making any good + rootStore.state.twoStageCachingDisabled = true console.log('Disabling two stage caching') } }) diff --git a/core/store/modules/category/mutations.ts b/core/store/modules/category/mutations.ts index 509952fb55..b5629e25cc 100644 --- a/core/store/modules/category/mutations.ts +++ b/core/store/modules/category/mutations.ts @@ -3,8 +3,8 @@ import * as types from '../../mutation-types' import { slugify, breadCrumbRoutes } from '../../helpers' import { entityKeyName } from '../../lib/entities' import EventBus from '../../lib/event-bus' -import config from 'config' import CategoryState from './types/CategoryState' +import rootStore from '../../' declare var global: any @@ -24,7 +24,7 @@ const mutations: MutationTree = { for (let category of state.list) { let catSlugSetter = (category) => { for (let subcat of category.children_data) { // TODO: fixme and move slug setting to vue-storefront-api - subcat = Object.assign(subcat, { slug: (subcat.hasOwnProperty('url_key') && config.products.useMagentoUrlKeys) ? subcat.url_key : (subcat.hasOwnProperty('name') ? slugify(subcat.name) + '-' + subcat.id : '') }) + subcat = Object.assign(subcat, { slug: (subcat.hasOwnProperty('url_key') && rootStore.state.config.products.useMagentoUrlKeys) ? subcat.url_key : (subcat.hasOwnProperty('name') ? slugify(subcat.name) + '-' + subcat.id : '') }) catSlugSetter(subcat) } } diff --git a/core/store/modules/order/mutations.ts b/core/store/modules/order/mutations.ts index cd204c5840..0c642ab8e8 100644 --- a/core/store/modules/order/mutations.ts +++ b/core/store/modules/order/mutations.ts @@ -2,8 +2,8 @@ import { MutationTree } from 'vuex' import * as types from '../../mutation-types' import * as entities from '../../lib/entities' import EventBus from '../../lib/event-bus' -import config from '../../lib/config' import OrderState from './types/OrderState' +import rootStore from '../../' declare var global: any @@ -24,7 +24,7 @@ const mutations: MutationTree = { console.error(reason) // it doesn't work on SSR }, (err, resp) => { if (err) console.error(err) - EventBus.$emit('order/PROCESS_QUEUE', { config: config }) // process checkout queue + EventBus.$emit('order/PROCESS_QUEUE', { config: rootStore.state.config }) // process checkout queue console.info('Order placed, orderId = ' + orderId) }) // populate cache } diff --git a/core/store/modules/product/actions.ts b/core/store/modules/product/actions.ts index ef4e908f04..632b50a90f 100644 --- a/core/store/modules/product/actions.ts +++ b/core/store/modules/product/actions.ts @@ -1,8 +1,7 @@ import Vue from 'vue' import { ActionTree } from 'vuex' -import config from '../../lib/config' import * as types from '../../mutation-types' -import { breadCrumbRoutes, productThumbnailPath, getThumbnailPath } from '../../helpers' +import { breadCrumbRoutes, productThumbnailPath } from '../../helpers' import { currentStoreView } from '../../lib/multistore' import { configureProductAsync, doPlatformPricesSync, filterOutUnavailableVariants, calculateTaxes, populateProductConfigurationAsync, setCustomProductOptionsAsync, setBundleProductOptionsAsync, getMediaGallery, configurableChildrenImages, attributeImages } from './helpers' import { entityKeyName } from '../../lib/entities' @@ -15,7 +14,7 @@ import uniqBy from 'lodash-es/uniqBy' import rootStore from '../../' import RootState from '../../types/RootState' import ProductState from './types/ProductState' -const bodybuilder = require('bodybuilder') +import bodybuilder from 'bodybuilder' declare var global: any @@ -85,7 +84,7 @@ const actions: ActionTree = { */ syncPlatformPricesOver (context, { skus }) { const storeView = currentStoreView() - return context.dispatch('sync/execute', { url: config.products.endpoint + '/render-list?skus=' + encodeURIComponent(skus.join(',')) + '¤cyCode=' + encodeURIComponent(storeView.i18n.currencyCode) + '&storeId=' + encodeURIComponent(storeView.storeId), // sync the cart + return context.dispatch('sync/execute', { url: rootStore.state.config.products.endpoint + '/render-list?skus=' + encodeURIComponent(skus.join(',')) + '¤cyCode=' + encodeURIComponent(storeView.i18n.currencyCode) + '&storeId=' + encodeURIComponent(storeView.storeId), // sync the cart payload: { method: 'GET', headers: { 'Content-Type': 'application/json' }, @@ -245,12 +244,12 @@ const actions: ActionTree = { console.debug('Entity cache is disabled for productList') } - if (config.entities.optimize) { + if (rootStore.state.config.entities.optimize) { if (excludeFields === null) { // if not set explicitly we do optimize the amount of data by using some default field list; this is cacheable - excludeFields = config.entities.product.excludeFields + excludeFields = rootStore.state.config.entities.product.excludeFields } if (includeFields === null) { // if not set explicitly we do optimize the amount of data by using some default field list; this is cacheable - includeFields = config.entities.product.includeFields + includeFields = rootStore.state.config.entities.product.includeFields } } return quickSearchByQuery({ query, start, size, entityType, sort, excludeFields, includeFields }).then((resp) => { @@ -261,7 +260,7 @@ const actions: ActionTree = { if (!product.parentSku) { product.parentSku = product.sku } - if (config.products.setFirstVarianAsDefaultInURL && product.hasOwnProperty('configurable_children') && product.configurable_children.length > 0) { + if (rootStore.state.config.products.setFirstVarianAsDefaultInURL && product.hasOwnProperty('configurable_children') && product.configurable_children.length > 0) { product.sku = product.configurable_children[0].sku } if (configuration) { @@ -428,12 +427,12 @@ const actions: ActionTree = { console.debug('Product:single - result from localForage (for ' + cacheKey + '), ms=' + (new Date().getTime() - benchmarkTime.getTime())) const _returnProductFromCacheHelper = (subresults) => { const cachedProduct = setupProduct(res) - if (config.products.alwaysSyncPlatformPricesOver) { + if (rootStore.state.config.products.alwaysSyncPlatformPricesOver) { doPlatformPricesSync([cachedProduct]).then((products) => { if (EventBus.$emitFilter) EventBus.$emitFilter('product-after-single', { key: key, options: options, product: products[0] }) resolve(products[0]) }) - if (!config.products.waitForPlatformSync) { + if (!rootStore.state.config.products.waitForPlatformSync) { if (EventBus.$emitFilter) EventBus.$emitFilter('product-after-single', { key: key, options: options, product: cachedProduct }) resolve(cachedProduct) } @@ -523,7 +522,7 @@ const actions: ActionTree = { // check if passed variant is the same as original const productUpdated = Object.assign({}, productOriginal, productVariant) populateProductConfigurationAsync(context, { product: productUpdated, selectedVariant: productVariant }) - if (!config.products.gallery.mergeConfigurableChildren) { + if (!rootStore.state.config.products.gallery.mergeConfigurableChildren) { context.commit(types.CATALOG_UPD_GALLERY, attributeImages(productVariant)) } context.commit(types.CATALOG_SET_PRODUCT_CURRENT, productUpdated) @@ -579,7 +578,7 @@ const actions: ActionTree = { context.dispatch('setProductGallery', { product: product }) - if (config.products.preventConfigurableChildrenDirectAccess) { + if (rootStore.state.config.products.preventConfigurableChildrenDirectAccess) { subloaders.push(context.dispatch('checkConfigurableParent', { product: product })) } } else { // error or redirect @@ -601,10 +600,10 @@ const actions: ActionTree = { setProductGallery(context, { product }) { if (product.type_id === 'configurable') { - if (!config.products.gallery.mergeConfigurableChildren && product.is_configured) { + if (!rootStore.state.config.products.gallery.mergeConfigurableChildren && product.is_configured) { context.commit(types.CATALOG_UPD_GALLERY, attributeImages(context.state.current)) } else { - let productGallery = uniqBy(configurableChildrenImages(product).concat(getMediaGallery(product)), 'src').filter(f => { return f.src && f.src !== config.images.productPlaceholder }) + let productGallery = uniqBy(configurableChildrenImages(product).concat(getMediaGallery(product)), 'src').filter(f => { return f.src && f.src !== rootStore.state.config.images.productPlaceholder }) context.commit(types.CATALOG_UPD_GALLERY, productGallery) } } else { @@ -627,7 +626,7 @@ const actions: ActionTree = { rootStore.dispatch('attribute/list', { // load attributes to be shown on the product details filterValues: [true], filterField: 'is_user_defined', - includeFields: config.entities.optimize ? config.entities.attribute.includeFields : null + includeFields: rootStore.state.config.entities.optimize ? rootStore.state.config.entities.attribute.includeFields : null }).then((attrs) => { context.dispatch('fetch', { parentSku: parentSku, childSku: childSku }).then((subpromises) => { Promise.all(subpromises).then(subresults => { diff --git a/core/store/modules/product/helpers.ts b/core/store/modules/product/helpers.ts index 919a8fd09b..2f3a37952f 100644 --- a/core/store/modules/product/helpers.ts +++ b/core/store/modules/product/helpers.ts @@ -1,5 +1,4 @@ import Vue from 'vue' -import config from '../../lib/config' import rootStore from '../../' import EventBus from '../../lib/event-bus' import { calculateProductTax } from '../../lib/taxcalc' @@ -14,7 +13,6 @@ import i18n from '../../lib/i18n' import { currentStoreView } from '../../lib/multistore' import { getThumbnailPath } from '../../helpers' - function _filterRootProductByStockitem (context, stockItem, product, errorCallback) { if (stockItem) { product.stock = stockItem @@ -22,7 +20,7 @@ function _filterRootProductByStockitem (context, stockItem, product, errorCallba product.errors.variants = i18n.t('No available product variants') context.state.current.errors = product.errors EventBus.$emit('product-after-removevariant', { product: product }) - if (config.products.listOutOfStockProducts === false) { + if (rootStore.state.config.products.listOutOfStockProducts === false) { errorCallback(new Error('Product query returned empty result')) } } @@ -30,7 +28,7 @@ function _filterRootProductByStockitem (context, stockItem, product, errorCallba } function _filterChildrenByStockitem (context, stockItems, product, diffLog) { - if (config.products.filterUnavailableVariants) { + if (rootStore.state.config.products.filterUnavailableVariants) { if (product.type_id === 'configurable' && product.configurable_children) { for (const stockItem of stockItems) { if (stockItem.is_in_stock === false) { @@ -78,7 +76,7 @@ function _filterChildrenByStockitem (context, stockItems, product, diffLog) { export function filterOutUnavailableVariants (context, product) { return new Promise((resolve, reject) => { - if (config.products.filterUnavailableVariants) { + if (rootStore.state.config.products.filterUnavailableVariants) { const _filterConfigurableHelper = () => { if (product.type_id === 'configurable' && product.configurable_children) { const stockItems = [] @@ -162,8 +160,8 @@ export function syncProductPrice (product, backProduct) { // TODO: we probably n */ export function doPlatformPricesSync (products) { return new Promise((resolve, reject) => { - if (config.products.alwaysSyncPlatformPricesOver) { - if (config.products.clearPricesBeforePlatformSync) { + if (rootStore.state.config.products.alwaysSyncPlatformPricesOver) { + if (rootStore.state.config.products.clearPricesBeforePlatformSync) { for (let product of products) { // clear out the prices as we need to sync them with Magento product.priceInclTax = null product.originalPriceInclTax = null @@ -228,7 +226,7 @@ export function doPlatformPricesSync (products) { } resolve(products) }) - if (!config.products.waitForPlatformSync && !Vue.prototype.$isServer) { + if (!rootStore.state.config.products.waitForPlatformSync && !Vue.prototype.$isServer) { console.log('Returning products, the prices yet to come from backend!') for (let product of products) { product.price_is_current = false // in case we're syncing up the prices we should mark if we do have current or not @@ -247,7 +245,7 @@ export function doPlatformPricesSync (products) { */ export function calculateTaxes (products, store) { return new Promise((resolve, reject) => { - if (config.tax.calculateServerSide) { + if (rootStore.state.config.tax.calculateServerSide) { console.debug('Taxes calculated server side, skipping') doPlatformPricesSync(products).then((products) => { resolve(products) @@ -371,12 +369,12 @@ export function populateProductConfigurationAsync (context, { product, selectedV } context.state.current_configuration[attr.attribute_code] = confVal // @deprecated fallback for VS <= 1.0RC - if (!('setupVariantByAttributeCode' in config.products) || config.products.setupVariantByAttributeCode === false) { + if (!('setupVariantByAttributeCode' in rootStore.state.config.products) || rootStore.state.config.products.setupVariantByAttributeCode === false) { const fallbackKey = attr.frontend_label ? attr.frontend_label : attr.default_frontend_label context.state.current_configuration[fallbackKey.toLowerCase()] = confVal // @deprecated fallback for VS <= 1.0RC } } - if (config.cart.setConfigurableProductOptions) { + if (rootStore.state.config.cart.setConfigurableProductOptions) { const productOption = setConfigurableProductOptionsAsync(context, { product: product, configuration: context.state.current_configuration }) // set the custom options if (productOption) { product.options = _internalMapOptions(productOption) @@ -439,7 +437,7 @@ export function configureProductAsync (context, { product, configuration, select } product.is_configured = true - if (config.cart.setConfigurableProductOptions && !selectDefaultVariant && !(Object.keys(configuration).length === 1 && configuration.sku)) { + if (rootStore.state.config.cart.setConfigurableProductOptions && !selectDefaultVariant && !(Object.keys(configuration).length === 1 && configuration.sku)) { // the condition above: if selectDefaultVariant - then "setCurrent" is seeting the configurable options; if configuration = { sku: '' } -> this is a special case when not configuring the product but just searching by sku const productOption = setConfigurableProductOptionsAsync(context, { product: product, configuration: configuration }) // set the custom options if (productOption) { @@ -476,7 +474,7 @@ export function getMediaGallery (product) { for (let mediaItem of product.media_gallery) { if (mediaItem.image) { mediaGallery.push({ - 'src': getThumbnailPath(mediaItem.image, config.products.gallery.width, config.products.gallery.height), + 'src': getThumbnailPath(mediaItem.image, rootStore.state.config.products.gallery.width, rootStore.state.config.products.gallery.height), 'loading': getThumbnailPath(product.image, 310, 300) }) } @@ -492,7 +490,7 @@ export function getMediaGallery (product) { export function configurableChildrenImages(product) { let configurableChildrenImages = [] - let variantsGroupBy = config.products.gallery.variantsGroupAttribute + let variantsGroupBy = rootStore.state.config.products.gallery.variantsGroupAttribute if (product.configurable_children && product.configurable_children.length > 0 && product.configurable_children[0][variantsGroupBy]) { let groupedByAttribute = groupBy(product.configurable_children, child => { return child[variantsGroupBy] @@ -500,7 +498,7 @@ export function configurableChildrenImages(product) { Object.keys(groupedByAttribute).forEach(confChild => { if (groupedByAttribute[confChild][0].image) { configurableChildrenImages.push({ - 'src': getThumbnailPath(groupedByAttribute[confChild][0].image, config.products.gallery.width, config.products.gallery.height), + 'src': getThumbnailPath(groupedByAttribute[confChild][0].image, rootStore.state.config.products.gallery.width, rootStore.state.config.products.gallery.height), 'loading': getThumbnailPath(product.image, 310, 300), 'id': confChild }) @@ -518,11 +516,11 @@ export function configurableChildrenImages(product) { export function attributeImages(product) { let attributeImages = [] - if (config.products.gallery.imageAttributes) { - for (let attribute of config.products.gallery.imageAttributes) { + if (rootStore.state.config.products.gallery.imageAttributes) { + for (let attribute of rootStore.state.config.products.gallery.imageAttributes) { if(product[attribute]) { attributeImages.push({ - 'src': getThumbnailPath(product[attribute], config.products.gallery.width, config.products.gallery.height), + 'src': getThumbnailPath(product[attribute], rootStore.state.config.products.gallery.width, rootStore.state.config.products.gallery.height), 'loading': getThumbnailPath(product[attribute], 310, 300) }) } diff --git a/core/store/modules/stock/actions.ts b/core/store/modules/stock/actions.ts index bf95473b91..750b47dc9f 100644 --- a/core/store/modules/stock/actions.ts +++ b/core/store/modules/stock/actions.ts @@ -1,7 +1,7 @@ -import config from '../../lib/config' import { ActionTree } from 'vuex' import RootState from '../../types/RootState' import StockState from './types/StockState' +import rootStore from '../../' const actions: ActionTree = { /** @@ -9,8 +9,8 @@ const actions: ActionTree = { */ check (context, { product, qty = 1 }) { return new Promise((resolve, reject) => { - if (config.stock.synchronize) { - context.dispatch('sync/queue', { url: config.stock.endpoint + '/check?sku=' + encodeURIComponent(product.sku), + if (rootStore.state.config.stock.synchronize) { + context.dispatch('sync/queue', { url: rootStore.state.config.stock.endpoint + '/check?sku=' + encodeURIComponent(product.sku), payload: { method: 'GET', headers: { 'Content-Type': 'application/json' }, @@ -31,8 +31,8 @@ const actions: ActionTree = { */ list (context, { skus }) { return new Promise((resolve, reject) => { - if (config.stock.synchronize) { - context.dispatch('sync/execute', { url: config.stock.endpoint + '/list?skus=' + encodeURIComponent(skus.join(',')), + if (rootStore.state.config.stock.synchronize) { + context.dispatch('sync/execute', { url: rootStore.state.config.stock.endpoint + '/list?skus=' + encodeURIComponent(skus.join(',')), payload: { method: 'GET', headers: { 'Content-Type': 'application/json' }, diff --git a/core/store/modules/stock/index.ts b/core/store/modules/stock/index.ts index 3eb850d598..d37e612153 100644 --- a/core/store/modules/stock/index.ts +++ b/core/store/modules/stock/index.ts @@ -1,26 +1,25 @@ import { Module } from 'vuex' import i18n from '@vue-storefront/core/lib/i18n' import actions from './actions' -import store from '../../' +import rootStore from '../../' import EventBus from '../../lib/event-bus' import * as types from '../../mutation-types' -import config from '../../lib/config' import RootState from '../../types/RootState' import StockState from './types/StockState' EventBus.$on('stock-after-check', (event) => { // example stock check callback setTimeout(() => { - store.dispatch('cart/getItem', event.product_sku).then((cartItem) => { + rootStore.dispatch('cart/getItem', event.product_sku).then((cartItem) => { if (cartItem && event.result.code !== 'ENOTFOUND') { if (!event.result.is_in_stock) { - if (!config.stock.allowOutOfStockInCart) { + if (!rootStore.state.config.stock.allowOutOfStockInCart) { console.log('Removing product from the cart', event.product_sku) - store.commit('cart/' + types.CART_DEL_ITEM, { product: { sku: event.product_sku } }, {root: true}) + rootStore.commit('cart/' + types.CART_DEL_ITEM, { product: { sku: event.product_sku } }, {root: true}) } else { - store.dispatch('cart/updateItem', { product: { errors: { stock: i18n.t('Out of the stock!') }, sku: event.product_sku, is_in_stock: false } }) + rootStore.dispatch('cart/updateItem', { product: { errors: { stock: i18n.t('Out of the stock!') }, sku: event.product_sku, is_in_stock: false } }) } } else { - store.dispatch('cart/updateItem', { product: { info: { stock: i18n.t('In stock!') }, sku: event.product_sku, is_in_stock: true } }) + rootStore.dispatch('cart/updateItem', { product: { info: { stock: i18n.t('In stock!') }, sku: event.product_sku, is_in_stock: true } }) } EventBus.$emit('cart-after-itemchanged', { item: cartItem }) } diff --git a/core/store/modules/sync/actions.ts b/core/store/modules/sync/actions.ts index 7358e2c63a..3119f2e552 100644 --- a/core/store/modules/sync/actions.ts +++ b/core/store/modules/sync/actions.ts @@ -6,8 +6,7 @@ import { _prepareTask } from './helpers' import * as localForage from 'localforage' import UniversalStorage from '@vue-storefront/store/lib/storage' import { currentStoreView } from '../../lib/multistore' -import store from '../../' -import config from 'config' +import rootStore from '../../' import RootState from '../../types/RootState' import SyncState from './types/SyncState' @@ -35,7 +34,7 @@ const actions: ActionTree = { const syncTaskCollection = new UniversalStorage(localForage.createInstance({ name: dbNamePrefix + 'shop', storeName: 'syncTasks', - driver: localForage[config.localForage.defaultDrivers['syncTasks']] + driver: localForage[rootStore.state.config.localForage.defaultDrivers['syncTasks']] })) syncTaskCollection.iterate((task, id, iterationNumber) => { if (!task.transmited) { @@ -48,14 +47,14 @@ const actions: ActionTree = { const dbNamePrefix = storeView.storeCode ? storeView.storeCode + '-' : '' task = _prepareTask(task) const usersCollection = new UniversalStorage(localForage.createInstance({ - name: (config.cart.multisiteCommonCart ? '' : dbNamePrefix) + 'shop', + name: (rootStore.state.config.cart.multisiteCommonCart ? '' : dbNamePrefix) + 'shop', storeName: 'user', - driver: localForage[config.localForage.defaultDrivers['user']] + driver: localForage[rootStore.state.config.localForage.defaultDrivers['user']] })) const cartsCollection = new UniversalStorage(localForage.createInstance({ - name: (config.cart.multisiteCommonCart ? '' : dbNamePrefix) + 'shop', + name: (rootStore.state.config.cart.multisiteCommonCart ? '' : dbNamePrefix) + 'shop', storeName: 'carts', - driver: localForage[config.localForage.defaultDrivers['carts']] + driver: localForage[rootStore.state.config.localForage.defaultDrivers['carts']] })) return new Promise((resolve, reject) => { if (Vue.prototype.$isServer) { @@ -73,11 +72,11 @@ const actions: ActionTree = { if (err) { console.error(err) } - if (!currentCartId && store.state.cart.cartServerToken) { // this is workaround; sometimes after page is loaded indexedb returns null despite the cart token is properly set - currentCartId = store.state.cart.cartServerToken + if (!currentCartId && rootStore.state.cart.cartServerToken) { // this is workaround; sometimes after page is loaded indexedb returns null despite the cart token is properly set + currentCartId = rootStore.state.cart.cartServerToken } - if (!currentToken && store.state.user.cartServerToken) { // this is workaround; sometimes after page is loaded indexedb returns null despite the cart token is properly set - currentToken = store.state.user.token + if (!currentToken && rootStore.state.user.cartServerToken) { // this is workaround; sometimes after page is loaded indexedb returns null despite the cart token is properly set + currentToken = rootStore.state.user.token } taskExecute(task, currentToken, currentCartId).then((result) => { resolve(result) diff --git a/core/store/modules/sync/mutations.ts b/core/store/modules/sync/mutations.ts index 5771d908a8..8f11e34079 100644 --- a/core/store/modules/sync/mutations.ts +++ b/core/store/modules/sync/mutations.ts @@ -2,8 +2,8 @@ import { MutationTree } from 'vuex' import * as types from '../../mutation-types' import { _prepareTask } from './helpers' import EventBus from '../../lib/event-bus' -import config from '../../lib/config' import SyncState from './types/SyncState' +import rootStore from '../../' declare var global: any @@ -17,7 +17,7 @@ const mutations: MutationTree = { task = _prepareTask(task) tasksCollection.setItem(task.task_id.toString(), task, (err, resp) => { if (err) console.error(err) - EventBus.$emit('sync/PROCESS_QUEUE', { config: config }) // process checkout queue + EventBus.$emit('sync/PROCESS_QUEUE', { config: rootStore.state.config }) // process checkout queue console.log('Synchronization task added url = ' + task.url + ' taskId = ' + task.task_id) }).catch((reason) => { console.error(reason) // it doesn't work on SSR diff --git a/core/store/modules/tax/actions.ts b/core/store/modules/tax/actions.ts index 5a20232dc7..420909b72f 100644 --- a/core/store/modules/tax/actions.ts +++ b/core/store/modules/tax/actions.ts @@ -3,7 +3,7 @@ import * as types from '../../mutation-types' import { quickSearchByQuery } from '../../lib/search' import RootState from '../../types/RootState' import TaxState from './types/TaxState' -const bodybuilder = require('bodybuilder') +import bodybuilder from 'bodybuilder' const actions: ActionTree = { /** diff --git a/core/store/modules/user/actions.ts b/core/store/modules/user/actions.ts index 7e6c11debc..275e6841b3 100644 --- a/core/store/modules/user/actions.ts +++ b/core/store/modules/user/actions.ts @@ -1,8 +1,7 @@ import { ActionTree } from 'vuex' import EventBus from '../../lib/event-bus' import * as types from '../../mutation-types' -import config from '../../lib/config' -import store from '../../' +import rootStore from '../../' import { ValidationError } from '../../lib/exceptions' import i18n from '../../lib/i18n' import { adjustMultistoreApiUrl } from '../../lib/multistore' @@ -26,7 +25,7 @@ const actions: ActionTree = { context.commit(types.USER_TOKEN_CHANGED, { newToken: res }) EventBus.$emit('session-after-authorized') - if (config.usePriceTiers) { + if (rootStore.state.config.usePriceTiers) { global.$VS.db.usersCollection.getItem('current-user', (err, userData) => { if (err) { console.error(err) @@ -61,7 +60,7 @@ const actions: ActionTree = { */ resetPassword (context, { email }) { console.log({ email: email }) - return context.dispatch('sync/execute', { url: config.users.resetPassword_endpoint, + return context.dispatch('sync/execute', { url: rootStore.state.config.users.resetPassword_endpoint, payload: { method: 'POST', mode: 'cors', @@ -79,8 +78,8 @@ const actions: ActionTree = { * Login user and return user profile and current token */ login (context, { username, password }) { - let url = config.users.login_endpoint - if (config.storeViews.multistore) { + let url = rootStore.state.config.users.login_endpoint + if (rootStore.state.config.storeViews.multistore) { url = adjustMultistoreApiUrl(url) } return fetch(url, { method: 'POST', @@ -93,7 +92,7 @@ const actions: ActionTree = { }).then(resp => { return resp.json() }) .then((resp) => { if (resp.code === 200) { - global.$VS.userTokenInvalidateLock = 0 + rootStore.state.userTokenInvalidateLock = 0 context.commit(types.USER_TOKEN_CHANGED, { newToken: resp.result, meta: resp.meta }) // TODO: handle the "Refresh-token" header context.dispatch('me', { refresh: true, useCache: false }).then(result => {}) context.dispatch('getOrdersHistory', { refresh: true, useCache: false }).then(result => {}) @@ -105,8 +104,8 @@ const actions: ActionTree = { * Login user and return user profile and current token */ register (context, { email, firstname, lastname, password }) { - let url = config.users.create_endpoint - if (config.storeViews.multistore) { + let url = rootStore.state.config.users.create_endpoint + if (rootStore.state.config.storeViews.multistore) { url = adjustMultistoreApiUrl(url) } return fetch(url, { method: 'POST', @@ -136,8 +135,8 @@ const actions: ActionTree = { if (err) { console.error(err) } - let url = config.users.refresh_endpoint - if (config.storeViews.multistore) { + let url = rootStore.state.config.users.refresh_endpoint + if (rootStore.state.config.storeViews.multistore) { url = adjustMultistoreApiUrl(url) } return fetch(url, { method: 'POST', @@ -163,7 +162,7 @@ const actions: ActionTree = { * @param userData */ setUserGroup(context, userData) { - if (config.usePriceTiers) { + if (rootStore.state.config.usePriceTiers) { if (userData.groupToken) { context.commit(types.USER_GROUP_TOKEN_CHANGED, userData.groupToken) } @@ -208,7 +207,7 @@ const actions: ActionTree = { } if (refresh) { - return context.dispatch('sync/execute', { url: config.users.me_endpoint, + return context.dispatch('sync/execute', { url: rootStore.state.config.users.me_endpoint, payload: { method: 'GET', mode: 'cors', headers: { @@ -255,7 +254,7 @@ const actions: ActionTree = { throw new ValidationError(validate.errors) } else { return new Promise((resolve, reject) => { - context.dispatch('sync/queue', { url: config.users.me_endpoint, + context.dispatch('sync/queue', { url: rootStore.state.config.users.me_endpoint, payload: { method: 'POST', headers: { 'Content-Type': 'application/json' }, @@ -277,7 +276,7 @@ const actions: ActionTree = { */ changePassword (context, passwordData) { console.log(context) - return context.dispatch('sync/execute', { url: config.users.changePassword_endpoint, + return context.dispatch('sync/execute', { url: rootStore.state.config.users.changePassword_endpoint, payload: { method: 'POST', mode: 'cors', @@ -292,7 +291,7 @@ const actions: ActionTree = { action1: { label: i18n.t('OK'), action: 'close' } }) - store.dispatch('user/login', { + rootStore.dispatch('user/login', { username: context.state.current.email, password: passwordData.newPassword }) @@ -368,7 +367,7 @@ const actions: ActionTree = { } if (refresh) { - return context.dispatch('sync/execute', { url: config.users.history_endpoint, + return context.dispatch('sync/execute', { url: rootStore.state.config.users.history_endpoint, payload: { method: 'GET', mode: 'cors', headers: { diff --git a/core/store/modules/user/index.ts b/core/store/modules/user/index.ts index a571c8f407..9015e4a993 100644 --- a/core/store/modules/user/index.ts +++ b/core/store/modules/user/index.ts @@ -4,7 +4,7 @@ import getters from './getters' import mutations from './mutations' import EventBus from '../../lib/event-bus' import i18n from '../../lib/i18n' -import store from '../../' +import rootStore from '../../' import RootState from '../../types/RootState' import UserState from './types/UserState' @@ -15,20 +15,20 @@ EventBus.$on('user-after-update', (event) => { message: i18n.t('Account data has successfully been updated'), action1: { label: i18n.t('OK'), action: 'close' } }) - store.dispatch('user/refreshCurrentUser', event.result) + rootStore.dispatch('user/refreshCurrentUser', event.result) } }) EventBus.$on('session-after-authorized', (event) => { // example stock check callback console.log('Loading user profile') - store.dispatch('user/me', { refresh: navigator.onLine }, { root: true }).then((us) => {}) // this will load user cart - store.dispatch('user/getOrdersHistory', { refresh: navigator.onLine }, { root: true }).then((us) => {}) + rootStore.dispatch('user/me', { refresh: navigator.onLine }, { root: true }).then((us) => {}) // this will load user cart + rootStore.dispatch('user/getOrdersHistory', { refresh: navigator.onLine }, { root: true }).then((us) => {}) }) // After order has been placed fill in missing address information in user's profile and update orders history EventBus.$on('order-after-placed', (order) => { - if (store.getters['user/isLoggedIn']) { - let currentUser = store.state.user.current + if (rootStore.getters['user/isLoggedIn']) { + let currentUser = rootStore.state.user.current let hasShippingAddress = currentUser.hasOwnProperty('default_shipping') let hasBillingAddress = currentUser.hasOwnProperty('default_billing') if (!(hasShippingAddress && hasBillingAddress)) { @@ -66,9 +66,9 @@ EventBus.$on('order-after-placed', (order) => { } } - store.dispatch('user/update', { customer: customer }) + rootStore.dispatch('user/update', { customer: customer }) } - store.dispatch('user/getOrdersHistory', { refresh: true, useCache: false }).then(result => {}) + rootStore.dispatch('user/getOrdersHistory', { refresh: true, useCache: false }).then(result => {}) } }) diff --git a/core/store/package.json b/core/store/package.json index 8eb23f5389..725ba7fe22 100644 --- a/core/store/package.json +++ b/core/store/package.json @@ -9,8 +9,7 @@ }, "dependencies": { "ajv": "^6.4.0", - "bodybuilder": "^2.2.10", - "config": "^1.30.0", + "bodybuilder": "^2.2.13", "he": "^1.1.1", "isomorphic-fetch": "^2.2.1", "localforage": "^1.7.2", diff --git a/core/store/types/RootState.ts b/core/store/types/RootState.ts index 02063eb896..ea53b43a47 100644 --- a/core/store/types/RootState.ts +++ b/core/store/types/RootState.ts @@ -1,15 +1,33 @@ export default interface RootState { version: string, + __DEMO_MODE__: boolean, + config: any, + cart: any, + checkout: any, + cms: any, + compare: any, + product: any, + shipping: any, + user: any, + wishlist: any, attribute: string, category: { - current_path: string + current_path: string, + current_product_query: any, current: { slug: string, name: string - } + }, + filters: any }, stock: { cache: any }, - storeView: any + storeView: any, + twoStageCachingDelta1: number, + twoStageCachingDelta2: number, + twoStageCachingDisabled: boolean, + userTokenInvalidated: string | null, + userTokenInvalidateAttemptsCount: number, + userTokenInvalidateLock: number, } diff --git a/package.json b/package.json index ac1e88a845..9a805960b2 100755 --- a/package.json +++ b/package.json @@ -44,7 +44,7 @@ "dependencies": { "ajv": "^5.2.2", "app-root-path": "^2.0.1", - "bodybuilder": "^2.2.1", + "bodybuilder": "^2.2.13", "config": "^1.30.0", "d3-dsv": "^1.0.8", "detect-installed": "^2.0.4", diff --git a/src/themes/default/package.json b/src/themes/default/package.json index 9230a32412..841d7d517e 100644 --- a/src/themes/default/package.json +++ b/src/themes/default/package.json @@ -10,7 +10,7 @@ "author": "pkarw and contributors", "license": "MIT", "dependencies": { - "bodybuilder": "^2.2.7", + "bodybuilder": "^2.2.13", "vue": "^2.5.13", "vue-carousel": "^0.6.9", "vue-no-ssr": "^0.2.2", diff --git a/src/themes/default/pages/Home.vue b/src/themes/default/pages/Home.vue index 3c70389021..5cd23e9409 100755 --- a/src/themes/default/pages/Home.vue +++ b/src/themes/default/pages/Home.vue @@ -76,7 +76,7 @@ export default { this.$store.dispatch('checkout/load') }, beforeMount () { - if (global.$VS.__DEMO_MODE__) { + if (this.$store.state.__DEMO_MODE__) { this.$store.dispatch('claims/check', { claimCode: 'onboardingAccepted' }).then((onboardingClaim) => { if (!onboardingClaim) { // show onboarding info this.$bus.$emit('modal-toggle', 'modal-onboard') diff --git a/yarn.lock b/yarn.lock index e1d70b9191..4bcea17a76 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1489,9 +1489,9 @@ body-parser@^1.16.1: raw-body "2.3.3" type-is "~1.6.16" -bodybuilder@^2.2.1, bodybuilder@^2.2.10, bodybuilder@^2.2.7: - version "2.2.11" - resolved "https://registry.yarnpkg.com/bodybuilder/-/bodybuilder-2.2.11.tgz#242a6ddf11c7b08e1673d1183c814b56f0998bfd" +bodybuilder@^2.2.13: + version "2.2.13" + resolved "https://registry.yarnpkg.com/bodybuilder/-/bodybuilder-2.2.13.tgz#82ced1c2144bd9ddce97c5d89fa13f7e24c40f8e" dependencies: lodash "^4.9.0" @@ -9341,10 +9341,6 @@ vue-hot-reload-api@^2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/vue-hot-reload-api/-/vue-hot-reload-api-2.3.0.tgz#97976142405d13d8efae154749e88c4e358cf926" -vue-i18n@^7.4.2: - version "7.8.1" - resolved "https://registry.yarnpkg.com/vue-i18n/-/vue-i18n-7.8.1.tgz#2ce4b6efde679a1e05ddb5d907bfc1bc218803b2" - vue-i18n@^8.0.0: version "8.0.0" resolved "https://registry.yarnpkg.com/vue-i18n/-/vue-i18n-8.0.0.tgz#ae0c6e05ec8e36151bcf5f47c7b538c8af6d0282"