diff --git a/CHANGELOG.md b/CHANGELOG.md index 5f17f25c5e..db4def0992 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -52,6 +52,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Fix v-model not working in BaseRadioButton - @lukeromanowicz (#4035) - always keep filters values as array of object - @gibkigonzo (#4045) - Fix ecosystem config to work with ts-node - @andrzejewsky (#3981) +- Add currentRoute to url module and return cached requests - @gibkigonzo (#4045) ## [1.11.0] - 2019.12.20 diff --git a/core/client-entry.ts b/core/client-entry.ts index c7135d0ad2..edc20abd62 100755 --- a/core/client-entry.ts +++ b/core/client-entry.ts @@ -103,6 +103,9 @@ const invokeClientEntry = async () => { if (!matched.length || !matched[0]) { return next() } + + store.dispatch('url/setCurrentRoute', to) + Promise.all(matched.map((c: any) => { // TODO: update me for mixins support const components = c.mixins && globalConfig.ssr.executeMixedinAsyncData ? Array.from(c.mixins) : [] union(components, [c]).map(SubComponent => { diff --git a/core/lib/search.ts b/core/lib/search.ts index 403bbdc769..e0a5cacead 100644 --- a/core/lib/search.ts +++ b/core/lib/search.ts @@ -33,7 +33,7 @@ export const quickSearchByQuery = async ({ query = {}, start = 0, size = 50, ent if (size <= 0) size = 50 if (start < 0) start = 0 - return new Promise((resolve, reject) => { + return new Promise(async (resolve, reject) => { const storeView = currentStoreView() const Request: SearchRequest = { store: storeCode || storeView.storeCode, // TODO: add grouped product and bundled product support @@ -58,20 +58,21 @@ export const quickSearchByQuery = async ({ query = {}, start = 0, size = 50, ent const cacheKey = sha3_224(JSON.stringify(Request)) const benchmarkTime = new Date() - cache.getItem(cacheKey, (err, res) => { - if (err) console.log(err) + try { + const res = await cache.getItem(cacheKey) if (res !== null) { res.cache = true res.noresults = false res.offline = !isOnline() // TODO: refactor it to checking ES heartbit - resolve(res) Logger.debug('Result from cache for ' + cacheKey + ' (' + entityType + '), ms=' + (new Date().getTime() - benchmarkTime.getTime()))() servedFromCache = true + resolve(res) + return } - }).catch((err) => { + } catch (err) { console.error('Cannot read cache for ' + cacheKey + ', ' + err) - }) + } /* use only for cache */ if (Request.groupId) { diff --git a/core/modules/catalog-next/store/category/getters.ts b/core/modules/catalog-next/store/category/getters.ts index 364142bdb4..c276ae7eaa 100644 --- a/core/modules/catalog-next/store/category/getters.ts +++ b/core/modules/catalog-next/store/category/getters.ts @@ -9,6 +9,7 @@ import { optionLabel } from '../../helpers/optionLabel' import trim from 'lodash-es/trim' import toString from 'lodash-es/toString' import forEach from 'lodash-es/forEach' +import get from 'lodash-es/get' import { getFiltersFromQuery } from '../../helpers/filterHelpers' import { Category } from '../../types/Category' import { parseCategoryPath } from '@vue-storefront/core/modules/breadcrumbs/helpers' @@ -42,8 +43,8 @@ const getters: GetterTree = { return valueCheck.filter(check => check === true).length === Object.keys(searchOptions).length }) || {} }, - getCurrentCategory: (state, getters, rootState) => { - return getters.getCategoryByParams(rootState.route.params) + getCurrentCategory: (state, getters, rootState, rootGetters) => { + return getters.getCategoryByParams(rootGetters['url/getCurrentRoute'].params) }, getAvailableFiltersFrom: (state, getters, rootState) => (aggregations) => { const filters = {} @@ -110,13 +111,16 @@ const getters: GetterTree = { return filters }, getFiltersMap: state => state.filtersMap, - getAvailableFilters: (state, getters) => getters.getCurrentCategory ? state.filtersMap[getters.getCurrentCategory.id] : {}, - getCurrentFiltersFrom: (state, getters, rootState) => (filters, categoryFilters) => { - const currentQuery = filters || rootState.route[products.routerFiltersSource] + getAvailableFilters: (state, getters) => { + const categoryId = get(getters.getCurrentCategory, 'id', null) + return state.filtersMap[categoryId] || {} + }, + getCurrentFiltersFrom: (state, getters, rootState, rootGetters) => (filters, categoryFilters) => { + const currentQuery = filters || rootGetters['url/getCurrentRoute'][products.routerFiltersSource] const availableFilters = categoryFilters || getters.getAvailableFilters return getFiltersFromQuery({availableFilters, filtersQuery: currentQuery}) }, - getCurrentSearchQuery: (state, getters, rootState) => getters.getCurrentFiltersFrom(rootState.route[products.routerFiltersSource]), + getCurrentSearchQuery: (state, getters, rootState, rootGetters) => getters.getCurrentFiltersFrom(rootGetters['url/getCurrentRoute'][products.routerFiltersSource]), getCurrentFilters: (state, getters) => getters.getCurrentSearchQuery.filters, hasActiveFilters: (state, getters) => !!Object.keys(getters.getCurrentFilters).length, getSystemFilterNames: () => products.systemFilterNames, diff --git a/core/modules/catalog-next/store/category/mutations.ts b/core/modules/catalog-next/store/category/mutations.ts index c391af5f46..7dc398d087 100644 --- a/core/modules/catalog-next/store/category/mutations.ts +++ b/core/modules/catalog-next/store/category/mutations.ts @@ -34,7 +34,7 @@ const mutations: MutationTree = { state.notFoundCategoryIds = [...state.notFoundCategoryIds, ...categoryIds] }, [types.CATEGORY_SET_CATEGORY_FILTERS] (state, {category, filters}) { - state.filtersMap[category.id] = filters + Vue.set(state.filtersMap, category.id, filters) }, [types.CATEGORY_SET_SEARCH_PRODUCTS_STATS] (state, stats = {}) { state.searchProductsStats = stats diff --git a/core/modules/url/store/actions.ts b/core/modules/url/store/actions.ts index 8cac1ff8ad..07ad84f966 100644 --- a/core/modules/url/store/actions.ts +++ b/core/modules/url/store/actions.ts @@ -93,5 +93,8 @@ export const actions: ActionTree = { } } } + }, + setCurrentRoute ({ commit }, payload) { + commit(types.SET_CURRENT_ROUTE, payload) } } diff --git a/core/modules/url/store/getters.ts b/core/modules/url/store/getters.ts new file mode 100644 index 0000000000..eac527f75c --- /dev/null +++ b/core/modules/url/store/getters.ts @@ -0,0 +1,3 @@ +export const getters = { + getCurrentRoute: (state) => state.currentRoute +} diff --git a/core/modules/url/store/index.ts b/core/modules/url/store/index.ts index 336bade112..315e3fc219 100644 --- a/core/modules/url/store/index.ts +++ b/core/modules/url/store/index.ts @@ -3,10 +3,12 @@ import { UrlState } from '../types/UrlState' import { mutations } from './mutations' import { actions } from './actions' import { state } from './state' +import { getters } from './getters' export const urlStore: Module = { namespaced: true, mutations, actions, - state + state, + getters } diff --git a/core/modules/url/store/mutation-types.ts b/core/modules/url/store/mutation-types.ts index 5f047c63b8..ec7537f0c5 100644 --- a/core/modules/url/store/mutation-types.ts +++ b/core/modules/url/store/mutation-types.ts @@ -1 +1,2 @@ export const REGISTER_MAPPING = 'URL/REGISTER_MAPPING' +export const SET_CURRENT_ROUTE = 'URL/SET_CURRENT_ROUTE' diff --git a/core/modules/url/store/mutations.ts b/core/modules/url/store/mutations.ts index ed2a7a8027..d4a3ed6c67 100644 --- a/core/modules/url/store/mutations.ts +++ b/core/modules/url/store/mutations.ts @@ -1,8 +1,12 @@ import { MutationTree } from 'vuex' import * as types from './mutation-types' +import omit from 'lodash-es/omit' export const mutations: MutationTree = { [types.REGISTER_MAPPING] (state, payload) { state.dispatcherMap = Object.assign({}, state.dispatcherMap, { [payload.url]: payload.routeData }) + }, + [types.SET_CURRENT_ROUTE] (state, payload = {}) { + state.currentRoute = omit(payload, ['matched']) } } diff --git a/core/modules/url/store/state.ts b/core/modules/url/store/state.ts index 58a10c29ae..f4dc5af317 100644 --- a/core/modules/url/store/state.ts +++ b/core/modules/url/store/state.ts @@ -1,5 +1,6 @@ import { UrlState } from '../types/UrlState' export const state: UrlState = { - dispatcherMap: {} + dispatcherMap: {}, + currentRoute: {} } diff --git a/core/modules/url/types/UrlState.ts b/core/modules/url/types/UrlState.ts index fba3babff0..d526a981ea 100644 --- a/core/modules/url/types/UrlState.ts +++ b/core/modules/url/types/UrlState.ts @@ -1,7 +1,9 @@ +import { Route } from 'vue-router'; import { LocalizedRoute } from '@vue-storefront/core/lib/types' // This object should represent structure of your modules Vuex state // It's a good practice is to name this interface accordingly to the KET (for example mailchimpState) export interface UrlState { - dispatcherMap: { [path: string]: LocalizedRoute} + dispatcherMap: { [path: string]: LocalizedRoute}, + currentRoute: Partial } diff --git a/core/server-entry.ts b/core/server-entry.ts index 530bef6ec1..8d054ff45d 100755 --- a/core/server-entry.ts +++ b/core/server-entry.ts @@ -78,6 +78,7 @@ export default async context => { if (!matchedComponents.length || !matchedComponents[0]) { return reject(new HttpError('No components matched', 404)) // TODO - don't redirect if already on page-not-found } + store.dispatch('url/setCurrentRoute', router.currentRoute) Promise.all(matchedComponents.map((Component: any) => { const components = Component.mixins ? Array.from(Component.mixins) : [] union(components, [Component]).map(SubComponent => { diff --git a/core/store/index.ts b/core/store/index.ts index ee38dbdd08..bbdac9a065 100644 --- a/core/store/index.ts +++ b/core/store/index.ts @@ -48,7 +48,8 @@ const state = { twoStageCachingDisabled: false, userTokenInvalidated: null, userTokenInvalidateAttemptsCount: 0, - userTokenInvalidateLock: 0 + userTokenInvalidateLock: 0, + url: {} } let rootStore = new Vuex.Store({ diff --git a/core/types/RootState.ts b/core/types/RootState.ts index bec8d6bbc3..017ed7f7b4 100644 --- a/core/types/RootState.ts +++ b/core/types/RootState.ts @@ -32,5 +32,6 @@ export default interface RootState { userTokenInvalidated: string | null, userTokenInvalidateAttemptsCount: number, userTokenInvalidateLock: number, - route?: any + route?: any, + url: any }