config#products TypeScript Examples
The following examples show how to use
config#products.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: cacheProductsHelper.ts From vue-storefront-1 with MIT License | 6 votes |
prefetchStockItems = (cachedProductsResponse, cache = {}) => {
const skus = []
let prefetchIndex = 0
cachedProductsResponse.items.map(i => {
if (products.configurableChildrenStockPrefetchStatic &&
products.configurableChildrenStockPrefetchStaticPrefetchCount > 0) {
if (prefetchIndex > 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) {
for (const confChild of i.configurable_children) {
const cachedItem = cache[confChild.id]
if (typeof cachedItem === 'undefined' || cachedItem === null) {
skus.push(confChild.sku)
}
}
prefetchIndex++
}
})
return skus
}
Example #2
Source File: actions.ts From vue-storefront-1 with MIT License | 4 votes |
actions: ActionTree<CategoryState, RootState> = {
async loadCategoryProducts ({ commit, getters, dispatch, rootState }, { route, category, pageSize = 50 } = {}) {
const searchCategory = category || getters.getCategoryFrom(route.path) || {}
const areFiltersInQuery = !!Object.keys(route[products.routerFiltersSource]).length
let categoryMappedFilters = getters.getFiltersMap[searchCategory.id]
if (!categoryMappedFilters && areFiltersInQuery) { // loading all filters only when some filters are currently chosen and category has no available filters yet
await dispatch('loadCategoryFilters', searchCategory)
categoryMappedFilters = getters.getFiltersMap[searchCategory.id]
}
const searchQuery = getters.getCurrentFiltersFrom(route[products.routerFiltersSource], categoryMappedFilters)
let filterQr = buildFilterProductsQuery(searchCategory, searchQuery.filters)
const { items, perPage, start, total, aggregations, attributeMetadata } = await dispatch('product/findProducts', {
query: filterQr,
sort: searchQuery.sort || `${products.defaultSortBy.attribute}:${products.defaultSortBy.order}`,
includeFields: entities.productList.includeFields,
excludeFields: entities.productList.excludeFields,
size: pageSize,
configuration: searchQuery.filters,
options: {
populateRequestCacheTags: true,
prefetchGroupProducts: false,
setProductErrors: false,
fallbackToDefaultWhenNoAvailable: true,
assignProductConfiguration: false,
separateSelectedVariant: false
}
}, { root: true })
await dispatch('loadAvailableFiltersFrom', {
aggregations,
attributeMetadata,
category: searchCategory,
filters: searchQuery.filters
})
commit(types.CATEGORY_SET_SEARCH_PRODUCTS_STATS, { perPage, start, total })
commit(types.CATEGORY_SET_PRODUCTS, items)
return items
},
async loadMoreCategoryProducts ({ commit, getters, rootState, dispatch }) {
const { perPage, start, total } = getters.getCategorySearchProductsStats
const totalValue = typeof total === 'object' ? total.value : total
if (start >= totalValue || totalValue < perPage) return
const searchQuery = getters.getCurrentSearchQuery
let filterQr = buildFilterProductsQuery(getters.getCurrentCategory, searchQuery.filters)
const searchResult = await dispatch('product/findProducts', {
query: filterQr,
sort: searchQuery.sort || `${products.defaultSortBy.attribute}:${products.defaultSortBy.order}`,
start: start + perPage,
size: perPage,
includeFields: entities.productList.includeFields,
excludeFields: entities.productList.excludeFields,
configuration: searchQuery.filters,
options: {
populateRequestCacheTags: true,
prefetchGroupProducts: false,
setProductErrors: false,
fallbackToDefaultWhenNoAvailable: true,
assignProductConfiguration: false,
separateSelectedVariant: false
}
}, { root: true })
commit(types.CATEGORY_SET_SEARCH_PRODUCTS_STATS, {
perPage: searchResult.perPage,
start: searchResult.start,
total: searchResult.total
})
commit(types.CATEGORY_ADD_PRODUCTS, searchResult.items)
return searchResult.items
},
async cacheProducts ({ commit, getters, dispatch, rootState }, { route } = {}) {
if (config.api.saveBandwidthOverCache) {
return
}
const searchCategory = getters.getCategoryFrom(route.path) || {}
const searchQuery = getters.getCurrentFiltersFrom(route[products.routerFiltersSource])
let filterQr = buildFilterProductsQuery(searchCategory, searchQuery.filters)
const cachedProductsResponse = await dispatch('product/findProducts', {
query: filterQr,
sort: searchQuery.sort,
options: {
populateRequestCacheTags: false,
prefetchGroupProducts: false
}
}, { root: true })
if (products.filterUnavailableVariants) { // prefetch the stock items
const skus = prefetchStockItems(cachedProductsResponse, rootState.stock.cache)
for (const chunkItem of chunk(skus, 15)) {
dispatch('stock/list', { skus: chunkItem }, { root: true }) // store it in the cache
}
}
},
async findCategories (context, categorySearchOptions: DataResolver.CategorySearchOptions): Promise<Category[]> {
return CategoryService.getCategories(categorySearchOptions)
},
async loadCategories ({ commit, getters }, categorySearchOptions: DataResolver.CategorySearchOptions): Promise<Category[]> {
const searchingByIds = !(!categorySearchOptions || !categorySearchOptions.filters || !categorySearchOptions.filters.id)
const searchedIds: string[] = searchingByIds ? [...categorySearchOptions.filters.id].map(String) : []
const loadedCategories: Category[] = []
if (searchingByIds && !categorySearchOptions.reloadAll) { // removing from search query already loaded categories, they are added to returned results
for (const [categoryId, category] of Object.entries(getters.getCategoriesMap)) {
if (searchedIds.includes(categoryId)) {
loadedCategories.push(category as Category)
}
}
categorySearchOptions.filters.id = searchedIds.filter(categoryId => !getters.getCategoriesMap[categoryId] && !getters.getNotFoundCategoryIds.includes(categoryId))
}
if (!searchingByIds || categorySearchOptions.filters.id.length) {
categorySearchOptions.filters = Object.assign(cloneDeep(config.entities.category.filterFields), categorySearchOptions.filters ? cloneDeep(categorySearchOptions.filters) : {})
const categories = await CategoryService.getCategories(categorySearchOptions)
if (Vue.prototype.$cacheTags) {
categories.forEach(category => {
Vue.prototype.$cacheTags.add(`C${category.id}`)
})
}
const notFoundCategories = searchedIds.filter(categoryId => !categories.some(cat => cat.id === parseInt(categoryId) || cat.id === categoryId))
commit(types.CATEGORY_ADD_CATEGORIES, categories)
commit(types.CATEGORY_ADD_NOT_FOUND_CATEGORY_IDS, notFoundCategories)
return [...loadedCategories, ...categories]
}
return loadedCategories
},
async loadCategory ({ commit }, categorySearchOptions: DataResolver.CategorySearchOptions): Promise<Category> {
const categories: Category[] = await CategoryService.getCategories(categorySearchOptions)
const category: Category = categories && categories.length ? categories[0] : null
if (Vue.prototype.$cacheTags) {
Vue.prototype.$cacheTags.add(`C${category.id}`)
}
commit(types.CATEGORY_ADD_CATEGORY, category)
return category
},
/**
* Fetch and process filters from current category and sets them in available filters.
*/
async loadCategoryFilters ({ dispatch, getters }, category) {
const searchCategory = category || getters.getCurrentCategory
let filterQr = buildFilterProductsQuery(searchCategory)
const { aggregations, attributeMetadata } = await quickSearchByQuery({
query: filterQr,
size: config.products.maxFiltersQuerySize,
excludeFields: ['*']
})
await dispatch('loadAvailableFiltersFrom', { aggregations, attributeMetadata: attributeMetadata, category })
},
async loadAvailableFiltersFrom ({ commit, getters, dispatch }, { aggregations, attributeMetadata, category, filters = {} }) {
if (config.entities.attribute.loadByAttributeMetadata) {
await dispatch('attribute/loadCategoryAttributes', { attributeMetadata }, { root: true })
}
const aggregationFilters = getters.getAvailableFiltersFrom(aggregations)
const currentCategory = category || getters.getCurrentCategory
const categoryMappedFilters = getters.getFiltersMap[currentCategory.id]
let resultFilters = aggregationFilters
const filtersKeys = Object.keys(filters)
if (categoryMappedFilters && filtersKeys.length) {
resultFilters = Object.assign(cloneDeep(categoryMappedFilters), cloneDeep(omit(aggregationFilters, filtersKeys)))
}
commit(types.CATEGORY_SET_CATEGORY_FILTERS, { category, filters: resultFilters })
},
async switchSearchFilters ({ dispatch }, filterVariants: FilterVariant[] = []) {
let currentQuery = router.currentRoute[products.routerFiltersSource]
filterVariants.forEach(filterVariant => {
currentQuery = changeFilterQuery({ currentQuery, filterVariant })
})
await dispatch('changeRouterFilterParameters', currentQuery)
},
async resetSearchFilters ({ dispatch }) {
await dispatch('changeRouterFilterParameters', {})
},
async changeRouterFilterParameters (context, query) {
router.push({ [products.routerFiltersSource]: query })
},
async loadCategoryBreadcrumbs ({ dispatch, getters }, { category, currentRouteName, omitCurrent = false }) {
if (!category) return
const categoryHierarchyIds = category.parent_ids ? [...category.parent_ids, category.id] : _prepareCategoryPathIds(category) // getters.getCategoriesHierarchyMap.find(categoryMapping => categoryMapping.includes(category.id))
const categoryFilters = Object.assign({ 'id': categoryHierarchyIds }, cloneDeep(config.entities.category.breadcrumbFilterFields))
const categories = await dispatch('loadCategories', { filters: categoryFilters, reloadAll: Object.keys(config.entities.category.breadcrumbFilterFields).length > 0 })
const sorted = []
for (const id of categoryHierarchyIds) {
const index = categories.findIndex(cat => cat.id.toString() === id)
if (index >= 0 && (!omitCurrent || categories[index].id !== category.id)) {
sorted.push(categories[index])
}
}
await dispatch('breadcrumbs/set', { current: currentRouteName, routes: parseCategoryPath(sorted) }, { root: true })
return sorted
},
/**
* Load categories within specified parent
* @param {Object} commit promise
* @param {Object} parent parent category
*/
async fetchMenuCategories ({ commit, getters, dispatch }, {
parent = null,
key = null,
value = null,
level = null,
onlyActive = true,
onlyNotEmpty = false,
size = 4000,
start = 0,
sort = 'position:asc',
includeFields = (config.entities.optimize ? config.entities.category.includeFields : null),
excludeFields = (config.entities.optimize ? config.entities.category.excludeFields : null),
skipCache = false
}) {
const { searchQuery, isCustomizedQuery } = createCategoryListQuery({ parent, level, key, value, onlyActive, onlyNotEmpty })
const shouldLoadCategories = skipCache || isCustomizedQuery
if (shouldLoadCategories) {
const resp = await quickSearchByQuery({ entityType: 'category', query: searchQuery, sort, size, start, includeFields, excludeFields })
await dispatch('registerCategoryMapping', { categories: resp.items })
commit(types.CATEGORY_UPD_MENU_CATEGORIES, { items: resp.items })
return resp
}
const list = { items: getters.getMenuCategories, total: getters.getMenuCategories.length }
return list
},
async registerCategoryMapping ({ dispatch }, { categories }) {
for (let category of categories) {
if (category.url_path) {
await dispatch('url/registerMapping', {
url: localizedDispatcherRoute(category.url_path),
routeData: transformCategoryUrl(category)
}, { root: true })
}
}
},
/** Below actions are not used from 1.12 and can be removed to reduce bundle */
...require('./deprecatedActions').default
}
Example #3
Source File: getters.ts From vue-storefront-1 with MIT License | 4 votes |
getters: GetterTree<CategoryState, RootState> = {
getCategories: (state): Category[] => Object.values(state.categoriesMap),
getCategoriesMap: (state): { [id: string]: Category} => state.categoriesMap,
getNotFoundCategoryIds: (state): string[] => state.notFoundCategoryIds,
getCategoryProducts: (state) => mapCategoryProducts(state.products, nonReactiveState.products),
getCategoryFrom: (state, getters) => (path: string = '') => {
return getters.getCategories.find(category => (removeStoreCodeFromRoute(path) as string).replace(/^(\/)/gm, '') === category.url_path)
},
getCategoryByParams: (state, getters, rootState) => (params: { [key: string]: string } = {}) => {
return getters.getCategories.find(category => {
let valueCheck = []
const searchOptions = getSearchOptionsFromRouteParams(params)
forEach(searchOptions, (value, key) => valueCheck.push(category[key] && category[key] === (category[key].constructor)(value)))
return valueCheck.filter(check => check === true).length === Object.keys(searchOptions).length
}) || {}
},
getCurrentCategory: (state, getters, rootState, rootGetters) => {
return getters.getCategoryByParams(rootState.route.params)
},
getAvailableFiltersFrom: (state, getters, rootState) => (aggregations) => {
const filters = {}
if (aggregations) { // populate filter aggregates
for (let attrToFilter of products.defaultFilters) { // fill out the filter options
let filterOptions: FilterVariant[] = []
let uniqueFilterValues = new Set<string>()
if (attrToFilter !== 'price') {
if (aggregations['agg_terms_' + attrToFilter]) {
let buckets = aggregations['agg_terms_' + attrToFilter].buckets
if (aggregations['agg_terms_' + attrToFilter + '_options']) {
buckets = buckets.concat(aggregations['agg_terms_' + attrToFilter + '_options'].buckets)
}
for (let option of buckets) {
uniqueFilterValues.add(toString(option.key))
}
}
uniqueFilterValues.forEach(key => {
const label = optionLabel(rootState.attribute, { attributeKey: attrToFilter, optionId: key })
if (trim(label) !== '') { // is there any situation when label could be empty and we should still support it?
filterOptions.push({
id: key,
label: label,
type: attrToFilter
})
}
});
filters[attrToFilter] = filterOptions.sort(compareByLabel)
} else { // special case is range filter for prices
const currencySign = currentStoreView().i18n.currencySign
if (aggregations['agg_range_' + attrToFilter]) {
let index = 0
let count = aggregations['agg_range_' + attrToFilter].buckets.length
for (let option of aggregations['agg_range_' + attrToFilter].buckets) {
filterOptions.push({
id: option.key,
type: attrToFilter,
from: option.from,
to: option.to,
label: (index === 0 || (index === count - 1)) ? (option.to ? '< ' + currencySign + option.to : '> ' + currencySign + option.from) : currencySign + option.from + (option.to ? ' - ' + option.to : ''), // TODO: add better way for formatting, extract currency sign
single: true
})
index++
}
filters[attrToFilter] = filterOptions
}
}
}
// Add sort to available filters
let variants = []
Object.keys(products.sortByAttributes).map(label => {
variants.push({
label: label,
id: products.sortByAttributes[label],
type: 'sort'
})
})
filters['sort'] = variants
}
return filters
},
getFiltersMap: state => state.filtersMap,
getAvailableFilters: (state, getters) => {
const categoryId = get(getters.getCurrentCategory, 'id', null)
return state.filtersMap[categoryId] || {}
},
getCurrentFiltersFrom: (state, getters, rootState) => (filters, categoryFilters) => {
const currentQuery = filters || rootState.route[products.routerFiltersSource]
const availableFilters = categoryFilters || getters.getAvailableFilters
return getFiltersFromQuery({ availableFilters, filtersQuery: currentQuery })
},
getCurrentSearchQuery: (state, getters, rootState) => getters.getCurrentFiltersFrom(rootState.route[products.routerFiltersSource]),
getCurrentFilters: (state, getters) => getters.getCurrentSearchQuery.filters,
hasActiveFilters: (state, getters) => !!Object.keys(getters.getCurrentFilters).length,
getSystemFilterNames: () => products.systemFilterNames,
getBreadcrumbs: (state, getters) => getters.getBreadcrumbsFor(getters.getCurrentCategory),
getBreadcrumbsFor: (state, getters) => category => {
if (!category) return []
const categoryHierarchyIds = _prepareCategoryPathIds(category)
let resultCategoryList = categoryHierarchyIds.map(categoryId => {
return getters.getCategoriesMap[categoryId]
}).filter(c => !!c)
return parseCategoryPath(resultCategoryList)
},
getCategorySearchProductsStats: state => state.searchProductsStats || {},
getCategoryProductsTotal: (state, getters) => {
const { total } = getters.getCategorySearchProductsStats
const totalValue = typeof total === 'object' ? total.value : total
return totalValue || 0
},
getMenuCategories (state, getters, rootState, rootGetters) {
return state.menuCategories || rootGetters['category/getCategories']
}
}