1
0
mirror of https://gitlab.com/bramw/baserow.git synced 2024-11-24 16:36:46 +00:00
bramw_baserow/web-frontend/modules/builder/mixins/collectionElement.js

184 lines
5.1 KiB
JavaScript

import { mapActions, mapGetters } from 'vuex'
import { DataProviderType } from '@baserow/modules/core/dataProviderTypes'
import { notifyIf } from '@baserow/modules/core/utils/error'
import _ from 'lodash'
export default {
data() {
return {
adhocFilters: undefined,
adhocSortings: undefined,
adhocSearch: undefined,
currentOffset: 0,
errorNotified: false,
resetTimeout: null,
contentFetchEnabled: true,
}
},
computed: {
...mapGetters({
getLoading: 'elementContent/getLoading',
getHasMorePage: 'elementContent/getHasMorePage',
getElementContent: 'elementContent/getElementContent',
getReset: 'elementContent/getReset',
getPagesDataSourceById: 'dataSource/getPagesDataSourceById',
getSharedPage: 'page/getSharedPage',
}),
reset() {
return this.getReset(this.element)
},
sharedPage() {
return this.getSharedPage(this.builder)
},
dataSource() {
if (!this.element.data_source_id) {
return null
}
const pages = [this.page, this.sharedPage]
return this.getPagesDataSourceById(pages, this.element.data_source_id)
},
dataSourceType() {
if (!this.dataSource) {
return null
}
return this.$registry.get('service', this.dataSource.type)
},
elementContent() {
return this.getElementContent(this.element, this.applicationContext)
},
hasMorePage() {
return this.getHasMorePage(this.element)
},
contentLoading() {
return (
this.$fetchState.pending ||
(this.getLoading(this.element) && !this.elementIsInError)
)
},
dispatchContext() {
return DataProviderType.getAllDataSourceDispatchContext(
this.$registry.getAll('builderDataProvider'),
this.applicationContext
)
},
elementHasSourceOfData() {
return this.elementType.hasSourceOfData(this.element)
},
adhocRefinements() {
return {
filters: this.adhocFilters,
sortings: this.adhocSortings,
search: this.adhocSearch,
}
},
elementIsInError() {
return this.elementType.isInError({
page: this.page,
element: this.element,
builder: this.builder,
})
},
},
watch: {
reset() {
this.debouncedReset()
},
'element.schema_property'(newValue, oldValue) {
if (newValue) {
this.debouncedReset()
}
},
'element.data_source_id'() {
this.debouncedReset()
},
'element.items_per_page'() {
this.debouncedReset()
},
dispatchContext: {
handler(newValue, prevValue) {
if (!_.isEqual(newValue, prevValue)) {
this.debouncedReset()
}
},
deep: true,
},
adhocRefinements: {
handler(newValue, prevValue) {
if (!_.isEqual(newValue, prevValue)) {
this.debouncedReset()
}
},
},
},
async fetch() {
if (!this.elementIsInError && this.elementType.fetchAtLoad) {
await this.fetchContent([0, this.element.items_per_page], true)
}
},
methods: {
...mapActions({
fetchElementContent: 'elementContent/fetchElementContent',
}),
debouncedReset() {
clearTimeout(this.resetTimeout)
this.resetTimeout = setTimeout(() => {
this.contentFetchEnabled = true
this.errorNotified = false
this.currentOffset = 0
this.loadMore(true)
}, 500)
},
async fetchContent(range, replace) {
if (!this.canFetch()) {
return
}
try {
await this.fetchElementContent({
page: this.page,
element: this.element,
dataSource: this.dataSource,
data: this.dispatchContext,
range,
filters: this.adhocRefinements.filters,
sortings: this.adhocRefinements.sortings,
search: this.adhocRefinements.search,
mode: this.applicationContext.mode,
replace,
})
this.currentOffset += this.element.items_per_page
} catch (error) {
// Handle the HTTP error if needed
this.onContentFetchError(error)
// We need to only launch one toast error message per element,
// not one per element fetch, or we can end up with many error
// toasts per element sharing a datasource.
if (!this.errorNotified) {
this.errorNotified = true
notifyIf(error)
}
}
},
async loadMore(replace = false) {
await this.fetchContent(
[this.currentOffset, this.element.items_per_page],
replace
)
},
/** Overrides this if you want to prevent data fetching */
canFetch() {
return this.contentFetchEnabled
},
/** Override this if you want to handle content fetch errors */
onContentFetchError(error) {
// If the request failed without reaching the server, `error.response`
// will be `undefined`, so we need to check that before checking the
// HTTP status code
if (error.response && [400, 404].includes(error.response.status)) {
this.contentFetchEnabled = false
}
},
},
}