Skip to content

Commit df68bd9

Browse files
authored
fix (grid view): group by flickering at every change (baserow#5043)
* revert: undo unnecessary frontend changes from f6a7d30 Revert all frontend changes introduced in "fix: bug in public view with hidden group by" (f6a7d30). The backend changes from that commit are kept as they are the actual fix for the public view bug. The reverted frontend changes caused a regression where group bys would flicker (disappear and reappear) when changing the group by order, because activeGroupBys was being cleared at the start of every refresh. * fix: public view crash when group by is added or removed Add ViewType.forceViewRefresh() method that handles updating the view, fields, and (for grid views) activeGroupBys atomically during a force_view_refresh realtime event. This prevents components from accessing fields that have been removed or haven't been added yet. Also fix LinkRowFieldType.isEqual crashing with null/undefined values when rows have no linked items. * fix: inconsistency in counting hidden fields in grid view * fix issue deleting/restoring group bys
1 parent f6225db commit df68bd9

20 files changed

Lines changed: 167 additions & 531 deletions

File tree

web-frontend/justfile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -102,10 +102,10 @@ test *ARGS:
102102
ci-test:
103103
yarn test:coverage
104104

105-
# Update Jest snapshots
105+
# Update Vitest snapshots
106106
[group('3 - testing')]
107107
update-snapshots:
108-
yarn test --update
108+
EXTRA_VITEST_PARAMS="--update" yarn test
109109

110110
# =============================================================================
111111
# Development

web-frontend/modules/database/components/field/DuplicateFieldModal.vue

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,7 @@ export default {
122122
position: 'right',
123123
fromField: this.fromField,
124124
undoRedoActionGroupId: this.actionGroupId,
125+
visible: true,
125126
})
126127
this.onDuplicationEnd()
127128
}

