@mezereon/bigcommerce-stencil
Version:
BigCommerce UI components for Mezereon Xperience
226 lines (214 loc) • 6.56 kB
JavaScript
import { isAbsoluteUrl, isEmpty } from '@/helpers'
import mz from '@mezereon/tracking'
import { mapGetters, mapState } from 'vuex'
export default {
data() {
return {
loading: true,
apiUrl: mz.config.search.url,
searchKey: mz.config.search.key
}
},
computed: {
...mapState('search', [
'pageId',
'queryId',
'segments',
'keyword',
'page',
'sort',
'pageSize',
'selections',
'filters',
'aggregations',
'hits',
'primaryKey',
'context',
'fallbackMode',
'queryParam',
'pagination',
'redirect'
]),
...mapGetters('search', ['getFacetBanners', 'getQuery'])
},
created() {
const store = this.$store
store.dispatch('api/setApiUrl', this.apiUrl, { root: true })
store.dispatch('api/setSearchKey', this.searchKey, { root: true })
if (this.$bus) this.$bus.on('run-query', this.doSearch)
},
mounted() {
// initial query is executed only when mz-context is on the page
if (this.$refs.context === undefined) {
this.loading = false
this.showResults()
return
}
if (this.fallbackMode) {
this.loading = false
this.turnOnFallbackMode()
return
}
// define queryParam and register query state change handler
this.$queryState.setQueryParam(this.queryParam)
this.$queryState.onChange(this.queryStateChange)
// run initial query
this.queryStateChange(this.$queryState.parseUrl())
},
methods: {
pushState(pagination) {
if (pagination.current_page == 1) {
return true
}
if (
pagination.pagingType === 'more' ||
pagination.pagingType == 'infinite'
) {
return false
}
return true
},
showResults() {
// hide aggregations div
const hideAggs =
isEmpty(this.getFacetBanners) && this.aggregations.length === 0
const aggs = document.querySelectorAll('.mz-aggs')
if (aggs) {
aggs.forEach((item) => {
item.style.display = hideAggs ? 'none' : 'block'
})
}
},
turnOnFallbackMode() {
// show fallback content
const app = document.querySelector('#mz-app')
if (app) {
app.style.setProperty('display', 'none', 'important')
}
const autocomplete = document.querySelector('#mz-autocomplete')
if (autocomplete) {
autocomplete.style.setProperty('display', 'none', 'important')
}
// remove mz-fallback class to make original controls visible
const fallback = document.querySelectorAll('.mz-fallback')
if (fallback) {
fallback.forEach((item) => {
item.classList.remove('mz-fallback')
})
}
window.mz.enabled = false
},
queryStateChange(state) {
this.loading = true
// use sort and pageSize from cookies when undefined
state.sort = state.sort || this.$cookies.get('sort')
state.pageSize = state.pageSize || this.$cookies.get('pageSize')
this.$store.dispatch('search/setState', state, { root: true })
this.runQuery(false)
},
doSearch() {
this.runQuery(true)
},
runQuery(push) {
const query = {
filter: this.context.filter,
pageUrl: this.context.pageUrl,
pageId: this.pageId,
keyword: this.keyword,
page: this.page,
sort: this.sort,
pageSize: this.pageSize,
filters: this.filters,
currency: this.context.currency
}
if (this.context.categoryId) {
query['categoryId'] = this.context.categoryId
}
const context = {
visitId: mz ? mz.getVisitId() : '',
visitorId: mz ? mz.getVisitorId() : '',
tags: this.context.tags,
narrow: this.context.narrow
}
this.$store
.dispatch('search/runQuery', { query, context }, { root: true })
.then(() => {
// hide loader
this.loading = false
if (this.pushState(this.pagination)) {
// push to history
if (push) {
this.$queryState.push(this.getQuery())
}
if (this.$scrollTo) {
if (mz && mz.config && mz.config.scroll) {
if (!mz.config.scroll.disabled) {
this.$scrollTo(
mz.config.scroll.element || 'body',
mz.config.scroll.duration || 300
)
}
} else {
this.$scrollTo(300)
}
}
}
this.showResults()
const event = { query, context, result: this.hits }
if (push) {
// emit after-query event needed for custom handlers
if (this.$bus) this.$bus.emit('after-query', event)
} else {
// emit after-initial-query event needed for custom handlers
if (this.$bus) this.$bus.emit('after-initial-query', event)
}
const self = this
this.$nextTick(() => {
if (self.$bus) self.$bus.emit('after-update', event)
})
if (mz && mz.track && this.hits) {
// retrieve top 10 unique ids from results for ML
const uids = []
for (let i = 0; i < 10 && i < this.hits.items.length; i++) {
uids.push(this.hits.items[i].item[this.hits.primaryKey])
}
const banners = []
if (this.hits.banners) {
for (const [k, v] of Object.entries(this.hits.banners)) {
if (v === null) {
continue
}
banners.push({ zone: k, id: v.id })
}
}
mz.track('query', {
queryId: this.queryId,
query,
segments: this.segments,
context,
total: this.hits.total,
banners,
uids,
redirect: this.redirect
})
}
if (this.redirect) {
let redirect = this.redirect
if (isAbsoluteUrl(redirect)) {
window.location.replace(redirect)
return
}
if (mz && mz.context && mz.context.root) {
redirect = `${mz.context.root}${redirect}`
}
window.location.replace(redirect)
return
}
})
.catch(() => {
this.loading = false
this.turnOnFallbackMode()
})
}
}
}