1
0
Fork 0
mirror of https://gitlab.com/bramw/baserow.git synced 2025-04-11 07:51:20 +00:00

Merge branch '132-fix-the-table-x-not-found-in-the-store' into 'develop'

Resolve "Fix "The table X not found in the store.""

Closes 

See merge request 
This commit is contained in:
Bram Wiepjes 2020-09-04 10:20:20 +00:00
commit 97a8d90045
8 changed files with 85 additions and 31 deletions
backend
src/baserow/contrib/database/fields
tests/baserow/contrib/database/field
changelog.md
web-frontend/modules
core/components
database

View file

@ -245,7 +245,10 @@ class LinkRowFieldType(FieldType):
model_class = LinkRowField
allowed_fields = ['link_row_table', 'link_row_related_field',
'link_row_relation_id']
serializer_field_names = ['link_row_table']
serializer_field_names = ['link_row_table', 'link_row_related_field']
serializer_field_overrides = {
'link_row_related_field': serializers.PrimaryKeyRelatedField(read_only=True)
}
api_exceptions_map = {
LinkRowTableNotProvided: ERROR_LINK_ROW_TABLE_NOT_PROVIDED,
LinkRowTableNotInSameDatabase: ERROR_LINK_ROW_TABLE_NOT_IN_SAME_DATABASE

View file

@ -426,7 +426,10 @@ def test_link_row_field_type_api_views(api_client, data_fixture):
{
'name': 'Link 1',
'type': 'link_row',
'link_row_table': customers_table.id
'link_row_table': customers_table.id,
# The `link_row_related_field` is a read_only field so we deliberately set
# an unknown id to see if it is ignored.
'link_row_related_field': 999999,
},
format='json',
HTTP_AUTHORIZATION=f'JWT {token}'
@ -442,6 +445,9 @@ def test_link_row_field_type_api_views(api_client, data_fixture):
field = LinkRowField.objects.all().order_by('id').first()
related_field = LinkRowField.objects.all().order_by('id').last()
assert response_json['link_row_related_field'] == related_field.id
assert response_json['link_row_related_field'] != 999999
# Check if the correct fields are correctly linked.
assert field.table.id == table.id
assert field.link_row_table.id == customers_table.id
@ -459,6 +465,7 @@ def test_link_row_field_type_api_views(api_client, data_fixture):
assert response_json['name'] == 'Link 1'
assert response_json['type'] == 'link_row'
assert response_json['link_row_table'] == customers_table.id
assert response_json['link_row_related_field'] == related_field.id
# Just fetching the related field and check if is has the correct values.
response = api_client.get(
@ -469,6 +476,7 @@ def test_link_row_field_type_api_views(api_client, data_fixture):
assert response.status_code == HTTP_200_OK
assert response_json['name'] == 'Example'
assert response_json['link_row_table'] == table.id
assert response_json['link_row_related_field'] == field.id
# Only updating the name of the field without changing anything else
response = api_client.patch(
@ -482,8 +490,23 @@ def test_link_row_field_type_api_views(api_client, data_fixture):
assert response_json['name'] == 'Link new name'
assert response_json['type'] == 'link_row'
assert response_json['link_row_table'] == customers_table.id
assert response_json['link_row_related_field'] == related_field.id
# Only try to update the link_row_related_field, but this is a read only field so
# nothing should happen.
response = api_client.patch(
reverse('api:database:fields:item', kwargs={'field_id': field_id}),
{'link_row_related_field': 9999},
format='json',
HTTP_AUTHORIZATION=f'JWT {token}'
)
response_json = response.json()
assert response.status_code == HTTP_200_OK
assert response_json['name'] == 'Link new name'
assert response_json['type'] == 'link_row'
assert response_json['link_row_table'] == customers_table.id
assert response_json['link_row_related_field'] == related_field.id
# Only updating the name of the field without changing anything else
response = api_client.patch(
reverse('api:database:fields:item', kwargs={'field_id': field_id}),
{'link_row_table': cars_table.id},
@ -495,6 +518,7 @@ def test_link_row_field_type_api_views(api_client, data_fixture):
assert response_json['name'] == 'Link new name'
assert response_json['type'] == 'link_row'
assert response_json['link_row_table'] == cars_table.id
assert response_json['link_row_related_field'] == related_field.id
field.refresh_from_db()
related_field.refresh_from_db()

View file

@ -4,6 +4,11 @@
* Prevent adding a new line to the long text field in the grid view when selecting the
cell by pressing the enter key.
* Fixed The table X is not found in the store error.
* Fixed bug where the selected name of the dropdown was not updated when that name was
changed.
* Fixed bug where the link row field is not removed from the store when the related
table is deleted.
## Released (2020-09-02)

View file

@ -3,11 +3,11 @@
<a class="dropdown__selected" @click="show()">
<template v-if="hasValue()">
<i
v-if="icon"
v-if="selectedIcon"
class="dropdown__selected-icon fas"
:class="'fa-' + icon"
:class="'fa-' + selectedIcon"
></i>
{{ name }}
{{ selectedName }}
</template>
<template v-if="!hasValue()">
Make a choice
@ -51,6 +51,14 @@ export default {
default: 'Search',
},
},
computed: {
selectedName() {
return this.getSelectedProperty(this.value, 'name')
},
selectedIcon() {
return this.getSelectedProperty(this.value, 'icon')
},
},
data() {
return {
open: false,
@ -59,23 +67,6 @@ export default {
query: '',
}
},
watch: {
/**
* If the value changes we have to update the visible name and icon.
*/
value(newValue) {
this.setDisplayValue(newValue)
},
},
/**
* When the dropdown first loads we have to check if there already is a value, if
* there is, we have to update the displayed name and icon.
*/
mounted() {
if (this.hasValue()) {
this.setDisplayValue(this.value)
}
},
methods: {
/**
* Returns true if there is a value.
@ -141,15 +132,17 @@ export default {
})
},
/**
* Changes the selected name and icon of the dropdown based on the provided value.
* Loops over all children to see if any of the values match with given value. If
* so the requested property of the child is returned
*/
setDisplayValue(value) {
this.$children.forEach((item) => {
getSelectedProperty(value, property) {
for (const i in this.$children) {
const item = this.$children[i]
if (item.value === value) {
this.name = item.name
this.icon = item.icon
return item[property]
}
})
}
return ''
},
},
}

View file

@ -88,7 +88,7 @@ export default {
}
}
throw new Error(`The table ${tableId} is not found in the store.`)
return []
},
},
mounted() {

View file

@ -151,6 +151,13 @@ export class FieldType extends Registerable {
prepareValueForUpdate(field, value) {
return value
}
/**
* A hook that is called when a table is deleted. Some fields depend on other tables
* than the table that they belong to. So action might be required when that table
* is deleted.
*/
tableDeleted(context, field, table, database) {}
}
export class TextFieldType extends FieldType {
@ -257,6 +264,17 @@ export class LinkRowFieldType extends FieldType {
prepareValueForUpdate(field, value) {
return value.map((item) => (typeof item === 'object' ? item.id : item))
}
/**
* When a table is deleted it might be the case that this is the related table of
* the field. If so it means that this field has already been deleted and it needs
* to be removed from the store without making an API call.
*/
tableDeleted({ dispatch }, field, table, database) {
if (field.link_row_table === table.id) {
dispatch('field/forceDelete', field, { root: true })
}
}
}
export class NumberFieldType extends FieldType {

View file

@ -203,6 +203,9 @@ export const getters = {
get: (state) => (id) => {
return state.items.find((item) => item.id === id)
},
getAll(state) {
return state.items
},
}
export default {

View file

@ -98,7 +98,15 @@ export const actions = {
* Delete the table from the store only. It will not send a request for deleting
* to the server.
*/
forceDelete({ commit, dispatch }, { database, table }) {
forceDelete(context, { database, table }) {
const { commit, rootGetters } = context
// Call the table deleted event on all fields.
rootGetters['field/getAll'].forEach((field) => {
const fieldType = this.$registry.get('field', field.type)
fieldType.tableDeleted(context, field, table, database)
})
if (table._.selected) {
// Redirect back to the dashboard because the table doesn't exist anymore.
this.$router.push({ name: 'dashboard' })