1
0
Fork 0
mirror of https://gitlab.com/bramw/baserow.git synced 2025-04-14 00:59:06 +00:00

Resolve "Allow to set more styles on non Root page elements"

This commit is contained in:
Jérémie Pardou 2023-12-22 10:06:35 +00:00
parent 6416f19fac
commit 3c05fc53ce
49 changed files with 891 additions and 443 deletions

View file

@ -105,6 +105,12 @@ class PublicElementSerializer(serializers.ModelSerializer):
"style_border_bottom_color", "style_border_bottom_color",
"style_border_bottom_size", "style_border_bottom_size",
"style_padding_bottom", "style_padding_bottom",
"style_border_left_color",
"style_border_left_size",
"style_padding_left",
"style_border_right_color",
"style_border_right_size",
"style_padding_right",
"style_background", "style_background",
"style_background_color", "style_background_color",
"style_width", "style_width",

View file

@ -57,6 +57,12 @@ class ElementSerializer(serializers.ModelSerializer):
"style_border_bottom_color", "style_border_bottom_color",
"style_border_bottom_size", "style_border_bottom_size",
"style_padding_bottom", "style_padding_bottom",
"style_border_left_color",
"style_border_left_size",
"style_padding_left",
"style_border_right_color",
"style_border_right_size",
"style_padding_right",
"style_background", "style_background",
"style_background_color", "style_background_color",
"style_width", "style_width",
@ -106,6 +112,12 @@ class CreateElementSerializer(serializers.ModelSerializer):
"style_border_bottom_color", "style_border_bottom_color",
"style_border_bottom_size", "style_border_bottom_size",
"style_padding_bottom", "style_padding_bottom",
"style_border_left_color",
"style_border_left_size",
"style_padding_left",
"style_border_right_color",
"style_border_right_size",
"style_padding_right",
"style_background", "style_background",
"style_background_color", "style_background_color",
"style_width", "style_width",
@ -122,6 +134,12 @@ class UpdateElementSerializer(serializers.ModelSerializer):
"style_border_bottom_color", "style_border_bottom_color",
"style_border_bottom_size", "style_border_bottom_size",
"style_padding_bottom", "style_padding_bottom",
"style_border_left_color",
"style_border_left_size",
"style_padding_left",
"style_border_right_color",
"style_border_right_size",
"style_padding_right",
"style_background", "style_background",
"style_background_color", "style_background_color",
"style_width", "style_width",

View file

