Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ existing tools and performs at any scale.
[![Deploy to Heroku](https://www.herokucdn.com/deploy/button.svg)](https://www.heroku.com/deploy/?template=https://github.com/baserow/baserow/tree/master)

```bash
docker run -v baserow_data:/baserow/data -p 80:80 -p 443:443 baserow/baserow:2.1.4
docker run -v baserow_data:/baserow/data -p 80:80 -p 443:443 baserow/baserow:2.1.5
```

![Baserow database screenshot](docs/assets/screenshot.png "Baserow database screenshot")
Expand Down Expand Up @@ -108,7 +108,7 @@ Created by Baserow B.V. - bram@baserow.io.

Distributes under the MIT license. See `LICENSE` for more information.

Version: 2.1.4
Version: 2.1.5

The official repository can be found at https://github.com/baserow/baserow.

Expand Down
2 changes: 1 addition & 1 deletion backend/docker/docker-entrypoint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ set -euo pipefail
# ENVIRONMENT VARIABLES USED DIRECTLY BY THIS ENTRYPOINT
# ======================================================

export BASEROW_VERSION="2.1.4"
export BASEROW_VERSION="2.1.5"

# Used by docker-entrypoint.sh to start the dev server
# If not configured you'll receive this: CommandError: "0.0.0.0:" is not a valid port number or address:port pair.
Expand Down
2 changes: 1 addition & 1 deletion backend/src/baserow/config/settings/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -469,7 +469,7 @@
"name": "MIT",
"url": "https://github.com/baserow/baserow/blob/develop/LICENSE",
},
"VERSION": "2.1.4",
"VERSION": "2.1.5",
"SERVE_INCLUDE_SCHEMA": False,
"TAGS": [
{"name": "Settings"},
Expand Down
5 changes: 1 addition & 4 deletions backend/src/baserow/contrib/builder/elements/mixins.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@

class ContainerElementTypeMixin:
# Container element types are imported first.
import_element_priority = 2
import_element_priority = 1

class SerializedDict(ElementDict):
pass
Expand Down Expand Up @@ -801,9 +801,6 @@ def extract_properties(


class FormElementTypeMixin:
# Form element types are imported second, after containers.
import_element_priority = 1

def is_valid(
self,
element: Type[FormElement],
Expand Down
26 changes: 1 addition & 25 deletions backend/src/baserow/contrib/builder/elements/registries.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
from rest_framework import serializers
from rest_framework.exceptions import ValidationError

from baserow.contrib.builder.formula_importer import import_formula
from baserow.contrib.builder.mixins import BuilderInstanceWithFormulaMixin
from baserow.contrib.builder.pages.models import Page
from baserow.core.formula.types import BaserowFormulaObject
Expand Down Expand Up @@ -202,8 +201,6 @@ def import_serialized(
cache: Dict[str, Any] | None = None,
**kwargs,
) -> ElementSubClass:
from baserow.contrib.builder.elements.handler import ElementHandler

# Add mapping for builder element event uids (for collection field or other
# elements that are using dynamic events.
if "builder_element_event_uids" not in id_mapping:
Expand All @@ -212,20 +209,6 @@ def import_serialized(
if cache is None:
cache = {}

import_context = {}

parent_element_id = serialized_values["parent_element_id"]

# If we have a parent element then we want to add used its import context
if parent_element_id:
imported_parent_element_id = id_mapping["builder_page_elements"][
parent_element_id
]
import_context = ElementHandler().get_import_context_addition(
imported_parent_element_id,
element_map=cache.get("imported_element_map", None),
)

existing_roles = cache.get("existing_roles", {}).get(page.builder.id)
if not existing_roles:
existing_roles = UserSourceHandler().get_all_roles_for_application(
Expand All @@ -246,16 +229,9 @@ def import_serialized(
files_zip,
storage,
cache,
**(kwargs | import_context),
)

# Update formulas of the current element
updated_models = self.import_formulas(
created_instance, id_mapping, import_formula, **(kwargs | import_context)
**kwargs,
)

[m.save() for m in updated_models]

# Add created instance to an element cache
cache.setdefault("imported_element_map", {})[created_instance.id] = (
created_instance
Expand Down
26 changes: 25 additions & 1 deletion backend/src/baserow/contrib/builder/pages/handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
from baserow.contrib.builder.elements.handler import ElementHandler
from baserow.contrib.builder.elements.registries import element_type_registry
from baserow.contrib.builder.elements.types import ElementDictSubClass
from baserow.contrib.builder.formula_importer import import_formula
from baserow.contrib.builder.models import Builder
from baserow.contrib.builder.pages.constants import (
ILLEGAL_PATH_SAMPLE_CHARACTER,
Expand Down Expand Up @@ -808,7 +809,6 @@ def import_elements(

# Sort the serialized elements so that we import:
# Containers first
# Form elements second
# Everything else after that.
def element_priority_sort(element_to_sort):
return element_type_registry.get(
Expand Down Expand Up @@ -849,6 +849,30 @@ def element_priority_sort(element_to_sort):
if progress:
progress.increment(state=IMPORT_SERIALIZED_IMPORTING)

# Now that all elements have been imported, loop back over them
# and start import their formulas. We do this because formulas can
# reference one another, so we need the full set of elements to be
# imported before we can safely import the formulas without running
# into issues of missing referenced elements in `id_mapping`.
updated_models = set()
for elt in imported_elements:
import_context = {}
if elt.parent_element_id:
import_context = ElementHandler().get_import_context_addition(
elt.parent_element_id,
element_map=cache.get("imported_element_map", None)
if cache
else None,
)
updated_models = updated_models | elt.get_type().import_formulas(
elt,
id_mapping,
import_formula,
**import_context,
)

[m.save() for m in updated_models]

return imported_elements

def import_workflow_actions(
Expand Down
2 changes: 1 addition & 1 deletion backend/src/baserow/version.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
VERSION = "2.1.4"
VERSION = "2.1.5"
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@
from baserow.contrib.builder.elements.handler import ElementHandler
from baserow.contrib.builder.elements.mixins import (
ContainerElementTypeMixin,
FormElementTypeMixin,
)
from baserow.contrib.builder.elements.models import (
ButtonElement,
Expand All @@ -64,6 +63,7 @@
element_type_registry,
)
from baserow.contrib.builder.elements.service import ElementService
from baserow.contrib.builder.pages.handler import PageHandler
from baserow.contrib.builder.pages.service import PageService
from baserow.contrib.database.fields.handler import FieldHandler
from baserow.core.handler import CoreHandler
Expand Down Expand Up @@ -269,7 +269,7 @@ def test_link_element_import_export_formula(data_fixture):
# After applying the ID mapping the imported formula should have updated
# the data source IDs
id_mapping = {"builder_data_sources": {data_source_1.id: data_source_2.id}}
imported_element = element_type.import_serialized(page, serialized, id_mapping)
[imported_element] = PageHandler().import_elements(page, [serialized], id_mapping)

expected_formula = f"get('data_source.{data_source_2.id}.field_1')"
expected_query_formula = f"get('data_source.{data_source_2.id}.field_2')"
Expand Down Expand Up @@ -300,7 +300,7 @@ def test_form_container_element_import_export_formula(data_fixture):
# After applying the ID mapping the imported formula should have updated
# the data source IDs
id_mapping = {"builder_data_sources": {data_source_1.id: data_source_2.id}}
imported_element = element_type.import_serialized(page, serialized, id_mapping)
[imported_element] = PageHandler().import_elements(page, [serialized], id_mapping)

expected_formula = f"get('data_source.{data_source_2.id}.field_1')"
assert imported_element.submit_button_label["formula"] == expected_formula
Expand Down Expand Up @@ -339,7 +339,7 @@ def test_text_element_import_export_formula(data_fixture):
# After applying the ID mapping the imported formula should have updated
# the data source IDs
id_mapping = {"builder_data_sources": {data_source_1.id: data_source_2.id}}
imported_element = element_type.import_serialized(page, serialized, id_mapping)
[imported_element] = PageHandler().import_elements(page, [serialized], id_mapping)

expected_formula = f"get('data_source.{data_source_2.id}.field_1')"
assert imported_element.value["formula"] == expected_formula
Expand All @@ -363,7 +363,7 @@ def test_input_text_element_import_export_formula(data_fixture):
# After applying the ID mapping the imported formula should have updated
# the data source IDs
id_mapping = {"builder_data_sources": {data_source_1.id: data_source_2.id}}
imported_element = element_type.import_serialized(page, serialized, id_mapping)
[imported_element] = PageHandler().import_elements(page, [serialized], id_mapping)

expected_formula = f"get('data_source.{data_source_2.id}.field_1')"
assert imported_element.label["formula"] == expected_formula
Expand All @@ -388,7 +388,7 @@ def test_image_element_import_export_formula(data_fixture):
# After applying the ID mapping the imported formula should have updated
# the data source IDs
id_mapping = {"builder_data_sources": {data_source_1.id: data_source_2.id}}
imported_element = element_type.import_serialized(page, serialized, id_mapping)
[imported_element] = PageHandler().import_elements(page, [serialized], id_mapping)

expected_formula = f"get('data_source.{data_source_2.id}.field_1')"
assert imported_element.image_url["formula"] == expected_formula
Expand All @@ -411,7 +411,7 @@ def test_button_element_import_export_formula(data_fixture):
# After applying the ID mapping the imported formula should have updated
# the data source IDs
id_mapping = {"builder_data_sources": {data_source_1.id: data_source_2.id}}
imported_element = element_type.import_serialized(page, serialized, id_mapping)
[imported_element] = PageHandler().import_elements(page, [serialized], id_mapping)

expected_formula = f"get('data_source.{data_source_2.id}.field_1')"
assert imported_element.value["formula"] == expected_formula
Expand Down Expand Up @@ -500,7 +500,7 @@ def test_choice_element_import_export_formula(data_fixture):
# After applying the ID mapping the imported formula should have updated
# the data source IDs
id_mapping = {"builder_data_sources": {data_source_1.id: data_source_2.id}}
imported_element = element_type.import_serialized(page, serialized, id_mapping)
[imported_element] = PageHandler().import_elements(page, [serialized], id_mapping)

expected_formula = f"get('data_source.{data_source_2.id}.field_1')"
assert imported_element.label["formula"] == expected_formula
Expand Down Expand Up @@ -793,26 +793,20 @@ def test_element_type_import_element_priority():
for element_type in element_types
if isinstance(element_type, ContainerElementTypeMixin)
]
form_element_types = [
element_type
for element_type in element_types
if isinstance(element_type, FormElementTypeMixin)
]
other_element_types = [
element_type
for element_type in element_types
if not isinstance(element_type, ContainerElementTypeMixin)
and not isinstance(element_type, FormElementTypeMixin)
]
manual_ordering = container_element_types + form_element_types + other_element_types
manual_ordering = container_element_types + other_element_types
expected_ordering = sorted(
element_types,
key=lambda element_type: element_type.import_element_priority,
reverse=True,
)
assert manual_ordering == expected_ordering, (
"The element types ordering are expected to be: "
"containers first, then form elements, then everything else."
"containers first, then everything else."
)


Expand Down Expand Up @@ -852,7 +846,7 @@ def test_checkbox_element_import_export_formula(data_fixture):
# After applying the ID mapping the imported formula should have updated
# the data source IDs
id_mapping = {"builder_data_sources": {data_source_1.id: data_source_2.id}}
imported_element = element_type.import_serialized(page, serialized, id_mapping)
[imported_element] = PageHandler().import_elements(page, [serialized], id_mapping)

expected_formula = f"get('data_source.{data_source_2.id}.field_1')"
assert imported_element.label["formula"] == expected_formula
Expand Down Expand Up @@ -909,8 +903,9 @@ def test_iframe_element_import_export_formula(data_fixture):

# After applying the ID mapping the imported formula should have updated
# the data source IDs
# rather than in element_type.import_serialized.
id_mapping = {"builder_data_sources": {data_source_1.id: data_source_2.id}}
imported_element = element_type.import_serialized(page, serialized, id_mapping)
[imported_element] = PageHandler().import_elements(page, [serialized], id_mapping)

expected_formula = f"get('data_source.{data_source_2.id}.field_1')"
assert imported_element.url["formula"] == expected_formula
Expand Down Expand Up @@ -961,8 +956,8 @@ def test_image_element_import_export(data_fixture, fake, storage):
image_file.delete()

with ZipFile(zip_buffer, "r", ZIP_DEFLATED, False) as files_zip:
imported_element = element_type.import_serialized(
page, serialized, id_mapping, files_zip=files_zip, storage=storage
[imported_element] = PageHandler().import_elements(
page, [serialized], id_mapping, files_zip=files_zip, storage=storage
)

expected_formula = f"get('data_source.{data_source_2.id}.field_1')"
Expand Down Expand Up @@ -995,7 +990,7 @@ def test_choice_element_import_export(data_fixture):
# the data source IDs
id_mapping = {"builder_data_sources": {42: data_source_2.id}}

imported_element = element_type.import_serialized(page, serialized, id_mapping)
[imported_element] = PageHandler().import_elements(page, [serialized], id_mapping)

expected_formula = f"get('data_source.{data_source_2.id}.field_1')"
assert imported_element.label["formula"] == expected_formula
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
LinkElement,
TextElement,
)
from baserow.contrib.builder.pages.handler import PageHandler
from baserow.core.formula import BaserowFormulaObject
from baserow.core.formula.field import BASEROW_FORMULA_VERSION_INITIAL
from baserow.core.formula.types import BASEROW_FORMULA_MODE_SIMPLE
Expand Down Expand Up @@ -96,9 +97,9 @@ def test_element_formula_generator_mixin(
)
serialized_element = element_type().export_serialized(exported_element)

imported_element = element_type().import_serialized(
[imported_element] = PageHandler().import_elements(
formula_generator_fixture["page"],
serialized_element,
[serialized_element],
formula_generator_fixture["id_mapping"],
)

Expand Down Expand Up @@ -143,9 +144,9 @@ def test_link_element_formula_generator(data_fixture, formula_generator_fixture)
)
serialized_element = LinkElementType().export_serialized(exported_element)

imported_element = LinkElementType().import_serialized(
[imported_element] = PageHandler().import_elements(
formula_generator_fixture["page"],
serialized_element,
[serialized_element],
formula_generator_fixture["id_mapping"],
)

Expand Down Expand Up @@ -248,9 +249,9 @@ def test_menu_element_formula_generator(data_fixture, formula_generator_fixture)

serialized_element = MenuElementType().export_serialized(menu_element)

imported_element = MenuElementType().import_serialized(
[imported_element] = PageHandler().import_elements(
formula_generator_fixture["page"],
serialized_element,
[serialized_element],
formula_generator_fixture["id_mapping"],
)

Expand Down
4 changes: 2 additions & 2 deletions backend/uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

17 changes: 17 additions & 0 deletions changelog.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,22 @@
# Changelog

## Released 2.1.5

### Bug fixes
* [Database] Remove ollama dependency [#4962](https://github.com/baserow/baserow/issues/4962)
* [Core] Fix a bug that caused an error when running the backend and frontend images as different users.
* [Core] Fix error page on token expiration to redirect to login
* [Builder] Fixed a bug that could cause a stale page ID to be set even after deleting the page.
* [Core] Improved the scheduling system in the periodic service.
* [Builder] Resolved a bug where a container-type element with a visibility condition would be unable to use form data in its formula.
* [Automation] Resolved a bug which caused the periodic trigger to reset its minute value if the interval was set to minute.
* [Automation] Resolved an issue which prevented hour and minute values from persisting in the periodic trigger form.

### Refactors
* [Automation] Add support for dispatching automation nodes asynchronously. [#3838](https://github.com/baserow/baserow/issues/3838)
* [Database] Update langchain to 0.3.28 [#4965](https://github.com/baserow/baserow/issues/4965)


## Released 2.1.4

### Bug fixes
Expand Down
Loading
Loading