Skip to content

Commit 8832606

Browse files
authored
Fix tag collection field type after data migration (baserow#4134)
1 parent b368c4f commit 8832606

File tree

7 files changed

+82
-15
lines changed

7 files changed

+82
-15
lines changed

backend/src/baserow/contrib/builder/api/elements/serializers.py

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
)
3333
from baserow.core.exceptions import InstanceTypeDoesNotExist
3434
from baserow.core.formula.serializers import FormulaSerializerField
35+
from baserow.core.formula.types import BASEROW_FORMULA_MODE_RAW
3536

3637

3738
class ElementSerializer(serializers.ModelSerializer):
@@ -482,3 +483,40 @@ def get_menu_items(self, obj):
482483
return MenuItemSerializer(
483484
root_items, many=True, context={"all_items": menu_items}
484485
).data
486+
487+
488+
@extend_schema_field(OpenApiTypes.STR)
489+
class CollectionFieldOptionalFormulaSerializerField(FormulaSerializerField):
490+
"""
491+
This field can be used to store a formula which mode depends on a field aside. If
492+
`is_formula_field_name` property is `True`,
493+
then the value will be treated as a simple formula otherwise, the value
494+
will be treated as raw formula.
495+
"""
496+
497+
def __init__(self, *args, is_formula_field_name=None, **kwargs):
498+
self.is_formula_field_name = is_formula_field_name
499+
super().__init__(*args, **kwargs)
500+
501+
def to_representation(self, value):
502+
value = super().to_representation(value)
503+
504+
is_formula = getattr(self.parent.instance, "config", {}).get(
505+
self.is_formula_field_name, False
506+
)
507+
508+
if not is_formula:
509+
# We force the type to raw as it's not a formula
510+
# For compat with unmigrated values.
511+
value["mode"] = "raw"
512+
513+
return value
514+
515+
def to_internal_value(self, data):
516+
data = super().to_internal_value(data)
517+
518+
is_formula = self.parent.data.get(self.is_formula_field_name, False)
519+
if not is_formula:
520+
data["mode"] = BASEROW_FORMULA_MODE_RAW
521+
522+
return data

backend/src/baserow/contrib/builder/elements/collection_field_types.py

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,7 @@
99
from baserow.contrib.builder.elements.registries import CollectionFieldType
1010
from baserow.contrib.builder.workflow_actions.models import BuilderWorkflowAction
1111
from baserow.core.constants import RatingStyleChoices
12-
from baserow.core.formula.serializers import (
13-
FormulaSerializerField,
14-
OptionalFormulaSerializerField,
15-
)
12+
from baserow.core.formula.serializers import FormulaSerializerField
1613
from baserow.core.formula.types import BaserowFormulaObject
1714
from baserow.core.registry import Instance
1815

@@ -236,12 +233,16 @@ class SerializedDict(TypedDict):
236233

237234
@property
238235
def serializer_field_overrides(self):
236+
from baserow.contrib.builder.api.elements.serializers import (
237+
CollectionFieldOptionalFormulaSerializerField,
238+
)
239+
239240
return {
240241
"values": FormulaSerializerField(
241242
help_text="The formula for the tags values",
242243
required=False,
243244
),
244-
"colors": OptionalFormulaSerializerField(
245+
"colors": CollectionFieldOptionalFormulaSerializerField(
245246
help_text="The formula or value for the tags colors",
246247
required=False,
247248
is_formula_field_name="colors_is_formula",

backend/src/baserow/core/formula/field.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -269,7 +269,7 @@ def _transform_db_property(
269269
:return: A `BaserowFormulaObject`.
270270
"""
271271

272-
if isinstance(value, str):
272+
if not isinstance(value, dict):
273273
return BaserowFormulaObject(
274274
mode=BASEROW_FORMULA_MODE_SIMPLE,
275275
version=BASEROW_FORMULA_VERSION_INITIAL,
@@ -390,7 +390,7 @@ def _transform_python_property(
390390
:return: A `BaserowFormulaMinified`.
391391
"""
392392

393-
if isinstance(value, str):
393+
if not isinstance(value, dict):
394394
return BaserowFormulaMinified(
395395
m=BASEROW_FORMULA_MODE_SIMPLE,
396396
v=BASEROW_FORMULA_VERSION_INITIAL,

backend/src/baserow/core/formula/serializers.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ def to_internal_value(self, data: Union[str, Dict[str, str]]):
109109
mode=BASEROW_FORMULA_MODE_SIMPLE,
110110
)
111111

112-
if not data["formula"]:
112+
if not data["formula"] or data["mode"] == BASEROW_FORMULA_MODE_RAW:
113113
return data
114114

115115
try:

web-frontend/modules/builder/collectionFieldTypes.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -247,9 +247,9 @@ export class TagsCollectionFieldType extends CollectionFieldType {
247247

248248
getProps(field, { resolveFormula, applicationContext }) {
249249
const values = ensureArray(resolveFormula(field.values))
250-
const colors = field.colors_is_formula
251-
? ensureArray(resolveFormula(field.colors))
252-
: [field.colors]
250+
251+
const colors = ensureArray(resolveFormula(field.colors))
252+
253253
const tags = values.map((value, index) => ({
254254
value,
255255
color: colors[index % colors.length],

web-frontend/modules/builder/components/elements/components/collectionField/form/TagsFieldForm.vue

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@
5252
class="margin-bottom-2"
5353
>
5454
<ColorInput
55-
v-model="values.colors"
55+
v-model="rawFormula"
5656
:color-variables="colorVariables"
5757
small
5858
/>
@@ -82,20 +82,43 @@ export default {
8282
allowedValues: ['values', 'colors', 'colors_is_formula', 'styles'],
8383
values: {
8484
values: {},
85-
colors: '#acc8f8',
85+
colors: {
86+
formula: '#acc8f8',
87+
mode: 'raw',
88+
},
8689
colors_is_formula: false,
8790
styles: {},
8891
},
8992
}
9093
},
94+
computed: {
95+
rawFormula: {
96+
get() {
97+
return this.values.colors.formula
98+
},
99+
set(newValue) {
100+
this.values.colors = {
101+
...this.values.colors,
102+
formula: newValue,
103+
mode: 'raw',
104+
}
105+
},
106+
},
107+
},
91108
methods: {
92109
setColorsToFormula() {
93110
this.values.colors_is_formula = true
94-
this.values.colors = `'${this.values.colors}'`
111+
this.values.colors = {
112+
formula: `'${this.values.colors.formula}'`,
113+
mode: 'simple',
114+
}
95115
},
96116
setColorsToPicker() {
97117
this.values.colors_is_formula = false
98-
this.values.colors = '#acc8f8'
118+
this.values.colors = {
119+
formula: '#acc8f8',
120+
mode: 'raw',
121+
}
99122
},
100123
},
101124
}

web-frontend/modules/core/formula/index.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,11 @@ export const resolveFormula = (
1919
return ''
2020
}
2121

22+
if (formulaCtx.mode === 'raw') {
23+
// We don't need to resolve the formula for raw mode.
24+
return formulaCtx.formula
25+
}
26+
2227
try {
2328
const tree = parseBaserowFormula(formulaCtx.formula)
2429
return new JavascriptExecutor(functions, RuntimeFormulaContext).visit(tree)

0 commit comments

Comments
 (0)