mirror of
https://gitlab.com/bramw/baserow.git
synced 2025-04-12 16:28:06 +00:00
138 lines
3.9 KiB
Vue
138 lines
3.9 KiB
Vue
<template>
|
|
<div class="grid-view-column" style="width: 200px;" @click="select($event)">
|
|
<component
|
|
:is="getFieldComponent(field.type)"
|
|
ref="column"
|
|
:field="field"
|
|
:value="row['field_' + field.id]"
|
|
:selected="selected"
|
|
@update="update"
|
|
/>
|
|
</div>
|
|
</template>
|
|
|
|
<script>
|
|
import { isElement } from '@baserow/modules/core/utils/dom'
|
|
import { notifyIf } from '@baserow/modules/core/utils/error'
|
|
|
|
export default {
|
|
name: 'GridViewField',
|
|
props: {
|
|
table: {
|
|
type: Object,
|
|
required: true,
|
|
},
|
|
field: {
|
|
type: Object,
|
|
required: true,
|
|
},
|
|
row: {
|
|
type: Object,
|
|
required: true,
|
|
},
|
|
},
|
|
data() {
|
|
return {
|
|
/**
|
|
* Indicates whether the field is selected.
|
|
*/
|
|
selected: false,
|
|
/**
|
|
* Timestamp of the last the time the user clicked on the field. We need this to
|
|
* check if it was double clicked.
|
|
*/
|
|
clickTimestamp: null,
|
|
}
|
|
},
|
|
/**
|
|
* Because the component can be destroyed if it moves out of the viewport we might
|
|
* need to take some action if the the component is in a selected state.
|
|
*/
|
|
beforeDestroy() {
|
|
if (this.selected) {
|
|
this.unselect()
|
|
}
|
|
},
|
|
methods: {
|
|
getFieldComponent(type) {
|
|
return this.$registry.get('field', type).getGridViewFieldComponent()
|
|
},
|
|
/**
|
|
* If the grid field component emits an update event this method will be called
|
|
* which will actually update the value via the store.
|
|
*/
|
|
update(value, oldValue) {
|
|
this.$store
|
|
.dispatch('view/grid/updateValue', {
|
|
table: this.table,
|
|
row: this.row,
|
|
field: this.field,
|
|
value,
|
|
oldValue,
|
|
})
|
|
.catch((error) => {
|
|
notifyIf(error, 'column')
|
|
})
|
|
.then(() => {
|
|
this.$forceUpdate()
|
|
})
|
|
|
|
// This is needed because in some cases we do have a value yet, so a watcher of
|
|
// the value is not guaranteed. This will make sure the component shows the
|
|
// latest value.
|
|
this.$forceUpdate()
|
|
},
|
|
/**
|
|
* Method that is called when a user clicks on the grid field. It wil
|
|
* @TODO improve speed somehow, maybe with the fastclick library.
|
|
*/
|
|
select(event) {
|
|
const timestamp = new Date().getTime()
|
|
|
|
if (this.selected) {
|
|
// If the field is already selected we will check if the click is a doubleclick
|
|
// if it was within 200 ms. The double click event can be useful for components
|
|
// because they might want to change the editing state.
|
|
if (
|
|
this.clickTimestamp !== null &&
|
|
timestamp - this.clickTimestamp < 200
|
|
) {
|
|
this.$refs.column.doubleClick()
|
|
}
|
|
} else {
|
|
// If the field is not yet selected we can change the state to selected.
|
|
this.selected = true
|
|
this.$nextTick(() => {
|
|
// Call the select method on the next tick because we want to wait for all
|
|
// changes to have rendered.
|
|
this.$refs.column.select()
|
|
})
|
|
|
|
// Register a body click event listener so that we can detect if a user has
|
|
// clicked outside the field. If that happens we want to unselect the field and
|
|
// possibly save the value.
|
|
this.$el.clickOutsideEvent = (event) => {
|
|
if (
|
|
// Check if the column is still selected.
|
|
this.selected &&
|
|
// If the click was outside the column element.
|
|
!isElement(this.$el, event.target)
|
|
) {
|
|
this.unselect()
|
|
}
|
|
}
|
|
document.body.addEventListener('click', this.$el.clickOutsideEvent)
|
|
}
|
|
|
|
this.clickTimestamp = timestamp
|
|
},
|
|
unselect() {
|
|
this.$refs.column.beforeUnSelect()
|
|
this.$nextTick(() => {
|
|
this.selected = false
|
|
})
|
|
document.body.removeEventListener('click', this.$el.clickOutsideEvent)
|
|
},
|
|
},
|
|
}
|
|
</script>
|