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
38 changes: 38 additions & 0 deletions backend/src/baserow/contrib/builder/api/elements/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
)
from baserow.core.exceptions import InstanceTypeDoesNotExist
from baserow.core.formula.serializers import FormulaSerializerField
from baserow.core.formula.types import BASEROW_FORMULA_MODE_RAW


class ElementSerializer(serializers.ModelSerializer):
Expand Down Expand Up @@ -482,3 +483,40 @@ def get_menu_items(self, obj):
return MenuItemSerializer(
root_items, many=True, context={"all_items": menu_items}
).data


@extend_schema_field(OpenApiTypes.STR)
class CollectionFieldOptionalFormulaSerializerField(FormulaSerializerField):
"""
This field can be used to store a formula which mode depends on a field aside. If
`is_formula_field_name` property is `True`,
then the value will be treated as a simple formula otherwise, the value
will be treated as raw formula.
"""

def __init__(self, *args, is_formula_field_name=None, **kwargs):
self.is_formula_field_name = is_formula_field_name
super().__init__(*args, **kwargs)

def to_representation(self, value):
value = super().to_representation(value)

is_formula = getattr(self.parent.instance, "config", {}).get(
self.is_formula_field_name, False
)

if not is_formula:
# We force the type to raw as it's not a formula
# For compat with unmigrated values.
value["mode"] = "raw"

return value

def to_internal_value(self, data):
data = super().to_internal_value(data)

is_formula = self.parent.data.get(self.is_formula_field_name, False)
if not is_formula:
data["mode"] = BASEROW_FORMULA_MODE_RAW

return data
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,7 @@
from baserow.contrib.builder.elements.registries import CollectionFieldType
from baserow.contrib.builder.workflow_actions.models import BuilderWorkflowAction
from baserow.core.constants import RatingStyleChoices
from baserow.core.formula.serializers import (
FormulaSerializerField,
OptionalFormulaSerializerField,
)
from baserow.core.formula.serializers import FormulaSerializerField
from baserow.core.formula.types import BaserowFormulaObject
from baserow.core.registry import Instance

Expand Down Expand Up @@ -236,12 +233,16 @@ class SerializedDict(TypedDict):

@property
def serializer_field_overrides(self):
from baserow.contrib.builder.api.elements.serializers import (
CollectionFieldOptionalFormulaSerializerField,
)

return {
"values": FormulaSerializerField(
help_text="The formula for the tags values",
required=False,
),
"colors": OptionalFormulaSerializerField(
"colors": CollectionFieldOptionalFormulaSerializerField(
help_text="The formula or value for the tags colors",
required=False,
is_formula_field_name="colors_is_formula",
Expand Down
4 changes: 2 additions & 2 deletions backend/src/baserow/core/formula/field.py
Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,7 @@ def _transform_db_property(
:return: A `BaserowFormulaObject`.
"""

if isinstance(value, str):
if not isinstance(value, dict):
return BaserowFormulaObject(
mode=BASEROW_FORMULA_MODE_SIMPLE,
version=BASEROW_FORMULA_VERSION_INITIAL,
Expand Down Expand Up @@ -390,7 +390,7 @@ def _transform_python_property(
:return: A `BaserowFormulaMinified`.
"""

if isinstance(value, str):
if not isinstance(value, dict):
return BaserowFormulaMinified(
m=BASEROW_FORMULA_MODE_SIMPLE,
v=BASEROW_FORMULA_VERSION_INITIAL,
Expand Down
2 changes: 1 addition & 1 deletion backend/src/baserow/core/formula/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ def to_internal_value(self, data: Union[str, Dict[str, str]]):
mode=BASEROW_FORMULA_MODE_SIMPLE,
)

if not data["formula"]:
if not data["formula"] or data["mode"] == BASEROW_FORMULA_MODE_RAW:
return data

try:
Expand Down
6 changes: 3 additions & 3 deletions web-frontend/modules/builder/collectionFieldTypes.js
Original file line number Diff line number Diff line change
Expand Up @@ -247,9 +247,9 @@ export class TagsCollectionFieldType extends CollectionFieldType {

getProps(field, { resolveFormula, applicationContext }) {
const values = ensureArray(resolveFormula(field.values))
const colors = field.colors_is_formula
? ensureArray(resolveFormula(field.colors))
: [field.colors]

const colors = ensureArray(resolveFormula(field.colors))

const tags = values.map((value, index) => ({
value,
color: colors[index % colors.length],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@
class="margin-bottom-2"
>
<ColorInput
v-model="values.colors"
v-model="rawFormula"
:color-variables="colorVariables"
small
/>
Expand Down Expand Up @@ -82,20 +82,43 @@ export default {
allowedValues: ['values', 'colors', 'colors_is_formula', 'styles'],
values: {
values: {},
colors: '#acc8f8',
colors: {
formula: '#acc8f8',
mode: 'raw',
},
colors_is_formula: false,
styles: {},
},
}
},
computed: {
rawFormula: {
get() {
return this.values.colors.formula
},
set(newValue) {
this.values.colors = {
...this.values.colors,
formula: newValue,
mode: 'raw',
}
},
},
},
methods: {
setColorsToFormula() {
this.values.colors_is_formula = true
this.values.colors = `'${this.values.colors}'`
this.values.colors = {
formula: `'${this.values.colors.formula}'`,
mode: 'simple',
}
},
setColorsToPicker() {
this.values.colors_is_formula = false
this.values.colors = '#acc8f8'
this.values.colors = {
formula: '#acc8f8',
mode: 'raw',
}
},
},
}
Expand Down
5 changes: 5 additions & 0 deletions web-frontend/modules/core/formula/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@ export const resolveFormula = (
return ''
}

if (formulaCtx.mode === 'raw') {
// We don't need to resolve the formula for raw mode.
return formulaCtx.formula
}

try {
const tree = parseBaserowFormula(formulaCtx.formula)
return new JavascriptExecutor(functions, RuntimeFormulaContext).visit(tree)
Expand Down
Loading