1
0
Fork 0
mirror of https://gitlab.com/bramw/baserow.git synced 2025-04-03 04:35:31 +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_size",
"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_color",
"style_width",

View file

@ -57,6 +57,12 @@ class ElementSerializer(serializers.ModelSerializer):
"style_border_bottom_color",
"style_border_bottom_size",
"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_color",
"style_width",
@ -106,6 +112,12 @@ class CreateElementSerializer(serializers.ModelSerializer):
"style_border_bottom_color",
"style_border_bottom_size",
"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_color",
"style_width",
@ -122,6 +134,12 @@ class UpdateElementSerializer(serializers.ModelSerializer):
"style_border_bottom_color",
"style_border_bottom_size",
"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_color",
"style_width",

View file

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

View file

@ -34,6 +34,12 @@ class ElementHandler:
"style_border_bottom_color",
"style_border_bottom_size",
"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_color",
"style_width",
@ -48,6 +54,12 @@ class ElementHandler:
"style_border_bottom_color",
"style_border_bottom_size",
"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_color",
"style_width",

View file

@ -109,7 +109,7 @@ class Element(
default=0, help_text="Pixel height of the top border."
)
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(
@ -122,7 +122,33 @@ class Element(
default=0, help_text="Pixel height of the bottom border."
)
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(
@ -281,7 +307,7 @@ class ColumnElement(ContainerElement):
],
)
column_gap = models.IntegerField(
default=30,
default=20,
help_text="The amount of space between the columns.",
validators=[
MinValueValidator(0, message="Value cannot be less than 0."),
@ -391,6 +417,12 @@ class LinkElement(Element):
max_length=10,
default=HorizontalAlignments.LEFT,
)
button_color = models.CharField(
max_length=20,
default="primary",
blank=True,
help_text="The color of the button",
)
class ImageElement(Element):
@ -479,6 +511,12 @@ class ButtonElement(Element):
max_length=10,
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):
@ -542,6 +580,13 @@ class TableElement(CollectionElement):
A table element
"""
button_color = models.CharField(
max_length=20,
default="primary",
blank=True,
help_text="The color of the button",
)
class FormContainerElement(ContainerElement):
"""
@ -550,6 +595,13 @@ class FormContainerElement(ContainerElement):
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):
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_size: 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_color: str
style_width: str

View file

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

View file

