pleroma-fe/src/components/list/list.js
2026-06-08 04:13:17 +03:00

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