mirror of
https://gitlab.com/bramw/baserow.git
synced 2024-11-25 00:46:46 +00:00
301 lines
8.4 KiB
Vue
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>
|