@ -398,6 +398,7 @@ class HeadingElementType(ElementType):
class SerializedDict(ElementDict): class SerializedDict(ElementDict):
value: BaserowFormula value: BaserowFormula
font_color: str
level: int level: int
@property @property
@ -417,6 +418,12 @@ class HeadingElementType(ElementType):
max_value=6, max_value=6,
default=1, default=1,
), ),
"font_color": serializers.CharField(
max_length=20,
required=False,
allow_blank=True,
help_text="Heading font color.",
),
} }
return overrides return overrides
@ -500,6 +507,7 @@ class LinkElementType(ElementType):
"target", "target",
"width", "width",
"alignment", "alignment",
"button_color",
] ]
allowed_fields = [ allowed_fields = [
"value", "value",
@ -512,6 +520,7 @@ class LinkElementType(ElementType):
"target", "target",
"width", "width",
"alignment", "alignment",
"button_color",
] ]
class SerializedDict(ElementDict): class SerializedDict(ElementDict):
@ -524,6 +533,7 @@ class LinkElementType(ElementType):
target: str target: str
width: str width: str
alignment: str alignment: str
button_color: str
def deserialize_property( def deserialize_property(
self, prop_name: str, value: Any, id_mapping: Dict[str, Any] self, prop_name: str, value: Any, id_mapping: Dict[str, Any]
@ -600,6 +610,12 @@ class LinkElementType(ElementType):
help_text=LinkElement._meta.get_field("alignment").help_text, help_text=LinkElement._meta.get_field("alignment").help_text,
required=False, required=False,
), ),
"button_color": serializers.CharField(
max_length=20,
required=False,
default="primary",
help_text="Button color.",
),
} }
return overrides return overrides
@ -846,13 +862,14 @@ class InputTextElementType(InputElementType):
class ButtonElementType(ElementType): class ButtonElementType(ElementType):
type = "button" type = "button"
model_class = ButtonElement model_class = ButtonElement
allowed_fields = ["value", "alignment", "width"] allowed_fields = ["value", "alignment", "width", "button_color"]
serializer_field_names = ["value", "alignment", "width"] serializer_field_names = ["value", "alignment", "width", "button_color"]
class SerializedDict(ElementDict): class SerializedDict(ElementDict):
value: BaserowFormula value: BaserowFormula
width: str width: str
alignment: str alignment: str
button_color: str
@property @property
def serializer_field_overrides(self): def serializer_field_overrides(self):
@ -875,6 +892,12 @@ class ButtonElementType(ElementType):
help_text=ButtonElement._meta.get_field("alignment").help_text, help_text=ButtonElement._meta.get_field("alignment").help_text,
required=False, required=False,
), ),
"button_color": serializers.CharField(
max_length=20,
required=False,
default="primary",
help_text="Button color.",
),
} }
return overrides return overrides
@ -896,6 +919,29 @@ class TableElementType(CollectionElementType):
type = "table" type = "table"
model_class = TableElement model_class = TableElement
class SerializedDict(CollectionElementType.SerializedDict):
button_color: str
@property
def allowed_fields(self):
return super().allowed_fields + ["button_color"]
@property
def serializer_field_names(self):
return super().serializer_field_names + ["button_color"]
@property
def serializer_field_overrides(self):
return {
**super().serializer_field_overrides,
"button_color": serializers.CharField(
max_length=20,
required=False,
default="primary",
help_text="Button color.",
),
}
def get_pytest_params(self, pytest_data_fixture) -> Dict[str, Any]: def get_pytest_params(self, pytest_data_fixture) -> Dict[str, Any]:
return {"data_source_id": None} return {"data_source_id": None}
@ -903,11 +949,12 @@ class TableElementType(CollectionElementType):
class FormContainerElementType(ContainerElementType): class FormContainerElementType(ContainerElementType):
type = "form_container" type = "form_container"
model_class = FormContainerElement model_class = FormContainerElement
allowed_fields = ["submit_button_label"] allowed_fields = ["submit_button_label", "button_color"]
serializer_field_names = ["submit_button_label"] serializer_field_names = ["submit_button_label", "button_color"]
class SerializedDict(ElementDict): class SerializedDict(ElementDict):
submit_button_label: BaserowFormula submit_button_label: BaserowFormula
button_color: str
def get_pytest_params(self, pytest_data_fixture) -> Dict[str, Any]: def get_pytest_params(self, pytest_data_fixture) -> Dict[str, Any]:
return {"submit_button_label": "'Submit'"} return {"submit_button_label": "'Submit'"}
@ -916,7 +963,7 @@ class FormContainerElementType(ContainerElementType):
def serializer_field_overrides(self): def serializer_field_overrides(self):
from baserow.core.formula.serializers import FormulaSerializerField from baserow.core.formula.serializers import FormulaSerializerField
overrides = { return {
"submit_button_label": FormulaSerializerField( "submit_button_label": FormulaSerializerField(
help_text=FormContainerElement._meta.get_field( help_text=FormContainerElement._meta.get_field(
"submit_button_label" "submit_button_label"
@ -924,11 +971,15 @@ class FormContainerElementType(ContainerElementType):
required=False, required=False,
allow_blank=True, allow_blank=True,
default="", default="",
) ),
"button_color": serializers.CharField(
max_length=20,
required=False,
default="primary",
help_text="Button color.",
),
} }
return overrides
@property @property
def child_types_allowed(self) -> List[str]: def child_types_allowed(self) -> List[str]:
child_types_allowed = [] child_types_allowed = []

View file

@ -34,6 +34,12 @@ class ElementHandler:
"style_border_bottom_color", "style_border_bottom_color",
"style_border_bottom_size", "style_border_bottom_size",
"style_padding_bottom", "style_padding_bottom",
"style_border_left_color",
"style_border_left_size",
"style_padding_left",
"style_border_right_color",
"style_border_right_size",
"style_padding_right",
"style_background", "style_background",
"style_background_color", "style_background_color",
"style_width", "style_width",
@ -48,6 +54,12 @@ class ElementHandler:
"style_border_bottom_color", "style_border_bottom_color",
"style_border_bottom_size", "style_border_bottom_size",
"style_padding_bottom", "style_padding_bottom",
"style_border_left_color",
"style_border_left_size",
"style_padding_left",
"style_border_right_color",
"style_border_right_size",
"style_padding_right",
"style_background", "style_background",
"style_background_color", "style_background_color",
"style_width", "style_width",

View file

@ -109,7 +109,7 @@ class Element(
default=0, help_text="Pixel height of the top border." default=0, help_text="Pixel height of the top border."
) )
style_padding_top = models.PositiveIntegerField( style_padding_top = models.PositiveIntegerField(
default=10, help_text="Padding height of the top border." default=10, help_text="Padding size of the top border."
) )
style_border_bottom_color = models.CharField( style_border_bottom_color = models.CharField(
@ -122,7 +122,33 @@ class Element(
default=0, help_text="Pixel height of the bottom border." default=0, help_text="Pixel height of the bottom border."
) )
style_padding_bottom = models.PositiveIntegerField( style_padding_bottom = models.PositiveIntegerField(
default=10, help_text="Padding height of the bottom border." default=10, help_text="Padding size of the bottom border."
)
style_border_left_color = models.CharField(
max_length=20,
default="border",
blank=True,
help_text="Left border color",
)
style_border_left_size = models.PositiveIntegerField(
default=0, help_text="Pixel height of the left border."
)
style_padding_left = models.PositiveIntegerField(
default=20, help_text="Padding size of the left border."
)
style_border_right_color = models.CharField(
max_length=20,
default="border",
blank=True,
help_text="Right border color",
)
style_border_right_size = models.PositiveIntegerField(
default=0, help_text="Pixel height of the right border."
)
style_padding_right = models.PositiveIntegerField(
default=20, help_text="Padding size of the right border."
) )
style_background = models.CharField( style_background = models.CharField(
@ -281,7 +307,7 @@ class ColumnElement(ContainerElement):
], ],
) )
column_gap = models.IntegerField( column_gap = models.IntegerField(
default=30, default=20,
help_text="The amount of space between the columns.", help_text="The amount of space between the columns.",
validators=[ validators=[
MinValueValidator(0, message="Value cannot be less than 0."), MinValueValidator(0, message="Value cannot be less than 0."),
@ -391,6 +417,12 @@ class LinkElement(Element):
max_length=10, max_length=10,
default=HorizontalAlignments.LEFT, default=HorizontalAlignments.LEFT,
) )
button_color = models.CharField(
max_length=20,
default="primary",
blank=True,
help_text="The color of the button",
)
class ImageElement(Element): class ImageElement(Element):
@ -479,6 +511,12 @@ class ButtonElement(Element):
max_length=10, max_length=10,
default=HorizontalAlignments.LEFT, default=HorizontalAlignments.LEFT,
) )
button_color = models.CharField(
max_length=20,
default="primary",
blank=True,
help_text="The color of the button",
)
class CollectionField(models.Model): class CollectionField(models.Model):
@ -542,6 +580,13 @@ class TableElement(CollectionElement):
A table element A table element
""" """
button_color = models.CharField(
max_length=20,
default="primary",
blank=True,
help_text="The color of the button",
)
class FormContainerElement(ContainerElement): class FormContainerElement(ContainerElement):
""" """
@ -550,6 +595,13 @@ class FormContainerElement(ContainerElement):
submit_button_label = FormulaField(default="") submit_button_label = FormulaField(default="")
button_color = models.CharField(
max_length=20,
default="primary",
blank=True,
help_text="The color of the button",
)
class DropdownElement(Element): class DropdownElement(Element):
label = FormulaField( label = FormulaField(

View file

@ -0,0 +1,131 @@
# Generated by Django 3.2.21 on 2023-12-19 13:35
import django.core.validators
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("builder", "0034_dropdownelement_dropdownelementoption"),
]
operations = [
migrations.AddField(
model_name="buttonelement",
name="button_color",
field=models.CharField(
blank=True,
default="primary",
help_text="The color of the button",
max_length=20,
),
),
migrations.AddField(
model_name="element",
name="style_border_left_color",
field=models.CharField(
blank=True,
default="border",
help_text="Left border color",
max_length=20,
),
),
migrations.AddField(
model_name="element",
name="style_border_left_size",
field=models.PositiveIntegerField(
default=0, help_text="Pixel height of the left border."
),
),
migrations.AddField(
model_name="element",
name="style_border_right_color",
field=models.CharField(
blank=True,
default="border",
help_text="Right border color",
max_length=20,
),
),
migrations.AddField(
model_name="element",
name="style_border_right_size",
field=models.PositiveIntegerField(
default=0, help_text="Pixel height of the right border."
),
),
migrations.AddField(
model_name="element",
name="style_padding_left",
field=models.PositiveIntegerField(
default=20, help_text="Padding size of the left border."
),
),
migrations.AddField(
model_name="element",
name="style_padding_right",
field=models.PositiveIntegerField(
default=20, help_text="Padding size of the right border."
),
),
migrations.AddField(
model_name="formcontainerelement",
name="button_color",
field=models.CharField(
blank=True,
default="primary",
help_text="The color of the button",
max_length=20,
),
),
migrations.AddField(
model_name="linkelement",
name="button_color",
field=models.CharField(
blank=True,
default="primary",
help_text="The color of the button",
max_length=20,
),
),
migrations.AddField(
model_name="tableelement",
name="button_color",
field=models.CharField(
blank=True,
default="primary",
help_text="The color of the button",
max_length=20,
),
),
migrations.AlterField(
model_name="columnelement",
name="column_gap",
field=models.IntegerField(
default=20,
help_text="The amount of space between the columns.",
validators=[
django.core.validators.MinValueValidator(
0, message="Value cannot be less than 0."
),
django.core.validators.MaxValueValidator(
2000, message="Value cannot be greater than 2000."
),
],
),
),
migrations.AlterField(
model_name="element",
name="style_padding_bottom",
field=models.PositiveIntegerField(
default=10, help_text="Padding size of the bottom border."
),
),
migrations.AlterField(
model_name="element",
name="style_padding_top",
field=models.PositiveIntegerField(
default=10, help_text="Padding size of the top border."
),
),
]

View file

@ -19,6 +19,12 @@ class ElementDict(TypedDict):
style_border_bottom_color: str style_border_bottom_color: str
style_border_bottom_size: int style_border_bottom_size: int
style_padding_bottom: int style_padding_bottom: int
style_border_left_color: str
style_border_left_size: int
style_padding_left: int
style_border_right_color: str
style_border_right_size: int
style_padding_right: int
style_background: str style_background: str
style_background_color: str style_background_color: str
style_width: str style_width: str

View file

@ -128,14 +128,21 @@ def test_builder_application_export(data_fixture):
"order": str(element1.order), "order": str(element1.order),
"parent_element_id": None, "parent_element_id": None,
"place_in_container": None, "place_in_container": None,
"font_color": "default",
"style_background_color": "#ffffffff", "style_background_color": "#ffffffff",
"style_border_bottom_color": "border", "style_border_bottom_color": "border",
"style_border_bottom_size": 0, "style_border_bottom_size": 0,
"style_border_top_color": "border", "style_border_top_color": "border",
"style_border_top_size": 0, "style_border_top_size": 0,
"style_border_left_color": "border",
"style_border_left_size": 0,
"style_border_right_color": "border",
"style_border_right_size": 0,
"style_width": "normal", "style_width": "normal",
"style_padding_top": 10, "style_padding_top": 10,
"style_padding_bottom": 10, "style_padding_bottom": 10,
"style_padding_left": 20,
"style_padding_right": 20,
"style_background": "none", "style_background": "none",
"value": element1.value, "value": element1.value,
"level": element1.level, "level": element1.level,
@ -151,9 +158,15 @@ def test_builder_application_export(data_fixture):
"style_border_bottom_size": 0, "style_border_bottom_size": 0,
"style_border_top_color": "border", "style_border_top_color": "border",
"style_border_top_size": 0, "style_border_top_size": 0,
"style_border_left_color": "border",
"style_border_left_size": 0,
"style_border_right_color": "border",
"style_border_right_size": 0,
"style_width": "normal", "style_width": "normal",
"style_padding_top": 10, "style_padding_top": 10,
"style_padding_bottom": 10, "style_padding_bottom": 10,
"style_padding_left": 20,
"style_padding_right": 20,
"style_background": "none", "style_background": "none",
"value": element2.value, "value": element2.value,
}, },
@ -167,9 +180,15 @@ def test_builder_application_export(data_fixture):
"style_border_bottom_size": 0, "style_border_bottom_size": 0,
"style_border_top_color": "border", "style_border_top_color": "border",
"style_border_top_size": 0, "style_border_top_size": 0,
"style_border_left_color": "border",
"style_border_left_size": 0,
"style_border_right_color": "border",
"style_border_right_size": 0,
"style_width": "normal", "style_width": "normal",
"style_padding_top": 10, "style_padding_top": 10,
"style_padding_bottom": 10, "style_padding_bottom": 10,
"style_padding_left": 20,
"style_padding_right": 20,
"style_background": "none", "style_background": "none",
"order": str(element_container.order), "order": str(element_container.order),
"column_amount": 3, "column_amount": 3,
@ -186,9 +205,15 @@ def test_builder_application_export(data_fixture):
"style_border_bottom_size": 0, "style_border_bottom_size": 0,
"style_border_top_color": "border", "style_border_top_color": "border",
"style_border_top_size": 0, "style_border_top_size": 0,
"style_border_left_color": "border",
"style_border_left_size": 0,
"style_border_right_color": "border",
"style_border_right_size": 0,
"style_width": "normal", "style_width": "normal",
"style_padding_top": 10, "style_padding_top": 10,
"style_padding_bottom": 10, "style_padding_bottom": 10,
"style_padding_left": 20,
"style_padding_right": 20,
"style_background": "none", "style_background": "none",
"order": str(element_inside_container.order), "order": str(element_inside_container.order),
"value": element_inside_container.value, "value": element_inside_container.value,
@ -241,14 +266,21 @@ def test_builder_application_export(data_fixture):
"order": str(element3.order), "order": str(element3.order),
"parent_element_id": None, "parent_element_id": None,
"place_in_container": None, "place_in_container": None,
"font_color": "default",
"style_background_color": "#ffffffff", "style_background_color": "#ffffffff",
"style_border_bottom_color": "border", "style_border_bottom_color": "border",
"style_border_bottom_size": 0, "style_border_bottom_size": 0,
"style_border_top_color": "border", "style_border_top_color": "border",
"style_border_top_size": 0, "style_border_top_size": 0,
"style_border_left_color": "border",
"style_border_left_size": 0,
"style_border_right_color": "border",
"style_border_right_size": 0,
"style_width": "normal", "style_width": "normal",
"style_padding_top": 10, "style_padding_top": 10,
"style_padding_bottom": 10, "style_padding_bottom": 10,
"style_padding_left": 20,
"style_padding_right": 20,
"style_background": "none", "style_background": "none",
"value": element3.value, "value": element3.value,
"level": element3.level, "level": element3.level,
@ -257,6 +289,7 @@ def test_builder_application_export(data_fixture):
"id": element4.id, "id": element4.id,
"type": "table", "type": "table",
"order": str(element4.order), "order": str(element4.order),
"button_color": "primary",
"parent_element_id": None, "parent_element_id": None,
"place_in_container": None, "place_in_container": None,
"style_background_color": "#ffffffff", "style_background_color": "#ffffffff",
@ -264,9 +297,15 @@ def test_builder_application_export(data_fixture):
"style_border_bottom_size": 0, "style_border_bottom_size": 0,
"style_border_top_color": "border", "style_border_top_color": "border",
"style_border_top_size": 0, "style_border_top_size": 0,
"style_border_left_color": "border",
"style_border_left_size": 0,
"style_border_right_color": "border",
"style_border_right_size": 0,
"style_width": "normal", "style_width": "normal",
"style_padding_top": 10, "style_padding_top": 10,
"style_padding_bottom": 10, "style_padding_bottom": 10,
"style_padding_left": 20,
"style_padding_right": 20,
"style_background": "none", "style_background": "none",
"items_per_page": 42, "items_per_page": 42,
"data_source_id": element4.data_source.id, "data_source_id": element4.data_source.id,

