1
0
Fork 0
mirror of https://gitlab.com/bramw/baserow.git synced 2025-04-12 16:28:06 +00:00
bramw_baserow/web-frontend/modules/database/components/view/grid/GridViewRows.vue
2023-11-06 15:14:11 +00:00

218 lines
5.8 KiB
Vue

<template>
<div
class="grid-view__rows"
:style="{
transform: `translateY(${rowsTop}px) translateX(${leftOffset || 0}px)`,
}"
>
<GridViewRow
v-for="(row, index) in rows"
:key="`row-${row._.persistentId}`"
:groups="groupsPerRow[row.id]"
:view="view"
:workspace-id="workspaceId"
:row="row"
:rendered-fields="renderedFields"
:visible-fields="visibleFields"
:all-fields-in-table="allFieldsInTable"
:primary-field-is-sticky="primaryFieldIsSticky"
:field-widths="fieldWidths"
:include-row-details="includeRowDetails"
:include-group-by="includeGroupBy"
:decorations-by-place="decorationsByPlace"
:read-only="readOnly"
:can-drag="view.sortings.length === 0 && activeGroupBys.length === 0"
:store-prefix="storePrefix"
:row-identifier-type="view.row_identifier_type"
:count="index + rowsStartIndex + bufferStartIndex + 1"
v-on="$listeners"
/>
</div>
</template>
<script>
import { mapGetters } from 'vuex'
import GridViewRow from '@baserow/modules/database/components/view/grid/GridViewRow'
import gridViewHelpers from '@baserow/modules/database/mixins/gridViewHelpers'
export default {
name: 'GridViewRows',
components: { GridViewRow },
mixins: [gridViewHelpers],
props: {
/**
* The visible fields that are within the viewport. The other ones are not rendered
* for performance reasons.
*/
renderedFields: {
type: Array,
required: true,
},
/**
* The fields that are chosen to be visible within the view.
*/
visibleFields: {
type: Array,
required: true,
},
/**
* All the fields in the table, regardless of the visibility, or whether they
* should be rendered.
*/
allFieldsInTable: {
type: Array,
required: true,
},
decorationsByPlace: {
type: Object,
required: true,
},
leftOffset: {
type: Number,
required: false,
default: 0,
},
view: {
type: Object,
required: true,
},
includeRowDetails: {
type: Boolean,
required: false,
default: () => false,
},
includeGroupBy: {
type: Boolean,
required: false,
default: () => false,
},
readOnly: {
type: Boolean,
required: true,
},
workspaceId: {
type: Number,
required: true,
},
primaryFieldIsSticky: {
type: Boolean,
required: false,
default: () => true,
},
},
computed: {
fieldWidths() {
const fieldWidths = {}
this.visibleFields.forEach((field) => {
fieldWidths[field.id] = this.getFieldWidth(field.id)
})
return fieldWidths
},
/**
* This computed property prepares an array with clear instructions on the groups
* for each row. It will hold data whether the row is the start of a group, or the
* end, and for which group that is.
*
* We're calculating this for all the rows in the buffer because that way we can
* immediately render the correct borders of the rows, even if the user is
* scrolling fast through them.
*
* It returns a structure like:
*
* {
* [rowId]: [
* {
* id: groupById,
* start: false,
* end: true,
* groupBy: {}
* }
* ]
* }
*/
groupsPerRow() {
const groupBys = this.activeGroupBys
const rows = this.allRows
const groups = {}
const fieldTypeMap = {}
const fieldMap = {}
rows.forEach((row, index) => {
const previousRow = rows[index - 1]
const nextRow = rows[index + 1]
let lastGroupStart = false
let lastGroupEnd = false
const startEndPerGroup = groupBys.map((groupBy) => {
let start = false // The start of a group based on the group by value.
let end = false // The end of a group based on the group by value.
let fieldType = fieldTypeMap[groupBy.field]
let field = fieldMap[groupBy.field]
if (fieldType === undefined) {
field = this.allFieldsInTable.find((f) => f.id === groupBy.field)
fieldType = this.$registry.get('field', field.type)
fieldMap[groupBy.field] = field
fieldTypeMap[groupBy.field] = fieldType
}
if (
previousRow === undefined ||
!fieldType.isEqual(
field,
previousRow[`field_${groupBy.field}`],
row[`field_${groupBy.field}`]
) ||
lastGroupStart
) {
start = true
}
if (
nextRow === undefined ||
!fieldType.isEqual(
field,
nextRow[`field_${groupBy.field}`],
row[`field_${groupBy.field}`]
) ||
lastGroupEnd
) {
end = true
}
lastGroupStart = start
lastGroupEnd = end
return {
id: groupBy.id,
start,
end,
groupBy,
}
})
groups[row.id] = startEndPerGroup
})
return groups
},
},
beforeCreate() {
this.$options.computed = {
...(this.$options.computed || {}),
...mapGetters({
rows: this.$options.propsData.storePrefix + 'view/grid/getRows',
allRows: this.$options.propsData.storePrefix + 'view/grid/getAllRows',
rowsTop: this.$options.propsData.storePrefix + 'view/grid/getRowsTop',
rowsStartIndex:
this.$options.propsData.storePrefix + 'view/grid/getRowsStartIndex',
bufferStartIndex:
this.$options.propsData.storePrefix + 'view/grid/getBufferStartIndex',
activeGroupBys:
this.$options.propsData.storePrefix + 'view/grid/getActiveGroupBys',
}),
}
},
}
</script>