152 lines
3.5 KiB
JavaScript
152 lines
3.5 KiB
JavaScript
import { isEmpty } from 'lodash'
|
|
|
|
import Checkbox from 'src/components/checkbox/checkbox.vue'
|
|
|
|
const List = {
|
|
props: {
|
|
boxOnly: {
|
|
type: Boolean,
|
|
default: false,
|
|
},
|
|
items: {
|
|
type: Array,
|
|
default: () => [],
|
|
},
|
|
fetchFunction: {
|
|
type: Function,
|
|
default: null,
|
|
},
|
|
itemsFunction: {
|
|
type: Function,
|
|
default: null,
|
|
},
|
|
getKey: {
|
|
type: Function,
|
|
default: (item) => item.id,
|
|
},
|
|
getClass: {
|
|
type: Function,
|
|
default: () => '',
|
|
},
|
|
nonInteractive: {
|
|
type: Boolean,
|
|
default: false,
|
|
},
|
|
scrollable: {
|
|
type: Boolean,
|
|
default: false,
|
|
},
|
|
selectable: {
|
|
type: Boolean,
|
|
default: false,
|
|
},
|
|
},
|
|
components: {
|
|
Checkbox,
|
|
},
|
|
data() {
|
|
return {
|
|
loading: false,
|
|
bottomedOut: false,
|
|
error: false,
|
|
dynamicItems: this.itemsFunction ? [] : null,
|
|
selected: [],
|
|
}
|
|
},
|
|
computed: {
|
|
allKeys() {
|
|
return this.actualItems.map(this.getKey)
|
|
},
|
|
filteredSelected() {
|
|
return this.allKeys.filter((key) => this.selected.indexOf(key) !== -1)
|
|
},
|
|
allSelected() {
|
|
return this.filteredSelected.length === this.actualItems.length
|
|
},
|
|
noneSelected() {
|
|
return this.filteredSelected.length === 0
|
|
},
|
|
someSelected() {
|
|
return !this.allSelected && !this.noneSelected
|
|
},
|
|
actualItems() {
|
|
return this.dynamicItems || this.actualItems
|
|
},
|
|
},
|
|
created() {
|
|
if (this.fetchFunction) {
|
|
window.addEventListener('scroll', this.scrollLoad)
|
|
|
|
if (this.dynamicItems.length === 0) {
|
|
this.fetchEntries()
|
|
}
|
|
}
|
|
},
|
|
unmounted() {
|
|
window.removeEventListener('scroll', this.scrollLoad)
|
|
},
|
|
methods: {
|
|
// Entries is not a computed because computed can't track the dynamic
|
|
// selector for changes and won't trigger after fetch.
|
|
updateEntries(newEntries) {
|
|
this.dynamicItems = this.itemsFunction(newEntries)
|
|
},
|
|
fetchEntries() {
|
|
if (!this.loading) {
|
|
this.loading = true
|
|
this.error = false
|
|
this.fetchFunction()
|
|
.then((newEntries) => {
|
|
this.loading = false
|
|
this.bottomedOut = isEmpty(newEntries)
|
|
return newEntries
|
|
})
|
|
.catch((error) => {
|
|
this.loading = false
|
|
this.error = error
|
|
})
|
|
.finally((newEntries) => {
|
|
this.updateEntries(newEntries)
|
|
})
|
|
}
|
|
},
|
|
scrollLoad(e) {
|
|
if (this.fetchFunction) {
|
|
const bodyBRect = document.body.getBoundingClientRect()
|
|
const height = Math.max(bodyBRect.height, -bodyBRect.y)
|
|
if (
|
|
this.loading === false &&
|
|
this.bottomedOut === false &&
|
|
this.$el.offsetHeight > 0 &&
|
|
window.innerHeight + window.pageYOffset >= height - 750
|
|
) {
|
|
this.fetchEntries()
|
|
}
|
|
}
|
|
},
|
|
isSelected(item) {
|
|
return this.filteredSelected.indexOf(this.getKey(item)) !== -1
|
|
},
|
|
toggle(checked, item) {
|
|
console.log('TOGGLE', checked, item)
|
|
const key = this.getKey(item)
|
|
const oldChecked = this.isSelected(key)
|
|
if (checked !== oldChecked) {
|
|
if (checked) {
|
|
this.selected.push(key)
|
|
} else {
|
|
this.selected.splice(this.selected.indexOf(key), 1)
|
|
}
|
|
}
|
|
},
|
|
toggleAll(value) {
|
|
if (value) {
|
|
this.selected = this.allKeys.slice(0)
|
|
} else {
|
|
this.selected = []
|
|
}
|
|
},
|
|
},
|
|
}
|
|
|
|
export default List
|