mirror of
https://gitlab.com/bramw/baserow.git
synced 2025-04-06 22:08:52 +00:00
Resolve "Make the table element responsive"
This commit is contained in:
parent
ad5da1f276
commit
d62e4fdb46
16 changed files with 320 additions and 82 deletions
backend
src/baserow/contrib/builder
tests/baserow/contrib/builder
changelog/entries/unreleased/feature
web-frontend/modules
|
@ -42,6 +42,7 @@ from baserow.contrib.builder.elements.models import (
|
||||||
TableElement,
|
TableElement,
|
||||||
TextElement,
|
TextElement,
|
||||||
VerticalAlignments,
|
VerticalAlignments,
|
||||||
|
get_default_table_orientation,
|
||||||
)
|
)
|
||||||
from baserow.contrib.builder.elements.registries import (
|
from baserow.contrib.builder.elements.registries import (
|
||||||
ElementType,
|
ElementType,
|
||||||
|
@ -219,14 +220,15 @@ class TableElementType(CollectionElementWithFieldsTypeMixin, ElementType):
|
||||||
|
|
||||||
class SerializedDict(CollectionElementWithFieldsTypeMixin.SerializedDict):
|
class SerializedDict(CollectionElementWithFieldsTypeMixin.SerializedDict):
|
||||||
button_color: str
|
button_color: str
|
||||||
|
orientation: dict
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def allowed_fields(self):
|
def allowed_fields(self):
|
||||||
return super().allowed_fields + ["button_color"]
|
return super().allowed_fields + ["button_color", "orientation"]
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def serializer_field_names(self):
|
def serializer_field_names(self):
|
||||||
return super().serializer_field_names + ["button_color"]
|
return super().serializer_field_names + ["button_color", "orientation"]
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def serializer_field_overrides(self):
|
def serializer_field_overrides(self):
|
||||||
|
@ -238,10 +240,18 @@ class TableElementType(CollectionElementWithFieldsTypeMixin, ElementType):
|
||||||
default="primary",
|
default="primary",
|
||||||
help_text="Button color.",
|
help_text="Button color.",
|
||||||
),
|
),
|
||||||
|
"orientation": serializers.JSONField(
|
||||||
|
allow_null=False,
|
||||||
|
default=get_default_table_orientation,
|
||||||
|
help_text=TableElement._meta.get_field("orientation").help_text,
|
||||||
|
),
|
||||||
}
|
}
|
||||||
|
|
||||||
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,
|
||||||
|
"orientation": get_default_table_orientation(),
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
class RepeatElementType(
|
class RepeatElementType(
|
||||||
|
|
|
@ -59,6 +59,14 @@ def get_default_element_content_type():
|
||||||
return ContentType.objects.get_for_model(Element)
|
return ContentType.objects.get_for_model(Element)
|
||||||
|
|
||||||
|
|
||||||
|
def get_default_table_orientation():
|
||||||
|
return {
|
||||||
|
"smartphone": "horizontal",
|
||||||
|
"tablet": "horizontal",
|
||||||
|
"desktop": "horizontal",
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
class Element(
|
class Element(
|
||||||
HierarchicalModelMixin,
|
HierarchicalModelMixin,
|
||||||
TrashableModelMixin,
|
TrashableModelMixin,
|
||||||
|
@ -765,7 +773,12 @@ class TableElement(CollectionElement):
|
||||||
blank=True,
|
blank=True,
|
||||||
help_text="The color of the button",
|
help_text="The color of the button",
|
||||||
)
|
)
|
||||||
|
orientation = models.JSONField(
|
||||||
|
blank=True,
|
||||||
|
null=True,
|
||||||
|
default=get_default_table_orientation,
|
||||||
|
help_text="The table orientation (horizontal or vertical) for each device type",
|
||||||
|
)
|
||||||
fields = models.ManyToManyField(CollectionField)
|
fields = models.ManyToManyField(CollectionField)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,39 @@
|
||||||
|
# Generated by Django 4.1.13 on 2024-06-06 11:12
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
from baserow.contrib.builder.elements.models import get_default_table_orientation
|
||||||
|
|
||||||
|
|
||||||
|
def populate_orientation_field(apps, schema_editor):
|
||||||
|
"""Add default orientation settings to all table elements."""
|
||||||
|
|
||||||
|
TableElement = apps.get_model("builder", "tableelement")
|
||||||
|
TableElement.objects.update(orientation={
|
||||||
|
"smartphone": "horizontal",
|
||||||
|
"tablet": "horizontal",
|
||||||
|
"desktop": "horizontal",
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
dependencies = [
|
||||||
|
("builder", "0022_choiceelement_choiceelementoption_and_more"),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name="tableelement",
|
||||||
|
name="orientation",
|
||||||
|
field=models.JSONField(
|
||||||
|
blank=True,
|
||||||
|
default=get_default_table_orientation,
|
||||||
|
help_text="The table orientation (horizontal or vertical) for each device type",
|
||||||
|
null=True,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
migrations.RunPython(
|
||||||
|
populate_orientation_field,
|
||||||
|
reverse_code=migrations.RunPython.noop,
|
||||||
|
),
|
||||||
|
]
|
|
@ -372,6 +372,11 @@ def test_builder_application_export(data_fixture):
|
||||||
"type": "table",
|
"type": "table",
|
||||||
"order": str(element4.order),
|
"order": str(element4.order),
|
||||||
"button_color": "primary",
|
"button_color": "primary",
|
||||||
|
"orientation": {
|
||||||
|
"smartphone": "horizontal",
|
||||||
|
"tablet": "horizontal",
|
||||||
|
"desktop": "horizontal",
|
||||||
|
},
|
||||||
"parent_element_id": None,
|
"parent_element_id": None,
|
||||||
"place_in_container": None,
|
"place_in_container": None,
|
||||||
"visibility": "all",
|
"visibility": "all",
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
{
|
||||||
|
"type": "feature",
|
||||||
|
"message": "[Builder] Add responsive behavior configuration for table element",
|
||||||
|
"issue_number": 2523,
|
||||||
|
"bullet_points": [],
|
||||||
|
"created_at": "2024-06-05"
|
||||||
|
}
|
|
@ -1,47 +1,93 @@
|
||||||
<template>
|
<template>
|
||||||
<table class="baserow-table">
|
<div class="baserow-table-wrapper">
|
||||||
<thead>
|
<table class="baserow-table" :class="`baserow-table--${orientation}`">
|
||||||
<tr class="baserow-table__header-row">
|
<template v-if="orientation === TABLE_ORIENTATION.HORIZONTAL">
|
||||||
<th
|
<thead>
|
||||||
v-for="field in fields"
|
<tr class="baserow-table__row">
|
||||||
:key="field.__id__"
|
<th
|
||||||
class="baserow-table__header-cell"
|
v-for="field in fields"
|
||||||
>
|
:key="field.__id__"
|
||||||
<slot name="field-name" :field="field">{{ field.name }}</slot>
|
class="baserow-table__header-cell"
|
||||||
</th>
|
>
|
||||||
</tr>
|
<slot name="field-name" :field="field">{{ field.name }}</slot>
|
||||||
</thead>
|
</th>
|
||||||
<tbody v-if="rows.length">
|
</tr>
|
||||||
<tr
|
</thead>
|
||||||
v-for="(row, index) in rows"
|
<tbody v-if="rows.length">
|
||||||
:key="row.__id__"
|
<tr
|
||||||
class="baserow-table__row"
|
v-for="(row, index) in rows"
|
||||||
>
|
:key="row.__id__"
|
||||||
<td v-for="field in fields" :key="field.id" class="baserow-table__cell">
|
class="baserow-table__row"
|
||||||
<slot
|
|
||||||
name="cell-content"
|
|
||||||
:value="row[field.name]"
|
|
||||||
:field="field"
|
|
||||||
:row-index="index"
|
|
||||||
>
|
>
|
||||||
{{ value }}
|
<td
|
||||||
</slot>
|
v-for="field in fields"
|
||||||
</td>
|
:key="field.id"
|
||||||
</tr>
|
class="baserow-table__cell"
|
||||||
</tbody>
|
>
|
||||||
<tbody v-else>
|
<slot
|
||||||
<tr>
|
name="cell-content"
|
||||||
<td class="baserow-table__empty-message" :colspan="fields.length">
|
:value="row[field.name]"
|
||||||
<slot name="empty-state"></slot>
|
:field="field"
|
||||||
</td>
|
:row-index="index"
|
||||||
</tr>
|
>
|
||||||
</tbody>
|
{{ value }}
|
||||||
</table>
|
</slot>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</template>
|
||||||
|
<template v-else>
|
||||||
|
<tbody v-if="rows.length">
|
||||||
|
<template v-for="(row, rowIndex) in rows">
|
||||||
|
<tr
|
||||||
|
v-for="(field, fieldIndex) in fields"
|
||||||
|
:key="`${row.__id__}_${field.id}`"
|
||||||
|
class="baserow-table__row"
|
||||||
|
>
|
||||||
|
<th
|
||||||
|
class="baserow-table__header-cell"
|
||||||
|
:class="{
|
||||||
|
'baserow-table__separator': fieldIndex === fields.length - 1,
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
{{ field.name }}
|
||||||
|
</th>
|
||||||
|
<td
|
||||||
|
class="baserow-table__cell"
|
||||||
|
:class="{
|
||||||
|
'baserow-table__separator': fieldIndex === fields.length - 1,
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
<slot
|
||||||
|
name="cell-content"
|
||||||
|
:value="row[field.name]"
|
||||||
|
:field="field"
|
||||||
|
:row-index="rowIndex"
|
||||||
|
>
|
||||||
|
{{ value }}
|
||||||
|
</slot>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</template>
|
||||||
|
</tbody>
|
||||||
|
</template>
|
||||||
|
<tbody v-if="!rows.length">
|
||||||
|
<tr>
|
||||||
|
<td class="baserow-table__empty-message" :colspan="fields.length">
|
||||||
|
<slot name="empty-state"></slot>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import { TABLE_ORIENTATION } from '@baserow/modules/builder/enums'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'BaserowTable',
|
name: 'BaserowTable',
|
||||||
|
inject: ['mode'],
|
||||||
props: {
|
props: {
|
||||||
fields: {
|
fields: {
|
||||||
type: Array,
|
type: Array,
|
||||||
|
@ -51,12 +97,18 @@ export default {
|
||||||
type: Array,
|
type: Array,
|
||||||
required: true,
|
required: true,
|
||||||
},
|
},
|
||||||
|
orientation: {
|
||||||
|
type: String,
|
||||||
|
default: TABLE_ORIENTATION.HORIZONTAL,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {}
|
return {}
|
||||||
},
|
},
|
||||||
computed: {},
|
computed: {
|
||||||
watch: {},
|
TABLE_ORIENTATION() {
|
||||||
methods: {},
|
return TABLE_ORIENTATION
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -5,7 +5,11 @@
|
||||||
}"
|
}"
|
||||||
class="table-element"
|
class="table-element"
|
||||||
>
|
>
|
||||||
<BaserowTable :fields="element.fields" :rows="rows">
|
<BaserowTable
|
||||||
|
:fields="element.fields"
|
||||||
|
:rows="rows"
|
||||||
|
:orientation="orientation"
|
||||||
|
>
|
||||||
<template #cell-content="{ rowIndex, field, value }">
|
<template #cell-content="{ rowIndex, field, value }">
|
||||||
<component
|
<component
|
||||||
:is="collectionFieldTypes[field.type].component"
|
:is="collectionFieldTypes[field.type].component"
|
||||||
|
@ -55,6 +59,8 @@ export default {
|
||||||
* display.
|
* display.
|
||||||
* @property {Object} fields - The fields of the data source.
|
* @property {Object} fields - The fields of the data source.
|
||||||
* @property {int} items_per_page - The number of items per page.
|
* @property {int} items_per_page - The number of items per page.
|
||||||
|
* @property {string} button_color - The color of the button.
|
||||||
|
* @property {string} orientation - The orientation for eaceh device.
|
||||||
*/
|
*/
|
||||||
element: {
|
element: {
|
||||||
type: Object,
|
type: Object,
|
||||||
|
@ -94,6 +100,10 @@ export default {
|
||||||
collectionFieldTypes() {
|
collectionFieldTypes() {
|
||||||
return this.$registry.getAll('collectionField')
|
return this.$registry.getAll('collectionField')
|
||||||
},
|
},
|
||||||
|
orientation() {
|
||||||
|
const device = this.$store.getters['page/getDeviceTypeSelected']
|
||||||
|
return this.element.orientation[device]
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
|
|
|
@ -30,10 +30,18 @@
|
||||||
@blur="$v.values.items_per_page.$touch()"
|
@blur="$v.values.items_per_page.$touch()"
|
||||||
></FormInput>
|
></FormInput>
|
||||||
<FormGroup :label="$t('repeatElementForm.orientationLabel')">
|
<FormGroup :label="$t('repeatElementForm.orientationLabel')">
|
||||||
<RadioButton v-model="values.orientation" value="vertical">
|
<RadioButton
|
||||||
|
v-model="values.orientation"
|
||||||
|
value="vertical"
|
||||||
|
icon="iconoir-table-rows"
|
||||||
|
>
|
||||||
{{ $t('repeatElementForm.orientationVertical') }}
|
{{ $t('repeatElementForm.orientationVertical') }}
|
||||||
</RadioButton>
|
</RadioButton>
|
||||||
<RadioButton v-model="values.orientation" value="horizontal">
|
<RadioButton
|
||||||
|
v-model="values.orientation"
|
||||||
|
value="horizontal"
|
||||||
|
icon="iconoir-view-columns-3"
|
||||||
|
>
|
||||||
{{ $t('repeatElementForm.orientationHorizontal') }}
|
{{ $t('repeatElementForm.orientationHorizontal') }}
|
||||||
</RadioButton>
|
</RadioButton>
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
|
|
|
@ -145,6 +145,30 @@
|
||||||
</template>
|
</template>
|
||||||
<p v-else>{{ $t('tableElementForm.selectSourceFirst') }}</p>
|
<p v-else>{{ $t('tableElementForm.selectSourceFirst') }}</p>
|
||||||
</FormGroup>
|
</FormGroup>
|
||||||
|
<FormGroup :label="$t('tableElementForm.orientation')">
|
||||||
|
<DeviceSelector
|
||||||
|
:device-type-selected="deviceTypeSelected"
|
||||||
|
direction="row"
|
||||||
|
@selected="actionSetDeviceTypeSelected"
|
||||||
|
>
|
||||||
|
<template #deviceTypeControl="{ deviceType }">
|
||||||
|
<RadioButton
|
||||||
|
v-model="values.orientation[deviceType.getType()]"
|
||||||
|
icon="iconoir-view-columns-3"
|
||||||
|
:value="TABLE_ORIENTATION.HORIZONTAL"
|
||||||
|
>
|
||||||
|
{{ $t('tableElementForm.orientationHorizontal') }}
|
||||||
|
</RadioButton>
|
||||||
|
<RadioButton
|
||||||
|
v-model="values.orientation[deviceType.getType()]"
|
||||||
|
icon="iconoir-table-rows"
|
||||||
|
:value="TABLE_ORIENTATION.VERTICAL"
|
||||||
|
>
|
||||||
|
{{ $t('tableElementForm.orientationVertical') }}
|
||||||
|
</RadioButton>
|
||||||
|
</template>
|
||||||
|
</DeviceSelector>
|
||||||
|
</FormGroup>
|
||||||
<ColorInputGroup
|
<ColorInputGroup
|
||||||
v-model="values.button_color"
|
v-model="values.button_color"
|
||||||
:label="$t('tableElementForm.buttonColor')"
|
:label="$t('tableElementForm.buttonColor')"
|
||||||
|
@ -168,23 +192,38 @@ import {
|
||||||
} from 'vuelidate/lib/validators'
|
} from 'vuelidate/lib/validators'
|
||||||
import elementForm from '@baserow/modules/builder/mixins/elementForm'
|
import elementForm from '@baserow/modules/builder/mixins/elementForm'
|
||||||
import collectionElementForm from '@baserow/modules/builder/mixins/collectionElementForm'
|
import collectionElementForm from '@baserow/modules/builder/mixins/collectionElementForm'
|
||||||
|
import { TABLE_ORIENTATION } from '@baserow/modules/builder/enums'
|
||||||
|
import DeviceSelector from '@baserow/modules/builder/components/page/header/DeviceSelector.vue'
|
||||||
|
import { mapActions, mapGetters } from 'vuex'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'TableElementForm',
|
name: 'TableElementForm',
|
||||||
components: { ApplicationBuilderFormulaInputGroup },
|
components: { DeviceSelector, ApplicationBuilderFormulaInputGroup },
|
||||||
mixins: [elementForm, collectionElementForm],
|
mixins: [elementForm, collectionElementForm],
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
allowedValues: ['data_source_id', 'fields', 'items_per_page'],
|
allowedValues: [
|
||||||
|
'data_source_id',
|
||||||
|
'fields',
|
||||||
|
'items_per_page',
|
||||||
|
'button_color',
|
||||||
|
'orientation',
|
||||||
|
],
|
||||||
values: {
|
values: {
|
||||||
fields: [],
|
fields: [],
|
||||||
data_source_id: null,
|
data_source_id: null,
|
||||||
items_per_page: 1,
|
items_per_page: 1,
|
||||||
|
button_color: '',
|
||||||
|
orientation: {},
|
||||||
},
|
},
|
||||||
userHasChangedDataSource: false,
|
userHasChangedDataSource: false,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
...mapGetters({ deviceTypeSelected: 'page/getDeviceTypeSelected' }),
|
||||||
|
TABLE_ORIENTATION() {
|
||||||
|
return TABLE_ORIENTATION
|
||||||
|
},
|
||||||
orderedCollectionTypes() {
|
orderedCollectionTypes() {
|
||||||
return this.$registry.getOrderedList('collectionField')
|
return this.$registry.getOrderedList('collectionField')
|
||||||
},
|
},
|
||||||
|
@ -203,6 +242,9 @@ export default {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
...mapActions({
|
||||||
|
actionSetDeviceTypeSelected: 'page/setDeviceTypeSelected',
|
||||||
|
}),
|
||||||
addField() {
|
addField() {
|
||||||
this.values.fields.push({
|
this.values.fields.push({
|
||||||
name: getNextAvailableNameInSequence(
|
name: getNextAvailableNameInSequence(
|
||||||
|
|
|
@ -1,23 +1,22 @@
|
||||||
<template>
|
<template>
|
||||||
<ul class="header__filter">
|
<div class="device-selector">
|
||||||
<li
|
<div
|
||||||
v-for="(deviceType, index) in deviceTypes"
|
v-for="(deviceType, index) in deviceTypes"
|
||||||
:key="deviceType.getType()"
|
:key="index"
|
||||||
class="header__filter-item"
|
class="device-selector__item"
|
||||||
:class="{ 'header__filter-item--no-margin-left': index === 0 }"
|
:class="`device-selector__item--${direction}`"
|
||||||
>
|
>
|
||||||
<a
|
<RadioButton
|
||||||
class="header__filter-link"
|
:key="deviceType.getType()"
|
||||||
:class="{
|
:value="deviceType.getType()"
|
||||||
'active active--primary': deviceTypeSelected === deviceType.getType(),
|
:icon="deviceType.iconClass"
|
||||||
}"
|
:model-value="deviceTypeSelected"
|
||||||
@click="$emit('selected', deviceType.getType())"
|
class="device-selector__button"
|
||||||
>
|
@click.native="$emit('selected', deviceType.getType())"
|
||||||
<i :class="`header__filter-icon ${deviceType.iconClass}`"></i>
|
></RadioButton>
|
||||||
</a>
|
|
||||||
<slot name="deviceTypeControl" :device-type="deviceType"></slot>
|
<slot name="deviceTypeControl" :device-type="deviceType"></slot>
|
||||||
</li>
|
</div>
|
||||||
</ul>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
@ -28,6 +27,11 @@ export default {
|
||||||
type: String,
|
type: String,
|
||||||
required: true,
|
required: true,
|
||||||
},
|
},
|
||||||
|
direction: {
|
||||||
|
type: String,
|
||||||
|
required: false,
|
||||||
|
default: 'column',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
deviceTypes() {
|
deviceTypes() {
|
||||||
|
|
|
@ -147,3 +147,8 @@ export const ELEMENT_EVENTS = {
|
||||||
DATA_SOURCE_REMOVED: 'DATA_SOURCE_REMOVED',
|
DATA_SOURCE_REMOVED: 'DATA_SOURCE_REMOVED',
|
||||||
DATA_SOURCE_AFTER_UPDATE: 'DATA_SOURCE_AFTER_UPDATE',
|
DATA_SOURCE_AFTER_UPDATE: 'DATA_SOURCE_AFTER_UPDATE',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const TABLE_ORIENTATION = {
|
||||||
|
HORIZONTAL: 'horizontal',
|
||||||
|
VERTICAL: 'vertical',
|
||||||
|
}
|
||||||
|
|
|
@ -427,7 +427,10 @@
|
||||||
"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",
|
"buttonColor": "Button color",
|
||||||
"refreshFieldsFromDataSource": "refresh fields from data source"
|
"refreshFieldsFromDataSource": "refresh fields from data source",
|
||||||
|
"orientation": "Orientation",
|
||||||
|
"orientationHorizontal": "Horizontal",
|
||||||
|
"orientationVertical": "Vertical"
|
||||||
},
|
},
|
||||||
"tableElement": {
|
"tableElement": {
|
||||||
"empty": "No items have been found.",
|
"empty": "No items have been found.",
|
||||||
|
@ -443,7 +446,7 @@
|
||||||
"itemsPerPage": "Items per page",
|
"itemsPerPage": "Items per page",
|
||||||
"itemsPerPagePlaceholder": "Enter value...",
|
"itemsPerPagePlaceholder": "Enter value...",
|
||||||
"itemsPerRowLabel": "Items per row",
|
"itemsPerRowLabel": "Items per row",
|
||||||
"itemsPerRowDescription": "Choose, per device type, what the number of repetitions per row should be.",
|
"itemsPerRowDescription": "Number of columns per row and device type.",
|
||||||
"orientationLabel": "Orientation",
|
"orientationLabel": "Orientation",
|
||||||
"orientationVertical": "Vertical",
|
"orientationVertical": "Vertical",
|
||||||
"orientationHorizontal": "Horizontal"
|
"orientationHorizontal": "Horizontal"
|
||||||
|
|
|
@ -29,3 +29,4 @@
|
||||||
@import 'loading_spinner';
|
@import 'loading_spinner';
|
||||||
@import 'update_user_source_form';
|
@import 'update_user_source_form';
|
||||||
@import 'user_source_users_context';
|
@import 'user_source_users_context';
|
||||||
|
@import 'device_selector';
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
.device-selector {
|
||||||
|
display: flex;
|
||||||
|
flex-flow: row wrap;
|
||||||
|
align-items: center;
|
||||||
|
gap: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.device-selector__item {
|
||||||
|
display: flex;
|
||||||
|
gap: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.device-selector__item--column {
|
||||||
|
flex: 1;
|
||||||
|
flex-flow: column nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.device-selector__item--row {
|
||||||
|
flex-direction: row;
|
||||||
|
flex-grow: 1;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.device-selector__button {
|
||||||
|
border: none;
|
||||||
|
box-shadow: none;
|
||||||
|
|
||||||
|
.button__icon {
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,3 +1,7 @@
|
||||||
|
.baserow-table-wrapper {
|
||||||
|
overflow-x: auto;
|
||||||
|
}
|
||||||
|
|
||||||
.baserow-table {
|
.baserow-table {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
border: 1px solid $black;
|
border: 1px solid $black;
|
||||||
|
@ -6,10 +10,6 @@
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.baserow-table__header-row {
|
|
||||||
background-color: $palette-neutral-200;
|
|
||||||
}
|
|
||||||
|
|
||||||
.baserow-table__header-cell,
|
.baserow-table__header-cell,
|
||||||
.baserow-table__cell {
|
.baserow-table__cell {
|
||||||
padding: 12px 20px 10px;
|
padding: 12px 20px 10px;
|
||||||
|
@ -17,13 +17,28 @@
|
||||||
|
|
||||||
.baserow-table__header-cell {
|
.baserow-table__header-cell {
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
border-bottom: 1px solid $black;
|
background-color: $palette-neutral-200;
|
||||||
}
|
}
|
||||||
|
|
||||||
.baserow-table__cell {
|
.baserow-table__separator {
|
||||||
border-bottom: 1px solid $black;
|
.baserow-table__row:not(:last-child) & {
|
||||||
|
border-bottom: 1px solid $black;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.baserow-table__row:last-child & {
|
.baserow-table--horizontal {
|
||||||
|
.baserow-table__header-cell,
|
||||||
|
.baserow-table__cell {
|
||||||
|
border-bottom: 1px solid $black;
|
||||||
|
}
|
||||||
|
|
||||||
|
.baserow-table__row:last-child .baserow-table__cell {
|
||||||
border-bottom: none;
|
border-bottom: none;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.baserow-table--vertical {
|
||||||
|
.baserow-table__header-cell {
|
||||||
|
border-right: 1px solid $black;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,14 +1,7 @@
|
||||||
.repeat-element__device-selector {
|
.repeat-element__device-selector {
|
||||||
gap: 10px;
|
|
||||||
|
|
||||||
input[type='number'] {
|
input[type='number'] {
|
||||||
margin-top: 5px;
|
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.header__filter-icon {
|
|
||||||
margin: 0 auto;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.repeat-element__preview {
|
.repeat-element__preview {
|
||||||
|
|
Loading…
Add table
Reference in a new issue