mirror of
https://gitlab.com/bramw/baserow.git
synced 2025-04-12 16:28:06 +00:00
218 lines
5.8 KiB
Vue
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>
|