web-frontend/modules/database/components/field/InsertFieldContext.vue

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ export default {
5959
position: this.position,
6060
fromField: this.fromField,
6161
undoRedoActionGroupId,
62+
visible: true, // when inserting a new field, it should always be visible
6263
})
6364
},
6465
toggle(ref, position) {

web-frontend/modules/database/components/view/grid/GridViewGroup.vue

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,12 @@
22
<div class="grid-view__group" v-bind="$attrs">
33
<div class="grid-view__group-cell">
44
<div class="grid-view__group-value">
5-
<component :is="groupByComponent" :field="field" :value="value" />
5+
<component
6+
:is="groupByComponent"
7+
v-if="groupByComponent"
8+
:field="field"
9+
:value="value"
10+
/>
611
</div>
712
<div v-if="count > 0" class="grid-view__group-count">
813
{{ count }}
@@ -19,8 +24,8 @@ export default {
1924
type: Object,
2025
required: true,
2126
},
22-
field: {
23-
type: Object,
27+
allFieldsInTable: {
28+
type: Array,
2429
required: true,
2530
},
2631
value: {
@@ -33,9 +38,24 @@ export default {
3338
},
3439
},
3540
computed: {
41+
field() {
42+
return this.getField(this.allFieldsInTable, this.groupBy)
43+
},
3644
groupByComponent() {
37-
const fieldType = this.$registry.get('field', this.field.type)
38-
return fieldType.getGroupByComponent(this.field)
45+
if (!this.field) {
46+
return null
47+
}
48+
return this.getGroupByComponent(this.field, this)
49+
},
50+
},
51+
methods: {
52+
getField(allFieldsInTable, groupBy) {
53+
const field = allFieldsInTable.find((f) => f.id === groupBy.field)
54+
return field
55+
},
56+
getGroupByComponent(field, parent) {
57+
const fieldType = parent.$registry.get('field', field.type)
58+
return fieldType.getGroupByComponent(field)
3959
},
4060
},
4161
}

web-frontend/modules/database/components/view/grid/GridViewGroups.vue

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
>
2121
<GridViewGroup
2222
:group-by="groupBy"
23-
:field="getGroupByField(groupBy)"
23+
:all-fields-in-table="allFieldsInTable"
2424
:value="groupSpan.value"
2525
:count="groupSpan.count"
2626
></GridViewGroup>
@@ -40,6 +40,14 @@ export default {
4040
components: { GridViewGroup },
4141
mixins: [gridViewHelpers],
4242
props: {
43+
/**
44+
* All the fields in the table, regardless of the visibility, or whether they
45+
* should be rendered.
46+
*/
47+
allFieldsInTable: {
48+
type: Array,
49+
required: true,
50+
},
4351
groupByValueSets: {
4452
type: Array,
4553
required: true,

web-frontend/modules/database/components/view/grid/GridViewHead.vue

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
<template>
22
<div class="grid-view__head">
33
<div
4-
v-for="{ groupBy, field } in activeGroupBysWithFields"
4+
v-for="groupBy in includeGroupBy ? activeGroupBys : []"
55
:key="'field-group-' + groupBy.field"
66
class="grid-view__head-group"
77
:style="{ width: groupBy.width + 'px' }"
8+
:set="field = $options.methods.getField(allFieldsInTable, groupBy)"
89
>
9-
<div class="grid-view__group-cell">
10+
<div v-if="field" class="grid-view__group-cell">
1011
<div class="grid-view__group-name">
1112
{{ field.name }}
1213
</div>
@@ -150,15 +151,6 @@ export default {
150151
},
151152
},
152153
emits: ['dragging', 'field-created', 'refresh'],
153-
computed: {
154-
activeGroupBysWithFields() {
155-
if (!this.includeGroupBy) return []
156-
return this.activeGroupBys.map((groupBy) => ({
157-
groupBy,
158-
field: this.getGroupByField(groupBy),
159-
}))
160-
},
161-
},
162154
methods: {
163155
/**
164156
* After newField is created pressing "insert left" or "insert right" button,
@@ -171,6 +163,7 @@ export default {
171163
newField,
172164
fromField,
173165
undoRedoActionGroupId = null,
166+
visible = null,
174167
}) {
175168
try {
176169
await this.$store.dispatch(
@@ -181,6 +174,7 @@ export default {
181174
fromField,
182175
undoRedoActionGroupId,
183176
readOnly: this.readOnly,
177+
visible,
184178
}
185179
)
186180
} catch (error) {
@@ -200,6 +194,10 @@ export default {
200194
onShownCreateFieldContext() {
201195
this.$refs.createFieldContext.showFieldTypesDropdown(this.$el)
202196
},
197+
getField(allFieldsInTable, groupBy) {
198+
const field = allFieldsInTable.find((f) => f.id === groupBy.field)
199+
return field
200+
},
203201
},
204202
}
205203
</script>

web-frontend/modules/database/components/view/grid/GridViewHide.vue

Lines changed: 3 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
</template>
3030

3131
<script>
32-
import { mapGetters } from 'vuex'
32+
import { filterHiddenFieldsFunction } from '@baserow/modules/database/utils/view'
3333
import { notifyIf } from '@baserow/modules/core/utils/error'
3434
import ViewFieldsContext from '@baserow/modules/database/components/view/ViewFieldsContext'
3535
@@ -60,29 +60,15 @@ export default {
6060
},
6161
computed: {
6262
hiddenFields() {
63-
return this.fields.filter((field) => {
64-
const exists = Object.prototype.hasOwnProperty.call(
65-
this.fieldOptions,
66-
field.id
67-
)
68-
return !exists || (exists && this.fieldOptions[field.id].hidden)
69-
})
63+
const isFieldHidden = filterHiddenFieldsFunction(this.fieldOptions)
64+
return this.fields.filter((field) => isFieldHidden(field))
7065
},
7166
fieldOptions() {
7267
return this.$store.getters[
7368
this.storePrefix + 'view/grid/getAllFieldOptions'
7469
]
7570
},
7671
},
77-
/*beforeCreate() {
78-
this.$options.computed = {
79-
...(this.$options.computed || {}),
80-
...mapGetters({
81-
fieldOptions:
82-
this.$options.propsData.storePrefix + 'view/grid/getAllFieldOptions',
83-
}),
84-
}
85-
},*/
8672
methods: {
8773
async updateAllFieldOptions({ newFieldOptions, oldFieldOptions }) {
8874
try {

web-frontend/modules/database/components/view/grid/GridViewSection.vue

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@
7575
></GridViewPlaceholder>
7676
<GridViewGroups
7777
v-if="includeGroupBy && activeGroupBys.length > 0"
78+
:all-fields-in-table="allFieldsInTable"
7879
:group-by-value-sets="groupByValueSets"
7980
:store-prefix="storePrefix"
8081
></GridViewGroups>
@@ -422,7 +423,12 @@ export default {
422423
return false
423424
}
424425
return groupBys.slice(0, groupByIndex + 1).every((groupBy) => {
425-
const groupByField = this.getGroupByField(groupBy)
426+
const groupByField = this.allFieldsInTable.find(
427+
(f) => f.id === groupBy.field
428+
)
429+
if (!groupByField) {
430+
return false
431+
}
426432
const groupByFieldType = this.$registry.get(
427433
'field',
428434
groupByField.type
@@ -444,9 +450,10 @@ export default {
444450
(metadata[`field_${groupBy.field}`] || []).find((entry) => {
445451
const groupByFields = groupBys
446452
.slice(0, groupByIndex + 1)
447-
.map((groupBy) => {
448-
return this.getGroupByField(groupBy)
449-
})
453+
.map((groupBy) =>
454+
this.allFieldsInTable.find((f) => f.id === groupBy.field)
455+
)
456+
.filter(Boolean)
450457
return fieldValuesAreEqualInObjects(
451458
groupByFields,
452459
this.$registry,

web-frontend/modules/database/components/view/grid/GroupByFieldLinkRow.vue

Lines changed: 0 additions & 40 deletions
This file was deleted.

web-frontend/modules/database/fieldTypes.js

Lines changed: 2 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,6 @@ import RowCardFieldEmail from '@baserow/modules/database/components/card/RowCard
114114
import RowCardFieldFile from '@baserow/modules/database/components/card/RowCardFieldFile'
115115
import RowCardFieldFormula from '@baserow/modules/database/components/card/RowCardFieldFormula'
116116
import RowCardFieldLinkRow from '@baserow/modules/database/components/card/RowCardFieldLinkRow'
117-
import GroupByFieldLinkRow from '@baserow/modules/database/components/view/grid/GroupByFieldLinkRow'
118117
import RowCardFieldMultipleSelect from '@baserow/modules/database/components/card/RowCardFieldMultipleSelect'
119118
import RowCardFieldNumber from '@baserow/modules/database/components/card/RowCardFieldNumber'
120119
import RowCardFieldRating from '@baserow/modules/database/components/card/RowCardFieldRating'
@@ -1361,10 +1360,6 @@ export class LinkRowFieldType extends FieldType {
13611360
return RowCardFieldLinkRow
13621361
}
13631362

1364-
getGroupByComponent() {
1365-
return GroupByFieldLinkRow
1366-
}
1367-
13681363
getRowHistoryEntryComponent() {
13691364
return RowHistoryFieldLinkRow
13701365
}
@@ -1392,8 +1387,8 @@ export class LinkRowFieldType extends FieldType {
13921387
}
13931388

13941389
isEqual(field, value1, value2) {
1395-
const value1Ids = value1.map((v) => v.id)
1396-
const value2Ids = value2.map((v) => v.id)
1390+
const value1Ids = (value1 || []).map((v) => v.id)
1391+
const value2Ids = (value2 || []).map((v) => v.id)
13971392

13981393
return _.isEqual(value1Ids, value2Ids)
13991394
}
@@ -4274,14 +4269,6 @@ export class FormulaFieldType extends mix(
42744269
return RowCardFieldFormula
42754270
}
42764271

4277-
getGroupByComponent(field) {
4278-
const formulaType = this.getFormulaType(field)
4279-
if (formulaType) {
4280-
return formulaType.getCardComponent(field)
4281-
}
4282-
return this.getCardComponent(field)
4283-
}
4284-
42854272
getFilterInputComponent(field, filterType) {
42864273
return this.getFormulaType(field)?.getFilterInputComponent(
42874274
field,

0 commit comments

Comments
 (0)