@ -73,7 +73,8 @@
"requiredField": "This field is required.",
"integerField": "The field must be an integer.",
"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": {
"admin": "Admin",

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -1,36 +1,19 @@
<template>
<FormElement class="control">
<label class="control__label">
{{ $t('fontSidePanelForm.label') }}
</label>
<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>
<ColorInputGroup
v-model="values.font_color"
:label="$t('fontSidePanelForm.label')"
:color-variables="colorVariables"
/>
</template>
<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 { resolveColor } from '@baserow/modules/core/utils/colors'
export default {
name: 'FontSelector',
components: { ColorPickerContext },
components: { ColorInputGroup },
mixins: [form],
props: {
colorVariables: {

View file

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

View file

@ -1,79 +1,60 @@
<template>
<form @submit.prevent>
<FormElement class="control">
<label class="control__label">{{ label }}</label>
<div class="control__elements">
<div
v-if="borderSizeIsAllowed || paddingIsAllowed"
class="row margin-bottom-2"
style="--gap: 6px"
>
<div v-if="borderSizeIsAllowed" class="col col-3">
<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()"
/>
<FormGroup :label="label" :error="error">
<div
v-if="borderIsAllowed || paddingIsAllowed"
class="row margin-bottom-2"
style="--gap: 6px"
>
<div v-if="borderIsAllowed" class="col col-3">
<div class="margin-bottom-1">
{{ $t('styleBoxForm.borderLabel') }}
</div>
<div v-if="paddingIsAllowed" class="col col-3">
<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 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
),
<input
v-model="values.border_size"
type="number"
class="input"
:class="{
'input--error': error,
}"
@click="$refs.colorPicker.toggle($refs.borderColor)"
></a>
{{ $t('styleBoxForm.borderLabel') }}
@blur="$v.values.border_size.$touch()"
/>
</div>
<div v-if="error" class="error">
{{ error }}
<div v-if="paddingIsAllowed" class="col col-3">
<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>
</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>
</template>
<script>
import { required, integer, between } from 'vuelidate/lib/validators'
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 { themeToColorVariables } from '@baserow/modules/builder/utils/theme'
export default {
name: 'StyleBoxForm',
components: { ColorPickerContext },
mixins: [form],
inject: ['builder'],
props: {
@ -90,12 +71,7 @@ export default {
required: false,
default: () => false,
},
borderColorIsAllowed: {
type: Boolean,
required: false,
default: () => false,
},
borderSizeIsAllowed: {
borderIsAllowed: {
type: Boolean,
required: false,
default: () => false,
@ -120,7 +96,7 @@ export default {
*/
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 {
return ''
}

View file

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

View file

@ -1,19 +1,32 @@
<template>
<div class="element__wrapper" :style="wrapperStyles">
<component
:is="component"
:element="element"
:children="children"
class="element"
/>
<div
class="element__wrapper"
:class="{
'element__wrapper--full-width':
element.style_width === WIDTH_TYPES.FULL.value,
'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>
</template>
<script>
import PageElement from '@baserow/modules/builder/mixins/pageElement'
import pageElement from '@baserow/modules/builder/mixins/pageElement'
export default {
name: 'PageElement',
mixins: [PageElement],
mixins: [pageElement],
}
</script>

View file

@ -1,61 +1,30 @@
<template>
<div
class="page-root-element__inner"
:style="{
'--background-color':
element.style_background === BACKGROUND_TYPES.COLOR.value
? resolveColor(element.style_background_color, colorVariables)
: 'transparent',
'--border-top': border(
element.style_border_top_size,
element.style_border_top_color
),
'--border-bottom': border(
element.style_border_bottom_size,
element.style_border_bottom_color
),
class="element__wrapper"
:class="{
'element__wrapper--full-width':
element.style_width === WIDTH_TYPES.FULL.value,
'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__wrapper element__wrapper--normal-width"
:class="{
'element__wrapper--full-width':
element.style_width === WIDTH_TYPES.FULL.value,
'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>
<component
:is="component"
:element="element"
:children="children"
class="element"
/>
</div>
</template>
<script>
import pageElement from '@baserow/modules/builder/mixins/pageElement'
import { BACKGROUND_TYPES, WIDTH_TYPES } from '@baserow/modules/builder/enums'
export default {
name: 'PageRootElement',
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>

View file

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

View file

@ -62,13 +62,14 @@ export class ElementType extends Registerable {
get stylesAll() {
return [
'style_border_top_color',
'style_border_top_size',
'style_padding_top',
'style_border_bottom_color',
'style_border_bottom_size',
'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_color',
'style_width',
@ -218,15 +219,7 @@ export class ColumnElementType extends ContainerElementType {
}
get childStylesForbidden() {
return [
'style_border_top_color',
'style_border_top_size',
'style_border_bottom_color',
'style_border_bottom_size',
'style_background',
'style_background_color',
'style_width',
]
return ['style_width']
}
get defaultPlaceInContainer() {
@ -667,4 +660,8 @@ export class FormContainerElementType extends ContainerElementType {
get events() {
return [SubmitEvent]
}
get childStylesForbidden() {
return ['style_width']
}
}

View file

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

View file

@ -1,6 +1,8 @@
import RuntimeFormulaContext from '@baserow/modules/core/runtimeFormulaContext'
import { resolveFormula } from '@baserow/modules/core/formula'
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 {
inject: ['builder', 'page', 'mode'],
@ -53,6 +55,9 @@ export default {
},
}
},
colorVariables() {
return themeToColorVariables(this.builder.theme)
},
},
methods: {
resolveFormula(formula) {
@ -93,5 +98,7 @@ export default {
fireSubmitEvent() {
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 { themeToColorVariables } from '@baserow/modules/builder/utils/theme'
import { BACKGROUND_TYPES, WIDTH_TYPES } from '@baserow/modules/builder/enums'
export default {
inject: ['builder', 'page'],
props: {
@ -16,6 +18,8 @@ export default {
},
},
computed: {
BACKGROUND_TYPES: () => BACKGROUND_TYPES,
WIDTH_TYPES: () => WIDTH_TYPES,
colorVariables() {
return themeToColorVariables(this.builder.theme)
},
@ -46,13 +50,61 @@ export default {
parentElementType.childStylesForbidden
)
},
/**
* Computes an object containing all the style properties that must be set on
* the element wrapper.
*/
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 = {
style_padding_top: {
'--padding-top': `${this.element.style_padding_top || 0}px`,
@ -60,10 +112,16 @@ export default {
style_padding_bottom: {
'--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) => {
if (stylesAllowed.includes(key)) {
if (this.allowedStyles.includes(key)) {
acc = { ...acc, ...styles[key] }
}
return acc
@ -72,5 +130,11 @@ export default {
},
methods: {
resolveColor,
border(size, color) {
return `solid ${size || 0}px ${this.resolveColor(
color,
this.colorVariables
)}`
},
},
}

View file

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

View file

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

View file

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

View file

@ -1,13 +1,31 @@
.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 {
margin: 0 auto;
padding-left: 20px;
padding-right: 20px;
max-width: $builder-page-max-width;
&--full-width {
max-width: 100%;
}
&--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 {
max-width: 100%;
}
@ -22,7 +40,7 @@
}
.element {
// this is a placeholder, the class will be added to every element component.
// Placeholder for element styles
}
.element--no-value {

View file

@ -3,7 +3,7 @@
cursor: pointer;
display: inline-block;
color: $white;
background-color: $black;
background-color: var(--button-color, $black);
line-height: 28px;
padding: 0 12px;
border: none;
@ -13,7 +13,7 @@
@include rounded($rounded);
&:hover {
background-color: lighten($black, 10%);
filter: brightness(1.3);
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 {
display: block;
width: 40px;
height: 20px;
border-radius: 2px;
box-shadow: 0 0 1px 0 rgba($black, 0.16);
box-shadow: 1px 1px 1px 1px rgba($black, 0.2);
&: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
ref="base_url"
class="form-input__input"
:class="{ 'remove-number-input-controls': true }"
:value="fromValue(value)"
:disabled="disabled"
: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 RadioButton from '@baserow/modules/core/components/RadioButton'
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) {
Vue.component('Context', Context)
@ -79,6 +81,8 @@ function setupVue(Vue) {
Vue.component('CallToAction', CallToAction)
Vue.component('FormGroup', FormGroup)
Vue.component('FormRow', FormRow)
Vue.component('ColorInput', ColorInput)
Vue.component('ColorInputGroup', ColorInputGroup)
Vue.filter('lowercase', lowercase)
Vue.filter('uppercase', uppercase)

View file

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