1
0
mirror of https://gitlab.com/bramw/baserow.git synced 2024-11-25 00:46:46 +00:00
bramw_baserow/web-frontend/modules/database/components/view/grid/GridViewCell.vue

239 lines
8.1 KiB
Vue

<template functional>
<!--
The :key property must be set here because it makes sure that the child components
are not re-rendered when functional component changes position in the DOM.
-->
<div
:key="
'row-field-cell-' +
props.row._.persistentId +
'-' +
props.field.id.toString()
"
ref="wrapper"
class="grid-view__column"
:class="{
'grid-view__column--matches-search':
props.row._.matchSearch &&
props.row._.fieldSearchMatches.includes(props.field.id.toString()),
'grid-view__column--multi-select': props.multiSelectPosition.selected,
'grid-view__column--multi-select-top': props.multiSelectPosition.top,
'grid-view__column--multi-select-right': props.multiSelectPosition.right,
'grid-view__column--multi-select-left': props.multiSelectPosition.left,
'grid-view__column--multi-select-bottom':
props.multiSelectPosition.bottom,
'grid-view__column--group-end': props.groupEnd,
}"
:style="data.style"
@click.exact="$options.methods.select($event, parent, props.field.id)"
@mousedown.left="$options.methods.cellMouseDownLeft($event, listeners)"
@mouseover="$options.methods.cellMouseover($event, listeners)"
@mouseup.left="$options.methods.cellMouseUpLeft($event, listeners)"
@click.shift.exact="$options.methods.cellShiftClick($event, listeners)"
>
<component
:is="$options.methods.getFunctionalComponent(parent, props)"
v-if="
!parent.isCellSelected(props.field.id) &&
// It could happen that the selected component needs to be alive in order to
// finish a task. This is for example the case when still uploading files. The
// alive list contains the field ids that must be kept alive. Once finished it
// is removed from that list.
!parent.alive.includes(props.field.id)
"
ref="unselectedField"
:workspace-id="props.workspaceId"
:field="props.field"
:value="props.row['field_' + props.field.id]"
:state="props.state"
:read-only="props.readOnly"
:store-prefix="props.storePrefix"
/>
<component
:is="$options.methods.getComponent(parent, props)"
v-else
ref="selectedField"
:workspace-id="props.workspaceId"
:field="props.field"
:value="props.row['field_' + props.field.id]"
:selected="parent.isCellSelected(props.field.id)"
:store-prefix="props.storePrefix"
:read-only="props.readOnly"
:row="props.row"
:all-fields-in-table="props.allFieldsInTable"
@update="(...args) => $options.methods.update(listeners, props, ...args)"
@paste="(...args) => $options.methods.paste(listeners, props, ...args)"
@edit="(...args) => $options.methods.edit(listeners, props, ...args)"
@refresh-row="$options.methods.refreshRow(listeners, props)"
@unselect="$options.methods.unselect(parent, props)"
@selected="$options.methods.selected(listeners, props, $event)"
@unselected="$options.methods.unselected(listeners, props, $event)"
@selectPrevious="
$options.methods.selectNext(listeners, props, 'previous')
"
@selectNext="$options.methods.selectNext(listeners, props, 'next')"
@selectAbove="$options.methods.selectNext(listeners, props, 'above')"
@selectBelow="$options.methods.selectNext(listeners, props, 'below')"
@add-row-after="$options.methods.addRowAfter(listeners, props)"
@add-keep-alive="parent.addKeepAlive(props.field.id)"
@remove-keep-alive="parent.removeKeepAlive(props.field.id)"
@edit-modal="$options.methods.editModal(listeners)"
/>
</div>
</template>
<script>
export default {
methods: {
/**
* Returns the functional component related to the field type. Functional
* components are much faster then regular components because they don't have a
* state. Unselected cells renders this functional component to improve speed
* because that will give the user a better experience. Once the user clicks on the
* cell, it is replaced with a the real field component which has the ability to
* change the data.
*/
getFunctionalComponent(parent, props) {
return parent.$registry
.get('field', props.field.type)
.getFunctionalGridViewFieldComponent(props.field)
},
/**
* Returns the component related to the field type. This component will only be
* rendered when the user has selected the cell. It will be used to edit the value.
*/
getComponent(parent, props) {
return parent.$registry
.get('field', props.field.type)
.getGridViewFieldComponent(props.field)
},
/**
* If the grid field component emits an update event then this method will be
* called which will add forward the event to the parent components which will
* eventually update the value.
*/
update(listeners, props, value, oldValue) {
if (listeners.update) {
listeners.update({
row: props.row,
field: props.field,
value,
oldValue,
})
}
},
paste(listeners, props, event) {
if (listeners.paste) {
listeners.paste({
data: event,
row: props.row,
field: props.field,
})
}
},
/**
* If the grid field components emits an edit event then the user has changed the
* value without saving it yet. This is for example used to check in real time if
* the value still matches the filters.
*/
edit(listeners, props, value, oldValue) {
if (listeners.edit) {
listeners.edit({
row: props.row,
field: props.field,
value,
oldValue,
})
}
},
/**
* When the user clicks on the cell it must be selected. We can only change that
* state by calling the parent `selectCell` method.
*/
select(event, parent, fieldId) {
event.preventFieldCellUnselect = true
parent.selectCell(fieldId)
},
cellMouseDownLeft(event, listeners) {
if (listeners['cell-mousedown-left'] && !event.shiftKey) {
listeners['cell-mousedown-left']()
}
},
cellMouseover(event, listeners) {
if (listeners['cell-mouseover']) {
listeners['cell-mouseover']()
}
},
cellMouseUpLeft(event, listeners) {
if (listeners['cell-mouseup-left']) {
listeners['cell-mouseup-left']()
}
},
cellShiftClick(event, listeners) {
if (listeners['cell-shift-click']) {
listeners['cell-shift-click']()
}
},
/**
* Called when the cell field type component needs to cell to be unselected.
*/
unselect(parent, props) {
if (parent.isCellSelected(props.field.id)) {
parent.selectCell(-1, -1)
}
},
/**
* Called after the field type component is selected.
*/
selected(listeners, props, event) {
if (listeners.selected) {
event.row = props.row
event.field = props.field
listeners.selected(event)
}
},
/**
* Called after the field type component is unselected.
*/
unselected(listeners, props, event) {
if (listeners.unselected) {
event.row = props.row
event.field = props.field
listeners.unselected(event)
}
},
/**
* Called when the field type component want to select to next cell. This for
* example happens when the user presses an arrow key.
*/
selectNext(listeners, props, direction) {
if (listeners['select-next']) {
listeners['select-next']({
row: props.row,
field: props.field,
direction,
})
}
},
/**
* Emits an event that creates a row directly after this row.
*/
addRowAfter(listeners, props) {
if (listeners['add-row-after']) {
listeners['add-row-after'](props.row)
}
},
editModal(listeners) {
if (listeners['edit-modal']) {
listeners['edit-modal']()
}
},
refreshRow(listeners, props) {
if (listeners['refresh-row']) {
listeners['refresh-row'](props.row)
}
},
},
}
</script>