View file

@ -73,7 +73,8 @@
"requiredField": "This field is required.", "requiredField": "This field is required.",
"integerField": "The field must be an integer.", "integerField": "The field must be an integer.",
"minValueField": "The field must be greater than or equal to {min}.", "minValueField": "The field must be greater than or equal to {min}.",
"maxValueField": "The field must be less than or equal to {max}." "maxValueField": "The field must be less than or equal to {max}.",
"minMaxValueField": "The field value must be between {min} and {max}."
}, },
"permission": { "permission": {
"admin": "Admin", "admin": "Admin",

View file

@ -25,11 +25,11 @@
@select-parent="actionSelectElement({ element: parentElement })" @select-parent="actionSelectElement({ element: parentElement })"
/> />
<PageRootElement <PageElement
v-if="isRootElement" v-if="isRootElement"
:element="element" :element="element"
:mode="mode" :mode="mode"
></PageRootElement> ></PageElement>
<PageElement v-else :element="element" :mode="mode" /> <PageElement v-else :element="element" :mode="mode" />
<InsertElementButton <InsertElementButton
@ -58,7 +58,6 @@ import { PLACEMENTS } from '@baserow/modules/builder/enums'
import AddElementModal from '@baserow/modules/builder/components/elements/AddElementModal' import AddElementModal from '@baserow/modules/builder/components/elements/AddElementModal'
import { notifyIf } from '@baserow/modules/core/utils/error' import { notifyIf } from '@baserow/modules/core/utils/error'
import { mapActions, mapGetters } from 'vuex' import { mapActions, mapGetters } from 'vuex'
import PageRootElement from '@baserow/modules/builder/components/page/PageRootElement'
import { checkIntermediateElements } from '@baserow/modules/core/utils/dom' import { checkIntermediateElements } from '@baserow/modules/core/utils/dom'
export default { export default {
@ -68,7 +67,6 @@ export default {
ElementMenu, ElementMenu,
InsertElementButton, InsertElementButton,
PageElement, PageElement,
PageRootElement,
}, },
inject: ['builder', 'page', 'mode'], inject: ['builder', 'page', 'mode'],
props: { props: {

View file

@ -1,5 +1,11 @@
<template> <template>
<div class="button-element" :class="classes"> <div
class="button-element"
:class="classes"
:style="{
'--button-color': resolveColor(element.button_color, colorVariables),
}"
>
<button <button
class="link-button-element-button" class="link-button-element-button"
:class="{ :class="{

View file

@ -1,5 +1,9 @@
<template> <template>
<div> <div
:style="{
'--button-color': resolveColor(element.button_color, colorVariables),
}"
>
<div v-if="mode === 'editing' && children.length === 0"> <div v-if="mode === 'editing' && children.length === 0">
<AddElementZone @add-element="showAddElementModal"></AddElementZone> <AddElementZone @add-element="showAddElementModal"></AddElementZone>
<AddElementModal <AddElementModal

View file

@ -5,6 +5,7 @@
:class="{ 'element--no-value': !resolvedValue }" :class="{ 'element--no-value': !resolvedValue }"
:style="{ :style="{
'--color': resolveColor(element.font_color, headingColorVariables), '--color': resolveColor(element.font_color, headingColorVariables),
'--font-size': `${builder.theme[`heading_${element.level}_font_size`]}px`,
}" }"
> >
{{ resolvedValue || $t('headingElement.noValue') }} {{ resolvedValue || $t('headingElement.noValue') }}

View file

@ -1,5 +1,11 @@
<template> <template>
<div class="link-element" :class="classes"> <div
class="link-element"
:class="classes"
:style="{
'--button-color': resolveColor(element.button_color, colorVariables),
}"
>
<a <a
:class="{ :class="{
'link-element__link': element.variant !== 'button', 'link-element__link': element.variant !== 'button',

View file

@ -1,5 +1,9 @@
<template> <template>
<div> <div
:style="{
'--button-color': resolveColor(element.button_color, colorVariables),
}"
>
<BaserowTable :fields="element.fields" :rows="rows"> <BaserowTable :fields="element.fields" :rows="rows">
<template #cell-content="{ field, value }"> <template #cell-content="{ field, value }">
<component <component

View file

@ -12,20 +12,21 @@
<FormElement class="control"> <FormElement class="control">
<WidthSelector v-model="values.width" /> <WidthSelector v-model="values.width" />
</FormElement> </FormElement>
<ColorInputGroup
v-model="values.button_color"
:label="$t('buttonElementForm.buttonColor')"
:color-variables="colorVariables"
/>
</form> </form>
</template> </template>
<script> <script>
import ApplicationBuilderFormulaInputGroup from '@baserow/modules/builder/components/ApplicationBuilderFormulaInputGroup' import ApplicationBuilderFormulaInputGroup from '@baserow/modules/builder/components/ApplicationBuilderFormulaInputGroup'
import form from '@baserow/modules/core/mixins/form' import { HORIZONTAL_ALIGNMENTS, WIDTHS } from '@baserow/modules/builder/enums'
import {
DATA_PROVIDERS_ALLOWED_ELEMENTS,
HORIZONTAL_ALIGNMENTS,
WIDTHS,
} from '@baserow/modules/builder/enums'
import HorizontalAlignmentsSelector from '@baserow/modules/builder/components/elements/components/forms/general/settings/HorizontalAlignmentsSelector' import HorizontalAlignmentsSelector from '@baserow/modules/builder/components/elements/components/forms/general/settings/HorizontalAlignmentsSelector'
import WidthSelector from '@baserow/modules/builder/components/elements/components/forms/general/settings/WidthSelector' import WidthSelector from '@baserow/modules/builder/components/elements/components/forms/general/settings/WidthSelector'
import { themeToColorVariables } from '@baserow/modules/builder/utils/theme'
import elementForm from '@baserow/modules/builder/mixins/elementForm'
export default { export default {
name: 'ButtonElementForm', name: 'ButtonElementForm',
@ -34,7 +35,7 @@ export default {
ApplicationBuilderFormulaInputGroup, ApplicationBuilderFormulaInputGroup,
HorizontalAlignmentsSelector, HorizontalAlignmentsSelector,
}, },
mixins: [form], mixins: [elementForm],
data() { data() {
return { return {
values: { values: {
@ -45,7 +46,9 @@ export default {
} }
}, },
computed: { computed: {
DATA_PROVIDERS_ALLOWED_ELEMENTS: () => DATA_PROVIDERS_ALLOWED_ELEMENTS, colorVariables() {
return themeToColorVariables(this.builder.theme)
},
}, },
} }
</script> </script>

View file

@ -48,13 +48,14 @@ import form from '@baserow/modules/core/mixins/form'
import { VERTICAL_ALIGNMENTS } from '@baserow/modules/builder/enums' import { VERTICAL_ALIGNMENTS } from '@baserow/modules/builder/enums'
import { required, integer, minValue, maxValue } from 'vuelidate/lib/validators' import { required, integer, minValue, maxValue } from 'vuelidate/lib/validators'
import VerticalAlignmentSelector from '@baserow/modules/builder/components/elements/components/forms/general/settings/VerticalAlignmentSelector' import VerticalAlignmentSelector from '@baserow/modules/builder/components/elements/components/forms/general/settings/VerticalAlignmentSelector'
import elementForm from '@baserow/modules/builder/mixins/elementForm'
export default { export default {
name: 'ColumnElementForm', name: 'ColumnElementForm',
components: { components: {
VerticalAlignmentSelector, VerticalAlignmentSelector,
}, },
mixins: [form], mixins: [elementForm],
data() { data() {
return { return {
values: { values: {

View file

@ -6,18 +6,22 @@
:label="$t('formContainerElementForm.submitButtonLabel')" :label="$t('formContainerElementForm.submitButtonLabel')"
:placeholder="$t('formContainerElementForm.submitButtonPlaceholder')" :placeholder="$t('formContainerElementForm.submitButtonPlaceholder')"
/> />
<ColorInputGroup
v-model="values.button_color"
:label="$t('formContainerElementForm.buttonColor')"
:color-variables="colorVariables"
/>
</form> </form>
</template> </template>
<script> <script>
import form from '@baserow/modules/core/mixins/form'
import ApplicationBuilderFormulaInputGroup from '@baserow/modules/builder/components/ApplicationBuilderFormulaInputGroup.vue' import ApplicationBuilderFormulaInputGroup from '@baserow/modules/builder/components/ApplicationBuilderFormulaInputGroup.vue'
import { DATA_PROVIDERS_ALLOWED_ELEMENTS } from '@baserow/modules/builder/enums' import elementForm from '@baserow/modules/builder/mixins/elementForm'
export default { export default {
name: 'FormContainerElementForm', name: 'FormContainerElementForm',
components: { ApplicationBuilderFormulaInputGroup }, components: { ApplicationBuilderFormulaInputGroup },
mixins: [form], mixins: [elementForm],
data() { data() {
return { return {
values: { values: {
@ -25,8 +29,5 @@ export default {
}, },
} }
}, },
computed: {
DATA_PROVIDERS_ALLOWED_ELEMENTS: () => DATA_PROVIDERS_ALLOWED_ELEMENTS,
},
} }
</script> </script>

View file

@ -1,22 +1,17 @@
<template> <template>
<form @submit.prevent @keydown.enter.prevent> <form @submit.prevent @keydown.enter.prevent>
<FormElement class="control"> <FormGroup :label="$t('headingElementForm.levelTitle')">
<label class="control__label"> <Dropdown v-model="values.level" :show-search="false">
{{ $t('headingElementForm.levelTitle') }} <DropdownItem
</label> v-for="level in levels"
<div class="control__elements"> :key="level.value"
<Dropdown v-model="values.level" :show-search="false"> :name="level.name"
<DropdownItem :value="level.value"
v-for="level in levels" >
:key="level.value" {{ level.name }}
:name="level.name" </DropdownItem>
:value="level.value" </Dropdown>
> </FormGroup>
{{ level.name }}
</DropdownItem>
</Dropdown>
</div>
</FormElement>
<ApplicationBuilderFormulaInputGroup <ApplicationBuilderFormulaInputGroup
v-model="values.value" v-model="values.value"
:label="$t('headingElementForm.textTitle')" :label="$t('headingElementForm.textTitle')"
@ -32,22 +27,24 @@
</template> </template>
<script> <script>
import form from '@baserow/modules/core/mixins/form'
import { DATA_PROVIDERS_ALLOWED_ELEMENTS } from '@baserow/modules/builder/enums'
import ApplicationBuilderFormulaInputGroup from '@baserow/modules/builder/components/ApplicationBuilderFormulaInputGroup' import ApplicationBuilderFormulaInputGroup from '@baserow/modules/builder/components/ApplicationBuilderFormulaInputGroup'
import headingElement from '@baserow/modules/builder/mixins/headingElement' import headingElement from '@baserow/modules/builder/mixins/headingElement'
import FontSelector from '@baserow/modules/builder/components/elements/components/forms/general/settings/FontSelector' import FontSelector from '@baserow/modules/builder/components/elements/components/forms/general/settings/FontSelector'
import elementForm from '@baserow/modules/builder/mixins/elementForm'
export default { export default {
name: 'HeaderElementForm', name: 'HeaderElementForm',
components: { FontSelector, ApplicationBuilderFormulaInputGroup }, components: {
mixins: [form, headingElement], FontSelector,
inject: ['builder'], ApplicationBuilderFormulaInputGroup,
},
mixins: [elementForm, headingElement],
data() { data() {
return { return {
values: { values: {
value: '', value: '',
level: 1, level: 1,
font_color: '',
}, },
levels: [...Array(6).keys()].map((level) => ({ levels: [...Array(6).keys()].map((level) => ({
name: this.$t('headingElementForm.headingName', { level: level + 1 }), name: this.$t('headingElementForm.headingName', { level: level + 1 }),
@ -55,8 +52,5 @@ export default {
})), })),
} }
}, },
computed: {
DATA_PROVIDERS_ALLOWED_ELEMENTS: () => DATA_PROVIDERS_ALLOWED_ELEMENTS,
},
} }
</script> </script>

View file

@ -46,7 +46,6 @@
<FormElement <FormElement
v-if="values.image_source_type === IMAGE_SOURCE_TYPES.URL" v-if="values.image_source_type === IMAGE_SOURCE_TYPES.URL"
class="control" class="control"
:error="fieldHasErrors('image_url')"
> >
<div class="control__elements"> <div class="control__elements">
<div class="control__description"> <div class="control__description">
@ -54,7 +53,6 @@
</div> </div>
<ApplicationBuilderFormulaInputGroup <ApplicationBuilderFormulaInputGroup
v-model="values.image_url" v-model="values.image_url"
:class="{ 'input--error': fieldHasErrors('image_url') }"
:placeholder="$t('elementForms.urlInputPlaceholder')" :placeholder="$t('elementForms.urlInputPlaceholder')"
:data-providers-allowed="DATA_PROVIDERS_ALLOWED_ELEMENTS" :data-providers-allowed="DATA_PROVIDERS_ALLOWED_ELEMENTS"
/> />
@ -82,9 +80,7 @@
</template> </template>
<script> <script>
import form from '@baserow/modules/core/mixins/form'
import { import {
DATA_PROVIDERS_ALLOWED_ELEMENTS,
HORIZONTAL_ALIGNMENTS, HORIZONTAL_ALIGNMENTS,
IMAGE_SOURCE_TYPES, IMAGE_SOURCE_TYPES,
} from '@baserow/modules/builder/enums' } from '@baserow/modules/builder/enums'
@ -93,6 +89,7 @@ import UserFilesModal from '@baserow/modules/core/components/files/UserFilesModa
import { UploadFileUserFileUploadType } from '@baserow/modules/core/userFileUploadTypes' import { UploadFileUserFileUploadType } from '@baserow/modules/core/userFileUploadTypes'
import HorizontalAlignmentSelector from '@baserow/modules/builder/components/elements/components/forms/general/settings/HorizontalAlignmentsSelector' import HorizontalAlignmentSelector from '@baserow/modules/builder/components/elements/components/forms/general/settings/HorizontalAlignmentsSelector'
import ApplicationBuilderFormulaInputGroup from '@baserow/modules/builder/components/ApplicationBuilderFormulaInputGroup.vue' import ApplicationBuilderFormulaInputGroup from '@baserow/modules/builder/components/ApplicationBuilderFormulaInputGroup.vue'
import elementForm from '@baserow/modules/builder/mixins/elementForm'
export default { export default {
name: 'ImageElementForm', name: 'ImageElementForm',
@ -101,7 +98,7 @@ export default {
HorizontalAlignmentSelector, HorizontalAlignmentSelector,
UserFilesModal, UserFilesModal,
}, },
mixins: [form], mixins: [elementForm],
data() { data() {
return { return {
values: { values: {
@ -120,7 +117,6 @@ export default {
IMAGE_FILE_TYPES() { IMAGE_FILE_TYPES() {
return IMAGE_FILE_TYPES return IMAGE_FILE_TYPES
}, },
DATA_PROVIDERS_ALLOWED_ELEMENTS: () => DATA_PROVIDERS_ALLOWED_ELEMENTS,
}, },
methods: { methods: {
openFileUploadModal() { openFileUploadModal() {

View file

@ -32,12 +32,12 @@
<script> <script>
import form from '@baserow/modules/core/mixins/form' import form from '@baserow/modules/core/mixins/form'
import ApplicationBuilderFormulaInputGroup from '@baserow/modules/builder/components/ApplicationBuilderFormulaInputGroup.vue' import ApplicationBuilderFormulaInputGroup from '@baserow/modules/builder/components/ApplicationBuilderFormulaInputGroup.vue'
import { DATA_PROVIDERS_ALLOWED_FORM_ELEMENTS } from '@baserow/modules/builder/enums' import elementForm from '@baserow/modules/builder/mixins/elementForm'
export default { export default {
name: 'InputTextElementForm', name: 'InputTextElementForm',
components: { ApplicationBuilderFormulaInputGroup }, components: { ApplicationBuilderFormulaInputGroup },
mixins: [form], mixins: [elementForm],
data() { data() {
return { return {
values: { values: {
@ -48,10 +48,6 @@ export default {
}, },
} }
}, },
computed: {
DATA_PROVIDERS_ALLOWED_FORM_ELEMENTS: () =>
DATA_PROVIDERS_ALLOWED_FORM_ELEMENTS,
},
methods: { methods: {
emitChange(newValues) { emitChange(newValues) {
if (this.isFormValid()) { if (this.isFormValid()) {

View file

@ -113,21 +113,22 @@
<FormElement v-if="values.variant === 'button'" class="control"> <FormElement v-if="values.variant === 'button'" class="control">
<WidthSelector v-model="values.width" /> <WidthSelector v-model="values.width" />
</FormElement> </FormElement>
<ColorInputGroup
v-model="values.button_color"
:label="$t('linkElementForm.buttonColor')"
:color-variables="colorVariables"
/>
</form> </form>
</template> </template>
<script> <script>
import form from '@baserow/modules/core/mixins/form'
import { LinkElementType } from '@baserow/modules/builder/elementTypes' import { LinkElementType } from '@baserow/modules/builder/elementTypes'
import HorizontalAlignmentSelector from '@baserow/modules/builder/components/elements/components/forms/general/settings/HorizontalAlignmentsSelector' import HorizontalAlignmentSelector from '@baserow/modules/builder/components/elements/components/forms/general/settings/HorizontalAlignmentsSelector'
import { import { HORIZONTAL_ALIGNMENTS, WIDTHS } from '@baserow/modules/builder/enums'
DATA_PROVIDERS_ALLOWED_ELEMENTS,
HORIZONTAL_ALIGNMENTS,
WIDTHS,
} from '@baserow/modules/builder/enums'
import WidthSelector from '@baserow/modules/builder/components/elements/components/forms/general/settings/WidthSelector' import WidthSelector from '@baserow/modules/builder/components/elements/components/forms/general/settings/WidthSelector'
import { PageParameterDataProviderType } from '@baserow/modules/builder/dataProviderTypes' import { PageParameterDataProviderType } from '@baserow/modules/builder/dataProviderTypes'
import ApplicationBuilderFormulaInputGroup from '@baserow/modules/builder/components/ApplicationBuilderFormulaInputGroup' import ApplicationBuilderFormulaInputGroup from '@baserow/modules/builder/components/ApplicationBuilderFormulaInputGroup'
import elementForm from '@baserow/modules/builder/mixins/elementForm'
export default { export default {
name: 'LinkElementForm', name: 'LinkElementForm',
@ -136,8 +137,7 @@ export default {
ApplicationBuilderFormulaInputGroup, ApplicationBuilderFormulaInputGroup,
HorizontalAlignmentSelector, HorizontalAlignmentSelector,
}, },
mixins: [form], mixins: [elementForm],
inject: ['builder', 'page'],
data() { data() {
let navigateTo = '' let navigateTo = ''
if (this.defaultValues.navigation_type === 'page') { if (this.defaultValues.navigation_type === 'page') {
@ -164,7 +164,6 @@ export default {
} }
}, },
computed: { computed: {
DATA_PROVIDERS_ALLOWED_ELEMENTS: () => DATA_PROVIDERS_ALLOWED_ELEMENTS,
DATA_PROVIDERS_ALLOWED_PAGE_PARAMETERS() { DATA_PROVIDERS_ALLOWED_PAGE_PARAMETERS() {
const PROVIDERS_TO_REMOVE = [ const PROVIDERS_TO_REMOVE = [
new PageParameterDataProviderType().getType(), new PageParameterDataProviderType().getType(),

View file

@ -10,15 +10,13 @@
</template> </template>
<script> <script>
import form from '@baserow/modules/core/mixins/form'
import { DATA_PROVIDERS_ALLOWED_ELEMENTS } from '@baserow/modules/builder/enums'
import ApplicationBuilderFormulaInputGroup from '@baserow/modules/builder/components/ApplicationBuilderFormulaInputGroup' import ApplicationBuilderFormulaInputGroup from '@baserow/modules/builder/components/ApplicationBuilderFormulaInputGroup'
import elementForm from '@baserow/modules/builder/mixins/elementForm'
export default { export default {
name: 'ParagraphElementForm', name: 'ParagraphElementForm',
components: { ApplicationBuilderFormulaInputGroup }, components: { ApplicationBuilderFormulaInputGroup },
mixins: [form], mixins: [elementForm],
data() { data() {
return { return {
values: { values: {
@ -26,8 +24,5 @@ export default {
}, },
} }
}, },
computed: {
DATA_PROVIDERS_ALLOWED_ELEMENTS: () => DATA_PROVIDERS_ALLOWED_ELEMENTS,
},
} }
</script> </script>

View file

@ -133,12 +133,15 @@
</template> </template>
<p v-else>{{ $t('tableElementForm.selectSourceFirst') }}</p> <p v-else>{{ $t('tableElementForm.selectSourceFirst') }}</p>
</FormElement> </FormElement>
<ColorInputGroup
v-model="values.button_color"
:label="$t('tableElementForm.buttonColor')"
:color-variables="colorVariables"
/>
</form> </form>
</template> </template>
<script> <script>
import form from '@baserow/modules/core/mixins/form'
import { DATA_PROVIDERS_ALLOWED_ELEMENTS } from '@baserow/modules/builder/enums'
import ApplicationBuilderFormulaInputGroup from '@baserow/modules/builder/components/ApplicationBuilderFormulaInputGroup' import ApplicationBuilderFormulaInputGroup from '@baserow/modules/builder/components/ApplicationBuilderFormulaInputGroup'
import { import {
getNextAvailableNameInSequence, getNextAvailableNameInSequence,
@ -152,12 +155,12 @@ import {
maxValue, maxValue,
} from 'vuelidate/lib/validators' } from 'vuelidate/lib/validators'
import { mapGetters } from 'vuex' import { mapGetters } from 'vuex'
import elementForm from '@baserow/modules/builder/mixins/elementForm'
export default { export default {
name: 'TableElementForm', name: 'TableElementForm',
components: { ApplicationBuilderFormulaInputGroup }, components: { ApplicationBuilderFormulaInputGroup },
mixins: [form], mixins: [elementForm],
inject: ['page'],
data() { data() {
return { return {
allowedValues: ['data_source_id', 'fields', 'items_per_page'], allowedValues: ['data_source_id', 'fields', 'items_per_page'],
@ -206,9 +209,6 @@ export default {
collectionTypes() { collectionTypes() {
return this.$registry.getAll('collectionField') return this.$registry.getAll('collectionField')
}, },
DATA_PROVIDERS_ALLOWED_ELEMENTS() {
return DATA_PROVIDERS_ALLOWED_ELEMENTS
},
...mapGetters({ ...mapGetters({
element: 'element/getSelected', element: 'element/getSelected',
}), }),

View file

@ -1,36 +1,19 @@
<template> <template>
<FormElement class="control"> <ColorInputGroup
<label class="control__label"> v-model="values.font_color"
{{ $t('fontSidePanelForm.label') }} :label="$t('fontSidePanelForm.label')"
</label> :color-variables="colorVariables"
<div class="control__elements"> />
<div class="color-input">
<ColorPickerContext
ref="colorPicker"
v-model="values.font_color"
:variables="colorVariables"
></ColorPickerContext>
<a
ref="fontColor"
class="color-input__preview"
:style="{
'background-color': resolveColor(values.font_color, colorVariables),
}"
@click="$refs.colorPicker.toggle($refs.fontColor)"
></a>
</div>
</div>
</FormElement>
</template> </template>
<script> <script>
import ColorPickerContext from '@baserow/modules/core/components/ColorPickerContext' import ColorInputGroup from '@baserow/modules/core/components/ColorInputGroup'
import form from '@baserow/modules/core/mixins/form' import form from '@baserow/modules/core/mixins/form'
import { resolveColor } from '@baserow/modules/core/utils/colors' import { resolveColor } from '@baserow/modules/core/utils/colors'
export default { export default {
name: 'FontSelector', name: 'FontSelector',
components: { ColorPickerContext }, components: { ColorInputGroup },
mixins: [form], mixins: [form],
props: { props: {
colorVariables: { colorVariables: {

View file

@ -1,74 +1,49 @@
<template> <template>
<form @submit.prevent> <form @submit.prevent>
<StyleBoxForm <StyleBoxForm
v-model="boxStyles.top" v-for="{ name, label } in borders"
:label="$t('defaultStyleForm.boxTop')" :key="name"
:padding-is-allowed="isStyleAllowed('style_padding_top')" v-model="boxStyles[name]"
:border-color-is-allowed="isStyleAllowed('style_border_top_color')" :label="label"
:border-size-is-allowed="isStyleAllowed('style_border_top_size')" :padding-is-allowed="isStyleAllowed(`style_padding_${name}`)"
:border-is-allowed="isStyleAllowed(`style_border_${name}`)"
/> />
<StyleBoxForm <FormGroup
v-model="boxStyles.bottom" v-if="isStyleAllowed('style_background')"
:label="$t('defaultStyleForm.boxBottom')" :label="$t('defaultStyleForm.backgroundLabel')"
:padding-is-allowed="isStyleAllowed('style_padding_bottom')" >
:border-color-is-allowed="isStyleAllowed('style_border_bottom_color')" <Dropdown v-model="values.style_background">
:border-size-is-allowed="isStyleAllowed('style_border_bottom_size')" <DropdownItem
/> v-for="type in Object.values(BACKGROUND_TYPES)"
<FormElement v-if="isStyleAllowed('style_background')" class="control"> :key="type.value"
<label class="control__label">{{ :name="$t(type.name)"
$t('defaultStyleForm.backgroundLabel') :value="type.value"
}}</label> />
<div class="control__elements"> </Dropdown>
<Dropdown v-model="values.style_background"> <ColorInputGroup
<DropdownItem v-if="
v-for="type in Object.values(BACKGROUND_TYPES)" values.style_background === BACKGROUND_TYPES.COLOR.value &&
:key="type.value" isStyleAllowed('style_background_color')
:name="$t(type.name)" "
:value="type.value" v-model="values.style_background_color"
></DropdownItem> label-after
</Dropdown> class="margin-top-2"
<div :label="$t('defaultStyleForm.backgroundColor')"
v-if=" :color-variables="colorVariables"
values.style_background === BACKGROUND_TYPES.COLOR.value && />
isStyleAllowed('style_background_color') </FormGroup>
" <FormGroup
class="color-input margin-top-2" v-if="isStyleAllowed('style_width')"
> :label="$t('defaultStyleForm.widthLabel')"
<ColorPickerContext >
ref="colorPicker" <Dropdown v-model="values.style_width">
v-model="values.style_background_color" <DropdownItem
:variables="colorVariables" v-for="type in Object.values(WIDTH_TYPES)"
></ColorPickerContext> :key="type.value"
<a :name="$t(type.name)"
ref="backgroundColor" :value="type.value"
class="color-input__preview margin-right-2" ></DropdownItem> </Dropdown
:style="{ ></FormGroup>
'background-color': resolveColor(
values.style_background_color,
colorVariables
),
}"
@click="$refs.colorPicker.toggle($refs.backgroundColor)"
></a>
{{ $t('defaultStyleForm.backgroundColor') }}
</div>
</div>
</FormElement>
<FormElement v-if="isStyleAllowed('style_width')" class="control">
<label class="control__label">{{
$t('defaultStyleForm.widthLabel')
}}</label>
<div class="control__elements">
<Dropdown v-model="values.style_width">
<DropdownItem
v-for="type in Object.values(WIDTH_TYPES)"
:key="type.value"
:name="$t(type.name)"
:value="type.value"
></DropdownItem>
</Dropdown>
</div>
</FormElement>
</form> </form>
</template> </template>
@ -76,10 +51,9 @@
import StyleBoxForm from '@baserow/modules/builder/components/elements/components/forms/style/StyleBoxForm' import StyleBoxForm from '@baserow/modules/builder/components/elements/components/forms/style/StyleBoxForm'
import styleForm from '@baserow/modules/builder/mixins/styleForm' import styleForm from '@baserow/modules/builder/mixins/styleForm'
import { BACKGROUND_TYPES, WIDTH_TYPES } from '@baserow/modules/builder/enums' import { BACKGROUND_TYPES, WIDTH_TYPES } from '@baserow/modules/builder/enums'
import ColorPickerContext from '@baserow/modules/core/components/ColorPickerContext'
export default { export default {
components: { StyleBoxForm, ColorPickerContext }, components: { StyleBoxForm },
mixins: [styleForm], mixins: [styleForm],
computed: { computed: {
BACKGROUND_TYPES: () => BACKGROUND_TYPES, BACKGROUND_TYPES: () => BACKGROUND_TYPES,

View file

@ -1,79 +1,60 @@
<template> <template>
<form @submit.prevent> <form @submit.prevent>
<FormElement class="control"> <FormGroup :label="label" :error="error">
<label class="control__label">{{ label }}</label> <div
<div class="control__elements"> v-if="borderIsAllowed || paddingIsAllowed"
<div class="row margin-bottom-2"
v-if="borderSizeIsAllowed || paddingIsAllowed" style="--gap: 6px"
class="row margin-bottom-2" >
style="--gap: 6px" <div v-if="borderIsAllowed" class="col col-3">
> <div class="margin-bottom-1">
<div v-if="borderSizeIsAllowed" class="col col-3"> {{ $t('styleBoxForm.borderLabel') }}
<div class="margin-bottom-1">
{{ $t('styleBoxForm.borderLabel') }}
</div>
<input
v-model="values.border_size"
type="number"
class="input"
:class="{
'input--error': error,
}"
@blur="$v.values.border_size.$touch()"
/>
</div> </div>
<div v-if="paddingIsAllowed" class="col col-3"> <input
<div class="margin-bottom-1"> v-model="values.border_size"
{{ $t('styleBoxForm.paddingLabel') }} type="number"
</div> class="input"
<input :class="{
v-model="values.padding" 'input--error': error,
type="number"
class="input"
:class="{
'input--error': error,
}"
@blur="$v.values.padding.$touch()"
/>
</div>
</div>
<div v-if="borderColorIsAllowed" class="color-input">
<ColorPickerContext
ref="colorPicker"
v-model="values.border_color"
:variables="colorVariables"
></ColorPickerContext>
<a
ref="borderColor"
class="color-input__preview margin-right-2"
:style="{
'background-color': resolveColor(
values.border_color,
colorVariables
),
}" }"
@click="$refs.colorPicker.toggle($refs.borderColor)" @blur="$v.values.border_size.$touch()"
></a> />
{{ $t('styleBoxForm.borderLabel') }}
</div> </div>
<div v-if="error" class="error"> <div v-if="paddingIsAllowed" class="col col-3">
{{ error }} <div class="margin-bottom-1">
{{ $t('styleBoxForm.paddingLabel') }}
</div>
<input
v-model="values.padding"
type="number"
class="input"
:class="{
'input--error': error,
}"
@blur="$v.values.padding.$touch()"
/>
</div> </div>
</div> </div>
</FormElement> <ColorInputGroup
v-if="borderIsAllowed"
v-model="values.border_color"
label-after
class="margin-top-2"
:label="$t('styleBoxForm.borderLabel')"
:color-variables="colorVariables"
/>
</FormGroup>
</form> </form>
</template> </template>
<script> <script>
import { required, integer, between } from 'vuelidate/lib/validators' import { required, integer, between } from 'vuelidate/lib/validators'
import form from '@baserow/modules/core/mixins/form' import form from '@baserow/modules/core/mixins/form'
import ColorPickerContext from '@baserow/modules/core/components/ColorPickerContext.vue'
import { resolveColor } from '@baserow/modules/core/utils/colors' import { resolveColor } from '@baserow/modules/core/utils/colors'
import { themeToColorVariables } from '@baserow/modules/builder/utils/theme' import { themeToColorVariables } from '@baserow/modules/builder/utils/theme'
export default { export default {
name: 'StyleBoxForm', name: 'StyleBoxForm',
components: { ColorPickerContext },
mixins: [form], mixins: [form],
inject: ['builder'], inject: ['builder'],
props: { props: {
@ -90,12 +71,7 @@ export default {
required: false, required: false,
default: () => false, default: () => false,
}, },
borderColorIsAllowed: { borderIsAllowed: {
type: Boolean,
required: false,
default: () => false,
},
borderSizeIsAllowed: {
type: Boolean, type: Boolean,
required: false, required: false,
default: () => false, default: () => false,
@ -120,7 +96,7 @@ export default {
*/ */
error() { error() {
if (this.$v.values.padding.$error || this.$v.values.border_size.$error) { if (this.$v.values.padding.$error || this.$v.values.border_size.$error) {
return this.$t('error.minMaxLength', { min: 0, max: 200 }) return this.$t('error.minMaxValueField', { min: 0, max: 200 })
} else { } else {
return '' return ''
} }

View file

@ -1,6 +1,6 @@
<template> <template>
<div> <div>
<PageRootElement <PageElement
v-for="element in elements" v-for="element in elements"
:key="element.id" :key="element.id"
:element="element" :element="element"
@ -10,10 +10,10 @@
</template> </template>
<script> <script>
import PageRootElement from '@baserow/modules/builder/components/page/PageRootElement' import PageElement from '@baserow/modules/builder/components/page/PageElement'
export default { export default {
components: { PageRootElement }, components: { PageElement },
inject: ['builder', 'mode'], inject: ['builder', 'mode'],
props: { props: {
page: { page: {

View file

@ -1,19 +1,32 @@
<template> <template>
<div class="element__wrapper" :style="wrapperStyles"> <div
<component class="element__wrapper"
:is="component" :class="{
:element="element" 'element__wrapper--full-width':
:children="children" element.style_width === WIDTH_TYPES.FULL.value,
class="element" 'element__wrapper--medium-width':
/> element.style_width === WIDTH_TYPES.MEDIUM.value,
'element__wrapper--small-width':
element.style_width === WIDTH_TYPES.SMALL.value,
}"
:style="wrapperStyles"
>
<div class="element__inner-wrapper" :style="innerWrapperStyles">
<component
:is="component"
:element="element"
:children="children"
class="element"
/>
</div>
</div> </div>
</template> </template>
<script> <script>
import PageElement from '@baserow/modules/builder/mixins/pageElement' import pageElement from '@baserow/modules/builder/mixins/pageElement'
export default { export default {
name: 'PageElement', name: 'PageElement',
mixins: [PageElement], mixins: [pageElement],
} }
</script> </script>

View file

@ -1,61 +1,30 @@
<template> <template>
<div <div
class="page-root-element__inner" class="element__wrapper"
:style="{ :class="{
'--background-color': 'element__wrapper--full-width':
element.style_background === BACKGROUND_TYPES.COLOR.value element.style_width === WIDTH_TYPES.FULL.value,
? resolveColor(element.style_background_color, colorVariables) 'element__wrapper--medium-width':
: 'transparent', element.style_width === WIDTH_TYPES.MEDIUM.value,
'--border-top': border( 'element__wrapper--small-width':
element.style_border_top_size, element.style_width === WIDTH_TYPES.SMALL.value,
element.style_border_top_color
),
'--border-bottom': border(
element.style_border_bottom_size,
element.style_border_bottom_color
),
}" }"
:style="wrapperStyles"
> >
<div <component
class="element__wrapper element__wrapper--normal-width" :is="component"
:class="{ :element="element"
'element__wrapper--full-width': :children="children"
element.style_width === WIDTH_TYPES.FULL.value, class="element"
'element__wrapper--medium-width': />
element.style_width === WIDTH_TYPES.MEDIUM.value,
'element__wrapper--small-width':
element.style_width === WIDTH_TYPES.SMALL.value,
}"
:style="wrapperStyles"
>
<component
:is="component"
:element="element"
:children="children"
class="element"
/>
</div>
</div> </div>
</template> </template>
<script> <script>
import pageElement from '@baserow/modules/builder/mixins/pageElement' import pageElement from '@baserow/modules/builder/mixins/pageElement'
import { BACKGROUND_TYPES, WIDTH_TYPES } from '@baserow/modules/builder/enums'
export default { export default {
name: 'PageRootElement', name: 'PageRootElement',
mixins: [pageElement], mixins: [pageElement],
computed: {
BACKGROUND_TYPES: () => BACKGROUND_TYPES,
WIDTH_TYPES: () => WIDTH_TYPES,
},
methods: {
border(size, color) {
return `solid ${size || 0}px ${this.resolveColor(
color,
this.colorVariables
)}`
},
},
} }
</script> </script>

View file

@ -22,38 +22,18 @@
></i> ></i>
</a> </a>
<div v-show="!isClosed('colors')"> <div v-show="!isClosed('colors')">
<div class="control"> <ColorInputGroup
<div class="control__elements"> :value="builder.theme.primary_color"
<div class="color-input"> label-after
<a :label="$t('mainThemeConfigBlock.primaryColor')"
ref="primaryColor" @input="setPropertyInStore('primary_color', $event)"
class="color-input__preview" />
:style="{ 'background-color': builder.theme.primary_color }" <ColorInputGroup
@click="openColorPicker($refs.primaryColor, 'primary_color')" :value="builder.theme.secondary_color"
></a> label-after
<div class="color-input__label"> :label="$t('mainThemeConfigBlock.secondaryColor')"
{{ $t('mainThemeConfigBlock.primaryColor') }} @input="setPropertyInStore('secondary_color', $event)"
</div> />
</div>
</div>
</div>
<div class="control">
<div class="control__elements">
<div class="color-input">
<a
ref="secondaryColor"
class="color-input__preview"
:style="{ 'background-color': builder.theme.secondary_color }"
@click="
openColorPicker($refs.secondaryColor, 'secondary_color')
"
></a>
<div class="color-input__label">
{{ $t('mainThemeConfigBlock.secondaryColor') }}
</div>
</div>
</div>
</div>
</div> </div>
</div> </div>
</div> </div>
@ -88,21 +68,10 @@
{{ $t('mainThemeConfigBlock.headingLabel', { i }) }} {{ $t('mainThemeConfigBlock.headingLabel', { i }) }}
</div> </div>
<div class="control__elements control__elements--flex"> <div class="control__elements control__elements--flex">
<div class="color-input"> <ColorInput
<a :value="builder.theme[`heading_${i}_color`]"
ref="headingColor" @input="setPropertyInStore(`heading_${i}_color`, $event)"
class="color-input__preview" />
:style="{
'background-color': builder.theme[`heading_${i}_color`],
}"
@click="
openColorPicker(
$refs.headingColor[i - 1],
`heading_${i}_color`
)
"
></a>
</div>
<div class="input__with-icon"> <div class="input__with-icon">
<input <input
type="number" type="number"

View file

@ -62,13 +62,14 @@ export class ElementType extends Registerable {
get stylesAll() { get stylesAll() {
return [ return [
'style_border_top_color',
'style_border_top_size',
'style_padding_top', 'style_padding_top',
'style_border_bottom_color',
'style_border_bottom_size',
'style_padding_bottom',
'style_padding_bottom', 'style_padding_bottom',
'style_padding_left',
'style_padding_right',
'style_border_top',
'style_border_bottom',
'style_border_left',
'style_border_right',
'style_background', 'style_background',
'style_background_color', 'style_background_color',
'style_width', 'style_width',
@ -218,15 +219,7 @@ export class ColumnElementType extends ContainerElementType {
} }
get childStylesForbidden() { get childStylesForbidden() {
return [ return ['style_width']
'style_border_top_color',
'style_border_top_size',
'style_border_bottom_color',
'style_border_bottom_size',
'style_background',
'style_background_color',
'style_width',
]
} }
get defaultPlaceInContainer() { get defaultPlaceInContainer() {
@ -667,4 +660,8 @@ export class FormContainerElementType extends ContainerElementType {
get events() { get events() {
return [SubmitEvent] return [SubmitEvent]
} }
get childStylesForbidden() {
return ['style_width']
}
} }

View file

@ -214,23 +214,24 @@
"noValue": "Unnamed..." "noValue": "Unnamed..."
}, },
"linkElementForm": { "linkElementForm": {
"text": "Text", "text": "Text",
"textPlaceholder": "Enter text...", "textPlaceholder": "Enter text...",
"navigateTo": "Navigate to", "navigateTo": "Navigate to",
"navigateToNotSet": "No destination", "navigateToNotSet": "No destination",
"navigateToCustom": "Custom URL", "navigateToCustom": "Custom URL",
"url": "Destination URL", "url": "Destination URL",
"urlPlaceholder": "Enter an URL...", "urlPlaceholder": "Enter an URL...",
"variant": "Variant", "variant": "Variant",
"variantLink": "Link", "variantLink": "Link",
"variantButton": "Button", "variantButton": "Button",
"target": "Open in...", "target": "Open in...",
"targetSelf": "Same tab", "targetSelf": "Same tab",
"targetNewTab": "New tab", "targetNewTab": "New tab",
"paramPlaceholder": "Enter a value...", "paramPlaceholder": "Enter a value...",
"paramsInErrorDescription": "The saved parameters don't match the page parameters. The page has probably been deleted or updated.", "paramsInErrorDescription": "The saved parameters don't match the page parameters. The page has probably been deleted or updated.",
"paramsInErrorButton": "Update parameters", "paramsInErrorButton": "Update parameters",
"pageParameterTypeError": "Invalid type" "pageParameterTypeError": "Invalid type",
"buttonColor": "Button color"
}, },
"widthSelector": { "widthSelector": {
"width": "Width", "width": "Width",
@ -302,16 +303,17 @@
"noDataSourceMessage": "Data sources can be used to fetch data from internal or external sources and display it on the page." "noDataSourceMessage": "Data sources can be used to fetch data from internal or external sources and display it on the page."
}, },
"defaultStyleForm": { "defaultStyleForm": {
"boxTop": "Top", "boxTop": "Top",
"boxBottom": "Bottom", "boxBottom": "Bottom",
"backgroundLabel": "Background", "boxLeft": "Left",
"backgroundColor": "Background color", "boxRight": "Right",
"widthLabel": "Width" "backgroundLabel": "Background",
"backgroundColor": "Background color",
"widthLabel": "Width"
}, },
"styleBoxForm": { "styleBoxForm": {
"borderLabel": "Border", "borderLabel": "Border",
"paddingLabel": "Padding", "paddingLabel": "Padding"
"error": "The value must be an integer between 0 and 200."
}, },
"mainThemeConfigBlock": { "mainThemeConfigBlock": {
"colorsLabel": "Colors", "colorsLabel": "Colors",
@ -322,8 +324,9 @@
"headingValue": "Heading <h{i}>" "headingValue": "Heading <h{i}>"
}, },
"buttonElementForm": { "buttonElementForm": {
"valueLabel": "Text", "valueLabel": "Text",
"valuePlaceholder": "Enter text..." "valuePlaceholder": "Enter text...",
"buttonColor": "Button color"
}, },
"buttonElement": { "buttonElement": {
"noValue": "Unnamed..." "noValue": "Unnamed..."
@ -348,7 +351,8 @@
"fieldDefaultName": "Column", "fieldDefaultName": "Column",
"fieldType": "Type", "fieldType": "Type",
"itemsPerPagePlaceholder": "Enter value...", "itemsPerPagePlaceholder": "Enter value...",
"selectSourceFirst": "Choose a list data source to begin configuring your fields." "selectSourceFirst": "Choose a list data source to begin configuring your fields.",
"buttonColor": "Button color"
}, },
"tableElement": { "tableElement": {
"empty": "No items have been found.", "empty": "No items have been found.",
@ -389,7 +393,8 @@
"fieldValueLabel": "Url", "fieldValueLabel": "Url",
"fieldValuePlaceholder": "Enter value...", "fieldValuePlaceholder": "Enter value...",
"fieldLinkNameLabel": "Link text", "fieldLinkNameLabel": "Link text",
"fieldLinkNamePlaceholder": "Enter value..." "fieldLinkNamePlaceholder": "Enter value...",
"buttonColor": "Button color"
}, },
"linkField": { "linkField": {
"details": "Details" "details": "Details"
@ -405,8 +410,9 @@
"integrationFieldLabel": "Integration" "integrationFieldLabel": "Integration"
}, },
"formContainerElementForm": { "formContainerElementForm": {
"submitButtonLabel": "Submit button", "submitButtonLabel": "Submit button",
"submitButtonPlaceholder": "Enter value..." "submitButtonPlaceholder": "Enter value...",
"buttonColor": "Button color"
}, },
"dropdownOptionSelector": { "dropdownOptionSelector": {
"label": "Options", "label": "Options",

View file

@ -1,6 +1,8 @@
import RuntimeFormulaContext from '@baserow/modules/core/runtimeFormulaContext' import RuntimeFormulaContext from '@baserow/modules/core/runtimeFormulaContext'
import { resolveFormula } from '@baserow/modules/core/formula' import { resolveFormula } from '@baserow/modules/core/formula'
import { ClickEvent, SubmitEvent } from '@baserow/modules/builder/eventTypes' import { ClickEvent, SubmitEvent } from '@baserow/modules/builder/eventTypes'
import { resolveColor } from '@baserow/modules/core/utils/colors'
import { themeToColorVariables } from '@baserow/modules/builder/utils/theme'
export default { export default {
inject: ['builder', 'page', 'mode'], inject: ['builder', 'page', 'mode'],
@ -53,6 +55,9 @@ export default {
}, },
} }
}, },
colorVariables() {
return themeToColorVariables(this.builder.theme)
},
}, },
methods: { methods: {
resolveFormula(formula) { resolveFormula(formula) {
@ -93,5 +98,7 @@ export default {
fireSubmitEvent() { fireSubmitEvent() {
this.fireEvent(SubmitEvent) this.fireEvent(SubmitEvent)
}, },
resolveColor,
}, },
} }

View file

@ -0,0 +1,29 @@
import { resolveColor } from '@baserow/modules/core/utils/colors'
import { themeToColorVariables } from '@baserow/modules/builder/utils/theme'
import form from '@baserow/modules/core/mixins/form'
import {
DATA_PROVIDERS_ALLOWED_ELEMENTS,
DATA_PROVIDERS_ALLOWED_FORM_ELEMENTS,
} from '@baserow/modules/builder/enums'
export default {
inject: ['builder', 'page', 'mode'],
mixins: [form],
data() {
return {
workflowActionsInProgress: false,
}
},
computed: {
colorVariables() {
return themeToColorVariables(this.builder.theme)
},
DATA_PROVIDERS_ALLOWED_ELEMENTS: () => DATA_PROVIDERS_ALLOWED_ELEMENTS,
DATA_PROVIDERS_ALLOWED_FORM_ELEMENTS: () =>
DATA_PROVIDERS_ALLOWED_FORM_ELEMENTS,
},
methods: {
resolveColor,
},
}

View file

@ -2,6 +2,8 @@ import _ from 'lodash'
import { resolveColor } from '@baserow/modules/core/utils/colors' import { resolveColor } from '@baserow/modules/core/utils/colors'
import { themeToColorVariables } from '@baserow/modules/builder/utils/theme' import { themeToColorVariables } from '@baserow/modules/builder/utils/theme'
import { BACKGROUND_TYPES, WIDTH_TYPES } from '@baserow/modules/builder/enums'
export default { export default {
inject: ['builder', 'page'], inject: ['builder', 'page'],
props: { props: {
@ -16,6 +18,8 @@ export default {
}, },
}, },
computed: { computed: {
BACKGROUND_TYPES: () => BACKGROUND_TYPES,
WIDTH_TYPES: () => WIDTH_TYPES,
colorVariables() { colorVariables() {
return themeToColorVariables(this.builder.theme) return themeToColorVariables(this.builder.theme)
}, },
@ -46,13 +50,61 @@ export default {
parentElementType.childStylesForbidden parentElementType.childStylesForbidden
) )
}, },
/** /**
* Computes an object containing all the style properties that must be set on * Computes an object containing all the style properties that must be set on
* the element wrapper. * the element wrapper.
*/ */
wrapperStyles() { wrapperStyles() {
const stylesAllowed = this.allowedStyles const styles = {
style_background_color: {
'--background-color':
this.element.style_background === BACKGROUND_TYPES.COLOR.value
? this.resolveColor(
this.element.style_background_color,
this.colorVariables
)
: 'transparent',
},
style_border_top: {
'--border-top': this.border(
this.element.style_border_top_size,
this.element.style_border_top_color
),
},
style_border_bottom: {
'--border-bottom': this.border(
this.element.style_border_bottom_size,
this.element.style_border_bottom_color
),
},
style_border_left: {
'--border-left': this.border(
this.element.style_border_left_size,
this.element.style_border_left_color
),
},
style_border_right: {
'--border-right': this.border(
this.element.style_border_right_size,
this.element.style_border_right_color
),
},
}
return Object.keys(styles).reduce((acc, key) => {
if (this.allowedStyles.includes(key)) {
acc = { ...acc, ...styles[key] }
}
return acc
}, {})
},
/**
* Computes an object containing all the style properties that must be set on
* the element inner wrapper.
*/
innerWrapperStyles() {
const styles = { const styles = {
style_padding_top: { style_padding_top: {
'--padding-top': `${this.element.style_padding_top || 0}px`, '--padding-top': `${this.element.style_padding_top || 0}px`,
@ -60,10 +112,16 @@ export default {
style_padding_bottom: { style_padding_bottom: {
'--padding-bottom': `${this.element.style_padding_bottom || 0}px`, '--padding-bottom': `${this.element.style_padding_bottom || 0}px`,
}, },
style_padding_left: {
'--padding-left': `${this.element.style_padding_left || 0}px`,
},
style_padding_right: {
'--padding-right': `${this.element.style_padding_right || 0}px`,
},
} }
return Object.keys(styles).reduce((acc, key) => { return Object.keys(styles).reduce((acc, key) => {
if (stylesAllowed.includes(key)) { if (this.allowedStyles.includes(key)) {
acc = { ...acc, ...styles[key] } acc = { ...acc, ...styles[key] }
} }
return acc return acc
@ -72,5 +130,11 @@ export default {
}, },
methods: { methods: {
resolveColor, resolveColor,
border(size, color) {
return `solid ${size || 0}px ${this.resolveColor(
color,
this.colorVariables
)}`
},
}, },
} }

View file

@ -1,8 +1,11 @@
import _ from 'lodash' import _ from 'lodash'
import form from '@baserow/modules/core/mixins/form' import form from '@baserow/modules/core/mixins/form'
import { resolveColor } from '@baserow/modules/core/utils/colors'
import { themeToColorVariables } from '@baserow/modules/builder/utils/theme' import { themeToColorVariables } from '@baserow/modules/builder/utils/theme'
const borderNames = ['top', 'bottom', 'left', 'right']
const borderStyleNames = borderNames.map((pos) => `style_border_${pos}`)
export default { export default {
inject: ['builder'], inject: ['builder'],
props: { props: {
@ -23,7 +26,7 @@ export default {
allowedValues, allowedValues,
values: this.getValuesFromElement(allowedValues), values: this.getValuesFromElement(allowedValues),
boxStyles: Object.fromEntries( boxStyles: Object.fromEntries(
['top', 'bottom'].map((pos) => [pos, this.getBoxStyleValue(pos)]) borderNames.map((pos) => [pos, this.getBoxStyleValue(pos)])
), ),
} }
}, },
@ -31,6 +34,17 @@ export default {
colorVariables() { colorVariables() {
return themeToColorVariables(this.builder.theme) return themeToColorVariables(this.builder.theme)
}, },
allowedStyles() {
return this.getAllowedStyles()
},
borders() {
return [
{ name: 'top', label: this.$t('defaultStyleForm.boxTop') },
{ name: 'bottom', label: this.$t('defaultStyleForm.boxBottom') },
{ name: 'left', label: this.$t('defaultStyleForm.boxLeft') },
{ name: 'right', label: this.$t('defaultStyleForm.boxRight') },
]
},
}, },
watch: { watch: {
boxStyles: { boxStyles: {
@ -43,9 +57,8 @@ export default {
}, },
}, },
methods: { methods: {
resolveColor,
isStyleAllowed(style) { isStyleAllowed(style) {
return this.allowedValues.includes(style) return this.allowedStyles.includes(style)
}, },
getBoxStyleValue(pos) { getBoxStyleValue(pos) {
return { return {
@ -61,20 +74,33 @@ export default {
this.values[`style_border_${pos}_size`] = newValue.border_size this.values[`style_border_${pos}_size`] = newValue.border_size
} }
}, },
getAllowedValues() { getAllowedStyles() {
const elementType = this.$registry.get('element', this.element.type) const elementType = this.$registry.get('element', this.element.type)
const parentElementType = this.parentElement const parentElementType = this.parentElement
? this.$registry.get('element', this.parentElement?.type) ? this.$registry.get('element', this.parentElement?.type)
: null : []
if (!parentElementType) { let styles = elementType.styles
return elementType.styles
if (parentElementType) {
styles = _.difference(
elementType.styles,
parentElementType.childStylesForbidden
)
} }
return _.difference( return styles
elementType.styles, },
parentElementType.childStylesForbidden getAllowedValues() {
) // Rewrite border style names
return this.getAllowedStyles()
.map((style) => {
if (borderStyleNames.includes(style)) {
return [`${style}_color`, `${style}_size`]
}
return style
})
.flat()
}, },
getValuesFromElement(allowedValues) { getValuesFromElement(allowedValues) {
return allowedValues.reduce((obj, value) => { return allowedValues.reduce((obj, value) => {

View file

@ -136,6 +136,7 @@
@import 'notification_panel'; @import 'notification_panel';
@import 'color_picker'; @import 'color_picker';
@import 'color_picker_context'; @import 'color_picker_context';
@import 'color_input_group';
@import 'formula_input_field'; @import 'formula_input_field';
@import 'get_formula_component'; @import 'get_formula_component';
@import 'theme_settings'; @import 'theme_settings';

View file

@ -9,7 +9,6 @@
@import 'side_panels'; @import 'side_panels';
@import 'empty_side_panel_state'; @import 'empty_side_panel_state';
@import 'page_editor'; @import 'page_editor';
@import 'page_root_element';
@import 'page_settings_path_params_form_element'; @import 'page_settings_path_params_form_element';
@import 'domain_card'; @import 'domain_card';
@import 'dns_status'; @import 'dns_status';

View file

@ -1,13 +1,31 @@
.element__wrapper { .element__wrapper {
padding: var(--padding-top, 0) 0 var(--padding-bottom, 0) 0; background-color: var(--background-color, $black);
border-top: var(--border-top, none);
border-bottom: var(--border-bottom, none);
border-left: var(--border-left, none);
border-right: var(--border-right, none);
margin: 0 auto;
max-width: $builder-page-max-width;
&--normal-width { &--full-width {
margin: 0 auto; max-width: 100%;
padding-left: 20px;
padding-right: 20px;
max-width: $builder-page-max-width;
} }
&--medium-width {
max-width: 960px;
}
&--small-width {
max-width: 680px;
}
}
.element__inner-wrapper {
padding: var(--padding-top, 0) var(--padding-right, 0)
var(--padding-bottom, 0) var(--padding-left, 0);
margin: 0 auto;
max-width: $builder-page-max-width;
&--full-width { &--full-width {
max-width: 100%; max-width: 100%;
} }
@ -22,7 +40,7 @@
} }
.element { .element {
// this is a placeholder, the class will be added to every element component. // Placeholder for element styles
} }
.element--no-value { .element--no-value {

View file

@ -3,7 +3,7 @@
cursor: pointer; cursor: pointer;
display: inline-block; display: inline-block;
color: $white; color: $white;
background-color: $black; background-color: var(--button-color, $black);
line-height: 28px; line-height: 28px;
padding: 0 12px; padding: 0 12px;
border: none; border: none;
@ -13,7 +13,7 @@
@include rounded($rounded); @include rounded($rounded);
&:hover { &:hover {
background-color: lighten($black, 10%); filter: brightness(1.3);
text-decoration: none; text-decoration: none;
} }

View file

@ -1,5 +0,0 @@
.page-root-element__inner {
background-color: var(--background-color, $black);
border-top: var(--border-top, none);
border-bottom: var(--border-bottom, none);
}

View file

@ -1,19 +1,11 @@
.color-input {
display: flex;
align-items: center;
}
.color-input__preview { .color-input__preview {
display: block;
width: 40px; width: 40px;
height: 20px; height: 20px;
border-radius: 2px; border-radius: 2px;
box-shadow: 0 0 1px 0 rgba($black, 0.16); box-shadow: 1px 1px 1px 1px rgba($black, 0.2);
&:hover { &:hover {
box-shadow: 0 0 2px 0 rgba($black, 0.16); box-shadow: 1px 1px 1px 0 rgba($black, 0.2);
} }
} }
.color-input__label {
margin-left: 10px;
}

View file

@ -0,0 +1,8 @@
.color-input-group--label-after {
display: flex;
align-items: center;
}
.color-input-group__label-after {
margin-left: 16px;
}

View file

@ -0,0 +1,41 @@
<template>
<div>
<ColorPickerContext
ref="colorPicker"
:value="value"
:variables="colorVariables"
@input="$emit('input', $event)"
/>
<a
ref="opener"
class="color-input__preview"
:style="{
'background-color': resolveColor(value, colorVariables),
}"
@click="$refs.colorPicker.toggle($refs.opener)"
/>
</div>
</template>
<script>
import ColorPickerContext from '@baserow/modules/core/components/ColorPickerContext'
import { resolveColor } from '@baserow/modules/core/utils/colors'
export default {
name: 'ColorInput',
components: { ColorPickerContext },
props: {
value: {
type: String,
required: false,
default: 'primary',
},
colorVariables: {
type: Array,
required: false,
default: () => [],
},
},
methods: { resolveColor },
}
</script>

View file

@ -0,0 +1,53 @@
<template>
<FormGroup v-if="!labelAfter" :label="label">
<ColorInput
:value="value"
:color-variables="colorVariables"
@input="$emit('input', $event)"
/>
</FormGroup>
<div v-else class="control">
<div class="control__elements">
<div class="color-input-group--label-after">
<ColorInput
:value="value"
:color-variables="colorVariables"
@input="$emit('input', $event)"
/>
<div class="color-input-group__label-after">
{{ label }}
</div>
</div>
</div>
</div>
</template>
<script>
import ColorInput from '@baserow/modules/core/components/ColorInput'
export default {
name: 'ColorInputGroup',
components: { ColorInput },
props: {
value: {
type: String,
required: false,
default: 'primary',
},
label: {
type: String,
required: true,
},
labelAfter: {
type: Boolean,
required: false,
default: false,
},
colorVariables: {
type: Array,
required: false,
default: () => [],
},
},
}
</script>

View file

@ -33,6 +33,7 @@
<input <input
ref="base_url" ref="base_url"
class="form-input__input" class="form-input__input"
:class="{ 'remove-number-input-controls': true }"
:value="fromValue(value)" :value="fromValue(value)"
:disabled="disabled" :disabled="disabled"
:type="type" :type="type"

View file

@ -45,6 +45,8 @@ import Badge from '@baserow/modules/core/components/Badge'
import Expandable from '@baserow/modules/core/components/Expandable.vue' import Expandable from '@baserow/modules/core/components/Expandable.vue'
import RadioButton from '@baserow/modules/core/components/RadioButton' import RadioButton from '@baserow/modules/core/components/RadioButton'
import Thumbnail from '@baserow/modules/core/components/Thumbnail' import Thumbnail from '@baserow/modules/core/components/Thumbnail'
import ColorInput from '@baserow/modules/core/components/ColorInput'
import ColorInputGroup from '@baserow/modules/core/components/ColorInputGroup'
function setupVue(Vue) { function setupVue(Vue) {
Vue.component('Context', Context) Vue.component('Context', Context)
@ -79,6 +81,8 @@ function setupVue(Vue) {
Vue.component('CallToAction', CallToAction) Vue.component('CallToAction', CallToAction)
Vue.component('FormGroup', FormGroup) Vue.component('FormGroup', FormGroup)
Vue.component('FormRow', FormRow) Vue.component('FormRow', FormRow)
Vue.component('ColorInput', ColorInput)
Vue.component('ColorInputGroup', ColorInputGroup)
Vue.filter('lowercase', lowercase) Vue.filter('lowercase', lowercase)
Vue.filter('uppercase', uppercase) Vue.filter('uppercase', uppercase)

View file

@ -260,6 +260,9 @@ export const conversionsMap = {
} }
export function isColorVariable(value) { export function isColorVariable(value) {
if (!value) {
return false
}
return value.substring(0, 1) !== '#' return value.substring(0, 1) !== '#'
} }