@mezereon/ui-components-vue
Version:
UI components for Mezereon - Vue
294 lines (289 loc) • 7.08 kB
JavaScript
import { isEmpty } from 'lodash'
import { createPopper } from '@popperjs/core'
import MzTooltip from './../components/MzTooltip'
export default {
name: 'Refinement',
components: {
MzTooltip
},
props: {
horizontal: {
type: Boolean,
required: true
},
aggregation: {
type: Object,
required: true
},
iconSet: {
type: String,
required: true
}
},
data() {
return {
hiddenProxy: null,
popper: null
}
},
computed: {
isBox() {
return this.display.style === 'box'
},
isSingle() {
return this.display.selection === 'single'
},
hidden: {
get() {
// if horizontal, then do not read cookie
if (this.horizontal) {
if (this.hiddenProxy == null) {
this.hiddenProxy = true
}
return this.hiddenProxy
}
if (typeof process === 'object' || this.hiddenProxy === null) {
if (!this.$cookies) {
return false
}
let collapsed = this.$cookies.get(
this.aggregation.name + '_collapsed'
)
if (collapsed === undefined) {
collapsed = this.display.collapsed
}
this.hiddenProxy = collapsed
}
return this.hiddenProxy
},
set(value) {
this.hiddenProxy = value
// do not store state in cookies for horizontal facet
if (this.horizontal) {
return
}
if (this.$cookies) {
this.$cookies.set(this.aggregation.name + '_collapsed', value, {
sameSite: 'strict'
})
}
}
},
isFilter() {
return !this.hidden && !isEmpty(this.selected)
},
items() {
return this.aggregation.items
},
display() {
return this.aggregation.display
},
selected() {
return this.aggregation.selected
}
},
methods: {
clickHandler(e) {
if (!this.$el.contains(e.target)) {
this.hide()
}
},
keyHandler(e) {
if (e.key === 'Escape') {
this.hide()
}
},
hide() {
if (!this.hidden) this.toggleVisibility()
},
toggleVisibility() {
this.hidden = !this.hidden
if (!this.hidden) {
this.showPopper()
} else {
this.hidePopper()
}
},
setupPopper() {
if (!this.horizontal) {
return
}
const button = this.$refs.button
const tooltip = this.$refs.tooltip
if (button) {
this.popper = createPopper(button, tooltip, {
modifiers: [
{
name: 'preventOverflow',
options: {
padding: 5
}
},
{
name: 'flip',
options: {
fallbackPlacements: ['top-start', 'bottom-start']
}
},
{
name: 'offset',
options: {
offset: [0, -1]
}
}
],
placement: 'bottom-start'
})
}
},
showPopper() {
if (!this.horizontal) {
return
}
if (!this.$refs || !this.$refs.tooltip) {
return
}
this.$refs.tooltip.setAttribute('data-show', '')
this.popper.update()
document.addEventListener('click', this.clickHandler)
},
hidePopper() {
if (!this.horizontal) {
return
}
document.removeEventListener('click', this.clickHandler)
this.$refs.tooltip.removeAttribute('data-show')
},
showTooltip() {
return {
'data-tooltip-position': 'top-right',
'data-tooltip-size': 'medium',
role: 'tooltip'
}
},
checked(item) {
return this.selected
? this.selected.find((x) => x === item.key) !== undefined
: false
},
clearSelections() {
this.$emit('input', [])
const event = {
name: this.aggregation.name,
value: [],
last: {
name: this.aggregation.name,
action: 'remove-all'
}
}
this.$emit('change', event)
},
clear() {
this.search = ''
this.$nextTick(() => this.$refs.search.focus())
},
expand() {
this.state = 'expanded'
this.$nextTick(() => this.$refs.search.focus())
},
collapse() {
this.state = 'collapsed'
this.search = ''
},
onClick(item) {
// click event is relevant only for box
if (this.isBox) {
this.onChange(item)
}
},
uncheckParent(item, selected) {
if (!item.parent) {
return selected
}
selected = selected.filter((x) => x !== item.parent.key)
this.$store.dispatch(
'search/updateSelections',
{
name: this.aggregation.name,
label: this.aggregation.label,
key: item.parent.key,
value: item.parent.value,
action: 'remove'
},
{ root: true }
)
return selected
},
uncheckChildren(item, selected) {
if (!item.children) {
return selected
}
for (const child of item.children) {
selected = selected.filter((x) => x !== child.key)
this.$store.dispatch(
'search/updateSelections',
{
name: this.aggregation.name,
label: this.aggregation.label,
key: child.key,
value: child.value,
action: 'remove'
},
{ root: true }
)
}
return selected
},
onChange(item) {
if (item.url && this.display.link == 'filters') {
if (this.$queryState && this.$queryState.stringifyFilters) {
const params = this.$queryState.stringifyFilters(this.filters)
const conn = params ? (item.url.includes('?') ? '&' : '?') : ''
const url = `${item.url}${conn}${params}`
document.location.href = url
return
}
}
if (item.url) {
document.location.href = item.url
return
}
if (!this.selected) {
return
}
const remove = this.checked(item)
let selected = this.selected
if (!remove) {
selected = this.uncheckParent(item, selected)
selected = this.uncheckChildren(item, selected)
}
const result = remove
? selected.filter((x) => x !== item.key)
: this.isSingle
? [item.key]
: [...selected, item.key]
this.$emit('input', result)
const event = {
name: this.aggregation.name,
value: result,
last: {
name: this.aggregation.name,
label: this.aggregation.label,
key: item.key,
value: item.value,
action: remove ? 'remove' : this.isSingle ? 'replace' : 'add'
}
}
this.$emit('change', event)
}
},
mounted() {
this.setupPopper()
},
beforeDestroy() {
if (!this.popper) {
return
}
this.popper.destroy()
}
}