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/SimpleGrid.vue
2024-07-25 13:14:50 +00:00

301 lines
8.4 KiB
Vue

<template>
<div
v-scroll="scroll"
class="simple-grid"
:class="{
'simple-grid--full-height': fullHeight,
'simple-grid--with-footer': withFooter,
'simple-grid--border': border,
}"
>
<div
v-if="fixedFields.length > 0 || showRowId"
ref="left"
class="simple-grid__left"
>
<div class="simple-grid__head">
<div
v-if="showRowId"
class="simple-grid__field simple-grid__field--first"
></div>
<div
v-for="field in fixedFields"
:key="field.id"
class="simple-grid__field"
>
<i
class="simple-grid__field-icon"
:class="fieldTypes[field.type].iconClass"
></i>
{{ field.name }}
</div>
</div>
<div class="simple-grid__body">
<div
v-for="row in rows"
:key="row.id"
class="simple-grid__row"
:class="{
'simple-grid__row--hover':
showHoveredRow && currentHoveredRow === row.id,
'simple-grid__row--disabled':
!multiple && selectedRows.includes(row.id),
'simple-grid__row--checked':
multiple && selectedRows.includes(row.id),
}"
@click="$emit('row-click', row)"
@mouseover="currentHoveredRow = row.id"
@mouseleave="currentHoveredRow = null"
>
<div
v-if="showRowId"
class="simple-grid__cell simple-grid__cell--first"
>
{{ row.id }}
<div
v-if="multiple"
v-show="
currentHoveredRow === row.id || selectedRows.includes(row.id)
"
class="simple-grid__cell-checkbox"
>
<Checkbox :checked="selectedRows.includes(row.id)"></Checkbox>
</div>
</div>
<div
v-for="field in fixedFields"
:key="field.id"
class="simple-grid__cell"
>
<SimpleGridField :field="field" :row="row" />
</div>
</div>
<div
v-if="canAddRow"
class="simple-grid__row"
:class="{
'simple-grid__row--hover': showHoveredRow && addRowHover,
}"
@mouseover="addRowHover = true"
@mouseleave="addRowHover = false"
@click="$emit('add-row')"
>
<a
class="simple-grid__cell simple-grid__cell--single simple-grid__add-row"
>
<i class="iconoir-plus" />
</a>
</div>
<div v-if="withFooter" class="simple-grid__foot">
<slot name="footLeft"></slot>
</div>
</div>
</div>
<div class="simple-grid__right-scrollbar-wrapper">
<Scrollbars
ref="scrollbars"
horizontal="getHorizontalScrollbarElement"
@horizontal="horizontalScroll"
></Scrollbars>
<div ref="right" class="simple-grid__right-wrapper">
<div class="simple-grid__right">
<div class="simple-grid__head">
<div
v-for="field in fields"
:key="field.id"
class="simple-grid__field"
>
<i
class="simple-grid__field-icon"
:class="fieldTypes[field.type].iconClass"
></i>
{{ field.name }}
</div>
</div>
<div class="simple-grid__body">
<div
v-for="row in rows"
:key="row.id"
class="simple-grid__row"
:class="{
'simple-grid__row--hover':
showHoveredRow && currentHoveredRow === row.id,
'simple-grid__row--disabled':
!multiple && selectedRows.includes(row.id),
'simple-grid__row--checked':
multiple && selectedRows.includes(row.id),
}"
@click="$emit('row-click', row)"
@mouseover="currentHoveredRow = row.id"
@mouseleave="currentHoveredRow = null"
>
<div
v-for="field in fields"
:key="field.id"
class="simple-grid__cell"
>
<SimpleGridField :field="field" :row="row" />
</div>
</div>
<div
v-if="canAddRow"
class="simple-grid__row"
:class="{
'simple-grid__row--hover': showHoveredRow && addRowHover,
}"
@mouseover="addRowHover = true"
@mouseleave="addRowHover = false"
@click="$emit('add-row')"
>
<div class="simple-grid__cell simple-grid__cell--single"></div>
</div>
<div v-if="withFooter" class="simple-grid__foot"></div>
</div>
</div>
</div>
<div v-if="withFooter" class="simple-grid__right-wrapper-footer"></div>
</div>
</div>
</template>
<script>
import SimpleGridField from './SimpleGridField'
import _ from 'lodash'
export default {
name: 'SimpleGrid',
components: { SimpleGridField },
props: {
rows: {
type: Array,
required: true,
},
fixedFields: {
type: Array,
required: false,
default: () => [],
},
fields: {
type: Array,
required: true,
},
selectedRows: {
type: Array,
required: false,
default: () => [],
},
showHoveredRow: {
type: Boolean,
required: false,
default: false,
},
canAddRow: {
type: Boolean,
required: false,
default: false,
},
showRowId: {
type: Boolean,
required: false,
default: false,
},
fullHeight: {
type: Boolean,
required: false,
default: false,
},
withFooter: {
type: Boolean,
required: false,
default: false,
},
border: {
type: Boolean,
required: false,
default: false,
},
multiple: {
type: Boolean,
required: false,
default: false,
},
},
data() {
return { addRowHover: false, currentHoveredRow: null }
},
computed: {
fieldTypes() {
return this.$registry.getAll('field')
},
},
mounted() {
const keydownEvent = (event) => {
if (
// If we allow row hovering, we also want to allow keyboard navigation.
this.showHoveredRow &&
// Check if the user has hit either of the keys we care about. If not,
// ignore.
(event.key === 'ArrowUp' || event.key === 'ArrowDown')
) {
// Prevent scrolling up and down while pressing the up and down key.
event.stopPropagation()
event.preventDefault()
this.handleUpAndDownArrowPress(event)
}
// Allow the Enter key to select the value that is currently being hovered
// over.
if (
this.showHoveredRow &&
this.currentHoveredRow &&
event.key === 'Enter'
) {
event.preventDefault()
event.stopPropagation()
const row = this.rows.find((row) => row.id === this.currentHoveredRow)
if (row) {
this.$emit('row-click', row)
}
}
}
document.body.addEventListener('keydown', keydownEvent)
this.$once('hide', () => {
document.body.removeEventListener('keydown', keydownEvent)
})
},
methods: {
getHorizontalScrollbarElement() {
return this.$refs.right
},
/**
* Event that is called when the users does any form of scrolling on the whole grid
* surface.
*/
scroll(pixelY, pixelX) {
const left = this.$refs.right.scrollLeft + pixelX
this.horizontalScroll(left)
this.$refs.scrollbars.update()
return pixelY !== 0
},
horizontalScroll(left) {
this.$refs.right.scrollLeft = left
},
handleUpAndDownArrowPress(event) {
const isArrowUp = event.key === 'ArrowUp'
let index = this.rows.findIndex((item) =>
_.isEqual(item.id, this.currentHoveredRow)
)
if (index === -1) {
// Selects the first or last row if no row was hovered before.
index = isArrowUp ? this.rows.length - 1 : 0
} else {
// Selects the previous or next row if a row was in hover state before.
index = isArrowUp ? index - 1 : index + 1
}
const next = this.rows[index]
if (next) {
this.currentHoveredRow = next.id
}
},
},
}
</script>