mirror of
https://gitlab.com/bramw/baserow.git
synced 2025-04-15 17:44:12 +00:00
687 lines
22 KiB
Vue
687 lines
22 KiB
Vue
<template>
|
|
<div v-scroll="scroll" class="grid-view">
|
|
<Scrollbars
|
|
ref="scrollbars"
|
|
horizontal="getHorizontalScrollbarElement"
|
|
vertical="getVerticalScrollbarElement"
|
|
:style="{ left: leftWidth + 'px' }"
|
|
@vertical="verticalScroll"
|
|
@horizontal="horizontalScroll"
|
|
></Scrollbars>
|
|
<GridViewSection
|
|
ref="left"
|
|
class="grid-view__left"
|
|
:fields="leftFields"
|
|
:table="table"
|
|
:view="view"
|
|
:include-field-width-handles="false"
|
|
:include-row-details="true"
|
|
:read-only="readOnly"
|
|
:store-prefix="storePrefix"
|
|
:style="{ width: leftWidth + 'px' }"
|
|
@refresh="$emit('refresh', $event)"
|
|
@row-hover="setRowHover($event.row, $event.value)"
|
|
@row-context="showRowContext($event.event, $event.row)"
|
|
@row-dragging="rowDragStart"
|
|
@add-row="addRow()"
|
|
@update="updateValue"
|
|
@edit="editValue"
|
|
@selected="selectedCell($event)"
|
|
@unselected="unselectedCell($event)"
|
|
@select-next="selectNextCell($event)"
|
|
@edit-modal="$refs.rowEditModal.show($event.id)"
|
|
>
|
|
<template #foot>
|
|
<div class="grid-view__column" :style="{ width: leftWidth + 'px' }">
|
|
<div class="grid-view__foot-info">{{ count }} rows</div>
|
|
</div>
|
|
</template>
|
|
</GridViewSection>
|
|
<div
|
|
ref="divider"
|
|
class="grid-view__divider"
|
|
:style="{ left: leftWidth + 'px' }"
|
|
></div>
|
|
<GridViewFieldWidthHandle
|
|
class="grid-view__divider-width"
|
|
:style="{ left: leftWidth + 'px' }"
|
|
:grid="view"
|
|
:field="primary"
|
|
:width="leftFieldsWidth"
|
|
:store-prefix="storePrefix"
|
|
></GridViewFieldWidthHandle>
|
|
<GridViewSection
|
|
ref="right"
|
|
class="grid-view__right"
|
|
:fields="visibleFields"
|
|
:table="table"
|
|
:view="view"
|
|
:include-add-field="true"
|
|
:can-order-fields="true"
|
|
:read-only="readOnly"
|
|
:store-prefix="storePrefix"
|
|
:style="{ left: leftWidth + 'px' }"
|
|
@refresh="$emit('refresh', $event)"
|
|
@row-hover="setRowHover($event.row, $event.value)"
|
|
@row-context="showRowContext($event.event, $event.row)"
|
|
@add-row="addRow()"
|
|
@update="updateValue"
|
|
@edit="editValue"
|
|
@selected="selectedCell($event)"
|
|
@unselected="unselectedCell($event)"
|
|
@select-next="selectNextCell($event)"
|
|
@edit-modal="$refs.rowEditModal.show($event.id)"
|
|
@scroll="scroll($event.pixelY, $event.pixelX)"
|
|
></GridViewSection>
|
|
<GridViewRowDragging
|
|
ref="rowDragging"
|
|
:table="table"
|
|
:view="view"
|
|
:primary="primary"
|
|
:fields="visibleFields"
|
|
:store-prefix="storePrefix"
|
|
vertical="getVerticalScrollbarElement"
|
|
@scroll="scroll($event.pixelY, $event.pixelX)"
|
|
></GridViewRowDragging>
|
|
<Context ref="rowContext">
|
|
<ul class="context__menu">
|
|
<li v-if="!readOnly">
|
|
<a @click=";[addRow(selectedRow), $refs.rowContext.hide()]">
|
|
<i class="context__menu-icon fas fa-fw fa-arrow-up"></i>
|
|
Insert row above
|
|
</a>
|
|
</li>
|
|
<li v-if="!readOnly">
|
|
<a @click=";[addRowAfter(selectedRow), $refs.rowContext.hide()]">
|
|
<i class="context__menu-icon fas fa-fw fa-arrow-down"></i>
|
|
Insert row below
|
|
</a>
|
|
</li>
|
|
<li>
|
|
<a
|
|
@click="
|
|
;[
|
|
$refs.rowEditModal.show(selectedRow.id),
|
|
$refs.rowContext.hide(),
|
|
]
|
|
"
|
|
>
|
|
<i class="context__menu-icon fas fa-fw fa-expand"></i>
|
|
Enlarge row
|
|
</a>
|
|
</li>
|
|
<li v-if="!readOnly">
|
|
<a @click="deleteRow(selectedRow)">
|
|
<i class="context__menu-icon fas fa-fw fa-trash"></i>
|
|
Delete row
|
|
</a>
|
|
</li>
|
|
</ul>
|
|
</Context>
|
|
<RowEditModal
|
|
ref="rowEditModal"
|
|
:table="table"
|
|
:primary="primary"
|
|
:fields="fields"
|
|
:rows="allRows"
|
|
:read-only="readOnly"
|
|
@update="updateValue"
|
|
@hidden="rowEditModalHidden"
|
|
@field-updated="$emit('refresh', $event)"
|
|
@field-deleted="$emit('refresh')"
|
|
></RowEditModal>
|
|
</div>
|
|
</template>
|
|
|
|
<script>
|
|
import { mapGetters } from 'vuex'
|
|
|
|
import { notifyIf } from '@baserow/modules/core/utils/error'
|
|
import GridViewSection from '@baserow/modules/database/components/view/grid/GridViewSection'
|
|
import GridViewFieldWidthHandle from '@baserow/modules/database/components/view/grid/GridViewFieldWidthHandle'
|
|
import GridViewRowDragging from '@baserow/modules/database/components/view/grid/GridViewRowDragging'
|
|
import RowEditModal from '@baserow/modules/database/components/row/RowEditModal'
|
|
import gridViewHelpers from '@baserow/modules/database/mixins/gridViewHelpers'
|
|
import { GridViewType } from '@baserow/modules/database/viewTypes'
|
|
|
|
export default {
|
|
name: 'GridView',
|
|
components: {
|
|
GridViewSection,
|
|
GridViewFieldWidthHandle,
|
|
GridViewRowDragging,
|
|
RowEditModal,
|
|
},
|
|
mixins: [gridViewHelpers],
|
|
props: {
|
|
primary: {
|
|
type: Object,
|
|
required: true,
|
|
},
|
|
fields: {
|
|
type: Array,
|
|
required: true,
|
|
},
|
|
view: {
|
|
type: Object,
|
|
required: true,
|
|
},
|
|
table: {
|
|
type: Object,
|
|
required: true,
|
|
},
|
|
database: {
|
|
type: Object,
|
|
required: true,
|
|
},
|
|
readOnly: {
|
|
type: Boolean,
|
|
required: true,
|
|
},
|
|
},
|
|
data() {
|
|
return {
|
|
lastHoveredRow: null,
|
|
selectedRow: null,
|
|
}
|
|
},
|
|
computed: {
|
|
/**
|
|
* Returns only the visible fields in the correct order.
|
|
*/
|
|
visibleFields() {
|
|
return this.fields
|
|
.filter((field) => {
|
|
const exists = Object.prototype.hasOwnProperty.call(
|
|
this.fieldOptions,
|
|
field.id
|
|
)
|
|
return !exists || (exists && !this.fieldOptions[field.id].hidden)
|
|
})
|
|
.sort((a, b) => {
|
|
const orderA = this.fieldOptions[a.id]
|
|
? this.fieldOptions[a.id].order
|
|
: GridViewType.getMaxPossibleOrderValue()
|
|
const orderB = this.fieldOptions[b.id]
|
|
? this.fieldOptions[b.id].order
|
|
: GridViewType.getMaxPossibleOrderValue()
|
|
|
|
// First by order.
|
|
if (orderA > orderB) {
|
|
return 1
|
|
} else if (orderA < orderB) {
|
|
return -1
|
|
}
|
|
|
|
// Then by id.
|
|
if (a.id < b.id) {
|
|
return -1
|
|
} else if (a.id > b.id) {
|
|
return 1
|
|
} else {
|
|
return 0
|
|
}
|
|
})
|
|
},
|
|
leftFields() {
|
|
return [this.primary]
|
|
},
|
|
leftFieldsWidth() {
|
|
return this.leftFields.reduce(
|
|
(value, field) => this.getFieldWidth(field.id) + value,
|
|
0
|
|
)
|
|
},
|
|
leftWidth() {
|
|
return this.leftFieldsWidth + this.gridViewRowDetailsWidth
|
|
},
|
|
},
|
|
watch: {
|
|
fieldOptions: {
|
|
deep: true,
|
|
handler() {
|
|
// When the field options have changed, it could be that the width of the
|
|
// fields have changed and in that case we want to update the scrollbars.
|
|
this.fieldsUpdated()
|
|
},
|
|
},
|
|
fields() {
|
|
// When a field is added or removed, we want to update the scrollbars.
|
|
this.fieldsUpdated()
|
|
},
|
|
},
|
|
beforeCreate() {
|
|
this.$options.computed = {
|
|
...(this.$options.computed || {}),
|
|
...mapGetters({
|
|
allRows: this.$options.propsData.storePrefix + 'view/grid/getAllRows',
|
|
count: this.$options.propsData.storePrefix + 'view/grid/getCount',
|
|
}),
|
|
}
|
|
},
|
|
created() {
|
|
// When the grid view is created we want to update the scrollbars.
|
|
this.fieldsUpdated()
|
|
},
|
|
beforeMount() {
|
|
this.$bus.$on('field-deleted', this.fieldDeleted)
|
|
},
|
|
mounted() {
|
|
this.$el.resizeEvent = () => {
|
|
const height = this.$refs.left.$refs.body.clientHeight
|
|
this.$store.dispatch(
|
|
this.storePrefix + 'view/grid/setWindowHeight',
|
|
height
|
|
)
|
|
}
|
|
this.$el.resizeEvent()
|
|
window.addEventListener('resize', this.$el.resizeEvent)
|
|
},
|
|
beforeDestroy() {
|
|
window.removeEventListener('resize', this.$el.resizeEvent)
|
|
this.$bus.$off('field-deleted', this.fieldDeleted)
|
|
},
|
|
methods: {
|
|
/**
|
|
* When a field is deleted we need to check if that field was related to any
|
|
* filters or sortings. If that is the case then the view needs to be refreshed so
|
|
* we can see fresh results.
|
|
*/
|
|
fieldDeleted({ field }) {
|
|
const filterIndex = this.view.filters.findIndex((filter) => {
|
|
return filter.field === field.id
|
|
})
|
|
const sortIndex = this.view.sortings.findIndex((sort) => {
|
|
return sort.field === field.id
|
|
})
|
|
if (filterIndex > -1 || sortIndex > -1) {
|
|
this.$emit('refresh')
|
|
}
|
|
},
|
|
/**
|
|
* Is called when anything related to a field has changed and in that case we want
|
|
* to update the scrollbars.
|
|
*/
|
|
fieldsUpdated() {
|
|
const scrollbars = this.$refs.scrollbars
|
|
// Vue can sometimes trigger this via watch before the child component
|
|
// scrollbars has been created, check it exists and has the expected method
|
|
if (scrollbars && scrollbars.update) {
|
|
scrollbars.update()
|
|
}
|
|
},
|
|
/**
|
|
* Called when a cell value has been updated. This can for example happen via the
|
|
* row edit modal or when editing a cell directly in the grid.
|
|
*/
|
|
async updateValue({ field, row, value, oldValue }) {
|
|
try {
|
|
await this.$store.dispatch(
|
|
this.storePrefix + 'view/grid/updateRowValue',
|
|
{
|
|
table: this.table,
|
|
view: this.view,
|
|
fields: this.fields,
|
|
primary: this.primary,
|
|
row,
|
|
field,
|
|
value,
|
|
oldValue,
|
|
}
|
|
)
|
|
} catch (error) {
|
|
notifyIf(error, 'field')
|
|
}
|
|
},
|
|
/**
|
|
* Called when a value is edited, but not yet saved. Here we can do a preliminary
|
|
* check to see if the values matches the filters.
|
|
*/
|
|
editValue({ field, row, value, oldValue }) {
|
|
const overrides = {}
|
|
overrides[`field_${field.id}`] = value
|
|
this.$store.dispatch(this.storePrefix + 'view/grid/onRowChange', {
|
|
view: this.view,
|
|
row,
|
|
fields: this.fields,
|
|
primary: this.primary,
|
|
overrides,
|
|
})
|
|
},
|
|
/**
|
|
* This method is called by the Scrollbars component and should return the element
|
|
* that handles the the horizontal scrolling.
|
|
*/
|
|
getHorizontalScrollbarElement() {
|
|
return this.$refs.right.$el
|
|
},
|
|
/**
|
|
* This method is called by the Scrollbars component and should return the element
|
|
* that handles the the vertical scrolling.
|
|
*/
|
|
getVerticalScrollbarElement() {
|
|
return this.$refs.right.$refs.body
|
|
},
|
|
/**
|
|
* Called when a user scrolls without using the scrollbar.
|
|
*/
|
|
scroll(pixelY, pixelX) {
|
|
const $rightBody = this.$refs.right.$refs.body
|
|
const $right = this.$refs.right.$el
|
|
|
|
const top = $rightBody.scrollTop + pixelY
|
|
const left = $right.scrollLeft + pixelX
|
|
|
|
this.verticalScroll(top)
|
|
this.horizontalScroll(left)
|
|
|
|
this.$refs.scrollbars.update()
|
|
},
|
|
/**
|
|
* Called when the user scrolls vertically. The scroll offset of both the left and
|
|
* right section must be updated and we want might need to fetch new rows which
|
|
* is handled by the grid view store.
|
|
*/
|
|
verticalScroll(top) {
|
|
this.$refs.left.$refs.body.scrollTop = top
|
|
this.$refs.right.$refs.body.scrollTop = top
|
|
|
|
this.$store.dispatch(
|
|
this.storePrefix + 'view/grid/fetchByScrollTopDelayed',
|
|
{
|
|
scrollTop: this.$refs.left.$refs.body.scrollTop,
|
|
fields: this.fields,
|
|
primary: this.primary,
|
|
}
|
|
)
|
|
},
|
|
/**
|
|
* Called when the user scrolls horizontally. If the user scrolls we might want to
|
|
* show a shadow next to the left section because that one has a fixed position.
|
|
*/
|
|
horizontalScroll(left) {
|
|
const $right = this.$refs.right.$el
|
|
const $divider = this.$refs.divider
|
|
const canScroll = $right.scrollWidth > $right.clientWidth
|
|
|
|
$divider.classList.toggle('shadow', canScroll && left > 0)
|
|
$right.scrollLeft = left
|
|
},
|
|
async addRow(before = null) {
|
|
try {
|
|
await this.$store.dispatch(
|
|
this.storePrefix + 'view/grid/createNewRow',
|
|
{
|
|
view: this.view,
|
|
table: this.table,
|
|
// We need a list of all fields including the primary one here.
|
|
fields: this.fields,
|
|
primary: this.primary,
|
|
values: {},
|
|
before,
|
|
}
|
|
)
|
|
} catch (error) {
|
|
notifyIf(error, 'row')
|
|
}
|
|
},
|
|
/**
|
|
* Because it is only possible to add a new row before another row, we have to
|
|
* figure out which row is below the given row and insert before that one. If the
|
|
* next row is not found, we can safely assume it is the last row and add it last.
|
|
*/
|
|
addRowAfter(row) {
|
|
const rows = this.$store.getters[
|
|
this.storePrefix + 'view/grid/getAllRows'
|
|
]
|
|
const index = rows.findIndex((r) => r.id === row.id)
|
|
let nextRow = null
|
|
|
|
if (index !== -1 && rows.length > index + 1) {
|
|
nextRow = rows[index + 1]
|
|
}
|
|
|
|
this.addRow(nextRow)
|
|
},
|
|
async deleteRow(row) {
|
|
try {
|
|
this.$refs.rowContext.hide()
|
|
// We need a small helper function that calculates the current scrollTop because
|
|
// the delete action will recalculate the visible scroll range and buffer.
|
|
const getScrollTop = () => this.$refs.left.$refs.body.scrollTop
|
|
await this.$store.dispatch(
|
|
this.storePrefix + 'view/grid/deleteExistingRow',
|
|
{
|
|
table: this.table,
|
|
view: this.view,
|
|
fields: this.fields,
|
|
primary: this.primary,
|
|
row,
|
|
getScrollTop,
|
|
}
|
|
)
|
|
} catch (error) {
|
|
notifyIf(error, 'row')
|
|
}
|
|
},
|
|
setRowHover(row, value) {
|
|
// Sometimes the mouseleave is not triggered, but because you can hover only one
|
|
// row at a time we can remember which was hovered last and set the hover state to
|
|
// false if it differs.
|
|
if (this.lastHoveredRow !== null && this.lastHoveredRow.id !== row.id) {
|
|
this.$store.dispatch(this.storePrefix + 'view/grid/setRowHover', {
|
|
row: this.lastHoveredRow,
|
|
value: false,
|
|
})
|
|
this.lastHoveredRow = null
|
|
}
|
|
|
|
this.$store.dispatch(this.storePrefix + 'view/grid/setRowHover', {
|
|
row,
|
|
value,
|
|
})
|
|
this.lastHoveredRow = row
|
|
},
|
|
showRowContext(event, row) {
|
|
this.selectedRow = row
|
|
this.$refs.rowContext.toggle(
|
|
{
|
|
top: event.clientY,
|
|
left: event.clientX,
|
|
},
|
|
'bottom',
|
|
'right',
|
|
0
|
|
)
|
|
},
|
|
/**
|
|
* Called when the user starts dragging the row. This will initiate the dragging
|
|
* effect and allows the user to move it to another position.
|
|
*/
|
|
rowDragStart({ event, row }) {
|
|
this.$refs.rowDragging.start(row, event)
|
|
},
|
|
/**
|
|
* When the modal hides and the related row does not match the filters anymore it
|
|
* must be deleted.
|
|
*/
|
|
rowEditModalHidden({ row }) {
|
|
// It could be that the row is not in the buffer anymore and in that case we also
|
|
// don't need to refresh the row.
|
|
if (
|
|
row === undefined ||
|
|
!Object.prototype.hasOwnProperty.call(row, 'id')
|
|
) {
|
|
return
|
|
}
|
|
|
|
this.$store.dispatch(this.storePrefix + 'view/grid/refreshRow', {
|
|
grid: this.view,
|
|
fields: this.fields,
|
|
primary: this.primary,
|
|
row,
|
|
getScrollTop: () => this.$refs.left.$refs.body.scrollTop,
|
|
})
|
|
},
|
|
/**
|
|
* When a cell is selected we want to make sure it is visible in the viewport, so
|
|
* we might need to scroll a little bit.
|
|
*/
|
|
selectedCell({ component, row, field }) {
|
|
const element = component.$el
|
|
const verticalContainer = this.$refs.right.$refs.body
|
|
const horizontalContainer = this.$refs.right.$el
|
|
|
|
const verticalContainerRect = verticalContainer.getBoundingClientRect()
|
|
const verticalContainerHeight = verticalContainer.clientHeight
|
|
|
|
const horizontalContainerRect = horizontalContainer.getBoundingClientRect()
|
|
const horizontalContainerWidth = horizontalContainer.clientWidth
|
|
|
|
const elementRect = element.getBoundingClientRect()
|
|
const elementTop = elementRect.top - verticalContainerRect.top
|
|
const elementBottom = elementRect.bottom - verticalContainerRect.top
|
|
const elementLeft = elementRect.left - horizontalContainerRect.left
|
|
const elementRight = elementRect.right - horizontalContainerRect.left
|
|
|
|
if (elementTop < 0) {
|
|
// If the field isn't visible in the viewport we need to scroll up in order
|
|
// to show it.
|
|
this.verticalScroll(elementTop + verticalContainer.scrollTop - 20)
|
|
this.$refs.scrollbars.updateVertical()
|
|
} else if (elementBottom > verticalContainerHeight) {
|
|
// If the field isn't visible in the viewport we need to scroll down in order
|
|
// to show it.
|
|
this.verticalScroll(
|
|
elementBottom +
|
|
verticalContainer.scrollTop -
|
|
verticalContainer.clientHeight +
|
|
20
|
|
)
|
|
this.$refs.scrollbars.updateVertical()
|
|
}
|
|
|
|
if (elementLeft < 0 && !field.primary) {
|
|
// If the field isn't visible in the viewport we need to scroll left in order
|
|
// to show it.
|
|
this.horizontalScroll(elementLeft + horizontalContainer.scrollLeft - 20)
|
|
this.$refs.scrollbars.updateHorizontal()
|
|
} else if (elementRight > horizontalContainerWidth && !field.primary) {
|
|
// If the field isn't visible in the viewport we need to scroll right in order
|
|
// to show it.
|
|
this.horizontalScroll(
|
|
elementRight +
|
|
horizontalContainer.scrollLeft -
|
|
horizontalContainer.clientWidth +
|
|
20
|
|
)
|
|
this.$refs.scrollbars.updateHorizontal()
|
|
}
|
|
|
|
this.$store.dispatch(this.storePrefix + 'view/grid/addRowSelectedBy', {
|
|
row,
|
|
field,
|
|
})
|
|
},
|
|
/**
|
|
* When a cell is unselected need to change the selected state of the row.
|
|
*/
|
|
unselectedCell({ row, field }) {
|
|
// We want to change selected state of the row on the next tick because if another
|
|
// cell within a row is selected, we want to wait for that selected state tot
|
|
// change. This will make sure that the row is stays selected.
|
|
this.$nextTick(() => {
|
|
this.$store.dispatch(
|
|
this.storePrefix + 'view/grid/removeRowSelectedBy',
|
|
{
|
|
grid: this.view,
|
|
fields: this.fields,
|
|
primary: this.primary,
|
|
row,
|
|
field,
|
|
getScrollTop: () => this.$refs.left.$refs.body.scrollTop,
|
|
}
|
|
)
|
|
})
|
|
},
|
|
/**
|
|
* This method is called when the next cell must be selected. This can for example
|
|
* happen when the tab key is pressed. It tries to find the next field based on the
|
|
* direction and will select that one.
|
|
*/
|
|
selectNextCell({ row, field, direction = 'next' }) {
|
|
const fields = this.visibleFields
|
|
const primary = this.primary
|
|
let nextFieldId = -1
|
|
let nextRowId = -1
|
|
|
|
if (direction === 'next' || direction === 'previous') {
|
|
nextRowId = row.id
|
|
|
|
if (field.primary && fields.length > 0 && direction === 'next') {
|
|
// If the currently selected field is the primary we can just select the
|
|
// first field of the fields if there are any.
|
|
nextFieldId = fields[0].id
|
|
} else if (!field.primary) {
|
|
// First we need to know which index the currently selected field has in the
|
|
// fields list.
|
|
const index = fields.findIndex((f) => f.id === field.id)
|
|
if (direction === 'next' && fields.length > index + 1) {
|
|
// If we want to select the next field we can just check if the next index
|
|
// exists and read the id from there.
|
|
nextFieldId = fields[index + 1].id
|
|
} else if (direction === 'previous' && index > 0) {
|
|
// If we want to select the previous field we can just check if aren't
|
|
// already the first and read the id from the previous.
|
|
nextFieldId = fields[index - 1].id
|
|
} else if (direction === 'previous' && index === 0) {
|
|
// If we want to select the previous field and we already are the first
|
|
// index we just select the primary.
|
|
nextFieldId = primary.id
|
|
}
|
|
}
|
|
}
|
|
|
|
if (direction === 'below' || direction === 'above') {
|
|
nextFieldId = field.id
|
|
const rows = this.$store.getters[
|
|
this.storePrefix + 'view/grid/getAllRows'
|
|
]
|
|
const index = rows.findIndex((r) => r.id === row.id)
|
|
|
|
if (index !== -1 && direction === 'below' && rows.length > index + 1) {
|
|
// If the next row index exists we can select the same field in the next row.
|
|
nextRowId = rows[index + 1].id
|
|
} else if (index !== -1 && direction === 'above' && index > 0) {
|
|
// If the previous row index exists we can select the same field in the
|
|
// previous row.
|
|
nextRowId = rows[index - 1].id
|
|
}
|
|
}
|
|
|
|
if (nextFieldId === -1 || nextRowId === -1) {
|
|
return
|
|
}
|
|
|
|
this.$store.dispatch(this.storePrefix + 'view/grid/setSelectedCell', {
|
|
rowId: nextRowId,
|
|
fieldId: nextFieldId,
|
|
})
|
|
},
|
|
/**
|
|
* This method is called from the parent component when the data in the view has
|
|
* been reset. This can for example happen when a user creates or updates a filter
|
|
* or wants to sort on a field.
|
|
*/
|
|
async refresh() {
|
|
await this.$store.dispatch(
|
|
this.storePrefix + 'view/grid/visibleByScrollTop',
|
|
this.$refs.right.$refs.body.scrollTop
|
|
)
|
|
this.$nextTick(() => {
|
|
this.fieldsUpdated()
|
|
})
|
|
},
|
|
},
|
|
}
|
|
</script>
|