diff --git a/.env.dev.example b/.env.dev.example index e577c0a51..dd5914320 100644 --- a/.env.dev.example +++ b/.env.dev.example @@ -29,3 +29,15 @@ MEDIA_URL=http://localhost:4000/media/ POSTGRES_DEV_EXTRA_ARGS="-c shared_buffers=512MB -c fsync=off -c full_page_writes=off -c synchronous_commit=off" POSTGRES_IMAGE_VERSION=12 + +# Settings for local dev with MinIO to have local s3-like object storage +# AWS_ACCESS_KEY_ID=<REDACTED> +# AWS_SECRET_ACCESS_KEY=<REDACTED> +# AWS_STORAGE_BUCKET_NAME=baserow +# AWS_S3_ENDPOINT_URL=http://192.168.1.16:9000 +# AWS_S3_USE_SSL=off +# AWS_S3_CUSTOM_DOMAIN= +# AWS_DEFAULT_ACL= +# AWS_S3_VERIFY=off +# AWS_S3_SIGNATURE_VERSION = 's3v4' +# AWS_S3_ADDRESSING_STYLE = 'path' diff --git a/.env.example b/.env.example index 1356c210d..1c6e3b15f 100644 --- a/.env.example +++ b/.env.example @@ -93,6 +93,7 @@ DATABASE_NAME=baserow # BASEROW_WEBHOOKS_MAX_PER_TABLE= # BASEROW_WEBHOOKS_MAX_CALL_LOG_ENTRIES= # BASEROW_WEBHOOKS_REQUEST_TIMEOUT_SECONDS= +# BASEROW_WEBHOOK_ROWS_ENTER_VIEW_BATCH_SIZE: # BASEROW_AIRTABLE_IMPORT_SOFT_TIME_LIMIT= # HOURS_UNTIL_TRASH_PERMANENTLY_DELETED= @@ -137,6 +138,7 @@ DATABASE_NAME=baserow # BASEROW_ENTERPRISE_AUDIT_LOG_CLEANUP_INTERVAL_MINUTES= # BASEROW_ENTERPRISE_AUDIT_LOG_RETENTION_DAYS= # BASEROW_ALLOW_MULTIPLE_SSO_PROVIDERS_FOR_SAME_ACCOUNT= +# BASEROW_ENTERPRISE_GROUPED_AGGREGATE_SERVICE_MAX_SERIES: # BASEROW_PERIODIC_FIELD_UPDATE_CRONTAB= # BASEROW_PERIODIC_FIELD_UPDATE_UNUSED_WORKSPACE_INTERVAL_MIN= diff --git a/.gitignore b/.gitignore index 3ef1fa69f..a648828b3 100644 --- a/.gitignore +++ b/.gitignore @@ -123,6 +123,9 @@ out/ .cursor-config/ !config/cursor/.cursor-config/ +# Pyright config file +pyrightconfig.json + # VIM's swap files *.swp @@ -146,4 +149,4 @@ premium/web-frontend/package.json # Storybook web-frontend/.nuxt-storybook/ -web-frontend/storybook-static \ No newline at end of file +web-frontend/storybook-static diff --git a/README.md b/README.md index 41d4d3258..f680a4f53 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ tool gives you the powers of a developer without leaving your browser. [](https://www.heroku.com/deploy/?template=https://github.com/bram2w/baserow/tree/master) ```bash -docker run -v baserow_data:/baserow/data -p 80:80 -p 443:443 baserow/baserow:1.31.1 +docker run -v baserow_data:/baserow/data -p 80:80 -p 443:443 baserow/baserow:1.32.0 ```  @@ -89,7 +89,7 @@ Created by Baserow B.V. - bram@baserow.io. Distributes under the MIT license. See `LICENSE` for more information. -Version: 1.31.1 +Version: 1.32.0 The official repository can be found at https://gitlab.com/baserow/baserow. diff --git a/backend/Makefile b/backend/Makefile index aab4dbc91..0ed2c9372 100644 --- a/backend/Makefile +++ b/backend/Makefile @@ -54,8 +54,8 @@ BACKEND_TESTS_DIRS_FROM_ROOT=backend/tests/ premium/backend/tests/ enterprise/ba .PHONY: help venv venv-clean install-oss install install-extra package docker-build package-install\ clean clean-all package-build package-clean deps deps-clean deps-install deps-install-dev deps-upgrade\ lint lint-fix lint-python format sort make-translations compile-translations\ - test test-builder test-builder-parallel test-compat test-compat-parallel test-coverage test-parallel \ - test-regenerate-ci-durations ci-test-python ci-check-startup-python ci-coverage-report fix\ + test test-builder test-builder-parallel test-coverage test-parallel test-regenerate-ci-durations\ + ci-test-python ci-check-startup-python ci-coverage-report fix\ run-dev @@ -179,18 +179,12 @@ test-builder: .check-dev test-builder-parallel: .check-dev $(VPYTEST) tests/baserow/contrib/builder -n 10 || exit -test-compat: .check-dev - $(VPYTEST) tests/baserow/compat --run-disabled-in-ci || exit; - test-regenerate-ci-durations: .check-dev $(VPYTEST) $(BACKEND_TESTS_DIRS) --store-durations || exit; test-parallel: .check-dev $(VPYTEST) $(BACKEND_TESTS_DIRS) -n 10 || exit; -test-compat-parallel: .check-dev - $(VPYTEST) tests/baserow/compat --run-disabled-in-ci -n 10 || exit; - .make-django-cmd: .check-dev for pkg_dir in $(SOURCE_DIRS); do echo $$pkg_dir ; cd $$pkg_dir ; \ $(VDJANGO) $(DJANGO_COMMAND) || true ; cd - ;\ diff --git a/backend/docker/docker-entrypoint.sh b/backend/docker/docker-entrypoint.sh index 936f23869..f4cc2a764 100755 --- a/backend/docker/docker-entrypoint.sh +++ b/backend/docker/docker-entrypoint.sh @@ -6,7 +6,7 @@ set -euo pipefail # ENVIRONMENT VARIABLES USED DIRECTLY BY THIS ENTRYPOINT # ====================================================== -export BASEROW_VERSION="1.31.1" +export BASEROW_VERSION="1.32.0" # Used by docker-entrypoint.sh to start the dev server # If not configured you'll receive this: CommandError: "0.0.0.0:" is not a valid port number or address:port pair. diff --git a/backend/src/baserow/api/templates/serializers.py b/backend/src/baserow/api/templates/serializers.py index d654352f7..84d2fcd03 100644 --- a/backend/src/baserow/api/templates/serializers.py +++ b/backend/src/baserow/api/templates/serializers.py @@ -28,6 +28,7 @@ class TemplateSerializer(serializers.ModelSerializer): "keywords", "workspace_id", "is_default", + "open_application", ) @extend_schema_field(OpenApiTypes.STR) diff --git a/backend/src/baserow/config/settings/base.py b/backend/src/baserow/config/settings/base.py index 6de08c823..3ecb93eba 100644 --- a/backend/src/baserow/config/settings/base.py +++ b/backend/src/baserow/config/settings/base.py @@ -423,7 +423,7 @@ SPECTACULAR_SETTINGS = { "name": "MIT", "url": "https://gitlab.com/baserow/baserow/-/blob/master/LICENSE", }, - "VERSION": "1.31.1", + "VERSION": "1.32.0", "SERVE_INCLUDE_SCHEMA": False, "TAGS": [ {"name": "Settings"}, @@ -986,6 +986,10 @@ BASEROW_WEBHOOKS_URL_CHECK_TIMEOUT_SECS = int( BASEROW_MAX_WEBHOOK_CALLS_IN_QUEUE_PER_WEBHOOK = ( int(os.getenv("BASEROW_MAX_WEBHOOK_CALLS_IN_QUEUE_PER_WEBHOOK", "0")) or None ) +BASEROW_WEBHOOKS_BATCH_LIMIT = int(os.getenv("BASEROW_WEBHOOKS_BATCH_LIMIT", 5)) +BASEROW_WEBHOOK_ROWS_ENTER_VIEW_BATCH_SIZE = int( + os.getenv("BASEROW_WEBHOOK_ROWS_ENTER_VIEW_BATCH_SIZE", BATCH_ROWS_SIZE_LIMIT) +) # ======== WARNING ======== # Please read and understand everything at: @@ -1271,7 +1275,9 @@ BASEROW_MAX_HEALTHY_CELERY_QUEUE_SIZE = int( BASEROW_USE_LOCAL_CACHE = str_to_bool(os.getenv("BASEROW_USE_LOCAL_CACHE", "true")) + # -- CACHALOT SETTINGS -- + CACHALOT_TIMEOUT = int(os.getenv("BASEROW_CACHALOT_TIMEOUT", 60 * 60 * 24 * 7)) BASEROW_CACHALOT_ONLY_CACHABLE_TABLES = os.getenv( "BASEROW_CACHALOT_ONLY_CACHABLE_TABLES", None diff --git a/backend/src/baserow/config/settings/test.py b/backend/src/baserow/config/settings/test.py index 2d6549bb6..694d59ec1 100644 --- a/backend/src/baserow/config/settings/test.py +++ b/backend/src/baserow/config/settings/test.py @@ -5,6 +5,8 @@ from unittest.mock import patch from dotenv import dotenv_values +from baserow.config.settings.utils import str_to_bool + # Create a .env.testing file in the backend directory to store different test settings and # override the default ones. For different test settings, provide the TEST_ENV_FILE # environment variable with the name of the file to use. Everything that starts with @@ -36,11 +38,22 @@ CELERY_TASK_EAGER_PROPAGATES = True CHANNEL_LAYERS = {"default": {"BACKEND": "channels.layers.InMemoryChannelLayer"}} + +# Set to 'off' to runs all migrations and disable the custom setup fixture that installs +# all pgPSQL functions. Default is 'on' for faster setup by skipping migrations. +BASEROW_TESTS_SETUP_DB_FIXTURE = str_to_bool( + os.getenv("BASEROW_TESTS_SETUP_DB_FIXTURE", "on") +) +DATABASES["default"]["TEST"] = { + "MIGRATE": not BASEROW_TESTS_SETUP_DB_FIXTURE, +} +# Psycopg3 only? # Disable default optimizations for the tests because they make tests slower. DATABASES["default"]["OPTIONS"] = { "server_side_binding": False, "prepare_threshold": None, } + # Open a second database connection that can be used to test transactions. DATABASES["default-copy"] = deepcopy(DATABASES["default"]) @@ -102,7 +115,6 @@ BASEROW_LOGIN_ACTION_LOG_LIMIT = RateLimit.from_string("1000/s") BASEROW_WEBHOOKS_ALLOW_PRIVATE_ADDRESS = False - CACHALOT_ENABLED = str_to_bool(os.getenv("CACHALOT_ENABLED", "false")) if CACHALOT_ENABLED: CACHES[CACHALOT_CACHE] = { diff --git a/backend/src/baserow/contrib/builder/api/data_sources/views.py b/backend/src/baserow/contrib/builder/api/data_sources/views.py index 1c83d424f..a251882ae 100644 --- a/backend/src/baserow/contrib/builder/api/data_sources/views.py +++ b/backend/src/baserow/contrib/builder/api/data_sources/views.py @@ -270,9 +270,7 @@ class DataSourceView(APIView): if "page_id" in request.data: page = PageHandler().get_page( int(request.data["page_id"]), - base_queryset=Page.objects_with_shared.filter( - builder=data_source.page.builder - ), + base_queryset=Page.objects.filter(builder=data_source.page.builder), ) # Do we have a service? diff --git a/backend/src/baserow/contrib/builder/api/domains/public_views.py b/backend/src/baserow/contrib/builder/api/domains/public_views.py index 331eeb87e..e3cfbbe19 100644 --- a/backend/src/baserow/contrib/builder/api/domains/public_views.py +++ b/backend/src/baserow/contrib/builder/api/domains/public_views.py @@ -1,8 +1,11 @@ +from typing import Any, Dict, List + from django.db import transaction from drf_spectacular.types import OpenApiTypes from drf_spectacular.utils import OpenApiParameter, extend_schema from rest_framework.permissions import AllowAny +from rest_framework.request import Request from rest_framework.response import Response from rest_framework.views import APIView @@ -27,7 +30,11 @@ from baserow.contrib.builder.api.data_sources.errors import ( from baserow.contrib.builder.api.data_sources.serializers import ( DispatchDataSourceRequestSerializer, ) -from baserow.contrib.builder.api.domains.serializers import PublicBuilderSerializer +from baserow.contrib.builder.api.domains.serializers import ( + PublicBuilderSerializer, + PublicDataSourceSerializer, + PublicElementSerializer, +) from baserow.contrib.builder.api.pages.errors import ERROR_PAGE_DOES_NOT_EXIST from baserow.contrib.builder.api.workflow_actions.serializers import ( BuilderWorkflowActionSerializer, @@ -42,12 +49,17 @@ from baserow.contrib.builder.data_sources.exceptions import ( ) from baserow.contrib.builder.data_sources.handler import DataSourceHandler from baserow.contrib.builder.data_sources.service import DataSourceService +from baserow.contrib.builder.domains.handler import DomainHandler from baserow.contrib.builder.domains.service import DomainService from baserow.contrib.builder.elements.registries import element_type_registry from baserow.contrib.builder.elements.service import ElementService from baserow.contrib.builder.errors import ERROR_BUILDER_DOES_NOT_EXIST from baserow.contrib.builder.exceptions import BuilderDoesNotExist -from baserow.contrib.builder.handler import BuilderHandler +from baserow.contrib.builder.handler import ( + BUILDER_PUBLIC_BUILDER_BY_DOMAIN_TTL_SECONDS, + BUILDER_PUBLIC_RECORDS_CACHE_TTL_SECONDS, + BuilderHandler, +) from baserow.contrib.builder.pages.exceptions import PageDoesNotExist from baserow.contrib.builder.pages.handler import PageHandler from baserow.contrib.builder.service import BuilderService @@ -57,6 +69,7 @@ from baserow.contrib.builder.workflow_actions.registries import ( from baserow.contrib.builder.workflow_actions.service import ( BuilderWorkflowActionService, ) +from baserow.core.cache import global_cache from baserow.core.exceptions import ApplicationDoesNotExist, PermissionException from baserow.core.services.exceptions import ( DoesNotExist, @@ -66,8 +79,6 @@ from baserow.core.services.exceptions import ( ) from baserow.core.services.registries import service_type_registry -from .serializers import PublicDataSourceSerializer, PublicElementSerializer - class PublicBuilderByDomainNameView(APIView): permission_classes = (AllowAny,) @@ -93,18 +104,36 @@ class PublicBuilderByDomainNameView(APIView): }, ) @map_exceptions({BuilderDoesNotExist: ERROR_BUILDER_DOES_NOT_EXIST}) - def get(self, request, domain_name): + def get(self, request: Request, domain_name: str): """ Responds with a serialized version of the builder related to the query. Try to match a published builder for the given domain name. Used to display the public site. """ + data = global_cache.get( + DomainHandler.get_public_builder_by_domain_cache_key(domain_name), + default=lambda: self._get_public_builder_by_domain(request, domain_name), + timeout=BUILDER_PUBLIC_BUILDER_BY_DOMAIN_TTL_SECONDS, + ) + return Response(data) + + def _get_public_builder_by_domain(self, request: Request, domain_name: str): + """ + Returns a serialized builder which has a domain matching `domain_name`. + + Only requested if the public get-by-domain cache is stale, or if the + application has been re-published. + + :param request: the HTTP request. + :param domain_name: the domain name to match. + :return: a publicly serialized builder. + """ + builder = DomainService().get_public_builder_by_domain_name( request.user, domain_name ) - - return Response(PublicBuilderSerializer(builder).data) + return PublicBuilderSerializer(builder).data class PublicBuilderByIdView(APIView): @@ -180,20 +209,44 @@ class PublicElementsView(APIView): PageDoesNotExist: ERROR_PAGE_DOES_NOT_EXIST, } ) - def get(self, request, page_id): + def get(self, request: Request, page_id: int): """ Responds with a list of serialized elements that belongs to the given page id. """ + if PageHandler().is_published_page(page_id): + data = global_cache.get( + PageHandler.get_page_public_records_cache_key( + page_id, request.user_source_user, "elements" + ), + default=lambda: self._get_public_page_elements(request, page_id), + timeout=BUILDER_PUBLIC_RECORDS_CACHE_TTL_SECONDS, + ) + else: + data = self._get_public_page_elements(request, page_id) + + return Response(data) + + def _get_public_page_elements( + self, request: Request, page_id: int + ) -> List[Dict[str, Any]]: + """ + Returns a list of serialized elements that belong to the given page id. + + Only requested if the public elements cache is stale, or if the page is + being previewed. + + :param request: the HTTP request. + :param page_id: the page id. + :return: a list of serialized elements. + """ + page = PageHandler().get_page(page_id) - elements = ElementService().get_elements(request.user, page) - - data = [ + return [ element_type_registry.get_serializer(element, PublicElementSerializer).data for element in elements ] - return Response(data) class PublicDataSourcesView(APIView): @@ -227,26 +280,48 @@ class PublicDataSourcesView(APIView): PageDoesNotExist: ERROR_PAGE_DOES_NOT_EXIST, } ) - def get(self, request, page_id): + def get(self, request: Request, page_id: int): """ Responds with a list of serialized data_sources that belong to the page if the user has access to it. """ - page = PageHandler().get_page(page_id) + if PageHandler().is_published_page(page_id): + data = global_cache.get( + PageHandler.get_page_public_records_cache_key( + page_id, request.user_source_user, "data_sources" + ), + default=lambda: self._get_public_page_data_sources(request, page_id), + timeout=BUILDER_PUBLIC_RECORDS_CACHE_TTL_SECONDS, + ) + else: + data = self._get_public_page_data_sources(request, page_id) + return Response(data) + + def _get_public_page_data_sources(self, request: Request, page_id: int): + """ + Returns a list of serialized data sources that belong to the given page id. + + Only requested if the public data sources cache is stale, or if the page is + being previewed. + + :param request: the HTTP request. + :param page_id: the page id. + :return: a list of serialized data sources. + """ + + page = PageHandler().get_page(page_id) data_sources = DataSourceService().get_data_sources(request.user, page) - handler = BuilderHandler() - public_properties = handler.get_builder_public_properties( + public_properties = BuilderHandler().get_builder_public_properties( request.user_source_user, page.builder ) - allowed_fields = [] for fields in public_properties["external"].values(): allowed_fields.extend(fields) - data = [ + return [ service_type_registry.get_serializer( data_source.service, PublicDataSourceSerializer, @@ -256,8 +331,6 @@ class PublicDataSourcesView(APIView): if data_source.service and data_source.service.integration_id ] - return Response(data) - class PublicBuilderWorkflowActionsView(APIView): permission_classes = (AllowAny,) @@ -295,14 +368,45 @@ class PublicBuilderWorkflowActionsView(APIView): PageDoesNotExist: ERROR_PAGE_DOES_NOT_EXIST, } ) - def get(self, request, page_id: int): - page = PageHandler().get_page(page_id) + def get(self, request: Request, page_id: int): + """ " + Responds with a list of serialized workflow actions that belongs to the given + page id. + """ + if PageHandler().is_published_page(page_id): + data = global_cache.get( + PageHandler.get_page_public_records_cache_key( + page_id, request.user_source_user, "workflow_actions" + ), + default=lambda: self._get_public_page_workflow_actions( + request, page_id + ), + timeout=BUILDER_PUBLIC_RECORDS_CACHE_TTL_SECONDS, + ) + else: + data = self._get_public_page_workflow_actions(request, page_id) + + return Response(data) + + def _get_public_page_workflow_actions(self, request: Request, page_id: int): + """ + Returns a list of serialized workflow actions that belong to the given page id. + + Only requested if the public workflow actions cache is stale, or if the page is + being previewed. + + :param request: the HTTP request. + :param page_id: the page id. + :return: a list of serialized workflow actions. + """ + + page = PageHandler().get_page(page_id) workflow_actions = BuilderWorkflowActionService().get_workflow_actions( request.user, page ) - data = [ + return [ builder_workflow_action_type_registry.get_serializer( workflow_action, BuilderWorkflowActionSerializer, @@ -311,8 +415,6 @@ class PublicBuilderWorkflowActionsView(APIView): for workflow_action in workflow_actions ] - return Response(data) - class PublicDispatchDataSourceView(APIView): permission_classes = (AllowAny,) diff --git a/backend/src/baserow/contrib/builder/api/elements/serializers.py b/backend/src/baserow/contrib/builder/api/elements/serializers.py index 8dbf8e7d9..a6eac0189 100644 --- a/backend/src/baserow/contrib/builder/api/elements/serializers.py +++ b/backend/src/baserow/contrib/builder/api/elements/serializers.py @@ -18,6 +18,9 @@ from baserow.contrib.builder.elements.models import ( CollectionElementPropertyOptions, CollectionField, Element, + LinkElement, + MenuItemElement, + NavigationElementMixin, ) from baserow.contrib.builder.elements.registries import ( collection_field_type_registry, @@ -378,3 +381,103 @@ class CollectionElementPropertyOptionsSerializer( class Meta: model = CollectionElementPropertyOptions fields = ["schema_property", "filterable", "sortable", "searchable"] + + +class MenuItemSerializer(serializers.ModelSerializer): + """Serializes the MenuItemElement.""" + + children = serializers.ListSerializer( + child=serializers.DictField(), + required=False, + help_text="A MenuItemElement that is a child of this instance.", + ) + + navigation_type = serializers.ChoiceField( + choices=NavigationElementMixin.NAVIGATION_TYPES.choices, + help_text=LinkElement._meta.get_field("navigation_type").help_text, + required=False, + ) + navigate_to_page_id = serializers.IntegerField( + allow_null=True, + default=None, + help_text=LinkElement._meta.get_field("navigate_to_page").help_text, + required=False, + ) + navigate_to_url = FormulaSerializerField( + help_text=LinkElement._meta.get_field("navigate_to_url").help_text, + default="", + allow_blank=True, + required=False, + ) + page_parameters = PageParameterValueSerializer( + many=True, + default=[], + help_text=LinkElement._meta.get_field("page_parameters").help_text, + required=False, + ) + query_parameters = PageParameterValueSerializer( + many=True, + default=[], + help_text=LinkElement._meta.get_field("query_parameters").help_text, + required=False, + ) + target = serializers.ChoiceField( + choices=NavigationElementMixin.TARGETS.choices, + help_text=LinkElement._meta.get_field("target").help_text, + required=False, + ) + + class Meta: + model = MenuItemElement + fields = [ + "id", + "variant", + "type", + "menu_item_order", + "uid", + "name", + "navigation_type", + "navigate_to_page_id", + "navigate_to_url", + "page_parameters", + "query_parameters", + "parent_menu_item", + "target", + "children", + ] + + def to_representation(self, instance): + """Recursively serializes child MenuItemElements.""" + + data = super().to_representation(instance) + all_items = self.context.get("all_items", []) + + # Get children from all_items to save queries + children = [i for i in all_items if instance.id == i.parent_menu_item_id] + + data["children"] = MenuItemSerializer( + children, many=True, context=self.context + ).data + + return data + + +class NestedMenuItemsMixin(serializers.Serializer): + menu_items = serializers.SerializerMethodField( + help_text="Menu items of the MenuElement." + ) + + @extend_schema_field(MenuItemSerializer) + def get_menu_items(self, obj): + """Return the serialized version of the MenuItemElement.""" + + # Prefetches the child MenuItemElements for performance. + menu_items = obj.menu_items.all() + + root_items = [ + child for child in menu_items if child.parent_menu_item_id is None + ] + + return MenuItemSerializer( + root_items, many=True, context={"all_items": menu_items} + ).data diff --git a/backend/src/baserow/contrib/builder/api/theme/serializers.py b/backend/src/baserow/contrib/builder/api/theme/serializers.py index 572e8056c..85d7fe67d 100644 --- a/backend/src/baserow/contrib/builder/api/theme/serializers.py +++ b/backend/src/baserow/contrib/builder/api/theme/serializers.py @@ -37,16 +37,35 @@ class DynamicConfigBlockSerializer(serializers.Serializer): if not isinstance(theme_config_block_type_name, list): theme_config_block_type_name = [theme_config_block_type_name] - for prop, type_name in zip(property_name, theme_config_block_type_name): - theme_config_block_type = theme_config_block_registry.get(type_name) - self.fields[prop] = theme_config_block_type.get_serializer_class( - request_serializer=request_serializer - )(**({"help_text": f"Styles overrides for {prop}"} | serializer_kwargs)) + for prop, type_names in zip(property_name, theme_config_block_type_name): + if not isinstance(type_names, list): + type_names = [type_names] + + config_blocks = ( + theme_config_block_registry.get(type_name) for type_name in type_names + ) + serializer_class = combine_theme_config_blocks_serializer_class( + config_blocks, + request_serializer=request_serializer, + name="SubConfigBlockSerializer", + ) + + self.fields[prop] = serializer_class(**serializer_kwargs) + + all_type_names = "".join( + [ + "And".join(sub.capitalize() for sub in p) + if isinstance(p, list) + else p.capitalize() + for p in theme_config_block_type_name + ] + ) # Dynamically create the Meta class with ref name to prevent collision class DynamicMeta: - type_names = "".join([p.capitalize() for p in theme_config_block_type_name]) - ref_name = f"{type_names}ConfigBlockSerializer" + type_names = all_type_names + ref_name = f"{all_type_names}ConfigBlockSerializer" + meta_ref_name = f"{all_type_names}ConfigBlockSerializer" self.Meta = DynamicMeta @@ -72,6 +91,41 @@ def serialize_builder_theme(builder: Builder) -> dict: return theme +def combine_theme_config_blocks_serializer_class( + theme_config_blocks, + request_serializer=False, + name="CombinedThemeConfigBlocksSerializer", +) -> serializers.Serializer: + """ + This helper function generates one single serializer that contains all the fields + of all the theme config blocks. The API always communicates all theme properties + flat in one single object. + + :return: The generated serializer. + """ + + attrs = {} + + for theme_config_block in theme_config_blocks: + serializer = theme_config_block.get_serializer_class( + request_serializer=request_serializer + ) + serializer_fields = serializer().get_fields() + + for name, field in serializer_fields.items(): + attrs[name] = field + + class Meta: + ref_name = "".join(t.type.capitalize() for t in theme_config_blocks) + name + meta_ref_name = "".join(t.type.capitalize() for t in theme_config_blocks) + name + + attrs["Meta"] = Meta + + class_object = type(name, (serializers.Serializer,), attrs) + + return class_object + + @cache def get_combined_theme_config_blocks_serializer_class( request_serializer=False, @@ -90,28 +144,10 @@ def get_combined_theme_config_blocks_serializer_class( "imported before the theme config blocks have been registered." ) - attrs = {} - - for theme_config_block in theme_config_block_registry.get_all(): - serializer = theme_config_block.get_serializer_class( - request_serializer=request_serializer - ) - serializer_fields = serializer().get_fields() - - for name, field in serializer_fields.items(): - attrs[name] = field - - class Meta: - meta_ref_name = "combined_theme_config_blocks_serializer" - - attrs["Meta"] = Meta - - class_object = type( - "CombinedThemeConfigBlocksSerializer", (serializers.Serializer,), attrs + return combine_theme_config_blocks_serializer_class( + theme_config_block_registry.get_all(), request_serializer=request_serializer ) - return class_object - CombinedThemeConfigBlocksSerializer = ( get_combined_theme_config_blocks_serializer_class() diff --git a/backend/src/baserow/contrib/builder/application_types.py b/backend/src/baserow/contrib/builder/application_types.py index 1e926fc0d..c3110654a 100755 --- a/backend/src/baserow/contrib/builder/application_types.py +++ b/backend/src/baserow/contrib/builder/application_types.py @@ -7,7 +7,6 @@ from django.conf import settings from django.contrib.auth.models import AbstractUser from django.core.files.storage import Storage from django.db import transaction -from django.db.models import Prefetch from django.db.transaction import Atomic from django.urls import include, path @@ -175,7 +174,7 @@ class BuilderApplicationType(ApplicationType): pages = PageHandler().get_pages( builder, - base_queryset=Page.objects_with_shared.prefetch_related( + base_queryset=Page.objects.prefetch_related( "element_set", "datasource_set" ), ) @@ -497,9 +496,7 @@ class BuilderApplicationType(ApplicationType): def enhance_queryset(self, queryset): queryset = queryset.select_related("favicon_file").prefetch_related( - "user_sources", - "integrations", - Prefetch("page_set", queryset=Page.objects_with_shared.all()), + "user_sources", "integrations", "page_set" ) queryset = theme_config_block_registry.enhance_list_builder_queryset(queryset) return queryset diff --git a/backend/src/baserow/contrib/builder/apps.py b/backend/src/baserow/contrib/builder/apps.py index f5376b6bc..843bd50ed 100644 --- a/backend/src/baserow/contrib/builder/apps.py +++ b/backend/src/baserow/contrib/builder/apps.py @@ -183,8 +183,10 @@ class BuilderConfig(AppConfig): ImageElementType, InputTextElementType, LinkElementType, + MenuElementType, RecordSelectorElementType, RepeatElementType, + SimpleContainerElementType, TableElementType, TextElementType, ) @@ -207,6 +209,8 @@ class BuilderConfig(AppConfig): element_type_registry.register(DateTimePickerElementType()) element_type_registry.register(HeaderElementType()) element_type_registry.register(FooterElementType()) + element_type_registry.register(MenuElementType()) + element_type_registry.register(SimpleContainerElementType()) from .domains.domain_types import CustomDomainType, SubDomainType from .domains.registries import domain_type_registry @@ -261,11 +265,11 @@ class BuilderConfig(AppConfig): theme_config_block_registry.register(ColorThemeConfigBlockType()) theme_config_block_registry.register(TypographyThemeConfigBlockType()) theme_config_block_registry.register(ButtonThemeConfigBlockType()) - theme_config_block_registry.register(LinkThemeConfigBlockType()) theme_config_block_registry.register(ImageThemeConfigBlockType()) theme_config_block_registry.register(PageThemeConfigBlockType()) theme_config_block_registry.register(InputThemeConfigBlockType()) theme_config_block_registry.register(TableThemeConfigBlockType()) + theme_config_block_registry.register(LinkThemeConfigBlockType()) from .workflow_actions.registries import builder_workflow_action_type_registry from .workflow_actions.workflow_action_types import ( diff --git a/backend/src/baserow/contrib/builder/domains/handler.py b/backend/src/baserow/contrib/builder/domains/handler.py index 08feea365..4497b89e0 100644 --- a/backend/src/baserow/contrib/builder/domains/handler.py +++ b/backend/src/baserow/contrib/builder/domains/handler.py @@ -1,5 +1,5 @@ from datetime import datetime, timezone -from typing import Iterable, List, cast +from typing import Iterable, List, Optional, cast from django.db.models import QuerySet from django.db.utils import IntegrityError @@ -13,8 +13,10 @@ from baserow.contrib.builder.domains.models import Domain from baserow.contrib.builder.domains.registries import DomainType from baserow.contrib.builder.exceptions import BuilderDoesNotExist from baserow.contrib.builder.models import Builder +from baserow.core.cache import global_cache from baserow.core.db import specific_iterator from baserow.core.exceptions import IdDoesNotExist +from baserow.core.models import Workspace from baserow.core.registries import ImportExportConfig, application_type_registry from baserow.core.storage import get_default_storage from baserow.core.trash.handler import TrashHandler @@ -193,6 +195,28 @@ class DomainHandler: return full_order + def get_published_domain_applications( + self, workspace: Optional[Workspace] = None + ) -> QuerySet[Builder]: + """ + Returns all published domain applications in a workspace or all published + domain applications in the instance if no workspace is provided. + + A domain application is the builder application which is associated with + the domain it was published to. It is not the application which the page + designer created their application with. + + :param workspace: Only return published domain applications in this workspace. + :return: A queryset of published domain applications. + """ + + applications = Builder.objects.exclude(published_from=None) + return ( + applications.filter(published_from__builder__workspace=workspace) + if workspace + else applications + ) + def publish(self, domain: Domain, progress: Progress | None = None): """ Publishes a builder for the given domain object. If the builder was @@ -252,4 +276,15 @@ class DomainHandler: domain.last_published = datetime.now(tz=timezone.utc) domain.save() + # Invalidate the public builder-by-domain cache after a new publication. + DomainHandler.invalidate_public_builder_by_domain_cache(domain.domain_name) + return domain + + @classmethod + def get_public_builder_by_domain_cache_key(cls, domain_name: str) -> str: + return f"ab_public_builder_by_domain_{domain_name}" + + @classmethod + def invalidate_public_builder_by_domain_cache(cls, domain_name: str): + global_cache.invalidate(cls.get_public_builder_by_domain_cache_key(domain_name)) diff --git a/backend/src/baserow/contrib/builder/elements/element_types.py b/backend/src/baserow/contrib/builder/elements/element_types.py index ba4c7e858..fed130d44 100644 --- a/backend/src/baserow/contrib/builder/elements/element_types.py +++ b/backend/src/baserow/contrib/builder/elements/element_types.py @@ -15,13 +15,17 @@ from typing import ( from django.core.exceptions import ValidationError from django.core.validators import validate_email -from django.db.models import IntegerField, QuerySet +from django.db.models import IntegerField, Q, QuerySet from django.db.models.functions import Cast from rest_framework import serializers from rest_framework.exceptions import ValidationError as DRFValidationError -from baserow.contrib.builder.api.elements.serializers import ChoiceOptionSerializer +from baserow.contrib.builder.api.elements.serializers import ( + ChoiceOptionSerializer, + MenuItemSerializer, + NestedMenuItemsMixin, +) from baserow.contrib.builder.data_providers.exceptions import ( FormDataProviderChunkInvalidException, ) @@ -47,13 +51,17 @@ from baserow.contrib.builder.elements.models import ( FormContainerElement, HeaderElement, HeadingElement, + HorizontalAlignments, IFrameElement, ImageElement, InputTextElement, LinkElement, + MenuElement, + MenuItemElement, NavigationElementMixin, RecordSelectorElement, RepeatElement, + SimpleContainerElement, TableElement, TextElement, VerticalAlignments, @@ -70,6 +78,7 @@ from baserow.contrib.builder.theme.theme_config_block_types import ( TableThemeConfigBlockType, ) from baserow.contrib.builder.types import ElementDict +from baserow.contrib.builder.workflow_actions.models import BuilderWorkflowAction from baserow.core.constants import ( DATE_FORMAT, DATE_FORMAT_CHOICES, @@ -270,6 +279,17 @@ class FormContainerElementType(ContainerElementTypeMixin, ElementType): ] +class SimpleContainerElementType(ContainerElementTypeMixin, ElementType): + type = "simple_container" + model_class = SimpleContainerElement + + class SerializedDict(ContainerElementTypeMixin.SerializedDict): + pass + + def get_pytest_params(self, pytest_data_fixture) -> Dict[str, Any]: + return {} + + class TableElementType(CollectionElementWithFieldsTypeMixin, ElementType): type = "table" model_class = TableElement @@ -303,10 +323,11 @@ class TableElementType(CollectionElementWithFieldsTypeMixin, ElementType): ), "styles": DynamicConfigBlockSerializer( required=False, - property_name=["button", "table"], + property_name=["button", "table", "header_button"], theme_config_block_type_name=[ ButtonThemeConfigBlockType.type, TableThemeConfigBlockType.type, + ButtonThemeConfigBlockType.type, ], serializer_kwargs={"required": False}, ), @@ -366,8 +387,11 @@ class RepeatElementType( **super().serializer_field_overrides, "styles": DynamicConfigBlockSerializer( required=False, - property_name="button", - theme_config_block_type_name=ButtonThemeConfigBlockType.type, + property_name=["button", "header_button"], + theme_config_block_type_name=[ + ButtonThemeConfigBlockType.type, + ButtonThemeConfigBlockType.type, + ], serializer_kwargs={"required": False}, ), } @@ -1961,3 +1985,327 @@ class FooterElementType(MultiPageContainerElementType): type = "footer" model_class = FooterElement + + +class MenuElementType(ElementType): + """ + A Menu element that provides navigation capabilities to the application. + """ + + type = "menu" + model_class = MenuElement + serializer_field_names = ["orientation", "alignment", "menu_items"] + allowed_fields = ["orientation", "alignment"] + + serializer_mixins = [NestedMenuItemsMixin] + request_serializer_mixins = [] + + class SerializedDict(ElementDict): + orientation: str + alignment: str + menu_items: List[Dict] + + @property + def serializer_field_overrides(self) -> Dict[str, Any]: + from baserow.contrib.builder.api.theme.serializers import ( + DynamicConfigBlockSerializer, + ) + from baserow.contrib.builder.theme.theme_config_block_types import ( + ButtonThemeConfigBlockType, + LinkThemeConfigBlockType, + ) + + overrides = { + **super().serializer_field_overrides, + "styles": DynamicConfigBlockSerializer( + required=False, + property_name="menu", + theme_config_block_type_name=[ + [ButtonThemeConfigBlockType.type, LinkThemeConfigBlockType.type] + ], + serializer_kwargs={"required": False}, + ), + } + return overrides + + @property + def request_serializer_field_overrides(self) -> Dict[str, Any]: + return { + **self.serializer_field_overrides, + "menu_items": MenuItemSerializer(many=True, required=False), + } + + def enhance_queryset( + self, queryset: QuerySet[MenuItemElement] + ) -> QuerySet[MenuItemElement]: + return queryset.prefetch_related("menu_items") + + def before_delete(self, instance: MenuElement) -> None: + """ + Handle any clean-up needed before the MenuElement is deleted. + + Deletes all related objects of this MenuElement instance such as Menu + Items and Workflow actions. + """ + + self.delete_workflow_actions(instance) + instance.menu_items.all().delete() + + def after_create(self, instance: MenuItemElement, values: Dict[str, Any]) -> None: + """ + After a MenuElement is created, MenuItemElements are bulk-created + using the information in the "menu_items" array. + """ + + menu_items = values.get("menu_items", []) + + created_menu_items = MenuItemElement.objects.bulk_create( + [ + MenuItemElement(**item, menu_item_order=index) + for index, item in enumerate(menu_items) + ] + ) + instance.menu_items.add(*created_menu_items) + + def delete_workflow_actions( + self, instance: MenuElement, menu_item_uids_to_keep: Optional[List[str]] = None + ) -> None: + """ + Deletes all Workflow actions related to a specific MenuElement instance. + + :param instance: The MenuElement instance for which related Workflow + actions will be deleted. + :param menu_item_uids_to_keep: An optional list of UUIDs. If a related + Workflow action matches a UUID in this list, it will *not* be deleted. + :return: None + """ + + # Get all workflow actions associated with this menu element. + all_workflow_actions = BuilderWorkflowAction.objects.filter(element=instance) + + # If there are menu items, only keep workflow actions that match + # existing menu items. + if menu_item_uids_to_keep: + workflow_actions_to_keep_query = Q() + for uid in menu_item_uids_to_keep: + workflow_actions_to_keep_query |= Q(event__startswith=uid) + + # Find Workflow actions to delete (those not matching any + # current Menu Item). + workflow_actions_to_delete = all_workflow_actions.exclude( + workflow_actions_to_keep_query + ) + else: + # Since there are no Menu Items, delete all Workflow actions + # for this element. + workflow_actions_to_delete = all_workflow_actions + + # Delete the workflow actions that are no longer associated with + # any menu item. + if workflow_actions_to_delete.exists(): + workflow_actions_to_delete.delete() + + def after_update(self, instance: MenuElement, values, changes: Dict[str, Tuple]): + """ + After the element has been updated we need to update the fields. + + :param instance: The instance of the element that has been updated. + :param values: The values that have been updated. + :param changes: A dictionary containing all changes which were made to the + collection element prior to `after_update` being called. + :return: None + """ + + if "menu_items" in values: + instance.menu_items.all().delete() + + menu_item_uids_to_keep = [item["uid"] for item in values["menu_items"]] + self.delete_workflow_actions(instance, menu_item_uids_to_keep) + + items_to_create = [] + child_uids_parent_uids = {} + + keys_to_remove = ["parent_menu_item", "menu_item_order"] + for index, item in enumerate(values["menu_items"]): + for key in keys_to_remove: + item.pop(key, None) + + # Keep track of child-parent relationship via the uid + for child_index, child in enumerate(item.pop("children", [])): + for key in keys_to_remove + ["children"]: + child.pop(key, None) + + items_to_create.append( + MenuItemElement(**child, menu_item_order=child_index) + ) + child_uids_parent_uids[str(child["uid"])] = str(item["uid"]) + + items_to_create.append(MenuItemElement(**item, menu_item_order=index)) + + created_items = MenuItemElement.objects.bulk_create(items_to_create) + instance.menu_items.add(*created_items) + + # Re-associate the child-parent + for item in instance.menu_items.all(): + if parent_uid := child_uids_parent_uids.get(str(item.uid)): + parent_item = instance.menu_items.filter(uid=parent_uid).first() + item.parent_menu_item = parent_item + item.save() + + super().after_update(instance, values, changes) + + def get_pytest_params(self, pytest_data_fixture): + return { + "orientation": RepeatElement.ORIENTATIONS.VERTICAL, + "alignment": HorizontalAlignments.LEFT, + } + + def deserialize_property( + self, + prop_name: str, + value: Any, + id_mapping: Dict[str, Any], + files_zip=None, + storage=None, + cache=None, + **kwargs, + ) -> Any: + if prop_name == "menu_items": + updated_menu_items = [] + for item in value: + updated = {} + for item_key, item_value in item.items(): + new_value = super().deserialize_property( + item_key, + NavigationElementManager().deserialize_property( + item_key, item_value, id_mapping, **kwargs + ), + id_mapping, + files_zip=files_zip, + storage=storage, + cache=cache, + **kwargs, + ) + updated[item_key] = new_value + updated_menu_items.append(updated) + return updated_menu_items + + return super().deserialize_property( + prop_name, + value, + id_mapping, + files_zip=files_zip, + storage=storage, + cache=cache, + **kwargs, + ) + + def serialize_property( + self, + element: MenuElement, + prop_name: str, + files_zip=None, + storage=None, + cache=None, + **kwargs, + ) -> Any: + if prop_name == "menu_items": + return MenuItemSerializer( + element.menu_items.all(), + many=True, + ).data + + return super().serialize_property( + element, + prop_name, + files_zip=files_zip, + storage=storage, + cache=cache, + **kwargs, + ) + + def create_instance_from_serialized( + self, + serialized_values: Dict[str, Any], + id_mapping, + files_zip=None, + storage=None, + cache=None, + **kwargs, + ) -> MenuElement: + menu_items = serialized_values.pop("menu_items", []) + + instance = super().create_instance_from_serialized( + serialized_values, + id_mapping, + files_zip=files_zip, + storage=storage, + cache=cache, + **kwargs, + ) + + menu_items_to_create = [] + child_uids_parent_uids = {} + + ids_uids = {i["id"]: i["uid"] for i in menu_items} + keys_to_remove = ["id", "menu_item_order", "children"] + for index, item in enumerate(menu_items): + for key in keys_to_remove: + item.pop(key, None) + + # Keep track of child-parent relationship via the uid + if parent_id := item.pop("parent_menu_item", None): + child_uids_parent_uids[item["uid"]] = ids_uids[parent_id] + + menu_items_to_create.append(MenuItemElement(**item, menu_item_order=index)) + + created_menu_items = MenuItemElement.objects.bulk_create(menu_items_to_create) + instance.menu_items.add(*created_menu_items) + + # Re-associate the child-parent + for item in instance.menu_items.all(): + if parent_uid := child_uids_parent_uids.get(str(item.uid)): + parent_item = instance.menu_items.filter(uid=parent_uid).first() + item.parent_menu_item = parent_item + item.save() + + return instance + + def formula_generator( + self, element: Element + ) -> Generator[str | Instance, str, None]: + """ + Generator that returns formula fields for the MenuElementType. + + The MenuElement has a menu_items field, which is a many-to-many + relationship with MenuItemElement. The MenuItemElement has navigation + related fields like page_parameters, yet does not have a type of its + own. + + This method ensures that any formulas found inside MenuItemElements + are extracted correctly. It ensures that when a formula is declared + in page_parameters, etc, the resolved formula value is available + in the frontend. + """ + + yield from super().formula_generator(element) + + for item in element.menu_items.all(): + for index, data in enumerate(item.page_parameters or []): + new_formula = yield data["value"] + if new_formula is not None: + item.page_parameters[index]["value"] = new_formula + yield item + + for index, data in enumerate(item.query_parameters or []): + new_formula = yield data["value"] + if new_formula is not None: + item.query_parameters[index]["value"] = new_formula + yield item + + for formula_field in NavigationElementManager.simple_formula_fields: + formula = getattr(item, formula_field, "") + new_formula = yield formula + if new_formula is not None: + setattr(item, formula_field, new_formula) + yield item diff --git a/backend/src/baserow/contrib/builder/elements/handler.py b/backend/src/baserow/contrib/builder/elements/handler.py index 648337003..c6a9a707c 100644 --- a/backend/src/baserow/contrib/builder/elements/handler.py +++ b/backend/src/baserow/contrib/builder/elements/handler.py @@ -237,7 +237,14 @@ class ElementHandler: """ if specific: - elements = specific_iterator(base_queryset) + elements = specific_iterator( + base_queryset, + per_content_type_queryset_hook=( + lambda element, queryset: element_type_registry.get_by_model( + element + ).enhance_queryset(queryset) + ), + ) else: elements = base_queryset diff --git a/backend/src/baserow/contrib/builder/elements/mixins.py b/backend/src/baserow/contrib/builder/elements/mixins.py index 321b1c887..b323c0952 100644 --- a/backend/src/baserow/contrib/builder/elements/mixins.py +++ b/backend/src/baserow/contrib/builder/elements/mixins.py @@ -834,7 +834,7 @@ class MultiPageElementTypeMixin: if "pages" in values: pages = PageHandler().get_pages( instance.page.builder, - base_queryset=Page.objects.filter( + base_queryset=Page.objects_without_shared.filter( id__in=[p.id for p in values["pages"]] ), ) @@ -852,7 +852,7 @@ class MultiPageElementTypeMixin: if "pages" in values: pages = PageHandler().get_pages( instance.page.builder, - base_queryset=Page.objects.filter( + base_queryset=Page.objects_without_shared.filter( id__in=[p.id for p in values["pages"]] ), ) diff --git a/backend/src/baserow/contrib/builder/elements/models.py b/backend/src/baserow/contrib/builder/elements/models.py index 4623a7c8d..62d2800cd 100644 --- a/backend/src/baserow/contrib/builder/elements/models.py +++ b/backend/src/baserow/contrib/builder/elements/models.py @@ -9,6 +9,7 @@ from django.db.models import SET_NULL, QuerySet from baserow.contrib.builder.constants import ( BACKGROUND_IMAGE_MODES, COLOR_FIELD_MAX_LENGTH, + HorizontalAlignments, VerticalAlignments, ) from baserow.core.constants import DATE_FORMAT_CHOICES, DATE_TIME_FORMAT_CHOICES @@ -990,3 +991,84 @@ class FooterElement(MultiPageElement, ContainerElement): """ A multi-page container element positioned at the bottom of the page. """ + + +class MenuItemElement(NavigationElementMixin): + """ + An item in a MenuElement. + """ + + class VARIANTS(models.TextChoices): + LINK = "link" + BUTTON = "button" + + variant = models.CharField( + choices=VARIANTS.choices, + help_text="The variant of the link.", + max_length=10, + default=VARIANTS.LINK, + ) + + class TYPES(models.TextChoices): + BUTTON = "button" + LINK = "link" + SEPARATOR = "separator" + SPACER = "spacer" + + type = models.CharField( + choices=TYPES.choices, + help_text="The type of the Menu Item.", + max_length=9, + default=TYPES.LINK, + ) + + name = models.CharField( + max_length=225, + help_text="The name of the Menu Item.", + ) + + menu_item_order = models.PositiveIntegerField() + uid = models.UUIDField(default=uuid.uuid4) + + parent_menu_item = models.ForeignKey( + "self", + on_delete=models.CASCADE, + null=True, + default=None, + help_text="The parent MenuItemElement element, if it is a nested item.", + related_name="menu_item_children", + ) + + class Meta: + ordering = ("menu_item_order",) + + +class MenuElement(Element): + """ + A menu element that helps with navigating the application. + """ + + class ORIENTATIONS(models.TextChoices): + HORIZONTAL = "horizontal" + VERTICAL = "vertical" + + orientation = models.CharField( + choices=ORIENTATIONS.choices, + max_length=10, + default=ORIENTATIONS.HORIZONTAL, + db_default=ORIENTATIONS.HORIZONTAL, + ) + + alignment = models.CharField( + choices=HorizontalAlignments.choices, + max_length=10, + default=HorizontalAlignments.LEFT, + ) + + menu_items = models.ManyToManyField(MenuItemElement) + + +class SimpleContainerElement(ContainerElement): + """ + A simple container to group elements + """ diff --git a/backend/src/baserow/contrib/builder/formula_property_extractor.py b/backend/src/baserow/contrib/builder/formula_property_extractor.py index 5c9631239..6596999f1 100644 --- a/backend/src/baserow/contrib/builder/formula_property_extractor.py +++ b/backend/src/baserow/contrib/builder/formula_property_extractor.py @@ -1,7 +1,5 @@ from typing import TYPE_CHECKING, Dict, List, Set -from django.contrib.auth.models import AbstractUser - from antlr4.tree import Tree from baserow.contrib.builder.data_providers.registries import ( @@ -11,6 +9,7 @@ from baserow.contrib.builder.elements.models import Element from baserow.contrib.builder.formula_importer import BaserowFormulaImporter from baserow.core.formula import BaserowFormula from baserow.core.formula.exceptions import InvalidBaserowFormula +from baserow.core.user_sources.user_source_user import UserSourceUser from baserow.core.utils import merge_dicts_no_duplicates, to_path if TYPE_CHECKING: @@ -176,10 +175,10 @@ def get_data_source_property_names( def get_builder_used_property_names( - user: AbstractUser, builder: "Builder" + user: UserSourceUser, builder: "Builder" ) -> Dict[str, Dict[int, List[str]]]: """ - Given a User and a Builder, return all property names used in the all the + Given a UserSourceUser and a Builder, return all property names used in the all the pages. This involves looping over all Elements, Workflow Actions, and Data Sources diff --git a/backend/src/baserow/contrib/builder/handler.py b/backend/src/baserow/contrib/builder/handler.py index c37fb9282..6099fd86a 100644 --- a/backend/src/baserow/contrib/builder/handler.py +++ b/backend/src/baserow/contrib/builder/handler.py @@ -1,22 +1,31 @@ from typing import Dict, List, Optional from django.conf import settings -from django.contrib.auth import get_user_model -from django.contrib.auth.models import AbstractUser +from django.db.models.query import QuerySet from baserow.contrib.builder.formula_property_extractor import ( get_builder_used_property_names, ) from baserow.contrib.builder.models import Builder from baserow.contrib.builder.theme.registries import theme_config_block_registry +from baserow.core.cache import global_cache from baserow.core.handler import CoreHandler -from baserow.core.utils import invalidate_versioned_cache, safe_get_or_set_cache +from baserow.core.models import Workspace +from baserow.core.user_sources.handler import UserSourceHandler +from baserow.core.user_sources.models import UserSource +from baserow.core.user_sources.user_source_user import UserSourceUser -User = get_user_model() -CACHE_KEY_PREFIX = "used_properties_for_page" +USED_PROPERTIES_CACHE_KEY_PREFIX = "used_properties_for_page" + +# The duration of the cached public element, data source and workflow action API views. +BUILDER_PUBLIC_RECORDS_CACHE_TTL_SECONDS = 60 * 60 + +# The duration of the cached public `get_public_builder_by_domain_name` view. +BUILDER_PUBLIC_BUILDER_BY_DOMAIN_TTL_SECONDS = 60 * 60 + +# The duration of the cached public properties for the builder API views. BUILDER_PREVIEW_USED_PROPERTIES_CACHE_TTL_SECONDS = 60 - SENTINEL = "__no_results__" @@ -46,20 +55,15 @@ class BuilderHandler: ) @classmethod - def _get_builder_version_cache(cls, builder: Builder): - return f"{CACHE_KEY_PREFIX}_version_{builder.id}" + def _get_builder_public_properties_version_cache(cls, builder: Builder) -> str: + return f"{USED_PROPERTIES_CACHE_KEY_PREFIX}_version_{builder.id}" def get_builder_used_properties_cache_key( - self, user: AbstractUser, builder: Builder - ) -> Optional[str]: + self, user: UserSourceUser, builder: Builder + ) -> str: """ Returns a cache key that can be used to key the results of making the expensive function call to get_builder_used_property_names(). - - If the user is a Django user, return None. This is because the Page - Designer should always have the latest data in the Preview (e.g. when - they are not authenticated). Also, the Django user doesn't have the role - attribute, unlike the User Source User. """ if user.is_anonymous or not user.role: @@ -68,14 +72,16 @@ class BuilderHandler: else: role = f"_{user.role}" - return f"{CACHE_KEY_PREFIX}_{builder.id}{role}" + return f"{USED_PROPERTIES_CACHE_KEY_PREFIX}_{builder.id}{role}" @classmethod - def invalidate_builder_public_properties_cache(cls, builder): - invalidate_versioned_cache(cls._get_builder_version_cache(builder)) + def invalidate_builder_public_properties_cache(cls, builder: Builder): + global_cache.invalidate( + invalidate_key=cls._get_builder_public_properties_version_cache(builder) + ) def get_builder_public_properties( - self, user: AbstractUser, builder: Builder + self, user: UserSourceUser, builder: Builder ) -> Dict[str, Dict[int, List[str]]]: """ Return a Dict where keys are ["all", "external", "internal"] and values @@ -94,13 +100,53 @@ class BuilderHandler: properties = get_builder_used_property_names(user, builder) return SENTINEL if properties is None else properties - result = safe_get_or_set_cache( + result = global_cache.get( self.get_builder_used_properties_cache_key(user, builder), - self._get_builder_version_cache(builder), default=compute_properties, + # We want to invalidate the cache for all roles at once so we create a + # unique key for all. + invalidate_key=self._get_builder_public_properties_version_cache(builder), timeout=settings.BUILDER_PUBLICLY_USED_PROPERTIES_CACHE_TTL_SECONDS if builder.workspace_id else BUILDER_PREVIEW_USED_PROPERTIES_CACHE_TTL_SECONDS, ) return result if result != SENTINEL else None + + def get_published_applications( + self, workspace: Optional[Workspace] = None + ) -> QuerySet[Builder]: + """ + Returns all published applications in a workspace or all published applications + in the instance if no workspace is provided. + + A published application is a builder application which points to one more + published domains. The application is the one that the page designer is + creating their application in. + + :param workspace: Only return published applications in this workspace. + :return: A queryset of published applications. + """ + + applications = Builder.objects.exclude(domains__published_to=None) + return applications.filter(workspace=workspace) if workspace else applications + + def aggregate_user_source_counts( + self, + workspace: Optional[Workspace] = None, + ) -> int: + """ + The builder implementation of the `UserSourceHandler.aggregate_user_counts` + method, we need it to only count user sources in published applications. + + :param workspace: If provided, only count user sources in published + applications within this workspace. + :return: The total number of user sources in published applications. + """ + + queryset = UserSourceHandler().get_user_sources( + base_queryset=UserSource.objects.filter( + application__in=self.get_published_applications(workspace) + ) + ) + return UserSourceHandler().aggregate_user_counts(workspace, queryset) diff --git a/backend/src/baserow/contrib/builder/locale/en/LC_MESSAGES/django.po b/backend/src/baserow/contrib/builder/locale/en/LC_MESSAGES/django.po index 306c9b390..3b1d5f76a 100644 --- a/backend/src/baserow/contrib/builder/locale/en/LC_MESSAGES/django.po +++ b/backend/src/baserow/contrib/builder/locale/en/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-01-15 11:59+0000\n" +"POT-Creation-Date: 2025-03-05 11:01+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Language-Team: LANGUAGE <LL@li.org>\n" @@ -46,18 +46,18 @@ msgstr "" msgid "Last name" msgstr "" -#: src/baserow/contrib/builder/data_providers/data_provider_types.py:452 +#: src/baserow/contrib/builder/data_providers/data_provider_types.py:563 #, python-format msgid "%(user_source_name)s member" msgstr "" -#: src/baserow/contrib/builder/data_sources/service.py:154 +#: src/baserow/contrib/builder/data_sources/service.py:158 msgid "Data source" msgstr "" -#: src/baserow/contrib/builder/elements/mixins.py:578 -#: src/baserow/contrib/builder/elements/mixins.py:583 -#: src/baserow/contrib/builder/elements/mixins.py:588 +#: src/baserow/contrib/builder/elements/mixins.py:586 +#: src/baserow/contrib/builder/elements/mixins.py:591 +#: src/baserow/contrib/builder/elements/mixins.py:596 #, python-format msgid "Column %(count)s" msgstr "" diff --git a/backend/src/baserow/contrib/builder/migrations/0052_menuitemelement_menuelement.py b/backend/src/baserow/contrib/builder/migrations/0052_menuitemelement_menuelement.py new file mode 100644 index 000000000..c65deb363 --- /dev/null +++ b/backend/src/baserow/contrib/builder/migrations/0052_menuitemelement_menuelement.py @@ -0,0 +1,165 @@ +# Generated by Django 5.0.9 on 2025-02-25 09:11 + +import uuid + +import django.db.models.deletion +from django.db import migrations, models + +import baserow.core.formula.field + + +class Migration(migrations.Migration): + dependencies = [ + ("builder", "0051_alter_builderworkflowaction_options"), + ] + + operations = [ + migrations.CreateModel( + name="MenuItemElement", + fields=[ + ( + "id", + models.AutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ( + "navigation_type", + models.CharField( + choices=[("page", "Page"), ("custom", "Custom")], + default="page", + help_text="The navigation type.", + max_length=10, + null=True, + ), + ), + ( + "navigate_to_url", + baserow.core.formula.field.FormulaField( + default="", + help_text="If no page is selected, this indicate the destination of the link.", + null=True, + ), + ), + ( + "page_parameters", + models.JSONField( + default=list, + help_text="The parameters for each parameters of the selected page if any.", + null=True, + ), + ), + ( + "query_parameters", + models.JSONField( + db_default=[], + default=list, + help_text="The query parameters for each parameter of the selected page if any.", + null=True, + ), + ), + ( + "target", + models.CharField( + choices=[("self", "Self"), ("blank", "Blank")], + default="self", + help_text="The target of the link when we click on it.", + max_length=10, + null=True, + ), + ), + ( + "variant", + models.CharField( + choices=[("link", "Link"), ("button", "Button")], + default="link", + help_text="The variant of the link.", + max_length=10, + ), + ), + ( + "type", + models.CharField( + choices=[ + ("button", "Button"), + ("link", "Link"), + ("separator", "Separator"), + ("spacer", "Spacer"), + ], + default="link", + help_text="The type of the Menu Item.", + max_length=9, + ), + ), + ( + "name", + models.CharField( + help_text="The name of the Menu Item.", max_length=225 + ), + ), + ("menu_item_order", models.PositiveIntegerField()), + ("uid", models.UUIDField(default=uuid.uuid4)), + ( + "navigate_to_page", + models.ForeignKey( + help_text=( + "Destination page id for this link. If null then we use the navigate_to_url property instead.", + ), + null=True, + on_delete=django.db.models.deletion.SET_NULL, + to="builder.page", + ), + ), + ( + "parent_menu_item", + models.ForeignKey( + default=None, + help_text="The parent MenuItemElement element, if it is a nested item.", + null=True, + on_delete=django.db.models.deletion.CASCADE, + related_name="menu_item_children", + to="builder.menuitemelement", + ), + ), + ], + options={ + "ordering": ("menu_item_order",), + }, + ), + migrations.CreateModel( + name="MenuElement", + fields=[ + ( + "element_ptr", + models.OneToOneField( + auto_created=True, + on_delete=django.db.models.deletion.CASCADE, + parent_link=True, + primary_key=True, + serialize=False, + to="builder.element", + ), + ), + ( + "orientation", + models.CharField( + choices=[ + ("horizontal", "Horizontal"), + ("vertical", "Vertical"), + ], + db_default="horizontal", + default="horizontal", + max_length=10, + ), + ), + ("menu_items", models.ManyToManyField(to="builder.menuitemelement")), + ], + options={ + "abstract": False, + }, + bases=("builder.element",), + ), + ] diff --git a/backend/src/baserow/contrib/builder/migrations/0053_buttonthemeconfigblock_button_active_background_color_and_more.py b/backend/src/baserow/contrib/builder/migrations/0053_buttonthemeconfigblock_button_active_background_color_and_more.py new file mode 100644 index 000000000..0daba052f --- /dev/null +++ b/backend/src/baserow/contrib/builder/migrations/0053_buttonthemeconfigblock_button_active_background_color_and_more.py @@ -0,0 +1,312 @@ +# Generated by Django 5.0.9 on 2025-03-05 10:12 + +import django.db.models.deletion +from django.db import migrations, models + +import baserow.core.fields + + +class Migration(migrations.Migration): + dependencies = [ + ("builder", "0052_menuitemelement_menuelement"), + ] + + operations = [ + migrations.AddField( + model_name="buttonthemeconfigblock", + name="button_active_background_color", + field=models.CharField( + blank=True, + default="#4783db", + help_text="The background color of buttons when active", + max_length=255, + ), + ), + migrations.AddField( + model_name="buttonthemeconfigblock", + name="button_active_border_color", + field=models.CharField( + blank=True, + default="#275d9f", + help_text="The border color of buttons when active", + max_length=255, + ), + ), + migrations.AddField( + model_name="buttonthemeconfigblock", + name="button_active_text_color", + field=models.CharField( + blank=True, + default="#ffffffff", + help_text="The text color of buttons when active", + max_length=255, + ), + ), + migrations.AddField( + model_name="linkthemeconfigblock", + name="link_active_text_color", + field=models.CharField( + blank=True, + default="#275d9f", + help_text="The hover color of links when active", + max_length=255, + ), + ), + migrations.AddField( + model_name="menuelement", + name="alignment", + field=models.CharField( + choices=[("left", "Left"), ("center", "Center"), ("right", "Right")], + default="left", + max_length=10, + ), + ), + migrations.CreateModel( + name="MenuThemeConfigBlock", + fields=[ + ( + "id", + models.AutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ( + "button_font_family", + models.CharField(default="inter", max_length=250), + ), + ("button_font_size", models.SmallIntegerField(default=13)), + ( + "button_font_weight", + models.CharField( + choices=[ + ("thin", "Thin"), + ("extra-light", "Extra Light"), + ("light", "Light"), + ("regular", "Regular"), + ("medium", "Medium"), + ("semi-bold", "Semi Bold"), + ("bold", "Bold"), + ("extra-bold", "Extra Bold"), + ("heavy", "Heavy"), + ("black", "Black"), + ("extra-black", "Extra Black"), + ], + db_default="regular", + default="regular", + max_length=11, + ), + ), + ( + "button_alignment", + models.CharField( + choices=[ + ("left", "Left"), + ("center", "Center"), + ("right", "Right"), + ], + default="left", + max_length=10, + ), + ), + ( + "button_text_alignment", + models.CharField( + choices=[ + ("left", "Left"), + ("center", "Center"), + ("right", "Right"), + ], + default="center", + max_length=10, + ), + ), + ( + "button_width", + models.CharField( + choices=[("auto", "Auto"), ("full", "Full")], + default="auto", + max_length=10, + ), + ), + ( + "button_background_color", + models.CharField( + blank=True, + default="primary", + help_text="The background color of buttons", + max_length=255, + ), + ), + ( + "button_text_color", + models.CharField( + blank=True, + default="#ffffffff", + help_text="The text color of buttons", + max_length=255, + ), + ), + ( + "button_border_color", + models.CharField( + blank=True, + default="border", + help_text="The border color of buttons", + max_length=255, + ), + ), + ( + "button_border_size", + models.SmallIntegerField(default=0, help_text="Button border size"), + ), + ( + "button_border_radius", + models.SmallIntegerField( + default=4, help_text="Button border radius" + ), + ), + ( + "button_vertical_padding", + models.SmallIntegerField( + default=12, help_text="Button vertical padding" + ), + ), + ( + "button_horizontal_padding", + models.SmallIntegerField( + default=12, help_text="Button horizontal padding" + ), + ), + ( + "button_hover_background_color", + models.CharField( + blank=True, + default="#96baf6ff", + help_text="The background color of buttons when hovered", + max_length=255, + ), + ), + ( + "button_hover_text_color", + models.CharField( + blank=True, + default="#ffffffff", + help_text="The text color of buttons when hovered", + max_length=255, + ), + ), + ( + "button_hover_border_color", + models.CharField( + blank=True, + default="border", + help_text="The border color of buttons when hovered", + max_length=255, + ), + ), + ( + "button_active_background_color", + models.CharField( + blank=True, + default="#4783db", + help_text="The background color of buttons when active", + max_length=255, + ), + ), + ( + "button_active_text_color", + models.CharField( + blank=True, + default="#ffffffff", + help_text="The text color of buttons when active", + max_length=255, + ), + ), + ( + "button_active_border_color", + models.CharField( + blank=True, + default="#275d9f", + help_text="The border color of buttons when active", + max_length=255, + ), + ), + ("link_font_family", models.CharField(default="inter", max_length=250)), + ("link_font_size", models.SmallIntegerField(default=13)), + ( + "link_font_weight", + models.CharField( + choices=[ + ("thin", "Thin"), + ("extra-light", "Extra Light"), + ("light", "Light"), + ("regular", "Regular"), + ("medium", "Medium"), + ("semi-bold", "Semi Bold"), + ("bold", "Bold"), + ("extra-bold", "Extra Bold"), + ("heavy", "Heavy"), + ("black", "Black"), + ("extra-black", "Extra Black"), + ], + db_default="regular", + default="regular", + max_length=11, + ), + ), + ( + "link_text_alignment", + models.CharField( + choices=[ + ("left", "Left"), + ("center", "Center"), + ("right", "Right"), + ], + default="left", + max_length=10, + ), + ), + ( + "link_text_color", + models.CharField( + blank=True, + default="primary", + help_text="The text color of links", + max_length=255, + ), + ), + ( + "link_hover_text_color", + models.CharField( + blank=True, + default="#96baf6ff", + help_text="The hover color of links when hovered", + max_length=255, + ), + ), + ( + "link_active_text_color", + models.CharField( + blank=True, + default="#275d9f", + help_text="The hover color of links when active", + max_length=255, + ), + ), + ( + "builder", + baserow.core.fields.AutoOneToOneField( + on_delete=django.db.models.deletion.CASCADE, + related_name="%(class)s", + to="builder.builder", + ), + ), + ], + options={ + "abstract": False, + }, + ), + ] diff --git a/backend/src/baserow/contrib/builder/migrations/0054_simplecontainerelement.py b/backend/src/baserow/contrib/builder/migrations/0054_simplecontainerelement.py new file mode 100644 index 000000000..8b2b91b4f --- /dev/null +++ b/backend/src/baserow/contrib/builder/migrations/0054_simplecontainerelement.py @@ -0,0 +1,36 @@ +# Generated by Django 5.0.9 on 2025-03-08 13:26 + +import django.db.models.deletion +from django.db import migrations, models + + +class Migration(migrations.Migration): + dependencies = [ + ( + "builder", + "0053_buttonthemeconfigblock_button_active_background_color_and_more", + ), + ] + + operations = [ + migrations.CreateModel( + name="SimpleContainerElement", + fields=[ + ( + "element_ptr", + models.OneToOneField( + auto_created=True, + on_delete=django.db.models.deletion.CASCADE, + parent_link=True, + primary_key=True, + serialize=False, + to="builder.element", + ), + ), + ], + options={ + "abstract": False, + }, + bases=("builder.element",), + ), + ] diff --git a/backend/src/baserow/contrib/builder/migrations/0055_linkthemeconfigblock_link_active_text_decoration_and_more.py b/backend/src/baserow/contrib/builder/migrations/0055_linkthemeconfigblock_link_active_text_decoration_and_more.py new file mode 100644 index 000000000..e0e31ff36 --- /dev/null +++ b/backend/src/baserow/contrib/builder/migrations/0055_linkthemeconfigblock_link_active_text_decoration_and_more.py @@ -0,0 +1,116 @@ +# Generated by Django 5.0.9 on 2025-03-18 13:03 + +from django.db import migrations + +import baserow.core.fields + + +class Migration(migrations.Migration): + dependencies = [ + ("builder", "0054_simplecontainerelement"), + ] + + operations = [ + migrations.AddField( + model_name="linkthemeconfigblock", + name="link_active_text_decoration", + field=baserow.core.fields.MultipleFlagField( + db_default="1000", + default="1000", + help_text="The text decoration flags [underline, strike, uppercase, italic]", + max_length=4, + num_flags=4, + ), + ), + migrations.AddField( + model_name="linkthemeconfigblock", + name="link_default_text_decoration", + field=baserow.core.fields.MultipleFlagField( + db_default="1000", + default="1000", + help_text="The text decoration flags [underline, strike, uppercase, italic]", + max_length=4, + num_flags=4, + ), + ), + migrations.AddField( + model_name="linkthemeconfigblock", + name="link_hover_text_decoration", + field=baserow.core.fields.MultipleFlagField( + db_default="1000", + default="1000", + help_text="The text decoration flags [underline, strike, uppercase, italic]", + max_length=4, + num_flags=4, + ), + ), + migrations.AddField( + model_name="typographythemeconfigblock", + name="heading_1_text_decoration", + field=baserow.core.fields.MultipleFlagField( + db_default="0000", + default="0000", + help_text="The text decoration flags [underline, strike, uppercase, italic]", + max_length=4, + num_flags=4, + ), + ), + migrations.AddField( + model_name="typographythemeconfigblock", + name="heading_2_text_decoration", + field=baserow.core.fields.MultipleFlagField( + db_default="0000", + default="0000", + help_text="The text decoration flags [underline, strike, uppercase, italic]", + max_length=4, + num_flags=4, + ), + ), + migrations.AddField( + model_name="typographythemeconfigblock", + name="heading_3_text_decoration", + field=baserow.core.fields.MultipleFlagField( + db_default="0000", + default="0000", + help_text="The text decoration flags [underline, strike, uppercase, italic]", + max_length=4, + num_flags=4, + ), + ), + migrations.AddField( + model_name="typographythemeconfigblock", + name="heading_4_text_decoration", + field=baserow.core.fields.MultipleFlagField( + db_default="0000", + default="0000", + help_text="The text decoration flags [underline, strike, uppercase, italic]", + max_length=4, + num_flags=4, + ), + ), + migrations.AddField( + model_name="typographythemeconfigblock", + name="heading_5_text_decoration", + field=baserow.core.fields.MultipleFlagField( + db_default="0000", + default="0000", + help_text="The text decoration flags [underline, strike, uppercase, italic]", + max_length=4, + num_flags=4, + ), + ), + migrations.AddField( + model_name="typographythemeconfigblock", + name="heading_6_text_decoration", + field=baserow.core.fields.MultipleFlagField( + db_default="0000", + default="0000", + help_text="The text decoration flags [underline, strike, uppercase, italic]", + max_length=4, + num_flags=4, + ), + ), + migrations.DeleteModel( + name="MenuThemeConfigBlock", + ), + ] diff --git a/backend/src/baserow/contrib/builder/models.py b/backend/src/baserow/contrib/builder/models.py index 5e2b7148e..3fb1e65ce 100644 --- a/backend/src/baserow/contrib/builder/models.py +++ b/backend/src/baserow/contrib/builder/models.py @@ -55,6 +55,10 @@ class Builder(Application): # but it's a more generic type return self.application_ptr + @property + def visible_pages(self): + return self.page_set(manager="objects_without_shared") + @cached_property def shared_page(self): from baserow.contrib.builder.pages.handler import PageHandler diff --git a/backend/src/baserow/contrib/builder/pages/handler.py b/backend/src/baserow/contrib/builder/pages/handler.py index 885172fbe..78e028d46 100644 --- a/backend/src/baserow/contrib/builder/pages/handler.py +++ b/backend/src/baserow/contrib/builder/pages/handler.py @@ -40,10 +40,14 @@ from baserow.contrib.builder.types import PageDict from baserow.contrib.builder.workflow_actions.handler import ( BuilderWorkflowActionHandler, ) +from baserow.core.cache import global_cache from baserow.core.exceptions import IdDoesNotExist from baserow.core.storage import ExportZipFile +from baserow.core.user_sources.user_source_user import UserSourceUser from baserow.core.utils import ChildProgressBuilder, MirrorDict, find_unused_name +BUILDER_PAGE_IS_PUBLISHED_CACHE_TTL_SECONDS = 60 * 60 + class PageHandler: def get_page(self, page_id: int, base_queryset: Optional[QuerySet] = None) -> Page: @@ -58,7 +62,7 @@ class PageHandler: """ if base_queryset is None: - base_queryset = Page.objects_with_shared + base_queryset = Page.objects try: return base_queryset.select_related("builder__workspace").get(id=page_id) @@ -70,7 +74,7 @@ class PageHandler: Returns the shared page for the given builder. """ - return Page.objects_with_shared.select_related("builder__workspace").get( + return Page.objects.select_related("builder__workspace").get( builder=builder, shared=True ) @@ -80,7 +84,7 @@ class PageHandler: """ if base_queryset is None: - base_queryset = Page.objects_with_shared.all() + base_queryset = Page.objects.all() return base_queryset.filter(builder=builder).select_related( "builder__workspace" @@ -178,7 +182,7 @@ class PageHandler: self.is_page_path_unique( page.builder, path, - base_queryset=Page.objects_with_shared.exclude( + base_queryset=Page.objects.exclude( id=page.id ), # We don't want to conflict with the current page raises=True, @@ -220,7 +224,7 @@ class PageHandler: """ if base_qs is None: - base_qs = Page.objects.filter(builder=builder) + base_qs = Page.objects_without_shared.filter(builder=builder) try: full_order = Page.order_objects(base_qs, order) @@ -229,6 +233,55 @@ class PageHandler: return full_order + @classmethod + def get_page_public_records_cache_key( + cls, page_id: int, user: UserSourceUser, record_name: str + ): + """ + Generates the cache key used by the public elements, data sources and workflow + actions endpoints. If the `user` is authenticated, and they have a role, we will + include the role in the cache key. + + :param page_id: the ID of the public page being requested. + :param user: the `UserSourceUser` performing the HTTP request. + :param record_name: one of "elements", "data_sources" or "workflow_actions". + Used to differentiate between public view endpoints. + :return: the cache key. + """ + + role = f"_{user.role}" if not user.is_anonymous and user.role else "" + return f"ab_public_page_{page_id}{role}_{record_name}_records" + + def is_published_page(self, public_page_id: int) -> bool: + """ + Returns whether this public page ID points to a published domain + application or not. + + :param public_page_id: The ID of the public page. + :return: whether this public page ID is published or not. + """ + + return global_cache.get( + f"ab_public_page_{public_page_id}_published", + default=lambda: self._is_published_application_page(public_page_id), + timeout=BUILDER_PAGE_IS_PUBLISHED_CACHE_TTL_SECONDS, + ) + + def _is_published_application_page(self, public_page_id: int) -> bool: + """ + Given a *public* page ID, is responsible for returning the published domain + application it's associated with. + + :param public_page_id: The ID of the public page. + :return: The published domain application associated with the public page. + """ + + return ( + Builder.objects.filter(page__id=public_page_id) + .exclude(published_from=None) + .exists() + ) + def duplicate_page( self, page: Page, progress_builder: Optional[ChildProgressBuilder] = None ): @@ -418,7 +471,7 @@ class PageHandler: :return: If the path is unique """ - queryset = Page.objects_with_shared if base_queryset is None else base_queryset + queryset = Page.objects if base_queryset is None else base_queryset existing_paths = queryset.filter(builder=builder).values_list("path", flat=True) diff --git a/backend/src/baserow/contrib/builder/pages/models.py b/backend/src/baserow/contrib/builder/pages/models.py index 1339b77f5..bc6769b54 100644 --- a/backend/src/baserow/contrib/builder/pages/models.py +++ b/backend/src/baserow/contrib/builder/pages/models.py @@ -46,8 +46,8 @@ class Page( ALLOW_ALL_EXCEPT = "allow_all_except" DISALLOW_ALL_EXCEPT = "disallow_all_except" - objects = PageWithoutSharedManager() - objects_with_shared = models.Manager() + objects = models.Manager() + objects_without_shared = PageWithoutSharedManager() builder = models.ForeignKey("builder.Builder", on_delete=models.CASCADE) order = models.PositiveIntegerField() @@ -98,7 +98,7 @@ class Page( @classmethod def get_last_order(cls, builder: "Builder"): - queryset = Page.objects.filter(builder=builder) + queryset = Page.objects_without_shared.filter(builder=builder) return cls.get_highest_order_of_queryset(queryset) + 1 diff --git a/backend/src/baserow/contrib/builder/pages/service.py b/backend/src/baserow/contrib/builder/pages/service.py index 719dc4020..6ea2d76ee 100644 --- a/backend/src/baserow/contrib/builder/pages/service.py +++ b/backend/src/baserow/contrib/builder/pages/service.py @@ -159,7 +159,9 @@ class PageService: context=builder, ) - all_pages = self.handler.get_pages(builder, base_queryset=Page.objects) + all_pages = self.handler.get_pages( + builder, base_queryset=Page.objects_without_shared + ) user_pages = CoreHandler().filter_queryset( user, diff --git a/backend/src/baserow/contrib/builder/theme/models.py b/backend/src/baserow/contrib/builder/theme/models.py index 9a16557d2..441e56224 100644 --- a/backend/src/baserow/contrib/builder/theme/models.py +++ b/backend/src/baserow/contrib/builder/theme/models.py @@ -8,7 +8,7 @@ from baserow.contrib.builder.constants import ( FontWeights, HorizontalAlignments, ) -from baserow.core.fields import AutoOneToOneField +from baserow.core.fields import AutoOneToOneField, MultipleFlagField from baserow.core.user_files.models import UserFile @@ -84,6 +84,12 @@ class TypographyThemeConfigBlock(ThemeConfigBlock): max_length=10, default=HorizontalAlignments.LEFT, ) + heading_1_text_decoration = MultipleFlagField( + default=[False, False, False, False], + num_flags=4, + db_default="0000", + help_text=("The text decoration flags [underline, strike, uppercase, italic]"), + ) heading_2_font_family = models.CharField( max_length=250, default="inter", @@ -103,6 +109,12 @@ class TypographyThemeConfigBlock(ThemeConfigBlock): max_length=10, default=HorizontalAlignments.LEFT, ) + heading_2_text_decoration = MultipleFlagField( + default=[False, False, False, False], + num_flags=4, + db_default="0000", + help_text=("The text decoration flags [underline, strike, uppercase, italic]"), + ) heading_3_font_family = models.CharField( max_length=250, default="inter", @@ -122,6 +134,12 @@ class TypographyThemeConfigBlock(ThemeConfigBlock): max_length=10, default=HorizontalAlignments.LEFT, ) + heading_3_text_decoration = MultipleFlagField( + default=[False, False, False, False], + num_flags=4, + db_default="0000", + help_text=("The text decoration flags [underline, strike, uppercase, italic]"), + ) heading_4_font_family = models.CharField( max_length=250, default="inter", @@ -141,6 +159,12 @@ class TypographyThemeConfigBlock(ThemeConfigBlock): max_length=10, default=HorizontalAlignments.LEFT, ) + heading_4_text_decoration = MultipleFlagField( + default=[False, False, False, False], + num_flags=4, + db_default="0000", + help_text=("The text decoration flags [underline, strike, uppercase, italic]"), + ) heading_5_font_family = models.CharField( max_length=250, default="inter", @@ -160,6 +184,12 @@ class TypographyThemeConfigBlock(ThemeConfigBlock): max_length=10, default=HorizontalAlignments.LEFT, ) + heading_5_text_decoration = MultipleFlagField( + default=[False, False, False, False], + num_flags=4, + db_default="0000", + help_text=("The text decoration flags [underline, strike, uppercase, italic]"), + ) heading_6_font_family = models.CharField( max_length=250, default="inter", @@ -179,9 +209,15 @@ class TypographyThemeConfigBlock(ThemeConfigBlock): max_length=10, default=HorizontalAlignments.LEFT, ) + heading_6_text_decoration = MultipleFlagField( + default=[False, False, False, False], + num_flags=4, + db_default="0000", + help_text=("The text decoration flags [underline, strike, uppercase, italic]"), + ) -class ButtonThemeConfigBlock(ThemeConfigBlock): +class ButtonThemeConfigBlockMixin(models.Model): button_font_family = models.CharField( max_length=250, default="inter", @@ -256,9 +292,34 @@ class ButtonThemeConfigBlock(ThemeConfigBlock): blank=True, help_text="The border color of buttons when hovered", ) + button_active_background_color = models.CharField( + max_length=COLOR_FIELD_MAX_LENGTH, + default="#4783db", + blank=True, + help_text="The background color of buttons when active", + ) + button_active_text_color = models.CharField( + max_length=COLOR_FIELD_MAX_LENGTH, + default="#ffffffff", + blank=True, + help_text="The text color of buttons when active", + ) + button_active_border_color = models.CharField( + max_length=COLOR_FIELD_MAX_LENGTH, + default="#275d9f", + blank=True, + help_text="The border color of buttons when active", + ) + + class Meta: + abstract = True -class LinkThemeConfigBlock(ThemeConfigBlock): +class ButtonThemeConfigBlock(ButtonThemeConfigBlockMixin, ThemeConfigBlock): + pass + + +class LinkThemeConfigBlockMixin(models.Model): link_font_family = models.CharField( max_length=250, default="inter", @@ -287,6 +348,37 @@ class LinkThemeConfigBlock(ThemeConfigBlock): blank=True, help_text="The hover color of links when hovered", ) + link_active_text_color = models.CharField( + max_length=COLOR_FIELD_MAX_LENGTH, + default="#275d9f", + blank=True, + help_text="The hover color of links when active", + ) + link_default_text_decoration = MultipleFlagField( + default=[True, False, False, False], + num_flags=4, + db_default="1000", + help_text=("The text decoration flags [underline, strike, uppercase, italic]"), + ) + link_hover_text_decoration = MultipleFlagField( + default=[True, False, False, False], + num_flags=4, + db_default="1000", + help_text=("The text decoration flags [underline, strike, uppercase, italic]"), + ) + link_active_text_decoration = MultipleFlagField( + default=[True, False, False, False], + num_flags=4, + db_default="1000", + help_text=("The text decoration flags [underline, strike, uppercase, italic]"), + ) + + class Meta: + abstract = True + + +class LinkThemeConfigBlock(LinkThemeConfigBlockMixin, ThemeConfigBlock): + pass class ImageThemeConfigBlock(ThemeConfigBlock): diff --git a/backend/src/baserow/contrib/builder/theme/theme_config_block_types.py b/backend/src/baserow/contrib/builder/theme/theme_config_block_types.py index 3e22f9ab8..9b349bd67 100644 --- a/backend/src/baserow/contrib/builder/theme/theme_config_block_types.py +++ b/backend/src/baserow/contrib/builder/theme/theme_config_block_types.py @@ -32,6 +32,41 @@ class TypographyThemeConfigBlockType(ThemeConfigBlockType): type = "typography" model_class = TypographyThemeConfigBlock + @property + def serializer_field_overrides(self): + return { + "heading_1_text_decoration": serializers.ListField( + child=serializers.BooleanField(), + help_text="Text decoration: [underline, stroke, uppercase, italic]", + required=False, + ), + "heading_2_text_decoration": serializers.ListField( + child=serializers.BooleanField(), + help_text="Text decoration: [underline, stroke, uppercase, italic]", + required=False, + ), + "heading_3_text_decoration": serializers.ListField( + child=serializers.BooleanField(), + help_text="Text decoration: [underline, stroke, uppercase, italic]", + required=False, + ), + "heading_4_text_decoration": serializers.ListField( + child=serializers.BooleanField(), + help_text="Text decoration: [underline, stroke, uppercase, italic]", + required=False, + ), + "heading_5_text_decoration": serializers.ListField( + child=serializers.BooleanField(), + help_text="Text decoration: [underline, stroke, uppercase, italic]", + required=False, + ), + "heading_6_text_decoration": serializers.ListField( + child=serializers.BooleanField(), + help_text="Text decoration: [underline, stroke, uppercase, italic]", + required=False, + ), + } + def import_serialized( self, parent: Any, @@ -63,6 +98,26 @@ class LinkThemeConfigBlockType(ThemeConfigBlockType): type = "link" model_class = LinkThemeConfigBlock + @property + def serializer_field_overrides(self): + return { + "link_default_text_decoration": serializers.ListField( + child=serializers.BooleanField(), + help_text="Default text decoration: [underline, stroke, uppercase, italic]", + required=False, + ), + "link_hover_text_decoration": serializers.ListField( + child=serializers.BooleanField(), + help_text="Hover text decoration: [underline, stroke, uppercase, italic]", + required=False, + ), + "link_active_text_decoration": serializers.ListField( + child=serializers.BooleanField(), + help_text="Active text decoration: [underline, stroke, uppercase, italic]", + required=False, + ), + } + class ImageThemeConfigBlockType(ThemeConfigBlockType): type = "image" diff --git a/backend/src/baserow/contrib/builder/workflow_actions/workflow_action_types.py b/backend/src/baserow/contrib/builder/workflow_actions/workflow_action_types.py index 104cb42ba..facc47cee 100644 --- a/backend/src/baserow/contrib/builder/workflow_actions/workflow_action_types.py +++ b/backend/src/baserow/contrib/builder/workflow_actions/workflow_action_types.py @@ -386,6 +386,10 @@ class BuilderWorkflowServiceActionType(BuilderWorkflowActionType): service = workflow_action.service.specific yield from service.get_type().formula_generator(service) + def enhance_queryset(self, queryset): + queryset = queryset.select_related("service") + return super().enhance_queryset(queryset) + class UpsertRowWorkflowActionType(BuilderWorkflowServiceActionType): type = "upsert_row" diff --git a/backend/src/baserow/contrib/dashboard/apps.py b/backend/src/baserow/contrib/dashboard/apps.py index 5bfbf1af4..71db1c2e7 100644 --- a/backend/src/baserow/contrib/dashboard/apps.py +++ b/backend/src/baserow/contrib/dashboard/apps.py @@ -1,7 +1,5 @@ from django.apps import AppConfig -from baserow.core.feature_flags import FF_DASHBOARDS, feature_flag_is_enabled - class DashboardConfig(AppConfig): name = "baserow.contrib.dashboard" @@ -18,105 +16,102 @@ class DashboardConfig(AppConfig): from .application_types import DashboardApplicationType - if feature_flag_is_enabled(FF_DASHBOARDS): - application_type_registry.register(DashboardApplicationType()) + application_type_registry.register(DashboardApplicationType()) - from baserow.contrib.dashboard.object_scopes import DashboardObjectScopeType + from baserow.contrib.dashboard.object_scopes import DashboardObjectScopeType - object_scope_type_registry.register(DashboardObjectScopeType()) + object_scope_type_registry.register(DashboardObjectScopeType()) - from baserow.contrib.dashboard.data_sources.object_scopes import ( - DashboardDataSourceObjectScopeType, - ) + from baserow.contrib.dashboard.data_sources.object_scopes import ( + DashboardDataSourceObjectScopeType, + ) - object_scope_type_registry.register(DashboardDataSourceObjectScopeType()) + object_scope_type_registry.register(DashboardDataSourceObjectScopeType()) - from baserow.contrib.dashboard.widgets.object_scopes import ( - WidgetObjectScopeType, - ) + from baserow.contrib.dashboard.widgets.object_scopes import ( + WidgetObjectScopeType, + ) - object_scope_type_registry.register(WidgetObjectScopeType()) + object_scope_type_registry.register(WidgetObjectScopeType()) - from baserow.contrib.dashboard.widgets.operations import ( - CreateWidgetOperationType, - DeleteWidgetOperationType, - ListWidgetsOperationType, - ReadWidgetOperationType, - RestoreWidgetOperationType, - UpdateWidgetOperationType, - ) + from baserow.contrib.dashboard.widgets.operations import ( + CreateWidgetOperationType, + DeleteWidgetOperationType, + ListWidgetsOperationType, + ReadWidgetOperationType, + RestoreWidgetOperationType, + UpdateWidgetOperationType, + ) - operation_type_registry.register(ListWidgetsOperationType()) - operation_type_registry.register(ReadWidgetOperationType()) - operation_type_registry.register(CreateWidgetOperationType()) - operation_type_registry.register(UpdateWidgetOperationType()) - operation_type_registry.register(DeleteWidgetOperationType()) - operation_type_registry.register(RestoreWidgetOperationType()) + operation_type_registry.register(ListWidgetsOperationType()) + operation_type_registry.register(ReadWidgetOperationType()) + operation_type_registry.register(CreateWidgetOperationType()) + operation_type_registry.register(UpdateWidgetOperationType()) + operation_type_registry.register(DeleteWidgetOperationType()) + operation_type_registry.register(RestoreWidgetOperationType()) - from baserow.contrib.dashboard.data_sources.operations import ( - CreateDashboardDataSourceOperationType, - DeleteDashboardDataSourceOperationType, - DispatchDashboardDataSourceOperationType, - ListDashboardDataSourcesOperationType, - ReadDashboardDataSourceOperationType, - UpdateDashboardDataSourceOperationType, - ) + from baserow.contrib.dashboard.data_sources.operations import ( + CreateDashboardDataSourceOperationType, + DeleteDashboardDataSourceOperationType, + DispatchDashboardDataSourceOperationType, + ListDashboardDataSourcesOperationType, + ReadDashboardDataSourceOperationType, + UpdateDashboardDataSourceOperationType, + ) - operation_type_registry.register(ListDashboardDataSourcesOperationType()) - operation_type_registry.register(CreateDashboardDataSourceOperationType()) - operation_type_registry.register(DeleteDashboardDataSourceOperationType()) - operation_type_registry.register(UpdateDashboardDataSourceOperationType()) - operation_type_registry.register(ReadDashboardDataSourceOperationType()) - operation_type_registry.register(DispatchDashboardDataSourceOperationType()) + operation_type_registry.register(ListDashboardDataSourcesOperationType()) + operation_type_registry.register(CreateDashboardDataSourceOperationType()) + operation_type_registry.register(DeleteDashboardDataSourceOperationType()) + operation_type_registry.register(UpdateDashboardDataSourceOperationType()) + operation_type_registry.register(ReadDashboardDataSourceOperationType()) + operation_type_registry.register(DispatchDashboardDataSourceOperationType()) - from baserow.contrib.dashboard.widgets.registries import ( - widget_type_registry, - ) - from baserow.contrib.dashboard.widgets.widget_types import SummaryWidgetType + from baserow.contrib.dashboard.widgets.registries import widget_type_registry + from baserow.contrib.dashboard.widgets.widget_types import SummaryWidgetType - widget_type_registry.register(SummaryWidgetType()) + widget_type_registry.register(SummaryWidgetType()) - from baserow.contrib.dashboard.widgets.trash_types import ( - WidgetTrashableItemType, - ) + from baserow.contrib.dashboard.widgets.trash_types import ( + WidgetTrashableItemType, + ) - trash_item_type_registry.register(WidgetTrashableItemType()) + trash_item_type_registry.register(WidgetTrashableItemType()) - from .ws.pages import DashboardPageType + from .ws.pages import DashboardPageType - page_registry.register(DashboardPageType()) + page_registry.register(DashboardPageType()) - from baserow.core.registries import permission_manager_type_registry + from baserow.core.registries import permission_manager_type_registry - from .permission_manager import AllowIfTemplatePermissionManagerType + from .permission_manager import AllowIfTemplatePermissionManagerType - prev_manager = permission_manager_type_registry.get( - AllowIfTemplatePermissionManagerType.type - ) - permission_manager_type_registry.unregister( - AllowIfTemplatePermissionManagerType.type - ) - permission_manager_type_registry.register( - AllowIfTemplatePermissionManagerType(prev_manager) - ) + prev_manager = permission_manager_type_registry.get( + AllowIfTemplatePermissionManagerType.type + ) + permission_manager_type_registry.unregister( + AllowIfTemplatePermissionManagerType.type + ) + permission_manager_type_registry.register( + AllowIfTemplatePermissionManagerType(prev_manager) + ) - from baserow.contrib.dashboard.data_sources.actions import ( - UpdateDashboardDataSourceActionType, - ) - from baserow.contrib.dashboard.widgets.actions import ( - CreateWidgetActionType, - DeleteWidgetActionType, - UpdateWidgetActionType, - ) + from baserow.contrib.dashboard.data_sources.actions import ( + UpdateDashboardDataSourceActionType, + ) + from baserow.contrib.dashboard.widgets.actions import ( + CreateWidgetActionType, + DeleteWidgetActionType, + UpdateWidgetActionType, + ) - from .ws.receivers import ( # noqa: F401 - dashboard_data_source_updated, - widget_created, - widget_deleted, - widget_updated, - ) + from .ws.receivers import ( # noqa: F401 + dashboard_data_source_updated, + widget_created, + widget_deleted, + widget_updated, + ) - action_type_registry.register(CreateWidgetActionType()) - action_type_registry.register(UpdateWidgetActionType()) - action_type_registry.register(DeleteWidgetActionType()) - action_type_registry.register(UpdateDashboardDataSourceActionType()) + action_type_registry.register(CreateWidgetActionType()) + action_type_registry.register(UpdateWidgetActionType()) + action_type_registry.register(DeleteWidgetActionType()) + action_type_registry.register(UpdateDashboardDataSourceActionType()) diff --git a/backend/src/baserow/contrib/database/airtable/airtable_column_types.py b/backend/src/baserow/contrib/database/airtable/airtable_column_types.py index ec0f77e19..fb41af96e 100644 --- a/backend/src/baserow/contrib/database/airtable/airtable_column_types.py +++ b/backend/src/baserow/contrib/database/airtable/airtable_column_types.py @@ -1,16 +1,18 @@ from datetime import datetime, timezone from decimal import Decimal, InvalidOperation -from typing import Any, Dict, Optional +from typing import Any, Dict from django.core.exceptions import ValidationError from baserow.contrib.database.export_serialized import DatabaseExportSerializedStructure from baserow.contrib.database.fields.models import ( NUMBER_MAX_DECIMAL_PLACES, + AutonumberField, BooleanField, CountField, CreatedOnField, DateField, + DurationField, EmailField, Field, FileField, @@ -26,9 +28,18 @@ from baserow.contrib.database.fields.models import ( URLField, ) from baserow.contrib.database.fields.registries import field_type_registry +from baserow.contrib.database.fields.utils.duration import D_H, H_M_S_SSS +from baserow.core.utils import get_value_at_path from .config import AirtableImportConfig -from .constants import AIRTABLE_NUMBER_FIELD_SEPARATOR_FORMAT_MAPPING +from .constants import ( + AIRTABLE_DURATION_FIELD_DURATION_FORMAT_MAPPING, + AIRTABLE_MAX_DURATION_VALUE, + AIRTABLE_NUMBER_FIELD_SEPARATOR_FORMAT_MAPPING, + AIRTABLE_RATING_COLOR_MAPPING, + AIRTABLE_RATING_ICON_MAPPING, +) +from .exceptions import AirtableSkipCellValue from .helpers import import_airtable_date_type_options, set_select_options_on_field from .import_report import ( ERROR_TYPE_DATA_TYPE_MISMATCH, @@ -38,7 +49,7 @@ from .import_report import ( AirtableImportReport, ) from .registry import AirtableColumnType -from .utils import get_airtable_row_primary_value +from .utils import get_airtable_row_primary_value, quill_to_markdown class TextAirtableColumnType(AirtableColumnType): @@ -53,7 +64,7 @@ class TextAirtableColumnType(AirtableColumnType): elif validator_name == "email": return EmailField() else: - return TextField() + return TextField(text_default=raw_airtable_column.get("default", "")) def to_baserow_export_serialized_value( self, @@ -86,6 +97,25 @@ class TextAirtableColumnType(AirtableColumnType): return value + def to_baserow_export_empty_value( + self, + row_id_mapping, + raw_airtable_table, + raw_airtable_row, + raw_airtable_column, + baserow_field, + files_to_download, + config, + import_report, + ): + # If the `text_default` is set, then we must return an empty string. If we + # don't, the value is omitted in the export, resulting in the default value + # automatically being set, while it's actually empty in Airtable. + if isinstance(baserow_field, TextField) and baserow_field.text_default != "": + return "" + else: + raise AirtableSkipCellValue + class MultilineTextAirtableColumnType(AirtableColumnType): type = "multilineText" @@ -102,7 +132,7 @@ class RichTextTextAirtableColumnType(AirtableColumnType): def to_baserow_field( self, raw_airtable_table, raw_airtable_column, config, import_report ): - return LongTextField() + return LongTextField(long_text_enable_rich_text=True) def to_baserow_export_serialized_value( self, @@ -116,37 +146,7 @@ class RichTextTextAirtableColumnType(AirtableColumnType): config, import_report, ): - # We don't support rich text formatting yet, so this converts the value to - # plain text. - rich_values = [] - for v in value["documentValue"]: - insert_value = v["insert"] - if isinstance(insert_value, str): - rich_values.append(insert_value) - elif isinstance(insert_value, dict): - rich_value = self._extract_value_from_airtable_rich_value_dict( - insert_value - ) - if rich_value is not None: - rich_values.append(rich_value) - - return "".join(rich_values) - - def _extract_value_from_airtable_rich_value_dict( - self, insert_value_dict: Dict[Any, Any] - ) -> Optional[str]: - """ - Airtable rich text fields can contain references to users. For now this method - attempts to return a @userId reference string. In the future if Baserow has - a rich text field and the ability to reference users in them we should map - this airtable userId to the corresponding Baserow user id. - """ - - mention = insert_value_dict.get("mention") - if isinstance(mention, dict): - user_id = mention.get("userId") - if user_id is not None: - return f"@{user_id}" + return quill_to_markdown(value["documentValue"]) class NumberAirtableColumnType(AirtableColumnType): @@ -155,10 +155,51 @@ class NumberAirtableColumnType(AirtableColumnType): def to_baserow_field( self, raw_airtable_table, raw_airtable_column, config, import_report ): + self.add_import_report_failed_if_default_is_provided( + raw_airtable_table, raw_airtable_column, import_report + ) + type_options = raw_airtable_column.get("typeOptions", {}) options_format = type_options.get("format", "") + + if options_format in ["duration", "durationInDays"]: + return self.to_duration_field( + raw_airtable_table, raw_airtable_column, config, import_report + ) + else: + return self.to_number_field( + raw_airtable_table, raw_airtable_column, config, import_report + ) + + def to_duration_field( + self, raw_airtable_table, raw_airtable_column, config, import_report + ): + type_options = raw_airtable_column.get("typeOptions", {}) + options_format = type_options.get("format", "") + duration_format = type_options.get("durationFormat", "") + + if options_format == "durationInDays": + # It looks like this option is broken in Airtable. When this is selected, + # the exact value seems to be in seconds, but it should be in days. We + # will therefore convert it to days when calculating the value. + duration_format = D_H + else: + # Fallback to the most specific format because that leaves most of the + # value intact. + duration_format = AIRTABLE_DURATION_FIELD_DURATION_FORMAT_MAPPING.get( + duration_format, H_M_S_SSS + ) + + return DurationField(duration_format=duration_format) + + def to_number_field( + self, raw_airtable_table, raw_airtable_column, config, import_report + ): suffix = "" + type_options = raw_airtable_column.get("typeOptions", {}) + options_format = type_options.get("format", "") + if "percent" in options_format: suffix = "%" @@ -173,7 +214,7 @@ class NumberAirtableColumnType(AirtableColumnType): if separator_format != "" and number_separator == "": import_report.add_failed( - f"Number field: \"{raw_airtable_column['name']}\"", + raw_airtable_column["name"], SCOPE_FIELD, raw_airtable_table.get("name", ""), ERROR_TYPE_UNSUPPORTED_FEATURE, @@ -204,14 +245,40 @@ class NumberAirtableColumnType(AirtableColumnType): if value is None: return None + type_options = raw_airtable_column.get("typeOptions", {}) + options_format = type_options.get("format", "") + row_name = get_airtable_row_primary_value(raw_airtable_table, raw_airtable_row) + + if options_format == "durationInDays": + # If the formatting is in days, we must multiply the raw value in seconds + # by the number of seconds in a day. + value = value * 60 * 60 * 24 + + if "duration" in options_format: + # If the value is higher than the maximum that the `timedelta` can handle, + # then we can't use it, so we have to drop it. The maximum number of days + # in `timedelta` is `999999999`, so the max number of seconds are + # 999999999 * 24 * 60 * 60 = 86399999913600. + if abs(value) > AIRTABLE_MAX_DURATION_VALUE: + import_report.add_failed( + f"Row: \"{row_name}\", field: \"{raw_airtable_column['name']}\"", + SCOPE_CELL, + raw_airtable_table["name"], + ERROR_TYPE_DATA_TYPE_MISMATCH, + f"Cell value was left empty because the duration seconds {value} " + f'is outside the -86399999913600 and 86399999913600 range."', + ) + return None + + # If the value is a duration, then we can use the same value because both + # store it as seconds. + return value + try: value = Decimal(value) except InvalidOperation: # If the value can't be parsed as decimal, then it might be corrupt, so we # need to inform the user and skip the import. - row_name = get_airtable_row_primary_value( - raw_airtable_table, raw_airtable_row - ) import_report.add_failed( f"Row: \"{row_name}\", field: \"{raw_airtable_column['name']}\"", SCOPE_CELL, @@ -224,8 +291,6 @@ class NumberAirtableColumnType(AirtableColumnType): # Airtable stores 10% as 0.1, so we would need to multiply it by 100 so get the # correct value in Baserow. - type_options = raw_airtable_column.get("typeOptions", {}) - options_format = type_options.get("format", "") if "percent" in options_format: value = value * 100 @@ -241,8 +306,39 @@ class RatingAirtableColumnType(AirtableColumnType): def to_baserow_field( self, raw_airtable_table, raw_airtable_column, config, import_report ): + type_options = raw_airtable_column.get("typeOptions", {}) + airtable_icon = type_options.get("icon", "") + airtable_max = type_options.get("max", 5) + airtable_color = type_options.get("color", "") + + style = AIRTABLE_RATING_ICON_MAPPING.get(airtable_icon, "") + if style == "": + style = list(AIRTABLE_RATING_ICON_MAPPING.values())[0] + import_report.add_failed( + raw_airtable_column["name"], + SCOPE_FIELD, + raw_airtable_table.get("name", ""), + ERROR_TYPE_UNSUPPORTED_FEATURE, + f"The field was imported, but the icon {airtable_icon} does not " + f"exist, so it defaulted to {style}.", + ) + + color = AIRTABLE_RATING_COLOR_MAPPING.get(airtable_color, "") + if color == "": + color = list(AIRTABLE_RATING_COLOR_MAPPING.values())[0] + import_report.add_failed( + raw_airtable_column["name"], + SCOPE_FIELD, + raw_airtable_table.get("name", ""), + ERROR_TYPE_UNSUPPORTED_FEATURE, + f"The field was imported, but the color {airtable_color} does not " + f"exist, so it defaulted to {color}.", + ) + return RatingField( - max_value=raw_airtable_column.get("typeOptions", {}).get("max", 5) + max_value=airtable_max, + style=style, + color=color, ) @@ -252,6 +348,32 @@ class CheckboxAirtableColumnType(AirtableColumnType): def to_baserow_field( self, raw_airtable_table, raw_airtable_column, config, import_report ): + self.add_import_report_failed_if_default_is_provided( + raw_airtable_table, raw_airtable_column, import_report + ) + + type_options = raw_airtable_column.get("typeOptions", {}) + airtable_icon = type_options.get("icon", "check") + airtable_color = type_options.get("color", "green") + + if airtable_icon != "check": + import_report.add_failed( + raw_airtable_column["name"], + SCOPE_FIELD, + raw_airtable_table.get("name", ""), + ERROR_TYPE_UNSUPPORTED_FEATURE, + f"The field was imported, but the icon {airtable_icon} is not supported.", + ) + + if airtable_color != "green": + import_report.add_failed( + raw_airtable_column["name"], + SCOPE_FIELD, + raw_airtable_table.get("name", ""), + ERROR_TYPE_UNSUPPORTED_FEATURE, + f"The field was imported, but the color {airtable_color} is not supported.", + ) + return BooleanField() def to_baserow_export_serialized_value( @@ -275,6 +397,13 @@ class DateAirtableColumnType(AirtableColumnType): def to_baserow_field( self, raw_airtable_table, raw_airtable_column, config, import_report ): + self.add_import_report_failed_if_default_is_provided( + raw_airtable_table, + raw_airtable_column, + import_report, + to_human_readable_default=lambda x: "Current date", + ) + type_options = raw_airtable_column.get("typeOptions", {}) # Check if a timezone is provided in the type options, if so, we might want # to use that timezone for the conversion later on. @@ -283,13 +412,6 @@ class DateAirtableColumnType(AirtableColumnType): # date_force_timezone=None it the equivalent of airtable_timezone="client". if airtable_timezone == "client": - import_report.add_failed( - raw_airtable_column["name"], - SCOPE_FIELD, - raw_airtable_table.get("name", ""), - ERROR_TYPE_UNSUPPORTED_FEATURE, - "The date field was imported, but the client timezone setting was dropped.", - ) airtable_timezone = None return DateField( @@ -358,15 +480,6 @@ class FormulaAirtableColumnType(AirtableColumnType): is_last_modified = display_type == "lastModifiedTime" is_created = display_type == "createdTime" - if is_last_modified or is_created and airtable_timezone == "client": - import_report.add_failed( - raw_airtable_column["name"], - SCOPE_FIELD, - raw_airtable_table.get("name", ""), - ERROR_TYPE_UNSUPPORTED_FEATURE, - "The field was imported, but the client timezone setting was dropped.", - ) - # date_force_timezone=None it the equivalent of airtable_timezone="client". if airtable_timezone == "client": airtable_timezone = None @@ -374,6 +487,22 @@ class FormulaAirtableColumnType(AirtableColumnType): # The formula conversion isn't support yet, but because the Created on and # Last modified fields work as a formula, we can convert those. if is_last_modified: + dependencies = type_options.get("dependencies", {}) + all_column_modifications = dependencies.get( + "dependsOnAllColumnModifications", False + ) + + if not all_column_modifications: + import_report.add_failed( + raw_airtable_column["name"], + SCOPE_FIELD, + raw_airtable_table.get("name", ""), + ERROR_TYPE_UNSUPPORTED_FEATURE, + f"The field was imported, but the support to depend on " + f"specific fields was dropped because that's not supported by " + f"Baserow.", + ) + return LastModifiedField( date_show_tzinfo=date_show_tzinfo, date_force_timezone=airtable_timezone, @@ -421,12 +550,72 @@ class ForeignKeyAirtableColumnType(AirtableColumnType): ): type_options = raw_airtable_column.get("typeOptions", {}) foreign_table_id = type_options.get("foreignTableId") + relationship = type_options.get("relationship", "many") # can be: one + view_id_for_record_selection = type_options.get( + "viewIdForRecordSelection", None + ) + filters_for_record_selection = type_options.get( + "filtersForRecordSelection", None + ) + ai_matching_options = type_options.get("aiMatchingOptions", None) + + if relationship != "many": + import_report.add_failed( + raw_airtable_column["name"], + SCOPE_FIELD, + raw_airtable_table.get("name", ""), + ERROR_TYPE_UNSUPPORTED_FEATURE, + f"The field was imported, but support for a one to many " + f"relationship was dropped because it's not supported by Baserow.", + ) + + if view_id_for_record_selection is not None: + import_report.add_failed( + raw_airtable_column["name"], + SCOPE_FIELD, + raw_airtable_table.get("name", ""), + ERROR_TYPE_UNSUPPORTED_FEATURE, + f"The field was imported, but limiting record selection to a view " + f"was dropped because the views have not been imported.", + ) + + if filters_for_record_selection is not None: + import_report.add_failed( + raw_airtable_column["name"], + SCOPE_FIELD, + raw_airtable_table.get("name", ""), + ERROR_TYPE_UNSUPPORTED_FEATURE, + f"The field was imported, but filtering record by a condition " + f"was dropped because it's not supported by Baserow.", + ) + + if ai_matching_options is not None: + import_report.add_failed( + raw_airtable_column["name"], + SCOPE_FIELD, + raw_airtable_table.get("name", ""), + ERROR_TYPE_UNSUPPORTED_FEATURE, + f"The field was imported, but using AI to show top matches was " + f"dropped because it's not supported by Baserow.", + ) return LinkRowField( link_row_table_id=foreign_table_id, link_row_related_field_id=type_options.get("symmetricColumnId"), ) + def after_field_objects_prepared( + self, field_mapping_per_table, baserow_field, raw_airtable_column + ): + foreign_table_id = raw_airtable_column["typeOptions"]["foreignTableId"] + foreign_field_mapping = field_mapping_per_table[foreign_table_id] + foreign_primary_field = next( + field["baserow_field"] + for field in foreign_field_mapping.values() + if field["baserow_field"].primary + ) + baserow_field.link_row_table_primary_field = foreign_primary_field + def to_baserow_export_serialized_value( self, row_id_mapping, @@ -531,12 +720,21 @@ class SelectAirtableColumnType(AirtableColumnType): def to_baserow_field( self, raw_airtable_table, raw_airtable_column, config, import_report ): - field = SingleSelectField() - field = set_select_options_on_field( - field, - raw_airtable_column.get("id", ""), - raw_airtable_column.get("typeOptions", {}), + id_value = raw_airtable_column.get("id", "") + type_options = raw_airtable_column.get("typeOptions", {}) + + def get_default(x): + return get_value_at_path(type_options, f"choices.{x}.name", "") + + self.add_import_report_failed_if_default_is_provided( + raw_airtable_table, + raw_airtable_column, + import_report, + to_human_readable_default=get_default, ) + + field = SingleSelectField() + field = set_select_options_on_field(field, id_value, type_options) return field @@ -562,12 +760,27 @@ class MultiSelectAirtableColumnType(AirtableColumnType): def to_baserow_field( self, raw_airtable_table, raw_airtable_column, config, import_report ): - field = MultipleSelectField() - field = set_select_options_on_field( - field, - raw_airtable_column.get("id", ""), - raw_airtable_column.get("typeOptions", {}), + id_value = raw_airtable_column.get("id", "") + type_options = raw_airtable_column.get("typeOptions", {}) + + def get_default(default): + default = default or [] + return ", ".join( + [ + get_value_at_path(type_options, f"choices.{v}.name", "") + for v in default + ] + ) + + self.add_import_report_failed_if_default_is_provided( + raw_airtable_table, + raw_airtable_column, + import_report, + to_human_readable_default=get_default, ) + + field = MultipleSelectField() + field = set_select_options_on_field(field, id_value, type_options) return field @@ -631,3 +844,12 @@ class CountAirtableColumnType(AirtableColumnType): import_report, ): return None + + +class AutoNumberAirtableColumnType(AirtableColumnType): + type = "autoNumber" + + def to_baserow_field( + self, raw_airtable_table, raw_airtable_column, config, import_report + ): + return AutonumberField() diff --git a/backend/src/baserow/contrib/database/airtable/airtable_filter_operators.py b/backend/src/baserow/contrib/database/airtable/airtable_filter_operators.py new file mode 100644 index 000000000..07e4be1e4 --- /dev/null +++ b/backend/src/baserow/contrib/database/airtable/airtable_filter_operators.py @@ -0,0 +1,423 @@ +from baserow.contrib.database.views.registries import view_filter_type_registry +from baserow.core.utils import get_value_at_path + +from .exceptions import AirtableSkipFilter +from .helpers import to_import_select_option_id +from .registry import AirtableFilterOperator +from .utils import ( + airtable_date_filter_value_to_baserow, + skip_filter_if_type_duration_and_value_too_high, +) + + +class AirtableContainsOperator(AirtableFilterOperator): + type = "contains" + + def to_baserow_filter_and_value( + self, + row_id_mapping, + raw_airtable_table, + raw_airtable_column, + baserow_field, + import_report, + value, + ): + if raw_airtable_column["type"] in ["foreignKey"]: + return view_filter_type_registry.get("link_row_contains"), value + + return view_filter_type_registry.get("contains"), value + + +class AirtableDoesNotContainOperator(AirtableFilterOperator): + type = "doesNotContain" + + def to_baserow_filter_and_value( + self, + row_id_mapping, + raw_airtable_table, + raw_airtable_column, + baserow_field, + import_report, + value, + ): + if raw_airtable_column["type"] in ["foreignKey"]: + return view_filter_type_registry.get("link_row_not_contains"), value + + if raw_airtable_column["type"] in ["multiSelect"]: + value = [f"{raw_airtable_column['id']}_{v}" for v in value] + value = ",".join(value) + return view_filter_type_registry.get("multiple_select_has_not"), value + + return view_filter_type_registry.get("contains_not"), value + + +class AirtableEqualOperator(AirtableFilterOperator): + type = "=" + + def to_baserow_filter_and_value( + self, + row_id_mapping, + raw_airtable_table, + raw_airtable_column, + baserow_field, + import_report, + value, + ): + if raw_airtable_column["type"] in [ + "text", + "multilineText", + "number", + "rating", + "phone", + "autoNumber", + ]: + skip_filter_if_type_duration_and_value_too_high(raw_airtable_column, value) + return view_filter_type_registry.get("equal"), str(value) + + if raw_airtable_column["type"] in ["checkbox"]: + return ( + view_filter_type_registry.get("boolean"), + "true" if value else "false", + ) + + if raw_airtable_column["type"] in ["select"]: + value = to_import_select_option_id(raw_airtable_column["id"], value) + return view_filter_type_registry.get("single_select_equal"), value + + if raw_airtable_column["type"] in ["multiSelect"]: + value = [f"{raw_airtable_column['id']}_{v}" for v in value] + value = ",".join(value) + return view_filter_type_registry.get("multiple_select_has"), value + + if raw_airtable_column["type"] in ["collaborator"]: + return view_filter_type_registry.get("multiple_collaborators_has"), value + + if raw_airtable_column["type"] in ["date"]: + value = airtable_date_filter_value_to_baserow(value) + return view_filter_type_registry.get("date_is"), value + + if raw_airtable_column["type"] in ["foreignKey"]: + if isinstance(value, list): + if len(value) > 1: + raise AirtableSkipFilter + foreign_table_id = get_value_at_path( + raw_airtable_column, "typeOptions.foreignTableId" + ) + table_row_id_mapping = row_id_mapping.get(foreign_table_id, {}) + value = [ + str(table_row_id_mapping.get(v)) + for v in value + if v in table_row_id_mapping + ] + value = ",".join(value) + return view_filter_type_registry.get("link_row_has"), value + + raise AirtableSkipFilter + + +class AirtableNotEqualOperator(AirtableFilterOperator): + type = "!=" + + def to_baserow_filter_and_value( + self, + row_id_mapping, + raw_airtable_table, + raw_airtable_column, + baserow_field, + import_report, + value, + ): + if raw_airtable_column["type"] in [ + "text", + "multilineText", + "number", + "rating", + "phone", + "autoNumber", + ]: + skip_filter_if_type_duration_and_value_too_high(raw_airtable_column, value) + return view_filter_type_registry.get("not_equal"), str(value) + + if raw_airtable_column["type"] in ["select"]: + value = to_import_select_option_id(raw_airtable_column["id"], value) + return view_filter_type_registry.get("single_select_not_equal"), value + + if raw_airtable_column["type"] in ["collaborator"]: + return ( + view_filter_type_registry.get("multiple_collaborators_has_not"), + value, + ) + + if raw_airtable_column["type"] in ["date"]: + value = airtable_date_filter_value_to_baserow(value) + return view_filter_type_registry.get("date_is_not"), value + + raise AirtableSkipFilter + + +class AirtableIsEmptyOperator(AirtableFilterOperator): + type = "isEmpty" + + def to_baserow_filter_and_value( + self, + row_id_mapping, + raw_airtable_table, + raw_airtable_column, + baserow_field, + import_report, + value, + ): + return view_filter_type_registry.get("empty"), "" + + +class AirtableIsNotEmptyOperator(AirtableFilterOperator): + type = "isNotEmpty" + + def to_baserow_filter_and_value( + self, + row_id_mapping, + raw_airtable_table, + raw_airtable_column, + baserow_field, + import_report, + value, + ): + return view_filter_type_registry.get("not_empty"), "" + + +class AirtableFilenameOperator(AirtableFilterOperator): + type = "filename" + + def to_baserow_filter_and_value( + self, + row_id_mapping, + raw_airtable_table, + raw_airtable_column, + baserow_field, + import_report, + value, + ): + return view_filter_type_registry.get("filename_contains"), value + + +class AirtableFiletypeOperator(AirtableFilterOperator): + type = "filetype" + + def to_baserow_filter_and_value( + self, + row_id_mapping, + raw_airtable_table, + raw_airtable_column, + baserow_field, + import_report, + value, + ): + if value == "image": + value = "image" + elif value == "text": + value = "document" + else: + raise AirtableSkipFilter + + return view_filter_type_registry.get("has_file_type"), value + + +class AirtableIsAnyOfOperator(AirtableFilterOperator): + type = "isAnyOf" + + def to_baserow_filter_and_value( + self, + row_id_mapping, + raw_airtable_table, + raw_airtable_column, + baserow_field, + import_report, + value, + ): + if raw_airtable_column["type"] in ["select"]: + value = [ + to_import_select_option_id(raw_airtable_column["id"], v) for v in value + ] + value = ",".join(value) + return view_filter_type_registry.get("single_select_is_any_of"), value + + raise AirtableSkipFilter + + +class AirtableIsNoneOfOperator(AirtableFilterOperator): + type = "isNoneOf" + + def to_baserow_filter_and_value( + self, + row_id_mapping, + raw_airtable_table, + raw_airtable_column, + baserow_field, + import_report, + value, + ): + if raw_airtable_column["type"] in ["select"]: + value = [ + to_import_select_option_id(raw_airtable_column["id"], v) for v in value + ] + value = ",".join(value) + return view_filter_type_registry.get("single_select_is_none_of"), value + + raise AirtableSkipFilter + + +class AirtableHasAnyOfOperator(AirtableFilterOperator): + type = "|" + + def to_baserow_filter_and_value( + self, + row_id_mapping, + raw_airtable_table, + raw_airtable_column, + baserow_field, + import_report, + value, + ): + raise AirtableSkipFilter + + +class AirtableHasAllOfOperator(AirtableFilterOperator): + type = "&" + + def to_baserow_filter_and_value( + self, + row_id_mapping, + raw_airtable_table, + raw_airtable_column, + baserow_field, + import_report, + value, + ): + raise AirtableSkipFilter + + +class AirtableLessThanOperator(AirtableFilterOperator): + type = "<" + + def to_baserow_filter_and_value( + self, + row_id_mapping, + raw_airtable_table, + raw_airtable_column, + baserow_field, + import_report, + value, + ): + if raw_airtable_column["type"] in [ + "number", + "rating", + "autoNumber", + ]: + skip_filter_if_type_duration_and_value_too_high(raw_airtable_column, value) + return view_filter_type_registry.get("lower_than"), str(value) + + if raw_airtable_column["type"] in ["date"]: + value = airtable_date_filter_value_to_baserow(value) + return view_filter_type_registry.get("date_is_before"), value + + raise AirtableSkipFilter + + +class AirtableMoreThanOperator(AirtableFilterOperator): + type = ">" + + def to_baserow_filter_and_value( + self, + row_id_mapping, + raw_airtable_table, + raw_airtable_column, + baserow_field, + import_report, + value, + ): + if raw_airtable_column["type"] in [ + "number", + "rating", + "autoNumber", + ]: + skip_filter_if_type_duration_and_value_too_high(raw_airtable_column, value) + return view_filter_type_registry.get("higher_than"), str(value) + + if raw_airtable_column["type"] in ["date"]: + value = airtable_date_filter_value_to_baserow(value) + return view_filter_type_registry.get("date_is_after"), value + + raise AirtableSkipFilter + + +class AirtableLessThanOrEqualOperator(AirtableFilterOperator): + type = "<=" + + def to_baserow_filter_and_value( + self, + row_id_mapping, + raw_airtable_table, + raw_airtable_column, + baserow_field, + import_report, + value, + ): + if raw_airtable_column["type"] in [ + "number", + "rating", + "autoNumber", + ]: + skip_filter_if_type_duration_and_value_too_high(raw_airtable_column, value) + return view_filter_type_registry.get("lower_than_or_equal"), str(value) + + if raw_airtable_column["type"] in ["date"]: + value = airtable_date_filter_value_to_baserow(value) + return view_filter_type_registry.get("date_is_on_or_before"), value + + raise AirtableSkipFilter + + +class AirtableMoreThanOrEqualOperator(AirtableFilterOperator): + type = ">=" + + def to_baserow_filter_and_value( + self, + row_id_mapping, + raw_airtable_table, + raw_airtable_column, + baserow_field, + import_report, + value, + ): + if raw_airtable_column["type"] in [ + "number", + "rating", + "autoNumber", + ]: + skip_filter_if_type_duration_and_value_too_high(raw_airtable_column, value) + return view_filter_type_registry.get("higher_than_or_equal"), str(value) + + if raw_airtable_column["type"] in ["date"]: + value = airtable_date_filter_value_to_baserow(value) + return view_filter_type_registry.get("date_is_on_or_after"), value + + raise AirtableSkipFilter + + +class AirtableIsWithinOperator(AirtableFilterOperator): + type = "isWithin" + + def to_baserow_filter_and_value( + self, + row_id_mapping, + raw_airtable_table, + raw_airtable_column, + baserow_field, + import_report, + value, + ): + if raw_airtable_column["type"] in ["date"]: + value = airtable_date_filter_value_to_baserow(value) + return view_filter_type_registry.get("date_is_within"), value + + raise AirtableSkipFilter diff --git a/backend/src/baserow/contrib/database/airtable/airtable_view_types.py b/backend/src/baserow/contrib/database/airtable/airtable_view_types.py new file mode 100644 index 000000000..f3d04cb53 --- /dev/null +++ b/backend/src/baserow/contrib/database/airtable/airtable_view_types.py @@ -0,0 +1,56 @@ +from baserow.contrib.database.airtable.registry import AirtableViewType +from baserow.contrib.database.views.models import GridView, GridViewFieldOptions +from baserow.contrib.database.views.view_types import GridViewType +from baserow.core.utils import get_value_at_path + + +class GridAirtableViewType(AirtableViewType): + type = "grid" + baserow_view_type = GridViewType.type + + def prepare_view_object( + self, + field_mapping, + view: GridView, + raw_airtable_table, + raw_airtable_view, + raw_airtable_view_data, + config, + import_report, + ): + # Airtable doesn't have this option, and by default it is count. + view.row_identifier_type = GridView.RowIdentifierTypes.count.value + + # Set the row height if the value size is available. Baserow doesn't support + # `xlarge`, so we're falling back on `large`in that case. + row_height_mapping = {v: v for v in GridView.RowHeightSizes.values} + row_height_mapping["xlarge"] = GridView.RowHeightSizes.large.value + row_height = get_value_at_path( + raw_airtable_view_data, "metadata.grid.rowHeight" + ) + view.row_height_size = row_height_mapping.get( + row_height, GridView.RowHeightSizes.small.value + ) + + # Map the columnOrder entries to the matching `GridViewFieldOptions`, + # and set that as `get_field_options`, so that it's correctly serialized + # exported. + field_options = [] + column_orders = raw_airtable_view_data.get("columnOrder", None) or [] + for index, column_order in enumerate(column_orders): + if column_order["columnId"] not in field_mapping: + continue + + field_options.append( + GridViewFieldOptions( + id=f"{raw_airtable_view['id']}_columnOrder_{index}", + grid_view_id=view.id, + field_id=column_order["columnId"], + width=column_order.get("width", 200), + hidden=not column_order.get("visibility", True), + order=index + 1, + ) + ) + view.get_field_options = lambda *args, **kwargs: field_options + + return view diff --git a/backend/src/baserow/contrib/database/airtable/constants.py b/backend/src/baserow/contrib/database/airtable/constants.py index e74182723..39685d415 100644 --- a/backend/src/baserow/contrib/database/airtable/constants.py +++ b/backend/src/baserow/contrib/database/airtable/constants.py @@ -1,17 +1,54 @@ +from baserow.contrib.database.fields.utils.duration import ( + H_M, + H_M_S, + H_M_S_S, + H_M_S_SS, + H_M_S_SSS, +) + +AIRTABLE_MAX_DURATION_VALUE = 86399999913600 +AIRTABLE_BASE_URL = "https://airtable.com" +AIRTABLE_API_BASE_URL = f"{AIRTABLE_BASE_URL}/v0.3" AIRTABLE_EXPORT_JOB_DOWNLOADING_BASE = "downloading-base" AIRTABLE_EXPORT_JOB_CONVERTING = "converting" AIRTABLE_EXPORT_JOB_DOWNLOADING_FILES = "downloading-files" AIRTABLE_BASEROW_COLOR_MAPPING = { - "blue": "blue", - "cyan": "light-blue", - "teal": "light-green", - "green": "green", - "yellow": "light-orange", - "orange": "orange", + "blue": "light-blue", + "cyan": "light-cyan", + "teal": "light-pink", # Baserow doesn't have teal, so we're using the left-over color + "green": "light-green", + "yellow": "light-yellow", + "orange": "light-orange", "red": "light-red", - "pink": "red", - "purple": "dark-blue", + "purple": "light-purple", "gray": "light-gray", + "blueMedium": "blue", + "cyanMedium": "cyan", + "tealMedium": "pink", + "greenMedium": "green", + "yellowMedium": "yellow", + "orangeMedium": "orange", + "redMedium": "red", + "purpleMedium": "purple", + "grayMedium": "gray", + "blueDark": "dark-blue", + "cyanDark": "dark-cyan", + "tealDark": "dark-pink", + "greenDark": "dark-green", + "yellowDark": "dark-yellow", + "orangeDark": "dark-orange", + "redDark": "dark-red", + "purpleDark": "dark-purple", + "grayDark": "dark-gray", + "blueDarker": "darker-blue", + "cyanDarker": "darker-cyan", + "tealDarker": "darker-pink", + "greenDarker": "darker-green", + "yellowDarker": "darker-yellow", + "orangeDarker": "darker-orange", + "redDarker": "darker-red", + "purpleDarker": "darker-purple", + "grayDarker": "darker-gray", } AIRTABLE_NUMBER_FIELD_SEPARATOR_FORMAT_MAPPING = { "commaPeriod": "COMMA_PERIOD", @@ -19,3 +56,51 @@ AIRTABLE_NUMBER_FIELD_SEPARATOR_FORMAT_MAPPING = { "spaceComma": "SPACE_COMMA", "spacePeriod": "SPACE_PERIOD", } +AIRTABLE_DURATION_FIELD_DURATION_FORMAT_MAPPING = { + "h:mm": H_M, + "h:mm:ss": H_M_S, + "h:mm:ss.s": H_M_S_S, + "h:mm:ss.ss": H_M_S_SS, + "h:mm:ss.sss": H_M_S_SSS, +} +# All colors from the rating field in Airtable: yellow, orange, red, pink, purple, +# blue, cyan, teal, green, gray. We're only mapping the ones that we have an +# alternative for. +AIRTABLE_RATING_COLOR_MAPPING = { + "blue": "dark-blue", + "green": "dark-green", + "orange": "dark-orange", + "red": "dark-red", +} +# All icons from Airtable: star, heart, thumbsUp, flag, dot. We're only mapping the +# ones that we have an alternative for. +AIRTABLE_RATING_ICON_MAPPING = { + "star": "star", + "heart": "heart", + "thumbsUp": "thumbs-up", + "flag": "flag", +} +AIRTABLE_ASCENDING_MAP = { + "ascending": True, + "descending": False, +} +AIRTABLE_DATE_FILTER_VALUE_MAP = { + "daysAgo": "{timeZone}?{numberOfDays}?nr_days_ago", + "daysFromNow": "{timeZone}?{numberOfDays}?nr_days_from_now", + "exactDate": "{timeZone}?{exactDate}?exact_date", + "nextMonth": "{timeZone}??next_month", + "nextNumberOfDays": "{timeZone}?{numberOfDays}?nr_days_from_now", + "nextWeek": "{timeZone}??next_week", + "oneMonthAgo": "{timeZone}??one_month_ago", + "oneWeekAgo": "{timeZone}?1?nr_weeks_ago", + "oneMonthFromNow": "{timeZone}?1?nr_months_from_now", + "oneWeekFromNow": "{timeZone}?1?nr_weeks_from_now", + "pastMonth": "{timeZone}?1?nr_months_ago", + "pastNumberOfDays": "{timeZone}?{numberOfDays}?nr_days_ago", + "pastWeek": "{timeZone}?1?nr_weeks_ago", + "pastYear": "{timeZone}?1?nr_years_ago", + "thisCalendarYear": "{timeZone}?0?nr_years_ago", + "today": "{timeZone}??today", + "tomorrow": "{timeZone}??tomorrow", + "yesterday": "{timeZone}??yesterday", +} diff --git a/backend/src/baserow/contrib/database/airtable/exceptions.py b/backend/src/baserow/contrib/database/airtable/exceptions.py index 1cce4abe6..d5890305a 100644 --- a/backend/src/baserow/contrib/database/airtable/exceptions.py +++ b/backend/src/baserow/contrib/database/airtable/exceptions.py @@ -8,3 +8,16 @@ class AirtableShareIsNotABase(Exception): class AirtableImportNotRespectingConfig(Exception): """Raised when the Airtable import is not respecting the `AirtableImportConfig`.""" + + +class AirtableSkipCellValue(Exception): + """ + Raised when an Airtable cell value must be skipped, and be omitted from the + export. + """ + + +class AirtableSkipFilter(Exception): + """ + Raised when an Airtable filter is not compatible and must be skipped. + """ diff --git a/backend/src/baserow/contrib/database/airtable/handler.py b/backend/src/baserow/contrib/database/airtable/handler.py index 1db69ce6d..844a86dc6 100644 --- a/backend/src/baserow/contrib/database/airtable/handler.py +++ b/backend/src/baserow/contrib/database/airtable/handler.py @@ -7,12 +7,15 @@ from typing import Dict, List, Optional, Tuple, Union from zipfile import ZIP_DEFLATED, ZipFile from django.contrib.auth import get_user_model +from django.contrib.contenttypes.models import ContentType from django.core.files.storage import Storage import requests from requests import Response from baserow.contrib.database.airtable.constants import ( + AIRTABLE_API_BASE_URL, + AIRTABLE_BASE_URL, AIRTABLE_EXPORT_JOB_CONVERTING, AIRTABLE_EXPORT_JOB_DOWNLOADING_BASE, AIRTABLE_EXPORT_JOB_DOWNLOADING_FILES, @@ -20,25 +23,29 @@ from baserow.contrib.database.airtable.constants import ( from baserow.contrib.database.airtable.registry import ( AirtableColumnType, airtable_column_type_registry, + airtable_view_type_registry, ) from baserow.contrib.database.application_types import DatabaseApplicationType from baserow.contrib.database.export_serialized import DatabaseExportSerializedStructure from baserow.contrib.database.fields.field_types import FieldType, field_type_registry from baserow.contrib.database.fields.models import Field from baserow.contrib.database.models import Database -from baserow.contrib.database.views.models import GridView -from baserow.contrib.database.views.registries import view_type_registry from baserow.core.export_serialized import CoreExportSerializedStructure from baserow.core.handler import CoreHandler from baserow.core.models import Workspace from baserow.core.registries import ImportExportConfig -from baserow.core.utils import ChildProgressBuilder, remove_invalid_surrogate_characters +from baserow.core.utils import ( + ChildProgressBuilder, + Progress, + remove_invalid_surrogate_characters, +) from .config import AirtableImportConfig from .exceptions import ( AirtableBaseNotPublic, AirtableImportNotRespectingConfig, AirtableShareIsNotABase, + AirtableSkipCellValue, ) from .import_report import ( ERROR_TYPE_UNSUPPORTED_FEATURE, @@ -48,6 +55,7 @@ from .import_report import ( SCOPE_VIEW, AirtableImportReport, ) +from .utils import parse_json_and_remove_invalid_surrogate_characters User = get_user_model() @@ -79,7 +87,7 @@ class AirtableHandler: :return: The request ID, initial data and the cookies of the response. """ - url = f"https://airtable.com/{share_id}" + url = f"{AIRTABLE_BASE_URL}/{share_id}" response = requests.get(url, headers=BASE_HEADERS) # nosec B113 if not response.ok: @@ -102,6 +110,44 @@ class AirtableHandler: return request_id, init_data, cookies + @staticmethod + def make_airtable_request(init_data: dict, request_id: str, **kwargs) -> Response: + """ + Helper method to make a valid request to to Airtable with the correct headers + and params. + + :param init_data: The init_data returned by the initially requested shared base. + :param request_id: The request_id returned by the initially requested shared + base. + :param kwargs: THe kwargs that must be passed into the `requests.get` method. + :return: The requests Response object related to the request. + """ + + application_id = list(init_data["rawApplications"].keys())[0] + client_code_version = init_data["codeVersion"] + page_load_id = init_data["pageLoadId"] + access_policy = json.loads(init_data["accessPolicy"]) + + params = kwargs.get("params", {}) + params["accessPolicy"] = json.dumps(access_policy) + params["request_id"] = request_id + + return requests.get( + headers={ + "x-airtable-application-id": application_id, + "x-airtable-client-queue-time": "45", + "x-airtable-inter-service-client": "webClient", + "x-airtable-inter-service-client-code-version": client_code_version, + "x-airtable-page-load-id": page_load_id, + "X-Requested-With": "XMLHttpRequest", + "x-time-zone": "Europe/Amsterdam", + "x-user-locale": "en", + **BASE_HEADERS, + }, + timeout=3 * 60, # it can take quite a while for Airtable to respond. + **kwargs, + ) # nosec + @staticmethod def fetch_table_data( table_id: str, @@ -135,43 +181,63 @@ class AirtableHandler: """ application_id = list(init_data["rawApplications"].keys())[0] - client_code_version = init_data["codeVersion"] - page_load_id = init_data["pageLoadId"] - stringified_object_params = { "includeDataForViewIds": None, "shouldIncludeSchemaChecksum": True, "mayOnlyIncludeRowAndCellDataForIncludedViews": False, } - access_policy = json.loads(init_data["accessPolicy"]) if fetch_application_structure: stringified_object_params["includeDataForTableIds"] = [table_id] - url = f"https://airtable.com/v0.3/application/{application_id}/read" + url = f"{AIRTABLE_API_BASE_URL}/application/{application_id}/read" else: - url = f"https://airtable.com/v0.3/table/{table_id}/readData" + url = f"{AIRTABLE_API_BASE_URL}/table/{table_id}/readData" - response = requests.get( + response = AirtableHandler.make_airtable_request( + init_data, + request_id, url=url, stream=stream, params={ "stringifiedObjectParams": json.dumps(stringified_object_params), - "requestId": request_id, - "accessPolicy": json.dumps(access_policy), - }, - headers={ - "x-airtable-application-id": application_id, - "x-airtable-client-queue-time": "45", - "x-airtable-inter-service-client": "webClient", - "x-airtable-inter-service-client-code-version": client_code_version, - "x-airtable-page-load-id": page_load_id, - "X-Requested-With": "XMLHttpRequest", - "x-time-zone": "Europe/Amsterdam", - "x-user-locale": "en", - **BASE_HEADERS, }, cookies=cookies, - ) # nosec B113 + ) + return response + + @staticmethod + def fetch_view_data( + view_id: str, + init_data: dict, + request_id: str, + cookies: dict, + stream=True, + ) -> Response: + """ + :param view_id: The Airtable view id that must be fetched. The id starts with + `viw`. + :param init_data: The init_data returned by the initially requested shared base. + :param request_id: The request_id returned by the initially requested shared + base. + :param cookies: The cookies dict returned by the initially requested shared + base. + :param stream: Indicates whether the request should be streamed. This could be + useful if we want to show a progress bar. It will directly be passed into + the `requests` request. + :return: The `requests` response containing the result. + """ + + stringified_object_params = {} + url = f"{AIRTABLE_API_BASE_URL}/view/{view_id}/readData" + + response = AirtableHandler.make_airtable_request( + init_data, + request_id, + url=url, + stream=stream, + params={"stringifiedObjectParams": json.dumps(stringified_object_params)}, + cookies=cookies, + ) return response @staticmethod @@ -247,6 +313,7 @@ class AirtableHandler: baserow_field.pk = 0 baserow_field.name = column["name"] baserow_field.order = order + baserow_field.description = column.get("description", None) or None baserow_field.primary = ( baserow_field_type.can_be_primary_field(baserow_field) and table["primaryColumnId"] == column["id"] @@ -305,25 +372,42 @@ class AirtableHandler: # Some empty rows don't have the `cellValuesByColumnId` property because it # doesn't contain values, hence the fallback to prevent failing hard. cell_values = row.get("cellValuesByColumnId", {}) - for column_id, column_value in cell_values.items(): - if column_id not in column_mapping: - continue - mapping_values = column_mapping[column_id] - baserow_serialized_value = mapping_values[ - "airtable_column_type" - ].to_baserow_export_serialized_value( + for column_id, mapping_values in column_mapping.items(): + airtable_column_type = mapping_values["airtable_column_type"] + args = [ row_id_mapping, table, row, mapping_values["raw_airtable_column"], mapping_values["baserow_field"], - column_value, + cell_values.get(column_id, None), files_to_download, config, import_report, - ) - exported_row[f"field_{column_id}"] = baserow_serialized_value + ] + + try: + # The column_id typically doesn't exist in the `cell_values` if the + # value is empty in Airtable. + if column_id in cell_values: + baserow_serialized_value = ( + airtable_column_type.to_baserow_export_serialized_value(*args) + ) + else: + # remove the cell_value because that one is not accepted in the args + # of this method. + args.pop(5) + baserow_serialized_value = ( + airtable_column_type.to_baserow_export_empty_value(*args) + ) + exported_row[f"field_{column_id}"] = baserow_serialized_value + except AirtableSkipCellValue: + # If the `AirtableSkipCellValue` is raised, then the cell value must + # not be included in the export. This is the default behavior for + # `to_baserow_export_empty_value`, but in some cases, a specific empty + # value must be returned. + pass return exported_row @@ -375,6 +459,243 @@ class AirtableHandler: return files_buffer + @classmethod + def _parse_table_fields( + cls, + schema: dict, + converting_progress: Progress, + config: AirtableImportConfig, + import_report: AirtableImportReport, + ): + field_mapping_per_table = {} + for table_index, table in enumerate(schema["tableSchemas"]): + field_mapping = {} + + # Loop over all the columns in the table and try to convert them to Baserow + # format. + primary = None + for column in table["columns"]: + ( + baserow_field, + baserow_field_type, + airtable_column_type, + ) = cls.to_baserow_field(table, column, config, import_report) + converting_progress.increment(state=AIRTABLE_EXPORT_JOB_CONVERTING) + + # None means that none of the field types know how to parse this field, + # so we must ignore it. + if baserow_field is None: + import_report.add_failed( + column["name"], + SCOPE_FIELD, + table["name"], + ERROR_TYPE_UNSUPPORTED_FEATURE, + f"""Field "{column['name']}" with field type {column["type"]} was not imported because it is not supported.""", + ) + continue + + # The `baserow_field` is returning it it's specific form, but it doesn't + # have the `content_type` property yet. This breaks all the `.specific` + # behavior because an `id` is also not set. + baserow_field.content_type = ContentType.objects.get_for_model( + baserow_field + ) + + # Construct a mapping where the Airtable column id is the key and the + # value contains the raw Airtable column values, Baserow field and + # the Baserow field type object for later use. + field_mapping[column["id"]] = { + "baserow_field": baserow_field, + "baserow_field_type": baserow_field_type, + "raw_airtable_column": column, + "airtable_column_type": airtable_column_type, + } + if baserow_field.primary: + primary = baserow_field + + # There is always a primary field, but it could be that it's not compatible + # with Baserow. In that case, we need to find an alternative field, or + # create a new one. + if primary is None: + # First check if another field can act as the primary field type. + found_existing_field = False + for value in field_mapping.values(): + if field_type_registry.get_by_model( + value["baserow_field"] + ).can_be_primary_field(value["baserow_field"]): + value["baserow_field"].primary = True + found_existing_field = True + import_report.add_failed( + value["baserow_field"].name, + SCOPE_FIELD, + table["name"], + ERROR_TYPE_UNSUPPORTED_FEATURE, + f"""Changed primary field to "{value["baserow_field"].name}" because the original primary field is incompatible.""", + ) + break + + # If none of the existing fields can be primary, we will add a new + # text field. + if not found_existing_field: + airtable_column = { + "id": "primary_field", + "name": "Primary field (auto created)", + "type": "text", + } + ( + baserow_field, + baserow_field_type, + airtable_column_type, + ) = cls.to_baserow_field( + table, airtable_column, config, import_report + ) + baserow_field.primary = True + baserow_field.content_type = ContentType.objects.get_for_model( + baserow_field + ) + field_mapping["primary_id"] = { + "baserow_field": baserow_field, + "baserow_field_type": baserow_field_type, + "raw_airtable_column": airtable_column, + "airtable_column_type": airtable_column_type, + } + import_report.add_failed( + baserow_field.name, + SCOPE_FIELD, + table["name"], + ERROR_TYPE_UNSUPPORTED_FEATURE, + f"""Created new primary field "{baserow_field.name}" because none of the provided fields are compatible.""", + ) + + field_mapping_per_table[table["id"]] = field_mapping + + # Loop over all created fields, and post process them if needed. This is for + # example needed for the link row field where the object must be enhanced with + # the primary field of the related tables. + for table_index, table in enumerate(schema["tableSchemas"]): + field_mapping = field_mapping_per_table[table["id"]] + + for field_object in field_mapping.values(): + field_object["airtable_column_type"].after_field_objects_prepared( + field_mapping_per_table, + field_object["baserow_field"], + field_object["raw_airtable_column"], + ) + + return field_mapping_per_table + + @classmethod + def _parse_rows_and_views( + cls, + schema: dict, + tables: list, + converting_progress: Progress, + row_id_mapping: Dict[str, int], + field_mapping_per_table: dict, + config: AirtableImportConfig, + import_report: AirtableImportReport, + ): + # A list containing all the exported table in Baserow format. + exported_tables = [] + + # A dict containing all the user files that must be downloaded and added to a + # zip file. + files_to_download = {} + + # Loop over the table one more time to export the fields, rows, and views to + # the serialized format. This must be done last after all the data is prepared + # correctly. + for table_index, table in enumerate(schema["tableSchemas"]): + field_mapping = field_mapping_per_table[table["id"]] + files_to_download_for_table = {} + + # Loop over all the fields and convert them to Baserow serialized format. + exported_fields = [ + value["baserow_field_type"].export_serialized(value["baserow_field"]) + for value in field_mapping.values() + ] + + # Loop over all the rows in the table and convert them to Baserow format. We + # need to provide the `row_id_mapping` and `field_mapping` because there + # could be references to other rows and fields. the + # `files_to_download_for_table` is needed because every value could be + # depending on additional files that must later be downloaded. + exported_rows = [] + for row_index, row in enumerate(tables[table["id"]]["rows"]): + exported_rows.append( + cls.to_baserow_row_export( + table, + row_id_mapping, + field_mapping, + row, + row_index, + files_to_download_for_table, + config, + import_report, + ) + ) + converting_progress.increment(state=AIRTABLE_EXPORT_JOB_CONVERTING) + + # Loop over all views to add them to them as failed to the import report + # because the views are not yet supported. + exported_views = [] + for view in table["views"]: + table_data = tables[table["id"]] + view_data = next( + ( + view_data + for view_data in table_data["viewDatas"] + if view_data["id"] == view["id"] + ) + ) + serialized_view = ( + airtable_view_type_registry.from_airtable_view_to_serialized( + field_mapping, + row_id_mapping, + table, + view, + view_data, + config, + import_report, + ) + ) + + if serialized_view is None: + import_report.add_failed( + view["name"], + SCOPE_VIEW, + table["name"], + ERROR_TYPE_UNSUPPORTED_FEATURE, + f"View \"{view['name']}\" was not imported because " + f"{view['type']} is not supported.", + ) + continue + + exported_views.append(serialized_view) + + exported_table = DatabaseExportSerializedStructure.table( + id=table["id"], + name=table["name"], + order=table_index, + fields=exported_fields, + views=exported_views, + rows=exported_rows, + data_sync=None, + ) + exported_tables.append(exported_table) + converting_progress.increment(state=AIRTABLE_EXPORT_JOB_CONVERTING) + + # Airtable has a mapping of signed URLs for the uploaded files. The + # mapping is provided in the table payload, and if it exists, we need + # that URL for download instead of the one originally provided. + signed_user_content_urls = tables[table["id"]]["signedUserContentUrls"] + for file_name, url in files_to_download_for_table.items(): + if url in signed_user_content_urls: + url = signed_user_content_urls[url] + files_to_download[file_name] = url + + return exported_tables, files_to_download + @classmethod def to_baserow_database_export( cls, @@ -389,9 +710,6 @@ class AirtableHandler: Converts the provided raw Airtable database dict to a Baserow export format and an in memory zip file containing all the downloaded user files. - @TODO add the views. - @TODO preserve the order of least one view. - :param init_data: The init_data, extracted from the initial page related to the shared base. :param schema: An object containing the schema of the Airtable base. @@ -430,13 +748,6 @@ class AirtableHandler: ), ) - # A list containing all the exported table in Baserow format. - exported_tables = [] - - # A dict containing all the user files that must be downloaded and added to a - # zip file. - files_to_download = {} - # A mapping containing the Airtable table id as key and as value another mapping # containing with the key as Airtable row id and the value as new Baserow row # id. This mapping is created because Airtable has string row id that look like @@ -451,151 +762,18 @@ class AirtableHandler: row["id"] = new_id converting_progress.increment(state=AIRTABLE_EXPORT_JOB_CONVERTING) - view_id = 0 - for table_index, table in enumerate(schema["tableSchemas"]): - field_mapping = {} - files_to_download_for_table = {} - - # Loop over all the columns in the table and try to convert them to Baserow - # format. - primary = None - for column in table["columns"]: - ( - baserow_field, - baserow_field_type, - airtable_column_type, - ) = cls.to_baserow_field(table, column, config, import_report) - converting_progress.increment(state=AIRTABLE_EXPORT_JOB_CONVERTING) - - # None means that none of the field types know how to parse this field, - # so we must ignore it. - if baserow_field is None: - import_report.add_failed( - column["name"], - SCOPE_FIELD, - table["name"], - ERROR_TYPE_UNSUPPORTED_FEATURE, - f"""Field "{column['name']}" with field type {column["type"]} was not imported because it is not supported.""", - ) - continue - - # Construct a mapping where the Airtable column id is the key and the - # value contains the raw Airtable column values, Baserow field and - # the Baserow field type object for later use. - field_mapping[column["id"]] = { - "baserow_field": baserow_field, - "baserow_field_type": baserow_field_type, - "raw_airtable_column": column, - "airtable_column_type": airtable_column_type, - } - if baserow_field.primary: - primary = baserow_field - - if primary is None: - # First check if another field can act as the primary field type. - found_existing_field = False - for value in field_mapping.values(): - if field_type_registry.get_by_model( - value["baserow_field"] - ).can_be_primary_field(value["baserow_field"]): - value["baserow_field"].primary = True - found_existing_field = True - break - - # If none of the existing fields can be primary, we will add a new - # text field. - if not found_existing_field: - airtable_column = { - "id": "primary_field", - "name": "Primary field (auto created)", - "type": "text", - } - ( - baserow_field, - baserow_field_type, - airtable_column_type, - ) = cls.to_baserow_field( - table, airtable_column, config, import_report - ) - baserow_field.primary = True - field_mapping["primary_id"] = { - "baserow_field": baserow_field, - "baserow_field_type": baserow_field_type, - "raw_airtable_column": airtable_column, - "airtable_column_type": airtable_column_type, - } - - # Loop over all the fields and convert them to Baserow serialized format. - exported_fields = [ - value["baserow_field_type"].export_serialized(value["baserow_field"]) - for value in field_mapping.values() - ] - - # Loop over all the rows in the table and convert them to Baserow format. We - # need to provide the `row_id_mapping` and `field_mapping` because there - # could be references to other rows and fields. the - # `files_to_download_for_table` is needed because every value could be - # depending on additional files that must later be downloaded. - exported_rows = [] - for row_index, row in enumerate(tables[table["id"]]["rows"]): - exported_rows.append( - cls.to_baserow_row_export( - table, - row_id_mapping, - field_mapping, - row, - row_index, - files_to_download_for_table, - config, - import_report, - ) - ) - converting_progress.increment(state=AIRTABLE_EXPORT_JOB_CONVERTING) - - # Create an empty grid view because the importing of views doesn't work - # yet. It's a bit quick and dirty, but it will be replaced soon. - grid_view = GridView(pk=0, id=None, name="Grid", order=1) - grid_view.get_field_options = lambda *args, **kwargs: [] - grid_view_type = view_type_registry.get_by_model(grid_view) - empty_serialized_grid_view = grid_view_type.export_serialized( - grid_view, None, None, None - ) - view_id += 1 - empty_serialized_grid_view["id"] = view_id - exported_views = [empty_serialized_grid_view] - - # Loop over all views to add them to them as failed to the import report - # because the views are not yet supported. - for view in table["views"]: - import_report.add_failed( - view["name"], - SCOPE_VIEW, - table["name"], - ERROR_TYPE_UNSUPPORTED_FEATURE, - f"View \"{view['name']}\" was not imported because views are not " - f"yet supported during import.", - ) - - exported_table = DatabaseExportSerializedStructure.table( - id=table["id"], - name=table["name"], - order=table_index, - fields=exported_fields, - views=exported_views, - rows=exported_rows, - data_sync=None, - ) - exported_tables.append(exported_table) - converting_progress.increment(state=AIRTABLE_EXPORT_JOB_CONVERTING) - - # Airtable has a mapping of signed URLs for the uploaded files. The - # mapping is provided in the table payload, and if it exists, we need - # that URL for download instead of the one originally provided. - signed_user_content_urls = tables[table["id"]]["signedUserContentUrls"] - for file_name, url in files_to_download_for_table.items(): - if url in signed_user_content_urls: - url = signed_user_content_urls[url] - files_to_download[file_name] = url + field_mapping_per_table = AirtableHandler._parse_table_fields( + schema, converting_progress, config, import_report + ) + exported_tables, files_to_download = AirtableHandler._parse_rows_and_views( + schema, + tables, + converting_progress, + row_id_mapping, + field_mapping_per_table, + config, + import_report, + ) # Just to be really clear that the automations and interfaces are not included. import_report.add_failed( @@ -643,6 +821,98 @@ class AirtableHandler: return exported_database, user_files_zip + @classmethod + def fetch_and_combine_airtable_data( + cls, + share_id: str, + progress_builder: Optional[ChildProgressBuilder] = None, + ) -> Union[dict, dict, list]: + """ + @TODO docs + + :param share_id: The shared Airtable ID of which the data must be fetched. + :param progress_builder: If provided will be used to build a child progress bar + and report on this methods progress to the parent of the progress_builder. + :return: The fetched init_data, schema, and list of tables enrichted with all + the row and view data. + """ + + progress = ChildProgressBuilder.build(progress_builder, child_total=100) + + # Execute the initial request to obtain the initial data that's needed to + # make the request. + request_id, init_data, cookies = cls.fetch_publicly_shared_base(share_id) + progress.increment(state=AIRTABLE_EXPORT_JOB_DOWNLOADING_BASE) + + # Loop over all the tables and make a request for each table to obtain the raw + # Airtable table data. + tables = [] + raw_tables = list( + init_data["singleApplicationScaffoldingData"]["tableById"].keys() + ) + for index, table_id in enumerate( + progress.track( + represents_progress=49, + state=AIRTABLE_EXPORT_JOB_DOWNLOADING_BASE, + iterable=raw_tables, + ) + ): + response = cls.fetch_table_data( + table_id=table_id, + init_data=init_data, + request_id=request_id, + cookies=cookies, + # At least one request must also fetch the application structure that + # contains the schema of all the tables, so we do this for the first + # table. + fetch_application_structure=index == 0, + stream=False, + ) + json_decoded_content = parse_json_and_remove_invalid_surrogate_characters( + response + ) + + tables.append(json_decoded_content) + + # Split database schema from the tables because we need this to be separated + # later on. + schema, tables = cls.extract_schema(tables) + + # Collect which for which view the data is missing, so that they can be + # fetched while respecting the progress afterward. + view_data_to_fetch = [] + for table in schema["tableSchemas"]: + existing_view_data = [ + view_data["id"] for view_data in tables[table["id"]]["viewDatas"] + ] + for view in table["views"]: + # Skip the view data that has already been loaded. + if view["id"] in existing_view_data: + continue + + view_data_to_fetch.append((table["id"], view["id"])) + + # Fetch the missing view data, and add them to the table object so that we have + # a complete object. + for table_id, view_id in progress.track( + represents_progress=50, + state=AIRTABLE_EXPORT_JOB_DOWNLOADING_BASE, + iterable=view_data_to_fetch, + ): + response = cls.fetch_view_data( + view_id=view_id, + init_data=init_data, + request_id=request_id, + cookies=cookies, + stream=False, + ) + json_decoded_content = parse_json_and_remove_invalid_surrogate_characters( + response + ) + tables[table_id]["viewDatas"].append(json_decoded_content["data"]) + + return init_data, schema, tables + @classmethod def import_from_airtable_to_workspace( cls, @@ -650,7 +920,7 @@ class AirtableHandler: share_id: str, storage: Optional[Storage] = None, progress_builder: Optional[ChildProgressBuilder] = None, - download_files_buffer: Union[None, IOBase] = None, + download_files_buffer: Optional[IOBase] = None, config: Optional[AirtableImportConfig] = None, ) -> Database: """ @@ -674,52 +944,10 @@ class AirtableHandler: progress = ChildProgressBuilder.build(progress_builder, child_total=1000) - # Execute the initial request to obtain the initial data that's needed to - # make the request. - request_id, init_data, cookies = cls.fetch_publicly_shared_base(share_id) - progress.increment(state=AIRTABLE_EXPORT_JOB_DOWNLOADING_BASE) - - # Loop over all the tables and make a request for each table to obtain the raw - # Airtable table data. - tables = [] - raw_tables = list( - init_data["singleApplicationScaffoldingData"]["tableById"].keys() + init_data, schema, tables = AirtableHandler.fetch_and_combine_airtable_data( + share_id, + progress.create_child_builder(represents_progress=100), ) - for index, table_id in enumerate( - progress.track( - represents_progress=99, - state=AIRTABLE_EXPORT_JOB_DOWNLOADING_BASE, - iterable=raw_tables, - ) - ): - response = cls.fetch_table_data( - table_id=table_id, - init_data=init_data, - request_id=request_id, - cookies=cookies, - # At least one request must also fetch the application structure that - # contains the schema of all the tables, so we do this for the first - # table. - fetch_application_structure=index == 0, - stream=False, - ) - try: - decoded_content = remove_invalid_surrogate_characters( - response.content, response.encoding - ) - json_decoded_content = json.loads(decoded_content) - except json.decoder.JSONDecodeError: - # In some cases, the `remove_invalid_surrogate_characters` results in - # invalid JSON. It's not completely clear why that is, but this - # fallback can still produce valid JSON to import in most cases if - # the original json didn't contain invalid surrogate characters. - json_decoded_content = response.json() - - tables.append(json_decoded_content) - - # Split database schema from the tables because we need this to be separated - # later on. - schema, tables = cls.extract_schema(tables) # Convert the raw Airtable data to Baserow export format so we can import that # later. diff --git a/backend/src/baserow/contrib/database/airtable/helpers.py b/backend/src/baserow/contrib/database/airtable/helpers.py index e2e2ba594..123d523d3 100644 --- a/backend/src/baserow/contrib/database/airtable/helpers.py +++ b/backend/src/baserow/contrib/database/airtable/helpers.py @@ -17,6 +17,10 @@ def import_airtable_date_type_options(type_options) -> dict: } +def to_import_select_option_id(field_id, choice_id): + return f"{field_id}_{choice_id}" + + def import_airtable_choices(field_id: str, type_options: dict) -> List[SelectOption]: order = type_options.get("choiceOrder", []) choices = type_options.get("choices", []) @@ -24,7 +28,7 @@ def import_airtable_choices(field_id: str, type_options: dict) -> List[SelectOpt SelectOption( # Combine select id with choice id as choice id is not guaranteed to be # unique across table - id=f"{field_id}_{choice['id']}", + id=to_import_select_option_id(field_id, choice["id"]), value=choice["name"], color=AIRTABLE_BASEROW_COLOR_MAPPING.get( # The color isn't always provided, hence the fallback to an empty diff --git a/backend/src/baserow/contrib/database/airtable/import_report.py b/backend/src/baserow/contrib/database/airtable/import_report.py index fb601e097..907a2e88f 100644 --- a/backend/src/baserow/contrib/database/airtable/import_report.py +++ b/backend/src/baserow/contrib/database/airtable/import_report.py @@ -16,13 +16,41 @@ from baserow.core.constants import BASEROW_COLORS SCOPE_FIELD = SelectOption(id="scope_field", value="Field", color="light-blue", order=1) SCOPE_CELL = SelectOption(id="scope_cell", value="Cell", color="light-green", order=2) SCOPE_VIEW = SelectOption(id="scope_view", value="View", color="light-cyan", order=3) +SCOPE_VIEW_SORT = SelectOption( + id="scope_view_sort", value="View sort", color="light-red", order=4 +) +SCOPE_VIEW_GROUP_BY = SelectOption( + id="scope_view_group_by", value="View group by", color="light-brown", order=5 +) +SCOPE_VIEW_FILTER = SelectOption( + id="scope_view_filter", value="View filter", color="light-pink", order=6 +) +SCOPE_VIEW_COLOR = SelectOption( + id="scope_view_color", value="View color", color="light-gray", order=7 +) +SCOPE_VIEW_FIELD_OPTIONS = SelectOption( + id="scope_view_field_options", + value="View field options", + color="light-purple", + order=8, +) SCOPE_AUTOMATIONS = SelectOption( - id="scope_automations", value="Automations", color="light-orange", order=4 + id="scope_automations", value="Automations", color="light-orange", order=9 ) SCOPE_INTERFACES = SelectOption( - id="scope_interfaces", value="Interfaces", color="light-yellow", order=5 + id="scope_interfaces", value="Interfaces", color="light-yellow", order=10 ) -ALL_SCOPES = [SCOPE_FIELD, SCOPE_CELL, SCOPE_VIEW, SCOPE_AUTOMATIONS, SCOPE_INTERFACES] +ALL_SCOPES = [ + SCOPE_FIELD, + SCOPE_CELL, + SCOPE_VIEW, + SCOPE_VIEW_SORT, + SCOPE_VIEW_GROUP_BY, + SCOPE_VIEW_FILTER, + SCOPE_VIEW_COLOR, + SCOPE_AUTOMATIONS, + SCOPE_INTERFACES, +] ERROR_TYPE_UNSUPPORTED_FEATURE = SelectOption( id="error_type_unsupported_feature", diff --git a/backend/src/baserow/contrib/database/airtable/registry.py b/backend/src/baserow/contrib/database/airtable/registry.py index cea8fce7f..f4b11c538 100644 --- a/backend/src/baserow/contrib/database/airtable/registry.py +++ b/backend/src/baserow/contrib/database/airtable/registry.py @@ -1,9 +1,55 @@ -from datetime import tzinfo -from typing import Any, Dict, Tuple, Union +from typing import Any, Dict, List, Optional, Tuple, Union + +from baserow_premium.views.decorator_types import LeftBorderColorDecoratorType +from baserow_premium.views.decorator_value_provider_types import ( + ConditionalColorValueProviderType, + SelectColorValueProviderType, +) from baserow.contrib.database.airtable.config import AirtableImportConfig -from baserow.contrib.database.airtable.import_report import AirtableImportReport +from baserow.contrib.database.airtable.constants import ( + AIRTABLE_ASCENDING_MAP, + AIRTABLE_BASEROW_COLOR_MAPPING, +) +from baserow.contrib.database.airtable.exceptions import ( + AirtableSkipCellValue, + AirtableSkipFilter, +) +from baserow.contrib.database.airtable.import_report import ( + ERROR_TYPE_DATA_TYPE_MISMATCH, + ERROR_TYPE_UNSUPPORTED_FEATURE, + SCOPE_FIELD, + SCOPE_VIEW_COLOR, + SCOPE_VIEW_FILTER, + SCOPE_VIEW_GROUP_BY, + SCOPE_VIEW_SORT, + AirtableImportReport, +) +from baserow.contrib.database.airtable.utils import ( + get_airtable_column_name, + unknown_value_to_human_readable, +) +from baserow.contrib.database.fields.field_filters import ( + FILTER_TYPE_AND, + FILTER_TYPE_OR, +) from baserow.contrib.database.fields.models import Field +from baserow.contrib.database.views.models import ( + DEFAULT_SORT_TYPE_KEY, + SORT_ORDER_ASC, + SORT_ORDER_DESC, + View, + ViewDecoration, + ViewFilter, + ViewFilterGroup, + ViewGroupBy, + ViewSort, +) +from baserow.contrib.database.views.registries import ( + ViewFilterType, + ViewType, + view_type_registry, +) from baserow.core.registry import Instance, Registry @@ -12,7 +58,6 @@ class AirtableColumnType(Instance): self, raw_airtable_table: dict, raw_airtable_column: dict, - timezone: tzinfo, config: AirtableImportConfig, import_report: AirtableImportReport, ) -> Union[Field, None]: @@ -34,6 +79,18 @@ class AirtableColumnType(Instance): raise NotImplementedError("The `to_baserow_field` must be implemented.") + def after_field_objects_prepared( + self, + field_mapping_per_table: Dict[str, Dict[str, Any]], + baserow_field: Field, + raw_airtable_column: dict, + ): + """ + Hook that is called after all field objects of all tables are prepared. This + allows to do some post-processing on the fields in case they depend on each + other. + """ + def to_baserow_export_serialized_value( self, row_id_mapping: Dict[str, Dict[str, int]], @@ -70,6 +127,40 @@ class AirtableColumnType(Instance): return value + def to_baserow_export_empty_value( + self, + row_id_mapping: Dict[str, Dict[str, int]], + raw_airtable_table: dict, + raw_airtable_row: dict, + raw_airtable_column: dict, + baserow_field: Field, + files_to_download: Dict[str, str], + config: AirtableImportConfig, + import_report: AirtableImportReport, + ): + # By default, raise the `AirtableSkipCellValue` so that the value is not + # included in the export. + raise AirtableSkipCellValue + + def add_import_report_failed_if_default_is_provided( + self, + raw_airtable_table: dict, + raw_airtable_column: dict, + import_report: AirtableImportReport, + to_human_readable_default=(lambda x: x), + ): + default = raw_airtable_column.get("default", "") + if default: + default = to_human_readable_default(default) + import_report.add_failed( + raw_airtable_column["name"], + SCOPE_FIELD, + raw_airtable_table.get("name", ""), + ERROR_TYPE_UNSUPPORTED_FEATURE, + f"The field was imported, but the default value " + f"{default} was dropped because that's not supported in Baserow.", + ) + class AirtableColumnTypeRegistry(Registry): name = "airtable_column" @@ -109,6 +200,699 @@ class AirtableColumnTypeRegistry(Registry): return None, None +class AirtableViewType(Instance): + baserow_view_type: Optional[str] = None + + def get_sorts( + self, + field_mapping: dict, + view_type: ViewType, + raw_airtable_table: dict, + raw_airtable_view: dict, + raw_airtable_view_data: dict, + import_report: AirtableImportReport, + ) -> List[ViewSort]: + """ + Maps the sorts from the raw Airtable view data to a list of Baserow + compatible ViewSort objects. + """ + + last_sorts_applied = raw_airtable_view_data.get("lastSortsApplied", None) + + if not view_type.can_sort or last_sorts_applied is None: + return [] + + sort_set = last_sorts_applied.get("sortSet", None) or [] + + view_sorts = [] + for sort in sort_set: + if sort["columnId"] not in field_mapping: + column_name = get_airtable_column_name( + raw_airtable_table, sort["columnId"] + ) + import_report.add_failed( + f'View "{raw_airtable_view["name"]}", Field ID "{column_name}"', + SCOPE_VIEW_SORT, + raw_airtable_table["name"], + ERROR_TYPE_UNSUPPORTED_FEATURE, + f'The sort on field "{column_name}" was ignored in view' + f' {raw_airtable_view["name"]} because the field is not imported.', + ) + continue + + mapping_entry = field_mapping[sort["columnId"]] + baserow_field_type = mapping_entry["baserow_field_type"] + baserow_field = mapping_entry["baserow_field"] + can_order_by = baserow_field_type.check_can_order_by( + baserow_field, DEFAULT_SORT_TYPE_KEY + ) + + if not can_order_by: + import_report.add_failed( + f'View "{raw_airtable_view["name"]}", Field "{baserow_field.name}"', + SCOPE_VIEW_SORT, + raw_airtable_table["name"], + ERROR_TYPE_UNSUPPORTED_FEATURE, + f'The sort on field "{baserow_field.name}" was ignored in view' + f' {raw_airtable_view["name"]} because it\'s not possible to ' + f"order by that field type.", + ) + continue + + view_sort = ViewSort( + id=sort["id"], + field_id=sort["columnId"], + order=SORT_ORDER_ASC if sort["ascending"] else SORT_ORDER_DESC, + ) + view_sorts.append(view_sort) + + return view_sorts + + def get_group_bys( + self, + field_mapping: dict, + view_type: ViewType, + raw_airtable_table: dict, + raw_airtable_view: dict, + raw_airtable_view_data: dict, + import_report: AirtableImportReport, + ) -> List[ViewGroupBy]: + """ + Maps the group bys from the raw Airtable view data to a list of Baserow + compatible ViewGroupBy objects. + """ + + group_levels = raw_airtable_view_data.get("groupLevels", None) + + if not view_type.can_sort or group_levels is None: + return [] + + view_group_by = [] + for group in group_levels: + if group["columnId"] not in field_mapping: + column_name = get_airtable_column_name( + raw_airtable_table, group["columnId"] + ) + import_report.add_failed( + f'View "{raw_airtable_view["name"]}", Field ID "{column_name}"', + SCOPE_VIEW_GROUP_BY, + raw_airtable_table["name"], + ERROR_TYPE_UNSUPPORTED_FEATURE, + f'The group by on field "{column_name}" was ignored in view' + f' {raw_airtable_view["name"]} because the field was not imported.', + ) + continue + + mapping_entry = field_mapping[group["columnId"]] + baserow_field_type = mapping_entry["baserow_field_type"] + baserow_field = mapping_entry["baserow_field"] + can_order_by = baserow_field_type.check_can_group_by( + baserow_field, DEFAULT_SORT_TYPE_KEY + ) + + if not can_order_by: + import_report.add_failed( + f'View "{raw_airtable_view["name"]}", Field "{baserow_field.name}"', + SCOPE_VIEW_GROUP_BY, + raw_airtable_table["name"], + ERROR_TYPE_UNSUPPORTED_FEATURE, + f'The group by on field "{baserow_field.name}" was ignored in view {raw_airtable_view["name"]} because it\'s not possible to group by that field type.', + ) + continue + + ascending = AIRTABLE_ASCENDING_MAP.get(group["order"], None) + + if ascending is None: + import_report.add_failed( + f'View "{raw_airtable_view["name"]}", Field "{baserow_field.name}"', + SCOPE_VIEW_GROUP_BY, + raw_airtable_table["name"], + ERROR_TYPE_UNSUPPORTED_FEATURE, + f'The group by on field "{baserow_field.name}" was ignored in view {raw_airtable_view["name"]} because the order {group["order"]} is incompatible.', + ) + continue + + view_group = ViewGroupBy( + id=group["id"], + field_id=group["columnId"], + order=SORT_ORDER_ASC if ascending else SORT_ORDER_DESC, + ) + view_group_by.append(view_group) + + return view_group_by + + def get_filter( + self, + field_mapping: dict, + row_id_mapping: Dict[str, Dict[str, int]], + raw_airtable_view: dict, + raw_airtable_table: dict, + import_report: AirtableImportReport, + filter_object: dict, + parent_group: Optional[ViewFilterGroup] = None, + ): + """ + This method converts a raw airtable filter object into a Baserow filter object + that's ready for the export system. + """ + + # If it's not a group, then it's an individual filter, and it must be + # parsed accordingly. + if filter_object["columnId"] not in field_mapping: + column_name = get_airtable_column_name( + raw_airtable_table, filter_object["columnId"] + ) + filter_value = unknown_value_to_human_readable(filter_object["value"]) + import_report.add_failed( + f'View "{raw_airtable_view["name"]}", Field ID "{column_name}"', + SCOPE_VIEW_FILTER, + raw_airtable_table["name"], + ERROR_TYPE_UNSUPPORTED_FEATURE, + f'The "{filter_object["operator"]}" filter with value ' + f'"{filter_value}" on field "{column_name}" was ignored ' + f'in view {raw_airtable_view["name"]} because the field was not ' + f"imported.", + ) + return None + + mapping_entry = field_mapping[filter_object["columnId"]] + baserow_field_type = mapping_entry["baserow_field_type"] + baserow_field = mapping_entry["baserow_field"] + raw_airtable_column = mapping_entry["raw_airtable_column"] + can_filter_by = baserow_field_type.check_can_filter_by(baserow_field) + + if not can_filter_by: + filter_value = unknown_value_to_human_readable(filter_object["value"]) + import_report.add_failed( + f'View "{raw_airtable_view["name"]}", Field "{baserow_field.name}"', + SCOPE_VIEW_FILTER, + raw_airtable_table["name"], + ERROR_TYPE_UNSUPPORTED_FEATURE, + f'The "{filter_object["operator"]}" filter with value ' + f'"{filter_value}" on field "{baserow_field.name}" was ' + f'ignored in view {raw_airtable_view["name"]} because it\'s not ' + f"possible to filter by that field type.", + ) + return None + + try: + filter_operator = airtable_filter_operator_registry.get( + filter_object["operator"] + ) + filter_type, value = filter_operator.to_baserow_filter_and_value( + row_id_mapping, + raw_airtable_table, + raw_airtable_column, + baserow_field, + import_report, + filter_object["value"], + ) + + if not filter_type.field_is_compatible(baserow_field): + raise AirtableSkipFilter + except ( + airtable_filter_operator_registry.does_not_exist_exception_class, + # If the `AirtableSkipFilter` exception is raised, then the Airtable + # filter existing, but is not compatible with the Baserow filters. This + # can be raised in the `to_baserow_filter_and_value`, but also if it + # appears to not be compatible afterward. + AirtableSkipFilter, + ): + filter_value = unknown_value_to_human_readable(filter_object["value"]) + import_report.add_failed( + f'View "{raw_airtable_view["name"]}", Field "{baserow_field.name}"', + SCOPE_VIEW_FILTER, + raw_airtable_table["name"], + ERROR_TYPE_UNSUPPORTED_FEATURE, + f'The "{filter_object["operator"]}" filter with value ' + f'"{filter_value}" on field "{baserow_field.name}" was ' + f'ignored in view {raw_airtable_view["name"]} because not no ' + f"compatible filter exists.", + ) + return None + + return ViewFilter( + id=filter_object["id"], + type=filter_type.type, + value=value, + field_id=filter_object["columnId"], + view_id=raw_airtable_view["id"], + group_id=parent_group.id if parent_group else None, + ) + + def get_filters( + self, + field_mapping: dict, + row_id_mapping: Dict[str, Dict[str, int]], + raw_airtable_view: dict, + raw_airtable_table: dict, + import_report: AirtableImportReport, + filter_object: dict, + filter_groups: Optional[List[ViewFilterGroup]] = None, + parent_group: Optional[ViewFilterGroup] = None, + ) -> Union[List[ViewFilter], List[ViewFilterGroup]]: + """ + Recursive method that either loops over the filters in the `filter_object`, and + converts it to two flat lists containing the Baserow ViewFilter and + ViewFilterGroup objects. + """ + + if filter_groups is None: + filter_groups = [] + + filters = [] + conjunction = filter_object.get("conjunction", None) + filter_set = filter_object.get("filterSet", None) + column_id = filter_object.get("columnId", None) + + if conjunction and filter_set: + # The filter_object is a nested structure, where if the `conjunction` and + # `filterSet` are in the object, it means that it's a filter group. + view_group = ViewFilterGroup( + # Specifically keep the id `None` for the root group because that + # doesn't exist in Baserow. + id=filter_object.get("id", None), + parent_group=parent_group, + filter_type=FILTER_TYPE_OR if conjunction == "or" else FILTER_TYPE_AND, + view_id=raw_airtable_view["id"], + ) + + if view_group not in filter_groups: + filter_groups.append(view_group) + + for child_filter in filter_set: + child_filters, _ = self.get_filters( + field_mapping, + row_id_mapping, + raw_airtable_view, + raw_airtable_table, + import_report, + child_filter, + filter_groups, + view_group, + ) + filters.extend(child_filters) + + return filters, filter_groups + elif column_id: + baserow_filter = self.get_filter( + field_mapping, + row_id_mapping, + raw_airtable_view, + raw_airtable_table, + import_report, + filter_object, + parent_group, + ) + + if baserow_filter is None: + return [], [] + else: + return [baserow_filter], [] + + return [], [] + + def get_select_column_decoration( + self, + field_mapping: dict, + view_type: ViewType, + row_id_mapping: Dict[str, Dict[str, int]], + raw_airtable_table: dict, + raw_airtable_view: dict, + raw_airtable_view_data: dict, + import_report: AirtableImportReport, + ) -> Optional[ViewDecoration]: + color_config = raw_airtable_view_data["colorConfig"] + select_column_id = color_config["selectColumnId"] + + if select_column_id not in field_mapping: + column_name = get_airtable_column_name(raw_airtable_table, select_column_id) + import_report.add_failed( + raw_airtable_view["name"], + SCOPE_VIEW_COLOR, + raw_airtable_table["name"], + ERROR_TYPE_DATA_TYPE_MISMATCH, + f'The select field coloring was ignored in {raw_airtable_view["name"]} ' + f"because {column_name} does not exist.", + ) + return None + + return ViewDecoration( + id=f"{raw_airtable_view['id']}_decoration", + view_id=raw_airtable_view["id"], + type=LeftBorderColorDecoratorType.type, + value_provider_type=SelectColorValueProviderType.type, + value_provider_conf={"field_id": select_column_id}, + order=1, + ) + + def get_color_definitions_decoration( + self, + field_mapping: dict, + view_type: ViewType, + row_id_mapping: Dict[str, Dict[str, int]], + raw_airtable_table: dict, + raw_airtable_view: dict, + raw_airtable_view_data: dict, + import_report: AirtableImportReport, + ) -> Optional[ViewDecoration]: + color_config = raw_airtable_view_data["colorConfig"] + color_definitions = color_config["colorDefinitions"] + default_color = AIRTABLE_BASEROW_COLOR_MAPPING.get( + color_config.get("defaultColor", ""), + "", + ) + baserow_colors = [] + + for color_definition in color_definitions: + filters, filter_groups = self.get_filters( + field_mapping, + row_id_mapping, + raw_airtable_view, + raw_airtable_table, + import_report, + color_definition, + ) + # Pop the first group because that shouldn't be in Baserow, and the type is + # defined on the view. + if len(filter_groups) > 0: + root_group = filter_groups.pop(0) + color = AIRTABLE_BASEROW_COLOR_MAPPING.get( + color_definition.get("color", ""), + "blue", + ) + baserow_colors.append( + { + "filter_groups": [ + { + "id": filter_group.id, + "filter_type": filter_group.filter_type, + "parent_group": ( + None + if filter_group.parent_group_id == root_group.id + else filter_group.parent_group_id + ), + } + for filter_group in filter_groups + ], + "filters": [ + { + "id": filter_object.id, + "type": filter_object.type, + "field": filter_object.field_id, + "group": ( + None + if filter_object.group_id == root_group.id + else filter_object.group_id + ), + "value": filter_object.value, + } + for filter_object in filters + ], + "operator": root_group.filter_type, + "color": color, + } + ) + + if default_color != "": + baserow_colors.append( + { + "filter_groups": [], + "filters": [], + "operator": "AND", + "color": default_color, + } + ) + + return ViewDecoration( + id=f"{raw_airtable_view['id']}_decoration", + view_id=raw_airtable_view["id"], + type=LeftBorderColorDecoratorType.type, + value_provider_type=ConditionalColorValueProviderType.type, + value_provider_conf={"colors": baserow_colors}, + order=1, + ) + + def get_decorations( + self, + field_mapping: dict, + view_type: ViewType, + row_id_mapping: Dict[str, Dict[str, int]], + raw_airtable_table: dict, + raw_airtable_view: dict, + raw_airtable_view_data: dict, + import_report: AirtableImportReport, + ) -> List[ViewDecoration]: + """ + Converts the raw Airtable color config into matching Baserow view decorations. + """ + + color_config = raw_airtable_view_data.get("colorConfig", None) + + if not view_type.can_decorate or color_config is None: + return [] + + color_config_type = color_config.get("type", "") + decoration = None + + if color_config_type == "selectColumn": + decoration = self.get_select_column_decoration( + field_mapping, + view_type, + row_id_mapping, + raw_airtable_table, + raw_airtable_view, + raw_airtable_view_data, + import_report, + ) + elif color_config_type == "colorDefinitions": + decoration = self.get_color_definitions_decoration( + field_mapping, + view_type, + row_id_mapping, + raw_airtable_table, + raw_airtable_view, + raw_airtable_view_data, + import_report, + ) + + if decoration: + return [decoration] + else: + return [] + + def to_serialized_baserow_view( + self, + field_mapping, + row_id_mapping, + raw_airtable_table, + raw_airtable_view, + raw_airtable_view_data, + config, + import_report, + ): + if self.baserow_view_type is None: + raise NotImplementedError( + "The `baserow_view_type` must be implemented for the AirtableViewType." + ) + + view_type = view_type_registry.get(self.baserow_view_type) + view = view_type.model_class( + id=raw_airtable_view["id"], + pk=raw_airtable_view["id"], + name=raw_airtable_view["name"], + order=raw_airtable_table["viewOrder"].index(raw_airtable_view["id"]) + 1, + ) + + filters_object = raw_airtable_view_data.get("filters", None) + filters = [] + filter_groups = [] + if view_type.can_filter and filters_object is not None: + filters, filter_groups = self.get_filters( + field_mapping, + row_id_mapping, + raw_airtable_view, + raw_airtable_table, + import_report, + filters_object, + ) + # Pop the first group because that shouldn't be in Baserow, and the type is + # defined on the view. + if len(filter_groups) > 0: + view.filter_type = filter_groups.pop(0).filter_type + + sorts = self.get_sorts( + field_mapping, + view_type, + raw_airtable_table, + raw_airtable_view, + raw_airtable_view_data, + import_report, + ) + group_bys = self.get_group_bys( + field_mapping, + view_type, + raw_airtable_table, + raw_airtable_view, + raw_airtable_view_data, + import_report, + ) + decorations = self.get_decorations( + field_mapping, + view_type, + row_id_mapping, + raw_airtable_table, + raw_airtable_view, + raw_airtable_view_data, + import_report, + ) + + view.get_field_options = lambda *args, **kwargs: [] + view._prefetched_objects_cache = { + "viewfilter_set": filters, + "filter_groups": filter_groups, + "viewsort_set": sorts, + "viewgroupby_set": group_bys, + "viewdecoration_set": decorations, + } + view = self.prepare_view_object( + field_mapping, + view, + raw_airtable_table, + raw_airtable_view, + raw_airtable_view_data, + config, + import_report, + ) + serialized = view_type.export_serialized(view) + + return serialized + + def prepare_view_object( + self, + field_mapping: dict, + view: View, + raw_airtable_table: dict, + raw_airtable_view: dict, + raw_airtable_view_data: dict, + config: AirtableImportConfig, + import_report: AirtableImportReport, + ) -> Union[dict, None]: + """ + Prepares the given view object before it's passed into the view type specific + `export_serialized` method. This should be used to set any properties that + are needed for the view specific export operations. + + Note that the common properties like name, filters, sorts, etc are added by + default depending on the Baserow view support for it. + + :param field_mapping: A dict containing all the imported fields. + :param view: The view object that must be prepared. + :param raw_airtable_table: The raw Airtable table data related to the column. + :param raw_airtable_view: The raw Airtable view values that must be + converted, this contains the name, for example. + :param raw_airtable_view_data: The Airtable view data. This contains the + filters, sorts, etc. + :param config: Additional configuration related to the import. + :param import_report: Used to collect what wasn't imported to report to the + user. + :return: The Baserow view type related to the Airtable column. If None is + provided, then the view is ignored in the conversion. + """ + + raise NotImplementedError( + "The `to_serialized_baserow_view` must be implemented." + ) + + +class AirtableViewTypeRegistry(Registry): + name = "airtable_view" + + def from_airtable_view_to_serialized( + self, + field_mapping: dict, + row_id_mapping: Dict[str, Dict[str, int]], + raw_airtable_table: dict, + raw_airtable_view: dict, + raw_airtable_view_data: dict, + config: AirtableImportConfig, + import_report: AirtableImportReport, + ) -> dict: + """ + Tries to find a Baserow view that matches that raw Airtable view data. If + None is returned, the view is not compatible with Baserow and must be ignored. + + :param field_mapping: A dict containing all the imported fields. + :param row_id_mapping: A dict mapping the Airable row IDs to Baserow row IDs + per table ID. + :param raw_airtable_table: The raw Airtable table data related to the column. + :param raw_airtable_view: The raw Airtable column data that must be imported. + :param raw_airtable_view_data: The raw Airtable view data containing filters, + sorts, etc. + :param config: Additional configuration related to the import. + :param import_report: Used to collect what wasn't imported to report to the + user. + :return: The related Baserow view and AirtableViewType that should be used + for the conversion. + """ + + try: + type_name = raw_airtable_view.get("type", "") + airtable_view_type = self.get(type_name) + serialized_view = airtable_view_type.to_serialized_baserow_view( + field_mapping, + row_id_mapping, + raw_airtable_table, + raw_airtable_view, + raw_airtable_view_data, + config, + import_report, + ) + + return serialized_view + except self.does_not_exist_exception_class: + # Returning `None` because it's okay to not important the incompatible + # views. It will be added to the `import_later` from the handler. + return None + + +class AirtableFilterOperator(Instance): + def to_baserow_filter_and_value( + self, + row_id_mapping: Dict[str, Dict[str, int]], + raw_airtable_table: dict, + raw_airtable_column: dict, + baserow_field: Field, + import_report: AirtableImportReport, + value: str, + ) -> Union[ViewFilterType, str]: + """ + Converts the given Airtable value into the matching Baserow filter type and + correct value. + + :param row_id_mapping: A dict mapping the Airable row IDs to Baserow row IDs + per table ID. + :param raw_airtable_table: The raw Airtable table data related to the filter. + :param raw_airtable_column: The raw Airtable column data related to the filter. + :param baserow_field: The Baserow field related to the filter. + :param import_report: Used to collect what wasn't imported to report to the + user. + :param value: The value that must be converted. + :raises AirtableSkipFilter: If no compatible Baserow filter can be found. + :return: The matching Baserow filter type and value. + """ + + raise NotImplementedError( + f"The `to_baserow_filter` must be implemented for {self.type}." + ) + + +class AirtableFilterOperatorRegistry(Registry): + name = "airtable_filter_operator" + + # A default airtable column type registry is created here, this is the one that is used # throughout the whole Baserow application to add a new airtable column type. airtable_column_type_registry = AirtableColumnTypeRegistry() +airtable_view_type_registry = AirtableViewTypeRegistry() +airtable_filter_operator_registry = AirtableFilterOperatorRegistry() diff --git a/backend/src/baserow/contrib/database/airtable/utils.py b/backend/src/baserow/contrib/database/airtable/utils.py index 5ff0acb37..fb7f4f610 100644 --- a/backend/src/baserow/contrib/database/airtable/utils.py +++ b/backend/src/baserow/contrib/database/airtable/utils.py @@ -1,4 +1,15 @@ +import json import re +from typing import Any, Optional, Union + +from requests import Response + +from baserow.contrib.database.airtable.constants import ( + AIRTABLE_DATE_FILTER_VALUE_MAP, + AIRTABLE_MAX_DURATION_VALUE, +) +from baserow.contrib.database.airtable.exceptions import AirtableSkipFilter +from baserow.core.utils import get_value_at_path, remove_invalid_surrogate_characters def extract_share_id_from_url(public_base_url: str) -> str: @@ -39,3 +50,250 @@ def get_airtable_row_primary_value(table, row): primary_value = row["id"] return primary_value + + +def get_airtable_column_name(raw_airtable_table, column_id) -> str: + """ + Tries to extract the name of the column from the provided Airtable table. + + :param raw_airtable_table: The table where to get the column names from. + :param column_id: The column ID to get the name for. + :return: The found column name or column_id if not found. + """ + + for column in raw_airtable_table["columns"]: + if column["id"] == column_id: + return column["name"] + + return column_id + + +def unknown_value_to_human_readable(value: Any) -> str: + """ + If a value can't be converted to human-readable value, then this function can be + used to generate something user-friendly. + + :param value: The value that must be converted. + :return: The human-readable string value. + """ + + if value is None: + return "" + if isinstance(value, list): + value_len = len(value) + return "1 item" if value_len == 1 else f"{value_len} items" + if isinstance(value, str) and value.startswith("usr"): + return "1 item" + return str(value) + + +def parse_json_and_remove_invalid_surrogate_characters(response: Response) -> dict: + """ + The response from Airtable can sometimes contain invalid surrogate characters. This + helper method removed them, and parses it to JSON. + + :param response: The response from the request to Airtable. + :return: Parsed JSON from the response. + """ + + try: + decoded_content = remove_invalid_surrogate_characters( + response.content, response.encoding + ) + json_decoded_content = json.loads(decoded_content) + except json.decoder.JSONDecodeError: + # In some cases, the `remove_invalid_surrogate_characters` results in + # invalid JSON. It's not completely clear why that is, but this + # fallback can still produce valid JSON to import in most cases if + # the original json didn't contain invalid surrogate characters. + json_decoded_content = response.json() + + return json_decoded_content + + +def quill_parse_inline(insert, attributes): + if "bold" in attributes: + insert = f"**{insert}**" + if "italic" in attributes: + insert = f"_{insert}_" + if "strike" in attributes: + insert = f"~{insert}~" + if "code" in attributes: + insert = f"`{insert}`" + if "link" in attributes: + insert = f"[{insert}]({attributes['link']})" + if isinstance(insert, object) and "mention" in insert: + insert = f"@{insert['mention'].get('userId', '')}" + + return insert + + +def quill_wrap_block(attributes): + prepend = "" + append = "" + multi_line = False + if "header" in attributes: + prepend = "#" * attributes["header"] + " " + if "list" in attributes: + list_type = attributes["list"] + prepend = " " * attributes.get("indent", 0) * 4 + if list_type == "ordered": + prepend += f"1. " + elif list_type == "bullet": + prepend += "- " + elif list_type == "unchecked": + prepend += "- [ ] " + elif list_type == "checked": + prepend += "- [x] " + if "blockquote" in attributes: + prepend = "> " + if "≈≈" in attributes: + prepend = "> " + if "code-block" in attributes: + prepend = "```\n" + append = "```\n" + multi_line = True + return prepend, append, multi_line + + +def quill_split_with_newlines(value): + parts = re.split(r"(\n)", value) + if parts and parts[0] == "": + parts.pop(0) + if parts and parts[-1] == "": + parts.pop() + return parts + + +def quill_to_markdown(ops: list) -> str: + """ + Airtable uses the QuillJS editor for their rich text field. There is no library + to convert it in Baserow compatible markdown. This is a simple, custom written + function to convert it to Baserow compatible markdown. + + The format is a bit odd because a newline entry can define how it should have been + formatted as on block level, making it a bit tricky because it's not sequential. + + See the `test_quill_to_markdown_airtable_example` test for an example. + + :param ops: The QuillJS delta object that must be converted to markdown. + :return: The converted markdown string. + """ + + md_output = [] + # Holds everything that must be written as a line. Each entry in the ops can add to + # it until a "\n" character is detected. + current_object = "" + # Temporarily holds markdown code that has start and ending block, like with + # code "```", for example. Need to temporarily store the prepend and append values, + # so that we can add to it if it consists of multiple lines. + current_multi_line = None + + def flush_line(): + nonlocal md_output + nonlocal current_object + if current_object != "": + md_output.append(current_object) + current_object = "" + + def flush_multi_line(current_prepend, current_append): + nonlocal current_object + nonlocal current_multi_line + if current_multi_line is not None and current_multi_line != ( + current_prepend, + current_append, + ): + current_object = ( + current_multi_line[0] + current_object + current_multi_line[1] + ) + flush_line() + current_multi_line = None + + for index, op in enumerate(ops): + raw_insert = op.get("insert", "") + attributes = op.get("attributes", {}) + + if isinstance(raw_insert, str): + insert_lines = quill_split_with_newlines(raw_insert) + else: + insert_lines = [raw_insert] + + # Break the insert by "\n" because the block formatting options should only + # refer to the previous line. + for insert_line in insert_lines: + is_new_line = insert_line == "\n" + + if is_new_line: + prepend, append, multi_line = quill_wrap_block(attributes) + flush_multi_line(prepend, append) + + # Starting a new multi-line block. All the following lines will be + # enclosed by the prepend and append. + if multi_line and current_multi_line is None: + current_multi_line = (prepend, append) + + parsed_insert = quill_parse_inline(insert_line, attributes) + current_object += parsed_insert + + if is_new_line and not multi_line: + current_object = prepend + current_object + append + flush_line() + + flush_multi_line(None, None) + flush_line() + + return "".join(md_output).strip() + + +def airtable_date_filter_value_to_baserow(value: Optional[Union[dict, str]]) -> str: + """ + Converts the provided Airtable filter date value to the Baserow compatible date + value string. + + :param value: A dict containing the Airtable date value. + :return: e.g. Europe/Amsterdam?2025-01-01?exact_date + """ + + if value is None: + return "" + + # If the value is a string, then it contains an exact date. This is the old format + # of Airtable. In that case, we can conert it to the correct format. + if isinstance(value, str): + value = { + "mode": "exactDate", + "exactDate": value, + "timeZone": "", # it's okay to leave the timezone empty in Baserow. + } + + mode = value["mode"] + if "exactDate" in value: + # By default, Airtable adds the time, but that is not needed in Baserow. + value["exactDate"] = value["exactDate"][:10] + date_string = AIRTABLE_DATE_FILTER_VALUE_MAP[mode] + return date_string.format(**value) + + +def skip_filter_if_type_duration_and_value_too_high(raw_airtable_column, value): + """ + If the provided Airtable column is a number with duration formatting, and if the + value exceeds the maximum we can process, then the `AirtableSkipFilter` is raised. + + :param raw_airtable_column: The related raw Airtable column. + :param value: The value that must be checked. + :raises: AirtableSkipFilter + """ + + is_duration = ( + get_value_at_path(raw_airtable_column, "typeOptions.format") == "duration" + ) + + if not is_duration: + return + + try: + value = int(value) + if abs(value) > AIRTABLE_MAX_DURATION_VALUE: + raise AirtableSkipFilter + except ValueError: + pass diff --git a/backend/src/baserow/contrib/database/api/fields/errors.py b/backend/src/baserow/contrib/database/api/fields/errors.py index 78d220405..23b72d18a 100644 --- a/backend/src/baserow/contrib/database/api/fields/errors.py +++ b/backend/src/baserow/contrib/database/api/fields/errors.py @@ -38,8 +38,8 @@ ERROR_ORDER_BY_FIELD_NOT_FOUND = ( ERROR_ORDER_BY_FIELD_NOT_POSSIBLE = ( "ERROR_ORDER_BY_FIELD_NOT_POSSIBLE", HTTP_400_BAD_REQUEST, - "It is not possible to order by {e.field_name} because the field type " - "{e.field_type} does not support filtering.", + "It is not possible to order by {e.field_name} using sort type {e.sort_type} " + "because the field type {e.field_type} does not support it.", ) ERROR_FILTER_FIELD_NOT_FOUND = ( "ERROR_FILTER_FIELD_NOT_FOUND", diff --git a/backend/src/baserow/contrib/database/api/tables/serializers.py b/backend/src/baserow/contrib/database/api/tables/serializers.py index 96943f655..a98a162de 100644 --- a/backend/src/baserow/contrib/database/api/tables/serializers.py +++ b/backend/src/baserow/contrib/database/api/tables/serializers.py @@ -1,9 +1,71 @@ +from django.utils.functional import lazy + from rest_framework import serializers +from rest_framework.exceptions import ValidationError from baserow.contrib.database.api.data_sync.serializers import DataSyncSerializer +from baserow.contrib.database.fields.registries import field_type_registry from baserow.contrib.database.table.models import Table +class TableImportConfiguration(serializers.Serializer): + """ + Additional table import configuration. + """ + + upsert_fields = serializers.ListField( + child=serializers.IntegerField(min_value=1), + min_length=1, + allow_null=True, + allow_empty=True, + default=None, + help_text=lazy( + lambda: ( + "A list of field IDs in the table used to generate a value for " + "identifying a row during the upsert process in file import. Each " + "field ID must reference an existing field in the table, which will " + "be used to match provided values against existing ones to determine " + "whether a row should be inserted or updated.\n " + "Field types that can be used in upsert fields: " + f"{','.join([f.type for f in field_type_registry.get_all() if f.can_upsert])}. " + "If specified, `upsert_values` should also be provided." + ) + ), + ) + upsert_values = serializers.ListField( + allow_empty=True, + allow_null=True, + default=None, + child=serializers.ListField( + min_length=1, + ), + help_text=( + "A list of values that are identifying rows in imported data.\n " + "The number of rows in `upsert_values` should be equal to the number of " + "rows in imported data. Each row in `upsert_values` should contain a " + "list of values that match the number and field types of fields selected " + "in `upsert_fields`. Based on `upsert_fields`, a similar upsert values " + "will be calculated for each row in the table.\n " + "There's no guarantee of uniqueness of row identification calculated from " + "`upsert_values` nor from the table. Repeated upsert values are compared " + "in order with matching values in the table. The imported data must be in " + "the same order as the table rows for correct matching." + ), + ) + + def validate(self, attrs): + if attrs.get("upsert_fields") and not len(attrs.get("upsert_values") or []): + raise ValidationError( + { + "upsert_value": ( + "upsert_values must not be empty " + "when upsert_fields are provided." + ) + } + ) + return attrs + + class TableSerializer(serializers.ModelSerializer): data_sync = DataSyncSerializer() @@ -74,10 +136,26 @@ class TableImportSerializer(serializers.Serializer): "for adding two rows to a table with two writable fields." ), ) + configuration = TableImportConfiguration(required=False, default=None) class Meta: fields = ("data",) + def validate(self, attrs): + if attrs.get("configuration"): + if attrs["configuration"].get("upsert_values"): + if len(attrs["configuration"].get("upsert_values")) != len( + attrs["data"] + ): + msg = ( + "`data` and `configuration.upsert_values` " + "should have the same length." + ) + raise ValidationError( + {"data": msg, "configuration": {"upsert_values": msg}} + ) + return attrs + class TableUpdateSerializer(serializers.ModelSerializer): class Meta: diff --git a/backend/src/baserow/contrib/database/api/tables/views.py b/backend/src/baserow/contrib/database/api/tables/views.py index b1f52867b..380bccacd 100644 --- a/backend/src/baserow/contrib/database/api/tables/views.py +++ b/backend/src/baserow/contrib/database/api/tables/views.py @@ -489,14 +489,14 @@ class AsyncTableImportView(APIView): workspace=table.database.workspace, context=table, ) - + configuration = data.get("configuration") data = data["data"] - file_import_job = JobHandler().create_and_start_job( request.user, "file_import", data=data, table=table, + configuration=configuration, ) serializer = job_type_registry.get_serializer(file_import_job, JobSerializer) diff --git a/backend/src/baserow/contrib/database/api/views/errors.py b/backend/src/baserow/contrib/database/api/views/errors.py index 0da28f76f..1a8dbf48b 100644 --- a/backend/src/baserow/contrib/database/api/views/errors.py +++ b/backend/src/baserow/contrib/database/api/views/errors.py @@ -57,7 +57,7 @@ ERROR_VIEW_SORT_FIELD_ALREADY_EXISTS = ( ERROR_VIEW_SORT_FIELD_NOT_SUPPORTED = ( "ERROR_VIEW_SORT_FIELD_NOT_SUPPORTED", HTTP_400_BAD_REQUEST, - "The field does not support view sorting.", + "The field does not support view sorting on the given type.", ) ERROR_VIEW_GROUP_BY_DOES_NOT_EXIST = ( "ERROR_VIEW_GROUP_BY_DOES_NOT_EXIST", diff --git a/backend/src/baserow/contrib/database/api/views/serializers.py b/backend/src/baserow/contrib/database/api/views/serializers.py index 34093b768..500a98abd 100644 --- a/backend/src/baserow/contrib/database/api/views/serializers.py +++ b/backend/src/baserow/contrib/database/api/views/serializers.py @@ -220,14 +220,14 @@ class UpdateViewFilterGroupSerializer(serializers.ModelSerializer): class ViewSortSerializer(serializers.ModelSerializer): class Meta: model = ViewSort - fields = ("id", "view", "field", "order") + fields = ("id", "view", "field", "order", "type") extra_kwargs = {"id": {"read_only": True}} class CreateViewSortSerializer(serializers.ModelSerializer): class Meta: model = ViewSort - fields = ("field", "order") + fields = ("field", "order", "type") extra_kwargs = { "order": {"default": ViewSort._meta.get_field("order").default}, } @@ -236,11 +236,12 @@ class CreateViewSortSerializer(serializers.ModelSerializer): class UpdateViewSortSerializer(serializers.ModelSerializer): class Meta(CreateViewFilterSerializer.Meta): model = ViewSort - fields = ("field", "order") + fields = ("field", "order", "type") extra_kwargs = { "field": {"required": False}, "order": {"required": False}, "width": {"required": False}, + "type": {"required": False}, } @@ -253,6 +254,7 @@ class ViewGroupBySerializer(serializers.ModelSerializer): "field", "order", "width", + "type", ) extra_kwargs = {"id": {"read_only": True}} @@ -264,10 +266,12 @@ class CreateViewGroupBySerializer(serializers.ModelSerializer): "field", "order", "width", + "type", ) extra_kwargs = { "order": {"default": ViewGroupBy._meta.get_field("order").default}, "width": {"default": ViewGroupBy._meta.get_field("width").default}, + "type": {"default": ViewGroupBy._meta.get_field("type").default}, } @@ -278,11 +282,13 @@ class UpdateViewGroupBySerializer(serializers.ModelSerializer): "field", "order", "width", + "type", ) extra_kwargs = { "field": {"required": False}, "order": {"required": False}, "width": {"required": False}, + "type": {"required": False}, } @@ -540,7 +546,7 @@ class PublicViewSortSerializer(serializers.ModelSerializer): class Meta: model = ViewSort - fields = ("id", "view", "field", "order") + fields = ("id", "view", "field", "order", "type") extra_kwargs = {"id": {"read_only": True}} @@ -555,6 +561,7 @@ class PublicViewGroupBySerializer(serializers.ModelSerializer): "field", "order", "width", + "type", ) extra_kwargs = {"id": {"read_only": True}} diff --git a/backend/src/baserow/contrib/database/api/views/views.py b/backend/src/baserow/contrib/database/api/views/views.py index 67d6e6a94..edc1db9c1 100644 --- a/backend/src/baserow/contrib/database/api/views/views.py +++ b/backend/src/baserow/contrib/database/api/views/views.py @@ -1540,7 +1540,11 @@ class ViewSortingsView(APIView): field = FieldHandler().get_field(data["field"]) view_sort = action_type_registry.get_by_type(CreateViewSortActionType).do( - request.user, view, field, data["order"] + request.user, + view, + field, + data["order"], + data.get("type"), ) serializer = ViewSortSerializer(view_sort) @@ -1645,6 +1649,7 @@ class ViewSortView(APIView): view_sort, data.get("field"), data.get("order"), + data.get("type"), ) serializer = ViewSortSerializer(view_sort) @@ -2219,7 +2224,7 @@ class ViewGroupBysView(APIView): view_group_by = action_type_registry.get_by_type( CreateViewGroupByActionType - ).do(request.user, view, field, data["order"], data["width"]) + ).do(request.user, view, field, data["order"], data["width"], data.get("type")) serializer = ViewGroupBySerializer(view_group_by) return Response(serializer.data) @@ -2326,6 +2331,7 @@ class ViewGroupByView(APIView): data.get("field"), data.get("order"), data.get("width"), + data.get("type"), ) serializer = ViewGroupBySerializer(view_group_by) diff --git a/backend/src/baserow/contrib/database/api/webhooks/serializers.py b/backend/src/baserow/contrib/database/api/webhooks/serializers.py index 6118e27cf..205dc6781 100644 --- a/backend/src/baserow/contrib/database/api/webhooks/serializers.py +++ b/backend/src/baserow/contrib/database/api/webhooks/serializers.py @@ -26,8 +26,15 @@ class TableWebhookEventConfig(serializers.Serializer): choices=webhook_event_type_registry.get_types(), ) fields = serializers.ListField( + required=False, child=serializers.IntegerField(), help_text="A list of field IDs that are related to the event.", + allow_empty=True, + ) + views = serializers.ListField( + required=False, + child=serializers.IntegerField(), + help_text="A list of view IDs that are related to the event.", ) @@ -186,13 +193,15 @@ class TableWebhookSerializer(serializers.ModelSerializer): @extend_schema_field(TableWebhookEventConfig(many=True)) def get_event_config(self, instance): - events = [ - { - "event_type": event.event_type, - "fields": [f.id for f in event.fields.all()], - } - for event in instance.events.all() - ] + events = [] + for event in instance.events.all(): + evt = {"event_type": event.event_type} + if fields := [f.id for f in event.fields.all()]: + evt["fields"] = fields + if views := [v.id for v in event.views.all()]: + evt["views"] = views + events.append(evt) + return [TableWebhookEventConfig(event).data for event in events] @extend_schema_field(OpenApiTypes.OBJECT) diff --git a/backend/src/baserow/contrib/database/application_types.py b/backend/src/baserow/contrib/database/application_types.py index 835d8be16..38c3e922a 100755 --- a/backend/src/baserow/contrib/database/application_types.py +++ b/backend/src/baserow/contrib/database/application_types.py @@ -33,12 +33,12 @@ from baserow.core.registries import ( ) from baserow.core.storage import ExportZipFile from baserow.core.trash.handler import TrashHandler -from baserow.core.utils import ChildProgressBuilder, grouper +from baserow.core.utils import ChildProgressBuilder, Progress, grouper from .constants import ( EXPORT_SERIALIZED_EXPORTING_TABLE, - IMPORT_SERIALIZED_IMPORTING, - IMPORT_SERIALIZED_IMPORTING_TABLE, + IMPORT_SERIALIZED_IMPORTING_TABLE_DATA, + IMPORT_SERIALIZED_IMPORTING_TABLE_STRUCTURE, ) from .data_sync.registries import data_sync_type_registry from .db.atomic import read_repeatable_single_database_atomic_transaction @@ -293,7 +293,7 @@ class DatabaseApplicationType(ApplicationType): import_export_config: ImportExportConfig, external_table_fields_to_import: List[Tuple[Table, Dict[str, Any]]], deferred_fk_update_collector: DeferredForeignKeyUpdater, - progress: ChildProgressBuilder, + progress: Progress, ) -> ImportedFields: """ Import the fields from the serialized data in the correct order based on their @@ -308,6 +308,10 @@ class DatabaseApplicationType(ApplicationType): also be imported. These fields will be imported into the existing table provided in the first item in the tuple, the second being the serialized field to import. + :param deferred_fk_update_collector: A collector that collects all the foreign + keys to update them later when the model with all the fields is created. + :param progress: A progress used to report progress of the import. + :return: The imported fields. """ field_cache = FieldCache() @@ -348,7 +352,10 @@ class DatabaseApplicationType(ApplicationType): if table_instance not in table_fields_by_name: table_fields_by_name[table_instance] = {} table_fields_by_name[table_instance][field_instance.name] = field_instance - progress.increment(state=IMPORT_SERIALIZED_IMPORTING) + table_name = serialized_table["name"] + progress.increment( + state=f"{IMPORT_SERIALIZED_IMPORTING_TABLE_STRUCTURE}{table_name}" + ) return field_instance fields_without_dependencies: List[Field] = [] @@ -404,7 +411,7 @@ class DatabaseApplicationType(ApplicationType): deferred_fk_update_collector, ) SearchHandler.after_field_created(external_field) - progress.increment(state=IMPORT_SERIALIZED_IMPORTING) + progress.increment() deferred_fk_update_collector.run_deferred_fk_updates( id_mapping, "database_fields" @@ -537,7 +544,9 @@ class DatabaseApplicationType(ApplicationType): self._create_table_schema( serialized_table, already_created_through_table_names ) - progress.increment(state=IMPORT_SERIALIZED_IMPORTING) + progress.increment( + state=f"{IMPORT_SERIALIZED_IMPORTING_TABLE_STRUCTURE}{serialized_table['name']}" + ) # Now that everything is in place we can start filling the table with the rows # in an efficient matter by using the bulk_create functionality. @@ -594,9 +603,9 @@ class DatabaseApplicationType(ApplicationType): user_email_mapping: Dict[str, Any], deferred_fk_update_collector: DeferredForeignKeyUpdater, id_mapping: Dict[str, Any], - files_zip: Optional[ZipFile] = None, - storage: Optional[Storage] = None, - progress: Optional[ChildProgressBuilder] = None, + files_zip: ZipFile | None, + storage: Storage | None, + progress: Progress, ): """ Imports the rows of a table from the serialized data in an efficient manner. @@ -610,7 +619,7 @@ class DatabaseApplicationType(ApplicationType): imported files from :param storage: An optional place to persist any user files if importing files from a the above file_zip. - :param progress: A progress builder used to report progress of the import. + :param progress: A progress used to report progress of the import. """ table_cache: Dict[str, Any] = {} @@ -668,7 +677,7 @@ class DatabaseApplicationType(ApplicationType): rows_to_be_inserted.append(row_instance) progress.increment( - state=f"{IMPORT_SERIALIZED_IMPORTING_TABLE}{serialized_table['id']}" + state=f"{IMPORT_SERIALIZED_IMPORTING_TABLE_DATA}{serialized_table['name']}" ) # We want to insert the rows in bulk because there could potentially be @@ -678,7 +687,7 @@ class DatabaseApplicationType(ApplicationType): table_model.objects.bulk_create(chunk, batch_size=512) progress.increment( len(chunk), - state=f"{IMPORT_SERIALIZED_IMPORTING_TABLE}{serialized_table['id']}", + state=f"{IMPORT_SERIALIZED_IMPORTING_TABLE_DATA}{serialized_table['name']}", ) # Every row import can have additional objects that must be inserted, @@ -811,7 +820,7 @@ class DatabaseApplicationType(ApplicationType): field_type.after_rows_imported( field, field_cache=imported_fields.field_cache ) - progress.increment(state=IMPORT_SERIALIZED_IMPORTING) + progress.increment() def _create_table_schema( self, serialized_table, already_created_through_table_names @@ -869,10 +878,13 @@ class DatabaseApplicationType(ApplicationType): """ table = serialized_table["_object"] + table_name = serialized_table["name"] for serialized_view in serialized_table["views"]: view_type = view_type_registry.get(serialized_view["type"]) view_type.import_serialized(table, serialized_view, id_mapping, files_zip) - progress.increment(state=IMPORT_SERIALIZED_IMPORTING) + progress.increment( + state=f"{IMPORT_SERIALIZED_IMPORTING_TABLE_STRUCTURE}{table_name}" + ) def _import_tables( self, @@ -906,7 +918,10 @@ class DatabaseApplicationType(ApplicationType): serialized_table["_object"] = table_instance serialized_table["field_instances"] = [] imported_tables.append(table_instance) - progress.increment(state=IMPORT_SERIALIZED_IMPORTING) + table_name = serialized_table["name"] + progress.increment( + state=f"{IMPORT_SERIALIZED_IMPORTING_TABLE_STRUCTURE}{table_name}" + ) return imported_tables @@ -924,7 +939,7 @@ class DatabaseApplicationType(ApplicationType): Imports a database application exported by the `export_serialized` method. """ - database_progress, table_progress = 1, 99 + database_progress, table_progress = 1, len(serialized_values["tables"]) progress = ChildProgressBuilder.build( progress_builder, child_total=database_progress + table_progress ) @@ -940,10 +955,7 @@ class DatabaseApplicationType(ApplicationType): ) database = application.specific - - if not serialized_values["tables"]: - progress.increment(state=IMPORT_SERIALIZED_IMPORTING, by=table_progress) - else: + if serialized_values["tables"]: self.import_tables_serialized( database, serialized_values["tables"], diff --git a/backend/src/baserow/contrib/database/apps.py b/backend/src/baserow/contrib/database/apps.py index 88fc41af3..1b2151096 100755 --- a/backend/src/baserow/contrib/database/apps.py +++ b/backend/src/baserow/contrib/database/apps.py @@ -158,7 +158,11 @@ class DatabaseConfig(AppConfig): action_type_registry.register(UpdateDataSyncTableActionType()) action_type_registry.register(SyncDataSyncTableActionType()) - from .airtable.registry import airtable_column_type_registry + from .airtable.registry import ( + airtable_column_type_registry, + airtable_filter_operator_registry, + airtable_view_type_registry, + ) from .data_sync.registries import data_sync_type_registry from .export.registries import table_exporter_registry from .fields.registries import ( @@ -616,6 +620,7 @@ class DatabaseConfig(AppConfig): webhook_event_type_registry.register(ViewDeletedEventType()) from .airtable.airtable_column_types import ( + AutoNumberAirtableColumnType, CheckboxAirtableColumnType, CountAirtableColumnType, DateAirtableColumnType, @@ -646,6 +651,49 @@ class DatabaseConfig(AppConfig): airtable_column_type_registry.register(MultipleAttachmentAirtableColumnType()) airtable_column_type_registry.register(RichTextTextAirtableColumnType()) airtable_column_type_registry.register(CountAirtableColumnType()) + airtable_column_type_registry.register(AutoNumberAirtableColumnType()) + + from .airtable.airtable_view_types import GridAirtableViewType + + airtable_view_type_registry.register(GridAirtableViewType()) + + from .airtable.airtable_filter_operators import ( + AirtableContainsOperator, + AirtableDoesNotContainOperator, + AirtableEqualOperator, + AirtableFilenameOperator, + AirtableFiletypeOperator, + AirtableHasAllOfOperator, + AirtableHasAnyOfOperator, + AirtableIsAnyOfOperator, + AirtableIsEmptyOperator, + AirtableIsNoneOfOperator, + AirtableIsNotEmptyOperator, + AirtableIsWithinOperator, + AirtableLessThanOperator, + AirtableLessThanOrEqualOperator, + AirtableMoreThanOperator, + AirtableMoreThanOrEqualOperator, + AirtableNotEqualOperator, + ) + + airtable_filter_operator_registry.register(AirtableContainsOperator()) + airtable_filter_operator_registry.register(AirtableDoesNotContainOperator()) + airtable_filter_operator_registry.register(AirtableEqualOperator()) + airtable_filter_operator_registry.register(AirtableNotEqualOperator()) + airtable_filter_operator_registry.register(AirtableIsEmptyOperator()) + airtable_filter_operator_registry.register(AirtableIsNotEmptyOperator()) + airtable_filter_operator_registry.register(AirtableFilenameOperator()) + airtable_filter_operator_registry.register(AirtableFiletypeOperator()) + airtable_filter_operator_registry.register(AirtableIsAnyOfOperator()) + airtable_filter_operator_registry.register(AirtableIsNoneOfOperator()) + airtable_filter_operator_registry.register(AirtableHasAnyOfOperator()) + airtable_filter_operator_registry.register(AirtableHasAllOfOperator()) + airtable_filter_operator_registry.register(AirtableLessThanOperator()) + airtable_filter_operator_registry.register(AirtableMoreThanOperator()) + airtable_filter_operator_registry.register(AirtableLessThanOrEqualOperator()) + airtable_filter_operator_registry.register(AirtableMoreThanOrEqualOperator()) + airtable_filter_operator_registry.register(AirtableIsWithinOperator()) from .data_sync.data_sync_types import ( ICalCalendarDataSyncType, @@ -947,6 +995,10 @@ class DatabaseConfig(AppConfig): from baserow.contrib.database.views.notification_types import ( FormSubmittedNotificationType, ) + from baserow.contrib.database.webhooks.notification_types import ( + WebhookDeactivatedNotificationType, + WebhookPayloadTooLargeNotificationType, + ) from baserow.core.notifications.registries import notification_type_registry notification_type_registry.register(CollaboratorAddedToRowNotificationType()) @@ -954,6 +1006,8 @@ class DatabaseConfig(AppConfig): UserMentionInRichTextFieldNotificationType() ) notification_type_registry.register(FormSubmittedNotificationType()) + notification_type_registry.register(WebhookDeactivatedNotificationType()) + notification_type_registry.register(WebhookPayloadTooLargeNotificationType()) # The signals must always be imported last because they use the registries # which need to be filled first. @@ -970,6 +1024,7 @@ class DatabaseConfig(AppConfig): import baserow.contrib.database.rows.tasks # noqa: F401 import baserow.contrib.database.search.tasks # noqa: F401 import baserow.contrib.database.table.receivers # noqa: F401 + import baserow.contrib.database.views.receivers # noqa: F401 import baserow.contrib.database.views.tasks # noqa: F401 # date/datetime min/max year handling - we need that for psycopg 3.x only diff --git a/backend/src/baserow/contrib/database/constants.py b/backend/src/baserow/contrib/database/constants.py index a7d8e3c5a..91c74750d 100644 --- a/backend/src/baserow/contrib/database/constants.py +++ b/backend/src/baserow/contrib/database/constants.py @@ -1,5 +1,6 @@ IMPORT_SERIALIZED_IMPORTING = "importing" -IMPORT_SERIALIZED_IMPORTING_TABLE = "importing-table-" +IMPORT_SERIALIZED_IMPORTING_TABLE_STRUCTURE = "importing-table-structure-" +IMPORT_SERIALIZED_IMPORTING_TABLE_DATA = "importing-table-data-" EXPORT_SERIALIZED_EXPORTING = "exporting" EXPORT_SERIALIZED_EXPORTING_TABLE = "exporting-table-" EXPORT_WORKSPACE_CREATE_ARCHIVE = "create-archive" diff --git a/backend/src/baserow/contrib/database/export/file_writer.py b/backend/src/baserow/contrib/database/export/file_writer.py index 89adaef74..42bc9fa31 100644 --- a/backend/src/baserow/contrib/database/export/file_writer.py +++ b/backend/src/baserow/contrib/database/export/file_writer.py @@ -47,6 +47,7 @@ class FileWriter(abc.ABC): self, queryset: QuerySet, write_row: Callable[[Any, bool], None], + progress_weight: int, ): """ A specialized method which knows how to write an entire queryset to the file @@ -54,6 +55,10 @@ class FileWriter(abc.ABC): :param queryset: The queryset to write to the file. :param write_row: A callable function which takes each row from the queryset in turn and writes to the file. + :param progress_weight: Indicates how much of the progress should count for + writing the rows in total. This can be used to reduce the total + percentage if there is some post-processing after writing to the rows + that must use some of the progress. """ def get_csv_dict_writer(self, headers, **kwargs): @@ -74,13 +79,16 @@ class PaginatedExportJobFileWriter(FileWriter): self.job = job self.last_check = None + def update_check(self): + self.last_check = time.perf_counter() + def write_bytes(self, value: bytes): self._file.write(value) def write(self, value: str, encoding="utf-8"): self._file.write(value.encode(encoding)) - def write_rows(self, queryset, write_row): + def write_rows(self, queryset, write_row, progress_weight=100): """ Writes the queryset to the file using the provided write_row callback. Every EXPORT_JOB_UPDATE_FREQUENCY_SECONDS will check if the job has been @@ -92,19 +100,27 @@ class PaginatedExportJobFileWriter(FileWriter): :param queryset: The queryset to write to the file. :param write_row: A callable function which takes each row from the queryset in turn and writes to the file. + :param progress_weight: Indicates how much of the progress should count for + writing the rows in total. This can be used to reduce the total + percentage if there is some post-processing after writing to the rows + that must use some of the progress. """ - self.last_check = time.perf_counter() + self.update_check() paginator = Paginator(queryset.all(), 2000) i = 0 + results = [] for page in paginator.page_range: for row in paginator.page(page).object_list: i = i + 1 is_last_row = i == paginator.count - write_row(row, is_last_row) - self._check_and_update_job(i, paginator.count) + result = write_row(row, is_last_row) + if result is not None: + results.append(result) + self._check_and_update_job(i, paginator.count, progress_weight) + return results - def _check_and_update_job(self, current_row, total_rows): + def _check_and_update_job(self, current_row, total_rows, progress_weight=100): """ Checks if enough time has passed and if so checks the state of the job and updates its progress percentage. @@ -124,12 +140,17 @@ class PaginatedExportJobFileWriter(FileWriter): ) is_last_row = current_row == total_rows if enough_time_has_passed or is_last_row: - self.last_check = time.perf_counter() + self.update_check() self.job.refresh_from_db() if self.job.is_cancelled_or_expired(): raise ExportJobCanceledException() else: - self.job.progress_percentage = current_row / total_rows * 100 + # min is used here because in case of files we get total size from + # files, but for progress measurement we use size of chunks that might + # be slightly bigger than the total size of the files + self.job.progress_percentage = min( + current_row / total_rows * progress_weight, 100 + ) self.job.save() @@ -144,6 +165,7 @@ class QuerysetSerializer(abc.ABC): def __init__(self, queryset, ordered_field_objects): self.queryset = queryset self.field_serializers = [lambda row: ("id", "id", row.id)] + self.ordered_field_objects = ordered_field_objects for field_object in ordered_field_objects: self.field_serializers.append(self._get_field_serializer(field_object)) diff --git a/backend/src/baserow/contrib/database/export_serialized.py b/backend/src/baserow/contrib/database/export_serialized.py index 13c7e7e7a..4cb4184b0 100644 --- a/backend/src/baserow/contrib/database/export_serialized.py +++ b/backend/src/baserow/contrib/database/export_serialized.py @@ -34,9 +34,13 @@ class DatabaseExportSerializedStructure: } @staticmethod - def file_field_value(name, visible_name, original_name): - return { + def file_field_value(name, visible_name, original_name, size=None): + data = { "name": name, "visible_name": visible_name, "original_name": original_name, } + + if size is not None: + data["size"] = size + return data diff --git a/backend/src/baserow/contrib/database/fields/constants.py b/backend/src/baserow/contrib/database/fields/constants.py index ba867b448..e03d46fc4 100644 --- a/backend/src/baserow/contrib/database/fields/constants.py +++ b/backend/src/baserow/contrib/database/fields/constants.py @@ -30,6 +30,7 @@ BASEROW_BOOLEAN_FIELD_FALSE_VALUES = [ "unchecked", False ] +SINGLE_SELECT_SORT_BY_ORDER = "order" class DeleteFieldStrategyEnum(Enum): diff --git a/backend/src/baserow/contrib/database/fields/exceptions.py b/backend/src/baserow/contrib/database/fields/exceptions.py index 6a95eade5..eb122712c 100644 --- a/backend/src/baserow/contrib/database/fields/exceptions.py +++ b/backend/src/baserow/contrib/database/fields/exceptions.py @@ -86,9 +86,17 @@ class OrderByFieldNotFound(Exception): class OrderByFieldNotPossible(Exception): """Raised when it is not possible to order by a field.""" - def __init__(self, field_name=None, field_type=None, *args, **kwargs): + def __init__( + self, + field_name: str = None, + field_type: str = None, + sort_type: str = None, + *args: list, + **kwargs: dict, + ): self.field_name = field_name self.field_type = field_type + self.sort_type = sort_type super().__init__(*args, **kwargs) diff --git a/backend/src/baserow/contrib/database/fields/field_filters.py b/backend/src/baserow/contrib/database/fields/field_filters.py index 4fed39282..6f8200b52 100644 --- a/backend/src/baserow/contrib/database/fields/field_filters.py +++ b/backend/src/baserow/contrib/database/fields/field_filters.py @@ -38,6 +38,42 @@ def parse_ids_from_csv_string(value: str) -> list[int]: return [] +def map_ids_from_csv_string( + value_string: str, mapping: Optional[dict] = None +) -> list[Union[str, int]]: + """ + Parses the provided value if needed and returns a list ids. + + :param value_string: The value that has been provided by the user. + :param mapping: Key is given option id, and the value is th target option id. + :return: A list of integers that represent ids. + """ + + # There is a small chance the value is an int in case a raw ID was provided in + # the row coloring, where the filters are stored as JSON. Cast it to a string to + # make it compatible. + if not isinstance(value_string, str): + value_string = str(value_string) + + parsed_values = [] + for value in value_string.split(","): + # In some cases, the select option ID is a string, like with the Airtable + # import. If the value can be found in the mapping, then we'll directly use + # that value. + if value in mapping: + parsed_values.append(str(mapping[value])) + continue + + if value.strip().isdigit(): + # Convert to int because the serialized value can be a string, but the key + # in the mapping is an int. + value = int(value) + if value in mapping: + parsed_values.append(str(mapping[value])) + + return parsed_values + + class AnnotatedQ: """ A simple wrapper class combining a params for a Queryset.annotate call with a diff --git a/backend/src/baserow/contrib/database/fields/field_helpers.py b/backend/src/baserow/contrib/database/fields/field_helpers.py index b8c1bf9ee..b1bf6828d 100644 --- a/backend/src/baserow/contrib/database/fields/field_helpers.py +++ b/backend/src/baserow/contrib/database/fields/field_helpers.py @@ -1,7 +1,11 @@ -from typing import Any, Dict, List +from typing import Any, Dict, List, Optional +from baserow.contrib.database.export_serialized import DatabaseExportSerializedStructure from baserow.contrib.database.fields.registries import field_type_registry from baserow.contrib.database.fields.utils.duration import D_H_M +from baserow.core.import_export.utils import file_chunk_generator +from baserow.core.storage import ExportZipFile, Storage +from baserow.core.user_files.handler import UserFileHandler def construct_all_possible_field_kwargs( @@ -295,3 +299,64 @@ def construct_all_possible_field_kwargs( all_interesting_field_kwargs.keys() ), "Please add the new field type to the testing dictionary of interesting kwargs" return all_interesting_field_kwargs + + +def prepare_files_for_export( + records: List[Dict[str, Any]], + cache: Dict[str, Any], + files_zip: Optional[ExportZipFile] = None, + storage: Optional[Storage] = None, + name_prefix: str = "", +) -> List[Dict[str, Any]]: + """ + Prepares file field values for export by either adding them to a zip file or + returning the serialized file data + + :param records: List of file records containing file metadata. + :param cache: A dictionary used to track which files have already been processed + to avoid duplicates. + :param files_zip: Optional ExportZipFile to add the actual file contents to. + :param storage: Optional storage backend to read the file contents from when adding + to zip. + :param name_prefix: Optional prefix to prepend to file names in the export. + :return: List of serialized file metadata + """ + + file_names = [] + user_file_handler = UserFileHandler() + + for record in records: + # Check if the user file object is already in the cache and if not, + # it must be fetched and added to it. + file_name = f"{name_prefix}{record['name']}" + cache_entry = f"user_file_{file_name}" + if cache_entry not in cache: + if files_zip is not None and file_name not in [ + item["name"] for item in files_zip.info_list() + ]: + file_path = user_file_handler.user_file_path(record["name"]) + # Create chunk generator for the file content and add it to the zip + # stream. That file will be read when zip stream is being + # written to final zip file + chunk_generator = file_chunk_generator(storage, file_path) + files_zip.add(chunk_generator, file_name) + + # This is just used to avoid writing the same file twice. + cache[cache_entry] = True + + if files_zip is None: + # If the zip file is `None`, it means we're duplicating this row. To + # avoid unnecessary queries, we jump add the complete file, and will + # use that during import instead of fetching the user file object. + file_names.append(record) + else: + file_names.append( + DatabaseExportSerializedStructure.file_field_value( + name=file_name, + visible_name=record["visible_name"], + original_name=record["name"], + size=record["size"], + ) + ) + + return file_names diff --git a/backend/src/baserow/contrib/database/fields/field_types.py b/backend/src/baserow/contrib/database/fields/field_types.py index 7b554707f..b5d25d575 100755 --- a/backend/src/baserow/contrib/database/fields/field_types.py +++ b/backend/src/baserow/contrib/database/fields/field_types.py @@ -93,7 +93,6 @@ from baserow.contrib.database.api.views.errors import ( ERROR_VIEW_NOT_IN_TABLE, ) from baserow.contrib.database.db.functions import RandomUUID -from baserow.contrib.database.export_serialized import DatabaseExportSerializedStructure from baserow.contrib.database.fields.filter_support.formula import ( FormulaFieldTypeArrayFilterSupport, ) @@ -132,7 +131,11 @@ from baserow.contrib.database.types import SerializedRowHistoryFieldMetadata from baserow.contrib.database.validators import UnicodeRegexValidator from baserow.contrib.database.views.exceptions import ViewDoesNotExist, ViewNotInTable from baserow.contrib.database.views.handler import ViewHandler -from baserow.contrib.database.views.models import OWNERSHIP_TYPE_COLLABORATIVE, View +from baserow.contrib.database.views.models import ( + DEFAULT_SORT_TYPE_KEY, + OWNERSHIP_TYPE_COLLABORATIVE, + View, +) from baserow.core.db import ( CombinedForeignKeyAndManyToManyMultipleFieldPrefetch, collate_expression, @@ -143,7 +146,6 @@ from baserow.core.fields import SyncedDateTimeField from baserow.core.formula import BaserowFormulaException from baserow.core.formula.parser.exceptions import FormulaFunctionTypeDoesNotExist from baserow.core.handler import CoreHandler -from baserow.core.import_export.utils import file_chunk_generator from baserow.core.models import UserFile, WorkspaceUser from baserow.core.registries import ImportExportConfig from baserow.core.storage import ExportZipFile, get_default_storage @@ -154,6 +156,7 @@ from baserow.core.utils import list_to_comma_separated_string from .constants import ( BASEROW_BOOLEAN_FIELD_FALSE_VALUES, BASEROW_BOOLEAN_FIELD_TRUE_VALUES, + SINGLE_SELECT_SORT_BY_ORDER, UPSERT_OPTION_DICT_KEY, DeleteFieldStrategyEnum, ) @@ -190,6 +193,7 @@ from .field_filters import ( filename_contains_filter, parse_ids_from_csv_string, ) +from .field_helpers import prepare_files_for_export from .field_sortings import OptionallyAnnotatedOrderBy from .fields import BaserowExpressionField, BaserowLastModifiedField from .fields import DurationField as DurationModelField @@ -260,7 +264,7 @@ if TYPE_CHECKING: class CollationSortMixin: def get_order( - self, field, field_name, order_direction, table_model=None + self, field, field_name, order_direction, sort_type, table_model=None ) -> OptionallyAnnotatedOrderBy: field_expr = collate_expression(F(field_name)) @@ -408,6 +412,8 @@ class TextFieldType(CollationSortMixin, FieldType): serializer_field_names = ["text_default"] _can_group_by = True + can_upsert = True + def get_serializer_field(self, instance, **kwargs): required = kwargs.get("required", False) return serializers.CharField( @@ -452,8 +458,9 @@ class LongTextFieldType(CollationSortMixin, FieldType): model_class = LongTextField allowed_fields = ["long_text_enable_rich_text"] serializer_field_names = ["long_text_enable_rich_text"] + can_upsert = True - def check_can_group_by(self, field: Field) -> bool: + def check_can_group_by(self, field: Field, sort_type: str) -> bool: return not field.long_text_enable_rich_text def can_be_primary_field(self, field_or_values: Union[Field, dict]) -> bool: @@ -566,6 +573,7 @@ class NumberFieldType(FieldType): } _can_group_by = True _db_column_fields = ["number_decimal_places"] + can_upsert = True def prepare_value_for_db(self, instance: NumberField, value): if value is None: @@ -807,6 +815,7 @@ class RatingFieldType(FieldType): serializer_field_names = ["max_value", "color", "style"] _can_group_by = True _db_column_fields = [] + can_upsert = True def prepare_value_for_db(self, instance, value): if not value: @@ -932,6 +941,7 @@ class BooleanFieldType(FieldType): type = "boolean" model_class = BooleanField _can_group_by = True + can_upsert = True def get_alter_column_prepare_new_value(self, connection, from_field, to_field): """ @@ -1021,6 +1031,7 @@ class DateFieldType(FieldType): } _can_group_by = True _db_column_fields = ["date_include_time"] + can_upsert = True def can_represent_date(self, field): return True @@ -1619,7 +1630,7 @@ class LastModifiedByFieldType(ReadOnlyFieldType): return user.email if user else None def get_order( - self, field, field_name, order_direction, table_model=None + self, field, field_name, order_direction, sort_type, table_model=None ) -> OptionallyAnnotatedOrderBy: """ If the user wants to sort the results they expect them to be ordered @@ -1627,7 +1638,7 @@ class LastModifiedByFieldType(ReadOnlyFieldType): """ order = collate_expression( - self.get_sortable_column_expression(field, field_name) + self.get_sortable_column_expression(field, field_name, sort_type) ) if order_direction == "ASC": @@ -1694,7 +1705,10 @@ class LastModifiedByFieldType(ReadOnlyFieldType): ) def get_sortable_column_expression( - self, field: Field, field_name: str + self, + field: Field, + field_name: str, + sort_type: str, ) -> Expression | F: return F(f"{field_name}__first_name") @@ -1833,7 +1847,7 @@ class CreatedByFieldType(ReadOnlyFieldType): return user.email if user else None def get_order( - self, field, field_name, order_direction, table_model=None + self, field, field_name, order_direction, sort_type, table_model=None ) -> OptionallyAnnotatedOrderBy: """ If the user wants to sort the results they expect them to be ordered @@ -1841,7 +1855,7 @@ class CreatedByFieldType(ReadOnlyFieldType): """ order = collate_expression( - self.get_sortable_column_expression(field, field_name) + self.get_sortable_column_expression(field, field_name, sort_type) ) if order_direction == "ASC": @@ -1908,7 +1922,10 @@ class CreatedByFieldType(ReadOnlyFieldType): ) def get_sortable_column_expression( - self, field: Field, field_name: str + self, + field: Field, + field_name: str, + sort_type: str, ) -> Expression | F: return F(f"{field_name}__first_name") @@ -1923,9 +1940,10 @@ class DurationFieldType(FieldType): serializer_field_names = ["duration_format"] _can_group_by = True _db_column_fields = [] + can_upsert = True def get_model_field(self, instance: DurationField, **kwargs): - return DurationModelField(instance.duration_format, null=True) + return DurationModelField(instance.duration_format, null=True, **kwargs) def get_serializer_field(self, instance: DurationField, **kwargs): return DurationFieldSerializer( @@ -2070,7 +2088,10 @@ class DurationFieldType(FieldType): setattr(row, field_name, value) def get_sortable_column_expression( - self, field: Field, field_name: str + self, + field: Field, + field_name: str, + sort_type: str, ) -> Expression | F: return F(f"{field_name}") @@ -2190,16 +2211,18 @@ class LinkRowFieldType( return field.specific.link_row_table_primary_field def _check_related_field_can_order_by( - self, related_primary_field: Type[Field] + self, + related_primary_field: Type[Field], + order_type: str, ) -> bool: related_primary_field_type = field_type_registry.get_by_model( related_primary_field.specific_class ) return related_primary_field_type.check_can_order_by( - related_primary_field.specific + related_primary_field.specific, order_type ) - def check_can_group_by(self, field): + def check_can_group_by(self, field, sort_type): related_primary_field = self._get_related_table_primary_field(field) if related_primary_field is None: return False @@ -2207,7 +2230,9 @@ class LinkRowFieldType( related_primary_field_type = field_type_registry.get_by_model( related_primary_field ) - return related_primary_field_type.check_can_group_by(related_primary_field) + return related_primary_field_type.check_can_group_by( + related_primary_field, sort_type + ) def _get_group_by_agg_expression(self, field_name: str) -> dict: return ArrayAgg( @@ -2221,11 +2246,13 @@ class LinkRowFieldType( distinct=True, ) - def check_can_order_by(self, field: Field) -> bool: + def check_can_order_by(self, field: Field, sort_type: str) -> bool: related_primary_field = self._get_related_table_primary_field(field) if related_primary_field is None: return False - return self._check_related_field_can_order_by(related_primary_field.specific) + return self._check_related_field_can_order_by( + related_primary_field.specific, sort_type + ) def get_value_for_filter(self, row: "GeneratedTableModel", field): related_primary_field = self._get_related_table_primary_field( @@ -2241,7 +2268,9 @@ class LinkRowFieldType( row, related_primary_field ) - def get_order(self, field, field_name, order_direction, table_model=None): + def get_order( + self, field, field_name, order_direction, sort_type, table_model=None + ): related_primary_field = self._get_related_table_primary_field( field, table_model ) @@ -2249,7 +2278,9 @@ class LinkRowFieldType( raise ValueError("Cannot find the related primary field.") related_primary_field = related_primary_field.specific - if not self._check_related_field_can_order_by(related_primary_field): + if not self._check_related_field_can_order_by( + related_primary_field, DEFAULT_SORT_TYPE_KEY + ): raise ValueError( "The primary field for the related table cannot be ordered by." ) @@ -2260,6 +2291,7 @@ class LinkRowFieldType( related_primary_field_type.get_sortable_column_expression( related_primary_field, f"{field_name}__{related_primary_field.db_column}", + sort_type, ) ) @@ -3434,6 +3466,9 @@ class LinkRowFieldType( **already_serialized_linked_rows, **new_serialized_linked_rows, }, + "linked_table_id": field.link_row_table_id, + "linked_field_id": field.link_row_related_field_id, + "primary_value": str(row), } def are_row_values_equal(self, value1: any, value2: any) -> bool: @@ -3461,6 +3496,7 @@ class LinkRowFieldType( class EmailFieldType(CollationSortMixin, CharFieldMatchingRegexFieldType): type = "email" model_class = EmailField + can_upsert = True @property def regex(self): @@ -3496,7 +3532,7 @@ class FileFieldType(FieldType): model_class = FileField can_be_in_form_view = True can_get_unique_values = False - _can_order_by = False + _can_order_by_types = [] def to_baserow_formula_type(self, field) -> BaserowFormulaType: return BaserowFormulaArrayType(BaserowFormulaSingleFileType(nullable=True)) @@ -3731,43 +3767,15 @@ class FileFieldType(FieldType): cache: Dict[str, Any], files_zip: Optional[ExportZipFile] = None, storage: Optional[Storage] = None, + name_prefix: str = "", ) -> List[Dict[str, Any]]: - file_names = [] - user_file_handler = UserFileHandler() - - for file in self.get_internal_value_from_db(row, field_name): - # Check if the user file object is already in the cache and if not, - # it must be fetched and added to it. - cache_entry = f"user_file_{file['name']}" - if cache_entry not in cache: - if files_zip is not None and file["name"] not in [ - item["name"] for item in files_zip.info_list() - ]: - file_path = user_file_handler.user_file_path(file["name"]) - # Create chunk generator for the file content and add it to the zip - # stream. That file will be read when zip stream is being - # written to final zip file - chunk_generator = file_chunk_generator(storage, file_path) - files_zip.add(chunk_generator, file["name"]) - - # This is just used to avoid writing the same file twice. - cache[cache_entry] = True - - if files_zip is None: - # If the zip file is `None`, it means we're duplicating this row. To - # avoid unnecessary queries, we jump add the complete file, and will - # use that during import instead of fetching the user file object. - file_names.append(file) - else: - file_names.append( - DatabaseExportSerializedStructure.file_field_value( - name=file["name"], - visible_name=file["visible_name"], - original_name=file["name"], - ) - ) - - return file_names + return prepare_files_for_export( + self.get_internal_value_from_db(row, field_name), + cache, + files_zip, + storage, + name_prefix, + ) def set_import_serialized_value( self, @@ -3877,7 +3885,10 @@ class SelectOptionBaseFieldType(FieldType): return queryset def get_sortable_column_expression( - self, field: Field, field_name: str + self, + field: Field, + field_name: str, + sort_type: str, ) -> Expression | F: return F(f"{field_name}__value") @@ -3899,6 +3910,7 @@ class SelectOptionBaseFieldType(FieldType): class SingleSelectFieldType(CollationSortMixin, SelectOptionBaseFieldType): type = "single_select" model_class = SingleSelectField + _can_order_by_types = [DEFAULT_SORT_TYPE_KEY, SINGLE_SELECT_SORT_BY_ORDER] def get_serializer_field(self, instance, **kwargs): required = kwargs.get("required", False) @@ -4152,8 +4164,19 @@ class SingleSelectFieldType(CollationSortMixin, SelectOptionBaseFieldType): connection, from_field, to_field ) + def get_sortable_column_expression( + self, + field: Field, + field_name: str, + sort_type: str, + ) -> Expression | F: + if sort_type == SINGLE_SELECT_SORT_BY_ORDER: + return F(f"{field_name}__order") + else: + return super().get_sortable_column_expression(field, field_name, sort_type) + def get_order( - self, field, field_name, order_direction, table_model=None + self, field, field_name, order_direction, sort_type, table_model=None ) -> OptionallyAnnotatedOrderBy: """ If the user wants to sort the results they expect them to be ordered @@ -4162,10 +4185,15 @@ class SingleSelectFieldType(CollationSortMixin, SelectOptionBaseFieldType): to the correct position. """ - order = collate_expression( - self.get_sortable_column_expression(field, field_name) + column_expression = self.get_sortable_column_expression( + field, field_name, sort_type ) + if sort_type == SINGLE_SELECT_SORT_BY_ORDER: + order = column_expression + else: + order = collate_expression(column_expression) + if order_direction == "ASC": order = order.asc(nulls_first=True) else: @@ -4613,7 +4641,9 @@ class MultipleSelectFieldType( q={f"select_option_value_{field_name}__iregex": rf"\m{value}\M"}, ) - def get_order(self, field, field_name, order_direction, table_model=None): + def get_order( + self, field, field_name, order_direction, sort_type, table_model=None + ): """ Order by the concatenated values of the select options, separated by a comma. """ @@ -4626,7 +4656,7 @@ class MultipleSelectFieldType( sort_column_name = f"{field_name}_agg_sort" query = Coalesce( StringAgg( - self.get_sortable_column_expression(field, field_name), + self.get_sortable_column_expression(field, field_name, sort_type), ",", output_field=models.TextField(), ), @@ -4726,6 +4756,7 @@ class PhoneNumberFieldType(CollationSortMixin, CharFieldMatchingRegexFieldType): type = "phone_number" model_class = PhoneNumberField + can_upsert = True MAX_PHONE_NUMBER_LENGTH = 100 @@ -5284,15 +5315,22 @@ class FormulaFieldType(FormulaFieldTypeArrayFilterSupport, ReadOnlyFieldType): if apply_updates: update_collector.apply_updates_and_get_updated_fields(field_cache) - def check_can_order_by(self, field): + def check_can_order_by(self, field, order_type): + # The formula types are not compatible with the order type. Therefore, + # if the `order_type` is not the default, it will always return False. + if order_type != DEFAULT_SORT_TYPE_KEY: + return False return self.to_baserow_formula_type(field.specific).can_order_by - def check_can_group_by(self, field): + def check_can_group_by(self, field, sort_type): + # The formula types are not compatible with the order type. Therefore, + # if the `order_type` is not the default, it will always return False. return self.to_baserow_formula_type(field.specific).can_group_by def get_order( - self, field, field_name, order_direction, table_model=None + self, field, field_name, order_direction, sort_type, table_model=None ) -> OptionallyAnnotatedOrderBy: + # Ignore the `sort_type` because that is not yet supported in formulas. return self.to_baserow_formula_type(field.specific).get_order( field, field_name, order_direction, table_model=table_model ) @@ -6039,7 +6077,10 @@ class LookupFieldType(FormulaFieldType): class MultipleCollaboratorsFieldType( - CollationSortMixin, ManyToManyFieldTypeSerializeToInputValueMixin, FieldType + CollationSortMixin, + ManyToManyFieldTypeSerializeToInputValueMixin, + ManyToManyGroupByMixin, + FieldType, ): type = "multiple_collaborators" model_class = MultipleCollaboratorsField @@ -6055,6 +6096,7 @@ class MultipleCollaboratorsFieldType( "notify_user_when_added": serializers.BooleanField(required=False), } is_many_to_many_field = True + _can_group_by = True def get_serializer_field(self, instance, **kwargs): required = kwargs.pop("required", False) @@ -6368,7 +6410,9 @@ class MultipleCollaboratorsFieldType( def random_to_input_value(self, field, value): return [{"id": user_id} for user_id in value] - def get_order(self, field, field_name, order_direction, table_model=None): + def get_order( + self, field, field_name, order_direction, sort_type, table_model=None + ): """ If the user wants to sort the results they expect them to be ordered alphabetically based on the user's name and not in the id which is @@ -6379,7 +6423,7 @@ class MultipleCollaboratorsFieldType( sort_column_name = f"{field_name}_agg_sort" query = Coalesce( StringAgg( - self.get_sortable_column_expression(field, field_name), + self.get_sortable_column_expression(field, field_name, sort_type), "", output_field=models.TextField(), ), @@ -6404,7 +6448,10 @@ class MultipleCollaboratorsFieldType( return value def get_sortable_column_expression( - self, field: Field, field_name: str + self, + field: Field, + field_name: str, + sort_type: str, ) -> Expression | F: return F(f"{field_name}__first_name") @@ -6422,13 +6469,17 @@ class MultipleCollaboratorsFieldType( JSONBAgg( get_collaborator_extractor(db_column, model_field), filter=Q(**{f"{db_column}__isnull": False}), + order=f"{db_column}__id", ), Value([], output_field=JSONField()), ) else: return Coalesce( wrap_in_subquery( - JSONBAgg(get_collaborator_extractor(db_column, model_field)), + JSONBAgg( + get_collaborator_extractor(db_column, model_field), + order=f"{db_column}__id", + ), db_column, model_field.model, ), @@ -6757,7 +6808,7 @@ class PasswordFieldType(FieldType): model_class = PasswordField can_be_in_form_view = True keep_data_on_duplication = True - _can_order_by = False + _can_order_by_types = [] _can_be_primary_field = False can_get_unique_values = False @@ -6803,7 +6854,7 @@ class PasswordFieldType(FieldType): # `False` as string depending on whether the value is set. return bool(value) - def prepare_row_history_value_from_action_meta_data(self, value): + def prepare_value_for_row_history(self, value): # We don't want to expose the hash of the password, so we just show `True` or # `False` as string depending on whether the value is set. return bool(value) diff --git a/backend/src/baserow/contrib/database/fields/handler.py b/backend/src/baserow/contrib/database/fields/handler.py index 89736208f..6838f6a9f 100644 --- a/backend/src/baserow/contrib/database/fields/handler.py +++ b/backend/src/baserow/contrib/database/fields/handler.py @@ -363,7 +363,7 @@ class FieldHandler(metaclass=baserow_trace_methods(tracer)): # already exists. If so the field cannot be created and an exception is raised. if primary and Field.objects.filter(table=table, primary=True).exists(): raise PrimaryFieldAlreadyExists( - f"A primary field already exists for the " f"table {table}." + f"A primary field already exists for the table {table}." ) # Figure out which model to use and which field types are allowed for the given @@ -579,6 +579,7 @@ class FieldHandler(metaclass=baserow_trace_methods(tracer)): raise IncompatiblePrimaryFieldTypeError(to_field_type_name) if baserow_field_type_changed: + ViewHandler().before_field_type_change(field) dependants_broken_due_to_type_change = ( from_field_type.get_dependants_which_will_break_when_field_type_changes( field, to_field_type, field_cache diff --git a/backend/src/baserow/contrib/database/fields/models.py b/backend/src/baserow/contrib/database/fields/models.py index 001f5c8f5..116992ed5 100644 --- a/backend/src/baserow/contrib/database/fields/models.py +++ b/backend/src/baserow/contrib/database/fields/models.py @@ -498,6 +498,11 @@ class LinkRowField(Field): @property def link_row_table_primary_field(self): + # It's possible to optionally preset the `link_row_table_primary_field` using + # the setter. If that's the case, then it must be returned. + if hasattr(self, "_link_row_table_primary_field"): + return self._link_row_table_primary_field + # LinkRowFieldType.enhance_field_queryset prefetches the primary field # into RELATED_PPRIMARY_FIELD_ATTR. Let's check if it's already there first. if related_primary_field_set := getattr( @@ -510,6 +515,10 @@ class LinkRowField(Field): except Field.DoesNotExist: return None + @link_row_table_primary_field.setter + def link_row_table_primary_field(self, value): + self._link_row_table_primary_field = value + @property def is_self_referencing(self): return self.link_row_table_id == self.table_id diff --git a/backend/src/baserow/contrib/database/fields/registries.py b/backend/src/baserow/contrib/database/fields/registries.py index 528d311ab..b1e2cb7fd 100644 --- a/backend/src/baserow/contrib/database/fields/registries.py +++ b/backend/src/baserow/contrib/database/fields/registries.py @@ -66,6 +66,7 @@ from baserow.core.registry import ( Registry, ) +from ..views.models import DEFAULT_SORT_TYPE_KEY from .exceptions import ( FieldTypeAlreadyRegistered, FieldTypeDoesNotExist, @@ -126,8 +127,11 @@ class FieldType( field_type_registry.register(ExampleFieldType()) """ - _can_order_by = True - """Indicates whether it is possible to order by this field type.""" + _can_order_by_types = [DEFAULT_SORT_TYPE_KEY] + """ + Indicates by which types can be ordered. Leave empty if it's not possible to sort + by the field type. + """ _can_be_primary_field = True """Some field types cannot be the primary field.""" @@ -206,6 +210,12 @@ class FieldType( some fields can depend on it like the `lookup` field. """ + can_upsert = False + """ + A field of this type may be used to calculate a match value during import, that + allows to update existing rows with imported data instead of adding them. + """ + @property def db_column_fields(self) -> Set[str]: if self._db_column_fields is not None: @@ -280,9 +290,9 @@ class FieldType( return getattr(row, field_name) - def prepare_row_history_value_from_action_meta_data(self, value): + def prepare_value_for_row_history(self, value): """ - Prepare the row action update action meta data value for the row history. + Prepare the value for the row history. This can be used to change the value to a different format if needed. It's for example used by the password field to mask the hash. """ @@ -855,15 +865,16 @@ class FieldType( field: Type[Field], field_name: str, order_direction: str, + sort_type: str, table_model: Optional["GeneratedTableModel"] = None, ) -> OptionallyAnnotatedOrderBy: """ This hook can be called to generate a different order by expression. - By default the normal field sorting will be applied. + By default, the normal field sorting will be applied. Optionally a different expression can be generated. This is for example used by the single select field generates a mapping achieve the correct sorting based on the select option value. - Additionally an annotation can be returned which will get applied to the + Additionally, an annotation can be returned which will get applied to the queryset. If you are implementing this method you should also implement the get_value_for_filter method. @@ -871,13 +882,15 @@ class FieldType( :param field: The related field object instance. :param field_name: The name of the field. :param order_direction: The sort order direction (either "ASC" or "DESC"). + :param sort_type: The sort type that must be used, `default` is set as default + when the sort is created. :param table_model: The table model instance that the field is part of, if available. :return: Either the expression that is added directly to the model.objects.order(), an AnnotatedOrderBy class or None. """ - field_expr = self.get_sortable_column_expression(field, field_name) + field_expr = self.get_sortable_column_expression(field, field_name, sort_type) if order_direction == "ASC": field_order_by = field_expr.asc(nulls_first=True) @@ -1602,36 +1615,38 @@ class FieldType( return self._can_filter_by - def check_can_order_by(self, field: Field) -> bool: + def check_can_order_by(self, field: Field, sort_type: str) -> bool: """ Override this method if this field type can sometimes be ordered or sometimes - cannot be ordered depending on the individual field state. By default will just - return the bool property _can_order_by so if your field type doesn't depend - on the field state and is always just True or False just set _can_order_by - to the desired value. + cannot be ordered depending on the individual field state. By default, it will + check if the provided `sort_type` is in the `_can_order_by_types` property. :param field: The field to check to see if it can be ordered by or not. + :param sort_type: The sort type to check if it's compatible. :return: True if a view can be ordered by this field, False otherwise. """ - return self._can_order_by + return sort_type in self._can_order_by_types - def check_can_group_by(self, field: Field) -> bool: + def check_can_group_by(self, field: Field, sort_type: str) -> bool: """ Override this method if this field type can sometimes be grouped or sometimes cannot be grouped depending on the individual field state. By default will just - return the bool property _can_group_by so if your field type doesn't depend - on the field state and is always just True or False just set _can_group_by - to the desired value. + return the bool property _can_group_by and checks if the sort_type is in the + `_can_order_by_types` property. :param field: The field to check to see if it can be grouped by or not. + :param sort_type: The sort type to check if it's compatible. :return: True if a view can be grouped by this field, False otherwise. """ - return self._can_group_by + return self._can_group_by and self.check_can_order_by(field, sort_type) def get_sortable_column_expression( - self, field: Field, field_name: str + self, + field: Field, + field_name: str, + sort_type: str, ) -> Expression | F: """ Returns the expression that can be used to sort the field in the database. @@ -1640,6 +1655,8 @@ class FieldType( :param field: The field where to get the sortable column expression for. :param field_name: The name of the field in the table. + :param sort_type: The sort type that must be used, `default` is set as default + when the sort is created. :return: The expression that can be used to sort the field in the database. """ diff --git a/backend/src/baserow/contrib/database/fields/tasks.py b/backend/src/baserow/contrib/database/fields/tasks.py index 6ff8d915c..c24150d31 100644 --- a/backend/src/baserow/contrib/database/fields/tasks.py +++ b/backend/src/baserow/contrib/database/fields/tasks.py @@ -95,10 +95,14 @@ def _run_periodic_field_type_update_per_workspace( all_updated_fields = [] - fields = qs.filter( - table__database__workspace_id=workspace.id, - table__trashed=False, - table__database__trashed=False, + fields = ( + qs.filter( + table__database__workspace_id=workspace.id, + table__trashed=False, + table__database__trashed=False, + ) + .select_related("table") + .prefetch_related("table__view_set") ) # noinspection PyBroadException try: @@ -114,6 +118,8 @@ def _run_periodic_field_type_update_per_workspace( tb=tb, ) + from baserow.contrib.database.views.handler import ViewSubscriptionHandler + # After a successful periodic update of all fields, we would need to update the # search index for all of them in one function per table to avoid ending up in a # deadlock because rows are updated simultaneously. @@ -123,6 +129,11 @@ def _run_periodic_field_type_update_per_workspace( for _, fields in fields_per_table.items(): SearchHandler().entire_field_values_changed_or_created(fields[0].table, fields) + with transaction.atomic(): + ViewSubscriptionHandler().notify_table_views_updates( + fields[0].table.view_set.all() + ) + @app.task(bind=True) def delete_mentions_marked_for_deletion(self): diff --git a/backend/src/baserow/contrib/database/file_import/job_types.py b/backend/src/baserow/contrib/database/file_import/job_types.py index c79d21f8a..753e2d4ec 100644 --- a/backend/src/baserow/contrib/database/file_import/job_types.py +++ b/backend/src/baserow/contrib/database/file_import/job_types.py @@ -26,6 +26,7 @@ from baserow.contrib.database.fields.exceptions import ( ) from baserow.contrib.database.rows.actions import ImportRowsActionType from baserow.contrib.database.rows.exceptions import ReportMaxErrorCountExceeded +from baserow.contrib.database.rows.types import FileImportDict from baserow.contrib.database.table.actions import CreateTableActionType from baserow.contrib.database.table.exceptions import ( InitialTableDataDuplicateName, @@ -91,6 +92,7 @@ class FileImportJobType(JobType): filtered_dict = dict(**values) filtered_dict.pop("data") + filtered_dict.pop("configuration", None) return filtered_dict def after_job_creation(self, job, values): @@ -99,7 +101,10 @@ class FileImportJobType(JobType): """ data_file = ContentFile( - json.dumps(values["data"], ensure_ascii=False).encode("utf8") + json.dumps( + {"data": values["data"], "configuration": values.get("configuration")}, + ensure_ascii=False, + ).encode("utf8") ) job.data_file.save(None, data_file) @@ -154,8 +159,7 @@ class FileImportJobType(JobType): """ with job.data_file.open("r") as fin: - data = json.load(fin) - + data: FileImportDict = json.load(fin) try: if job.table is None: new_table, error_report = action_type_registry.get_by_type( @@ -164,7 +168,7 @@ class FileImportJobType(JobType): job.user, job.database, name=job.name, - data=data, + data=data["data"], first_row_header=job.first_row_header, progress=progress, ) diff --git a/backend/src/baserow/contrib/database/locale/en/LC_MESSAGES/django.po b/backend/src/baserow/contrib/database/locale/en/LC_MESSAGES/django.po index cf1987b19..a9bf9b0e7 100644 --- a/backend/src/baserow/contrib/database/locale/en/LC_MESSAGES/django.po +++ b/backend/src/baserow/contrib/database/locale/en/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-01-15 11:59+0000\n" +"POT-Creation-Date: 2025-03-18 19:55+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Language-Team: LANGUAGE <LL@li.org>\n" @@ -38,11 +38,11 @@ msgid "" "\"%(database_name)s\" (%(database_id)s)." msgstr "" -#: src/baserow/contrib/database/airtable/actions.py:22 +#: src/baserow/contrib/database/airtable/actions.py:23 msgid "Import database from Airtable" msgstr "" -#: src/baserow/contrib/database/airtable/actions.py:24 +#: src/baserow/contrib/database/airtable/actions.py:25 #, python-format msgid "" "Imported database " @@ -80,7 +80,7 @@ msgstr "" msgid "The data sync synchronized" msgstr "" -#: src/baserow/contrib/database/data_sync/handler.py:186 +#: src/baserow/contrib/database/data_sync/handler.py:187 #: src/baserow/contrib/database/table/handler.py:548 msgid "Grid" msgstr "" @@ -148,8 +148,8 @@ msgid "" "%(new_primary_field_name)s" msgstr "" -#: src/baserow/contrib/database/fields/models.py:415 -#: src/baserow/contrib/database/fields/models.py:594 +#: src/baserow/contrib/database/fields/models.py:453 +#: src/baserow/contrib/database/fields/models.py:641 msgid "The format of the duration." msgstr "" @@ -458,155 +458,155 @@ msgstr "" msgid "View sorted on field \"%(field_name)s\" (%(field_id)s)" msgstr "" -#: src/baserow/contrib/database/views/actions.py:832 +#: src/baserow/contrib/database/views/actions.py:849 msgid "Update a view sort" msgstr "" -#: src/baserow/contrib/database/views/actions.py:833 +#: src/baserow/contrib/database/views/actions.py:850 #, python-format msgid "View sort updated on field \"%(field_name)s\" (%(field_id)s)" msgstr "" -#: src/baserow/contrib/database/views/actions.py:941 +#: src/baserow/contrib/database/views/actions.py:978 msgid "Delete a view sort" msgstr "" -#: src/baserow/contrib/database/views/actions.py:942 +#: src/baserow/contrib/database/views/actions.py:979 #, python-format msgid "View sort deleted from field \"%(field_name)s\" (%(field_id)s)" msgstr "" -#: src/baserow/contrib/database/views/actions.py:1027 +#: src/baserow/contrib/database/views/actions.py:1073 msgid "Order views" msgstr "" -#: src/baserow/contrib/database/views/actions.py:1027 +#: src/baserow/contrib/database/views/actions.py:1073 msgid "Views order changed" msgstr "" -#: src/baserow/contrib/database/views/actions.py:1098 +#: src/baserow/contrib/database/views/actions.py:1144 msgid "Update view field options" msgstr "" -#: src/baserow/contrib/database/views/actions.py:1099 +#: src/baserow/contrib/database/views/actions.py:1145 msgid "ViewFieldOptions updated" msgstr "" -#: src/baserow/contrib/database/views/actions.py:1200 +#: src/baserow/contrib/database/views/actions.py:1247 msgid "View slug URL updated" msgstr "" -#: src/baserow/contrib/database/views/actions.py:1201 +#: src/baserow/contrib/database/views/actions.py:1248 msgid "View changed public slug URL" msgstr "" -#: src/baserow/contrib/database/views/actions.py:1274 +#: src/baserow/contrib/database/views/actions.py:1321 msgid "Update view" msgstr "" -#: src/baserow/contrib/database/views/actions.py:1275 +#: src/baserow/contrib/database/views/actions.py:1322 #, python-format msgid "View \"%(view_name)s\" (%(view_id)s) updated" msgstr "" -#: src/baserow/contrib/database/views/actions.py:1356 +#: src/baserow/contrib/database/views/actions.py:1403 msgid "Create view" msgstr "" -#: src/baserow/contrib/database/views/actions.py:1357 +#: src/baserow/contrib/database/views/actions.py:1404 #, python-format msgid "View \"%(view_name)s\" (%(view_id)s) created" msgstr "" -#: src/baserow/contrib/database/views/actions.py:1431 +#: src/baserow/contrib/database/views/actions.py:1478 msgid "Duplicate view" msgstr "" -#: src/baserow/contrib/database/views/actions.py:1433 +#: src/baserow/contrib/database/views/actions.py:1480 #, python-format msgid "" "View \"%(view_name)s\" (%(view_id)s) duplicated from view " "\"%(original_view_name)s\" (%(original_view_id)s)" msgstr "" -#: src/baserow/contrib/database/views/actions.py:1507 +#: src/baserow/contrib/database/views/actions.py:1554 msgid "Delete view" msgstr "" -#: src/baserow/contrib/database/views/actions.py:1508 +#: src/baserow/contrib/database/views/actions.py:1555 #, python-format msgid "View \"%(view_name)s\" (%(view_id)s) deleted" msgstr "" -#: src/baserow/contrib/database/views/actions.py:1570 +#: src/baserow/contrib/database/views/actions.py:1617 msgid "Create decoration" msgstr "" -#: src/baserow/contrib/database/views/actions.py:1571 +#: src/baserow/contrib/database/views/actions.py:1618 #, python-format msgid "View decoration %(decorator_id)s created" msgstr "" -#: src/baserow/contrib/database/views/actions.py:1675 +#: src/baserow/contrib/database/views/actions.py:1722 msgid "Update decoration" msgstr "" -#: src/baserow/contrib/database/views/actions.py:1676 +#: src/baserow/contrib/database/views/actions.py:1723 #, python-format msgid "View decoration %(decorator_id)s updated" msgstr "" -#: src/baserow/contrib/database/views/actions.py:1813 +#: src/baserow/contrib/database/views/actions.py:1860 msgid "Delete decoration" msgstr "" -#: src/baserow/contrib/database/views/actions.py:1814 +#: src/baserow/contrib/database/views/actions.py:1861 #, python-format msgid "View decoration %(decorator_id)s deleted" msgstr "" -#: src/baserow/contrib/database/views/actions.py:1910 +#: src/baserow/contrib/database/views/actions.py:1957 msgid "Create a view group" msgstr "" -#: src/baserow/contrib/database/views/actions.py:1911 +#: src/baserow/contrib/database/views/actions.py:1958 #, python-format msgid "View grouped on field \"%(field_name)s\" (%(field_id)s)" msgstr "" -#: src/baserow/contrib/database/views/actions.py:2011 +#: src/baserow/contrib/database/views/actions.py:2063 msgid "Update a view group" msgstr "" -#: src/baserow/contrib/database/views/actions.py:2012 +#: src/baserow/contrib/database/views/actions.py:2064 #, python-format msgid "View group by updated on field \"%(field_name)s\" (%(field_id)s)" msgstr "" -#: src/baserow/contrib/database/views/actions.py:2140 +#: src/baserow/contrib/database/views/actions.py:2213 msgid "Delete a view group" msgstr "" -#: src/baserow/contrib/database/views/actions.py:2141 +#: src/baserow/contrib/database/views/actions.py:2214 #, python-format msgid "View group by deleted from field \"%(field_name)s\" (%(field_id)s)" msgstr "" -#: src/baserow/contrib/database/views/actions.py:2235 +#: src/baserow/contrib/database/views/actions.py:2312 msgid "Submit form" msgstr "" -#: src/baserow/contrib/database/views/actions.py:2236 +#: src/baserow/contrib/database/views/actions.py:2313 #, python-format msgid "Row (%(row_id)s) created via form submission" msgstr "" -#: src/baserow/contrib/database/views/notification_types.py:84 +#: src/baserow/contrib/database/views/notification_types.py:86 #, python-format msgid "%(form_name)s has been submitted in %(table_name)s" msgstr "" -#: src/baserow/contrib/database/views/notification_types.py:101 +#: src/baserow/contrib/database/views/notification_types.py:103 #, python-format msgid "and 1 more field" msgid_plural "and %(count)s more fields" @@ -645,3 +645,28 @@ msgid "" "Webhook \"%(webhook_name)s\" (%(webhook_id)s) as %(webhook_request_method)s " "to %(webhook_url)s\" updated" msgstr "" + +#: src/baserow/contrib/database/webhooks/notification_types.py:92 +#, python-format +msgid "%(name)s webhook has been deactivated." +msgstr "" + +#: src/baserow/contrib/database/webhooks/notification_types.py:99 +#, python-format +msgid "" +"The webhook failed more than %(max_failures)s consecutive times and was " +"therefore deactivated." +msgstr "" + +#: src/baserow/contrib/database/webhooks/notification_types.py:155 +#, python-format +msgid "%(name)s webhook payload too large." +msgstr "" + +#: src/baserow/contrib/database/webhooks/notification_types.py:162 +#, python-format +msgid "" +"The payload for the %(name)s webhook with event ID %(event_id)s was too " +"large. The content has been split into multiple batches, but data above the " +"batch limit of %(batch_limit)s was discarded." +msgstr "" diff --git a/backend/src/baserow/contrib/database/locale/fr/LC_MESSAGES/django.po b/backend/src/baserow/contrib/database/locale/fr/LC_MESSAGES/django.po index a8642467d..c2dcc2a3a 100644 --- a/backend/src/baserow/contrib/database/locale/fr/LC_MESSAGES/django.po +++ b/backend/src/baserow/contrib/database/locale/fr/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2024-01-18 13:32+0000\n" -"PO-Revision-Date: 2024-01-19 09:37+0000\n" +"PO-Revision-Date: 2025-03-18 13:24+0000\n" "Last-Translator: Jérémie Pardou-Piquemal <jrmi@jeremiez.net>\n" "Language-Team: French <https://hosted.weblate.org/projects/baserow/" "backend-database/fr/>\n" @@ -17,7 +17,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n > 1;\n" -"X-Generator: Weblate 5.4-dev\n" +"X-Generator: Weblate 5.11-dev\n" #: src/baserow/contrib/database/action/scopes.py:9 #, python-format @@ -180,7 +180,7 @@ msgstr "Machine de Turing" #: src/baserow/contrib/database/plugins.py:103 msgid "Computer architecture" -msgstr "Architecture des ordinateur" +msgstr "Architecture de l'ordinateur" #: src/baserow/contrib/database/plugins.py:104 msgid "Cellular Automata" diff --git a/backend/src/baserow/contrib/database/management/commands/install_airtable_templates.py b/backend/src/baserow/contrib/database/management/commands/install_airtable_templates.py new file mode 100644 index 000000000..fb677e6fc --- /dev/null +++ b/backend/src/baserow/contrib/database/management/commands/install_airtable_templates.py @@ -0,0 +1,146 @@ +import json +import re +import sys +from tempfile import NamedTemporaryFile + +from django.core.management.base import BaseCommand +from django.db import transaction + +import requests +from tqdm import tqdm + +from baserow.contrib.database.airtable.config import AirtableImportConfig +from baserow.contrib.database.airtable.constants import AIRTABLE_BASE_URL +from baserow.contrib.database.airtable.exceptions import AirtableBaseNotPublic +from baserow.contrib.database.airtable.handler import BASE_HEADERS, AirtableHandler +from baserow.contrib.database.airtable.utils import ( + parse_json_and_remove_invalid_surrogate_characters, +) +from baserow.core.models import Workspace +from baserow.core.utils import Progress, remove_invalid_surrogate_characters + + +class Command(BaseCommand): + help = ( + "This command fetches all Airtable templates, and attemps to import them into " + "the given workspace. It's created for testing purposes of the Airtable import." + ) + + def add_arguments(self, parser): + parser.add_argument( + "workspace_id", + type=int, + help="The workspace ID where a copy of the imported Airtable base must be " + "added to.", + ) + parser.add_argument( + "--start", + type=int, + help="From which index should the import start.", + default=0, + ) + parser.add_argument( + "--limit", + type=int, + help="The maximum number of templates to install.", + default=-1, + ) + + def handle(self, *args, **options): + workspace_id = options["workspace_id"] + start_index = options["start"] + limit = options["limit"] + + try: + workspace = Workspace.objects.get(pk=workspace_id) + except Workspace.DoesNotExist: + self.stdout.write( + self.style.ERROR(f"The workspace with id {workspace_id} was not found.") + ) + sys.exit(1) + + html_url = f"{AIRTABLE_BASE_URL}/templates" + html_response = requests.get(html_url, headers=BASE_HEADERS) # nosec + + if not html_response.ok: + raise Exception("test") + + decoded_content = remove_invalid_surrogate_characters(html_response.content) + raw_init_data = re.search( + "window.initData = (.*?)<\\/script>", decoded_content + ).group(1) + init_data = json.loads(raw_init_data) + client_code_version = init_data["codeVersion"] + page_load_id = init_data["pageLoadId"] + + templates_url = ( + f"{AIRTABLE_BASE_URL}/v0.3/exploreApplications" + f"?templateStatus=listed" + f"&shouldDisplayFull=true" + f"&descriptionSnippetMaxLength=300" + f"&categoryType=templateDesktopV2" + ) + + response = requests.get( + templates_url, + headers={ + "x-airtable-inter-service-client": "webClient", + "x-airtable-inter-service-client-code-version": client_code_version, + "x-airtable-page-load-id": page_load_id, + "X-Requested-With": "XMLHttpRequest", + "x-time-zone": "Europe/Amsterdam", + "x-user-locale": "en", + **BASE_HEADERS, + }, + timeout=3 * 60, + ) # nosec + + json_decoded_content = parse_json_and_remove_invalid_surrogate_characters( + response + ) + + applications_by_id = json_decoded_content["exploreApplicationsById"].values() + i = 0 + for index, application in enumerate(applications_by_id): + share_id = application["shareId"] + title = application["title"] + + if limit != -1 and i >= limit: + print("finished!") + return + + if index < start_index - 1: + print( + f"Skipping {title} {share_id} {index + 1}/{len(applications_by_id)}" + ) + continue + + i += 1 + print( + f"Going to import {title} {share_id} {index + 1}/{len(applications_by_id)}" + ) + + with tqdm(total=1000) as progress_bar: + progress = Progress(1000) + + def progress_updated(percentage, state): + progress_bar.set_description(state) + progress_bar.update(progress.progress - progress_bar.n) + + progress.register_updated_event(progress_updated) + + with NamedTemporaryFile() as download_files_buffer: + config = AirtableImportConfig(skip_files=True) + with transaction.atomic(): + try: + AirtableHandler.import_from_airtable_to_workspace( + workspace, + share_id, + progress_builder=progress.create_child_builder( + represents_progress=progress.total + ), + download_files_buffer=download_files_buffer, + config=config, + ) + except AirtableBaseNotPublic: + print(" Skipping because it's not public.") diff --git a/backend/src/baserow/contrib/database/migrations/0181_tablewebhookcall_batch_id_and_more.py b/backend/src/baserow/contrib/database/migrations/0181_tablewebhookcall_batch_id_and_more.py new file mode 100644 index 000000000..bcbad367e --- /dev/null +++ b/backend/src/baserow/contrib/database/migrations/0181_tablewebhookcall_batch_id_and_more.py @@ -0,0 +1,24 @@ +# Generated by Django 5.0.9 on 2025-03-04 18:18 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + dependencies = [ + ("database", "0180_view_allow_public_export"), + ] + + operations = [ + migrations.AddField( + model_name="tablewebhookcall", + name="batch_id", + field=models.PositiveIntegerField( + help_text="The batch ID for this call. Null if not part of a batch. Used for batching multiple calls of the same event_id due to large data.", + null=True, + ), + ), + migrations.AlterUniqueTogether( + name="tablewebhookcall", + unique_together={("event_id", "batch_id", "webhook", "event_type")}, + ), + ] diff --git a/backend/src/baserow/contrib/database/migrations/0182_tablewebhookevent_views_viewrows_viewsubscription.py b/backend/src/baserow/contrib/database/migrations/0182_tablewebhookevent_views_viewrows_viewsubscription.py new file mode 100644 index 000000000..34b0cf309 --- /dev/null +++ b/backend/src/baserow/contrib/database/migrations/0182_tablewebhookevent_views_viewrows_viewsubscription.py @@ -0,0 +1,93 @@ +# Generated by Django 5.0.9 on 2025-03-07 15:43 + +import django.contrib.postgres.fields +import django.db.models.deletion +from django.db import migrations, models + +import baserow.core.fields + + +class Migration(migrations.Migration): + dependencies = [ + ("contenttypes", "0002_remove_content_type_name"), + ("database", "0181_tablewebhookcall_batch_id_and_more"), + ] + + operations = [ + migrations.AddField( + model_name="tablewebhookevent", + name="views", + field=models.ManyToManyField(to="database.view"), + ), + migrations.CreateModel( + name="ViewRows", + fields=[ + ( + "id", + models.AutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ("created_on", models.DateTimeField(auto_now_add=True)), + ("updated_on", baserow.core.fields.SyncedDateTimeField(auto_now=True)), + ( + "row_ids", + django.contrib.postgres.fields.ArrayField( + base_field=models.PositiveIntegerField(), + default=list, + help_text="The rows that are shown in the view. This list can be used by webhooks to determine which rows have been changed since the last check.", + size=None, + ), + ), + ( + "view", + models.OneToOneField( + on_delete=django.db.models.deletion.CASCADE, + related_name="rows", + to="database.view", + ), + ), + ], + options={ + "abstract": False, + }, + ), + migrations.CreateModel( + name="ViewSubscription", + fields=[ + ( + "id", + models.AutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ("subscriber_id", models.PositiveIntegerField()), + ( + "subscriber_content_type", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + to="contenttypes.contenttype", + ), + ), + ( + "view", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + related_name="subscribers", + to="database.view", + ), + ), + ], + options={ + "unique_together": { + ("view", "subscriber_content_type", "subscriber_id") + }, + }, + ), + ] diff --git a/backend/src/baserow/contrib/database/migrations/0183_viewgroupby_type_viewsort_type.py b/backend/src/baserow/contrib/database/migrations/0183_viewgroupby_type_viewsort_type.py new file mode 100644 index 000000000..433c958d0 --- /dev/null +++ b/backend/src/baserow/contrib/database/migrations/0183_viewgroupby_type_viewsort_type.py @@ -0,0 +1,32 @@ +# Generated by Django 5.0.9 on 2025-03-10 12:23 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + dependencies = [ + ("database", "0182_tablewebhookevent_views_viewrows_viewsubscription"), + ] + + operations = [ + migrations.AddField( + model_name="viewgroupby", + name="type", + field=models.CharField( + db_default="default", + default="default", + help_text="Indicates the sort type. Will automatically fall back to `default` if incompatible with field type.", + max_length=32, + ), + ), + migrations.AddField( + model_name="viewsort", + name="type", + field=models.CharField( + db_default="default", + default="default", + help_text="Indicates the sort type. Will automatically fall back to `default` if incompatible with field type.", + max_length=32, + ), + ), + ] diff --git a/backend/src/baserow/contrib/database/plugins.py b/backend/src/baserow/contrib/database/plugins.py index 1d7075fb5..a54dcf27c 100755 --- a/backend/src/baserow/contrib/database/plugins.py +++ b/backend/src/baserow/contrib/database/plugins.py @@ -66,7 +66,7 @@ class DatabasePlugin(Plugin): ["John", "Von Neumann", "", True], ["Blaise", "Pascal", "", True], ] - row_handler.import_rows(user, table, data, send_realtime_update=False) + row_handler.import_rows(user, table, data=data, send_realtime_update=False) # Creating the example projects table. table = table_handler.create_table_and_fields( @@ -86,4 +86,4 @@ class DatabasePlugin(Plugin): [_("Computer architecture"), str(date(1945, 1, 1)), False], [_("Cellular Automata"), str(date(1952, 6, 1)), False], ] - row_handler.import_rows(user, table, data, send_realtime_update=False) + row_handler.import_rows(user, table, data=data, send_realtime_update=False) diff --git a/backend/src/baserow/contrib/database/populate.py b/backend/src/baserow/contrib/database/populate.py index 64c696f29..06659e181 100644 --- a/backend/src/baserow/contrib/database/populate.py +++ b/backend/src/baserow/contrib/database/populate.py @@ -95,7 +95,9 @@ def load_test_data(): ("Rabbit", select_by_name["Meat"], fake.sentence(nb_words=10)), ] - RowHandler().import_rows(user, products_table, data, send_realtime_update=False) + RowHandler().import_rows( + user, products_table, data=data, send_realtime_update=False + ) try: suppliers_table = Table.objects.get(name="Suppliers", database=database) @@ -195,7 +197,7 @@ def load_test_data(): ] RowHandler().import_rows( - user, suppliers_table, data, send_realtime_update=False + user, suppliers_table, data=data, send_realtime_update=False ) try: @@ -253,7 +255,7 @@ def load_test_data(): ] RowHandler().import_rows( - user, retailers_table, data, send_realtime_update=False + user, retailers_table, data=data, send_realtime_update=False ) try: @@ -358,5 +360,5 @@ def load_test_data(): ] RowHandler().import_rows( - user, user_accounts_table, data, send_realtime_update=False + user, user_accounts_table, data=data, send_realtime_update=False ) diff --git a/backend/src/baserow/contrib/database/rows/actions.py b/backend/src/baserow/contrib/database/rows/actions.py index e52088efa..9d3d13180 100755 --- a/backend/src/baserow/contrib/database/rows/actions.py +++ b/backend/src/baserow/contrib/database/rows/actions.py @@ -6,6 +6,8 @@ from typing import Any, Dict, List, Optional, Tuple, Type from django.contrib.auth.models import AbstractUser from django.utils.translation import gettext_lazy as _ +from loguru import logger + from baserow.contrib.database.action.scopes import ( TABLE_ACTION_CONTEXT, TableActionScopeType, @@ -18,6 +20,7 @@ from baserow.contrib.database.rows.handler import ( GeneratedTableModelForUpdate, RowHandler, ) +from baserow.contrib.database.rows.types import FileImportDict from baserow.contrib.database.table.handler import TableHandler from baserow.contrib.database.table.models import GeneratedTableModel, Table from baserow.core.action.models import Action @@ -178,13 +181,17 @@ class CreateRowsActionType(UndoableActionType): "Can't create rows because it has a data sync." ) - rows = RowHandler().create_rows( - user, - table, - rows_values, - before_row=before_row, - model=model, - send_webhook_events=send_webhook_events, + rows = ( + RowHandler() + .create_rows( + user, + table, + rows_values, + before_row=before_row, + model=model, + send_webhook_events=send_webhook_events, + ) + .created_rows ) workspace = table.database.workspace @@ -244,7 +251,7 @@ class ImportRowsActionType(UndoableActionType): cls, user: AbstractUser, table: Table, - data=List[List[Any]], + data: FileImportDict, progress: Optional[Progress] = None, ) -> Tuple[List[GeneratedTableModel], Dict[str, Any]]: """ @@ -270,9 +277,14 @@ class ImportRowsActionType(UndoableActionType): ) created_rows, error_report = RowHandler().import_rows( - user, table, data, progress=progress + user, + table, + data=data["data"], + configuration=data.get("configuration") or {}, + progress=progress, ) - + if error_report: + logger.warning(f"Errors during rows import: {error_report}") workspace = table.database.workspace params = cls.Params( table.id, @@ -836,7 +848,7 @@ class UpdateRowsActionType(UndoableActionType): @classmethod def serialized_to_params(cls, serialized_params: Any) -> Any: - """ + """` When storing integers as dictionary keys in a database, they are saved as strings. This method is designed to convert these string keys back into integers. This ensures that we can accurately use the row.id as a diff --git a/backend/src/baserow/contrib/database/rows/exceptions.py b/backend/src/baserow/contrib/database/rows/exceptions.py index 96f5fbfce..b494b4586 100644 --- a/backend/src/baserow/contrib/database/rows/exceptions.py +++ b/backend/src/baserow/contrib/database/rows/exceptions.py @@ -36,3 +36,12 @@ class CannotDeleteRowsInTable(Exception): """ Raised when it's not possible to delete rows in the table. """ + + +class InvalidRowLength(Exception): + """ + Row's length doesn't match expected length based on schema. + """ + + def __init__(self, row_idx: int): + self.row_idx = row_idx diff --git a/backend/src/baserow/contrib/database/rows/handler.py b/backend/src/baserow/contrib/database/rows/handler.py index 1c91cb225..a7b2f7f16 100644 --- a/backend/src/baserow/contrib/database/rows/handler.py +++ b/backend/src/baserow/contrib/database/rows/handler.py @@ -1,14 +1,13 @@ from collections import defaultdict from copy import deepcopy from decimal import Decimal +from functools import cached_property from typing import ( TYPE_CHECKING, Any, Dict, Iterable, List, - NamedTuple, - NewType, Optional, Set, Tuple, @@ -17,24 +16,37 @@ from typing import ( cast, ) +from django import db from django.contrib.auth.models import AbstractUser from django.core.exceptions import ValidationError from django.db import connection, transaction +from django.db.models import Field as DjangoField from django.db.models import Model, QuerySet, Window from django.db.models.expressions import RawSQL from django.db.models.fields.related import ForeignKey, ManyToManyField from django.db.models.functions import RowNumber from django.utils.encoding import force_str +from celery.utils import chunks from opentelemetry import metrics, trace from baserow.contrib.database.fields.dependencies.handler import FieldDependencyHandler from baserow.contrib.database.fields.dependencies.update_collector import ( FieldUpdateCollector, ) +from baserow.contrib.database.fields.exceptions import ( + FieldNotInTable, + IncompatibleField, +) from baserow.contrib.database.fields.field_cache import FieldCache -from baserow.contrib.database.fields.registries import field_type_registry +from baserow.contrib.database.fields.registries import FieldType, field_type_registry from baserow.contrib.database.fields.utils import get_field_id_from_field_key +from baserow.contrib.database.search.handler import SearchHandler +from baserow.contrib.database.table.constants import ( + CREATED_BY_COLUMN_NAME, + LAST_MODIFIED_BY_COLUMN_NAME, + ROW_NEEDS_BACKGROUND_UPDATE_COLUMN_NAME, +) from baserow.contrib.database.table.models import GeneratedTableModel, Table from baserow.contrib.database.table.operations import ( CreateRowDatabaseTableOperationType, @@ -49,20 +61,15 @@ from baserow.core.db import ( ) from baserow.core.exceptions import CannotCalculateIntermediateOrder from baserow.core.handler import CoreHandler +from baserow.core.psycopg import sql from baserow.core.telemetry.utils import baserow_trace_methods from baserow.core.trash.handler import TrashHandler from baserow.core.trash.registries import trash_item_type_registry from baserow.core.utils import Progress, get_non_unique_values, grouper -from ..search.handler import SearchHandler -from ..table.constants import ( - CREATED_BY_COLUMN_NAME, - LAST_MODIFIED_BY_COLUMN_NAME, - ROW_NEEDS_BACKGROUND_UPDATE_COLUMN_NAME, -) from .constants import ROW_IMPORT_CREATION, ROW_IMPORT_VALIDATION from .error_report import RowErrorReport -from .exceptions import RowDoesNotExist, RowIdsNotUnique +from .exceptions import InvalidRowLength, RowDoesNotExist, RowIdsNotUnique from .operations import ( DeleteDatabaseRowOperationType, MoveRowDatabaseRowOperationType, @@ -77,19 +84,23 @@ from .signals import ( rows_deleted, rows_updated, ) +from .types import ( + CreatedRowsData, + FieldsMetadata, + FileImportConfiguration, + GeneratedTableModelForUpdate, + RowId, + RowsForUpdate, + UpdatedRowsData, +) if TYPE_CHECKING: + from django.db.backends.utils import CursorWrapper + from baserow.contrib.database.fields.models import Field tracer = trace.get_tracer(__name__) -GeneratedTableModelForUpdate = NewType( - "GeneratedTableModelForUpdate", GeneratedTableModel -) - -RowsForUpdate = NewType("RowsForUpdate", QuerySet) - - BATCH_SIZE = 1024 meter = metrics.get_meter(__name__) @@ -139,29 +150,18 @@ def prepare_field_errors(field_errors): } -FieldsMetadata = NewType("FieldsMetadata", Dict[str, Any]) -RowValues = NewType("RowValues", Dict[str, Any]) -RowId = NewType("RowId", int) - - -class UpdatedRowsWithOldValuesAndMetadata(NamedTuple): - updated_rows: List[GeneratedTableModelForUpdate] - original_rows_values_by_id: Dict[RowId, RowValues] - updated_fields_metadata_by_row_id: Dict[RowId, FieldsMetadata] - - class RowM2MChangeTracker: def __init__(self): self._deleted_m2m_rels: Dict[ - str, Dict["Field", Dict[GeneratedTableModel, Set[int]]] + str, Dict["DjangoField", Dict[GeneratedTableModel, Set[int]]] ] = defaultdict(lambda: defaultdict(lambda: defaultdict(set))) self._created_m2m_rels: Dict[ - str, Dict["Field", Dict[GeneratedTableModel, Set[int]]] + str, Dict["DjangoField", Dict[GeneratedTableModel, Set[int]]] ] = defaultdict(lambda: defaultdict(lambda: defaultdict(set))) def track_m2m_update_for_field_and_row( self, - field: "Field", + field: "DjangoField", field_name: str, row: GeneratedTableModel, new_values: Iterable[int], @@ -181,7 +181,7 @@ class RowM2MChangeTracker: def track_m2m_created_for_new_row( self, row: GeneratedTableModel, - field: "Field", + field: "DjangoField", new_values: Iterable[Union[int, Model]], ): field_type = field_type_registry.get_by_model(field) @@ -197,7 +197,7 @@ class RowM2MChangeTracker: def get_created_m2m_rels_per_field_for_type( self, field_type - ) -> Dict["Field", Dict[GeneratedTableModel, Set[int]]]: + ) -> Dict["DjangoField", Dict[GeneratedTableModel, Set[int]]]: return self._created_m2m_rels[field_type] def get_deleted_link_row_rels_for_update_collector( @@ -816,6 +816,8 @@ class RowHandler(metaclass=baserow_trace_methods(tracer)): send_webhook_events=send_webhook_events, rows_values_refreshed_from_db=False, m2m_change_tracker=m2m_change_tracker, + fields=fields, + dependant_fields=dependant_fields, ) return instance @@ -1005,6 +1007,8 @@ class RowHandler(metaclass=baserow_trace_methods(tracer)): before_return=before_return, updated_field_ids=updated_field_ids, m2m_change_tracker=m2m_change_tracker, + fields=[f for f in updated_fields if f.id in updated_field_ids], + dependant_fields=dependant_fields, ) return row @@ -1017,7 +1021,7 @@ class RowHandler(metaclass=baserow_trace_methods(tracer)): updated_field_ids: Set[int], m2m_change_tracker: Optional[RowM2MChangeTracker] = None, skip_search_updates: bool = False, - ) -> List["Field"]: + ) -> List["DjangoField"]: """ Prepares a list of fields that are dependent on the updated fields and updates them. @@ -1084,7 +1088,7 @@ class RowHandler(metaclass=baserow_trace_methods(tracer)): send_webhook_events: bool = True, generate_error_report: bool = False, skip_search_update: bool = False, - ) -> List[GeneratedTableModel]: + ) -> CreatedRowsData: """ Creates new rows for a given table without checking permissions. It also calls the rows_created signal. @@ -1215,11 +1219,11 @@ class RowHandler(metaclass=baserow_trace_methods(tracer)): send_webhook_events=send_webhook_events, prepared_rows_values=prepared_rows_values, m2m_change_tracker=m2m_change_tracker, + fields=updated_fields, + dependant_fields=dependant_fields, ) - if generate_error_report: - return inserted_rows, report - return rows_to_return + return CreatedRowsData(rows_to_return, report) def create_rows( self, @@ -1232,7 +1236,7 @@ class RowHandler(metaclass=baserow_trace_methods(tracer)): send_webhook_events: bool = True, generate_error_report: bool = False, skip_search_update: bool = False, - ) -> List[GeneratedTableModel]: + ) -> CreatedRowsData: """ Creates new rows for a given table if the user belongs to the related workspace. It also calls the rows_created signal. @@ -1283,7 +1287,7 @@ class RowHandler(metaclass=baserow_trace_methods(tracer)): self, model: Type[GeneratedTableModel], created_rows: List[GeneratedTableModel], - ) -> List["Field"]: + ) -> List["DjangoField"]: """ Generates a list of dependant fields that need to be updated after the rows have been created and updates them. @@ -1437,11 +1441,11 @@ class RowHandler(metaclass=baserow_trace_methods(tracer)): return report - def create_rows_by_batch( + def force_create_rows_by_batch( self, user: AbstractUser, table: Table, - rows: List[Dict[str, Any]], + rows_values: List[Dict[str, Any]], progress: Optional[Progress] = None, model: Optional[Type[GeneratedTableModel]] = None, ) -> Tuple[List[GeneratedTableModel], Dict[str, Dict[str, Any]]]: @@ -1451,13 +1455,13 @@ class RowHandler(metaclass=baserow_trace_methods(tracer)): :param user: The user of whose behalf the rows are created. :param table: The table for which the rows should be created. - :param rows: List of rows values for rows that need to be created. + :param rows_values: List of rows values for rows that need to be created. :param progress: Give a progress instance to track the progress of the import. :param model: Optional model to prevent recomputing table model. :return: The created rows and the error report. """ - if not rows: + if not rows_values: return [], {} if progress: @@ -1468,7 +1472,7 @@ class RowHandler(metaclass=baserow_trace_methods(tracer)): report = {} all_created_rows = [] - for count, chunk in enumerate(grouper(BATCH_SIZE, rows)): + for count, chunk in enumerate(grouper(BATCH_SIZE, rows_values)): row_start_index = count * BATCH_SIZE created_rows, creation_report = self.create_rows( user=user, @@ -1497,11 +1501,64 @@ class RowHandler(metaclass=baserow_trace_methods(tracer)): return all_created_rows, report + def force_update_rows_by_batch( + self, + user: AbstractUser, + table: Table, + rows_values: List[Dict[str, Any]], + progress: Progress, + model: Optional[Type[GeneratedTableModel]] = None, + ) -> Tuple[List[Dict[str, Any] | None], Dict[str, Dict[str, Any]]]: + """ + Creates rows by batch and generates an error report instead of failing on first + error. + + :param user: The user of whose behalf the rows are created. + :param table: The table for which the rows should be created. + :param rows_values: List of rows values for rows that need to be created. + :param progress: Give a progress instance to track the progress of the import. + :param model: Optional model to prevent recomputing table model. + :return: The created rows and the error report. + """ + + if not rows_values: + return [], {} + + progress.increment(state=ROW_IMPORT_CREATION) + + if model is None: + model = table.get_model() + + report = {} + all_updated_rows = [] + for count, chunk in enumerate(grouper(BATCH_SIZE, rows_values)): + updated_rows = self.force_update_rows( + user=user, + table=table, + model=model, + rows_values=chunk, + send_realtime_update=False, + send_webhook_events=False, + # Don't trigger loads of search updates for every batch of rows we + # create but instead a single one for this entire table at the end. + skip_search_update=True, + generate_error_report=True, + ) + + if progress: + progress.increment(len(chunk)) + report.update(updated_rows.errors) + all_updated_rows.extend(updated_rows.updated_rows) + + SearchHandler.field_value_updated_or_created(table) + return all_updated_rows, report + def import_rows( self, user: AbstractUser, table: Table, - data: List[List[Any]], + data: list[list[Any]], + configuration: FileImportConfiguration | None = None, validate: bool = True, progress: Optional[Progress] = None, send_realtime_update: bool = True, @@ -1517,12 +1574,15 @@ class RowHandler(metaclass=baserow_trace_methods(tracer)): :param user: The user of whose behalf the rows are created. :param table: The table for which the rows should be created. :param data: List of rows values for rows that need to be created. + :param configuration: Optional import configuration dict. :param validate: If True the data are validated before the import. :param progress: Give a progress instance to track the progress of the import. :param send_realtime_update: The parameter passed to the rows_created signal indicating if a realtime update should be send. + :raises InvalidRowLength: + :return: The created row instances and the error report. """ @@ -1535,6 +1595,15 @@ class RowHandler(metaclass=baserow_trace_methods(tracer)): ) error_report = RowErrorReport(data) + configuration = configuration or {} + update_handler = UpsertRowsMappingHandler( + table=table, + upsert_fields=configuration.get("upsert_fields") or [], + upsert_values=configuration.get("upsert_values") or [], + ) + # Pre-run upsert configuration validation. + # Can raise InvalidRowLength + update_handler.validate() model = table.get_model() @@ -1599,10 +1668,40 @@ class RowHandler(metaclass=baserow_trace_methods(tracer)): else None ) - created_rows, creation_report = self.create_rows_by_batch( - user, table, valid_rows, progress=creation_sub_progress, model=model + # split rows to insert and update lists. If there's no upsert field selected, + # this will not populate rows_values_to_update. + update_map = update_handler.process_map + + rows_values_to_create = [] + rows_values_to_update = [] + if update_map: + for current_idx, import_idx in original_row_index_mapping.items(): + row = valid_rows[current_idx] + if update_idx := update_map.get(import_idx): + row["id"] = update_idx + rows_values_to_update.append(row) + else: + rows_values_to_create.append(row) + else: + rows_values_to_create = valid_rows + + created_rows, creation_report = self.force_create_rows_by_batch( + user, + table, + rows_values_to_create, + progress=creation_sub_progress, + model=model, ) + if rows_values_to_update: + updated_rows, updated_report = self.force_update_rows_by_batch( + user, + table, + rows_values_to_update, + progress=creation_sub_progress, + model=model, + ) + # Add errors to global report for index, error in creation_report.items(): error_report.add_error( @@ -1610,6 +1709,13 @@ class RowHandler(metaclass=baserow_trace_methods(tracer)): error, ) + if rows_values_to_update: + for index, error in updated_report.items(): + error_report.add_error( + original_row_index_mapping[int(index)], + error, + ) + if send_realtime_update: # Just send a single table_updated here as realtime update instead # of rows_created because we might import a lot of rows. @@ -1620,7 +1726,7 @@ class RowHandler(metaclass=baserow_trace_methods(tracer)): def get_fields_metadata_for_row_history( self, row: GeneratedTableModelForUpdate, - updated_fields: List["Field"], + updated_fields: List["DjangoField"], metadata, ) -> FieldsMetadata: """ @@ -1642,7 +1748,7 @@ class RowHandler(metaclass=baserow_trace_methods(tracer)): def get_fields_metadata_for_rows( self, rows: List[GeneratedTableModelForUpdate], - updated_fields: List["Field"], + updated_fields: List["DjangoField"], fields_metadata_by_row_id=None, ) -> Dict[RowId, FieldsMetadata]: """ @@ -1678,7 +1784,8 @@ class RowHandler(metaclass=baserow_trace_methods(tracer)): send_realtime_update: bool = True, send_webhook_events: bool = True, skip_search_update: bool = False, - ) -> UpdatedRowsWithOldValuesAndMetadata: + generate_error_report: bool = False, + ) -> UpdatedRowsData: """ Updates field values in batch based on provided rows with the new values. @@ -1698,6 +1805,7 @@ class RowHandler(metaclass=baserow_trace_methods(tracer)): :param skip_search_update: If you want to instead trigger the search handler cells update later on after many create_rows calls then set this to True but make sure you trigger it eventually. + :param generate_error_report: Generate error report if set to True. :raises RowIdsNotUnique: When trying to update the same row multiple times. :raises RowDoesNotExist: When any of the rows don't exist. @@ -1710,9 +1818,12 @@ class RowHandler(metaclass=baserow_trace_methods(tracer)): user_id = user and user.id - prepared_rows_values, _ = self.prepare_rows_in_bulk( - model._field_objects, rows_values + prepared_rows_values, errors = self.prepare_rows_in_bulk( + model._field_objects, + rows_values, + generate_error_report=generate_error_report, ) + report = {index: err for index, err in errors.items()} row_ids = [r["id"] for r in prepared_rows_values] non_unique_ids = get_non_unique_values(row_ids) @@ -1875,7 +1986,7 @@ class RowHandler(metaclass=baserow_trace_methods(tracer)): if ( not isinstance(model_field, ManyToManyField) and field_id in updated_field_ids - and field_type.valid_for_bulk_update(model_field) + and field_type.valid_for_bulk_update(field_obj["field"]) ): bulk_update_fields.append(field_name) @@ -1895,6 +2006,7 @@ class RowHandler(metaclass=baserow_trace_methods(tracer)): if not skip_search_update: SearchHandler.field_value_updated_or_created(table) + # Reload rows from the database to get the updated values for formulas updated_rows_to_return = list( model.objects.all().enhance_by_fields().filter(id__in=row_ids) ) @@ -1910,18 +2022,22 @@ class RowHandler(metaclass=baserow_trace_methods(tracer)): m2m_change_tracker=m2m_change_tracker, send_realtime_update=send_realtime_update, send_webhook_events=send_webhook_events, + fields=[f for f in updated_fields if f.id in updated_field_ids], + dependant_fields=dependant_fields, ) fields_metadata_by_row_id = self.get_fields_metadata_for_rows( updated_rows_to_return, updated_fields, fields_metadata_by_row_id ) - - return UpdatedRowsWithOldValuesAndMetadata( + updated_rows = UpdatedRowsData( updated_rows_to_return, original_row_values_by_id, fields_metadata_by_row_id, + report, ) + return updated_rows + def update_rows( self, user: AbstractUser, @@ -1932,7 +2048,8 @@ class RowHandler(metaclass=baserow_trace_methods(tracer)): send_realtime_update: bool = True, send_webhook_events: bool = True, skip_search_update: bool = False, - ) -> UpdatedRowsWithOldValuesAndMetadata: + generate_error_report: bool = False, + ) -> UpdatedRowsData: """ Updates field values in batch based on provided rows with the new values. @@ -1975,6 +2092,7 @@ class RowHandler(metaclass=baserow_trace_methods(tracer)): send_realtime_update, send_webhook_events, skip_search_update, + generate_error_report=generate_error_report, ) def get_rows( @@ -2103,6 +2221,8 @@ class RowHandler(metaclass=baserow_trace_methods(tracer)): updated_field_ids=[], prepared_rows_values=None, send_webhook_events=send_webhook_events, + fields=[], + dependant_fields=dependant_fields, ) return row @@ -2204,6 +2324,8 @@ class RowHandler(metaclass=baserow_trace_methods(tracer)): before_return=before_return, send_realtime_update=send_realtime_update, send_webhook_events=send_webhook_events, + fields=updated_fields, + dependant_fields=dependant_fields, ) def update_dependencies_of_rows_deleted(self, table, row, model): @@ -2265,7 +2387,6 @@ class RowHandler(metaclass=baserow_trace_methods(tracer)): triggered. Defaults to true. :param permanently_delete: If `true` the rows will be permanently deleted instead of trashed. - :raises RowDoesNotExist: When the row with the provided id does not exist. """ workspace = table.database.workspace @@ -2275,8 +2396,46 @@ class RowHandler(metaclass=baserow_trace_methods(tracer)): workspace=workspace, context=table, ) + return self.force_delete_rows( + user, + table, + row_ids, + model=model, + send_realtime_update=send_realtime_update, + send_webhook_events=send_webhook_events, + permanently_delete=permanently_delete, + ) - if not model: + def force_delete_rows( + self, + user: AbstractUser, + table: Table, + row_ids: List[int], + model: Optional[Type[GeneratedTableModel]] = None, + send_realtime_update: bool = True, + send_webhook_events: bool = True, + permanently_delete: bool = False, + ) -> TrashedRows: + """ + Trashes existing rows of the given table based on row_ids, without checking + user permissions. + + :param user: The user of whose behalf the change is made. + :param table: The table for which the row must be deleted. + :param row_ids: The ids of the rows that must be deleted. + :param model: If the correct model has already been generated, it can be + provided so that it does not have to be generated for a second time. + :param send_realtime_update: If set to false then it is up to the caller to + send the rows_created or similar signal. Defaults to True. + :param send_webhook_events: If set the false then the webhooks will not be + triggered. Defaults to true. + :param permanently_delete: If `true` the rows will be permanently deleted + instead of trashed. + :raises RowDoesNotExist: When the row with the provided id does not exist. + """ + + workspace = table.database.workspace + if model is None: model = table.get_model() non_unique_ids = get_non_unique_values(row_ids) @@ -2310,9 +2469,7 @@ class RowHandler(metaclass=baserow_trace_methods(tracer)): TrashHandler.trash(user, workspace, table.database, trashed_rows) - rows_deleted_counter.add( - len(row_ids), - ) + rows_deleted_counter.add(len(row_ids)) updated_field_ids = [] updated_fields = [] @@ -2359,6 +2516,8 @@ class RowHandler(metaclass=baserow_trace_methods(tracer)): before_return=before_return, send_realtime_update=send_realtime_update, send_webhook_events=send_webhook_events, + fields=updated_fields, + dependant_fields=dependant_fields, ) return trashed_rows @@ -2386,3 +2545,233 @@ class RowHandler(metaclass=baserow_trace_methods(tracer)): self, table=table, ) + + +def merge_values_expression( + row: list[str | int | float | None], + field_handlers: "list[UpsertFieldHandler]", + query_params: list, +) -> sql.Composable: + """ + Create a sql expression that will produce text value from a list of row values. Any + value, that should be interpolated, will be added to provided `query_params` list. + + :param row: a list of values in a row + :param field_handlers: a list of field types for a row. The number of handlers + should equal the number of values in a row. + :param query_params: param values container + :return: + """ + + fields = [] + + for val, field_handler in zip(row, field_handlers): + fields.append(field_handler.get_field_concat_expression()) + query_params.append(field_handler.prepare_value(val)) + + return UpsertRowsMappingHandler.SEPARATOR.join(fields) + + +class UpsertFieldHandler: + """ + Helper class to handle field's upsert handling. + """ + + def __init__(self, table: Table, field_id: id): + self.table = table + # TODO: here we are using field id, but it may be so the field_id + # is `'id'` string. + try: + self._field_def = field_def = next( + ( + f + for f in table.get_model().get_field_objects() + if f["field"].id == field_id + ) + ) + except StopIteration: + raise FieldNotInTable(field_id) + + self.field: Field = field_def["field"] + self.field_type: FieldType = field_def["type"] + if not self.field_type.can_upsert: + raise IncompatibleField(self.field.id) + self.field_name = self.field.db_column + + def prepare_value(self, value: str) -> Any: + return self.field_type.prepare_value_for_db(self.field, value) + + def get_field_concat_expression(self) -> sql.Composable: + column_type = sql.SQL(self.get_column_type() or "text") + return sql.SQL(" COALESCE(CAST({}::{} AS TEXT), '<NULL>')::TEXT ").format( + sql.Placeholder(), column_type + ) + + def get_column_type(self) -> str | None: + table_field: DjangoField = self.field_type.get_model_field(self.field) + return table_field.db_type(db.connection) + + +class UpsertRowsMappingHandler: + """ + Helper class for mapping new rows values to existing table rows during an upsert + operation. + + This class processes upsert values from the provided data and matches them with + existing row IDs in the database. The resulting mapping helps determine which + imported rows should update existing ones. + + ### Usage: + + >>> importrows = ImportRowsMappingHandler(table, [1234], [['a'], ['b']]) + + # Returns a dictionary where: + # - Keys represent the index of the upsert values in the imported dataset. + # - Values represent the corresponding row ID in the database. + >>> importrows.process_map + {0: 1, 1: 2} + + # In this example: + # - The first imported value ['a'] (index 0) corresponds to the row with ID 1. + # - The second imported value ['b'] (index 1) corresponds to the row with ID 2. + """ + + SEPARATOR = sql.SQL(" || '__-__' || ") + PER_CHUNK = 100 + + def __init__( + self, table: Table, upsert_fields: list[int], upsert_values: list[list[Any]] + ): + self.table = table + self.table_name = table.get_database_table_name() + self.import_fields = [UpsertFieldHandler(table, fidx) for fidx in upsert_fields] + self.upsert_values = upsert_values + + def validate(self): + """ + Validates if upsert configuration conforms formal requirements + :raises InvalidRowLength: + """ + + expected_length = len(self.import_fields) + for ridx, uval in enumerate(self.upsert_values): + if len(uval) != expected_length: + raise InvalidRowLength(ridx) + + @cached_property + def process_map(self) -> dict[int, int]: + """ + Calculates a map between import row indexes and table row ids. + """ + + # no upsert value fields, no need for mapping + if not self.import_fields: + return {} + + script_template = sql.SQL( + """ + CREATE TEMP TABLE table_upsert_indexes (id INT, upsert_value TEXT, group_index INT); + + CREATE TEMP TABLE table_import (id INT, upsert_value TEXT); + + CREATE TEMP VIEW table_import_indexes AS + SELECT id, upsert_value, RANK() + OVER (PARTITION BY upsert_value ORDER BY id, upsert_value ) + AS group_index + FROM table_import ORDER BY id ; + """ + ) + + self.execute(script_template) + self.insert_table_values() + self.insert_imported_values() + # this is just a list of pairs, not very usable. + calculated = self.calculate_map() + + # map import row idx -> update row_id in table + return {r[1]: r[0] for r in calculated} + + @cached_property + def connection(self): + return db.connection + + @cached_property + def cursor(self): + return self.connection.cursor() + + def execute(self, query, *args, **kwargs) -> "CursorWrapper": + self.cursor.execute(query, *args, **kwargs) + return self.cursor + + def insert_table_values(self): + """ + Populates temp upsert comparison table with values from an exsisting table. + Values from multiple source columns will be normalized to one text value. + """ + + columns = self.SEPARATOR.join( + [ + sql.SQL("COALESCE(CAST({} AS TEXT), '<NULL>')::TEXT").format( + sql.Identifier(field.field_name) + ) + for field in self.import_fields + ] + ) + + query = sql.SQL( + """WITH subq AS (SELECT r.id, {} AS upsert_value FROM {} r WHERE NOT trashed) + INSERT INTO table_upsert_indexes (id, upsert_value, group_index) + SELECT id, upsert_value, RANK() + OVER (PARTITION BY upsert_value ORDER BY id, upsert_value ) + AS group_index + FROM subq ORDER BY id """ + ).format( + columns, sql.Identifier(self.table_name) + ) # nosec B608 + + self.execute(query) + + def insert_imported_values(self): + """ + Builds and executes bulk insert queries for upsert comparison values + from import data. + """ + + for _chunk in chunks(enumerate(self.upsert_values), self.PER_CHUNK): + # put all params (processed values) for the query into a container + query_params = [] + rows_query = [] + for rowidx, row in _chunk: + # per-row insert query + query_params.append(rowidx) + row_to_add = sql.SQL("({}, {})").format( + sql.Placeholder(), + merge_values_expression(row, self.import_fields, query_params), + ) + rows_query.append(row_to_add) + + rows_placeholder = sql.SQL(",\n").join(rows_query) + script_template = sql.SQL( + "INSERT INTO table_import (id, upsert_value) VALUES {};" + ).format( + rows_placeholder + ) # nosec B608 + self.execute(script_template, query_params) + + def calculate_map(self) -> list[tuple[int, int]]: + """ + Calculates a map between imported row index -> table row id + that can be used to detect if a row that is imported should be updated + (mapping exists) or inserted as a new one. + """ + + q = sql.SQL( + """ + SELECT t.id, i.id + FROM table_upsert_indexes t + JOIN table_import_indexes i + ON (i.upsert_value = t.upsert_value + AND i.group_index = t.group_index); + """ + ) + return self.execute(q).fetchall() diff --git a/backend/src/baserow/contrib/database/rows/history.py b/backend/src/baserow/contrib/database/rows/history.py index 34ff4318f..60b91854f 100644 --- a/backend/src/baserow/contrib/database/rows/history.py +++ b/backend/src/baserow/contrib/database/rows/history.py @@ -1,4 +1,7 @@ +from collections import defaultdict +from dataclasses import dataclass from datetime import datetime +from itertools import groupby from typing import Any, Dict, List, NamedTuple, NewType, Optional from django.conf import settings @@ -21,6 +24,19 @@ tracer = trace.get_tracer(__name__) FieldName = NewType("FieldName", str) +# Dict of table_id -> row_id -> field_name -> +# {added: List[row_id], removed:List[row_id], metadata: Dict} +RelatedRowsDiff = Dict[int, Dict[int, Dict[str, Dict[str, Any]]]] + + +@dataclass +class ActionData: + uuid: str + type: str + timestamp: datetime + command_type: ActionCommandType + params: Dict[str, Any] + class RowChangeDiff(NamedTuple): """ @@ -29,6 +45,8 @@ class RowChangeDiff(NamedTuple): and after values of those fields. """ + row_id: int + table_id: int changed_field_names: List[FieldName] before_values: Dict[FieldName, Any] after_values: Dict[FieldName, Any] @@ -38,38 +56,34 @@ class RowHistoryHandler: @classmethod def _construct_entry_from_action_and_diff( cls, - user, - table_id, - row_id, - field_names, - row_fields_metadata, - action_type, - action_uuid, - action_timestamp, - action_command_type, - diff, + user: AbstractBaseUser, + action: ActionData, + fields_metadata: Dict[str, Any], + row_diff: RowChangeDiff, ): return RowHistory( user_id=user.id, user_name=user.first_name, - table_id=table_id, - row_id=row_id, - field_names=field_names, - fields_metadata=row_fields_metadata, - action_uuid=action_uuid, - action_command_type=action_command_type.value, - action_timestamp=action_timestamp, - action_type=action_type, - before_values=diff.before_values, - after_values=diff.after_values, + table_id=row_diff.table_id, + row_id=row_diff.row_id, + field_names=row_diff.changed_field_names, + fields_metadata=fields_metadata, + action_uuid=action.uuid, + action_command_type=action.command_type.value, + action_timestamp=action.timestamp, + action_type=action.type, + before_values=row_diff.before_values, + after_values=row_diff.after_values, ) @classmethod def _extract_row_diff( cls, + table_id: int, + row_id: int, + fields_metadata: Dict[str, Any], before_values: Dict[str, Any], after_values: Dict[str, Any], - fields_metadata, ) -> Optional[RowChangeDiff]: """ Extracts the fields that have changed between the before and after values of a @@ -94,18 +108,20 @@ class RowHistoryHandler: before_fields = { k: field_type_registry.get( fields_metadata[k]["type"] - ).prepare_row_history_value_from_action_meta_data(v) + ).prepare_value_for_row_history(v) for k, v in before_values.items() if k in changed_fields } after_fields = { k: field_type_registry.get( fields_metadata[k]["type"] - ).prepare_row_history_value_from_action_meta_data(v) + ).prepare_value_for_row_history(v) for k, v in after_values.items() if k in changed_fields } - return RowChangeDiff(list(changed_fields), before_fields, after_fields) + return RowChangeDiff( + row_id, table_id, list(changed_fields), before_fields, after_fields + ) @classmethod def _raise_if_ids_mismatch(cls, before_values, after_values, fields_metadata): @@ -120,62 +136,205 @@ class RowHistoryHandler: "are the same. This should never happen." ) + @classmethod + def _update_related_tables_entries( + cls, + related_rows_diff: RelatedRowsDiff, + fields_metadata: Dict[str, Any], + row_diff: RowChangeDiff, + ) -> RelatedRowsDiff: + """ + Updates the record of changes in related tables when link_row fields are + modified. + + When a row's link_row field is updated (adding or removing connections to rows + in another table), this method tracks those changes from the perspective of the + rows in the related table, so that history can be properly displayed for both + sides of the relationship. + + The method updates related_rows_diff in-place, maintaining a record of which + rows were added or removed from each link relationship. + + :param related_rows_diff: Nested dictionary tracking changes for each affected + related row + :param fields_metadata: Metadata about the fields that were changed in + this update + :param row_diff: The changes made to the current row, including before/after + values + :return: The updated related_rows_diff dictionary + """ + + def _init_linked_row_diff(linked_field_id): + return { + "added": [], + "removed": [], + "metadata": { + "id": linked_field_id, + "type": "link_row", + "linked_rows": {}, + }, + } + + def _update_linked_row_diff( + field_metadata: Dict[str, Any], row_ids_set: set[int], key: str + ): + linked_table_id = field_metadata["linked_table_id"] + linked_field_id = field_metadata["linked_field_id"] + linked_field_name = f"field_{linked_field_id}" + + for linked_row_id in row_ids_set: + linked_diff = related_rows_diff[linked_table_id][linked_row_id][ + linked_field_name + ] + if not linked_diff: + linked_diff = _init_linked_row_diff(linked_field_id) + related_rows_diff[linked_table_id][linked_row_id][ + linked_field_name + ] = linked_diff + linked_diff[key].append(row_id) + linked_diff["metadata"]["linked_rows"][row_id] = { + "value": field_metadata["primary_value"] + } + + row_id = row_diff.row_id + for field_name in row_diff.changed_field_names: + field_metadata = fields_metadata[field_name] + + # Ignore fields that are not link_row fields or that doesn't have a related + # field in the linked table. + if ( + field_metadata["type"] != "link_row" + or not field_metadata["linked_field_id"] + ): + continue + + after_set = set(row_diff.after_values[field_name]) + before_set = set(row_diff.before_values[field_name]) + + row_ids_added = after_set - before_set + _update_linked_row_diff(field_metadata, row_ids_added, "added") + + row_ids_removed = before_set - after_set + _update_linked_row_diff(field_metadata, row_ids_removed, "removed") + + return related_rows_diff + + @classmethod + def _construct_related_rows_entries( + cls, + related_rows_diff: RelatedRowsDiff, + user: AbstractBaseUser, + action: ActionData, + ) -> List[RowHistory]: + """ + Creates RowHistory entries for rows in related tables that were affected by + changes to the current row. Specifically, when a link_row field is updated, + this method ensures that the changes are also tracked from the perspective of + the related rows. + + :param related_rows_diff: A nested dictionary that tracks changes for each + affected related row. It includes details about rows added or removed + from link_row relationships. + :param user: The user who performed the action that triggered the changes. + :param action: The action metadata that describes the operation performed. + :return: A list of RowHistory entries representing the changes for the + related rows. + """ + + entries = [] + for linked_table_id, table_changes in related_rows_diff.items(): + for linked_row_id, row_changes in table_changes.items(): + field_names = list(row_changes.keys()) + fields_metadata, before_values, after_values = {}, {}, {} + + for field_name in field_names: + row_field_changes = row_changes[field_name] + fields_metadata[field_name] = row_field_changes["metadata"] + before_values[field_name] = row_field_changes["removed"] + after_values[field_name] = row_field_changes["added"] + + linked_entry = RowHistory( + user_id=user.id, + user_name=user.first_name, + table_id=linked_table_id, + row_id=linked_row_id, + field_names=field_names, + fields_metadata=fields_metadata, + action_uuid=action.uuid, + action_command_type=action.command_type.value, + action_timestamp=action.timestamp, + action_type=action.type, + before_values=before_values, + after_values=after_values, + ) + entries.append(linked_entry) + return entries + @classmethod @baserow_trace(tracer) def record_history_from_update_rows_action( cls, user: AbstractBaseUser, - action_uuid: str, - action_params: Dict[str, Any], - action_timestamp: datetime, - action_command_type: ActionCommandType, + action: ActionData, ): - params = UpdateRowsActionType.serialized_to_params(action_params) + params = UpdateRowsActionType.serialized_to_params(action.params) + table_id = params.table_id after_values = params.row_values before_values = [ params.original_rows_values_by_id[r["id"]] for r in after_values ] - if action_command_type == ActionCommandType.UNDO: + if action.command_type == ActionCommandType.UNDO: before_values, after_values = after_values, before_values row_history_entries = [] + related_rows_diff: RelatedRowsDiff = defaultdict( + lambda: defaultdict(lambda: defaultdict(dict)) + ) for i, after in enumerate(after_values): before = before_values[i] fields_metadata = params.updated_fields_metadata_by_row_id[after["id"]] cls._raise_if_ids_mismatch(before, after, fields_metadata) - diff = cls._extract_row_diff(before, after, fields_metadata) - if diff is None: + row_id = after["id"] + row_diff = cls._extract_row_diff( + table_id, row_id, fields_metadata, before, after + ) + if row_diff is None: continue changed_fields_metadata = { k: v for k, v in fields_metadata.items() - if k in diff.changed_field_names + if k in row_diff.changed_field_names } - row_id = after["id"] + entry = cls._construct_entry_from_action_and_diff( user, - params.table_id, - row_id, - diff.changed_field_names, + action, changed_fields_metadata, - UpdateRowsActionType.type, - action_uuid, - action_timestamp, - action_command_type, - diff, + row_diff, ) row_history_entries.append(entry) + cls._update_related_tables_entries( + related_rows_diff, changed_fields_metadata, row_diff + ) + + related_entries = cls._construct_related_rows_entries( + related_rows_diff, user, action + ) + row_history_entries.extend(related_entries) if row_history_entries: row_history_entries = RowHistory.objects.bulk_create(row_history_entries) - rows_history_updated.send( - RowHistoryHandler, - table_id=params.table_id, - row_history_entries=row_history_entries, - ) + for table_id, per_table_row_history_entries in groupby( + row_history_entries, lambda e: e.table_id + ): + rows_history_updated.send( + RowHistoryHandler, + table_id=table_id, + row_history_entries=list(per_table_row_history_entries), + ) @classmethod @baserow_trace(tracer) @@ -233,5 +392,12 @@ def on_action_done_update_row_history( if action_type and action_type.type in ROW_HISTORY_ACTIONS: add_entry_handler = ROW_HISTORY_ACTIONS[action_type.type] add_entry_handler( - user, action_uuid, action_params, action_timestamp, action_command_type + user, + ActionData( + action_uuid, + action_type.type, + action_timestamp, + action_command_type, + action_params, + ), ) diff --git a/backend/src/baserow/contrib/database/rows/types.py b/backend/src/baserow/contrib/database/rows/types.py new file mode 100644 index 000000000..149dfc8c9 --- /dev/null +++ b/backend/src/baserow/contrib/database/rows/types.py @@ -0,0 +1,39 @@ +import typing +from typing import Any, NamedTuple, NewType + +from django.db.models import QuerySet + +from baserow.contrib.database.table.models import GeneratedTableModel + +GeneratedTableModelForUpdate = NewType( + "GeneratedTableModelForUpdate", GeneratedTableModel +) + +RowsForUpdate = NewType("RowsForUpdate", QuerySet) + + +class FileImportConfiguration(typing.TypedDict): + upsert_fields: list[int] + upsert_values: list[list[typing.Any]] + + +class FileImportDict(typing.TypedDict): + data: list[list[typing.Any]] + configuration: FileImportConfiguration | None + + +FieldsMetadata = NewType("FieldsMetadata", dict[str, Any]) +RowValues = NewType("RowValues", dict[str, Any]) +RowId = NewType("RowId", int) + + +class UpdatedRowsData(NamedTuple): + updated_rows: list[GeneratedTableModelForUpdate] + original_rows_values_by_id: dict[RowId, RowValues] + updated_fields_metadata_by_row_id: dict[RowId, FieldsMetadata] + errors: dict[int, dict[str, Any]] | None = None + + +class CreatedRowsData(NamedTuple): + created_rows: list[GeneratedTableModel] + errors: dict[int, dict[str, Any]] | None = None diff --git a/backend/src/baserow/contrib/database/table/handler.py b/backend/src/baserow/contrib/database/table/handler.py index 221d3e0fd..c0e832edd 100644 --- a/backend/src/baserow/contrib/database/table/handler.py +++ b/backend/src/baserow/contrib/database/table/handler.py @@ -486,7 +486,11 @@ class TableHandler(metaclass=baserow_trace_methods(tracer)): table = self.create_table_and_fields(user, database, name, fields) _, error_report = RowHandler().import_rows( - user, table, data, progress=progress, send_realtime_update=False + user, + table, + data=data, + progress=progress, + send_realtime_update=False, ) table_created.send(self, table=table, user=user) diff --git a/backend/src/baserow/contrib/database/table/models.py b/backend/src/baserow/contrib/database/table/models.py index 5215bb81a..0a1b1723d 100644 --- a/backend/src/baserow/contrib/database/table/models.py +++ b/backend/src/baserow/contrib/database/table/models.py @@ -50,6 +50,7 @@ from baserow.contrib.database.table.constants import ( USER_TABLE_DATABASE_NAME_PREFIX, ) from baserow.contrib.database.views.exceptions import ViewFilterTypeNotAllowedForField +from baserow.contrib.database.views.models import DEFAULT_SORT_TYPE_KEY from baserow.contrib.database.views.registries import view_filter_type_registry from baserow.core.db import MultiFieldPrefetchQuerysetMixin, specific_iterator from baserow.core.fields import AutoTrueBooleanField @@ -332,6 +333,8 @@ class TableModelQuerySet(MultiFieldPrefetchQuerysetMixin, models.QuerySet): raise OrderByFieldNotFound(order) order_direction = "DESC" if order[:1] == "-" else "ASC" + type_match = re.search(r"\[(.*?)\]", order) + sort_type = type_match.group(1) if type_match else DEFAULT_SORT_TYPE_KEY field_object = field_object_dict[field_name_or_id] field_type = field_object["type"] field_name = field_object["name"] @@ -339,15 +342,18 @@ class TableModelQuerySet(MultiFieldPrefetchQuerysetMixin, models.QuerySet): user_field_name = field_object["field"].name error_display_name = user_field_name if user_field_names else field_name - if not field_object["type"].check_can_order_by(field_object["field"]): + if not field_object["type"].check_can_order_by( + field_object["field"], sort_type + ): raise OrderByFieldNotPossible( error_display_name, field_type.type, - f"It is not possible to order by field type {field_type.type}.", + sort_type, + f"It is not possible to order by field type {field_type.type} using sort type {sort_type}.", ) field_annotated_order_by = field_type.get_order( - field, field_name, order_direction, table_model=self.model + field, field_name, order_direction, sort_type, table_model=self.model ) if field_annotated_order_by.annotation is not None: diff --git a/backend/src/baserow/contrib/database/trash/trash_types.py b/backend/src/baserow/contrib/database/trash/trash_types.py index 1b3d6ae58..d70ed87da 100644 --- a/backend/src/baserow/contrib/database/trash/trash_types.py +++ b/backend/src/baserow/contrib/database/trash/trash_types.py @@ -309,6 +309,8 @@ class RowTrashableItemType(TrashableItemType): model=model, before=None, user=None, + fields=updated_fields, + dependant_fields=dependant_fields, ) def permanently_delete_item(self, row, trash_item_lookup_cache=None): @@ -432,6 +434,8 @@ class RowsTrashableItemType(TrashableItemType): model=model, before=None, user=None, + fields=updated_fields, + dependant_fields=dependant_fields, ) else: # Use table signal here instead of row signal because we don't want diff --git a/backend/src/baserow/contrib/database/views/actions.py b/backend/src/baserow/contrib/database/views/actions.py index fc85a121f..3b2e605f6 100755 --- a/backend/src/baserow/contrib/database/views/actions.py +++ b/backend/src/baserow/contrib/database/views/actions.py @@ -755,6 +755,7 @@ class CreateViewSortActionType(UndoableActionType): "database_id", "view_sort_id", "sort_order", + "sort_type", ] @dataclasses.dataclass @@ -769,10 +770,16 @@ class CreateViewSortActionType(UndoableActionType): database_name: str view_sort_id: int sort_order: str + sort_type: str @classmethod def do( - cls, user: AbstractUser, view: View, field: Field, sort_order: str + cls, + user: AbstractUser, + view: View, + field: Field, + sort_order: str, + sort_type: Optional[str] = None, ) -> ViewSort: """ Creates a new view sort. @@ -785,9 +792,13 @@ class CreateViewSortActionType(UndoableActionType): :param field: The field that needs to be sorted. :param sort_order: The desired order, can either be ascending (A to Z) or descending (Z to A). + :param sort_type: The sort type that must be used, `default` is set as default + when the sort is created. """ - view_sort = ViewHandler().create_sort(user, view, field, sort_order) + view_sort = ViewHandler().create_sort( + user, view, field, sort_order, sort_type=sort_type + ) params = cls.Params( field.id, @@ -800,6 +811,7 @@ class CreateViewSortActionType(UndoableActionType): view.table.database.name, view_sort.id, sort_order, + sort_type, ) workspace = view.table.database.workspace cls.register_action(user, params, cls.scope(view.id), workspace) @@ -822,7 +834,12 @@ class CreateViewSortActionType(UndoableActionType): view = view_handler.get_view(params.view_id) view_handler.create_sort( - user, view, field, params.sort_order, params.view_sort_id + user, + view, + field, + params.sort_order, + params.view_sort_id, + params.sort_type, ) @@ -840,8 +857,10 @@ class UpdateViewSortActionType(UndoableActionType): "database_id", "view_sort_id", "sort_order", + "sort_type", "original_field_id", "original_sort_order", + "original_sort_type", ] @dataclasses.dataclass @@ -856,9 +875,11 @@ class UpdateViewSortActionType(UndoableActionType): database_name: str view_sort_id: int sort_order: str + sort_type: str original_field_id: int original_field_name: str original_sort_order: str + original_sort_type: str @classmethod def do( @@ -867,6 +888,7 @@ class UpdateViewSortActionType(UndoableActionType): view_sort: ViewSort, field: Optional[Field] = None, order: Optional[str] = None, + sort_type: Optional[str] = None, ) -> ViewSort: """ Updates the values of an existing view sort. @@ -878,6 +900,8 @@ class UpdateViewSortActionType(UndoableActionType): :param view_sort: The view sort that needs to be updated. :param field: The field that must be sorted on. :param order: Indicates the sort order direction. + :param sort_type: The sort type that must be used, `default` is set as default + when the sort is created. """ original_field_id = view_sort.field.id @@ -885,9 +909,12 @@ class UpdateViewSortActionType(UndoableActionType): view_id = view_sort.view.id view_name = view_sort.view.name original_sort_order = view_sort.order + original_sort_type = view_sort.type handler = ViewHandler() - updated_view_sort = handler.update_sort(user, view_sort, field, order) + updated_view_sort = handler.update_sort( + user, view_sort, field, order, sort_type + ) cls.register_action( user=user, @@ -902,9 +929,11 @@ class UpdateViewSortActionType(UndoableActionType): updated_view_sort.view.table.database.name, updated_view_sort.id, updated_view_sort.order, + updated_view_sort.type, original_field_id, original_field_name, original_sort_order, + original_sort_type, ), scope=cls.scope(view_sort.view.id), workspace=view_sort.view.table.database.workspace, @@ -923,7 +952,13 @@ class UpdateViewSortActionType(UndoableActionType): view_handler = ViewHandler() view_sort = view_handler.get_sort(user, params.view_sort_id) - view_handler.update_sort(user, view_sort, field, params.original_sort_order) + view_handler.update_sort( + user, + view_sort, + field, + params.original_sort_order, + params.original_sort_type, + ) @classmethod def redo(cls, user: AbstractUser, params: Params, action_to_redo: Action): @@ -932,7 +967,9 @@ class UpdateViewSortActionType(UndoableActionType): view_handler = ViewHandler() view_sort = view_handler.get_sort(user, params.view_sort_id) - view_handler.update_sort(user, view_sort, field, params.sort_order) + view_handler.update_sort( + user, view_sort, field, params.sort_order, params.sort_type + ) class DeleteViewSortActionType(UndoableActionType): @@ -949,6 +986,7 @@ class DeleteViewSortActionType(UndoableActionType): "database_id", "view_sort_id", "sort_order", + "sort_type", ] @dataclasses.dataclass @@ -963,6 +1001,7 @@ class DeleteViewSortActionType(UndoableActionType): database_name: str view_sort_id: int sort_order: str + sort_type: str @classmethod def do(cls, user: AbstractUser, view_sort: ViewSort): @@ -983,6 +1022,7 @@ class DeleteViewSortActionType(UndoableActionType): field_id = view_sort.field.id field_name = view_sort.field.name sort_order = view_sort.order + sort_type = view_sort.type ViewHandler().delete_sort(user, view_sort) @@ -997,6 +1037,7 @@ class DeleteViewSortActionType(UndoableActionType): view_sort.view.table.database.name, view_sort_id, sort_order, + sort_type, ) workspace = view_sort.view.table.database.workspace cls.register_action(user, params, cls.scope(view_sort.view.id), workspace) @@ -1012,7 +1053,12 @@ class DeleteViewSortActionType(UndoableActionType): field = FieldHandler().get_field(params.field_id) view_handler.create_sort( - user, view, field, params.sort_order, params.view_sort_id + user, + view, + field, + params.sort_order, + params.view_sort_id, + params.sort_type, ) @classmethod @@ -1100,7 +1146,8 @@ class UpdateViewFieldOptionsActionType(UndoableActionType): VIEW_ACTION_CONTEXT, ) analytics_params = [ - "view_id" "table_id", + "view_id", + "table_id", "database_id", "field_options", "original_field_options", @@ -1934,6 +1981,7 @@ class CreateViewGroupByActionType(UndoableActionType): view_group_by_id: int group_by_order: str group_by_width: int + group_by_type: str @classmethod def do( @@ -1943,6 +1991,7 @@ class CreateViewGroupByActionType(UndoableActionType): field: Field, group_by_order: str, group_by_width: int, + group_by_type: str, ) -> ViewGroupBy: """ Creates a new view group_by. @@ -1956,10 +2005,11 @@ class CreateViewGroupByActionType(UndoableActionType): :param group_by_order: The desired order, can either be ascending (A to Z) or descending (Z to A). :param group_by_width: The pixel width of the group by. + :param group_by_type: @TODO docs """ view_group_by = ViewHandler().create_group_by( - user, view, field, group_by_order, group_by_width + user, view, field, group_by_order, group_by_width, group_by_type ) params = cls.Params( @@ -1974,6 +2024,7 @@ class CreateViewGroupByActionType(UndoableActionType): view_group_by.id, group_by_order, group_by_width, + group_by_type, ) workspace = view.table.database.workspace cls.register_action(user, params, cls.scope(view.id), workspace) @@ -2001,6 +2052,7 @@ class CreateViewGroupByActionType(UndoableActionType): field, params.group_by_order, params.group_by_width, + params.group_by_type, params.view_group_by_id, ) @@ -2020,10 +2072,12 @@ class UpdateViewGroupByActionType(UndoableActionType): "view_group_by_id", "group_by_order", "group_by_width", + "group_by_type", "original_field_id", "original_field_name", "original_group_by_order", "original_group_by_width", + "original_group_by_type", ] @dataclasses.dataclass @@ -2039,10 +2093,12 @@ class UpdateViewGroupByActionType(UndoableActionType): view_group_by_id: int group_by_order: str group_by_width: int + group_by_type: str original_field_id: int original_field_name: str original_group_by_order: str original_group_by_width: int + original_group_by_type: str @classmethod def do( @@ -2052,6 +2108,7 @@ class UpdateViewGroupByActionType(UndoableActionType): field: Optional[Field] = None, order: Optional[str] = None, width: Optional[int] = None, + sort_type: Optional[str] = None, ) -> ViewGroupBy: """ Updates the values of an existing view group_by. @@ -2064,6 +2121,8 @@ class UpdateViewGroupByActionType(UndoableActionType): :param field: The field that must be grouped on. :param order: Indicates the group by order direction. :param width: The visual pixel width of the group by. + :param sort_type: The sort type that must be used, `default` is set as default + when the sort is created. """ original_field_id = view_group_by.field.id @@ -2072,10 +2131,16 @@ class UpdateViewGroupByActionType(UndoableActionType): view_name = view_group_by.view.name original_group_by_order = view_group_by.order original_group_by_width = view_group_by.width + original_group_by_type = view_group_by.type handler = ViewHandler() updated_view_group_by = handler.update_group_by( - user, view_group_by, field, order, width + user, + view_group_by, + field, + order, + width, + sort_type, ) cls.register_action( @@ -2092,10 +2157,12 @@ class UpdateViewGroupByActionType(UndoableActionType): updated_view_group_by.id, updated_view_group_by.order, updated_view_group_by.width, + updated_view_group_by.type, original_field_id, original_field_name, original_group_by_order, original_group_by_width, + original_group_by_type, ), scope=cls.scope(view_group_by.view.id), workspace=view_group_by.view.table.database.workspace, @@ -2120,6 +2187,7 @@ class UpdateViewGroupByActionType(UndoableActionType): field, params.original_group_by_order, params.original_group_by_width, + params.original_group_by_type, ) @classmethod @@ -2130,7 +2198,12 @@ class UpdateViewGroupByActionType(UndoableActionType): view_group_by = view_handler.get_group_by(user, params.view_group_by_id) view_handler.update_group_by( - user, view_group_by, field, params.group_by_order, params.group_by_width + user, + view_group_by, + field, + params.group_by_order, + params.group_by_width, + params.group_by_type, ) @@ -2164,6 +2237,7 @@ class DeleteViewGroupByActionType(UndoableActionType): view_group_by_id: int group_by_order: str group_by_width: int + group_by_type: str @classmethod def do(cls, user: AbstractUser, view_group_by: ViewGroupBy): @@ -2185,6 +2259,7 @@ class DeleteViewGroupByActionType(UndoableActionType): field_name = view_group_by.field.name group_by_order = view_group_by.order group_by_width = view_group_by.width + group_by_type = view_group_by.type ViewHandler().delete_group_by(user, view_group_by) @@ -2200,6 +2275,7 @@ class DeleteViewGroupByActionType(UndoableActionType): view_group_by_id, group_by_order, group_by_width, + group_by_type, ) workspace = view_group_by.view.table.database.workspace cls.register_action(user, params, cls.scope(view_group_by.view.id), workspace) @@ -2220,6 +2296,7 @@ class DeleteViewGroupByActionType(UndoableActionType): field, params.group_by_order, params.group_by_width, + params.group_by_type, params.view_group_by_id, ) diff --git a/backend/src/baserow/contrib/database/views/handler.py b/backend/src/baserow/contrib/database/views/handler.py index ae728fa1d..5dc120cdc 100644 --- a/backend/src/baserow/contrib/database/views/handler.py +++ b/backend/src/baserow/contrib/database/views/handler.py @@ -1,4 +1,5 @@ import dataclasses +import itertools import re import traceback from collections import defaultdict, namedtuple @@ -125,13 +126,16 @@ from .exceptions import ( ViewSortNotSupported, ) from .models import ( + DEFAULT_SORT_TYPE_KEY, OWNERSHIP_TYPE_COLLABORATIVE, View, ViewDecoration, ViewFilter, ViewFilterGroup, ViewGroupBy, + ViewRows, ViewSort, + ViewSubscription, ) from .registries import ( decorator_type_registry, @@ -142,6 +146,8 @@ from .registries import ( ) from .signals import ( form_submitted, + rows_entered_view, + rows_exited_view, view_created, view_decoration_created, view_decoration_deleted, @@ -216,6 +222,41 @@ class ViewIndexingHandler(metaclass=baserow_trace_methods(tracer)): return f"i{table_id}:" + @classmethod + def before_field_type_change(cls, field: Field, model=None): + """ + Remove all the indexes for the views that have a sort on the field + that is being changed. + + :param field: The field that is being changed. + :param model: The model to use for the table. If not provided it will be + taken from the field. + """ + + views = View.objects.filter( + id__in=ViewSort.objects.filter(field=field).values("view_id"), + db_index_name__isnull=False, + ) + if not views: + return + + if model is None: + model = field.table.get_model() + + dropped_indexes = set() + for view in views: + if view.db_index_name in dropped_indexes: + continue + + cls.drop_index( + view=view, + db_index=django_models.Index("id", name=view.db_index_name), + model=model, + ) + dropped_indexes.add(view.db_index_name) + + View.objects.filter(id__in=[v.id for v in views]).update(db_index_name=None) + @classmethod def _get_index_hash( cls, field_order_bys: List[OptionallyAnnotatedOrderBy] @@ -312,6 +353,7 @@ class ViewIndexingHandler(metaclass=baserow_trace_methods(tracer)): field_object["field"], field_object["name"], view_sort_or_group_by.order, + view_sort_or_group_by.type, table_model=model, ) @@ -440,6 +482,12 @@ class ViewIndexingHandler(metaclass=baserow_trace_methods(tracer)): ): return current_index_name + cls.drop_index(view, db_index, model) + + return current_index_name + + @classmethod + def drop_index(cls, view, db_index, model=None): if model is None: model = view.table.get_model() @@ -452,8 +500,6 @@ class ViewIndexingHandler(metaclass=baserow_trace_methods(tracer)): view_table_id=view.table_id, ) - return current_index_name - @classmethod def update_index_by_view_id(cls, view_id: int, nowait=True): """ @@ -591,6 +637,16 @@ class ViewHandler(metaclass=baserow_trace_methods(tracer)): ) return views + def before_field_type_change(self, field: Field): + """ + Allow trigger custom logic before field is changed. + By default it calls ViewIndexingHandler.before_field_type_change. + + :param field: The field that is being changed. + """ + + ViewIndexingHandler.before_field_type_change(field) + def list_workspace_views( self, user: AbstractUser, @@ -874,7 +930,9 @@ class ViewHandler(metaclass=baserow_trace_methods(tracer)): view_type = view_type_registry.get_by_model(original_view) - cache = {} + cache = { + "workspace_id": workspace.id, + } # Use export/import to duplicate the view easily serialized = view_type.export_serialized(original_view, cache) @@ -896,6 +954,7 @@ class ViewHandler(metaclass=baserow_trace_methods(tracer)): # the mapping remain the same. They haven't change because we're only # reimporting the view and not the table, fields, etc. id_mapping = { + "workspace_id": workspace.id, "database_fields": MirrorDict(), "database_field_select_options": MirrorDict(), } @@ -1317,13 +1376,17 @@ class ViewHandler(metaclass=baserow_trace_methods(tracer)): # `after_fields_changed_or_deleted` can be called in bulk and make it query # efficient. changed_fields = set() + all_fields_mapping = {field.id: field for field in fields} + # Fetch the sorts of all updated fields to check if the sort, including the + # type, is still compatible. + sorts_to_check = ViewSort.objects.filter(field_id__in=all_fields_mapping.keys()) fields_to_delete_sortings = [ - f - for f in fields + all_fields_mapping[sort.field_id] + for sort in sorts_to_check if not field_type_registry.get_by_model( - f.specific_class - ).check_can_order_by(f) + all_fields_mapping[sort.field_id].specific_class + ).check_can_order_by(all_fields_mapping[sort.field_id], sort.type) ] # If it's a primary field, we also need to remove any sortings on the @@ -1344,12 +1407,17 @@ class ViewHandler(metaclass=baserow_trace_methods(tracer)): if deleted_count > 0: changed_fields.update(fields_to_delete_sortings) + # Fetch the group bys of all updated fields to check if the group by, including + # the type, is still compatible. + groups_to_check = ViewGroupBy.objects.filter( + field_id__in=all_fields_mapping.keys() + ) fields_to_delete_groupings = [ - f - for f in fields + all_fields_mapping[sort.field_id] + for sort in groups_to_check if not field_type_registry.get_by_model( - f.specific_class - ).check_can_group_by(f) + all_fields_mapping[sort.field_id].specific_class + ).check_can_group_by(all_fields_mapping[sort.field_id], sort.type) ] if fields_to_delete_groupings: deleted_count, _ = ViewGroupBy.objects.filter( @@ -1422,7 +1490,7 @@ class ViewHandler(metaclass=baserow_trace_methods(tracer)): field_type = field_type_registry.get_by_model(field.specific_class) # Check whether the updated field is still compatible with the group by. # If not, it must be deleted. - if not field_type.check_can_group_by(field): + if not field_type.check_can_group_by(field, DEFAULT_SORT_TYPE_KEY): ViewGroupBy.objects.filter(field=field).delete() def get_filter_builder( @@ -1877,6 +1945,7 @@ class ViewHandler(metaclass=baserow_trace_methods(tracer)): field, field_name, view_sort_or_group_by.order, + view_sort_or_group_by.type, table_model=queryset.model, ) field_annotation = field_annotated_order_by.annotation @@ -2008,6 +2077,7 @@ class ViewHandler(metaclass=baserow_trace_methods(tracer)): field: Field, order: str, primary_key: Optional[int] = None, + sort_type: Optional[str] = None, ) -> ViewSort: """ Creates a new view sort. @@ -2018,6 +2088,8 @@ class ViewHandler(metaclass=baserow_trace_methods(tracer)): :param order: The desired order, can either be ascending (A to Z) or descending (Z to A). :param primary_key: An optional primary key to give to the new view sort. + :param sort_type: The sort type that must be used, `default` is set as default + when the sort is created. :raises ViewSortNotSupported: When the provided view does not support sorting. :raises FieldNotInTable: When the provided field does not belong to the provided view's table. @@ -2034,6 +2106,9 @@ class ViewHandler(metaclass=baserow_trace_methods(tracer)): user, CreateViewSortOperationType.type, workspace=workspace, context=view ) + if not sort_type: + sort_type = DEFAULT_SORT_TYPE_KEY + # Check if view supports sorting. view_type = view_type_registry.get_by_model(view.specific_class) if not view_type.can_sort: @@ -2043,9 +2118,9 @@ class ViewHandler(metaclass=baserow_trace_methods(tracer)): # Check if the field supports sorting. field_type = field_type_registry.get_by_model(field.specific_class) - if not field_type.check_can_order_by(field): + if not field_type.check_can_order_by(field, sort_type): raise ViewSortFieldNotSupported( - f"The field {field.pk} does not support sorting." + f"The field {field.pk} does not support sorting with type {sort_type}." ) # Check if field belongs to the grid views table @@ -2061,7 +2136,11 @@ class ViewHandler(metaclass=baserow_trace_methods(tracer)): ) view_sort = ViewSort.objects.create( - pk=primary_key, view=view, field=field, order=order + pk=primary_key, + view=view, + field=field, + order=order, + type=sort_type, ) view_sort_created.send(self, view_sort=view_sort, user=user) @@ -2074,6 +2153,7 @@ class ViewHandler(metaclass=baserow_trace_methods(tracer)): view_sort: ViewSort, field: Optional[Field] = None, order: Optional[str] = None, + sort_type: Optional[str] = None, ) -> ViewSort: """ Updates the values of an existing view sort. @@ -2095,6 +2175,7 @@ class ViewHandler(metaclass=baserow_trace_methods(tracer)): workspace = view_sort.view.table.database.workspace field = field if field is not None else view_sort.field order = order if order is not None else view_sort.order + sort_type = sort_type if sort_type is not None else view_sort.type CoreHandler().check_permissions( user, ReadFieldOperationType.type, workspace=workspace, context=field @@ -2119,7 +2200,12 @@ class ViewHandler(metaclass=baserow_trace_methods(tracer)): # If the field has changed we need to check if the new field type supports # sorting. field_type = field_type_registry.get_by_model(field.specific_class) - if field.id != view_sort.field_id and not field_type.check_can_order_by(field): + if ( + field.id != view_sort.field_id or sort_type != view_sort.type + ) and not field_type.check_can_order_by( + field, + sort_type, + ): raise ViewSortFieldNotSupported( f"The field {field.pk} does not support sorting." ) @@ -2136,6 +2222,7 @@ class ViewHandler(metaclass=baserow_trace_methods(tracer)): view_sort.field = field view_sort.order = order + view_sort.type = sort_type view_sort.save() view_sort_updated.send(self, view_sort=view_sort, user=user) @@ -2238,6 +2325,7 @@ class ViewHandler(metaclass=baserow_trace_methods(tracer)): field: Field, order: str, width: int, + sort_type: str = None, primary_key: Optional[int] = None, ) -> ViewGroupBy: """ @@ -2248,6 +2336,9 @@ class ViewHandler(metaclass=baserow_trace_methods(tracer)): :param field: The field that needs to be grouped. :param order: The desired order, can either be ascending (A to Z) or descending (Z to A). + :param width: The visual width of the group column. + :param sort_type: The sort type that must be used, `default` is set as default + when the sort is created. :param primary_key: An optional primary key to give to the new view group_by. :raises ViewGroupByNotSupported: When the provided view does not support grouping. @@ -2264,6 +2355,9 @@ class ViewHandler(metaclass=baserow_trace_methods(tracer)): user, CreateViewGroupByOperationType.type, workspace=workspace, context=view ) + if not sort_type: + sort_type = DEFAULT_SORT_TYPE_KEY + # Check if view supports grouping. view_type = view_type_registry.get_by_model(view.specific_class) if not view_type.can_group_by: @@ -2273,9 +2367,9 @@ class ViewHandler(metaclass=baserow_trace_methods(tracer)): # Check if the field supports grouping. field_type = field_type_registry.get_by_model(field.specific_class) - if not field_type.check_can_group_by(field): + if not field_type.check_can_group_by(field, sort_type): raise ViewGroupByFieldNotSupported( - f"The field {field.pk} does not support grouping." + f"The field {field.pk} does not support grouping with type {sort_type}." ) # Check if field belongs to the grid views table @@ -2291,7 +2385,12 @@ class ViewHandler(metaclass=baserow_trace_methods(tracer)): ) view_group_by = ViewGroupBy.objects.create( - pk=primary_key, view=view, field=field, order=order, width=width + pk=primary_key, + view=view, + field=field, + order=order, + width=width, + type=sort_type, ) view_group_by_created.send(self, view_group_by=view_group_by, user=user) @@ -2305,6 +2404,7 @@ class ViewHandler(metaclass=baserow_trace_methods(tracer)): field: Optional[Field] = None, order: Optional[str] = None, width: Optional[int] = None, + sort_type: Optional[str] = None, ) -> ViewGroupBy: """ Updates the values of an existing view group_by. @@ -2314,6 +2414,8 @@ class ViewHandler(metaclass=baserow_trace_methods(tracer)): :param field: The field that must be grouped on. :param order: Indicates the group by order direction. :param width: The visual width of the group by. + :param sort_type: The sort type that must be used, `default` is set as default + when the sort is created. :raises ViewGroupByDoesNotExist: When the view used by the filter is trashed. :raises ViewGroupByFieldNotSupported: When the field does not support grouping. :raises FieldNotInTable: When the provided field does not belong to the @@ -2330,6 +2432,7 @@ class ViewHandler(metaclass=baserow_trace_methods(tracer)): field = field if field is not None else view_group_by.field order = order if order is not None else view_group_by.order width = width if width is not None else view_group_by.width + sort_type = sort_type if sort_type is not None else view_group_by.type CoreHandler().check_permissions( user, ReadFieldOperationType.type, workspace=workspace, context=field @@ -2354,8 +2457,11 @@ class ViewHandler(metaclass=baserow_trace_methods(tracer)): # If the field has changed we need to check if the new field type supports # grouping. field_type = field_type_registry.get_by_model(field.specific_class) - if field.id != view_group_by.field_id and not field_type.check_can_order_by( - field + if ( + field.id != view_group_by.field_id or sort_type != view_group_by.type + ) and not field_type.check_can_order_by( + field, + sort_type, ): raise ViewGroupByFieldNotSupported( f"The field {field.pk} does not support grouping." @@ -2368,12 +2474,14 @@ class ViewHandler(metaclass=baserow_trace_methods(tracer)): and view_group_by.view.viewgroupby_set.filter(field_id=field.pk).exists() ): raise ViewGroupByFieldAlreadyExist( - f"A group by for the field {field.pk} already exists." + f"A group by for the field {field.pk} already exists with type " + f"{sort_type}." ) view_group_by.field = field view_group_by.order = order view_group_by.width = width + view_group_by.type = sort_type view_group_by.save() view_group_by_updated.send(self, view_group_by=view_group_by, user=user) @@ -3206,7 +3314,12 @@ class ViewHandler(metaclass=baserow_trace_methods(tracer)): return view def submit_form_view( - self, user, form, values, model=None, enabled_field_options=None + self, + user, + form, + values, + model: GeneratedTableModel | None = None, + enabled_field_options=None, ): """ Handles when a form is submitted. It will validate the data by checking if @@ -3522,7 +3635,7 @@ class ViewHandler(metaclass=baserow_trace_methods(tracer)): field_name = field.db_column field_type = field_type_registry.get_by_model(field.specific_class) - if not field_type.check_can_group_by(field): + if not field_type.check_can_group_by(field, DEFAULT_SORT_TYPE_KEY): raise ValueError(f"Can't group by {field_name}.") value = getattr(row, field_name) @@ -3753,3 +3866,127 @@ class CachingPublicViewRowChecker: # filters and so the result of the first check will be still # valid for any subsequent checks. return True + + +class ViewSubscriptionHandler: + @classmethod + def subscribe_to_views(cls, subscriber: django_models.Model, views: list[View]): + """ + Subscribes a subscriber to the provided views. If the ViewRows already exist, it + ensure to notify any changes to the subscriber first, so that the subscriber can + be notified only for the changes that happened after the subscription. + + :param subscriber: The subscriber to subscribe to the views. + :param views: The views to subscribe to. + """ + + cls.notify_table_views_updates(views) + ViewRows.create_missing_for_views(views) + + new_subscriptions = [] + for view in views: + new_subscriptions.append(ViewSubscription(subscriber=subscriber, view=view)) + ViewSubscription.objects.bulk_create(new_subscriptions, ignore_conflicts=True) + + @classmethod + def unsubscribe_from_views( + cls, subscriber: django_models.Model, views: list[View] | None = None + ): + """ + Unsubscribes a subscriber from the provided views. If the views are not + provided, it unsubscribes the subscriber from all views. Make sure to use a + table-specific model for the subscriber to avoid unsubscribing from views that + are not related to the subscriber. + + :param subscriber: The subscriber to unsubscribe from the views. + :param views: The views to unsubscribe from. If not provided, the subscriber + will be unsubscribed + """ + + q = Q( + subscriber_content_type=ContentType.objects.get_for_model(subscriber), + subscriber_id=subscriber.pk, + ) + if views is not None: + q &= Q(view__in=views) + + ViewSubscription.objects.filter(q).delete() + + @classmethod + def check_views_with_time_sensitive_filters(cls): + """ + Checks for views that have time-sensitive filters. If a view has a + time-sensitive filter, calling this method periodically ensure proper signals + are emitted to notify subscribers that the view results have changed. + """ + + views = View.objects.filter( + id__in=ViewFilter.objects.filter( + type__in=view_filter_type_registry.get_time_sensitive_filter_types(), + view__in=ViewSubscription.objects.values("view"), + ).values("view_id") + ).order_by("table", "id") + for _, view_group in itertools.groupby(views, key=lambda f: f.table): + view_ids = [v.id for v in view_group] + if view_ids: + cls._notify_table_views_updates(view_ids) + + @classmethod + def notify_table_views_updates( + cls, views: list[View], model: GeneratedTableModel | None = None + ): + """ + Verify if the views have subscribers and notify them of any changes in the view + results. + + :param views: The views to notify subscribers of. + :param model: The table model to use for the views. If not provided, the model + will be generated automatically. + """ + + view_ids_with_subscribers = ViewSubscription.objects.filter( + view__in=views + ).values_list("view_id", flat=True) + if view_ids_with_subscribers: + cls._notify_table_views_updates(view_ids_with_subscribers, model) + + @classmethod + def _notify_table_views_updates( + cls, view_ids: list[int], model: GeneratedTableModel | None = None + ): + """ + Notify subscribers of any changes in the view results, emitting the appropriate + signals and updating the ViewRows state. + + :param view_ids: The view ids to notify subscribers of. + :param model: The table model to use for the views. If not provided, the model + will be generated automatically + """ + + view_rows = list( + ViewRows.objects.select_related("view__table") + .filter(view_id__in=view_ids) + .select_for_update(of=("self",)) + .order_by("view_id") + ) + + if model is None: + model = view_rows[0].view.table.get_model() + + for view_state in view_rows: + view = view_state.view + new_row_ids, row_ids_entered, row_ids_exited = view_state.get_diff(model) + changed = False + if row_ids_entered: + rows_entered_view.send( + sender=cls, view=view, row_ids=row_ids_entered, model=model + ) + changed = True + if row_ids_exited: + rows_exited_view.send( + sender=cls, view=view, row_ids=row_ids_exited, model=model + ) + changed = True + if changed: + view_state.row_ids = new_row_ids + view_state.save() diff --git a/backend/src/baserow/contrib/database/views/models.py b/backend/src/baserow/contrib/database/views/models.py index ffd469ae9..0c1bf916b 100644 --- a/backend/src/baserow/contrib/database/views/models.py +++ b/backend/src/baserow/contrib/database/views/models.py @@ -4,7 +4,9 @@ from typing import Iterable, Optional, Union from django.contrib.auth.hashers import check_password, make_password from django.contrib.auth.models import User +from django.contrib.contenttypes.fields import GenericForeignKey from django.contrib.contenttypes.models import ContentType +from django.contrib.postgres.fields import ArrayField from django.db import models from django.db.models import Q from django.db.models.query import Prefetch @@ -53,6 +55,9 @@ VIEW_OWNERSHIP_TYPES = [OWNERSHIP_TYPE_COLLABORATIVE] # Must be the same as `modules/database/constants.js`. DEFAULT_FORM_VIEW_FIELD_COMPONENT_KEY = "default" +# Must be the same as `modules/database/constants.js`. +DEFAULT_SORT_TYPE_KEY = "default" + def get_default_view_content_type(): return ContentType.objects.get_for_model(View) @@ -501,6 +506,13 @@ class ViewSort(HierarchicalModelMixin, models.Model): "and DESC (Descending) is from Z to A.", default=SORT_ORDER_ASC, ) + type = models.CharField( + max_length=32, + default=DEFAULT_SORT_TYPE_KEY, + db_default=DEFAULT_SORT_TYPE_KEY, + help_text=f"Indicates the sort type. Will automatically fall back to `" + f"{DEFAULT_SORT_TYPE_KEY}` if incompatible with field type.", + ) def get_parent(self): return self.view @@ -536,6 +548,13 @@ class ViewGroupBy(HierarchicalModelMixin, models.Model): "and DESC (Descending) is from Z to A.", default=SORT_ORDER_ASC, ) + type = models.CharField( + max_length=32, + default=DEFAULT_SORT_TYPE_KEY, + db_default=DEFAULT_SORT_TYPE_KEY, + help_text=f"Indicates the sort type. Will automatically fall back to `" + f"{DEFAULT_SORT_TYPE_KEY}` if incompatible with field type.", + ) width = models.PositiveIntegerField( default=200, help_text="The pixel width of the group by in the related view.", @@ -936,3 +955,68 @@ class FormViewFieldOptionsCondition(HierarchicalModelMixin, models.Model): class Meta: ordering = ("id",) + + +class ViewRows(CreatedAndUpdatedOnMixin, models.Model): + view = models.OneToOneField(View, on_delete=models.CASCADE, related_name="rows") + row_ids = ArrayField( + models.PositiveIntegerField(), + default=list, + help_text="The rows that are shown in the view. This list can be used by webhooks " + "to determine which rows have been changed since the last check.", + ) + + @classmethod + def create_missing_for_views(cls, views: list[View], model=None): + """ + Creates ViewRows objects for the given views if they don't already exist. + + :param views: The views for which to create ViewRows objects. + """ + + from baserow.contrib.database.views.handler import ViewHandler + + existing_view_ids = ViewRows.objects.filter(view__in=views).values_list( + "view_id", flat=True + ) + view_map = {view.id: view for view in views} + missing_view_ids = list(set(view_map.keys()) - set(existing_view_ids)) + + view_rows = [] + for view_id in missing_view_ids: + view = view_map[view_id] + row_ids = ( + ViewHandler() + .get_queryset(view, model=model, apply_sorts=False) + .values_list("id", flat=True) + ) + view_rows.append(ViewRows(view=view, row_ids=list(row_ids))) + + return ViewRows.objects.bulk_create(view_rows, ignore_conflicts=True) + + def get_diff(self, model=None): + """ + Executes the view query and returns the current row IDs in the view, + along with the differences between the current state and the last saved state. + """ + + from baserow.contrib.database.views.handler import ViewHandler + + rows = ViewHandler().get_queryset(self.view, model=model, apply_sorts=False) + previous_row_ids = set(self.row_ids) + new_row_ids = set(rows.order_by().values_list("id", flat=True)) + + row_ids_entered = new_row_ids - previous_row_ids + row_ids_exited = previous_row_ids - new_row_ids + + return list(new_row_ids), list(row_ids_entered), list(row_ids_exited) + + +class ViewSubscription(models.Model): + view = models.ForeignKey(View, on_delete=models.CASCADE, related_name="subscribers") + subscriber_content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE) + subscriber_id = models.PositiveIntegerField() + subscriber = GenericForeignKey("subscriber_content_type", "subscriber_id") + + class Meta: + unique_together = ("view", "subscriber_content_type", "subscriber_id") diff --git a/backend/src/baserow/contrib/database/views/receivers.py b/backend/src/baserow/contrib/database/views/receivers.py new file mode 100644 index 000000000..138daafac --- /dev/null +++ b/backend/src/baserow/contrib/database/views/receivers.py @@ -0,0 +1,98 @@ +from django.dispatch import receiver + +from baserow.contrib.database.fields.signals import ( + field_deleted, + field_restored, + field_updated, +) +from baserow.contrib.database.rows.signals import ( + rows_created, + rows_deleted, + rows_updated, +) +from baserow.contrib.database.table.models import GeneratedTableModel, Table +from baserow.contrib.database.views.models import View +from baserow.contrib.database.views.signals import ( + view_filter_created, + view_filter_deleted, + view_filter_group_created, + view_filter_group_deleted, + view_filter_group_updated, + view_filter_updated, + view_updated, +) + +from .handler import ViewSubscriptionHandler + + +def _notify_table_data_updated(table: Table, model: GeneratedTableModel | None = None): + """ + Notifies the table views that the table data has been updated. This will result in + the table views to be updated and the subscribers to be notified. + + :param table: The table for which the data has been updated. + :param model: The model that was updated if available. + """ + + ViewSubscriptionHandler.notify_table_views_updates( + table.view_set.all(), model=model + ) + + +def _notify_view_results_updated(view: View): + """ + Notify the table view that the results of the view have been updated. This will + result in the subscribers to be notified. + + :param view: The view for which the results have been updated. + """ + + ViewSubscriptionHandler.notify_table_views_updates([view]) + + +@receiver([rows_updated, rows_created, rows_deleted]) +def notify_rows_signals(sender, rows, user, table, model, dependant_fields, **kwargs): + _notify_table_data_updated(table, model) + + updated_tables = set() + for field in dependant_fields: + updated_tables.add(field.table) + for updated_table in updated_tables: + _notify_table_data_updated(updated_table) + + +@receiver(view_updated) +def notify_view_updated(sender, view, user, old_view, **kwargs): + _notify_view_results_updated(view) + + +@receiver([view_filter_created, view_filter_updated, view_filter_deleted]) +def notify_view_filter_created_or_updated(sender, view_filter, user, **kwargs): + _notify_view_results_updated(view_filter.view) + + +@receiver( + [view_filter_group_created, view_filter_group_updated, view_filter_group_deleted] +) +def notify_view_filter_group_created_or_updated( + sender, view_filter_group, user, **kwargs +): + _notify_view_results_updated(view_filter_group.view) + + +def _notify_tables_of_fields_updated_or_deleted(field, related_fields, user, **kwargs): + tables_to_notify = set([field.table]) + for updated_field in related_fields: + tables_to_notify.add(updated_field.table) + for table in tables_to_notify: + _notify_table_data_updated(table) + + +@receiver([field_restored, field_updated]) +def notify_field_updated(sender, field, related_fields, user, **kwargs): + _notify_tables_of_fields_updated_or_deleted(field, related_fields, user, **kwargs) + + +@receiver(field_deleted) +def notify_field_deleted(sender, field_id, field, related_fields, user, **kwargs): + _notify_tables_of_fields_updated_or_deleted(field, related_fields, user, **kwargs) diff --git a/backend/src/baserow/contrib/database/views/registries.py b/backend/src/baserow/contrib/database/views/registries.py index a1bc7ff72..8dc5c6541 100644 --- a/backend/src/baserow/contrib/database/views/registries.py +++ b/backend/src/baserow/contrib/database/views/registries.py @@ -1007,6 +1007,19 @@ class ViewFilterType(Instance): for t in self.compatible_field_types ) + @property + def time_sensitive(self) -> bool: + """ + Indicates if the filter results depend on the current time. + For example, filters like 'date_is' with operators like `today` or `yesterday` + will return different results as time passes, even if the underlying + data hasn't changed. + + :returns: True if the filter results change based on current time + """ + + return False + class ViewFilterTypeRegistry(Registry): """ @@ -1020,6 +1033,21 @@ class ViewFilterTypeRegistry(Registry): does_not_exist_exception_class = ViewFilterTypeDoesNotExist already_registered_exception_class = ViewFilterTypeAlreadyRegistered + def get_time_sensitive_filter_types(self) -> List[str]: + """ + Returns a list of filter types that are time-dependent. For example, filters + like `date_is` with operators like `today` or `yesterday` will return different + results as time passes, even if the underlying data hasn't changed. + + :returns: A list of filter types that are time-sensitive + """ + + return [ + filter_type.type + for filter_type in self.registry.values() + if filter_type.time_sensitive + ] + class ViewAggregationType(Instance): """ diff --git a/backend/src/baserow/contrib/database/views/signals.py b/backend/src/baserow/contrib/database/views/signals.py index 0954992f7..067d9a1fe 100644 --- a/backend/src/baserow/contrib/database/views/signals.py +++ b/backend/src/baserow/contrib/database/views/signals.py @@ -31,6 +31,9 @@ view_decoration_deleted = Signal() view_field_options_updated = Signal() +rows_entered_view = Signal() +rows_exited_view = Signal() + @receiver(field_signals.field_deleted) def field_deleted(sender, field, **kwargs): diff --git a/backend/src/baserow/contrib/database/views/tasks.py b/backend/src/baserow/contrib/database/views/tasks.py index c75c6ac00..5478fa11f 100644 --- a/backend/src/baserow/contrib/database/views/tasks.py +++ b/backend/src/baserow/contrib/database/views/tasks.py @@ -1,4 +1,5 @@ import traceback +from datetime import timedelta from django.conf import settings from django.core.cache import cache @@ -9,7 +10,10 @@ from loguru import logger from baserow.config.celery import app from baserow.contrib.database.views.exceptions import ViewDoesNotExist -from baserow.contrib.database.views.handler import ViewIndexingHandler +from baserow.contrib.database.views.handler import ( + ViewIndexingHandler, + ViewSubscriptionHandler, +) AUTO_INDEX_CACHE_KEY = "auto_index_view_cache_key" @@ -105,3 +109,23 @@ def schedule_view_index_update(view_id: int): return transaction.on_commit(lambda: _schedule_view_index_update(view_id)) + + +@app.task(queue="export") +def periodic_check_for_views_with_time_sensitive_filters(): + """ + Periodically checks for views that have time-sensitive filters. If a view has a + time-sensitive filter, this task ensure proper signals are emitted to notify + subscribers that the view results have changed. + """ + + with transaction.atomic(): + ViewSubscriptionHandler.check_views_with_time_sensitive_filters() + + +@app.on_after_finalize.connect +def setup_periodic_tasks(sender, **kwargs): + sender.add_periodic_task( + timedelta(minutes=30), + periodic_check_for_views_with_time_sensitive_filters.s(), + ) diff --git a/backend/src/baserow/contrib/database/views/view_filters.py b/backend/src/baserow/contrib/database/views/view_filters.py index a68829c84..e077dc71b 100644 --- a/backend/src/baserow/contrib/database/views/view_filters.py +++ b/backend/src/baserow/contrib/database/views/view_filters.py @@ -21,6 +21,7 @@ from baserow.contrib.database.fields.field_filters import ( FilterBuilder, OptionallyAnnotatedQ, filename_contains_filter, + map_ids_from_csv_string, parse_ids_from_csv_string, ) from baserow.contrib.database.fields.field_types import ( @@ -436,6 +437,10 @@ class HigherThanOrEqualViewFilterType(NumericComparisonViewFilterType): class TimezoneAwareDateViewFilterType(ViewFilterType): + @property + def time_sensitive(self) -> bool: + return True + compatible_field_types = [ DateFieldType.type, LastModifiedFieldType.type, @@ -1102,13 +1107,12 @@ class SingleSelectEqualViewFilterType(ViewFilterType): return filter_function(field_name, value, model_field, field) def set_import_serialized_value(self, value, id_mapping): + mapping = id_mapping["database_field_select_options"] try: - value = int(value) - except ValueError: + return map_ids_from_csv_string(value, mapping)[0] + except IndexError: return "" - return str(id_mapping["database_field_select_options"].get(value, "")) - class SingleSelectNotEqualViewFilterType( NotViewFilterTypeMixin, SingleSelectEqualViewFilterType @@ -1159,13 +1163,8 @@ class SingleSelectIsAnyOfViewFilterType(ViewFilterType): return filter_function(field_name, option_ids, model_field, field) def set_import_serialized_value(self, value: str | None, id_mapping: dict) -> str: - # Parses the old option ids and remaps them to the new option ids. - old_options_ids = parse_ids_from_csv_string(value or "") select_option_map = id_mapping["database_field_select_options"] - new_values = [] - for old_id in old_options_ids: - if new_id := select_option_map.get(old_id): - new_values.append(str(new_id)) + new_values = map_ids_from_csv_string(value or "", select_option_map) return ",".join(new_values) @@ -1414,15 +1413,8 @@ class MultipleSelectHasViewFilterType(ManyToManyHasBaseViewFilter): return filter_function(field_name, option_ids, model_field, field) def set_import_serialized_value(self, value: str | None, id_mapping: dict) -> str: - # Parses the old option ids and remaps them to the new option ids. - old_options_ids = parse_ids_from_csv_string(value or "") select_option_map = id_mapping["database_field_select_options"] - - new_values = [] - for old_id in old_options_ids: - if new_id := select_option_map.get(old_id): - new_values.append(str(new_id)) - + new_values = map_ids_from_csv_string(value or "", select_option_map) return ",".join(new_values) @@ -1777,6 +1769,10 @@ DATE_FILTER_OPERATOR_DELTA_MAP = { class BaseDateMultiStepViewFilterType(ViewFilterType): incompatible_operators = [] + @property + def time_sensitive(self) -> bool: + return True + def get_filter_date( self, operator: str, diff --git a/backend/src/baserow/contrib/database/webhooks/exceptions.py b/backend/src/baserow/contrib/database/webhooks/exceptions.py index 19c7db54b..93f04081d 100644 --- a/backend/src/baserow/contrib/database/webhooks/exceptions.py +++ b/backend/src/baserow/contrib/database/webhooks/exceptions.py @@ -18,5 +18,21 @@ class TableWebhookEventConfigFieldNotInTable(Exception): ) +class TableWebhookEventConfigViewNotInTable(Exception): + """Raised when trying to update the""" + + def __init__(self, view_id=None, *args, **kwargs): + self.view_id = view_id + super().__init__( + f"The view {view_id} does not belong to the table.", + *args, + **kwargs, + ) + + class SkipWebhookCall(Exception): """Raised when the webhook call must be skipped""" + + +class WebhookPayloadTooLarge(Exception): + """Raised when the webhook payload is too large and exceeds the batches limit.""" diff --git a/backend/src/baserow/contrib/database/webhooks/handler.py b/backend/src/baserow/contrib/database/webhooks/handler.py index c20f26164..1a969e985 100644 --- a/backend/src/baserow/contrib/database/webhooks/handler.py +++ b/backend/src/baserow/contrib/database/webhooks/handler.py @@ -11,12 +11,14 @@ from requests import PreparedRequest, Response from baserow.contrib.database.fields.models import Field from baserow.contrib.database.table.models import Table +from baserow.contrib.database.views.models import View from baserow.core.handler import CoreHandler from baserow.core.utils import extract_allowed, set_allowed_attrs from .exceptions import ( TableWebhookDoesNotExist, TableWebhookEventConfigFieldNotInTable, + TableWebhookEventConfigViewNotInTable, TableWebhookMaxAllowedCountExceeded, ) from .models import ( @@ -39,18 +41,21 @@ from .validators import get_webhook_request_function class WebhookHandler: - def find_webhooks_to_call(self, table_id: int, event_type: str) -> QuerySet: + def find_webhooks_to_call( + self, table_id: int, event_type: str, additional_filters: Q | None = None + ) -> QuerySet[TableWebhook]: """ This function is responsible for finding all the webhooks related to a table that must be triggered on a specific event. """ - q = Q() - q.add(Q(events__event_type__in=[event_type]), Q.OR) + q = Q(events__event_type__in=[event_type]) + if additional_filters is not None: + q &= additional_filters event_type_object = webhook_event_type_registry.get(event_type) if event_type_object.should_trigger_when_all_event_types_selected: - q.add(Q(include_all_events=True), Q.OR) + q |= Q(include_all_events=True) return ( TableWebhook.objects.filter( @@ -170,14 +175,25 @@ class WebhookHandler: # could have been deleted. if not event_object: continue - event_fields = Field.objects.filter( - table_id=webhook.table_id, id__in=event["fields"] - ) - for field_id in event["fields"]: - if not next((f for f in event_fields if field_id == f.id), None): + + # Set fields + field_ids = event.get("fields", []) + fields = Field.objects.filter(table_id=webhook.table_id, id__in=field_ids) + for field_id in field_ids: + if not next((f for f in fields if field_id == f.id), None): raise TableWebhookEventConfigFieldNotInTable(field_id) - event_object.fields.set(event_fields) + event_object.fields.set(fields) + + # Set views + view_ids = event.get("views", []) + views = View.objects.filter(id__in=view_ids, table_id=webhook.table_id) + for view_id in view_ids: + if not next((v for v in views if view_id == v.id), None): + raise TableWebhookEventConfigViewNotInTable(view_id) + + event_object.views.set(views) + event_object.get_type().after_update(event_object) def create_table_webhook( self, @@ -223,20 +239,24 @@ class WebhookHandler: values = extract_allowed(kwargs, allowed_fields) webhook = TableWebhook.objects.create(table_id=table.id, **values) + webhook_events = [] if events is not None and not values.get("include_all_events"): - event_headers = [] - for event in events: - event_object = TableWebhookEvent( - event_type=event, webhook_id=webhook.id + for event_type in events: + webhook_event = TableWebhookEvent( + event_type=event_type, webhook=webhook ) - event_object.full_clean() - event_headers.append(event_object) + webhook_event.full_clean() + webhook_events.append(webhook_event) - webhook_events = TableWebhookEvent.objects.bulk_create(event_headers) + webhook_events = TableWebhookEvent.objects.bulk_create(webhook_events) if event_config is not None and not values.get("include_all_events"): self._update_webhook_event_config(webhook, event_config, webhook_events) + for webhook_event in webhook_events: + webhook_event_type = webhook_event.get_type() + webhook_event_type.after_create(webhook_event) + if headers is not None: header_objects = [] for key, value in headers.items(): @@ -247,7 +267,6 @@ class WebhookHandler: header_objects.append(header) TableWebhookHeader.objects.bulk_create(header_objects) - return webhook def update_table_webhook( @@ -303,6 +322,7 @@ class WebhookHandler: kwargs.get("include_all_events", False) and not old_include_all_events ) + created_events = [] if not should_update_events: TableWebhookEvent.objects.filter(webhook=webhook).delete() elif events is not None: @@ -327,11 +347,15 @@ class WebhookHandler: ] if len(events_to_create) > 0: - TableWebhookEvent.objects.bulk_create(events_to_create) + created_events = TableWebhookEvent.objects.bulk_create(events_to_create) if event_config is not None and should_update_events: self._update_webhook_event_config(webhook, event_config) + for webhook_event in created_events: + webhook_event_type = webhook_event.get_type() + webhook_event_type.after_create(webhook_event) + if headers is not None: existing_headers = webhook.headers.all() diff --git a/backend/src/baserow/contrib/database/webhooks/models.py b/backend/src/baserow/contrib/database/webhooks/models.py index f2d4ecfce..b1687c4b0 100644 --- a/backend/src/baserow/contrib/database/webhooks/models.py +++ b/backend/src/baserow/contrib/database/webhooks/models.py @@ -1,10 +1,13 @@ import uuid +from django.conf import settings +from django.contrib.contenttypes.fields import GenericRelation from django.core.validators import MaxLengthValidator from django.db import models from baserow.contrib.database.fields.models import Field from baserow.contrib.database.table.models import Table +from baserow.contrib.database.views.models import View from baserow.core.models import CreatedAndUpdatedOnMixin from .validators import header_name_validator, header_value_validator, url_validator @@ -58,6 +61,18 @@ class TableWebhook(CreatedAndUpdatedOnMixin, models.Model): def header_dict(self): return {header.name: header.value for header in self.headers.all()} + @property + def batch_limit(self) -> int: + """ + This value will be used to limit the amount batches a single webhook can make to + paginate the payload. If the payload is too large to be sent in one go, the + event_type can split it into multiple batches. If the number of batches exceeds + this limit, a notification will be sent to workspace admins informing them that + the webhook couldn't send all the data. + """ + + return settings.BASEROW_WEBHOOKS_BATCH_LIMIT + class Meta: ordering = ("id",) @@ -68,6 +83,17 @@ class TableWebhookEvent(CreatedAndUpdatedOnMixin, models.Model): ) event_type = models.CharField(max_length=50) fields = models.ManyToManyField(Field) + views = models.ManyToManyField(View) + view_subscriptions = GenericRelation( + "ViewSubscription", + content_type_field="subscriber_content_type", + object_id_field="subscriber_id", + ) + + def get_type(self): + from .registries import webhook_event_type_registry + + return webhook_event_type_registry.get(self.event_type) class Meta: ordering = ("id",) @@ -90,6 +116,13 @@ class TableWebhookCall(models.Model): editable=False, help_text="Event ID where the call originated from.", ) + batch_id = models.PositiveIntegerField( + null=True, + help_text=( + "The batch ID for this call. Null if not part of a batch. " + "Used for batching multiple calls of the same event_id due to large data." + ), + ) webhook = models.ForeignKey( TableWebhook, related_name="calls", on_delete=models.CASCADE ) @@ -111,3 +144,4 @@ class TableWebhookCall(models.Model): class Meta: ordering = ("-called_time",) + unique_together = ("event_id", "batch_id", "webhook", "event_type") diff --git a/backend/src/baserow/contrib/database/webhooks/notification_types.py b/backend/src/baserow/contrib/database/webhooks/notification_types.py new file mode 100644 index 000000000..df0f5688b --- /dev/null +++ b/backend/src/baserow/contrib/database/webhooks/notification_types.py @@ -0,0 +1,169 @@ +from dataclasses import asdict, dataclass +from typing import List + +from django.conf import settings +from django.utils.translation import gettext as _ + +from baserow.core.models import ( + WORKSPACE_USER_PERMISSION_ADMIN, + Workspace, + WorkspaceUser, +) +from baserow.core.notifications.handler import NotificationHandler +from baserow.core.notifications.models import NotificationRecipient +from baserow.core.notifications.registries import ( + EmailNotificationTypeMixin, + NotificationType, +) + +from .models import TableWebhook + + +@dataclass +class DeactivatedWebhookData: + webhook_id: int + table_id: int + database_id: int + webhook_name: str + + @classmethod + def from_webhook(cls, webhook): + return cls( + webhook_id=webhook.id, + table_id=webhook.table_id, + database_id=webhook.table.database_id, + webhook_name=webhook.name, + ) + + +def notify_admins_in_workspace( + workspace: Workspace, notification_type: str, data: dict +) -> List[NotificationRecipient]: + """ + Notifies all admins in the workspace about an important event, such as a webhook + deactivation or a payload exceeding size limits. + + :param workspace: The workspace whose admins will be notified. + :param notification_type: The type of notification to send. + :param data: The data to include in the notification. + :return: A list of created notification recipients. + """ + + admins_workspace_users = WorkspaceUser.objects.filter( + workspace=workspace, + permissions=WORKSPACE_USER_PERMISSION_ADMIN, + user__profile__to_be_deleted=False, + user__is_active=True, + ).select_related("user") + admins_in_workspace = [admin.user for admin in admins_workspace_users] + + return NotificationHandler.create_direct_notification_for_users( + notification_type=notification_type, + recipients=admins_in_workspace, + data=data, + sender=None, + workspace=workspace, + ) + + +class WebhookDeactivatedNotificationType(EmailNotificationTypeMixin, NotificationType): + type = "webhook_deactivated" + has_web_frontend_route = True + + @classmethod + def notify_admins_in_workspace( + cls, webhook: TableWebhook + ) -> List[NotificationRecipient]: + """ + Creates a notification of this type for each admin in the workspace that the + webhook belongs to. + + :param webhook: The webhook that was deactivated. + :return: A list of notification recipients that have been created. + """ + + workspace = webhook.table.database.workspace + return notify_admins_in_workspace( + workspace, cls.type, asdict(DeactivatedWebhookData.from_webhook(webhook)) + ) + + @classmethod + def get_notification_title_for_email(cls, notification, context): + return _("%(name)s webhook has been deactivated.") % { + "name": notification.data["webhook_name"], + } + + @classmethod + def get_notification_description_for_email(cls, notification, context): + return _( + "The webhook failed more than %(max_failures)s consecutive times and " + "was therefore deactivated." + ) % { + "max_failures": settings.BASEROW_WEBHOOKS_MAX_CONSECUTIVE_TRIGGER_FAILURES, + } + + +@dataclass +class WebhookPayloadTooLargeData: + webhook_id: int + table_id: int + database_id: int + webhook_name: str + event_id: str + batch_limit: int + + @classmethod + def from_webhook(cls, webhook: TableWebhook, event_id: str): + return cls( + webhook_id=webhook.id, + table_id=webhook.table_id, + database_id=webhook.table.database_id, + webhook_name=webhook.name, + event_id=event_id, + batch_limit=webhook.batch_limit, + ) + + +class WebhookPayloadTooLargeNotificationType( + EmailNotificationTypeMixin, NotificationType +): + type = "webhook_payload_too_large" + has_web_frontend_route = True + + @classmethod + def notify_admins_in_workspace( + cls, webhook: TableWebhook, event_id: str + ) -> List[NotificationRecipient]: + """ + Creates a notification of this type for each admin in the workspace that the + webhook belongs to. + + :param webhook: The webhook trying to send a payload that is too large. + :param event_id: The event id that triggered the notification. + :return: A list of notification recipients that have been created. + """ + + workspace = webhook.table.database.workspace + return notify_admins_in_workspace( + workspace, + cls.type, + asdict(WebhookPayloadTooLargeData.from_webhook(webhook, event_id)), + ) + + @classmethod + def get_notification_title_for_email(cls, notification, context): + return _("%(name)s webhook payload too large.") % { + "name": notification.data["webhook_name"], + } + + @classmethod + def get_notification_description_for_email(cls, notification, context): + return _( + "The payload for the %(name)s webhook with event ID %(event_id)s " + "was too large. The content has been split into multiple batches, but " + "data above the batch limit of %(batch_limit)s was discarded." + ) % { + "name": notification.data["webhook_name"], + "event_id": notification.data["event_id"], + "batch_limit": notification.data["batch_limit"], + } diff --git a/backend/src/baserow/contrib/database/webhooks/registries.py b/backend/src/baserow/contrib/database/webhooks/registries.py index 7e8b88d9b..973278d5a 100644 --- a/backend/src/baserow/contrib/database/webhooks/registries.py +++ b/backend/src/baserow/contrib/database/webhooks/registries.py @@ -1,13 +1,16 @@ import uuid +from typing import Optional from django.core.exceptions import ImproperlyConfigured from django.db import transaction +from django.db.models import Q from django.dispatch.dispatcher import Signal from baserow.contrib.database.table.models import Table +from baserow.contrib.database.webhooks.models import TableWebhook, TableWebhookEvent from baserow.core.registry import Instance, ModelRegistryMixin, Registry -from .exceptions import SkipWebhookCall +from .exceptions import SkipWebhookCall, WebhookPayloadTooLarge from .tasks import call_webhook @@ -15,8 +18,8 @@ class WebhookEventType(Instance): """ This class represents a custom webhook event type that can be added to the webhook event type registry. Each registered event type needs to set a django signal on - which it will listen on. Upon initialization the webhook event type will connect - to the django signal. + which it will listen on. Upon initialization the webhook event type will connect to + the django signal. The 'listener' function will be called for every received signal. The listener will generate a unique ID for every received signal, find all webhooks that need to be @@ -97,6 +100,17 @@ class WebhookEventType(Instance): return table + def get_additional_filters_for_webhooks_to_call( + self, **kwargs: dict + ) -> Optional[Q]: + """ + Filters to pass to WebhookHandler.find_webhooks_to_call. By default, no + additional filters are applied. + + :param kwargs: The arguments of the signal. + :return: A dictionary of additional filters. + """ + def listener(self, **kwargs: dict): """ The method that is called when the signal is triggered. By default it will @@ -107,6 +121,55 @@ class WebhookEventType(Instance): transaction.on_commit(lambda: self.listener_after_commit(**kwargs)) + def _paginate_payload( + self, webhook: TableWebhook, event_id: str, payload: dict[str, any] + ) -> tuple[dict, dict | None]: + """ + This method is called in the celery task and can be overwritten to paginate the + payload, if it's too large to send all the data at once. The default + implementation returns the payload and None as the next cursor, but if the + payload is too large to be sent in one go, this method can be used to return a + part of the payload and the remaining part as the next cursor. Proper `batch_id` + values will be added to the payload by the caller to keep track of the current + batch. + + :param payload: The payload that must be paginated. + :return: A tuple containing the payload to be sent and the remaining payload for + the next batch if any or None. + """ + + return payload, None + + def paginate_payload(self, webhook, event_id, payload) -> tuple[dict, dict | None]: + """ + This method calls the `_paginate_payload` method and adds a `batch_id` to the + payload if the remaining payload is not None. The `batch_id` is used to keep + track of the current batch of the payload. + + :param webhook: The webhook object related to the call. + :param event_id: The unique uuid event id of the event that triggered the call. + :param payload: The payload that must be paginated. + :return: A tuple containing the payload to be sent and the remaining payload for + the next batch if any or None. + """ + + batch_id = int(payload.get("batch_id", None) or 1) + if webhook.batch_limit > 0 and batch_id > webhook.batch_limit: + raise WebhookPayloadTooLarge( + f"Payload for event '{self.type}' (event_id: '{event_id}') exceeds " + f"the batch limit of ({webhook.batch_limit} batches)." + ) + + prepared_payload, remaining_payload = self._paginate_payload( + webhook, event_id, payload + ) + + if remaining_payload is not None: + prepared_payload["batch_id"] = batch_id + remaining_payload["batch_id"] = batch_id + 1 + + return prepared_payload, remaining_payload + def listener_after_commit(self, **kwargs): """ Called after the signal is triggered and the transaction commits. By default it @@ -123,7 +186,8 @@ class WebhookEventType(Instance): table = self.get_table_object(**kwargs) webhook_handler = WebhookHandler() - webhooks = webhook_handler.find_webhooks_to_call(table.id, self.type) + filters = self.get_additional_filters_for_webhooks_to_call(**kwargs) + webhooks = webhook_handler.find_webhooks_to_call(table.id, self.type, filters) event_id = uuid.uuid4() for webhook in webhooks: try: @@ -144,8 +208,24 @@ class WebhookEventType(Instance): except SkipWebhookCall: pass + def after_create(self, webhook_event: TableWebhookEvent): + """ + This method is called after a webhook event has been created. By default it + does nothing, but can be overwritten to add additional functionality. -class WebhookEventTypeRegistry(ModelRegistryMixin, Registry): + :param webhook_event: The created webhook event. + """ + + def after_update(self, webhook_event: TableWebhookEvent): + """ + This method is called after a webhook event has been updated. By default it + does nothing, but can be overwritten to add additional functionality. + + :param webhook_event: The updated webhook event. + """ + + +class WebhookEventTypeRegistry(ModelRegistryMixin, Registry[WebhookEventType]): name = "webhook_event" diff --git a/backend/src/baserow/contrib/database/webhooks/tasks.py b/backend/src/baserow/contrib/database/webhooks/tasks.py index 223865416..007b8f835 100644 --- a/backend/src/baserow/contrib/database/webhooks/tasks.py +++ b/backend/src/baserow/contrib/database/webhooks/tasks.py @@ -1,3 +1,4 @@ +from copy import deepcopy from datetime import datetime, timezone from django.conf import settings @@ -8,6 +9,10 @@ from django.db.utils import OperationalError from loguru import logger from baserow.config.celery import app +from baserow.contrib.database.webhooks.exceptions import WebhookPayloadTooLarge +from baserow.contrib.database.webhooks.notification_types import ( + WebhookPayloadTooLargeNotificationType, +) from baserow.core.redis import RedisQueue @@ -83,29 +88,18 @@ def call_webhook( can still measure this. """ - from advocate import UnacceptableAddressException - from requests import RequestException - - from .handler import WebhookHandler - from .models import TableWebhook, TableWebhookCall + from .models import TableWebhook + from .registries import webhook_event_type_registry if self.request.retries > retries: retries = self.request.retries try: with transaction.atomic(): - handler = WebhookHandler() - try: webhook = TableWebhook.objects.select_for_update( - of=("self",), - nowait=True, - ).get( - id=webhook_id, - # If a webhook is not active anymore, then it should not be - # executed. - active=True, - ) + of=("self",), nowait=True + ).get(id=webhook_id, active=True) except TableWebhook.DoesNotExist: # If the webhook has been deleted or disabled while executing, we don't # want to continue making calls the URL because we can't update the @@ -127,65 +121,36 @@ def call_webhook( else: raise e - request = None - response = None - success = False - error = "" - + # Paginate the payload if necessary and enqueue the remaining data. + webhook_event_type = webhook_event_type_registry.get(event_type) try: - request, response = handler.make_request(method, url, headers, payload) - success = response.ok - except RequestException as exception: - request = exception.request - response = exception.response - error = str(exception) - except UnacceptableAddressException as exception: - error = f"UnacceptableAddressException: {exception}" - - TableWebhookCall.objects.update_or_create( - event_id=event_id, - event_type=event_type, - webhook=webhook, - defaults={ - "called_time": datetime.now(tz=timezone.utc), - "called_url": url, - "request": handler.format_request(request) - if request is not None - else None, - "response": handler.format_response(response) - if response is not None - else None, - "response_status": response.status_code - if response is not None - else None, - "error": error, - }, - ) - handler.clean_webhook_calls(webhook) - - if success and webhook.failed_triggers != 0: - # If the call was successful and failed triggers had been increased in - # the past, we can safely reset it to 0 again to prevent deactivation of - # the webhook. - webhook.failed_triggers = 0 - webhook.save() - elif not success and ( - webhook.failed_triggers - < settings.BASEROW_WEBHOOKS_MAX_CONSECUTIVE_TRIGGER_FAILURES - ): - # If the task has reached the maximum amount of failed calls, we're - # going to give up and increase the total failed triggers of the webhook - # if we're still operating within the limits of the max consecutive - # trigger failures. - webhook.failed_triggers += 1 - webhook.save() - elif not success: - # If webhook has reached the maximum amount of failed triggers, - # we're going to deactivate it because we can reasonably assume that the - # target doesn't listen anymore. At this point we've tried 8 * 10 times. - # The user can manually activate it again when it's fixed. - webhook.active = False - webhook.save() + payload, remaining = webhook_event_type.paginate_payload( + webhook, event_id, deepcopy(payload) + ) + except WebhookPayloadTooLarge: + success = True # We don't want to retry this call, because it will fail again. + transaction.on_commit( + lambda: WebhookPayloadTooLargeNotificationType.notify_admins_in_workspace( + webhook, event_id + ) + ) + else: + success = make_request_and_save_result( + webhook, event_id, event_type, method, url, headers, payload + ) + # enqueue the next call if there is still remaining payload + if success and remaining: + args = ( + webhook_id, + event_id, + event_type, + method, + url, + headers, + remaining, + ) + kwargs = {"retries": 0} + enqueue_webhook_task(webhook_id, event_id, args, kwargs) # After the transaction successfully commits we can delay the next call # in the queue, so that only one call is triggered concurrently. @@ -207,3 +172,84 @@ def call_webhook( kwargs = self.request.kwargs or {} kwargs["retries"] = retries + 1 self.retry(countdown=2**retries, kwargs=kwargs) + + +def make_request_and_save_result( + webhook, event_id, event_type, method, url, headers, payload +): + from advocate import UnacceptableAddressException + from requests import RequestException + + from .handler import WebhookHandler + from .models import TableWebhookCall + from .notification_types import WebhookDeactivatedNotificationType + + handler = WebhookHandler() + + request = None + response = None + success = False + error = "" + + try: + request, response = handler.make_request(method, url, headers, payload) + success = response.ok + except RequestException as exception: + request = exception.request + response = exception.response + error = str(exception) + except UnacceptableAddressException as exception: + error = f"UnacceptableAddressException: {exception}" + + TableWebhookCall.objects.update_or_create( + event_id=event_id, + batch_id=payload.get("batch_id", None), + event_type=event_type, + webhook=webhook, + defaults={ + "called_time": datetime.now(tz=timezone.utc), + "called_url": url, + "request": handler.format_request(request) if request is not None else None, + "response": handler.format_response(response) + if response is not None + else None, + "response_status": response.status_code if response is not None else None, + "error": error, + }, + ) + handler.clean_webhook_calls(webhook) + + if success: + if webhook.failed_triggers != 0: + # If the call was successful and failed triggers had been increased + # in the past, we can safely reset it to 0 again to prevent + # deactivation of the webhook. + webhook.failed_triggers = 0 + webhook.save() + elif ( + webhook.failed_triggers + < settings.BASEROW_WEBHOOKS_MAX_CONSECUTIVE_TRIGGER_FAILURES + ): + # If the task has reached the maximum amount of failed calls, we're + # going to give up and increase the total failed triggers of the webhook + # if we're still operating within the limits of the max consecutive + # trigger failures. + webhook.failed_triggers += 1 + webhook.save() + else: + # If webhook has reached the maximum amount of failed triggers, we're + # going to deactivate it because we can reasonably assume that the + # target doesn't listen anymore. At this point we've tried 8 * 10 times. + # The user can manually activate it again when it's fixed. + webhook.active = False + webhook.save() + + # Send a notification to the workspace admins that the webhook was + # deactivated. + transaction.on_commit( + lambda: WebhookDeactivatedNotificationType.notify_admins_in_workspace( + webhook + ) + ) + + return success diff --git a/backend/src/baserow/contrib/integrations/local_baserow/service_types.py b/backend/src/baserow/contrib/integrations/local_baserow/service_types.py index 5a758ab12..c223e3855 100644 --- a/backend/src/baserow/contrib/integrations/local_baserow/service_types.py +++ b/backend/src/baserow/contrib/integrations/local_baserow/service_types.py @@ -61,7 +61,11 @@ from baserow.contrib.database.views.exceptions import ( AggregationTypeDoesNotExist, ViewDoesNotExist, ) +from baserow.contrib.database.views.models import DEFAULT_SORT_TYPE_KEY from baserow.contrib.database.views.service import ViewService +from baserow.contrib.database.views.view_aggregations import ( + DistributionViewAggregationType, +) from baserow.contrib.integrations.local_baserow.api.serializers import ( LocalBaserowTableServiceFieldMappingSerializer, ) @@ -90,7 +94,7 @@ from baserow.contrib.integrations.local_baserow.utils import ( guess_cast_function_from_response_serializer_field, guess_json_type_from_response_serializer_field, ) -from baserow.core.cache import local_cache +from baserow.core.cache import global_cache, local_cache from baserow.core.formula import resolve_formula from baserow.core.formula.registries import formula_runtime_function_registry from baserow.core.handler import CoreHandler @@ -115,6 +119,9 @@ if TYPE_CHECKING: from baserow.contrib.database.table.models import GeneratedTableModel, Table +SCHEMA_CACHE_TTL = 60 * 60 # 1 hour + + class LocalBaserowServiceType(ServiceType): """ The `ServiceType` for all `LocalBaserow` integration services. @@ -220,6 +227,8 @@ class LocalBaserowTableServiceType(LocalBaserowServiceType): return model.objects.all().enhance_by_fields( only_field_ids=extract_field_ids_from_list(only_field_names) + if only_field_names is not None + else None ) def enhance_queryset(self, queryset): @@ -482,6 +491,29 @@ class LocalBaserowTableServiceType(LocalBaserowServiceType): :return: A schema dictionary, or None if no `Table` has been applied. """ + if service.table_id is None: + return None + + properties = global_cache.get( + f"table_{service.table_id}_{service.table.version}__service_schema", + default=lambda: self._get_table_properties(service, allowed_fields), + timeout=SCHEMA_CACHE_TTL, + ) + + return self.get_schema_for_return_type(service, properties) + + def _get_table_properties( + self, service: ServiceSubClass, allowed_fields: Optional[List[str]] = None + ) -> Optional[Dict[str, Any]]: + """ + Extracts the properties from the table model fields. + + :param service: A `LocalBaserowTableService` subclass. + :param allowed_fields: The properties which are allowed to be included in the + properties. + :return: A schema dictionary, or None if no `Table` has been applied. + """ + field_objects = self.get_table_field_objects(service) if field_objects is None: @@ -517,7 +549,7 @@ class LocalBaserowTableServiceType(LocalBaserowServiceType): "searchable": field_type.is_searchable(field) and field_type.type not in self.unsupported_adhoc_searchable_field_types, - "sortable": field_type.check_can_order_by(field) + "sortable": field_type.check_can_order_by(field, DEFAULT_SORT_TYPE_KEY) and field_type.type not in self.unsupported_adhoc_sortable_field_types, "filterable": field_type.check_can_filter_by(field) and field_type.type @@ -526,7 +558,7 @@ class LocalBaserowTableServiceType(LocalBaserowServiceType): "metadata": field_serializer.data, } | self.get_json_type_from_response_serializer_field(field, field_type) - return self.get_schema_for_return_type(service, properties) + return properties def get_schema_name(self, service: ServiceSubClass) -> str: """ @@ -570,7 +602,7 @@ class LocalBaserowTableServiceType(LocalBaserowServiceType): return local_cache.get( f"integration_service_{service.table_id}_table_model", - service.table.get_model, + lambda: service.table.get_model(), ) def get_table_field_objects( @@ -592,6 +624,18 @@ class LocalBaserowTableServiceType(LocalBaserowServiceType): def get_context_data( self, service: ServiceSubClass, allowed_fields: Optional[List[str]] = None + ) -> Dict[str, Any]: + if service.table_id is None: + return None + + return global_cache.get( + f"table_{service.table_id}_{service.table.version}__service_context_data", + default=lambda: self._get_context_data(service, allowed_fields), + timeout=SCHEMA_CACHE_TTL, + ) + + def _get_context_data( + self, service: ServiceSubClass, allowed_fields: Optional[List[str]] = None ) -> Dict[str, Any]: field_objects = self.get_table_field_objects(service) @@ -622,6 +666,22 @@ class LocalBaserowTableServiceType(LocalBaserowServiceType): def get_context_data_schema( self, service: ServiceSubClass, allowed_fields: Optional[List[str]] = None ) -> Optional[Dict[str, Any]]: + if service.table_id is None: + return None + + return global_cache.get( + f"table_{service.table_id}_{service.table.version}__service_context_data_schema", + default=lambda: self._get_context_data_schema(service, allowed_fields), + timeout=SCHEMA_CACHE_TTL, + ) + + def _get_context_data_schema( + self, service: ServiceSubClass, allowed_fields: Optional[List[str]] = None + ) -> Optional[Dict[str, Any]]: + """ + Returns the context data schema for the table associated with the service. + """ + field_objects = self.get_table_field_objects(service) if field_objects is None: @@ -1184,6 +1244,10 @@ class LocalBaserowAggregateRowsUserServiceType( dispatch_type = DispatchTypes.DISPATCH_DATA_SOURCE serializer_mixins = LocalBaserowTableServiceFilterableMixin.mixin_serializer_mixins + # Local Baserow aggregate rows does not currently support the distribution + # aggregation type, this will be resolved in a future release. + unsupported_aggregation_types = [DistributionViewAggregationType.type] + def get_schema_name(self, service: LocalBaserowAggregateRows) -> str: """ The Local Baserow aggregation schema name added to the `title` in @@ -1322,6 +1386,19 @@ class LocalBaserowAggregateRowsUserServiceType( # The table and view will be prepared in the parent values = super().prepare_values(values, user, instance) + # Aggregation types are always checked for compatibility + # no matter if they have been already set previously + aggregation_type = values.get( + "aggregation_type", getattr(instance, "aggregation_type", "") + ) + + if aggregation_type in self.unsupported_aggregation_types: + raise DRFValidationError( + detail=f"The {aggregation_type} aggregation type " + "is not currently supported.", + code="unsupported_aggregation_type", + ) + if "table" in values: # Reset the field if the table has changed if ( @@ -1351,12 +1428,6 @@ class LocalBaserowAggregateRowsUserServiceType( code="invalid_field", ) - # Aggregation types are always checked for compatibility - # no matter if they have been already set previously - aggregation_type = values.get( - "aggregation_type", getattr(instance, "aggregation_type", "") - ) - if aggregation_type and field: agg_type = field_aggregation_registry.get(aggregation_type) if not agg_type.field_is_compatible(field): diff --git a/backend/src/baserow/core/cache.py b/backend/src/baserow/core/cache.py index 0efc43f07..a679c4625 100644 --- a/backend/src/baserow/core/cache.py +++ b/backend/src/baserow/core/cache.py @@ -2,8 +2,12 @@ from contextlib import contextmanager from typing import Callable, TypeVar from django.conf import settings +from django.core.cache import cache from asgiref.local import Local +from redis.exceptions import LockNotOwnedError + +from baserow.version import VERSION as BASEROW_VERSION T = TypeVar("T") @@ -108,3 +112,147 @@ class LocalCacheMiddleware: def __call__(self, request): with local_cache.context(): return self.get_response(request) + + +SENTINEL = object() + + +class GlobalCache: + """ + A global cache wrapper around the Django cache system that provides + invalidation capabilities and a lock mechanism to prevent multiple + concurrent updates. It's also versioned with Baserow version. + + Example Usage: + + # Storing and retrieving a value + value = global_cache.get( + "user_123_data", + default=lambda: expensive_computation(), + timeout=300 + ) + + # Invalidating a cache key + global_cache.invalidate("user_123_data") + """ + + VERSION_KEY_TTL = 60 * 60 * 24 * 10 # 10 days + + def _get_version_cache_key( + self, key: str, invalidate_key: None | str = None + ) -> str: + """ + Generates a versioned cache key for tracking different versions of a cached + value. + + :param key: The base cache key. + :param invalidate_key: The key used when this cache is invalidated. + :return: A modified cache key used for version tracking. + """ + + key = key if invalidate_key is None else invalidate_key + + return f"{BASEROW_VERSION}_{key}__current_version" + + def _get_cache_key_with_version(self, key: str) -> str: + """ + Generates a cache key with included version. + + :param key: The base cache key. + :return: A modified cache key with version. + """ + + version = cache.get(self._get_version_cache_key(key), 0) + return f"{BASEROW_VERSION}_{key}__version_{version}" + + def get( + self, + key: str, + default: T | Callable[[], T] = None, + invalidate_key: None | str = None, + timeout: int = 60, + ) -> T: + """ + Retrieves a value from the cache if it exists; otherwise, sets it using the + provided default value. + + This function also uses a lock (if available on the cache backend) to ensure + multi call safety when setting a new value. + + :param key: The key of the cache value to get (or set). Make sure this key is + unique and not used elsewhere. + :param invalidate_key: The key used when this cache is invalidated. A default + one is used if none is provided and this value otherwise. Can be used to + invalidate multiple caches at the same time. When invalidating the cache you + must use the same key later. + :param default: The default value to store in the cache if the key is absent. + Can be either a literal value or a callable. If it's a callable, + the function is called to retrieve the default value. + :param timeout: The cache timeout in seconds for newly set values. + Defaults to 60. + :return: The cached value if it exists; otherwise, the newly set value. + """ + + version_key = self._get_version_cache_key(key, invalidate_key) + + version = cache.get(version_key, 0) + + cache_key_to_use = f"{BASEROW_VERSION}_{key}__version_{version}" + + cached = cache.get(cache_key_to_use, SENTINEL) + + if cached is SENTINEL: + use_lock = hasattr(cache, "lock") + if use_lock: + cache_lock = cache.lock(f"{cache_key_to_use}__lock", timeout=10) + cache_lock.acquire() + try: + cached = cache.get(cache_key_to_use, SENTINEL) + # We check again to make sure it hasn't been populated in the meantime + # while acquiring the lock + if cached is SENTINEL: + if callable(default): + cached = default() + else: + cached = default + + cache.set( + cache_key_to_use, + cached, + timeout=timeout, + ) + finally: + if use_lock: + try: + cache_lock.release() + except LockNotOwnedError: + # If the lock release fails, it might be because of the timeout + # and it's been stolen so we don't really care + pass + + return cached + + def invalidate(self, key: None | str = None, invalidate_key: None | str = None): + """ + Invalidates the cached value associated with the given key, ensuring that + subsequent cache reads will miss and require a new value to be set. + + :param key: The cache key to invalidate. + :param invalidate_key: The key to use for invalidation. If provided, this key + must match the one given at cache creation. + """ + + version_key = self._get_version_cache_key(key, invalidate_key) + + try: + cache.incr(version_key, 1) + except ValueError: + # If the cache key does not exist, initialize its versioning. + cache.set( + version_key, + 1, + timeout=self.VERSION_KEY_TTL, + ) + + +global_cache = GlobalCache() diff --git a/backend/src/baserow/core/db.py b/backend/src/baserow/core/db.py index be5d95a84..5b897d1c9 100644 --- a/backend/src/baserow/core/db.py +++ b/backend/src/baserow/core/db.py @@ -22,6 +22,7 @@ from django.contrib.contenttypes.models import ContentType from django.db import DEFAULT_DB_ALIAS, connection, transaction from django.db.models import ForeignKey, ManyToManyField, Max, Model, Prefetch, QuerySet from django.db.models.functions import Collate +from django.db.models.query import ModelIterable from django.db.models.sql.query import LOOKUP_SEP from django.db.transaction import Atomic, get_connection @@ -470,6 +471,7 @@ class MultiFieldPrefetchQuerysetMixin(Generic[ModelInstance]): if ( self._multi_field_prefetch_related_funcs and not self._multi_field_prefetch_done + and issubclass(self._iterable_class, ModelIterable) ): for f in self._multi_field_prefetch_related_funcs: f(self, self._result_cache) diff --git a/backend/src/baserow/core/emails_context_types.py b/backend/src/baserow/core/emails_context_types.py index 75e02e142..1b7e862df 100644 --- a/backend/src/baserow/core/emails_context_types.py +++ b/backend/src/baserow/core/emails_context_types.py @@ -20,4 +20,5 @@ class CoreEmailContextType(EmailContextType): "baserow_embedded_share_hostname": settings.BASEROW_EMBEDDED_SHARE_HOSTNAME, "logo_url": settings.PUBLIC_WEB_FRONTEND_URL + "/img/logo.svg", "logo_additional_text": "", + "show_baserow_description": True, } diff --git a/backend/src/baserow/core/feature_flags.py b/backend/src/baserow/core/feature_flags.py index 586097adb..365062721 100644 --- a/backend/src/baserow/core/feature_flags.py +++ b/backend/src/baserow/core/feature_flags.py @@ -2,7 +2,6 @@ from django.conf import settings from baserow.core.exceptions import FeatureDisabledException -FF_DASHBOARDS = "dashboards" FF_ENABLE_ALL = "*" diff --git a/backend/src/baserow/core/fields.py b/backend/src/baserow/core/fields.py index 231c24d80..f0870c90a 100644 --- a/backend/src/baserow/core/fields.py +++ b/backend/src/baserow/core/fields.py @@ -257,3 +257,84 @@ class LenientDecimalField(models.Field): **kwargs, } ) + + +def default_boolean_list(num_flags): + """Returns a default list of False values""" + + return [False] * num_flags + + +class MultipleFlagField(models.CharField): + """Stores a list of booleans as a binary string""" + + def __init__(self, num_flags=8, default=None, *args, **kwargs): + self.num_flags = num_flags + kwargs.setdefault("max_length", num_flags) # Ensures max length is set + + # Handle list-based default values properly + if default is None: + default = default_boolean_list(num_flags) + if isinstance(default, list): + if len(default) != num_flags: + raise ValueError(f"Default list must have exactly {num_flags} elements") + # Convert list to string representation + kwargs["default"] = "".join("1" if flag else "0" for flag in default) + elif isinstance(default, str): + if len(default) != num_flags or not set(default).issubset({"0", "1"}): + raise ValueError( + f"Default string must be exactly {num_flags} characters of " + "'0' or '1'" + ) + kwargs["default"] = default + else: + raise ValueError( + "Default must be a list of booleans, a binary string, or None" + ) + + super().__init__(*args, **kwargs) + + def from_db_value(self, value, expression, connection): + """ + Converts the stored binary string into a list of booleans when retrieving + from the database + """ + + if value is None: + return default_boolean_list(self.num_flags) + return [char == "1" for char in value] + + def to_python(self, value): + """Ensures the value is always returned as a list of booleans""" + + if isinstance(value, list): + return value + return [char == "1" for char in value] + + def get_prep_value(self, value): + """Converts the list of booleans into a binary string for database storage""" + + if isinstance(value, str): + # If Django passes the default value as a string, assume it's already in + # correct format + if len(value) != self.num_flags or not set(value).issubset({"0", "1"}): + raise ValueError( + f"Stored string must have exactly {self.num_flags} characters of " + "'0' or '1'" + ) + return value + elif isinstance(value, list): + if len(value) != self.num_flags: + raise ValueError(f"List must have exactly {self.num_flags} elements") + return "".join("1" if flag else "0" for flag in value) + else: + raise ValueError( + "Value must be a list of booleans or a valid binary string" + ) + + def deconstruct(self): + """Ensures Django migrations correctly store and restore num_flags""" + + name, path, args, kwargs = super().deconstruct() + kwargs["num_flags"] = self.num_flags # Add num_flags explicitly + return name, path, args, kwargs diff --git a/backend/src/baserow/core/generative_ai/generative_ai_model_types.py b/backend/src/baserow/core/generative_ai/generative_ai_model_types.py index 44bf5dd47..a02b91efa 100644 --- a/backend/src/baserow/core/generative_ai/generative_ai_model_types.py +++ b/backend/src/baserow/core/generative_ai/generative_ai_model_types.py @@ -118,26 +118,27 @@ class OpenAIGenerativeAIModelType( run, thread, assistant = None, None, None try: client = self.get_client(workspace) + kwargs = {} + if temperature: + kwargs["temperature"] = temperature + assistant = client.beta.assistants.create( name="Assistant that have access to user files", instructions="", model=model, tools=[{"type": "file_search"}], + **kwargs, ) thread = client.beta.threads.create() attachments = [ {"file_id": file_id, "tools": [{"type": "file_search"}]} for file_id in file_ids ] - kwargs = {} - if temperature: - kwargs["temperature"] = temperature message = client.beta.threads.messages.create( thread_id=thread.id, role="user", content=prompt, attachments=attachments, - **kwargs, ) run = client.beta.threads.runs.create_and_poll( thread_id=thread.id, diff --git a/backend/src/baserow/core/handler.py b/backend/src/baserow/core/handler.py index 10093e150..d2bce7467 100755 --- a/backend/src/baserow/core/handler.py +++ b/backend/src/baserow/core/handler.py @@ -1946,6 +1946,7 @@ class CoreHandler(metaclass=baserow_trace_methods(tracer)): # hash mismatch, which means the workspace has already been deleted, we can # create a new workspace and import the exported applications into that # workspace. + imported_id_mapping = None if not installed_template or installed_template.export_hash != export_hash: # It is optionally possible for a template to have additional files. # They are stored in a ZIP file and are generated when the template @@ -1959,13 +1960,14 @@ class CoreHandler(metaclass=baserow_trace_methods(tracer)): files_buffer = BytesIO() workspace = Workspace.objects.create(name=parsed_json["name"]) - self.import_applications_to_workspace( + _, id_mapping = self.import_applications_to_workspace( workspace, parsed_json["export"], files_buffer=files_buffer, import_export_config=config, storage=storage, ) + imported_id_mapping = id_mapping if files_buffer: files_buffer.close() @@ -1982,6 +1984,13 @@ class CoreHandler(metaclass=baserow_trace_methods(tracer)): "workspace": workspace, } + # If the template was imported, then we'll map the desired open_application + # id to the actually imported application id. + if "open_application" in parsed_json and imported_id_mapping is not None: + kwargs["open_application"] = imported_id_mapping["applications"].get( + parsed_json["open_application"], None + ) + if not installed_template: installed_template = Template.objects.create(slug=slug, **kwargs) else: diff --git a/backend/src/baserow/core/import_export/handler.py b/backend/src/baserow/core/import_export/handler.py index aaf7fe4a0..2ae39ea18 100644 --- a/backend/src/baserow/core/import_export/handler.py +++ b/backend/src/baserow/core/import_export/handler.py @@ -63,7 +63,7 @@ from baserow.core.user_files.exceptions import ( InvalidFileStreamError, ) from baserow.core.user_files.handler import UserFileHandler -from baserow.core.utils import ChildProgressBuilder, Progress, grouper, stream_size +from baserow.core.utils import ChildProgressBuilder, grouper, stream_size from baserow.version import VERSION tracer = trace.get_tracer(__name__) @@ -780,7 +780,7 @@ class ImportExportHandler(metaclass=baserow_trace_methods(tracer)): import_export_config: ImportExportConfig, zip_file: ZipFile, storage: Storage, - progress: Progress, + progress_builder: Optional[ChildProgressBuilder] = None, ) -> Application: """ Imports a single application into a workspace from the provided data. @@ -815,7 +815,7 @@ class ImportExportHandler(metaclass=baserow_trace_methods(tracer)): id_mapping, zip_file, storage, - progress_builder=progress.create_child_builder(represents_progress=1), + progress_builder=progress_builder, ) return imported_application @@ -828,7 +828,7 @@ class ImportExportHandler(metaclass=baserow_trace_methods(tracer)): import_export_config: ImportExportConfig, zip_file: ZipFile, storage: Storage, - progress: Progress, + progress_builder: Optional[ChildProgressBuilder] = None, ) -> List[Application]: """ Imports multiple applications into a workspace from the provided application @@ -866,6 +866,14 @@ class ImportExportHandler(metaclass=baserow_trace_methods(tracer)): manifest["applications"].keys(), key=application_priority_sort, reverse=True ) + application_count = sum( + len(manifest["applications"][application_type]["items"]) + for application_type in prioritized_applications + ) + progress = ChildProgressBuilder.build( + progress_builder, child_total=application_count + ) + for application_type in prioritized_applications: for application_manifest in manifest["applications"][application_type][ "items" @@ -880,7 +888,7 @@ class ImportExportHandler(metaclass=baserow_trace_methods(tracer)): import_export_config, zip_file, storage, - progress, + progress.create_child_builder(represents_progress=1), ) except Exception as exc: # noqa # Trash the already imported applications so the user won't see @@ -898,7 +906,11 @@ class ImportExportHandler(metaclass=baserow_trace_methods(tracer)): return imported_applications def extract_files_from_zip( - self, tmp_import_path: str, zip_file: ZipFile, storage: Storage + self, + tmp_import_path: str, + zip_file: ZipFile, + storage: Storage, + progress_builder: Optional[ChildProgressBuilder] = None, ): """ Extracts files from a zip archive to a specified temporary import path. @@ -910,13 +922,20 @@ class ImportExportHandler(metaclass=baserow_trace_methods(tracer)): extracted. :param zip_file: The ZipFile instance containing the files to be extracted. :param storage: The storage instance used to save the extracted files. + :param progress_builder: A progress builder that allows for publishing progress. """ - for file_info in zip_file.infolist(): + file_list = zip_file.infolist() + progress = ChildProgressBuilder.build( + progress_builder, child_total=len(file_list) + ) + + for file_info in file_list: extracted_file_path = join(tmp_import_path, file_info.filename) with zip_file.open(file_info) as extracted_file: file_content = extracted_file.read() storage.save(extracted_file_path, ContentFile(file_content)) + progress.increment() def import_workspace_applications( self, @@ -983,9 +1002,12 @@ class ImportExportHandler(metaclass=baserow_trace_methods(tracer)): self.mark_resource_invalid(resource) raise - self.extract_files_from_zip(import_tmp_path, zip_file, storage) - - progress.set_progress(15) + self.extract_files_from_zip( + import_tmp_path, + zip_file, + storage, + progress.create_child_builder(represents_progress=10), + ) try: self.validate_checksums(manifest_data, import_tmp_path, storage) @@ -1011,7 +1033,7 @@ class ImportExportHandler(metaclass=baserow_trace_methods(tracer)): import_export_config, zip_file, storage, - progress, + progress.create_child_builder(represents_progress=80), ) for application in imported_applications: diff --git a/backend/src/baserow/core/jobs/models.py b/backend/src/baserow/core/jobs/models.py index 4014de02d..5db964766 100644 --- a/backend/src/baserow/core/jobs/models.py +++ b/backend/src/baserow/core/jobs/models.py @@ -1,4 +1,4 @@ -from datetime import datetime +from datetime import datetime, timezone from typing import Any from django.contrib.auth import get_user_model @@ -113,7 +113,7 @@ class Job(CreatedAndUpdatedOnMixin, PolymorphicContentTypeMixin, models.Model): progress = { "progress_percentage": self.progress_percentage, "state": self.state, - "updated_on": datetime.now(), + "updated_on": datetime.now(tz=timezone.utc), } cache.set(job_progress_key(self.id), progress, timeout=None) diff --git a/backend/src/baserow/core/jobs/tasks.py b/backend/src/baserow/core/jobs/tasks.py index b8ce994db..d4024a94c 100644 --- a/backend/src/baserow/core/jobs/tasks.py +++ b/backend/src/baserow/core/jobs/tasks.py @@ -64,7 +64,6 @@ def run_async_job(self, job_id: int): job.set_state_failed(str(e), error) job.save() - raise finally: # Delete the import job cached entry because the transaction has been committed diff --git a/backend/src/baserow/core/locale/en/LC_MESSAGES/django.po b/backend/src/baserow/core/locale/en/LC_MESSAGES/django.po index 5c3844515..20ac26ab0 100644 --- a/backend/src/baserow/core/locale/en/LC_MESSAGES/django.po +++ b/backend/src/baserow/core/locale/en/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2025-01-15 11:59+0000\n" +"POT-Creation-Date: 2025-03-18 19:55+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Language-Team: LANGUAGE <LL@li.org>\n" @@ -242,7 +242,7 @@ msgstr "" msgid "Decimal number" msgstr "" -#: src/baserow/core/handler.py:2109 src/baserow/core/user/handler.py:267 +#: src/baserow/core/handler.py:2130 src/baserow/core/user/handler.py:267 #, python-format msgid "%(name)s's workspace" msgstr "" @@ -305,16 +305,12 @@ msgid_plural "Plus %(counter)s more notifications." msgstr[0] "" msgstr[1] "" -#: src/baserow/core/templates/baserow/core/notifications_summary.html:239 -msgid "View in Baserow" -msgstr "" - -#: src/baserow/core/templates/baserow/core/notifications_summary.html:253 -#: src/baserow/core/templates/baserow/core/user/account_deleted.html:186 -#: src/baserow/core/templates/baserow/core/user/account_deletion_cancelled.html:186 -#: src/baserow/core/templates/baserow/core/user/account_deletion_scheduled.html:191 -#: src/baserow/core/templates/baserow/core/user/reset_password.html:209 -#: src/baserow/core/templates/baserow/core/workspace_invitation.html:213 +#: src/baserow/core/templates/baserow/core/notifications_summary.html:237 +#: src/baserow/core/templates/baserow/core/user/account_deleted.html:188 +#: src/baserow/core/templates/baserow/core/user/account_deletion_cancelled.html:188 +#: src/baserow/core/templates/baserow/core/user/account_deletion_scheduled.html:193 +#: src/baserow/core/templates/baserow/core/user/reset_password.html:211 +#: src/baserow/core/templates/baserow/core/workspace_invitation.html:215 msgid "" "Baserow is an open source no-code database tool which allows you to " "collaborate on projects, customers and more. It gives you the powers of a " @@ -494,47 +490,47 @@ msgid "" "\"%(auth_provider_type)s\" (%(auth_provider_id)s) auth provider" msgstr "" -#: src/baserow/core/user/actions.py:318 +#: src/baserow/core/user/actions.py:323 msgid "Send reset user password" msgstr "" -#: src/baserow/core/user/actions.py:319 +#: src/baserow/core/user/actions.py:324 #, python-format msgid "User \"%(user_email)s\" (%(user_id)s) requested to reset password" msgstr "" -#: src/baserow/core/user/actions.py:352 +#: src/baserow/core/user/actions.py:357 msgid "Change user password" msgstr "" -#: src/baserow/core/user/actions.py:353 +#: src/baserow/core/user/actions.py:358 #, python-format msgid "User \"%(user_email)s\" (%(user_id)s) changed password" msgstr "" -#: src/baserow/core/user/actions.py:392 +#: src/baserow/core/user/actions.py:397 msgid "Reset user password" msgstr "" -#: src/baserow/core/user/actions.py:393 +#: src/baserow/core/user/actions.py:398 #, python-format msgid "User \"%(user_email)s\" (%(user_id)s) reset password" msgstr "" -#: src/baserow/core/user/actions.py:429 +#: src/baserow/core/user/actions.py:434 msgid "Send verify email" msgstr "" -#: src/baserow/core/user/actions.py:430 +#: src/baserow/core/user/actions.py:435 #, python-format msgid "User \"%(user_email)s\" (%(user_id)s) requested to verify email" msgstr "" -#: src/baserow/core/user/actions.py:463 +#: src/baserow/core/user/actions.py:468 msgid "Verify email" msgstr "" -#: src/baserow/core/user/actions.py:464 +#: src/baserow/core/user/actions.py:469 #, python-format msgid "User \"%(user_email)s\" (%(user_id)s) verify email" msgstr "" diff --git a/backend/src/baserow/core/locale/fr/LC_MESSAGES/django.po b/backend/src/baserow/core/locale/fr/LC_MESSAGES/django.po index b11da6f64..e0c465be3 100644 --- a/backend/src/baserow/core/locale/fr/LC_MESSAGES/django.po +++ b/backend/src/baserow/core/locale/fr/LC_MESSAGES/django.po @@ -3,8 +3,8 @@ msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2024-01-18 13:32+0000\n" -"PO-Revision-Date: 2024-12-16 15:08+0000\n" -"Last-Translator: Anonymous <noreply@weblate.org>\n" +"PO-Revision-Date: 2025-03-18 19:52+0000\n" +"Last-Translator: Jérémie Pardou-Piquemal <jrmi@jeremiez.net>\n" "Language-Team: French <https://hosted.weblate.org/projects/baserow/" "backend-core/fr/>\n" "Language: fr\n" @@ -12,7 +12,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n > 1;\n" -"X-Generator: Weblate 5.9\n" +"X-Generator: Weblate 5.11-dev\n" #: src/baserow/core/action/scopes.py:9 #, python-format @@ -404,7 +404,7 @@ msgid "" "hours." msgstr "" "Pour poursuivre la réinitialisation de votre mot de passe, il suffit de " -"cliquer sur le bouton ci-dessous, et vous vous pourrez modifier votre mot de " +"cliquer sur le bouton ci-dessous, et vous pourrez modifier votre mot de " "passe. Ce lien expirera dans %(hours)s heures." #: src/baserow/core/templates/baserow/core/workspace_invitation.html:149 @@ -484,11 +484,11 @@ msgid "" "time" msgstr "" "Utilisateur \"%(user_email)s\" (%(user_id)s) programmé pour être supprimé " -"après le délais de grâce" +"après le délai de grâce" #: src/baserow/core/user/actions.py:196 msgid "Cancel user deletion" -msgstr "Annulation la suppression d'un utilisateur" +msgstr "Annulation de la suppression d'un utilisateur" #: src/baserow/core/user/actions.py:198 #, python-format diff --git a/backend/src/baserow/core/migrations/0095_alter_userfile_image_height_and_more.py b/backend/src/baserow/core/migrations/0095_alter_userfile_image_height_and_more.py new file mode 100644 index 000000000..409c19ce6 --- /dev/null +++ b/backend/src/baserow/core/migrations/0095_alter_userfile_image_height_and_more.py @@ -0,0 +1,22 @@ +# Generated by Django 5.0.9 on 2025-03-17 20:01 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + dependencies = [ + ("core", "0094_alter_importexportresource_size"), + ] + + operations = [ + migrations.AlterField( + model_name="userfile", + name="image_height", + field=models.PositiveIntegerField(null=True), + ), + migrations.AlterField( + model_name="userfile", + name="image_width", + field=models.PositiveIntegerField(null=True), + ), + ] diff --git a/backend/src/baserow/core/migrations/0096_template_open_application.py b/backend/src/baserow/core/migrations/0096_template_open_application.py new file mode 100644 index 000000000..1b6e20984 --- /dev/null +++ b/backend/src/baserow/core/migrations/0096_template_open_application.py @@ -0,0 +1,20 @@ +# Generated by Django 5.0.9 on 2025-03-18 16:34 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + dependencies = [ + ("core", "0095_alter_userfile_image_height_and_more"), + ] + + operations = [ + migrations.AddField( + model_name="template", + name="open_application", + field=models.IntegerField( + help_text="The application ID that must be opened when the template is previewed. If null, then the first will automatically be chosen.", + null=True, + ), + ), + ] diff --git a/backend/src/baserow/core/models.py b/backend/src/baserow/core/models.py index 34919c8ed..f43c4eabf 100755 --- a/backend/src/baserow/core/models.py +++ b/backend/src/baserow/core/models.py @@ -472,6 +472,11 @@ class Template(models.Model): blank=True, help_text="Keywords related to the template that can be used for search.", ) + open_application = models.IntegerField( + null=True, + help_text="The application ID that must be opened when the template is " + "previewed. If null, then the first will automatically be chosen.", + ) class Meta: ordering = ("name",) diff --git a/backend/src/baserow/core/redis.py b/backend/src/baserow/core/redis.py index 617d29329..402821b1f 100644 --- a/backend/src/baserow/core/redis.py +++ b/backend/src/baserow/core/redis.py @@ -1,4 +1,5 @@ import json +from collections import defaultdict from typing import Any, Optional from redis.client import Redis @@ -99,3 +100,20 @@ class RedisQueue: """ self.redis_connection.delete(self.queue_key) + + +class WebhookRedisQueue(RedisQueue): + queues = defaultdict(list) + + def enqueue_task(self, task_object): + self.queues[self.queue_key].append(task_object) + return True + + def get_and_pop_next(self): + try: + return self.queues[self.queue_key].pop(0) + except IndexError: + return None + + def clear(self): + self.queues[self.queue_key] = [] diff --git a/backend/src/baserow/core/registry.py b/backend/src/baserow/core/registry.py index 1d271d525..8653ba89e 100644 --- a/backend/src/baserow/core/registry.py +++ b/backend/src/baserow/core/registry.py @@ -137,6 +137,12 @@ class CustomFieldsInstanceMixin: useful if you want to add some custom SerializerMethodField for example. """ + request_serializer_mixins = None + """ + The serializer mixins that must be added to the serializer for requests. + This property is useful if you want to add some custom behaviour for example. + """ + serializer_extra_kwargs = None """ The extra kwargs that must be added to the serializer fields. This property is @@ -189,7 +195,7 @@ class CustomFieldsInstanceMixin: # as serializers are callable) which lazy loads a serializer mixin, or # 2) Serializers can provide a serializer mixin directly. dynamic_serializer_mixins = [] - for serializer_mixin in self.serializer_mixins: + for serializer_mixin in self.get_serializer_mixins(request_serializer): if isinstance(serializer_mixin, FunctionType): dynamic_serializer_mixins.append(serializer_mixin()) else: @@ -249,6 +255,12 @@ class CustomFieldsInstanceMixin: return serializer_class(model_instance_or_instances, context=context, **kwargs) + def get_serializer_mixins(self, request_serializer: bool) -> List: + if request_serializer and self.request_serializer_mixins is not None: + return self.request_serializer_mixins + else: + return self.serializer_mixins + def get_field_overrides( self, request_serializer: bool, extra_params: Dict, **kwargs ) -> Dict: diff --git a/backend/src/baserow/core/services/dispatch_context.py b/backend/src/baserow/core/services/dispatch_context.py index 99181cbc8..38c87cd79 100644 --- a/backend/src/baserow/core/services/dispatch_context.py +++ b/backend/src/baserow/core/services/dispatch_context.py @@ -54,7 +54,8 @@ class DispatchContext(RuntimeFormulaContext, ABC): @abstractmethod def is_publicly_searchable(self) -> bool: """ - Responsible for returning whether external users can apply search or not. + Responsible for returning whether external service visitors + can apply search or not. """ @abstractmethod @@ -77,7 +78,8 @@ class DispatchContext(RuntimeFormulaContext, ABC): @abstractmethod def is_publicly_filterable(self) -> bool: """ - Responsible for returning whether external users can apply filters or not. + Responsible for returning whether external service visitors + can apply filters or not. """ @abstractmethod @@ -91,7 +93,8 @@ class DispatchContext(RuntimeFormulaContext, ABC): @abstractmethod def is_publicly_sortable(self) -> bool: """ - Responsible for returning whether external users can apply sortings or not. + Responsible for returning whether external service visitors + can apply sortings or not. """ @abstractmethod diff --git a/backend/src/baserow/core/templates/baserow/core/notifications_summary.html b/backend/src/baserow/core/templates/baserow/core/notifications_summary.html index e26965f31..8b933197a 100644 --- a/backend/src/baserow/core/templates/baserow/core/notifications_summary.html +++ b/backend/src/baserow/core/templates/baserow/core/notifications_summary.html @@ -230,29 +230,15 @@ </tr> <!-- htmlmin:ignore -->{% endif %} <!-- htmlmin:ignore --> - <tr> - <td align="left" vertical-align="middle" style="font-size:0px;padding:10px 25px;word-break:break-word;"> - <table border="0" cellpadding="0" cellspacing="0" role="presentation" style="border-collapse:separate;line-height:100%;"> - <tbody> - <tr> - <td align="center" bgcolor="#5190ef" role="presentation" style="border:none;border-radius:4px;cursor:auto;mso-padding-alt:12px 30px;background:#5190ef;" valign="middle"> - <a href="{{ baserow_embedded_share_url }}" style="display:inline-block;background:#5190ef;color:#ffffff;font-family:Inter,sans-serif;font-size:15px;font-weight:600;line-height:120%;margin:0;text-decoration:none;text-transform:none;padding:12px 30px;mso-padding-alt:0px;border-radius:4px;" target="_blank"> {% trans "View in Baserow" %} </a> - </td> - </tr> - </tbody> - </table> - </td> - </tr> - <tr> - <td align="left" style="font-size:0px;padding:10px 25px;word-break:break-word;"> - <div style="font-family:Inter,sans-serif;font-size:12px;line-height:1;text-align:left;color:#9c9c9f;">{{ baserow_embedded_share_url }}</div> - </td> - </tr> + <!-- htmlmin:ignore -->{% if show_baserow_description %} + <!-- htmlmin:ignore --> <tr> <td align="left" style="font-size:0px;padding:10px 25px;word-break:break-word;"> <div style="font-family:Inter,sans-serif;font-size:13px;line-height:170%;text-align:left;color:#070810;">{% blocktrans trimmed %} Baserow is an open source no-code database tool which allows you to collaborate on projects, customers and more. It gives you the powers of a developer without leaving your browser. {% endblocktrans %}</div> </td> </tr> + <!-- htmlmin:ignore -->{% endif %} + <!-- htmlmin:ignore --> </tbody> </table> </div> diff --git a/backend/src/baserow/core/templates/baserow/core/notifications_summary.mjml.eta b/backend/src/baserow/core/templates/baserow/core/notifications_summary.mjml.eta index 30d79e603..3e12064f7 100644 --- a/backend/src/baserow/core/templates/baserow/core/notifications_summary.mjml.eta +++ b/backend/src/baserow/core/templates/baserow/core/notifications_summary.mjml.eta @@ -31,18 +31,14 @@ {% endblocktrans %} </mj-text> <mj-raw><!-- htmlmin:ignore -->{% endif %}<!-- htmlmin:ignore --></mj-raw> - <mj-button mj-class="button mt-20" href="{{ baserow_embedded_share_url }}"> - {% trans "View in Baserow" %} - </mj-button> - <mj-text mj-class="button-url"> - {{ baserow_embedded_share_url }} - </mj-text> - <mj-text mj-class="text"> - {% blocktrans trimmed %} - Baserow is an open source no-code database tool which allows you to collaborate - on projects, customers and more. It gives you the powers of a developer without - leaving your browser. - {% endblocktrans %} - </mj-text> + <mj-raw><!-- htmlmin:ignore -->{% if show_baserow_description %}<!-- htmlmin:ignore --></mj-raw> + <mj-text mj-class="text"> + {% blocktrans trimmed %} + Baserow is an open source no-code database tool which allows you to collaborate + on projects, customers and more. It gives you the powers of a developer without + leaving your browser. + {% endblocktrans %} + </mj-text> + <mj-raw><!-- htmlmin:ignore -->{% endif %}<!-- htmlmin:ignore --></mj-raw> </mj-column> </mj-section> diff --git a/backend/src/baserow/core/templates/baserow/core/user/account_deleted.html b/backend/src/baserow/core/templates/baserow/core/user/account_deleted.html index d6d13a41c..2bd8557c8 100644 --- a/backend/src/baserow/core/templates/baserow/core/user/account_deleted.html +++ b/backend/src/baserow/core/templates/baserow/core/user/account_deleted.html @@ -181,11 +181,15 @@ <div style="font-family:Inter,sans-serif;font-size:13px;line-height:170%;text-align:left;color:#070810;">{% blocktrans trimmed with baserow_embedded_share_hostname as baserow_embedded_share_hostname %} Your account ({{ username }}) on Baserow ({{ baserow_embedded_share_hostname }}) has been permanently deleted. {% endblocktrans %}</div> </td> </tr> + <!-- htmlmin:ignore -->{% if show_baserow_description %} + <!-- htmlmin:ignore --> <tr> <td align="left" style="font-size:0px;padding:10px 25px;word-break:break-word;"> <div style="font-family:Inter,sans-serif;font-size:13px;line-height:170%;text-align:left;color:#070810;">{% blocktrans trimmed %} Baserow is an open source no-code database tool which allows you to collaborate on projects, customers and more. It gives you the powers of a developer without leaving your browser. {% endblocktrans %}</div> </td> </tr> + <!-- htmlmin:ignore -->{% endif %} + <!-- htmlmin:ignore --> </tbody> </table> </div> diff --git a/backend/src/baserow/core/templates/baserow/core/user/account_deleted.mjml.eta b/backend/src/baserow/core/templates/baserow/core/user/account_deleted.mjml.eta index 880dbe0d4..1a3ce57f2 100644 --- a/backend/src/baserow/core/templates/baserow/core/user/account_deleted.mjml.eta +++ b/backend/src/baserow/core/templates/baserow/core/user/account_deleted.mjml.eta @@ -10,12 +10,14 @@ deleted. {% endblocktrans %} </mj-text> - <mj-text mj-class="text"> - {% blocktrans trimmed %} - Baserow is an open source no-code database tool which allows you to collaborate - on projects, customers and more. It gives you the powers of a developer without - leaving your browser. - {% endblocktrans %} - </mj-text> + <mj-raw><!-- htmlmin:ignore -->{% if show_baserow_description %}<!-- htmlmin:ignore --></mj-raw> + <mj-text mj-class="text"> + {% blocktrans trimmed %} + Baserow is an open source no-code database tool which allows you to collaborate + on projects, customers and more. It gives you the powers of a developer without + leaving your browser. + {% endblocktrans %} + </mj-text> + <mj-raw><!-- htmlmin:ignore -->{% endif %}<!-- htmlmin:ignore --></mj-raw> </mj-column> </mj-section> diff --git a/backend/src/baserow/core/templates/baserow/core/user/account_deletion_cancelled.html b/backend/src/baserow/core/templates/baserow/core/user/account_deletion_cancelled.html index c3cf014af..dfdcebe01 100644 --- a/backend/src/baserow/core/templates/baserow/core/user/account_deletion_cancelled.html +++ b/backend/src/baserow/core/templates/baserow/core/user/account_deletion_cancelled.html @@ -181,11 +181,15 @@ <div style="font-family:Inter,sans-serif;font-size:13px;line-height:170%;text-align:left;color:#070810;">{% blocktrans trimmed with user.username as username and baserow_embedded_share_hostname as baserow_embedded_share_hostname %} Your account ({{ username }}) on Baserow ({{ baserow_embedded_share_hostname }}) was pending deletion, but you've logged in so this operation has been cancelled. {% endblocktrans %}</div> </td> </tr> + <!-- htmlmin:ignore -->{% if show_baserow_description %} + <!-- htmlmin:ignore --> <tr> <td align="left" style="font-size:0px;padding:10px 25px;word-break:break-word;"> <div style="font-family:Inter,sans-serif;font-size:13px;line-height:170%;text-align:left;color:#070810;">{% blocktrans trimmed %} Baserow is an open source no-code database tool which allows you to collaborate on projects, customers and more. It gives you the powers of a developer without leaving your browser. {% endblocktrans %}</div> </td> </tr> + <!-- htmlmin:ignore -->{% endif %} + <!-- htmlmin:ignore --> </tbody> </table> </div> diff --git a/backend/src/baserow/core/templates/baserow/core/user/account_deletion_cancelled.mjml.eta b/backend/src/baserow/core/templates/baserow/core/user/account_deletion_cancelled.mjml.eta index 5778d7929..fedefc2f0 100644 --- a/backend/src/baserow/core/templates/baserow/core/user/account_deletion_cancelled.mjml.eta +++ b/backend/src/baserow/core/templates/baserow/core/user/account_deletion_cancelled.mjml.eta @@ -10,12 +10,14 @@ logged in so this operation has been cancelled. {% endblocktrans %} </mj-text> - <mj-text mj-class="text"> - {% blocktrans trimmed %} - Baserow is an open source no-code database tool which allows you to collaborate - on projects, customers and more. It gives you the powers of a developer without - leaving your browser. - {% endblocktrans %} - </mj-text> + <mj-raw><!-- htmlmin:ignore -->{% if show_baserow_description %}<!-- htmlmin:ignore --></mj-raw> + <mj-text mj-class="text"> + {% blocktrans trimmed %} + Baserow is an open source no-code database tool which allows you to collaborate + on projects, customers and more. It gives you the powers of a developer without + leaving your browser. + {% endblocktrans %} + </mj-text> + <mj-raw><!-- htmlmin:ignore -->{% endif %}<!-- htmlmin:ignore --></mj-raw> </mj-column> </mj-section> diff --git a/backend/src/baserow/core/templates/baserow/core/user/account_deletion_scheduled.html b/backend/src/baserow/core/templates/baserow/core/user/account_deletion_scheduled.html index 1560ce300..bf792010e 100644 --- a/backend/src/baserow/core/templates/baserow/core/user/account_deletion_scheduled.html +++ b/backend/src/baserow/core/templates/baserow/core/user/account_deletion_scheduled.html @@ -186,11 +186,15 @@ <div style="font-family:Inter,sans-serif;font-size:13px;line-height:170%;text-align:left;color:#070810;">{% blocktrans trimmed %} If you've changed your mind and want to cancel your account deletion, you just have to login again. {% endblocktrans %}</div> </td> </tr> + <!-- htmlmin:ignore -->{% if show_baserow_description %} + <!-- htmlmin:ignore --> <tr> <td align="left" style="font-size:0px;padding:10px 25px;word-break:break-word;"> <div style="font-family:Inter,sans-serif;font-size:13px;line-height:170%;text-align:left;color:#070810;">{% blocktrans trimmed %} Baserow is an open source no-code database tool which allows you to collaborate on projects, customers and more. It gives you the powers of a developer without leaving your browser. {% endblocktrans %}</div> </td> </tr> + <!-- htmlmin:ignore -->{% endif %} + <!-- htmlmin:ignore --> </tbody> </table> </div> diff --git a/backend/src/baserow/core/templates/baserow/core/user/account_deletion_scheduled.mjml.eta b/backend/src/baserow/core/templates/baserow/core/user/account_deletion_scheduled.mjml.eta index 0e9c2efa5..3a2e2201a 100644 --- a/backend/src/baserow/core/templates/baserow/core/user/account_deletion_scheduled.mjml.eta +++ b/backend/src/baserow/core/templates/baserow/core/user/account_deletion_scheduled.mjml.eta @@ -16,12 +16,14 @@ you just have to login again. {% endblocktrans %} </mj-text> - <mj-text mj-class="text"> - {% blocktrans trimmed %} - Baserow is an open source no-code database tool which allows you to collaborate - on projects, customers and more. It gives you the powers of a developer without - leaving your browser. - {% endblocktrans %} - </mj-text> + <mj-raw><!-- htmlmin:ignore -->{% if show_baserow_description %}<!-- htmlmin:ignore --></mj-raw> + <mj-text mj-class="text"> + {% blocktrans trimmed %} + Baserow is an open source no-code database tool which allows you to collaborate + on projects, customers and more. It gives you the powers of a developer without + leaving your browser. + {% endblocktrans %} + </mj-text> + <mj-raw><!-- htmlmin:ignore -->{% endif %}<!-- htmlmin:ignore --></mj-raw> </mj-column> </mj-section> diff --git a/backend/src/baserow/core/templates/baserow/core/user/reset_password.html b/backend/src/baserow/core/templates/baserow/core/user/reset_password.html index 574841fda..985f0d46a 100644 --- a/backend/src/baserow/core/templates/baserow/core/user/reset_password.html +++ b/backend/src/baserow/core/templates/baserow/core/user/reset_password.html @@ -204,11 +204,15 @@ <div style="font-family:Inter,sans-serif;font-size:12px;line-height:1;text-align:left;color:#9c9c9f;">{{ reset_url }}</div> </td> </tr> + <!-- htmlmin:ignore -->{% if show_baserow_description %} + <!-- htmlmin:ignore --> <tr> <td align="left" style="font-size:0px;padding:10px 25px;word-break:break-word;"> <div style="font-family:Inter,sans-serif;font-size:13px;line-height:170%;text-align:left;color:#070810;">{% blocktrans trimmed %} Baserow is an open source no-code database tool which allows you to collaborate on projects, customers and more. It gives you the powers of a developer without leaving your browser. {% endblocktrans %}</div> </td> </tr> + <!-- htmlmin:ignore -->{% endif %} + <!-- htmlmin:ignore --> </tbody> </table> </div> diff --git a/backend/src/baserow/core/templates/baserow/core/user/reset_password.mjml.eta b/backend/src/baserow/core/templates/baserow/core/user/reset_password.mjml.eta index 74fc44958..e917c0183 100644 --- a/backend/src/baserow/core/templates/baserow/core/user/reset_password.mjml.eta +++ b/backend/src/baserow/core/templates/baserow/core/user/reset_password.mjml.eta @@ -23,12 +23,14 @@ <mj-text mj-class="button-url"> {{ reset_url }} </mj-text> - <mj-text mj-class="text"> - {% blocktrans trimmed %} - Baserow is an open source no-code database tool which allows you to collaborate - on projects, customers and more. It gives you the powers of a developer without - leaving your browser. - {% endblocktrans %} - </mj-text> + <mj-raw><!-- htmlmin:ignore -->{% if show_baserow_description %}<!-- htmlmin:ignore --></mj-raw> + <mj-text mj-class="text"> + {% blocktrans trimmed %} + Baserow is an open source no-code database tool which allows you to collaborate + on projects, customers and more. It gives you the powers of a developer without + leaving your browser. + {% endblocktrans %} + </mj-text> + <mj-raw><!-- htmlmin:ignore -->{% endif %}<!-- htmlmin:ignore --></mj-raw> </mj-column> </mj-section> diff --git a/backend/src/baserow/core/templates/baserow/core/workspace_invitation.html b/backend/src/baserow/core/templates/baserow/core/workspace_invitation.html index 18781212f..b9c96003c 100644 --- a/backend/src/baserow/core/templates/baserow/core/workspace_invitation.html +++ b/backend/src/baserow/core/templates/baserow/core/workspace_invitation.html @@ -208,11 +208,15 @@ <div style="font-family:Inter,sans-serif;font-size:12px;line-height:1;text-align:left;color:#9c9c9f;">{{ public_accept_url }}</div> </td> </tr> + <!-- htmlmin:ignore -->{% if show_baserow_description %} + <!-- htmlmin:ignore --> <tr> <td align="left" style="font-size:0px;padding:10px 25px;word-break:break-word;"> <div style="font-family:Inter,sans-serif;font-size:13px;line-height:170%;text-align:left;color:#070810;">{% blocktrans trimmed %} Baserow is an open source no-code database tool which allows you to collaborate on projects, customers and more. It gives you the powers of a developer without leaving your browser. {% endblocktrans %}</div> </td> </tr> + <!-- htmlmin:ignore -->{% endif %} + <!-- htmlmin:ignore --> </tbody> </table> </div> diff --git a/backend/src/baserow/core/templates/baserow/core/workspace_invitation.mjml.eta b/backend/src/baserow/core/templates/baserow/core/workspace_invitation.mjml.eta index 6bc8692ea..92ece4788 100644 --- a/backend/src/baserow/core/templates/baserow/core/workspace_invitation.mjml.eta +++ b/backend/src/baserow/core/templates/baserow/core/workspace_invitation.mjml.eta @@ -20,12 +20,14 @@ <mj-text mj-class="button-url"> {{ public_accept_url }} </mj-text> - <mj-text mj-class="text"> - {% blocktrans trimmed %} - Baserow is an open source no-code database tool which allows you to collaborate - on projects, customers and more. It gives you the powers of a developer without - leaving your browser. - {% endblocktrans %} - </mj-text> + <mj-raw><!-- htmlmin:ignore -->{% if show_baserow_description %}<!-- htmlmin:ignore --></mj-raw> + <mj-text mj-class="text"> + {% blocktrans trimmed %} + Baserow is an open source no-code database tool which allows you to collaborate + on projects, customers and more. It gives you the powers of a developer without + leaving your browser. + {% endblocktrans %} + </mj-text> + <mj-raw><!-- htmlmin:ignore -->{% endif %}<!-- htmlmin:ignore --></mj-raw> </mj-column> </mj-section> diff --git a/backend/src/baserow/core/user/actions.py b/backend/src/baserow/core/user/actions.py index ecd106655..b70f4b70d 100644 --- a/backend/src/baserow/core/user/actions.py +++ b/backend/src/baserow/core/user/actions.py @@ -291,6 +291,11 @@ class SignInUserActionType(ActionType): auth_provider ).type + # This check must always be performed, even if the `log_signin_action` call is + # rate limited. + if user.profile.to_be_deleted: + UserHandler().cancel_user_deletion(user) + def log_signin_action(): handler.user_signed_in_via_provider(user, auth_provider) cls.register_action( diff --git a/backend/src/baserow/core/user_files/models.py b/backend/src/baserow/core/user_files/models.py index 45da4784f..3243dbd70 100644 --- a/backend/src/baserow/core/user_files/models.py +++ b/backend/src/baserow/core/user_files/models.py @@ -17,8 +17,8 @@ class UserFile(models.Model): size = models.PositiveIntegerField() mime_type = models.CharField(max_length=127, blank=True) is_image = models.BooleanField(default=False) - image_width = models.PositiveSmallIntegerField(null=True) - image_height = models.PositiveSmallIntegerField(null=True) + image_width = models.PositiveIntegerField(null=True) + image_height = models.PositiveIntegerField(null=True) uploaded_at = models.DateTimeField(auto_now_add=True) uploaded_by = models.ForeignKey(User, on_delete=models.SET_NULL, null=True) sha256_hash = models.CharField(max_length=64, db_index=True) diff --git a/backend/src/baserow/core/user_sources/handler.py b/backend/src/baserow/core/user_sources/handler.py index 75650b946..9d5cc84c5 100644 --- a/backend/src/baserow/core/user_sources/handler.py +++ b/backend/src/baserow/core/user_sources/handler.py @@ -12,7 +12,7 @@ from loguru import logger from baserow.core.db import specific_iterator from baserow.core.exceptions import ApplicationOperationNotSupported from baserow.core.integrations.handler import IntegrationHandler -from baserow.core.models import Application +from baserow.core.models import Application, Workspace from baserow.core.registries import application_type_registry from baserow.core.storage import ExportZipFile from baserow.core.user_sources.exceptions import UserSourceDoesNotExist @@ -374,7 +374,7 @@ class UserSourceHandler: ): """ Responsible for iterating over all registered user source types, and asking the - implementation to count the number of external users it points to. + implementation to count the number of application users it points to. :param user_source_type: Optionally, a specific user source type to update. :param update_in_chunks: Whether to update the user count in chunks or not. @@ -399,8 +399,45 @@ class UserSourceHandler: except Exception as e: if not settings.TESTS: logger.exception( - f"Counting {user_source_type.type} external users failed: {e}" + f"Counting {user_source_type.type} application users failed: {e}" ) if raise_on_error: raise e continue + + def aggregate_user_counts( + self, + workspace: Optional[Workspace] = None, + base_queryset: Optional[QuerySet] = None, + ) -> int: + """ + Responsible for returning the sum total of all user counts in the instance. + If a workspace is provided, this aggregation is reduced to applications + within this workspace. + + :param workspace: The workspace to filter the aggregation by. + :param base_queryset: The base queryset to use to build the query. + :return: The total number of user source users in the instance, or within the + workspace if provided. + """ + + queryset = ( + base_queryset + if base_queryset is not None + else self.get_user_sources( + base_queryset=UserSource.objects.filter( + application__workspace=workspace + ) + if workspace + else None + ) + ) + + user_source_counts: List[int] = [] + for user_source in queryset: + user_source_type: UserSourceType = user_source.get_type() # type: ignore + user_source_count = user_source_type.get_user_count(user_source) + if user_source_count is not None: + user_source_counts.append(user_source_count.count) + + return sum(user_source_counts) diff --git a/backend/src/baserow/core/utils.py b/backend/src/baserow/core/utils.py index 35838b453..fba2403fc 100644 --- a/backend/src/baserow/core/utils.py +++ b/backend/src/baserow/core/utils.py @@ -14,27 +14,14 @@ from decimal import Decimal from fractions import Fraction from itertools import chain, islice from numbers import Number -from typing import ( - Any, - Callable, - Dict, - Iterable, - List, - Optional, - Set, - Tuple, - Type, - Union, -) +from typing import Any, Dict, Iterable, List, Optional, Set, Tuple, Type, Union from django.conf import settings -from django.core.cache import cache from django.db import transaction from django.db.models import ForeignKey, ManyToManyField, Model from django.db.models.fields import NOT_PROVIDED from django.db.transaction import get_connection -from redis.exceptions import LockNotOwnedError from requests.utils import guess_json_utf from baserow.contrib.database.db.schema import optional_atomic @@ -910,6 +897,9 @@ class MirrorDict(defaultdict): def __missing__(self, key): return key + def __contains__(self, key): + return True + def get(self, key, default=None): return self[key] @@ -1206,81 +1196,3 @@ def are_hostnames_same(hostname1: str, hostname2: str) -> bool: ips1 = get_all_ips(hostname1) ips2 = get_all_ips(hostname2) return not ips1.isdisjoint(ips2) - - -def safe_get_or_set_cache( - cache_key: str, - version_cache_key: str = None, - default: Any | Callable = None, - timeout: int = 60, -) -> Any: - """ - Retrieves a value from the cache if it exists; otherwise, sets it using the - provided default value. If a version cache key is provided, the function uses - a versioned key to manage cache invalidation. - - This function also uses a lock (if available on the cache backend) to ensure - multi call safety when setting a new value. - - :param cache_key: The base key to look up in the cache. - :param version_cache_key: An optional key used to version the cache. If - provided,. - :param default: The default value to store in the cache if the key is absent. - Can be either a literal value or a callable. If it's a callable, - the function is called to retrieve the default value. - :param timeout: The cache timeout in seconds for newly set values. Defaults to 60. - :return: The cached value if it exists; otherwise, the newly set value. - """ - - cached = cache.get(cache_key) - - cache_key_to_use = cache_key - if version_cache_key is not None: - version = cache.get(version_cache_key, 0) - cache_key_to_use = f"{cache_key}__version_{version}" - - if cached is None: - use_lock = hasattr(cache, "lock") - if use_lock: - cache_lock = cache.lock(f"{cache_key_to_use}__lock", timeout=10) - cache_lock.acquire() - try: - cached = cache.get(cache_key_to_use) - # We check again to make sure it hasn't been populated in the meantime - # while acquiring the lock - if cached is None: - if callable(default): - cached = default() - else: - cached = default - - cache.set( - cache_key_to_use, - cached, - timeout=timeout, - ) - finally: - if use_lock: - try: - cache_lock.release() - except LockNotOwnedError: - # If the lock release fails, it might be because of the timeout - # and it's been stolen so we don't really care - pass - - return cached - - -def invalidate_versioned_cache(version_cache_key: str): - """ - Invalidates (or increments) the version associated with a versioned cache, - forcing future reads on this versioned key to miss the cache. - - :param version_cache_key: The key whose version is to be incremented in the cache. - """ - - try: - cache.incr(version_cache_key, 1) - except ValueError: - # No cache key, we create one - cache.set(version_cache_key, 1) diff --git a/backend/src/baserow/core/workflow_actions/handler.py b/backend/src/baserow/core/workflow_actions/handler.py index 1df2e3d93..37c76b160 100644 --- a/backend/src/baserow/core/workflow_actions/handler.py +++ b/backend/src/baserow/core/workflow_actions/handler.py @@ -58,7 +58,14 @@ class WorkflowActionHandler(ABC): if base_queryset is None: base_queryset = self.model.objects - return specific_iterator(base_queryset) + return specific_iterator( + base_queryset, + per_content_type_queryset_hook=( + lambda action, queryset: self.registry.get_by_model( + action + ).enhance_queryset(queryset) + ), + ) def create_workflow_action( self, workflow_action_type: WorkflowActionType, **prepared_values diff --git a/backend/src/baserow/test_utils/fixtures/element.py b/backend/src/baserow/test_utils/fixtures/element.py index 1e4008b6a..275d6318f 100644 --- a/backend/src/baserow/test_utils/fixtures/element.py +++ b/backend/src/baserow/test_utils/fixtures/element.py @@ -1,3 +1,4 @@ +import uuid from copy import deepcopy from baserow.contrib.builder.elements.models import ( @@ -10,6 +11,8 @@ from baserow.contrib.builder.elements.models import ( ImageElement, InputTextElement, LinkElement, + MenuElement, + MenuItemElement, RecordSelectorElement, RepeatElement, TableElement, @@ -116,6 +119,37 @@ class ElementFixtures: ) return element + def create_builder_menu_element(self, user=None, page=None, **kwargs): + return self.create_builder_element(MenuElement, user, page, **kwargs) + + def create_builder_menu_element_items( + self, user=None, page=None, menu_element=None, menu_items=None, **kwargs + ): + if not menu_element: + menu_element = self.create_builder_menu_element( + user=user, page=page, **kwargs + ) + + if not menu_items: + menu_items = [ + { + "variant": "link", + "type": "link", + "uid": uuid.uuid4(), + "name": "Test Link", + } + ] + + created_items = MenuItemElement.objects.bulk_create( + [ + MenuItemElement(**item, menu_item_order=index) + for index, item in enumerate(menu_items) + ] + ) + menu_element.menu_items.add(*created_items) + + return menu_element + def create_builder_element(self, model_class, user=None, page=None, **kwargs): if user is None: user = self.create_user() diff --git a/backend/src/baserow/test_utils/fixtures/file_import.py b/backend/src/baserow/test_utils/fixtures/file_import.py index 29bae68d2..86333cd2a 100644 --- a/backend/src/baserow/test_utils/fixtures/file_import.py +++ b/backend/src/baserow/test_utils/fixtures/file_import.py @@ -33,6 +33,7 @@ class FileImportFixtures: for field_index in range(column_count): row.append(f"data_{index}_{field_index}") data.append(row) + data = {"data": data} else: data = kwargs.pop("data") diff --git a/backend/src/baserow/test_utils/fixtures/row.py b/backend/src/baserow/test_utils/fixtures/row.py index a140f2098..004b761c9 100644 --- a/backend/src/baserow/test_utils/fixtures/row.py +++ b/backend/src/baserow/test_utils/fixtures/row.py @@ -78,7 +78,7 @@ class RowFixture: for row in rows ], ) - return created_rows + return created_rows.created_rows def get_rows(self, fields: List[Field]) -> List[List[Any]]: model = fields[0].table.get_model() diff --git a/backend/src/baserow/test_utils/fixtures/table.py b/backend/src/baserow/test_utils/fixtures/table.py index 8d615713f..309ae37d7 100644 --- a/backend/src/baserow/test_utils/fixtures/table.py +++ b/backend/src/baserow/test_utils/fixtures/table.py @@ -57,16 +57,20 @@ class TableFixtures: ) ) if rows: - created_rows = RowHandler().force_create_rows( - user=user, - table=table, - rows_values=[ - { - f"field_{field.id}": row[index] - for index, field in enumerate(fields) - } - for row in rows - ], + created_rows = ( + RowHandler() + .force_create_rows( + user=user, + table=table, + rows_values=[ + { + f"field_{field.id}": row[index] + for index, field in enumerate(fields) + } + for row in rows + ], + ) + .created_rows ) else: created_rows = [] @@ -101,12 +105,15 @@ class TableFixtures: if not table_b.field_set.filter(primary=True).exists(): self.create_text_field(table=table_b, name="primary", primary=True) + has_related_field = kwargs.pop("has_related_field", True) + link_field = FieldHandler().create_field( user=user, table=table_a, type_name="link_row", name="link", link_row_table=table_b, + has_related_field=has_related_field, ) return table_a, table_b, link_field diff --git a/backend/src/baserow/test_utils/fixtures/user_source.py b/backend/src/baserow/test_utils/fixtures/user_source.py index 6b7e44f5d..8410447f2 100644 --- a/backend/src/baserow/test_utils/fixtures/user_source.py +++ b/backend/src/baserow/test_utils/fixtures/user_source.py @@ -73,3 +73,48 @@ class UserSourceFixtures: ) return user_source, integration + + def create_local_baserow_table_user_source( + self, application=None, integration=None, table=None, user=None, **kwargs + ): + if not application: + if user is None: + user = self.create_user() + application_args = kwargs.pop("application_args", {}) + application = self.create_builder_application(user=user, **application_args) + + if not integration: + integration = self.create_local_baserow_integration(application=application) + + if not table: + table, fields, rows = self.build_table( + user=user, + columns=[ + ("Email", "text"), + ("Name", "text"), + ("Role", "text"), + ], + rows=[ + ["bram@baserow.io", "Bram", ""], + ["jrmi@baserow.io", "Jérémie", ""], + ["peter@baserow.io", "Peter", ""], + ["tsering@baserow.io", "Tsering", ""], + ["evren@baserow.io", "Evren", ""], + ], + ) + email_field, name_field, role_field = fields + else: + email_field = table.field_set.get(name="Email") + name_field = table.field_set.get(name="Name") + role_field = table.field_set.get(name="Role") + + local_baserow_user_source_type = user_source_type_registry.get("local_baserow") + return self.create_user_source( + local_baserow_user_source_type.model_class, + application=application, + integration=integration, + table=table, + email_field=email_field, + name_field=name_field, + role_field=role_field, + ) diff --git a/backend/src/baserow/test_utils/helpers.py b/backend/src/baserow/test_utils/helpers.py index 64fa1bb99..2d6444b88 100644 --- a/backend/src/baserow/test_utils/helpers.py +++ b/backend/src/baserow/test_utils/helpers.py @@ -318,7 +318,7 @@ def setup_interesting_test_table( blank_row, row = row_handler.force_create_rows( user, table, [{}, row_values], model=model - ) + ).created_rows # Setup the link rows linked_row_1, linked_row_2, linked_row_3 = row_handler.force_create_rows( @@ -337,7 +337,7 @@ def setup_interesting_test_table( link_table_primary_text_field.db_column: "", }, ], - ) + ).created_rows linked_row_4, linked_row_5, linked_row_6 = row_handler.force_create_rows( user=user, table=decimal_link_table, @@ -352,7 +352,7 @@ def setup_interesting_test_table( decimal_table_primary_decimal_field.db_column: None, }, ], - ) + ).created_rows with freeze_time("2020-01-01 12:00"): user_file_1 = data_fixture.create_user_file( original_name=f"name{file_suffix}.txt", @@ -372,7 +372,7 @@ def setup_interesting_test_table( file_link_table_primary_file_field.db_column: None, }, ], - ) + ).created_rows link_row_9, link_row_10 = row_handler.force_create_rows( user=user, table=multiple_collaborators_link_table, @@ -389,7 +389,7 @@ def setup_interesting_test_table( ], }, ], - ) + ).created_rows link_row_field_id = name_to_field_id["link_row"] link_row_field_without_related_id = name_to_field_id["link_row_without_related"] diff --git a/backend/src/baserow/test_utils/pytest_conftest.py b/backend/src/baserow/test_utils/pytest_conftest.py index de6725dc5..e92f52fc8 100755 --- a/backend/src/baserow/test_utils/pytest_conftest.py +++ b/backend/src/baserow/test_utils/pytest_conftest.py @@ -28,6 +28,9 @@ from rest_framework.test import APIRequestFactory from sqlparse import format from baserow.contrib.database.application_types import DatabaseApplicationType +from baserow.contrib.database.fields.fields import SerialField +from baserow.contrib.database.fields.models import LinkRowField +from baserow.contrib.database.webhooks.registries import webhook_event_type_registry from baserow.core.cache import local_cache from baserow.core.context import clear_current_workspace_id from baserow.core.exceptions import PermissionDenied @@ -38,6 +41,7 @@ from baserow.core.services.utils import ServiceAdhocRefinements from baserow.core.trash.trash_types import WorkspaceTrashableItemType from baserow.core.user_sources.registries import UserSourceCount from baserow.core.utils import get_value_at_path +from baserow.test_utils.setup_formulas import iter_formula_pgsql_functions SKIP_FLAGS = ["disabled-in-ci", "once-per-day-in-ci"] COMMAND_LINE_FLAG_PREFIX = "--run-" @@ -230,6 +234,14 @@ def mutable_job_type_registry(): job_type_registry.get_for_class.cache_clear() +@pytest.fixture() +def mutable_webhook_event_type_registry(): + with patch.object(webhook_event_type_registry, "registry", {}): + webhook_event_type_registry.get_for_class.cache_clear() + yield webhook_event_type_registry + webhook_event_type_registry.get_for_class.cache_clear() + + @pytest.fixture() def stub_user_source_registry(data_fixture, mutable_user_source_registry, fake): from baserow.core.user_sources.registries import UserSourceType @@ -901,6 +913,34 @@ def test_thread(): yield run_callable +@pytest.fixture(scope="session", autouse=True) +def baserow_db_setup(django_db_setup, django_db_blocker): + """ + Initialize the Baserow database for tests by installing custom pgSQL functions + and sequences. Disable this fixture with BASEROW_TESTS_SETUP_DB_FIXTURE=off if + running a subset of tests with `--no-migrations --reuse-db` and the pgSQL + functions are not needed or if you want to run all migrations. + """ + + if getattr(django_settings, "BASEROW_TESTS_SETUP_DB_FIXTURE", False) is False: + return + + def init_link_row_sequence(): + db_table = LinkRowField._meta.db_table + db_column = "link_row_relation_id" + + sequence_name = SerialField.get_sequence_name(db_table, db_column) + with connection.cursor() as cursor: + cursor.execute(f"CREATE SEQUENCE IF NOT EXISTS {sequence_name};") + + all_formula_functions = "\n".join(iter_formula_pgsql_functions()) + with django_db_blocker.unblock(): + with connection.cursor() as cursor: + cursor.execute(all_formula_functions) + + init_link_row_sequence() + + @pytest.fixture() def use_tmp_media_root(tmpdir, settings): settings.MEDIA_ROOT = tmpdir diff --git a/backend/src/baserow/test_utils/setup_formulas.py b/backend/src/baserow/test_utils/setup_formulas.py new file mode 100644 index 000000000..a8981740e --- /dev/null +++ b/backend/src/baserow/test_utils/setup_formulas.py @@ -0,0 +1,36 @@ +import os +import re +from typing import Iterable + +ROOT_DIR = os.path.abspath(os.path.dirname(os.path.realpath(__file__)) + "/..") + +MIGRATION_DIRS = [ + ROOT_DIR + "/contrib/database/migrations", + # Add more migration directories here if needed. +] + +# Matches all SQL functions in migration files. +FORMULA_PATTERN = re.compile( + r"create or replace function.*?language plpgsql;|create or replace function.*?language sql immutable strict;", + re.DOTALL | re.IGNORECASE, +) + + +def iter_formula_pgsql_functions() -> Iterable[str]: + """ + Iterates over all custom pgSQL functions in the migration files and yields the + content of the functions so they can be installed without running the migrations. + + :return: An iterable with the content of the pgSQL functions. + """ + + for migrations_dir in MIGRATION_DIRS: + for root, _, files in os.walk(migrations_dir): + for file in files: + if file.endswith(".py"): + file_path = os.path.join(root, file) + with open(file_path, "r") as f: + content = f.read() + matches = FORMULA_PATTERN.findall(content) + for match in matches: + yield match.replace("\\\\", "\\") diff --git a/backend/src/baserow/version.py b/backend/src/baserow/version.py index 560aa6346..49d00283a 100644 --- a/backend/src/baserow/version.py +++ b/backend/src/baserow/version.py @@ -1 +1 @@ -VERSION = "1.31.1" +VERSION = "1.32.0" diff --git a/backend/templates/ab_baserow_theme.json b/backend/templates/ab_baserow_theme.json new file mode 100644 index 000000000..8e174fbd8 --- /dev/null +++ b/backend/templates/ab_baserow_theme.json @@ -0,0 +1,4929 @@ +{ + "baserow_template_version": 1, + "name": "Baserow Theme", + "icon": "", + "keywords": [ + "application", + "builder", + "theme", + "baserow" + ], + "categories": [ + "Application Themes" + ], + "open_application": 177, + "export": [ + { + "pages": [ + { + "id": 214, + "name": "__shared__", + "order": 1, + "path": "__shared__", + "path_params": [], + "query_params": [], + "shared": true, + "elements": [ + { + "id": 3292, + "order": "0.33333333333333331483", + "type": "menu", + "parent_element_id": 3290, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "menu": { + "link_font_size": 13, + "link_text_color": "zoOtT", + "link_font_weight": "semi-bold", + "button_text_color": "zoOtT", + "button_border_size": 1, + "link_hover_text_color": "#2f3135", + "link_active_text_color": "zoOtT", + "button_background_color": "ElMaZ", + "button_hover_text_color": "zoOtT", + "button_active_text_color": "zoOtT", + "link_hover_text_decoration": [ + false, + false, + false, + false + ], + "link_active_text_decoration": [ + false, + false, + false, + false + ], + "link_default_text_decoration": [ + false, + false, + false, + false + ], + "button_hover_background_color": "#fafafa", + "button_active_background_color": "ElMaZ" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 8, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 8, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "orientation": "horizontal", + "alignment": "right", + "menu_items": [ + { + "id": 1, + "variant": "link", + "type": "link", + "menu_item_order": 0, + "uid": "8ba013be-494a-4a06-8917-a8767c401ad2", + "name": "Page 1", + "navigation_type": "page", + "navigate_to_page_id": null, + "navigate_to_url": "", + "page_parameters": [], + "query_parameters": [], + "parent_menu_item": null, + "target": "self", + "children": [] + }, + { + "id": 2, + "variant": "link", + "type": "link", + "menu_item_order": 1, + "uid": "bbfd8ca3-a0cd-489e-be09-cd1d46efb14a", + "name": "Sub page 1", + "navigation_type": "page", + "navigate_to_page_id": 215, + "navigate_to_url": "", + "page_parameters": [], + "query_parameters": [], + "parent_menu_item": 1, + "target": "self", + "children": [] + }, + { + "id": 3, + "variant": "link", + "type": "link", + "menu_item_order": 2, + "uid": "b38bf885-f808-45ee-9c50-36d92f7d1d39", + "name": "Page 2", + "navigation_type": "page", + "navigate_to_page_id": 215, + "navigate_to_url": "", + "page_parameters": [], + "query_parameters": [], + "parent_menu_item": null, + "target": "self", + "children": [] + }, + { + "id": 4, + "variant": "link", + "type": "link", + "menu_item_order": 3, + "uid": "df9febeb-2f8b-49f6-9469-d8b44f28f1b0", + "name": "Sub page 2", + "navigation_type": "page", + "navigate_to_page_id": 215, + "navigate_to_url": "", + "page_parameters": [], + "query_parameters": [], + "parent_menu_item": 1, + "target": "self", + "children": [] + }, + { + "id": 5, + "variant": "link", + "type": "link", + "menu_item_order": 4, + "uid": "ad8260e4-e1b9-4cfc-9eb3-c2cdf8f6f1f1", + "name": "Sub page 3", + "navigation_type": "page", + "navigate_to_page_id": 215, + "navigate_to_url": "", + "page_parameters": [], + "query_parameters": [], + "parent_menu_item": 1, + "target": "self", + "children": [] + }, + { + "id": 6, + "variant": "link", + "type": "link", + "menu_item_order": 5, + "uid": "be62d7f3-f6be-44a9-9c75-5866bc51c30b", + "name": "Page 3", + "navigation_type": "page", + "navigate_to_page_id": 215, + "navigate_to_url": "", + "page_parameters": [], + "query_parameters": [], + "parent_menu_item": null, + "target": "self", + "children": [] + }, + { + "id": 7, + "variant": "link", + "type": "button", + "menu_item_order": 6, + "uid": "0cbdfe6e-344e-427f-86c7-450f48bb5f21", + "name": "Contact us", + "navigation_type": "page", + "navigate_to_page_id": null, + "navigate_to_url": "", + "page_parameters": [], + "query_parameters": [], + "parent_menu_item": null, + "target": "self", + "children": [] + } + ] + }, + { + "id": 3297, + "order": "0.50000000000000000000", + "type": "text", + "parent_element_id": 3294, + "place_in_container": "2", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 15, + "body_text_color": "#ffffff", + "body_font_weight": "semi-bold" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 20, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Newsletter'", + "format": "plain" + }, + { + "id": 3298, + "order": "0.66666666666666662966", + "type": "text", + "parent_element_id": 3294, + "place_in_container": "2", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 13, + "body_text_color": "#ffffff" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Signup for our newsletter by filling out your email address.'", + "format": "plain" + }, + { + "id": 3290, + "order": "1.00000000000000000000", + "type": "header", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 20, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "medium", + "style_width_child": "normal", + "share_type": "all", + "pages": [] + }, + { + "id": 3293, + "order": "1.00000000000000000000", + "type": "simple_container", + "parent_element_id": 3291, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "medium" + }, + { + "id": 3294, + "order": "1.00000000000000000000", + "type": "column", + "parent_element_id": 3293, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "column_amount": 3, + "column_gap": 20, + "alignment": "top" + }, + { + "id": 3295, + "order": "1.00000000000000000000", + "type": "form_container", + "parent_element_id": 3294, + "place_in_container": "2", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "button": { + "button_alignment": "right" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "submit_button_label": "'Submit'", + "reset_initial_values_post_submission": false + }, + { + "id": 3296, + "order": "1.00000000000000000000", + "type": "input_text", + "parent_element_id": 3295, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "label": "", + "required": true, + "validation_type": "email", + "placeholder": "'Your email address...'", + "default_value": "", + "is_multiline": false, + "rows": 3, + "input_type": "text" + }, + { + "id": 3299, + "order": "1.00000000000000000000", + "type": "text", + "parent_element_id": 3294, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 15, + "body_text_color": "#ffffff", + "body_font_weight": "semi-bold" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 20, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Quick links'", + "format": "plain" + }, + { + "id": 3300, + "order": "1.00000000000000000000", + "type": "text", + "parent_element_id": 3294, + "place_in_container": "1", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 15, + "body_text_color": "#ffffff", + "body_font_weight": "semi-bold" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 20, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Community'", + "format": "plain" + }, + { + "id": 3291, + "order": "2.00000000000000000000", + "type": "footer", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 30, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 30, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "color", + "style_background_color": "zoOtT", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "full", + "style_width_child": "normal", + "share_type": "all", + "pages": [] + }, + { + "id": 3301, + "order": "2.00000000000000000000", + "type": "link", + "parent_element_id": 3294, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "link": { + "link_font_size": 13, + "link_text_color": "#f2f2f2", + "link_font_weight": "medium", + "link_hover_text_color": "#f2f2f2", + "link_active_text_color": "#f2f2f2" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 12, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "navigation_type": "page", + "navigate_to_page_id": 215, + "page_parameters": [], + "query_parameters": [], + "navigate_to_url": "", + "target": "self", + "value": "'About us'", + "variant": "link" + }, + { + "id": 3302, + "order": "2.00000000000000000000", + "type": "link", + "parent_element_id": 3294, + "place_in_container": "1", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "link": { + "link_font_size": 13, + "link_text_color": "#f2f2f2", + "link_font_weight": "medium", + "link_hover_text_color": "#f2f2f2", + "link_active_text_color": "#f2f2f2" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 12, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "navigation_type": "page", + "navigate_to_page_id": 215, + "page_parameters": [], + "query_parameters": [], + "navigate_to_url": "", + "target": "self", + "value": "'Documents'", + "variant": "link" + }, + { + "id": 3303, + "order": "3.00000000000000000000", + "type": "link", + "parent_element_id": 3294, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "link": { + "link_font_size": 13, + "link_text_color": "#f2f2f2", + "link_font_weight": "medium", + "link_hover_text_color": "#f2f2f2", + "link_active_text_color": "#f2f2f2" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 12, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "navigation_type": "page", + "navigate_to_page_id": 215, + "page_parameters": [], + "query_parameters": [], + "navigate_to_url": "", + "target": "self", + "value": "'Contact us'", + "variant": "link" + }, + { + "id": 3304, + "order": "3.00000000000000000000", + "type": "link", + "parent_element_id": 3294, + "place_in_container": "1", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "link": { + "link_font_size": 13, + "link_text_color": "#f2f2f2", + "link_font_weight": "medium", + "link_hover_text_color": "#f2f2f2", + "link_active_text_color": "#f2f2f2" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 12, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "navigation_type": "page", + "navigate_to_page_id": 215, + "page_parameters": [], + "query_parameters": [], + "navigate_to_url": "", + "target": "self", + "value": "'Support'", + "variant": "link" + }, + { + "id": 3305, + "order": "4.00000000000000000000", + "type": "link", + "parent_element_id": 3294, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "link": { + "link_font_size": 13, + "link_text_color": "#f2f2f2", + "link_font_weight": "medium", + "link_hover_text_color": "#f2f2f2", + "link_active_text_color": "#f2f2f2" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 12, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "navigation_type": "page", + "navigate_to_page_id": 215, + "page_parameters": [], + "query_parameters": [], + "navigate_to_url": "", + "target": "self", + "value": "'Career'", + "variant": "link" + }, + { + "id": 3306, + "order": "4.00000000000000000000", + "type": "link", + "parent_element_id": 3294, + "place_in_container": "1", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "link": { + "link_font_size": 13, + "link_text_color": "#f2f2f2", + "link_font_weight": "medium", + "link_hover_text_color": "#f2f2f2", + "link_active_text_color": "#f2f2f2" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 12, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "navigation_type": "page", + "navigate_to_page_id": 215, + "page_parameters": [], + "query_parameters": [], + "navigate_to_url": "", + "target": "self", + "value": "'FAQ'", + "variant": "link" + }, + { + "id": 3307, + "order": "5.00000000000000000000", + "type": "link", + "parent_element_id": 3294, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "link": { + "link_font_size": 13, + "link_text_color": "#f2f2f2", + "link_font_weight": "medium", + "link_hover_text_color": "#f2f2f2", + "link_active_text_color": "#f2f2f2" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 12, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "navigation_type": "page", + "navigate_to_page_id": 215, + "page_parameters": [], + "query_parameters": [], + "navigate_to_url": "", + "target": "self", + "value": "'Become a partner'", + "variant": "link" + }, + { + "id": 3308, + "order": "5.00000000000000000000", + "type": "link", + "parent_element_id": 3294, + "place_in_container": "1", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "link": { + "link_font_size": 13, + "link_text_color": "#f2f2f2", + "link_font_weight": "medium", + "link_hover_text_color": "#f2f2f2", + "link_active_text_color": "#f2f2f2" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 12, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "navigation_type": "page", + "navigate_to_page_id": 215, + "page_parameters": [], + "query_parameters": [], + "navigate_to_url": "", + "target": "self", + "value": "'Privacy policy'", + "variant": "link" + }, + { + "id": 3309, + "order": "6.00000000000000000000", + "type": "link", + "parent_element_id": 3294, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "link": { + "link_font_size": 13, + "link_text_color": "#f2f2f2", + "link_font_weight": "medium", + "link_hover_text_color": "#f2f2f2", + "link_active_text_color": "#f2f2f2" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 12, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "navigation_type": "page", + "navigate_to_page_id": 215, + "page_parameters": [], + "query_parameters": [], + "navigate_to_url": "", + "target": "self", + "value": "'Sign in'", + "variant": "link" + }, + { + "id": 3310, + "order": "6.00000000000000000000", + "type": "link", + "parent_element_id": 3294, + "place_in_container": "1", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "link": { + "link_font_size": 13, + "link_text_color": "#f2f2f2", + "link_font_weight": "medium", + "link_hover_text_color": "#f2f2f2", + "link_active_text_color": "#f2f2f2" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 12, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "navigation_type": "page", + "navigate_to_page_id": 215, + "page_parameters": [], + "query_parameters": [], + "navigate_to_url": "", + "target": "self", + "value": "'Blog'", + "variant": "link" + }, + { + "id": 3311, + "order": "7.00000000000000000000", + "type": "link", + "parent_element_id": 3294, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "link": { + "link_font_size": 13, + "link_text_color": "#f2f2f2", + "link_font_weight": "medium", + "link_hover_text_color": "#f2f2f2", + "link_active_text_color": "#f2f2f2" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 12, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "navigation_type": "page", + "navigate_to_page_id": 215, + "page_parameters": [], + "query_parameters": [], + "navigate_to_url": "", + "target": "self", + "value": "'Sign up'", + "variant": "link" + }, + { + "id": 3312, + "order": "7.00000000000000000000", + "type": "link", + "parent_element_id": 3294, + "place_in_container": "1", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "link": { + "link_font_size": 13, + "link_text_color": "#f2f2f2", + "link_font_weight": "medium", + "link_hover_text_color": "#f2f2f2", + "link_active_text_color": "#f2f2f2" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 12, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "navigation_type": "page", + "navigate_to_page_id": 215, + "page_parameters": [], + "query_parameters": [], + "navigate_to_url": "", + "target": "self", + "value": "'Terms & conditions'", + "variant": "link" + } + ], + "data_sources": [], + "workflow_actions": [ + { + "id": 313, + "type": "notification", + "order": 1, + "page_id": 214, + "element_id": 3292, + "event": "0cbdfe6e-344e-427f-86c7-450f48bb5f21_click", + "title": "'Show contact form'", + "description": "'Show contact form'" + }, + { + "id": 314, + "type": "notification", + "order": 1, + "page_id": 214, + "element_id": 3295, + "event": "submit", + "title": "'Newsletter'", + "description": "'Signup for newsletter'" + } + ], + "visibility": "all", + "role_type": "allow_all", + "roles": [] + }, + { + "id": 215, + "name": "Examples", + "order": 1, + "path": "/", + "path_params": [], + "query_params": [], + "shared": false, + "elements": [ + { + "id": 3347, + "order": "0.50000000000000000000", + "type": "text", + "parent_element_id": 3336, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 13, + "body_text_color": "#ffffff", + "body_font_weight": "medium" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 4, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Secondary'", + "format": "plain" + }, + { + "id": 3348, + "order": "0.66666666666666662966", + "type": "text", + "parent_element_id": 3337, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 13, + "body_font_weight": "medium" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 4, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Border'", + "format": "plain" + }, + { + "id": 3349, + "order": "0.66666666666666662966", + "type": "text", + "parent_element_id": 3341, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 13, + "body_text_color": "ElMaZ", + "body_font_weight": "medium" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 4, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Custom 2'", + "format": "plain" + }, + { + "id": 3317, + "order": "1.00000000000000000000", + "type": "heading", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "heading_2_font_weight": "semi-bold" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 20, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "medium", + "style_width_child": "normal", + "value": "'Recent projects'", + "level": 2 + }, + { + "id": 3318, + "order": "1.00000000000000000000", + "type": "iframe", + "parent_element_id": 3314, + "place_in_container": "1", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 20, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "source_type": "url", + "url": "'https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d2437.5900465602517!2d4.825077027115522!3d52.341582849423204!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x47c5e18eae78495d%3A0xc6ec111aab4c79fe!2sB.%20Amsterdam!5e0!3m2!1sen!2snl!4v1741957273376!5m2!1sen!2snl\" width=\"600\" height=\"450\" style=\"border:0;'", + "embed": "", + "height": 268 + }, + { + "id": 3331, + "order": "1.00000000000000000000", + "type": "simple_container", + "parent_element_id": 3313, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 1, + "style_padding_top": 24, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 1, + "style_padding_bottom": 24, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 1, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 1, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 6, + "style_border_radius": 6, + "style_background": "color", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal" + }, + { + "id": 3332, + "order": "1.00000000000000000000", + "type": "simple_container", + "parent_element_id": 3313, + "place_in_container": "1", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 1, + "style_padding_top": 24, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 1, + "style_padding_bottom": 24, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 1, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 1, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 6, + "style_border_radius": 6, + "style_background": "color", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal" + }, + { + "id": 3333, + "order": "1.00000000000000000000", + "type": "simple_container", + "parent_element_id": 3313, + "place_in_container": "2", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 1, + "style_padding_top": 24, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 1, + "style_padding_bottom": 24, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 1, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 1, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 6, + "style_border_radius": 6, + "style_background": "color", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal" + }, + { + "id": 3334, + "order": "1.00000000000000000000", + "type": "form_container", + "parent_element_id": 3314, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "button": { + "button_alignment": "right" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "submit_button_label": "'Submit'", + "reset_initial_values_post_submission": false + }, + { + "id": 3335, + "order": "1.00000000000000000000", + "type": "simple_container", + "parent_element_id": 3315, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 20, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 50, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "color", + "style_background_color": "primary", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal" + }, + { + "id": 3336, + "order": "1.00000000000000000000", + "type": "simple_container", + "parent_element_id": 3315, + "place_in_container": "1", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 20, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 50, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "color", + "style_background_color": "secondary", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal" + }, + { + "id": 3337, + "order": "1.00000000000000000000", + "type": "simple_container", + "parent_element_id": 3315, + "place_in_container": "2", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 20, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 50, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "color", + "style_background_color": "border", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal" + }, + { + "id": 3338, + "order": "1.00000000000000000000", + "type": "simple_container", + "parent_element_id": 3315, + "place_in_container": "3", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 20, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 50, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "color", + "style_background_color": "success", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal" + }, + { + "id": 3339, + "order": "1.00000000000000000000", + "type": "simple_container", + "parent_element_id": 3315, + "place_in_container": "4", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 20, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 50, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "color", + "style_background_color": "warning", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal" + }, + { + "id": 3340, + "order": "1.00000000000000000000", + "type": "simple_container", + "parent_element_id": 3315, + "place_in_container": "5", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 20, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 50, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "color", + "style_background_color": "error", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal" + }, + { + "id": 3341, + "order": "1.00000000000000000000", + "type": "simple_container", + "parent_element_id": 3316, + "place_in_container": "1", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 20, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 50, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "color", + "style_background_color": "zoOtT", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal" + }, + { + "id": 3344, + "order": "1.00000000000000000000", + "type": "input_text", + "parent_element_id": 3334, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "label": "'Your name'", + "required": true, + "validation_type": "any", + "placeholder": "'Enter your name here...'", + "default_value": "", + "is_multiline": false, + "rows": 3, + "input_type": "text" + }, + { + "id": 3350, + "order": "1.00000000000000000000", + "type": "heading", + "parent_element_id": 3331, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "heading_3_font_size": 16 + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 24, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Rebranding website'", + "level": 3 + }, + { + "id": 3351, + "order": "1.00000000000000000000", + "type": "text", + "parent_element_id": 3335, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 13, + "body_text_color": "#ffffff", + "body_font_weight": "medium" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 4, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Primary'", + "format": "plain" + }, + { + "id": 3352, + "order": "1.00000000000000000000", + "type": "text", + "parent_element_id": 3336, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_color": "#ffffff" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'#2BC3F1'", + "format": "plain" + }, + { + "id": 3353, + "order": "1.00000000000000000000", + "type": "text", + "parent_element_id": 3338, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 13, + "body_font_weight": "medium" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 4, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Success'", + "format": "plain" + }, + { + "id": 3354, + "order": "1.00000000000000000000", + "type": "text", + "parent_element_id": 3343, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 13, + "body_text_color": "#ffffff", + "body_font_weight": "medium" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 4, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Custom 3'", + "format": "plain" + }, + { + "id": 3355, + "order": "1.50000000000000000000", + "type": "heading", + "parent_element_id": 3332, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "heading_3_font_size": 16 + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 24, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Customer research'", + "level": 3 + }, + { + "id": 3356, + "order": "1.50000000000000000000", + "type": "text", + "parent_element_id": 3342, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 13, + "body_font_weight": "medium" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 4, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Custom 1'", + "format": "plain" + }, + { + "id": 3313, + "order": "2.00000000000000000000", + "type": "column", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 40, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "medium", + "style_width_child": "normal", + "column_amount": 3, + "column_gap": 24, + "alignment": "top" + }, + { + "id": 3319, + "order": "2.00000000000000000000", + "type": "text", + "parent_element_id": 3314, + "place_in_container": "1", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Visit us at: Streetname 100, The Netherlands'", + "format": "plain" + }, + { + "id": 3342, + "order": "2.00000000000000000000", + "type": "simple_container", + "parent_element_id": 3316, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 20, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 50, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "color", + "style_background_color": "ElMaZ", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal" + }, + { + "id": 3343, + "order": "2.00000000000000000000", + "type": "simple_container", + "parent_element_id": 3316, + "place_in_container": "2", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 20, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 50, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "color", + "style_background_color": "V6EVv", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal" + }, + { + "id": 3345, + "order": "2.00000000000000000000", + "type": "input_text", + "parent_element_id": 3334, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "label": "'Your email'", + "required": true, + "validation_type": "email", + "placeholder": "'Enter your email here...'", + "default_value": "", + "is_multiline": false, + "rows": 3, + "input_type": "text" + }, + { + "id": 3357, + "order": "2.00000000000000000000", + "type": "text", + "parent_element_id": 3331, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 11, + "body_text_color": "V6EVv" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 6, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Kick-off date'", + "format": "plain" + }, + { + "id": 3358, + "order": "2.00000000000000000000", + "type": "heading", + "parent_element_id": 3333, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "heading_3_font_size": 16 + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 24, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'App builder launch'", + "level": 3 + }, + { + "id": 3359, + "order": "2.00000000000000000000", + "type": "text", + "parent_element_id": 3335, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_color": "#ffffff" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'#4E5CFE'", + "format": "plain" + }, + { + "id": 3360, + "order": "2.00000000000000000000", + "type": "text", + "parent_element_id": 3337, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12 + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'#EDEDED'", + "format": "plain" + }, + { + "id": 3361, + "order": "2.00000000000000000000", + "type": "text", + "parent_element_id": 3339, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 13, + "body_font_weight": "medium" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 4, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Warning'", + "format": "plain" + }, + { + "id": 3362, + "order": "2.00000000000000000000", + "type": "text", + "parent_element_id": 3341, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_color": "ElMaZ" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'#202128'", + "format": "plain" + }, + { + "id": 3363, + "order": "2.50000000000000000000", + "type": "text", + "parent_element_id": 3332, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 11, + "body_text_color": "V6EVv" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 6, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Kick-off date'", + "format": "plain" + }, + { + "id": 3320, + "order": "3.00000000000000000000", + "type": "heading", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "heading_2_font_weight": "semi-bold" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 20, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "medium", + "style_width_child": "normal", + "value": "'My tasks'", + "level": 2 + }, + { + "id": 3346, + "order": "3.00000000000000000000", + "type": "input_text", + "parent_element_id": 3334, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "label": "'Your question'", + "required": true, + "validation_type": "any", + "placeholder": "'Enter your question here...'", + "default_value": "", + "is_multiline": true, + "rows": 5, + "input_type": "text" + }, + { + "id": 3364, + "order": "3.00000000000000000000", + "type": "text", + "parent_element_id": 3331, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 16, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'2024-02-09'", + "format": "plain" + }, + { + "id": 3365, + "order": "3.00000000000000000000", + "type": "text", + "parent_element_id": 3333, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 11, + "body_text_color": "V6EVv" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 6, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Kick-off date'", + "format": "plain" + }, + { + "id": 3366, + "order": "3.00000000000000000000", + "type": "text", + "parent_element_id": 3338, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12 + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'#12D452'", + "format": "plain" + }, + { + "id": 3367, + "order": "3.00000000000000000000", + "type": "text", + "parent_element_id": 3340, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 13, + "body_font_weight": "medium" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 4, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Error'", + "format": "plain" + }, + { + "id": 3368, + "order": "3.00000000000000000000", + "type": "text", + "parent_element_id": 3342, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12 + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'#ffffff'", + "format": "plain" + }, + { + "id": 3369, + "order": "3.00000000000000000000", + "type": "text", + "parent_element_id": 3343, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_color": "#ffffff" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'#6A6B70'", + "format": "plain" + }, + { + "id": 3370, + "order": "3.50000000000000000000", + "type": "text", + "parent_element_id": 3332, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 16, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'2024-03-15'", + "format": "plain" + }, + { + "id": 3321, + "order": "4.00000000000000000000", + "type": "table", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 40, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "medium", + "style_width_child": "normal", + "data_source_id": 382, + "items_per_page": 20, + "button_load_more_label": "", + "schema_property": null, + "property_options": [], + "fields": [ + { + "uid": "01e71c25-dfd0-4772-94dd-1630376a29ae", + "name": "Name", + "type": "text", + "styles": {}, + "config": { + "value": "get('current_record.field_7204')" + } + }, + { + "uid": "a0c999b2-f45d-4d92-9c3e-352e5baabb1f", + "name": "Status", + "type": "tags", + "styles": { + "cell": {} + }, + "config": { + "values": "get('current_record.field_7205.value')", + "colors_is_formula": true, + "colors": "concat('#',get('current_record.field_7209'))" + } + }, + { + "uid": "e4546824-a48a-402a-a6ce-b811f248a347", + "name": "Client", + "type": "text", + "styles": {}, + "config": { + "value": "get('current_record.field_7206.*.value')" + } + } + ], + "orientation": { + "tablet": "horizontal", + "desktop": "horizontal", + "smartphone": "horizontal" + } + }, + { + "id": 3371, + "order": "4.00000000000000000000", + "type": "text", + "parent_element_id": 3331, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 11, + "body_text_color": "V6EVv" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 6, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Due date'", + "format": "plain" + }, + { + "id": 3372, + "order": "4.00000000000000000000", + "type": "text", + "parent_element_id": 3333, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 16, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'2024-04-07'", + "format": "plain" + }, + { + "id": 3373, + "order": "4.00000000000000000000", + "type": "text", + "parent_element_id": 3339, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12 + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'#FFD269'", + "format": "plain" + }, + { + "id": 3374, + "order": "4.50000000000000000000", + "type": "text", + "parent_element_id": 3332, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 11, + "body_text_color": "V6EVv" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 6, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Due date'", + "format": "plain" + }, + { + "id": 3322, + "order": "5.00000000000000000000", + "type": "heading", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "heading_2_font_weight": "semi-bold" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 20, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "medium", + "style_width_child": "normal", + "value": "'Contact us'", + "level": 2 + }, + { + "id": 3375, + "order": "5.00000000000000000000", + "type": "text", + "parent_element_id": 3331, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 16, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'2024-02-16'", + "format": "plain" + }, + { + "id": 3376, + "order": "5.00000000000000000000", + "type": "text", + "parent_element_id": 3333, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 11, + "body_text_color": "V6EVv" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 6, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Due date'", + "format": "plain" + }, + { + "id": 3377, + "order": "5.00000000000000000000", + "type": "text", + "parent_element_id": 3340, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12 + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'#FF5A44'", + "format": "plain" + }, + { + "id": 3378, + "order": "5.50000000000000000000", + "type": "text", + "parent_element_id": 3332, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 16, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'2024-02-12'", + "format": "plain" + }, + { + "id": 3314, + "order": "6.00000000000000000000", + "type": "column", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 40, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "medium", + "style_width_child": "normal", + "column_amount": 2, + "column_gap": 40, + "alignment": "top" + }, + { + "id": 3379, + "order": "6.00000000000000000000", + "type": "text", + "parent_element_id": 3331, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 11, + "body_text_color": "V6EVv" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 6, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Label'", + "format": "plain" + }, + { + "id": 3380, + "order": "6.00000000000000000000", + "type": "text", + "parent_element_id": 3333, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 16, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'2024-04-12'", + "format": "plain" + }, + { + "id": 3323, + "order": "6.50000000000000000000", + "type": "heading", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "heading_2_font_weight": "semi-bold" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 20, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "medium", + "style_width_child": "normal", + "value": "'Colors'", + "level": 2 + }, + { + "id": 3381, + "order": "6.50000000000000000000", + "type": "text", + "parent_element_id": 3332, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 11, + "body_text_color": "V6EVv" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 6, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Label'", + "format": "plain" + }, + { + "id": 3315, + "order": "7.00000000000000000000", + "type": "column", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "medium", + "style_width_child": "normal", + "column_amount": 6, + "column_gap": 1, + "alignment": "top" + }, + { + "id": 3382, + "order": "7.00000000000000000000", + "type": "text", + "parent_element_id": 3331, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 16, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Value'", + "format": "plain" + }, + { + "id": 3383, + "order": "7.00000000000000000000", + "type": "text", + "parent_element_id": 3333, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 11, + "body_text_color": "V6EVv" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 6, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Label'", + "format": "plain" + }, + { + "id": 3316, + "order": "7.50000000000000000000", + "type": "column", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 40, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "medium", + "style_width_child": "normal", + "column_amount": 6, + "column_gap": 1, + "alignment": "top" + }, + { + "id": 3384, + "order": "7.50000000000000000000", + "type": "text", + "parent_element_id": 3332, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 16, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Value'", + "format": "plain" + }, + { + "id": 3324, + "order": "8.00000000000000000000", + "type": "heading", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "medium", + "style_width_child": "normal", + "value": "'Heading 1'", + "level": 1 + }, + { + "id": 3385, + "order": "8.00000000000000000000", + "type": "link", + "parent_element_id": 3331, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "button": { + "button_width": "full" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 10, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "navigation_type": "page", + "navigate_to_page_id": 215, + "page_parameters": [], + "query_parameters": [], + "navigate_to_url": "", + "target": "self", + "value": "'View tasks'", + "variant": "button" + }, + { + "id": 3386, + "order": "8.00000000000000000000", + "type": "text", + "parent_element_id": 3333, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 16, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Value'", + "format": "plain" + }, + { + "id": 3325, + "order": "9.00000000000000000000", + "type": "heading", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "medium", + "style_width_child": "normal", + "value": "'Heading 2'", + "level": 2 + }, + { + "id": 3387, + "order": "9.00000000000000000000", + "type": "link", + "parent_element_id": 3332, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "button": { + "button_width": "full" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 10, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "navigation_type": "page", + "navigate_to_page_id": 215, + "page_parameters": [], + "query_parameters": [], + "navigate_to_url": "", + "target": "self", + "value": "'View tasks'", + "variant": "button" + }, + { + "id": 3326, + "order": "10.00000000000000000000", + "type": "heading", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "medium", + "style_width_child": "normal", + "value": "'Heading 3'", + "level": 3 + }, + { + "id": 3388, + "order": "10.00000000000000000000", + "type": "link", + "parent_element_id": 3333, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "button": { + "button_width": "full" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 10, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "navigation_type": "page", + "navigate_to_page_id": 215, + "page_parameters": [], + "query_parameters": [], + "navigate_to_url": "", + "target": "self", + "value": "'View tasks'", + "variant": "button" + }, + { + "id": 3327, + "order": "11.00000000000000000000", + "type": "heading", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "medium", + "style_width_child": "normal", + "value": "'Heading 4'", + "level": 4 + }, + { + "id": 3328, + "order": "12.00000000000000000000", + "type": "heading", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "medium", + "style_width_child": "normal", + "value": "'Heading 5'", + "level": 5 + }, + { + "id": 3329, + "order": "13.00000000000000000000", + "type": "heading", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "medium", + "style_width_child": "normal", + "value": "'Heading 6'", + "level": 6 + }, + { + "id": 3330, + "order": "14.00000000000000000000", + "type": "text", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 40, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "medium", + "style_width_child": "normal", + "value": "'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque eu mollis purus. Integer ac bibendum metus. Morbi nunc eros, suscipit sed tristique vel, rutrum a nibh. In urna leo, pulvinar ac nunc vitae, vulputate pretium magna. Vivamus leo mauris, iaculis vel velit at, dapibus convallis magna. Sed tincidunt leo dui, vel viverra ex gravida eget. Pellentesque posuere scelerisque velit, in rutrum lorem vestibulum eleifend. Phasellus at consectetur urna, id bibendum neque. Fusce et metus magna.'", + "format": "plain" + } + ], + "data_sources": [ + { + "id": 382, + "name": "Tasks", + "order": "1.00000000000000000000", + "service": { + "id": 489, + "integration_id": 35, + "type": "local_baserow_list_rows", + "table_id": 738, + "view_id": null, + "sortings": [], + "search_query": "", + "filter_type": "AND", + "filters": [] + } + } + ], + "workflow_actions": [ + { + "id": 315, + "type": "notification", + "order": 1, + "page_id": 215, + "element_id": 3334, + "event": "submit", + "title": "'Thank you'", + "description": "'Thank youb for filling out the contact us form.'" + } + ], + "visibility": "all", + "role_type": "allow_all", + "roles": [] + } + ], + "integrations": [ + { + "id": 35, + "name": "Local Baserow", + "order": "1.00000000000000000000", + "type": "local_baserow", + "authorized_user": null + } + ], + "theme": { + "primary_color": "#4e5cfe", + "secondary_color": "#2bc3f1", + "border_color": "#ededed", + "main_success_color": "#12d452", + "main_warning_color": "#ffd269", + "main_error_color": "#ff5a44", + "custom_colors": [ + { + "name": "Custom 1", + "color": "#ffffff", + "value": "ElMaZ" + }, + { + "name": "Custom 2", + "color": "#202128", + "value": "zoOtT" + }, + { + "name": "Custom 3", + "color": "#6a6b70", + "value": "V6EVv" + } + ], + "body_font_family": "inter", + "body_font_size": 14, + "body_font_weight": "regular", + "body_text_color": "zoOtT", + "body_text_alignment": "left", + "heading_1_font_family": "inter", + "heading_1_font_size": 32, + "heading_1_font_weight": "bold", + "heading_1_text_color": "zoOtT", + "heading_1_text_alignment": "left", + "heading_1_text_decoration": [ + false, + false, + false, + false + ], + "heading_2_font_family": "inter", + "heading_2_font_size": 24, + "heading_2_font_weight": "bold", + "heading_2_text_color": "zoOtT", + "heading_2_text_alignment": "left", + "heading_2_text_decoration": [ + false, + false, + false, + false + ], + "heading_3_font_family": "inter", + "heading_3_font_size": 24, + "heading_3_font_weight": "semi-bold", + "heading_3_text_color": "zoOtT", + "heading_3_text_alignment": "left", + "heading_3_text_decoration": [ + false, + false, + false, + false + ], + "heading_4_font_family": "inter", + "heading_4_font_size": 20, + "heading_4_font_weight": "semi-bold", + "heading_4_text_color": "zoOtT", + "heading_4_text_alignment": "left", + "heading_4_text_decoration": [ + false, + false, + false, + false + ], + "heading_5_font_family": "inter", + "heading_5_font_size": 16, + "heading_5_font_weight": "semi-bold", + "heading_5_text_color": "zoOtT", + "heading_5_text_alignment": "left", + "heading_5_text_decoration": [ + false, + false, + false, + false + ], + "heading_6_font_family": "inter", + "heading_6_font_size": 14, + "heading_6_font_weight": "semi-bold", + "heading_6_text_color": "zoOtT", + "heading_6_text_alignment": "left", + "heading_6_text_decoration": [ + false, + false, + false, + false + ], + "button_font_family": "inter", + "button_font_size": 12, + "button_font_weight": "semi-bold", + "button_alignment": "left", + "button_text_alignment": "center", + "button_width": "auto", + "button_background_color": "primary", + "button_text_color": "ElMaZ", + "button_border_color": "border", + "button_border_size": 0, + "button_border_radius": 6, + "button_vertical_padding": 10, + "button_horizontal_padding": 12, + "button_hover_background_color": "#4653e5", + "button_hover_text_color": "ElMaZ", + "button_hover_border_color": "border", + "button_active_background_color": "primary", + "button_active_text_color": "ElMaZ", + "button_active_border_color": "border", + "image_alignment": "left", + "image_max_width": 100, + "image_max_height": null, + "image_border_radius": 0, + "image_constraint": "contain", + "page_background_color": "#fafafa", + "page_background_file_id": null, + "page_background_mode": "tile", + "label_font_family": "inter", + "label_text_color": "zoOtT", + "label_font_size": 13, + "label_font_weight": "medium", + "input_font_family": "inter", + "input_font_size": 14, + "input_font_weight": "regular", + "input_text_color": "zoOtT", + "input_background_color": "#ffffff", + "input_border_color": "#d7d8d9", + "input_border_size": 1, + "input_border_radius": 6, + "input_vertical_padding": 12, + "input_horizontal_padding": 16, + "table_border_color": "border", + "table_border_size": 1, + "table_border_radius": 6, + "table_header_background_color": "#f7f7f7", + "table_header_text_color": "V6EVv", + "table_header_font_size": 13, + "table_header_font_weight": "semi-bold", + "table_header_font_family": "inter", + "table_header_text_alignment": "left", + "table_cell_background_color": "ElMaZ", + "table_cell_alternate_background_color": "ElMaZ", + "table_cell_alignment": "left", + "table_cell_vertical_padding": 18, + "table_cell_horizontal_padding": 24, + "table_vertical_separator_color": "#000000FF", + "table_vertical_separator_size": 0, + "table_horizontal_separator_color": "border", + "table_horizontal_separator_size": 1, + "link_font_family": "inter", + "link_font_size": 14, + "link_font_weight": "regular", + "link_text_alignment": "left", + "link_text_color": "primary", + "link_hover_text_color": "#4653e5", + "link_active_text_color": "primary", + "link_default_text_decoration": [ + true, + false, + false, + false + ], + "link_hover_text_decoration": [ + true, + false, + false, + false + ], + "link_active_text_decoration": [ + true, + false, + false, + false + ] + }, + "user_sources": [], + "favicon_file": null, + "login_page": null, + "id": 177, + "name": "Baserow theme", + "order": 1, + "type": "builder" + }, + { + "id": 175, + "name": "Baserow database", + "order": 2, + "type": "database", + "tables": [ + { + "id": 738, + "name": "Tasks", + "order": 1, + "fields": [ + { + "id": 7204, + "type": "text", + "name": "Name", + "description": null, + "order": 0, + "primary": true, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "text_default": "" + }, + { + "id": 7205, + "type": "single_select", + "name": "Status", + "description": null, + "order": 1, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "select_options": [ + { + "id": 3211, + "value": "In progress", + "color": "light-cyan", + "order": 0 + }, + { + "id": 3212, + "value": "Ready", + "color": "light-green", + "order": 1 + }, + { + "id": 3213, + "value": "On hold", + "color": "light-yellow", + "order": 2 + }, + { + "id": 3214, + "value": "Blocked", + "color": "light-brown", + "order": 3 + } + ] + }, + { + "id": 7206, + "type": "link_row", + "name": "Client", + "description": null, + "order": 2, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "link_row_table_id": 739, + "link_row_related_field_id": null, + "link_row_limit_selection_view_id": null, + "has_related_field": false + }, + { + "id": 7209, + "type": "formula", + "name": "Status color", + "description": null, + "order": 3, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "date_show_tzinfo": null, + "date_format": null, + "duration_format": null, + "number_prefix": "", + "error": null, + "date_time_format": null, + "number_suffix": "", + "nullable": false, + "number_separator": "", + "number_decimal_places": null, + "date_force_timezone": null, + "date_include_time": null, + "array_formula_type": null, + "formula": "if(field('Status') = 'In progress', 'ECFBFD',\nif(field('Status') = 'Ready', 'ECFCF1', \nif(field('Status') = 'On hold', 'F5F5F5', \nif(field('Status') = 'Blocked', 'FFF2F0',\n''))))", + "formula_type": "text" + } + ], + "views": [ + { + "id": 3286, + "type": "grid", + "name": "Grid", + "order": 1, + "ownership_type": "collaborative", + "owned_by": "bram@baserow.io", + "filter_type": "AND", + "filters_disabled": false, + "filters": [], + "filter_groups": [], + "sortings": [], + "group_bys": [], + "decorations": [], + "public": false, + "row_identifier_type": "id", + "row_height_size": "small", + "field_options": [ + { + "id": 27036, + "field_id": 7204, + "width": 294, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 27037, + "field_id": 7205, + "width": 248, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 27038, + "field_id": 7206, + "width": 200, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 27039, + "field_id": 7209, + "width": 200, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + } + ] + } + ], + "rows": [ + { + "id": 1, + "order": "1.00000000000000000000", + "created_on": "2025-03-14T12:47:43.944761+00:00", + "updated_on": "2025-03-14T12:50:42.758525+00:00", + "created_by": "bram@baserow.io", + "last_modified_by": "bram@baserow.io", + "field_7204": "Facilitate Case Study Discussions", + "field_7205": 3211, + "field_7206": [ + 1 + ], + "field_7209": null + }, + { + "id": 2, + "order": "2.00000000000000000000", + "created_on": "2025-03-14T12:47:43.944821+00:00", + "updated_on": "2025-03-14T12:50:45.243685+00:00", + "created_by": "bram@baserow.io", + "last_modified_by": "bram@baserow.io", + "field_7204": "Design Interactive Workshops", + "field_7205": 3212, + "field_7206": [ + 2 + ], + "field_7209": null + }, + { + "id": 3, + "order": "3.00000000000000000000", + "created_on": "2025-03-14T12:48:20.544029+00:00", + "updated_on": "2025-03-14T12:50:47.917272+00:00", + "created_by": "bram@baserow.io", + "last_modified_by": "bram@baserow.io", + "field_7204": "Facilitate Case Study Discussions", + "field_7205": 3213, + "field_7206": [ + 3 + ], + "field_7209": null + }, + { + "id": 4, + "order": "4.00000000000000000000", + "created_on": "2025-03-14T12:48:21.131545+00:00", + "updated_on": "2025-03-14T12:50:50.161461+00:00", + "created_by": "bram@baserow.io", + "last_modified_by": "bram@baserow.io", + "field_7204": "Design Interactive Workshops", + "field_7205": 3214, + "field_7206": [ + 4 + ], + "field_7209": null + }, + { + "id": 5, + "order": "5.00000000000000000000", + "created_on": "2025-03-14T12:48:21.638510+00:00", + "updated_on": "2025-03-14T12:50:52.369005+00:00", + "created_by": "bram@baserow.io", + "last_modified_by": "bram@baserow.io", + "field_7204": "Facilitate Case Study Discussions", + "field_7205": 3211, + "field_7206": [ + 5 + ], + "field_7209": null + }, + { + "id": 6, + "order": "6.00000000000000000000", + "created_on": "2025-03-14T12:48:31.532384+00:00", + "updated_on": "2025-03-14T12:50:54.683754+00:00", + "created_by": "bram@baserow.io", + "last_modified_by": "bram@baserow.io", + "field_7204": "Design Interactive Workshops", + "field_7205": 3212, + "field_7206": [ + 6 + ], + "field_7209": null + } + ], + "data_sync": null + }, + { + "id": 739, + "name": "Client", + "order": 2, + "fields": [ + { + "id": 7207, + "type": "text", + "name": "Name", + "description": null, + "order": 0, + "primary": true, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "text_default": "" + }, + { + "id": 7208, + "type": "long_text", + "name": "Notes", + "description": null, + "order": 3, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "long_text_enable_rich_text": false + } + ], + "views": [ + { + "id": 3287, + "type": "grid", + "name": "Grid", + "order": 1, + "ownership_type": "collaborative", + "owned_by": "bram@baserow.io", + "filter_type": "AND", + "filters_disabled": false, + "filters": [], + "filter_groups": [], + "sortings": [], + "group_bys": [], + "decorations": [], + "public": false, + "row_identifier_type": "id", + "row_height_size": "small", + "field_options": [ + { + "id": 27040, + "field_id": 7207, + "width": 200, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 27041, + "field_id": 7208, + "width": 457, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + } + ] + } + ], + "rows": [ + { + "id": 1, + "order": "1.00000000000000000000", + "created_on": "2025-03-14T12:48:36.629478+00:00", + "updated_on": "2025-03-14T12:49:27.285052+00:00", + "created_by": "bram@baserow.io", + "last_modified_by": "bram@baserow.io", + "field_7207": "Ferrari", + "field_7208": "Ferrari is a prestigious Italian luxury sports car manufacturer known for their iconic red vehicles with sleek designs and powerful engines. With a history dating back to 1939, Ferrari has become synonymous with speed, performance, and exclusivity. Their cars are revered for their precision engineering and unmatched driving experience." + }, + { + "id": 2, + "order": "2.00000000000000000000", + "created_on": "2025-03-14T12:48:36.629532+00:00", + "updated_on": "2025-03-14T12:49:28.295210+00:00", + "created_by": "bram@baserow.io", + "last_modified_by": "bram@baserow.io", + "field_7207": "Facebook", + "field_7208": "Facebook is a popular social networking platform that allows users to connect with friends and family, share updates, photos, and videos, and join groups or events. With over 2 billion active users, Facebook has become a hub for communication, networking, advertising, and staying connected with others around the world." + }, + { + "id": 3, + "order": "3.00000000000000000000", + "created_on": "2025-03-14T12:48:45.278577+00:00", + "updated_on": "2025-03-14T12:49:29.314092+00:00", + "created_by": "bram@baserow.io", + "last_modified_by": "bram@baserow.io", + "field_7207": "General Electric", + "field_7208": "General Electric, commonly known as GE, is a multinational conglomerate based in the United States. Founded in 1892, the company specializes in areas such as aviation, healthcare, power, and renewable energy. GE is known for its innovative technology and has a global presence in over 180 countries." + }, + { + "id": 4, + "order": "4.00000000000000000000", + "created_on": "2025-03-14T12:48:45.278647+00:00", + "updated_on": "2025-03-14T12:49:30.250861+00:00", + "created_by": "bram@baserow.io", + "last_modified_by": "bram@baserow.io", + "field_7207": "Pizza Hut", + "field_7208": "Pizza Hut is a popular American restaurant chain known for its delicious pizza offerings. With over 18,000 locations worldwide, Pizza Hut is a favorite destination for families and pizza lovers alike. With a wide variety of toppings, crust options, and sides, Pizza Hut offers something for everyone to enjoy." + }, + { + "id": 5, + "order": "5.00000000000000000000", + "created_on": "2025-03-14T12:48:45.278688+00:00", + "updated_on": "2025-03-14T12:49:31.172965+00:00", + "created_by": "bram@baserow.io", + "last_modified_by": "bram@baserow.io", + "field_7207": "Nintendo", + "field_7208": "Nintendo is a Japanese multinational consumer electronics and video game company known for creating iconic games and consoles such as Mario, Zelda, and the Nintendo Switch. Founded in 1889, Nintendo continues to innovate and delight gamers around the world with its colorful and imaginative gaming experiences." + }, + { + "id": 6, + "order": "6.00000000000000000000", + "created_on": "2025-03-14T12:48:45.278726+00:00", + "updated_on": "2025-03-14T12:49:32.192236+00:00", + "created_by": "bram@baserow.io", + "last_modified_by": "bram@baserow.io", + "field_7207": "McDonalds", + "field_7208": "McDonald's is a well-known fast food chain that offers a wide range of menu options, including burgers, fries, chicken sandwiches, and breakfast items. With a focus on convenience and affordability, McDonald's has become a popular choice for quick meals and snacks for people of all ages around the world." + } + ], + "data_sync": null + } + ] + } + ] +} diff --git a/backend/templates/ab_baserow_theme.zip b/backend/templates/ab_baserow_theme.zip new file mode 100644 index 000000000..15cb0ecb3 Binary files /dev/null and b/backend/templates/ab_baserow_theme.zip differ diff --git a/backend/templates/ab_eclipse_theme.json b/backend/templates/ab_eclipse_theme.json new file mode 100644 index 000000000..df727bed0 --- /dev/null +++ b/backend/templates/ab_eclipse_theme.json @@ -0,0 +1,4930 @@ +{ + "baserow_template_version": 1, + "name": "Eclipse Theme", + "icon": "", + "keywords": [ + "application", + "builder", + "theme", + "eclipse" + ], + "categories": [ + "Application Themes" + ], + "open_application": 178, + "export": [ + { + "pages": [ + { + "id": 216, + "name": "__shared__", + "order": 1, + "path": "__shared__", + "path_params": [], + "query_params": [], + "shared": true, + "elements": [ + { + "id": 3391, + "order": "0.33333333333333331483", + "type": "menu", + "parent_element_id": 3389, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "menu": { + "link_font_size": 13, + "link_text_color": "ElMaZ", + "link_font_weight": "semi-bold", + "button_border_size": 1, + "link_hover_text_color": "ElMaZ", + "link_active_text_color": "ElMaZ", + "button_background_color": "zoOtT", + "link_hover_text_decoration": [ + false, + false, + false, + false + ], + "link_active_text_decoration": [ + false, + false, + false, + false + ], + "link_default_text_decoration": [ + false, + false, + false, + false + ], + "button_hover_background_color": "#1b1d25", + "button_active_background_color": "zoOtT" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 8, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 8, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "orientation": "horizontal", + "alignment": "right", + "menu_items": [ + { + "id": 8, + "variant": "link", + "type": "link", + "menu_item_order": 0, + "uid": "8ba013be-494a-4a06-8917-a8767c401ad2", + "name": "Page 1", + "navigation_type": "page", + "navigate_to_page_id": null, + "navigate_to_url": "", + "page_parameters": [], + "query_parameters": [], + "parent_menu_item": null, + "target": "self", + "children": [] + }, + { + "id": 9, + "variant": "link", + "type": "link", + "menu_item_order": 1, + "uid": "bbfd8ca3-a0cd-489e-be09-cd1d46efb14a", + "name": "Sub page 1", + "navigation_type": "page", + "navigate_to_page_id": 217, + "navigate_to_url": "", + "page_parameters": [], + "query_parameters": [], + "parent_menu_item": 8, + "target": "self", + "children": [] + }, + { + "id": 10, + "variant": "link", + "type": "link", + "menu_item_order": 2, + "uid": "b38bf885-f808-45ee-9c50-36d92f7d1d39", + "name": "Page 2", + "navigation_type": "page", + "navigate_to_page_id": 217, + "navigate_to_url": "", + "page_parameters": [], + "query_parameters": [], + "parent_menu_item": null, + "target": "self", + "children": [] + }, + { + "id": 11, + "variant": "link", + "type": "link", + "menu_item_order": 3, + "uid": "df9febeb-2f8b-49f6-9469-d8b44f28f1b0", + "name": "Sub page 2", + "navigation_type": "page", + "navigate_to_page_id": 217, + "navigate_to_url": "", + "page_parameters": [], + "query_parameters": [], + "parent_menu_item": 8, + "target": "self", + "children": [] + }, + { + "id": 12, + "variant": "link", + "type": "link", + "menu_item_order": 4, + "uid": "ad8260e4-e1b9-4cfc-9eb3-c2cdf8f6f1f1", + "name": "Sub page 3", + "navigation_type": "page", + "navigate_to_page_id": 217, + "navigate_to_url": "", + "page_parameters": [], + "query_parameters": [], + "parent_menu_item": 8, + "target": "self", + "children": [] + }, + { + "id": 13, + "variant": "link", + "type": "link", + "menu_item_order": 5, + "uid": "be62d7f3-f6be-44a9-9c75-5866bc51c30b", + "name": "Page 3", + "navigation_type": "page", + "navigate_to_page_id": 217, + "navigate_to_url": "", + "page_parameters": [], + "query_parameters": [], + "parent_menu_item": null, + "target": "self", + "children": [] + }, + { + "id": 14, + "variant": "link", + "type": "button", + "menu_item_order": 6, + "uid": "0cbdfe6e-344e-427f-86c7-450f48bb5f21", + "name": "Contact us", + "navigation_type": "page", + "navigate_to_page_id": null, + "navigate_to_url": "", + "page_parameters": [], + "query_parameters": [], + "parent_menu_item": null, + "target": "self", + "children": [] + } + ] + }, + { + "id": 3396, + "order": "0.50000000000000000000", + "type": "text", + "parent_element_id": 3393, + "place_in_container": "2", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 15, + "body_text_color": "#ffffff", + "body_font_weight": "semi-bold" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 20, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Newsletter'", + "format": "plain" + }, + { + "id": 3397, + "order": "0.66666666666666662966", + "type": "text", + "parent_element_id": 3393, + "place_in_container": "2", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 13, + "body_text_color": "#ffffff" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Signup for our newsletter by filling out your email address.'", + "format": "plain" + }, + { + "id": 3389, + "order": "1.00000000000000000000", + "type": "header", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 20, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "medium", + "style_width_child": "normal", + "share_type": "all", + "pages": [] + }, + { + "id": 3392, + "order": "1.00000000000000000000", + "type": "simple_container", + "parent_element_id": 3390, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "medium" + }, + { + "id": 3393, + "order": "1.00000000000000000000", + "type": "column", + "parent_element_id": 3392, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "column_amount": 3, + "column_gap": 20, + "alignment": "top" + }, + { + "id": 3394, + "order": "1.00000000000000000000", + "type": "form_container", + "parent_element_id": 3393, + "place_in_container": "2", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "button": { + "button_alignment": "right" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "submit_button_label": "'Submit'", + "reset_initial_values_post_submission": false + }, + { + "id": 3395, + "order": "1.00000000000000000000", + "type": "input_text", + "parent_element_id": 3394, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "input": { + "input_text_color": "ElMaZ" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "label": "", + "required": true, + "validation_type": "email", + "placeholder": "'Your email address...'", + "default_value": "", + "is_multiline": false, + "rows": 3, + "input_type": "text" + }, + { + "id": 3398, + "order": "1.00000000000000000000", + "type": "text", + "parent_element_id": 3393, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 15, + "body_text_color": "#ffffff", + "body_font_weight": "semi-bold" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 20, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Quick links'", + "format": "plain" + }, + { + "id": 3399, + "order": "1.00000000000000000000", + "type": "text", + "parent_element_id": 3393, + "place_in_container": "1", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 15, + "body_text_color": "#ffffff", + "body_font_weight": "semi-bold" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 20, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Community'", + "format": "plain" + }, + { + "id": 3390, + "order": "2.00000000000000000000", + "type": "footer", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 30, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 30, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "color", + "style_background_color": "zoOtT", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "full", + "style_width_child": "normal", + "share_type": "all", + "pages": [] + }, + { + "id": 3400, + "order": "2.00000000000000000000", + "type": "link", + "parent_element_id": 3393, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "link": { + "link_font_size": 13, + "link_text_color": "#f2f2f2", + "link_font_weight": "medium", + "link_hover_text_color": "#f2f2f2", + "link_active_text_color": "#f2f2f2" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 12, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "navigation_type": "page", + "navigate_to_page_id": 217, + "page_parameters": [], + "query_parameters": [], + "navigate_to_url": "", + "target": "self", + "value": "'About us'", + "variant": "link" + }, + { + "id": 3401, + "order": "2.00000000000000000000", + "type": "link", + "parent_element_id": 3393, + "place_in_container": "1", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "link": { + "link_font_size": 13, + "link_text_color": "#f2f2f2", + "link_font_weight": "medium", + "link_hover_text_color": "#f2f2f2", + "link_active_text_color": "#f2f2f2" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 12, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "navigation_type": "page", + "navigate_to_page_id": 217, + "page_parameters": [], + "query_parameters": [], + "navigate_to_url": "", + "target": "self", + "value": "'Documents'", + "variant": "link" + }, + { + "id": 3402, + "order": "3.00000000000000000000", + "type": "link", + "parent_element_id": 3393, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "link": { + "link_font_size": 13, + "link_text_color": "#f2f2f2", + "link_font_weight": "medium", + "link_hover_text_color": "#f2f2f2", + "link_active_text_color": "#f2f2f2" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 12, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "navigation_type": "page", + "navigate_to_page_id": 217, + "page_parameters": [], + "query_parameters": [], + "navigate_to_url": "", + "target": "self", + "value": "'Contact us'", + "variant": "link" + }, + { + "id": 3403, + "order": "3.00000000000000000000", + "type": "link", + "parent_element_id": 3393, + "place_in_container": "1", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "link": { + "link_font_size": 13, + "link_text_color": "#f2f2f2", + "link_font_weight": "medium", + "link_hover_text_color": "#f2f2f2", + "link_active_text_color": "#f2f2f2" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 12, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "navigation_type": "page", + "navigate_to_page_id": 217, + "page_parameters": [], + "query_parameters": [], + "navigate_to_url": "", + "target": "self", + "value": "'Support'", + "variant": "link" + }, + { + "id": 3404, + "order": "4.00000000000000000000", + "type": "link", + "parent_element_id": 3393, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "link": { + "link_font_size": 13, + "link_text_color": "#f2f2f2", + "link_font_weight": "medium", + "link_hover_text_color": "#f2f2f2", + "link_active_text_color": "#f2f2f2" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 12, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "navigation_type": "page", + "navigate_to_page_id": 217, + "page_parameters": [], + "query_parameters": [], + "navigate_to_url": "", + "target": "self", + "value": "'Career'", + "variant": "link" + }, + { + "id": 3405, + "order": "4.00000000000000000000", + "type": "link", + "parent_element_id": 3393, + "place_in_container": "1", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "link": { + "link_font_size": 13, + "link_text_color": "#f2f2f2", + "link_font_weight": "medium", + "link_hover_text_color": "#f2f2f2", + "link_active_text_color": "#f2f2f2" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 12, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "navigation_type": "page", + "navigate_to_page_id": 217, + "page_parameters": [], + "query_parameters": [], + "navigate_to_url": "", + "target": "self", + "value": "'FAQ'", + "variant": "link" + }, + { + "id": 3406, + "order": "5.00000000000000000000", + "type": "link", + "parent_element_id": 3393, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "link": { + "link_font_size": 13, + "link_text_color": "#f2f2f2", + "link_font_weight": "medium", + "link_hover_text_color": "#f2f2f2", + "link_active_text_color": "#f2f2f2" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 12, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "navigation_type": "page", + "navigate_to_page_id": 217, + "page_parameters": [], + "query_parameters": [], + "navigate_to_url": "", + "target": "self", + "value": "'Become a partner'", + "variant": "link" + }, + { + "id": 3407, + "order": "5.00000000000000000000", + "type": "link", + "parent_element_id": 3393, + "place_in_container": "1", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "link": { + "link_font_size": 13, + "link_text_color": "#f2f2f2", + "link_font_weight": "medium", + "link_hover_text_color": "#f2f2f2", + "link_active_text_color": "#f2f2f2" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 12, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "navigation_type": "page", + "navigate_to_page_id": 217, + "page_parameters": [], + "query_parameters": [], + "navigate_to_url": "", + "target": "self", + "value": "'Privacy policy'", + "variant": "link" + }, + { + "id": 3408, + "order": "6.00000000000000000000", + "type": "link", + "parent_element_id": 3393, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "link": { + "link_font_size": 13, + "link_text_color": "#f2f2f2", + "link_font_weight": "medium", + "link_hover_text_color": "#f2f2f2", + "link_active_text_color": "#f2f2f2" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 12, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "navigation_type": "page", + "navigate_to_page_id": 217, + "page_parameters": [], + "query_parameters": [], + "navigate_to_url": "", + "target": "self", + "value": "'Sign in'", + "variant": "link" + }, + { + "id": 3409, + "order": "6.00000000000000000000", + "type": "link", + "parent_element_id": 3393, + "place_in_container": "1", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "link": { + "link_font_size": 13, + "link_text_color": "#f2f2f2", + "link_font_weight": "medium", + "link_hover_text_color": "#f2f2f2", + "link_active_text_color": "#f2f2f2" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 12, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "navigation_type": "page", + "navigate_to_page_id": 217, + "page_parameters": [], + "query_parameters": [], + "navigate_to_url": "", + "target": "self", + "value": "'Blog'", + "variant": "link" + }, + { + "id": 3410, + "order": "7.00000000000000000000", + "type": "link", + "parent_element_id": 3393, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "link": { + "link_font_size": 13, + "link_text_color": "#f2f2f2", + "link_font_weight": "medium", + "link_hover_text_color": "#f2f2f2", + "link_active_text_color": "#f2f2f2" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 12, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "navigation_type": "page", + "navigate_to_page_id": 217, + "page_parameters": [], + "query_parameters": [], + "navigate_to_url": "", + "target": "self", + "value": "'Sign up'", + "variant": "link" + }, + { + "id": 3411, + "order": "7.00000000000000000000", + "type": "link", + "parent_element_id": 3393, + "place_in_container": "1", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "link": { + "link_font_size": 13, + "link_text_color": "#f2f2f2", + "link_font_weight": "medium", + "link_hover_text_color": "#f2f2f2", + "link_active_text_color": "#f2f2f2" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 12, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "navigation_type": "page", + "navigate_to_page_id": 217, + "page_parameters": [], + "query_parameters": [], + "navigate_to_url": "", + "target": "self", + "value": "'Terms & conditions'", + "variant": "link" + } + ], + "data_sources": [], + "workflow_actions": [ + { + "id": 316, + "type": "notification", + "order": 1, + "page_id": 216, + "element_id": 3391, + "event": "0cbdfe6e-344e-427f-86c7-450f48bb5f21_click", + "title": "'Show contact form'", + "description": "'Show contact form'" + }, + { + "id": 317, + "type": "notification", + "order": 1, + "page_id": 216, + "element_id": 3394, + "event": "submit", + "title": "'Newsletter'", + "description": "'Signup for newsletter'" + } + ], + "visibility": "all", + "role_type": "allow_all", + "roles": [] + }, + { + "id": 217, + "name": "Examples", + "order": 1, + "path": "/", + "path_params": [], + "query_params": [], + "shared": false, + "elements": [ + { + "id": 3446, + "order": "0.50000000000000000000", + "type": "text", + "parent_element_id": 3435, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 13, + "body_text_color": "#ffffff", + "body_font_weight": "medium" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 4, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Secondary'", + "format": "plain" + }, + { + "id": 3447, + "order": "0.66666666666666662966", + "type": "text", + "parent_element_id": 3436, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 13, + "body_font_weight": "medium" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 4, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Border'", + "format": "plain" + }, + { + "id": 3448, + "order": "0.66666666666666662966", + "type": "text", + "parent_element_id": 3440, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 13, + "body_text_color": "ElMaZ", + "body_font_weight": "medium" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 4, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Custom 2'", + "format": "plain" + }, + { + "id": 3416, + "order": "1.00000000000000000000", + "type": "heading", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "heading_2_font_weight": "semi-bold" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 20, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "medium", + "style_width_child": "normal", + "value": "'Recent projects'", + "level": 2 + }, + { + "id": 3417, + "order": "1.00000000000000000000", + "type": "iframe", + "parent_element_id": 3413, + "place_in_container": "1", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 20, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "source_type": "url", + "url": "'https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d2437.5900465602517!2d4.825077027115522!3d52.341582849423204!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x47c5e18eae78495d%3A0xc6ec111aab4c79fe!2sB.%20Amsterdam!5e0!3m2!1sen!2snl!4v1741957273376!5m2!1sen!2snl\" width=\"600\" height=\"450\" style=\"border:0;'", + "embed": "", + "height": 268 + }, + { + "id": 3430, + "order": "1.00000000000000000000", + "type": "simple_container", + "parent_element_id": 3412, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 1, + "style_padding_top": 24, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 1, + "style_padding_bottom": 24, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 1, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 1, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 6, + "style_border_radius": 6, + "style_background": "color", + "style_background_color": "zoOtT", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal" + }, + { + "id": 3431, + "order": "1.00000000000000000000", + "type": "simple_container", + "parent_element_id": 3412, + "place_in_container": "1", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 1, + "style_padding_top": 24, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 1, + "style_padding_bottom": 24, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 1, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 1, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 6, + "style_border_radius": 6, + "style_background": "color", + "style_background_color": "zoOtT", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal" + }, + { + "id": 3432, + "order": "1.00000000000000000000", + "type": "simple_container", + "parent_element_id": 3412, + "place_in_container": "2", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 1, + "style_padding_top": 24, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 1, + "style_padding_bottom": 24, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 1, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 1, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 6, + "style_border_radius": 6, + "style_background": "color", + "style_background_color": "zoOtT", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal" + }, + { + "id": 3433, + "order": "1.00000000000000000000", + "type": "form_container", + "parent_element_id": 3413, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "button": { + "button_alignment": "right" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "submit_button_label": "'Submit'", + "reset_initial_values_post_submission": false + }, + { + "id": 3434, + "order": "1.00000000000000000000", + "type": "simple_container", + "parent_element_id": 3414, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 20, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 50, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "color", + "style_background_color": "primary", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal" + }, + { + "id": 3435, + "order": "1.00000000000000000000", + "type": "simple_container", + "parent_element_id": 3414, + "place_in_container": "1", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 20, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 50, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "color", + "style_background_color": "secondary", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal" + }, + { + "id": 3436, + "order": "1.00000000000000000000", + "type": "simple_container", + "parent_element_id": 3414, + "place_in_container": "2", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 20, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 50, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "color", + "style_background_color": "border", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal" + }, + { + "id": 3437, + "order": "1.00000000000000000000", + "type": "simple_container", + "parent_element_id": 3414, + "place_in_container": "3", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 20, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 50, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "color", + "style_background_color": "success", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal" + }, + { + "id": 3438, + "order": "1.00000000000000000000", + "type": "simple_container", + "parent_element_id": 3414, + "place_in_container": "4", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 20, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 50, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "color", + "style_background_color": "warning", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal" + }, + { + "id": 3439, + "order": "1.00000000000000000000", + "type": "simple_container", + "parent_element_id": 3414, + "place_in_container": "5", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 20, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 50, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "color", + "style_background_color": "error", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal" + }, + { + "id": 3440, + "order": "1.00000000000000000000", + "type": "simple_container", + "parent_element_id": 3415, + "place_in_container": "1", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 20, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 50, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "color", + "style_background_color": "zoOtT", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal" + }, + { + "id": 3443, + "order": "1.00000000000000000000", + "type": "input_text", + "parent_element_id": 3433, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "label": "'Your name'", + "required": true, + "validation_type": "any", + "placeholder": "'Enter your name here...'", + "default_value": "", + "is_multiline": false, + "rows": 3, + "input_type": "text" + }, + { + "id": 3449, + "order": "1.00000000000000000000", + "type": "heading", + "parent_element_id": 3430, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "heading_3_font_size": 16 + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 24, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Rebranding website'", + "level": 3 + }, + { + "id": 3450, + "order": "1.00000000000000000000", + "type": "text", + "parent_element_id": 3434, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 13, + "body_text_color": "#ffffff", + "body_font_weight": "medium" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 4, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Primary'", + "format": "plain" + }, + { + "id": 3451, + "order": "1.00000000000000000000", + "type": "text", + "parent_element_id": 3435, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_color": "#ffffff" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'#32CBFF'", + "format": "plain" + }, + { + "id": 3452, + "order": "1.00000000000000000000", + "type": "text", + "parent_element_id": 3437, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 13, + "body_font_weight": "medium" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 4, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Success'", + "format": "plain" + }, + { + "id": 3453, + "order": "1.00000000000000000000", + "type": "text", + "parent_element_id": 3442, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 13, + "body_text_color": "#ffffff", + "body_font_weight": "medium" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 4, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Custom 3'", + "format": "plain" + }, + { + "id": 3454, + "order": "1.50000000000000000000", + "type": "heading", + "parent_element_id": 3431, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "heading_3_font_size": 16 + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 24, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Customer research'", + "level": 3 + }, + { + "id": 3455, + "order": "1.50000000000000000000", + "type": "text", + "parent_element_id": 3441, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 13, + "body_text_color": "zoOtT", + "body_font_weight": "medium" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 4, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Custom 1'", + "format": "plain" + }, + { + "id": 3412, + "order": "2.00000000000000000000", + "type": "column", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 40, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "medium", + "style_width_child": "normal", + "column_amount": 3, + "column_gap": 24, + "alignment": "top" + }, + { + "id": 3418, + "order": "2.00000000000000000000", + "type": "text", + "parent_element_id": 3413, + "place_in_container": "1", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Visit us at: Streetname 100, The Netherlands'", + "format": "plain" + }, + { + "id": 3441, + "order": "2.00000000000000000000", + "type": "simple_container", + "parent_element_id": 3415, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 20, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 50, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "color", + "style_background_color": "ElMaZ", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal" + }, + { + "id": 3442, + "order": "2.00000000000000000000", + "type": "simple_container", + "parent_element_id": 3415, + "place_in_container": "2", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 20, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 50, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "color", + "style_background_color": "V6EVv", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal" + }, + { + "id": 3444, + "order": "2.00000000000000000000", + "type": "input_text", + "parent_element_id": 3433, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "label": "'Your email'", + "required": true, + "validation_type": "email", + "placeholder": "'Enter your email here...'", + "default_value": "", + "is_multiline": false, + "rows": 3, + "input_type": "text" + }, + { + "id": 3456, + "order": "2.00000000000000000000", + "type": "text", + "parent_element_id": 3430, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 11, + "body_text_color": "V6EVv" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 6, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Kick-off date'", + "format": "plain" + }, + { + "id": 3457, + "order": "2.00000000000000000000", + "type": "heading", + "parent_element_id": 3432, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "heading_3_font_size": 16 + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 24, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'App builder launch'", + "level": 3 + }, + { + "id": 3458, + "order": "2.00000000000000000000", + "type": "text", + "parent_element_id": 3434, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_color": "#ffffff" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'#4E70DA'", + "format": "plain" + }, + { + "id": 3459, + "order": "2.00000000000000000000", + "type": "text", + "parent_element_id": 3436, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12 + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'#2E3038'", + "format": "plain" + }, + { + "id": 3460, + "order": "2.00000000000000000000", + "type": "text", + "parent_element_id": 3438, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 13, + "body_font_weight": "medium" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 4, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Warning'", + "format": "plain" + }, + { + "id": 3461, + "order": "2.00000000000000000000", + "type": "text", + "parent_element_id": 3440, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_color": "ElMaZ" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'#181A24'", + "format": "plain" + }, + { + "id": 3462, + "order": "2.50000000000000000000", + "type": "text", + "parent_element_id": 3431, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 11, + "body_text_color": "V6EVv" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 6, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Kick-off date'", + "format": "plain" + }, + { + "id": 3419, + "order": "3.00000000000000000000", + "type": "heading", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "heading_2_font_weight": "semi-bold" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 20, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "medium", + "style_width_child": "normal", + "value": "'My tasks'", + "level": 2 + }, + { + "id": 3445, + "order": "3.00000000000000000000", + "type": "input_text", + "parent_element_id": 3433, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "label": "'Your question'", + "required": true, + "validation_type": "any", + "placeholder": "'Enter your question here...'", + "default_value": "", + "is_multiline": true, + "rows": 5, + "input_type": "text" + }, + { + "id": 3463, + "order": "3.00000000000000000000", + "type": "text", + "parent_element_id": 3430, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 16, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'2024-02-09'", + "format": "plain" + }, + { + "id": 3464, + "order": "3.00000000000000000000", + "type": "text", + "parent_element_id": 3432, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 11, + "body_text_color": "V6EVv" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 6, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Kick-off date'", + "format": "plain" + }, + { + "id": 3465, + "order": "3.00000000000000000000", + "type": "text", + "parent_element_id": 3437, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12 + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'#3BB273'", + "format": "plain" + }, + { + "id": 3466, + "order": "3.00000000000000000000", + "type": "text", + "parent_element_id": 3439, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 13, + "body_font_weight": "medium" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 4, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Error'", + "format": "plain" + }, + { + "id": 3467, + "order": "3.00000000000000000000", + "type": "text", + "parent_element_id": 3441, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_color": "zoOtT" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'#FFFFFF'", + "format": "plain" + }, + { + "id": 3468, + "order": "3.00000000000000000000", + "type": "text", + "parent_element_id": 3442, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_color": "#ffffff" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'#A9ADB5'", + "format": "plain" + }, + { + "id": 3469, + "order": "3.50000000000000000000", + "type": "text", + "parent_element_id": 3431, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 16, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'2024-03-15'", + "format": "plain" + }, + { + "id": 3420, + "order": "4.00000000000000000000", + "type": "table", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 40, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "medium", + "style_width_child": "normal", + "data_source_id": 383, + "items_per_page": 20, + "button_load_more_label": "", + "schema_property": null, + "property_options": [], + "fields": [ + { + "uid": "9738d833-ecbb-4c17-b036-d771ebada21d", + "name": "Name", + "type": "text", + "styles": {}, + "config": { + "value": "get('current_record.field_7210')" + } + }, + { + "uid": "c07ee14b-c187-4c3f-ae26-f5935c1ff89b", + "name": "Status", + "type": "tags", + "styles": {}, + "config": { + "values": "get('current_record.field_7211.value')", + "colors_is_formula": true, + "colors": "concat('#',get('current_record.field_7215'))" + } + }, + { + "uid": "dbebcfa4-3735-4d2d-89ec-2db1653fc482", + "name": "Client", + "type": "text", + "styles": {}, + "config": { + "value": "get('current_record.field_7212.*.value')" + } + } + ], + "orientation": { + "tablet": "horizontal", + "desktop": "horizontal", + "smartphone": "horizontal" + } + }, + { + "id": 3470, + "order": "4.00000000000000000000", + "type": "text", + "parent_element_id": 3430, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 11, + "body_text_color": "V6EVv" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 6, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Due date'", + "format": "plain" + }, + { + "id": 3471, + "order": "4.00000000000000000000", + "type": "text", + "parent_element_id": 3432, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 16, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'2024-04-07'", + "format": "plain" + }, + { + "id": 3472, + "order": "4.00000000000000000000", + "type": "text", + "parent_element_id": 3438, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12 + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'#E1BC29'", + "format": "plain" + }, + { + "id": 3473, + "order": "4.50000000000000000000", + "type": "text", + "parent_element_id": 3431, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 11, + "body_text_color": "V6EVv" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 6, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Due date'", + "format": "plain" + }, + { + "id": 3421, + "order": "5.00000000000000000000", + "type": "heading", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "heading_2_font_weight": "semi-bold" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 20, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "medium", + "style_width_child": "normal", + "value": "'Contact us'", + "level": 2 + }, + { + "id": 3474, + "order": "5.00000000000000000000", + "type": "text", + "parent_element_id": 3430, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 16, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'2024-02-16'", + "format": "plain" + }, + { + "id": 3475, + "order": "5.00000000000000000000", + "type": "text", + "parent_element_id": 3432, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 11, + "body_text_color": "V6EVv" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 6, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Due date'", + "format": "plain" + }, + { + "id": 3476, + "order": "5.00000000000000000000", + "type": "text", + "parent_element_id": 3439, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12 + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'#E15554'", + "format": "plain" + }, + { + "id": 3477, + "order": "5.50000000000000000000", + "type": "text", + "parent_element_id": 3431, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 16, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'2024-02-12'", + "format": "plain" + }, + { + "id": 3413, + "order": "6.00000000000000000000", + "type": "column", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 40, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "medium", + "style_width_child": "normal", + "column_amount": 2, + "column_gap": 40, + "alignment": "top" + }, + { + "id": 3478, + "order": "6.00000000000000000000", + "type": "text", + "parent_element_id": 3430, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 11, + "body_text_color": "V6EVv" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 6, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Label'", + "format": "plain" + }, + { + "id": 3479, + "order": "6.00000000000000000000", + "type": "text", + "parent_element_id": 3432, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 16, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'2024-04-12'", + "format": "plain" + }, + { + "id": 3422, + "order": "6.50000000000000000000", + "type": "heading", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "heading_2_font_weight": "semi-bold" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 20, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "medium", + "style_width_child": "normal", + "value": "'Colors'", + "level": 2 + }, + { + "id": 3480, + "order": "6.50000000000000000000", + "type": "text", + "parent_element_id": 3431, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 11, + "body_text_color": "V6EVv" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 6, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Label'", + "format": "plain" + }, + { + "id": 3414, + "order": "7.00000000000000000000", + "type": "column", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "medium", + "style_width_child": "normal", + "column_amount": 6, + "column_gap": 1, + "alignment": "top" + }, + { + "id": 3481, + "order": "7.00000000000000000000", + "type": "text", + "parent_element_id": 3430, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 16, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Value'", + "format": "plain" + }, + { + "id": 3482, + "order": "7.00000000000000000000", + "type": "text", + "parent_element_id": 3432, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 11, + "body_text_color": "V6EVv" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 6, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Label'", + "format": "plain" + }, + { + "id": 3415, + "order": "7.50000000000000000000", + "type": "column", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 40, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "medium", + "style_width_child": "normal", + "column_amount": 6, + "column_gap": 1, + "alignment": "top" + }, + { + "id": 3483, + "order": "7.50000000000000000000", + "type": "text", + "parent_element_id": 3431, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 16, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Value'", + "format": "plain" + }, + { + "id": 3423, + "order": "8.00000000000000000000", + "type": "heading", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "medium", + "style_width_child": "normal", + "value": "'Heading 1'", + "level": 1 + }, + { + "id": 3484, + "order": "8.00000000000000000000", + "type": "link", + "parent_element_id": 3430, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "button": { + "button_width": "full" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 10, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "navigation_type": "page", + "navigate_to_page_id": 217, + "page_parameters": [], + "query_parameters": [], + "navigate_to_url": "", + "target": "self", + "value": "'View tasks'", + "variant": "button" + }, + { + "id": 3485, + "order": "8.00000000000000000000", + "type": "text", + "parent_element_id": 3432, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 16, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Value'", + "format": "plain" + }, + { + "id": 3424, + "order": "9.00000000000000000000", + "type": "heading", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "medium", + "style_width_child": "normal", + "value": "'Heading 2'", + "level": 2 + }, + { + "id": 3486, + "order": "9.00000000000000000000", + "type": "link", + "parent_element_id": 3431, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "button": { + "button_width": "full" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 10, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "navigation_type": "page", + "navigate_to_page_id": 217, + "page_parameters": [], + "query_parameters": [], + "navigate_to_url": "", + "target": "self", + "value": "'View tasks'", + "variant": "button" + }, + { + "id": 3425, + "order": "10.00000000000000000000", + "type": "heading", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "medium", + "style_width_child": "normal", + "value": "'Heading 3'", + "level": 3 + }, + { + "id": 3487, + "order": "10.00000000000000000000", + "type": "link", + "parent_element_id": 3432, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "button": { + "button_width": "full" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 10, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "navigation_type": "page", + "navigate_to_page_id": 217, + "page_parameters": [], + "query_parameters": [], + "navigate_to_url": "", + "target": "self", + "value": "'View tasks'", + "variant": "button" + }, + { + "id": 3426, + "order": "11.00000000000000000000", + "type": "heading", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "medium", + "style_width_child": "normal", + "value": "'Heading 4'", + "level": 4 + }, + { + "id": 3427, + "order": "12.00000000000000000000", + "type": "heading", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "medium", + "style_width_child": "normal", + "value": "'Heading 5'", + "level": 5 + }, + { + "id": 3428, + "order": "13.00000000000000000000", + "type": "heading", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "medium", + "style_width_child": "normal", + "value": "'Heading 6'", + "level": 6 + }, + { + "id": 3429, + "order": "14.00000000000000000000", + "type": "text", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 40, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "medium", + "style_width_child": "normal", + "value": "'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque eu mollis purus. Integer ac bibendum metus. Morbi nunc eros, suscipit sed tristique vel, rutrum a nibh. In urna leo, pulvinar ac nunc vitae, vulputate pretium magna. Vivamus leo mauris, iaculis vel velit at, dapibus convallis magna. Sed tincidunt leo dui, vel viverra ex gravida eget. Pellentesque posuere scelerisque velit, in rutrum lorem vestibulum eleifend. Phasellus at consectetur urna, id bibendum neque. Fusce et metus magna.'", + "format": "plain" + } + ], + "data_sources": [ + { + "id": 383, + "name": "Tasks", + "order": "1.00000000000000000000", + "service": { + "id": 490, + "integration_id": 36, + "type": "local_baserow_list_rows", + "table_id": 740, + "view_id": null, + "sortings": [], + "search_query": "", + "filter_type": "AND", + "filters": [] + } + } + ], + "workflow_actions": [ + { + "id": 318, + "type": "notification", + "order": 1, + "page_id": 217, + "element_id": 3433, + "event": "submit", + "title": "'Thank you'", + "description": "'Thank youb for filling out the contact us form.'" + } + ], + "visibility": "all", + "role_type": "allow_all", + "roles": [] + } + ], + "integrations": [ + { + "id": 36, + "name": "Local Baserow", + "order": "1.00000000000000000000", + "type": "local_baserow", + "authorized_user": null + } + ], + "theme": { + "primary_color": "#4e70da", + "secondary_color": "#7cdedc", + "border_color": "#2e3038", + "main_success_color": "#3bb273", + "main_warning_color": "#e1bc29", + "main_error_color": "#e15554", + "custom_colors": [ + { + "name": "Custom 1", + "color": "#ffffff", + "value": "ElMaZ" + }, + { + "name": "Custom 2", + "color": "#181a24", + "value": "zoOtT" + }, + { + "name": "Custom 3", + "color": "#a9adb5", + "value": "V6EVv" + } + ], + "body_font_family": "inter", + "body_font_size": 14, + "body_font_weight": "regular", + "body_text_color": "ElMaZ", + "body_text_alignment": "left", + "heading_1_font_family": "inter", + "heading_1_font_size": 32, + "heading_1_font_weight": "bold", + "heading_1_text_color": "ElMaZ", + "heading_1_text_alignment": "left", + "heading_1_text_decoration": [ + false, + false, + false, + false + ], + "heading_2_font_family": "inter", + "heading_2_font_size": 24, + "heading_2_font_weight": "bold", + "heading_2_text_color": "ElMaZ", + "heading_2_text_alignment": "left", + "heading_2_text_decoration": [ + false, + false, + false, + false + ], + "heading_3_font_family": "inter", + "heading_3_font_size": 24, + "heading_3_font_weight": "semi-bold", + "heading_3_text_color": "ElMaZ", + "heading_3_text_alignment": "left", + "heading_3_text_decoration": [ + false, + false, + false, + false + ], + "heading_4_font_family": "inter", + "heading_4_font_size": 20, + "heading_4_font_weight": "semi-bold", + "heading_4_text_color": "ElMaZ", + "heading_4_text_alignment": "left", + "heading_4_text_decoration": [ + false, + false, + false, + false + ], + "heading_5_font_family": "inter", + "heading_5_font_size": 16, + "heading_5_font_weight": "semi-bold", + "heading_5_text_color": "ElMaZ", + "heading_5_text_alignment": "left", + "heading_5_text_decoration": [ + false, + false, + false, + false + ], + "heading_6_font_family": "inter", + "heading_6_font_size": 14, + "heading_6_font_weight": "semi-bold", + "heading_6_text_color": "transparent", + "heading_6_text_alignment": "left", + "heading_6_text_decoration": [ + false, + false, + false, + false + ], + "button_font_family": "inter", + "button_font_size": 12, + "button_font_weight": "semi-bold", + "button_alignment": "left", + "button_text_alignment": "center", + "button_width": "auto", + "button_background_color": "primary", + "button_text_color": "ElMaZ", + "button_border_color": "border", + "button_border_size": 0, + "button_border_radius": 8, + "button_vertical_padding": 10, + "button_horizontal_padding": 12, + "button_hover_background_color": "#4462bf", + "button_hover_text_color": "ElMaZ", + "button_hover_border_color": "border", + "button_active_background_color": "primary", + "button_active_text_color": "ElMaZ", + "button_active_border_color": "border", + "image_alignment": "left", + "image_max_width": 100, + "image_max_height": null, + "image_border_radius": 0, + "image_constraint": "contain", + "page_background_color": "#0e111d", + "page_background_file_id": null, + "page_background_mode": "tile", + "label_font_family": "inter", + "label_text_color": "ElMaZ", + "label_font_size": 13, + "label_font_weight": "semi-bold", + "input_font_family": "inter", + "input_font_size": 14, + "input_font_weight": "regular", + "input_text_color": "ElMaZ", + "input_background_color": "zoOtT", + "input_border_color": "border", + "input_border_size": 1, + "input_border_radius": 8, + "input_vertical_padding": 12, + "input_horizontal_padding": 16, + "table_border_color": "border", + "table_border_size": 1, + "table_border_radius": 6, + "table_header_background_color": "#22242e", + "table_header_text_color": "V6EVv", + "table_header_font_size": 13, + "table_header_font_weight": "semi-bold", + "table_header_font_family": "inter", + "table_header_text_alignment": "left", + "table_cell_background_color": "zoOtT", + "table_cell_alternate_background_color": "zoOtT", + "table_cell_alignment": "left", + "table_cell_vertical_padding": 18, + "table_cell_horizontal_padding": 24, + "table_vertical_separator_color": "border", + "table_vertical_separator_size": 0, + "table_horizontal_separator_color": "border", + "table_horizontal_separator_size": 1, + "link_font_family": "inter", + "link_font_size": 14, + "link_font_weight": "medium", + "link_text_alignment": "left", + "link_text_color": "secondary", + "link_hover_text_color": "#4dd2ff", + "link_active_text_color": "secondary", + "link_default_text_decoration": [ + true, + false, + false, + false + ], + "link_hover_text_decoration": [ + true, + false, + false, + false + ], + "link_active_text_decoration": [ + true, + false, + false, + false + ] + }, + "user_sources": [], + "favicon_file": null, + "login_page": null, + "id": 178, + "name": "Eclipse theme", + "order": 1, + "type": "builder" + }, + { + "id": 176, + "name": "Eclipse database", + "order": 2, + "type": "database", + "tables": [ + { + "id": 740, + "name": "Tasks", + "order": 1, + "fields": [ + { + "id": 7210, + "type": "text", + "name": "Name", + "description": null, + "order": 0, + "primary": true, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "text_default": "" + }, + { + "id": 7211, + "type": "single_select", + "name": "Status", + "description": null, + "order": 1, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "select_options": [ + { + "id": 3215, + "value": "In progress", + "color": "light-cyan", + "order": 0 + }, + { + "id": 3216, + "value": "Ready", + "color": "light-green", + "order": 1 + }, + { + "id": 3217, + "value": "On hold", + "color": "light-yellow", + "order": 2 + }, + { + "id": 3218, + "value": "Blocked", + "color": "light-brown", + "order": 3 + } + ] + }, + { + "id": 7212, + "type": "link_row", + "name": "Client", + "description": null, + "order": 2, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "link_row_table_id": 741, + "link_row_related_field_id": null, + "link_row_limit_selection_view_id": null, + "has_related_field": false + }, + { + "id": 7215, + "type": "formula", + "name": "Status color", + "description": null, + "order": 3, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "date_show_tzinfo": null, + "date_format": null, + "duration_format": null, + "number_prefix": "", + "error": null, + "date_time_format": null, + "number_suffix": "", + "nullable": false, + "number_separator": "", + "number_decimal_places": null, + "date_force_timezone": null, + "date_include_time": null, + "array_formula_type": null, + "formula": "if(field('Status') = 'In progress', '4e70da3d',\nif(field('Status') = 'Ready', '3bb2733d', \nif(field('Status') = 'On hold', 'a9adb53d', \nif(field('Status') = 'Blocked', 'e155543d',\n''))))", + "formula_type": "text" + } + ], + "views": [ + { + "id": 3288, + "type": "grid", + "name": "Grid", + "order": 1, + "ownership_type": "collaborative", + "owned_by": "bram@baserow.io", + "filter_type": "AND", + "filters_disabled": false, + "filters": [], + "filter_groups": [], + "sortings": [], + "group_bys": [], + "decorations": [], + "public": false, + "row_identifier_type": "id", + "row_height_size": "small", + "field_options": [ + { + "id": 27042, + "field_id": 7210, + "width": 294, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 27043, + "field_id": 7211, + "width": 248, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 27044, + "field_id": 7212, + "width": 200, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 27045, + "field_id": 7215, + "width": 200, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + } + ] + } + ], + "rows": [ + { + "id": 1, + "order": "1.00000000000000000000", + "created_on": "2025-03-14T12:47:43.944761+00:00", + "updated_on": "2025-03-14T12:50:42.758525+00:00", + "created_by": "bram@baserow.io", + "last_modified_by": "bram@baserow.io", + "field_7210": "Facilitate Case Study Discussions", + "field_7211": 3215, + "field_7212": [ + 1 + ], + "field_7215": null + }, + { + "id": 2, + "order": "2.00000000000000000000", + "created_on": "2025-03-14T12:47:43.944821+00:00", + "updated_on": "2025-03-14T12:50:45.243685+00:00", + "created_by": "bram@baserow.io", + "last_modified_by": "bram@baserow.io", + "field_7210": "Design Interactive Workshops", + "field_7211": 3216, + "field_7212": [ + 2 + ], + "field_7215": null + }, + { + "id": 3, + "order": "3.00000000000000000000", + "created_on": "2025-03-14T12:48:20.544029+00:00", + "updated_on": "2025-03-14T12:50:47.917272+00:00", + "created_by": "bram@baserow.io", + "last_modified_by": "bram@baserow.io", + "field_7210": "Facilitate Case Study Discussions", + "field_7211": 3217, + "field_7212": [ + 3 + ], + "field_7215": null + }, + { + "id": 4, + "order": "4.00000000000000000000", + "created_on": "2025-03-14T12:48:21.131545+00:00", + "updated_on": "2025-03-14T12:50:50.161461+00:00", + "created_by": "bram@baserow.io", + "last_modified_by": "bram@baserow.io", + "field_7210": "Design Interactive Workshops", + "field_7211": 3218, + "field_7212": [ + 4 + ], + "field_7215": null + }, + { + "id": 5, + "order": "5.00000000000000000000", + "created_on": "2025-03-14T12:48:21.638510+00:00", + "updated_on": "2025-03-14T12:50:52.369005+00:00", + "created_by": "bram@baserow.io", + "last_modified_by": "bram@baserow.io", + "field_7210": "Facilitate Case Study Discussions", + "field_7211": 3215, + "field_7212": [ + 5 + ], + "field_7215": null + }, + { + "id": 6, + "order": "6.00000000000000000000", + "created_on": "2025-03-14T12:48:31.532384+00:00", + "updated_on": "2025-03-14T12:50:54.683754+00:00", + "created_by": "bram@baserow.io", + "last_modified_by": "bram@baserow.io", + "field_7210": "Design Interactive Workshops", + "field_7211": 3216, + "field_7212": [ + 6 + ], + "field_7215": null + } + ], + "data_sync": null + }, + { + "id": 741, + "name": "Client", + "order": 2, + "fields": [ + { + "id": 7213, + "type": "text", + "name": "Name", + "description": null, + "order": 0, + "primary": true, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "text_default": "" + }, + { + "id": 7214, + "type": "long_text", + "name": "Notes", + "description": null, + "order": 3, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "long_text_enable_rich_text": false + } + ], + "views": [ + { + "id": 3289, + "type": "grid", + "name": "Grid", + "order": 1, + "ownership_type": "collaborative", + "owned_by": "bram@baserow.io", + "filter_type": "AND", + "filters_disabled": false, + "filters": [], + "filter_groups": [], + "sortings": [], + "group_bys": [], + "decorations": [], + "public": false, + "row_identifier_type": "id", + "row_height_size": "small", + "field_options": [ + { + "id": 27046, + "field_id": 7213, + "width": 200, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 27047, + "field_id": 7214, + "width": 457, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + } + ] + } + ], + "rows": [ + { + "id": 1, + "order": "1.00000000000000000000", + "created_on": "2025-03-14T12:48:36.629478+00:00", + "updated_on": "2025-03-14T12:49:27.285052+00:00", + "created_by": "bram@baserow.io", + "last_modified_by": "bram@baserow.io", + "field_7213": "Ferrari", + "field_7214": "Ferrari is a prestigious Italian luxury sports car manufacturer known for their iconic red vehicles with sleek designs and powerful engines. With a history dating back to 1939, Ferrari has become synonymous with speed, performance, and exclusivity. Their cars are revered for their precision engineering and unmatched driving experience." + }, + { + "id": 2, + "order": "2.00000000000000000000", + "created_on": "2025-03-14T12:48:36.629532+00:00", + "updated_on": "2025-03-14T12:49:28.295210+00:00", + "created_by": "bram@baserow.io", + "last_modified_by": "bram@baserow.io", + "field_7213": "Facebook", + "field_7214": "Facebook is a popular social networking platform that allows users to connect with friends and family, share updates, photos, and videos, and join groups or events. With over 2 billion active users, Facebook has become a hub for communication, networking, advertising, and staying connected with others around the world." + }, + { + "id": 3, + "order": "3.00000000000000000000", + "created_on": "2025-03-14T12:48:45.278577+00:00", + "updated_on": "2025-03-14T12:49:29.314092+00:00", + "created_by": "bram@baserow.io", + "last_modified_by": "bram@baserow.io", + "field_7213": "General Electric", + "field_7214": "General Electric, commonly known as GE, is a multinational conglomerate based in the United States. Founded in 1892, the company specializes in areas such as aviation, healthcare, power, and renewable energy. GE is known for its innovative technology and has a global presence in over 180 countries." + }, + { + "id": 4, + "order": "4.00000000000000000000", + "created_on": "2025-03-14T12:48:45.278647+00:00", + "updated_on": "2025-03-14T12:49:30.250861+00:00", + "created_by": "bram@baserow.io", + "last_modified_by": "bram@baserow.io", + "field_7213": "Pizza Hut", + "field_7214": "Pizza Hut is a popular American restaurant chain known for its delicious pizza offerings. With over 18,000 locations worldwide, Pizza Hut is a favorite destination for families and pizza lovers alike. With a wide variety of toppings, crust options, and sides, Pizza Hut offers something for everyone to enjoy." + }, + { + "id": 5, + "order": "5.00000000000000000000", + "created_on": "2025-03-14T12:48:45.278688+00:00", + "updated_on": "2025-03-14T12:49:31.172965+00:00", + "created_by": "bram@baserow.io", + "last_modified_by": "bram@baserow.io", + "field_7213": "Nintendo", + "field_7214": "Nintendo is a Japanese multinational consumer electronics and video game company known for creating iconic games and consoles such as Mario, Zelda, and the Nintendo Switch. Founded in 1889, Nintendo continues to innovate and delight gamers around the world with its colorful and imaginative gaming experiences." + }, + { + "id": 6, + "order": "6.00000000000000000000", + "created_on": "2025-03-14T12:48:45.278726+00:00", + "updated_on": "2025-03-14T12:49:32.192236+00:00", + "created_by": "bram@baserow.io", + "last_modified_by": "bram@baserow.io", + "field_7213": "McDonalds", + "field_7214": "McDonald's is a well-known fast food chain that offers a wide range of menu options, including burgers, fries, chicken sandwiches, and breakfast items. With a focus on convenience and affordability, McDonald's has become a popular choice for quick meals and snacks for people of all ages around the world." + } + ], + "data_sync": null + } + ] + } + ] +} diff --git a/backend/templates/ab_eclipse_theme.zip b/backend/templates/ab_eclipse_theme.zip new file mode 100644 index 000000000..15cb0ecb3 Binary files /dev/null and b/backend/templates/ab_eclipse_theme.zip differ diff --git a/backend/templates/ab_ivory_theme.json b/backend/templates/ab_ivory_theme.json new file mode 100644 index 000000000..9ba06b6c5 --- /dev/null +++ b/backend/templates/ab_ivory_theme.json @@ -0,0 +1,4929 @@ +{ + "baserow_template_version": 1, + "name": "Ivory Theme", + "icon": "", + "keywords": [ + "application", + "builder", + "theme", + "eclipse" + ], + "categories": [ + "Application Themes" + ], + "open_application": 181, + "export": [ + { + "pages": [ + { + "id": 218, + "name": "__shared__", + "order": 1, + "path": "__shared__", + "path_params": [], + "query_params": [], + "shared": true, + "elements": [ + { + "id": 3490, + "order": "0.33333333333333331483", + "type": "menu", + "parent_element_id": 3488, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "menu": { + "link_font_size": 13, + "link_text_color": "zoOtT", + "button_border_size": 1, + "link_hover_text_color": "#2f3135", + "link_active_text_color": "zoOtT", + "button_background_color": "ElMaZ", + "link_hover_text_decoration": [ + false, + false, + false, + false + ], + "link_active_text_decoration": [ + false, + false, + false, + false + ], + "link_default_text_decoration": [ + false, + false, + false, + false + ], + "button_hover_background_color": "#fafafa", + "button_active_background_color": "ElMaZ" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 8, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 8, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "orientation": "horizontal", + "alignment": "right", + "menu_items": [ + { + "id": 15, + "variant": "link", + "type": "link", + "menu_item_order": 0, + "uid": "8ba013be-494a-4a06-8917-a8767c401ad2", + "name": "Page 1", + "navigation_type": "page", + "navigate_to_page_id": null, + "navigate_to_url": "", + "page_parameters": [], + "query_parameters": [], + "parent_menu_item": null, + "target": "self", + "children": [] + }, + { + "id": 16, + "variant": "link", + "type": "link", + "menu_item_order": 1, + "uid": "bbfd8ca3-a0cd-489e-be09-cd1d46efb14a", + "name": "Sub page 1", + "navigation_type": "page", + "navigate_to_page_id": 219, + "navigate_to_url": "", + "page_parameters": [], + "query_parameters": [], + "parent_menu_item": 15, + "target": "self", + "children": [] + }, + { + "id": 17, + "variant": "link", + "type": "link", + "menu_item_order": 2, + "uid": "b38bf885-f808-45ee-9c50-36d92f7d1d39", + "name": "Page 2", + "navigation_type": "page", + "navigate_to_page_id": 219, + "navigate_to_url": "", + "page_parameters": [], + "query_parameters": [], + "parent_menu_item": null, + "target": "self", + "children": [] + }, + { + "id": 18, + "variant": "link", + "type": "link", + "menu_item_order": 3, + "uid": "df9febeb-2f8b-49f6-9469-d8b44f28f1b0", + "name": "Sub page 2", + "navigation_type": "page", + "navigate_to_page_id": 219, + "navigate_to_url": "", + "page_parameters": [], + "query_parameters": [], + "parent_menu_item": 15, + "target": "self", + "children": [] + }, + { + "id": 19, + "variant": "link", + "type": "link", + "menu_item_order": 4, + "uid": "ad8260e4-e1b9-4cfc-9eb3-c2cdf8f6f1f1", + "name": "Sub page 3", + "navigation_type": "page", + "navigate_to_page_id": 219, + "navigate_to_url": "", + "page_parameters": [], + "query_parameters": [], + "parent_menu_item": 15, + "target": "self", + "children": [] + }, + { + "id": 20, + "variant": "link", + "type": "link", + "menu_item_order": 5, + "uid": "be62d7f3-f6be-44a9-9c75-5866bc51c30b", + "name": "Page 3", + "navigation_type": "page", + "navigate_to_page_id": 219, + "navigate_to_url": "", + "page_parameters": [], + "query_parameters": [], + "parent_menu_item": null, + "target": "self", + "children": [] + }, + { + "id": 21, + "variant": "link", + "type": "button", + "menu_item_order": 6, + "uid": "0cbdfe6e-344e-427f-86c7-450f48bb5f21", + "name": "Contact us", + "navigation_type": "page", + "navigate_to_page_id": null, + "navigate_to_url": "", + "page_parameters": [], + "query_parameters": [], + "parent_menu_item": null, + "target": "self", + "children": [] + } + ] + }, + { + "id": 3495, + "order": "0.50000000000000000000", + "type": "text", + "parent_element_id": 3492, + "place_in_container": "2", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 15, + "body_text_color": "#ffffff", + "body_font_weight": "semi-bold" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 20, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Newsletter'", + "format": "plain" + }, + { + "id": 3496, + "order": "0.66666666666666662966", + "type": "text", + "parent_element_id": 3492, + "place_in_container": "2", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 13, + "body_text_color": "#ffffff" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Signup for our newsletter by filling out your email address.'", + "format": "plain" + }, + { + "id": 3488, + "order": "1.00000000000000000000", + "type": "header", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 20, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "medium", + "style_width_child": "normal", + "share_type": "all", + "pages": [] + }, + { + "id": 3491, + "order": "1.00000000000000000000", + "type": "simple_container", + "parent_element_id": 3489, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "medium" + }, + { + "id": 3492, + "order": "1.00000000000000000000", + "type": "column", + "parent_element_id": 3491, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "column_amount": 3, + "column_gap": 20, + "alignment": "top" + }, + { + "id": 3493, + "order": "1.00000000000000000000", + "type": "form_container", + "parent_element_id": 3492, + "place_in_container": "2", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "button": { + "button_alignment": "right" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "submit_button_label": "'Submit'", + "reset_initial_values_post_submission": false + }, + { + "id": 3494, + "order": "1.00000000000000000000", + "type": "input_text", + "parent_element_id": 3493, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "label": "", + "required": true, + "validation_type": "email", + "placeholder": "'Your email address...'", + "default_value": "", + "is_multiline": false, + "rows": 3, + "input_type": "text" + }, + { + "id": 3497, + "order": "1.00000000000000000000", + "type": "text", + "parent_element_id": 3492, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 15, + "body_text_color": "#ffffff", + "body_font_weight": "semi-bold" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 20, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Quick links'", + "format": "plain" + }, + { + "id": 3498, + "order": "1.00000000000000000000", + "type": "text", + "parent_element_id": 3492, + "place_in_container": "1", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 15, + "body_text_color": "#ffffff", + "body_font_weight": "semi-bold" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 20, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Community'", + "format": "plain" + }, + { + "id": 3489, + "order": "2.00000000000000000000", + "type": "footer", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 30, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 30, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "color", + "style_background_color": "zoOtT", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "full", + "style_width_child": "normal", + "share_type": "all", + "pages": [] + }, + { + "id": 3499, + "order": "2.00000000000000000000", + "type": "link", + "parent_element_id": 3492, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "link": { + "link_font_size": 13, + "link_text_color": "#f2f2f2", + "link_font_weight": "medium", + "link_hover_text_color": "#f2f2f2", + "link_active_text_color": "#f2f2f2" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 12, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "navigation_type": "page", + "navigate_to_page_id": 219, + "page_parameters": [], + "query_parameters": [], + "navigate_to_url": "", + "target": "self", + "value": "'About us'", + "variant": "link" + }, + { + "id": 3500, + "order": "2.00000000000000000000", + "type": "link", + "parent_element_id": 3492, + "place_in_container": "1", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "link": { + "link_font_size": 13, + "link_text_color": "#f2f2f2", + "link_font_weight": "medium", + "link_hover_text_color": "#f2f2f2", + "link_active_text_color": "#f2f2f2" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 12, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "navigation_type": "page", + "navigate_to_page_id": 219, + "page_parameters": [], + "query_parameters": [], + "navigate_to_url": "", + "target": "self", + "value": "'Documents'", + "variant": "link" + }, + { + "id": 3501, + "order": "3.00000000000000000000", + "type": "link", + "parent_element_id": 3492, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "link": { + "link_font_size": 13, + "link_text_color": "#f2f2f2", + "link_font_weight": "medium", + "link_hover_text_color": "#f2f2f2", + "link_active_text_color": "#f2f2f2" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 12, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "navigation_type": "page", + "navigate_to_page_id": 219, + "page_parameters": [], + "query_parameters": [], + "navigate_to_url": "", + "target": "self", + "value": "'Contact us'", + "variant": "link" + }, + { + "id": 3502, + "order": "3.00000000000000000000", + "type": "link", + "parent_element_id": 3492, + "place_in_container": "1", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "link": { + "link_font_size": 13, + "link_text_color": "#f2f2f2", + "link_font_weight": "medium", + "link_hover_text_color": "#f2f2f2", + "link_active_text_color": "#f2f2f2" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 12, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "navigation_type": "page", + "navigate_to_page_id": 219, + "page_parameters": [], + "query_parameters": [], + "navigate_to_url": "", + "target": "self", + "value": "'Support'", + "variant": "link" + }, + { + "id": 3503, + "order": "4.00000000000000000000", + "type": "link", + "parent_element_id": 3492, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "link": { + "link_font_size": 13, + "link_text_color": "#f2f2f2", + "link_font_weight": "medium", + "link_hover_text_color": "#f2f2f2", + "link_active_text_color": "#f2f2f2" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 12, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "navigation_type": "page", + "navigate_to_page_id": 219, + "page_parameters": [], + "query_parameters": [], + "navigate_to_url": "", + "target": "self", + "value": "'Career'", + "variant": "link" + }, + { + "id": 3504, + "order": "4.00000000000000000000", + "type": "link", + "parent_element_id": 3492, + "place_in_container": "1", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "link": { + "link_font_size": 13, + "link_text_color": "#f2f2f2", + "link_font_weight": "medium", + "link_hover_text_color": "#f2f2f2", + "link_active_text_color": "#f2f2f2" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 12, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "navigation_type": "page", + "navigate_to_page_id": 219, + "page_parameters": [], + "query_parameters": [], + "navigate_to_url": "", + "target": "self", + "value": "'FAQ'", + "variant": "link" + }, + { + "id": 3505, + "order": "5.00000000000000000000", + "type": "link", + "parent_element_id": 3492, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "link": { + "link_font_size": 13, + "link_text_color": "#f2f2f2", + "link_font_weight": "medium", + "link_hover_text_color": "#f2f2f2", + "link_active_text_color": "#f2f2f2" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 12, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "navigation_type": "page", + "navigate_to_page_id": 219, + "page_parameters": [], + "query_parameters": [], + "navigate_to_url": "", + "target": "self", + "value": "'Become a partner'", + "variant": "link" + }, + { + "id": 3506, + "order": "5.00000000000000000000", + "type": "link", + "parent_element_id": 3492, + "place_in_container": "1", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "link": { + "link_font_size": 13, + "link_text_color": "#f2f2f2", + "link_font_weight": "medium", + "link_hover_text_color": "#f2f2f2", + "link_active_text_color": "#f2f2f2" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 12, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "navigation_type": "page", + "navigate_to_page_id": 219, + "page_parameters": [], + "query_parameters": [], + "navigate_to_url": "", + "target": "self", + "value": "'Privacy policy'", + "variant": "link" + }, + { + "id": 3507, + "order": "6.00000000000000000000", + "type": "link", + "parent_element_id": 3492, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "link": { + "link_font_size": 13, + "link_text_color": "#f2f2f2", + "link_font_weight": "medium", + "link_hover_text_color": "#f2f2f2", + "link_active_text_color": "#f2f2f2" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 12, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "navigation_type": "page", + "navigate_to_page_id": 219, + "page_parameters": [], + "query_parameters": [], + "navigate_to_url": "", + "target": "self", + "value": "'Sign in'", + "variant": "link" + }, + { + "id": 3508, + "order": "6.00000000000000000000", + "type": "link", + "parent_element_id": 3492, + "place_in_container": "1", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "link": { + "link_font_size": 13, + "link_text_color": "#f2f2f2", + "link_font_weight": "medium", + "link_hover_text_color": "#f2f2f2", + "link_active_text_color": "#f2f2f2" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 12, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "navigation_type": "page", + "navigate_to_page_id": 219, + "page_parameters": [], + "query_parameters": [], + "navigate_to_url": "", + "target": "self", + "value": "'Blog'", + "variant": "link" + }, + { + "id": 3509, + "order": "7.00000000000000000000", + "type": "link", + "parent_element_id": 3492, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "link": { + "link_font_size": 13, + "link_text_color": "#f2f2f2", + "link_font_weight": "medium", + "link_hover_text_color": "#f2f2f2", + "link_active_text_color": "#f2f2f2" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 12, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "navigation_type": "page", + "navigate_to_page_id": 219, + "page_parameters": [], + "query_parameters": [], + "navigate_to_url": "", + "target": "self", + "value": "'Sign up'", + "variant": "link" + }, + { + "id": 3510, + "order": "7.00000000000000000000", + "type": "link", + "parent_element_id": 3492, + "place_in_container": "1", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "link": { + "link_font_size": 13, + "link_text_color": "#f2f2f2", + "link_font_weight": "medium", + "link_hover_text_color": "#f2f2f2", + "link_active_text_color": "#f2f2f2" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 12, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "navigation_type": "page", + "navigate_to_page_id": 219, + "page_parameters": [], + "query_parameters": [], + "navigate_to_url": "", + "target": "self", + "value": "'Terms & conditions'", + "variant": "link" + } + ], + "data_sources": [], + "workflow_actions": [ + { + "id": 319, + "type": "notification", + "order": 1, + "page_id": 218, + "element_id": 3490, + "event": "0cbdfe6e-344e-427f-86c7-450f48bb5f21_click", + "title": "'Show contact form'", + "description": "'Show contact form'" + }, + { + "id": 320, + "type": "notification", + "order": 1, + "page_id": 218, + "element_id": 3493, + "event": "submit", + "title": "'Newsletter'", + "description": "'Signup for newsletter'" + } + ], + "visibility": "all", + "role_type": "allow_all", + "roles": [] + }, + { + "id": 219, + "name": "Examples", + "order": 1, + "path": "/", + "path_params": [], + "query_params": [], + "shared": false, + "elements": [ + { + "id": 3545, + "order": "0.50000000000000000000", + "type": "text", + "parent_element_id": 3534, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 13, + "body_text_color": "#ffffff", + "body_font_weight": "medium" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 4, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Secondary'", + "format": "plain" + }, + { + "id": 3546, + "order": "0.66666666666666662966", + "type": "text", + "parent_element_id": 3535, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 13, + "body_font_weight": "medium" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 4, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Border'", + "format": "plain" + }, + { + "id": 3547, + "order": "0.66666666666666662966", + "type": "text", + "parent_element_id": 3539, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 13, + "body_text_color": "ElMaZ", + "body_font_weight": "medium" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 4, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Custom 2'", + "format": "plain" + }, + { + "id": 3515, + "order": "1.00000000000000000000", + "type": "heading", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "heading_2_font_weight": "semi-bold" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 20, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "medium", + "style_width_child": "normal", + "value": "'Recent projects'", + "level": 2 + }, + { + "id": 3516, + "order": "1.00000000000000000000", + "type": "iframe", + "parent_element_id": 3512, + "place_in_container": "1", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 20, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "source_type": "url", + "url": "'https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d2437.5900465602517!2d4.825077027115522!3d52.341582849423204!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x47c5e18eae78495d%3A0xc6ec111aab4c79fe!2sB.%20Amsterdam!5e0!3m2!1sen!2snl!4v1741957273376!5m2!1sen!2snl\" width=\"600\" height=\"450\" style=\"border:0;'", + "embed": "", + "height": 268 + }, + { + "id": 3529, + "order": "1.00000000000000000000", + "type": "simple_container", + "parent_element_id": 3511, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 1, + "style_padding_top": 24, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 1, + "style_padding_bottom": 24, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 1, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 1, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 6, + "style_border_radius": 6, + "style_background": "color", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal" + }, + { + "id": 3530, + "order": "1.00000000000000000000", + "type": "simple_container", + "parent_element_id": 3511, + "place_in_container": "1", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 1, + "style_padding_top": 24, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 1, + "style_padding_bottom": 24, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 1, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 1, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 6, + "style_border_radius": 6, + "style_background": "color", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal" + }, + { + "id": 3531, + "order": "1.00000000000000000000", + "type": "simple_container", + "parent_element_id": 3511, + "place_in_container": "2", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 1, + "style_padding_top": 24, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 1, + "style_padding_bottom": 24, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 1, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 1, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 6, + "style_border_radius": 6, + "style_background": "color", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal" + }, + { + "id": 3532, + "order": "1.00000000000000000000", + "type": "form_container", + "parent_element_id": 3512, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "button": { + "button_alignment": "right" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "submit_button_label": "'Submit'", + "reset_initial_values_post_submission": false + }, + { + "id": 3533, + "order": "1.00000000000000000000", + "type": "simple_container", + "parent_element_id": 3513, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 20, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 50, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "color", + "style_background_color": "primary", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal" + }, + { + "id": 3534, + "order": "1.00000000000000000000", + "type": "simple_container", + "parent_element_id": 3513, + "place_in_container": "1", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 20, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 50, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "color", + "style_background_color": "secondary", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal" + }, + { + "id": 3535, + "order": "1.00000000000000000000", + "type": "simple_container", + "parent_element_id": 3513, + "place_in_container": "2", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 20, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 50, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "color", + "style_background_color": "border", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal" + }, + { + "id": 3536, + "order": "1.00000000000000000000", + "type": "simple_container", + "parent_element_id": 3513, + "place_in_container": "3", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 20, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 50, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "color", + "style_background_color": "success", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal" + }, + { + "id": 3537, + "order": "1.00000000000000000000", + "type": "simple_container", + "parent_element_id": 3513, + "place_in_container": "4", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 20, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 50, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "color", + "style_background_color": "warning", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal" + }, + { + "id": 3538, + "order": "1.00000000000000000000", + "type": "simple_container", + "parent_element_id": 3513, + "place_in_container": "5", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 20, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 50, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "color", + "style_background_color": "error", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal" + }, + { + "id": 3539, + "order": "1.00000000000000000000", + "type": "simple_container", + "parent_element_id": 3514, + "place_in_container": "1", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 20, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 50, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "color", + "style_background_color": "zoOtT", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal" + }, + { + "id": 3542, + "order": "1.00000000000000000000", + "type": "input_text", + "parent_element_id": 3532, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "label": "'Your name'", + "required": true, + "validation_type": "any", + "placeholder": "'Enter your name here...'", + "default_value": "", + "is_multiline": false, + "rows": 3, + "input_type": "text" + }, + { + "id": 3548, + "order": "1.00000000000000000000", + "type": "heading", + "parent_element_id": 3529, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "heading_3_font_size": 16, + "heading_3_font_family": "arial", + "heading_3_font_weight": "bold" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 24, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Rebranding website'", + "level": 3 + }, + { + "id": 3549, + "order": "1.00000000000000000000", + "type": "text", + "parent_element_id": 3533, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 13, + "body_text_color": "#ffffff", + "body_font_weight": "medium" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 4, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Primary'", + "format": "plain" + }, + { + "id": 3550, + "order": "1.00000000000000000000", + "type": "text", + "parent_element_id": 3534, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_color": "#ffffff" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'#522B47'", + "format": "plain" + }, + { + "id": 3551, + "order": "1.00000000000000000000", + "type": "text", + "parent_element_id": 3536, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 13, + "body_font_weight": "medium" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 4, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Success'", + "format": "plain" + }, + { + "id": 3552, + "order": "1.00000000000000000000", + "type": "text", + "parent_element_id": 3541, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 13, + "body_text_color": "#ffffff", + "body_font_weight": "medium" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 4, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Custom 3'", + "format": "plain" + }, + { + "id": 3553, + "order": "1.50000000000000000000", + "type": "heading", + "parent_element_id": 3530, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "heading_3_font_size": 16, + "heading_3_font_family": "arial", + "heading_3_font_weight": "bold" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 24, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Customer research'", + "level": 3 + }, + { + "id": 3554, + "order": "1.50000000000000000000", + "type": "text", + "parent_element_id": 3540, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 13, + "body_font_weight": "medium" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 4, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Custom 1'", + "format": "plain" + }, + { + "id": 3511, + "order": "2.00000000000000000000", + "type": "column", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 40, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "medium", + "style_width_child": "normal", + "column_amount": 3, + "column_gap": 24, + "alignment": "top" + }, + { + "id": 3517, + "order": "2.00000000000000000000", + "type": "text", + "parent_element_id": 3512, + "place_in_container": "1", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Visit us at: Streetname 100, The Netherlands'", + "format": "plain" + }, + { + "id": 3540, + "order": "2.00000000000000000000", + "type": "simple_container", + "parent_element_id": 3514, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 20, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 50, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "color", + "style_background_color": "ElMaZ", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal" + }, + { + "id": 3541, + "order": "2.00000000000000000000", + "type": "simple_container", + "parent_element_id": 3514, + "place_in_container": "2", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 20, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 50, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "color", + "style_background_color": "V6EVv", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal" + }, + { + "id": 3543, + "order": "2.00000000000000000000", + "type": "input_text", + "parent_element_id": 3532, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "label": "'Your email'", + "required": true, + "validation_type": "email", + "placeholder": "'Enter your email here...'", + "default_value": "", + "is_multiline": false, + "rows": 3, + "input_type": "text" + }, + { + "id": 3555, + "order": "2.00000000000000000000", + "type": "text", + "parent_element_id": 3529, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 11, + "body_text_color": "V6EVv" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 6, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Kick-off date'", + "format": "plain" + }, + { + "id": 3556, + "order": "2.00000000000000000000", + "type": "heading", + "parent_element_id": 3531, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "heading_3_font_size": 16, + "heading_3_font_family": "arial", + "heading_3_font_weight": "bold" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 24, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'App builder launch'", + "level": 3 + }, + { + "id": 3557, + "order": "2.00000000000000000000", + "type": "text", + "parent_element_id": 3533, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_color": "#ffffff" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'#E8D6BC'", + "format": "plain" + }, + { + "id": 3558, + "order": "2.00000000000000000000", + "type": "text", + "parent_element_id": 3535, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12 + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'#EBE6E1'", + "format": "plain" + }, + { + "id": 3559, + "order": "2.00000000000000000000", + "type": "text", + "parent_element_id": 3537, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 13, + "body_font_weight": "medium" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 4, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Warning'", + "format": "plain" + }, + { + "id": 3560, + "order": "2.00000000000000000000", + "type": "text", + "parent_element_id": 3539, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_color": "ElMaZ" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'#191102'", + "format": "plain" + }, + { + "id": 3561, + "order": "2.50000000000000000000", + "type": "text", + "parent_element_id": 3530, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 11, + "body_text_color": "V6EVv" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 6, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Kick-off date'", + "format": "plain" + }, + { + "id": 3518, + "order": "3.00000000000000000000", + "type": "heading", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "heading_2_font_weight": "semi-bold" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 20, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "medium", + "style_width_child": "normal", + "value": "'My tasks'", + "level": 2 + }, + { + "id": 3544, + "order": "3.00000000000000000000", + "type": "input_text", + "parent_element_id": 3532, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "label": "'Your question'", + "required": true, + "validation_type": "any", + "placeholder": "'Enter your question here...'", + "default_value": "", + "is_multiline": true, + "rows": 5, + "input_type": "text" + }, + { + "id": 3562, + "order": "3.00000000000000000000", + "type": "text", + "parent_element_id": 3529, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 16, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'2024-02-09'", + "format": "plain" + }, + { + "id": 3563, + "order": "3.00000000000000000000", + "type": "text", + "parent_element_id": 3531, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 11, + "body_text_color": "V6EVv" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 6, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Kick-off date'", + "format": "plain" + }, + { + "id": 3564, + "order": "3.00000000000000000000", + "type": "text", + "parent_element_id": 3536, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12 + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'#618B25'", + "format": "plain" + }, + { + "id": 3565, + "order": "3.00000000000000000000", + "type": "text", + "parent_element_id": 3538, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 13, + "body_font_weight": "medium" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 4, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Error'", + "format": "plain" + }, + { + "id": 3566, + "order": "3.00000000000000000000", + "type": "text", + "parent_element_id": 3540, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12 + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'#ffffff'", + "format": "plain" + }, + { + "id": 3567, + "order": "3.00000000000000000000", + "type": "text", + "parent_element_id": 3541, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_color": "#ffffff" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'#6F686D'", + "format": "plain" + }, + { + "id": 3568, + "order": "3.50000000000000000000", + "type": "text", + "parent_element_id": 3530, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 16, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'2024-03-15'", + "format": "plain" + }, + { + "id": 3519, + "order": "4.00000000000000000000", + "type": "table", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 40, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "medium", + "style_width_child": "normal", + "data_source_id": 384, + "items_per_page": 20, + "button_load_more_label": "", + "schema_property": null, + "property_options": [], + "fields": [ + { + "uid": "16f2bd45-8dbc-466d-81c4-ee4e734cdea5", + "name": "Name", + "type": "text", + "styles": {}, + "config": { + "value": "get('current_record.field_7220')" + } + }, + { + "uid": "4ecfd86e-73e8-4a48-8d7c-968b3ad596f7", + "name": "Status", + "type": "tags", + "styles": {}, + "config": { + "values": "get('current_record.field_7221.value')", + "colors_is_formula": true, + "colors": "concat('#', get('current_record.field_7225'))" + } + }, + { + "uid": "8cf73f08-5ebe-42fe-802e-5a5ddcbf7f40", + "name": "Client", + "type": "text", + "styles": {}, + "config": { + "value": "get('current_record.field_7222.*.value')" + } + } + ], + "orientation": { + "tablet": "horizontal", + "desktop": "horizontal", + "smartphone": "horizontal" + } + }, + { + "id": 3569, + "order": "4.00000000000000000000", + "type": "text", + "parent_element_id": 3529, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 11, + "body_text_color": "V6EVv" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 6, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Due date'", + "format": "plain" + }, + { + "id": 3570, + "order": "4.00000000000000000000", + "type": "text", + "parent_element_id": 3531, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 16, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'2024-04-07'", + "format": "plain" + }, + { + "id": 3571, + "order": "4.00000000000000000000", + "type": "text", + "parent_element_id": 3537, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12 + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'E2B95A'", + "format": "plain" + }, + { + "id": 3572, + "order": "4.50000000000000000000", + "type": "text", + "parent_element_id": 3530, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 11, + "body_text_color": "V6EVv" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 6, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Due date'", + "format": "plain" + }, + { + "id": 3520, + "order": "5.00000000000000000000", + "type": "heading", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "heading_2_font_weight": "semi-bold" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 20, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "medium", + "style_width_child": "normal", + "value": "'Contact us'", + "level": 2 + }, + { + "id": 3573, + "order": "5.00000000000000000000", + "type": "text", + "parent_element_id": 3529, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 16, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'2024-02-16'", + "format": "plain" + }, + { + "id": 3574, + "order": "5.00000000000000000000", + "type": "text", + "parent_element_id": 3531, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 11, + "body_text_color": "V6EVv" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 6, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Due date'", + "format": "plain" + }, + { + "id": 3575, + "order": "5.00000000000000000000", + "type": "text", + "parent_element_id": 3538, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12 + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'#FF5A44'", + "format": "plain" + }, + { + "id": 3576, + "order": "5.50000000000000000000", + "type": "text", + "parent_element_id": 3530, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 16, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'2024-02-12'", + "format": "plain" + }, + { + "id": 3512, + "order": "6.00000000000000000000", + "type": "column", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 40, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "medium", + "style_width_child": "normal", + "column_amount": 2, + "column_gap": 40, + "alignment": "top" + }, + { + "id": 3577, + "order": "6.00000000000000000000", + "type": "text", + "parent_element_id": 3529, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 11, + "body_text_color": "V6EVv" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 6, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Label'", + "format": "plain" + }, + { + "id": 3578, + "order": "6.00000000000000000000", + "type": "text", + "parent_element_id": 3531, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 16, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'2024-04-12'", + "format": "plain" + }, + { + "id": 3521, + "order": "6.50000000000000000000", + "type": "heading", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "heading_2_font_weight": "semi-bold" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 20, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "medium", + "style_width_child": "normal", + "value": "'Colors'", + "level": 2 + }, + { + "id": 3579, + "order": "6.50000000000000000000", + "type": "text", + "parent_element_id": 3530, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 11, + "body_text_color": "V6EVv" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 6, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Label'", + "format": "plain" + }, + { + "id": 3513, + "order": "7.00000000000000000000", + "type": "column", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "medium", + "style_width_child": "normal", + "column_amount": 6, + "column_gap": 1, + "alignment": "top" + }, + { + "id": 3580, + "order": "7.00000000000000000000", + "type": "text", + "parent_element_id": 3529, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 16, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Value'", + "format": "plain" + }, + { + "id": 3581, + "order": "7.00000000000000000000", + "type": "text", + "parent_element_id": 3531, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 11, + "body_text_color": "V6EVv" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 6, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Label'", + "format": "plain" + }, + { + "id": 3514, + "order": "7.50000000000000000000", + "type": "column", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 40, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "medium", + "style_width_child": "normal", + "column_amount": 6, + "column_gap": 1, + "alignment": "top" + }, + { + "id": 3582, + "order": "7.50000000000000000000", + "type": "text", + "parent_element_id": 3530, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 16, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Value'", + "format": "plain" + }, + { + "id": 3522, + "order": "8.00000000000000000000", + "type": "heading", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "medium", + "style_width_child": "normal", + "value": "'Heading 1'", + "level": 1 + }, + { + "id": 3583, + "order": "8.00000000000000000000", + "type": "link", + "parent_element_id": 3529, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "button": { + "button_width": "full" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 10, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "navigation_type": "page", + "navigate_to_page_id": 219, + "page_parameters": [], + "query_parameters": [], + "navigate_to_url": "", + "target": "self", + "value": "'View tasks'", + "variant": "button" + }, + { + "id": 3584, + "order": "8.00000000000000000000", + "type": "text", + "parent_element_id": 3531, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 16, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Value'", + "format": "plain" + }, + { + "id": 3523, + "order": "9.00000000000000000000", + "type": "heading", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "medium", + "style_width_child": "normal", + "value": "'Heading 2'", + "level": 2 + }, + { + "id": 3585, + "order": "9.00000000000000000000", + "type": "link", + "parent_element_id": 3530, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "button": { + "button_width": "full" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 10, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "navigation_type": "page", + "navigate_to_page_id": 219, + "page_parameters": [], + "query_parameters": [], + "navigate_to_url": "", + "target": "self", + "value": "'View tasks'", + "variant": "button" + }, + { + "id": 3524, + "order": "10.00000000000000000000", + "type": "heading", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "medium", + "style_width_child": "normal", + "value": "'Heading 3'", + "level": 3 + }, + { + "id": 3586, + "order": "10.00000000000000000000", + "type": "link", + "parent_element_id": 3531, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "button": { + "button_width": "full" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 10, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "navigation_type": "page", + "navigate_to_page_id": 219, + "page_parameters": [], + "query_parameters": [], + "navigate_to_url": "", + "target": "self", + "value": "'View tasks'", + "variant": "button" + }, + { + "id": 3525, + "order": "11.00000000000000000000", + "type": "heading", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "medium", + "style_width_child": "normal", + "value": "'Heading 4'", + "level": 4 + }, + { + "id": 3526, + "order": "12.00000000000000000000", + "type": "heading", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "medium", + "style_width_child": "normal", + "value": "'Heading 5'", + "level": 5 + }, + { + "id": 3527, + "order": "13.00000000000000000000", + "type": "heading", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "medium", + "style_width_child": "normal", + "value": "'Heading 6'", + "level": 6 + }, + { + "id": 3528, + "order": "14.00000000000000000000", + "type": "text", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 40, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "medium", + "style_width_child": "normal", + "value": "'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque eu mollis purus. Integer ac bibendum metus. Morbi nunc eros, suscipit sed tristique vel, rutrum a nibh. In urna leo, pulvinar ac nunc vitae, vulputate pretium magna. Vivamus leo mauris, iaculis vel velit at, dapibus convallis magna. Sed tincidunt leo dui, vel viverra ex gravida eget. Pellentesque posuere scelerisque velit, in rutrum lorem vestibulum eleifend. Phasellus at consectetur urna, id bibendum neque. Fusce et metus magna.'", + "format": "plain" + } + ], + "data_sources": [ + { + "id": 384, + "name": "Tasks", + "order": "1.00000000000000000000", + "service": { + "id": 491, + "integration_id": 37, + "type": "local_baserow_list_rows", + "table_id": 743, + "view_id": null, + "sortings": [], + "search_query": "", + "filter_type": "AND", + "filters": [] + } + } + ], + "workflow_actions": [ + { + "id": 321, + "type": "notification", + "order": 1, + "page_id": 219, + "element_id": 3532, + "event": "submit", + "title": "'Thank you'", + "description": "'Thank youb for filling out the contact us form.'" + } + ], + "visibility": "all", + "role_type": "allow_all", + "roles": [] + } + ], + "integrations": [ + { + "id": 37, + "name": "Local Baserow", + "order": "1.00000000000000000000", + "type": "local_baserow", + "authorized_user": null + } + ], + "theme": { + "primary_color": "#e8d6bc", + "secondary_color": "#522b47", + "border_color": "#ebe6e1", + "main_success_color": "#618b25", + "main_warning_color": "#e2b95a", + "main_error_color": "#ff5a44", + "custom_colors": [ + { + "name": "Custom 1", + "color": "#ffffff", + "value": "ElMaZ" + }, + { + "name": "Custom 2", + "color": "#191102", + "value": "zoOtT" + }, + { + "name": "Custom 3", + "color": "#6f686d", + "value": "V6EVv" + } + ], + "body_font_family": "arial", + "body_font_size": 14, + "body_font_weight": "regular", + "body_text_color": "zoOtT", + "body_text_alignment": "left", + "heading_1_font_family": "times_new_roman", + "heading_1_font_size": 32, + "heading_1_font_weight": "bold", + "heading_1_text_color": "zoOtT", + "heading_1_text_alignment": "left", + "heading_1_text_decoration": [ + false, + false, + false, + false + ], + "heading_2_font_family": "times_new_roman", + "heading_2_font_size": 24, + "heading_2_font_weight": "bold", + "heading_2_text_color": "zoOtT", + "heading_2_text_alignment": "left", + "heading_2_text_decoration": [ + false, + false, + false, + false + ], + "heading_3_font_family": "times_new_roman", + "heading_3_font_size": 24, + "heading_3_font_weight": "regular", + "heading_3_text_color": "zoOtT", + "heading_3_text_alignment": "left", + "heading_3_text_decoration": [ + false, + false, + false, + false + ], + "heading_4_font_family": "arial", + "heading_4_font_size": 20, + "heading_4_font_weight": "regular", + "heading_4_text_color": "zoOtT", + "heading_4_text_alignment": "left", + "heading_4_text_decoration": [ + false, + false, + false, + false + ], + "heading_5_font_family": "arial", + "heading_5_font_size": 16, + "heading_5_font_weight": "regular", + "heading_5_text_color": "zoOtT", + "heading_5_text_alignment": "left", + "heading_5_text_decoration": [ + false, + false, + false, + false + ], + "heading_6_font_family": "arial", + "heading_6_font_size": 14, + "heading_6_font_weight": "regular", + "heading_6_text_color": "zoOtT", + "heading_6_text_alignment": "left", + "heading_6_text_decoration": [ + false, + false, + false, + false + ], + "button_font_family": "arial", + "button_font_size": 12, + "button_font_weight": "bold", + "button_alignment": "left", + "button_text_alignment": "center", + "button_width": "auto", + "button_background_color": "primary", + "button_text_color": "zoOtT", + "button_border_color": "border", + "button_border_size": 0, + "button_border_radius": 100, + "button_vertical_padding": 10, + "button_horizontal_padding": 12, + "button_hover_background_color": "#dbcab2", + "button_hover_text_color": "zoOtT", + "button_hover_border_color": "border", + "button_active_background_color": "primary", + "button_active_text_color": "zoOtT", + "button_active_border_color": "border", + "image_alignment": "left", + "image_max_width": 100, + "image_max_height": null, + "image_border_radius": 0, + "image_constraint": "contain", + "page_background_color": "#f5f2ef", + "page_background_file_id": null, + "page_background_mode": "tile", + "label_font_family": "arial", + "label_text_color": "zoOtT", + "label_font_size": 13, + "label_font_weight": "bold", + "input_font_family": "arial", + "input_font_size": 14, + "input_font_weight": "regular", + "input_text_color": "zoOtT", + "input_background_color": "#ffffff", + "input_border_color": "#d7d8d9", + "input_border_size": 1, + "input_border_radius": 8, + "input_vertical_padding": 12, + "input_horizontal_padding": 16, + "table_border_color": "border", + "table_border_size": 1, + "table_border_radius": 8, + "table_header_background_color": "#faf7f5", + "table_header_text_color": "V6EVv", + "table_header_font_size": 13, + "table_header_font_weight": "bold", + "table_header_font_family": "arial", + "table_header_text_alignment": "left", + "table_cell_background_color": "ElMaZ", + "table_cell_alternate_background_color": "ElMaZ", + "table_cell_alignment": "left", + "table_cell_vertical_padding": 18, + "table_cell_horizontal_padding": 24, + "table_vertical_separator_color": "#000000FF", + "table_vertical_separator_size": 0, + "table_horizontal_separator_color": "border", + "table_horizontal_separator_size": 1, + "link_font_family": "arial", + "link_font_size": 14, + "link_font_weight": "regular", + "link_text_alignment": "left", + "link_text_color": "secondary", + "link_hover_text_color": "#381d31", + "link_active_text_color": "secondary", + "link_default_text_decoration": [ + true, + false, + false, + false + ], + "link_hover_text_decoration": [ + true, + false, + false, + false + ], + "link_active_text_decoration": [ + true, + false, + false, + false + ] + }, + "user_sources": [], + "favicon_file": null, + "login_page": null, + "id": 181, + "name": "Ivory theme", + "order": 1, + "type": "builder" + }, + { + "id": 180, + "name": "Ivory database", + "order": 2, + "type": "database", + "tables": [ + { + "id": 743, + "name": "Tasks", + "order": 1, + "fields": [ + { + "id": 7220, + "type": "text", + "name": "Name", + "description": null, + "order": 0, + "primary": true, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "text_default": "" + }, + { + "id": 7221, + "type": "single_select", + "name": "Status", + "description": null, + "order": 1, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "select_options": [ + { + "id": 3222, + "value": "In progress", + "color": "light-cyan", + "order": 0 + }, + { + "id": 3223, + "value": "Ready", + "color": "light-green", + "order": 1 + }, + { + "id": 3224, + "value": "On hold", + "color": "light-yellow", + "order": 2 + }, + { + "id": 3225, + "value": "Blocked", + "color": "light-brown", + "order": 3 + } + ] + }, + { + "id": 7222, + "type": "link_row", + "name": "Client", + "description": null, + "order": 2, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "link_row_table_id": 744, + "link_row_related_field_id": null, + "link_row_limit_selection_view_id": null, + "has_related_field": false + }, + { + "id": 7225, + "type": "formula", + "name": "Status color", + "description": null, + "order": 3, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "date_show_tzinfo": null, + "date_format": null, + "duration_format": null, + "number_prefix": "", + "error": null, + "date_time_format": null, + "number_suffix": "", + "nullable": false, + "number_separator": "", + "number_decimal_places": null, + "date_force_timezone": null, + "date_include_time": null, + "array_formula_type": null, + "formula": "if(field('Status') = 'In progress', 'ECFBFD',\nif(field('Status') = 'Ready', 'ECFCF1', \nif(field('Status') = 'On hold', 'F5F5F5', \nif(field('Status') = 'Blocked', 'FFF2F0',\n''))))", + "formula_type": "text" + } + ], + "views": [ + { + "id": 3291, + "type": "grid", + "name": "Grid", + "order": 1, + "ownership_type": "collaborative", + "owned_by": "bram@baserow.io", + "filter_type": "AND", + "filters_disabled": false, + "filters": [], + "filter_groups": [], + "sortings": [], + "group_bys": [], + "decorations": [], + "public": false, + "row_identifier_type": "id", + "row_height_size": "small", + "field_options": [ + { + "id": 27052, + "field_id": 7220, + "width": 294, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 27053, + "field_id": 7221, + "width": 248, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 27054, + "field_id": 7222, + "width": 200, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 27055, + "field_id": 7225, + "width": 200, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + } + ] + } + ], + "rows": [ + { + "id": 1, + "order": "1.00000000000000000000", + "created_on": "2025-03-14T12:47:43.944761+00:00", + "updated_on": "2025-03-14T12:50:42.758525+00:00", + "created_by": "bram@baserow.io", + "last_modified_by": "bram@baserow.io", + "field_7220": "Facilitate Case Study Discussions", + "field_7221": 3222, + "field_7222": [ + 1 + ], + "field_7225": null + }, + { + "id": 2, + "order": "2.00000000000000000000", + "created_on": "2025-03-14T12:47:43.944821+00:00", + "updated_on": "2025-03-14T12:50:45.243685+00:00", + "created_by": "bram@baserow.io", + "last_modified_by": "bram@baserow.io", + "field_7220": "Design Interactive Workshops", + "field_7221": 3223, + "field_7222": [ + 2 + ], + "field_7225": null + }, + { + "id": 3, + "order": "3.00000000000000000000", + "created_on": "2025-03-14T12:48:20.544029+00:00", + "updated_on": "2025-03-14T12:50:47.917272+00:00", + "created_by": "bram@baserow.io", + "last_modified_by": "bram@baserow.io", + "field_7220": "Facilitate Case Study Discussions", + "field_7221": 3224, + "field_7222": [ + 3 + ], + "field_7225": null + }, + { + "id": 4, + "order": "4.00000000000000000000", + "created_on": "2025-03-14T12:48:21.131545+00:00", + "updated_on": "2025-03-14T12:50:50.161461+00:00", + "created_by": "bram@baserow.io", + "last_modified_by": "bram@baserow.io", + "field_7220": "Design Interactive Workshops", + "field_7221": 3225, + "field_7222": [ + 4 + ], + "field_7225": null + }, + { + "id": 5, + "order": "5.00000000000000000000", + "created_on": "2025-03-14T12:48:21.638510+00:00", + "updated_on": "2025-03-14T12:50:52.369005+00:00", + "created_by": "bram@baserow.io", + "last_modified_by": "bram@baserow.io", + "field_7220": "Facilitate Case Study Discussions", + "field_7221": 3222, + "field_7222": [ + 5 + ], + "field_7225": null + }, + { + "id": 6, + "order": "6.00000000000000000000", + "created_on": "2025-03-14T12:48:31.532384+00:00", + "updated_on": "2025-03-14T12:50:54.683754+00:00", + "created_by": "bram@baserow.io", + "last_modified_by": "bram@baserow.io", + "field_7220": "Design Interactive Workshops", + "field_7221": 3223, + "field_7222": [ + 6 + ], + "field_7225": null + } + ], + "data_sync": null + }, + { + "id": 744, + "name": "Client", + "order": 2, + "fields": [ + { + "id": 7223, + "type": "text", + "name": "Name", + "description": null, + "order": 0, + "primary": true, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "text_default": "" + }, + { + "id": 7224, + "type": "long_text", + "name": "Notes", + "description": null, + "order": 3, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "long_text_enable_rich_text": false + } + ], + "views": [ + { + "id": 3292, + "type": "grid", + "name": "Grid", + "order": 1, + "ownership_type": "collaborative", + "owned_by": "bram@baserow.io", + "filter_type": "AND", + "filters_disabled": false, + "filters": [], + "filter_groups": [], + "sortings": [], + "group_bys": [], + "decorations": [], + "public": false, + "row_identifier_type": "id", + "row_height_size": "small", + "field_options": [ + { + "id": 27056, + "field_id": 7223, + "width": 200, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 27057, + "field_id": 7224, + "width": 457, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + } + ] + } + ], + "rows": [ + { + "id": 1, + "order": "1.00000000000000000000", + "created_on": "2025-03-14T12:48:36.629478+00:00", + "updated_on": "2025-03-14T12:49:27.285052+00:00", + "created_by": "bram@baserow.io", + "last_modified_by": "bram@baserow.io", + "field_7223": "Ferrari", + "field_7224": "Ferrari is a prestigious Italian luxury sports car manufacturer known for their iconic red vehicles with sleek designs and powerful engines. With a history dating back to 1939, Ferrari has become synonymous with speed, performance, and exclusivity. Their cars are revered for their precision engineering and unmatched driving experience." + }, + { + "id": 2, + "order": "2.00000000000000000000", + "created_on": "2025-03-14T12:48:36.629532+00:00", + "updated_on": "2025-03-14T12:49:28.295210+00:00", + "created_by": "bram@baserow.io", + "last_modified_by": "bram@baserow.io", + "field_7223": "Facebook", + "field_7224": "Facebook is a popular social networking platform that allows users to connect with friends and family, share updates, photos, and videos, and join groups or events. With over 2 billion active users, Facebook has become a hub for communication, networking, advertising, and staying connected with others around the world." + }, + { + "id": 3, + "order": "3.00000000000000000000", + "created_on": "2025-03-14T12:48:45.278577+00:00", + "updated_on": "2025-03-14T12:49:29.314092+00:00", + "created_by": "bram@baserow.io", + "last_modified_by": "bram@baserow.io", + "field_7223": "General Electric", + "field_7224": "General Electric, commonly known as GE, is a multinational conglomerate based in the United States. Founded in 1892, the company specializes in areas such as aviation, healthcare, power, and renewable energy. GE is known for its innovative technology and has a global presence in over 180 countries." + }, + { + "id": 4, + "order": "4.00000000000000000000", + "created_on": "2025-03-14T12:48:45.278647+00:00", + "updated_on": "2025-03-14T12:49:30.250861+00:00", + "created_by": "bram@baserow.io", + "last_modified_by": "bram@baserow.io", + "field_7223": "Pizza Hut", + "field_7224": "Pizza Hut is a popular American restaurant chain known for its delicious pizza offerings. With over 18,000 locations worldwide, Pizza Hut is a favorite destination for families and pizza lovers alike. With a wide variety of toppings, crust options, and sides, Pizza Hut offers something for everyone to enjoy." + }, + { + "id": 5, + "order": "5.00000000000000000000", + "created_on": "2025-03-14T12:48:45.278688+00:00", + "updated_on": "2025-03-14T12:49:31.172965+00:00", + "created_by": "bram@baserow.io", + "last_modified_by": "bram@baserow.io", + "field_7223": "Nintendo", + "field_7224": "Nintendo is a Japanese multinational consumer electronics and video game company known for creating iconic games and consoles such as Mario, Zelda, and the Nintendo Switch. Founded in 1889, Nintendo continues to innovate and delight gamers around the world with its colorful and imaginative gaming experiences." + }, + { + "id": 6, + "order": "6.00000000000000000000", + "created_on": "2025-03-14T12:48:45.278726+00:00", + "updated_on": "2025-03-14T12:49:32.192236+00:00", + "created_by": "bram@baserow.io", + "last_modified_by": "bram@baserow.io", + "field_7223": "McDonalds", + "field_7224": "McDonald's is a well-known fast food chain that offers a wide range of menu options, including burgers, fries, chicken sandwiches, and breakfast items. With a focus on convenience and affordability, McDonald's has become a popular choice for quick meals and snacks for people of all ages around the world." + } + ], + "data_sync": null + } + ] + } + ] +} diff --git a/backend/templates/ab_ivory_theme.zip b/backend/templates/ab_ivory_theme.zip new file mode 100644 index 000000000..15cb0ecb3 Binary files /dev/null and b/backend/templates/ab_ivory_theme.zip differ diff --git a/backend/templates/car-dealership-inventory.json b/backend/templates/car-dealership-inventory.json index eaf3b0d2a..fb807bc5c 100644 --- a/backend/templates/car-dealership-inventory.json +++ b/backend/templates/car-dealership-inventory.json @@ -19,130 +19,2592 @@ ], "export": [ { - "id": 45157, + "id": 2169, "name": "Car Dealership Inventory", "order": 1, "type": "database", "tables": [ { - "id": 111551, - "name": "Cars", + "id": 5695, + "name": "Brands", "order": 1, "fields": [ { - "id": 705223, - "type": "formula", - "name": "ID", + "id": 59745, + "type": "text", + "name": "Name", + "description": null, "order": 0, "primary": true, - "error": null, - "date_format": null, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "text_default": "" + }, + { + "id": 59746, + "type": "link_row", + "name": "Models", + "description": null, + "order": 3, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "link_row_table_id": 5696, + "link_row_related_field_id": 59759, + "link_row_limit_selection_view_id": null, + "has_related_field": true + }, + { + "id": 59836, + "type": "count", + "name": "Count models", + "description": null, + "order": 4, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "number_suffix": "", + "number_separator": "", "date_include_time": null, - "date_time_format": null, - "number_decimal_places": null, + "duration_format": null, + "date_force_timezone": null, + "date_show_tzinfo": null, "array_formula_type": null, + "error": null, + "number_decimal_places": 0, + "date_time_format": null, + "number_prefix": "", + "nullable": false, + "date_format": null, + "through_field_id": 59746 + } + ], + "views": [ + { + "id": 26455, + "type": "grid", + "name": "All brands", + "order": 1, + "ownership_type": "collaborative", + "owned_by": "frederik@baserow.io", + "filter_type": "AND", + "filters_disabled": false, + "filters": [], + "filter_groups": [], + "sortings": [ + { + "id": 20329, + "field_id": 59836, + "order": "DESC" + } + ], + "group_bys": [], + "decorations": [], + "public": false, + "row_identifier_type": "id", + "row_height_size": "small", + "field_options": [ + { + "id": 261258, + "field_id": 59745, + "width": 130, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261259, + "field_id": 59746, + "width": 200, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261260, + "field_id": 59836, + "width": 200, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + } + ] + } + ], + "rows": [ + { + "id": 1, + "order": "1.00000000000000000000", + "created_on": "2025-02-07T08:58:57.519555+00:00", + "updated_on": "2025-02-07T08:59:32.036991+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59745": "Honda", + "field_59746": [ + 7, + 8 + ], + "field_59836": null + }, + { + "id": 2, + "order": "2.00000000000000000000", + "created_on": "2025-02-07T08:58:57.519590+00:00", + "updated_on": "2025-02-07T08:59:34.215043+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59745": "Mazda", + "field_59746": [ + 9, + 10 + ], + "field_59836": null + }, + { + "id": 3, + "order": "3.00000000000000000000", + "created_on": "2025-02-07T08:59:35.268423+00:00", + "updated_on": "2025-02-07T08:59:36.124338+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59745": "Mitsubishi", + "field_59746": [ + 5, + 6 + ], + "field_59836": null + }, + { + "id": 4, + "order": "4.00000000000000000000", + "created_on": "2025-02-07T08:59:37.198872+00:00", + "updated_on": "2025-02-07T08:59:39.786026+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59745": "Toyota", + "field_59746": [ + 1, + 2, + 3, + 4 + ], + "field_59836": null + } + ], + "data_sync": null + }, + { + "id": 5696, + "name": "Models", + "order": 2, + "fields": [ + { + "id": 59747, + "type": "text", + "name": "Model and variant", + "description": null, + "order": 0, + "primary": true, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "text_default": "" + }, + { + "id": 59748, + "type": "file", + "name": "Photo", + "description": null, + "order": 2, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false + }, + { + "id": 59749, + "type": "single_select", + "name": "Type", + "description": null, + "order": 3, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "select_options": [ + { + "id": 21033, + "value": "Sedan", + "color": "gray", + "order": 0 + }, + { + "id": 21034, + "value": "Coupe", + "color": "gray", + "order": 1 + }, + { + "id": 21035, + "value": "Convertible", + "color": "gray", + "order": 2 + }, + { + "id": 21036, + "value": "Sports car", + "color": "gray", + "order": 3 + }, + { + "id": 21037, + "value": "Hatchback", + "color": "gray", + "order": 4 + }, + { + "id": 21038, + "value": "Multipurpose vehicle (MPV)", + "color": "gray", + "order": 5 + }, + { + "id": 21039, + "value": "Van", + "color": "gray", + "order": 6 + }, + { + "id": 21040, + "value": "Sport utility vehicle (SUV)", + "color": "gray", + "order": 7 + }, + { + "id": 21041, + "value": "Pickup truck", + "color": "gray", + "order": 8 + }, + { + "id": 21042, + "value": "Motorcycle", + "color": "gray", + "order": 9 + } + ] + }, + { + "id": 59750, + "type": "number", + "name": "Engine size (L)", + "description": null, + "order": 4, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "number_decimal_places": 2, + "number_negative": false, + "number_prefix": "", + "number_suffix": "", + "number_separator": "" + }, + { + "id": 59751, + "type": "single_select", + "name": "Transmission", + "description": null, + "order": 5, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "select_options": [ + { + "id": 21043, + "value": "Automatic", + "color": "light-blue", + "order": 0 + }, + { + "id": 21044, + "value": "CVT", + "color": "light-blue", + "order": 1 + }, + { + "id": 21045, + "value": "Manual", + "color": "light-blue", + "order": 2 + } + ] + }, + { + "id": 59752, + "type": "single_select", + "name": "Fuel type", + "description": null, + "order": 6, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "select_options": [ + { + "id": 21046, + "value": "Gasoline", + "color": "green", + "order": 0 + }, + { + "id": 21047, + "value": "Diesel", + "color": "orange", + "order": 1 + }, + { + "id": 21048, + "value": "Hybrid", + "color": "dark-gray", + "order": 2 + }, + { + "id": 21049, + "value": "Electric", + "color": "red", + "order": 3 + }, + { + "id": 21050, + "value": "Hydrogen", + "color": "dark-blue", + "order": 4 + }, + { + "id": 21051, + "value": "LPG", + "color": "light-blue", + "order": 5 + } + ] + }, + { + "id": 59753, + "type": "number", + "name": "Seat count", + "description": null, + "order": 7, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "number_decimal_places": 0, + "number_negative": false, + "number_prefix": "", + "number_suffix": "", + "number_separator": "" + }, + { + "id": 59754, + "type": "number", + "name": "Body length", + "description": null, + "order": 8, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "number_decimal_places": 0, + "number_negative": false, + "number_prefix": "", + "number_suffix": "mm", + "number_separator": "SPACE_PERIOD" + }, + { + "id": 59755, + "type": "number", + "name": "Body width", + "description": null, + "order": 9, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "number_decimal_places": 0, + "number_negative": false, + "number_prefix": "", + "number_suffix": "mm", + "number_separator": "SPACE_PERIOD" + }, + { + "id": 59756, + "type": "number", + "name": "Body height", + "description": null, + "order": 10, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "number_decimal_places": 0, + "number_negative": false, + "number_prefix": "", + "number_suffix": "mm", + "number_separator": "SPACE_PERIOD" + }, + { + "id": 59870, + "type": "formula", + "name": "In stock count", + "description": null, + "order": 11, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "number_suffix": "", + "number_separator": "", + "date_include_time": null, + "duration_format": null, + "date_force_timezone": null, + "date_show_tzinfo": null, + "array_formula_type": null, + "error": null, + "number_decimal_places": 0, + "date_time_format": null, + "number_prefix": "", + "nullable": false, + "date_format": null, + "formula": "count(filter(field('Related cars'),totext(lookup('Related cars','Status')) != 'Sold'))", + "formula_type": "number" + }, + { + "id": 59837, + "type": "count", + "name": "History count", + "description": null, + "order": 12, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "number_suffix": "", + "number_separator": "", + "date_include_time": null, + "duration_format": null, + "date_force_timezone": null, + "date_show_tzinfo": null, + "array_formula_type": null, + "error": null, + "number_decimal_places": 0, + "date_time_format": null, + "number_prefix": "", + "nullable": false, + "date_format": null, + "through_field_id": 59757 + }, + { + "id": 59757, + "type": "link_row", + "name": "Related cars", + "description": null, + "order": 13, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "link_row_table_id": 5697, + "link_row_related_field_id": 59762, + "link_row_limit_selection_view_id": null, + "has_related_field": true + }, + { + "id": 59758, + "type": "number", + "name": "Year model", + "description": null, + "order": 14, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "number_decimal_places": 0, + "number_negative": false, + "number_prefix": "", + "number_suffix": "", + "number_separator": "" + }, + { + "id": 59759, + "type": "link_row", + "name": "Brand", + "description": null, + "order": 15, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "link_row_table_id": 5695, + "link_row_related_field_id": 59746, + "link_row_limit_selection_view_id": null, + "has_related_field": true + } + ], + "views": [ + { + "id": 26456, + "type": "grid", + "name": "All models", + "order": 1, + "ownership_type": "collaborative", + "owned_by": null, + "filter_type": "AND", + "filters_disabled": false, + "filters": [], + "filter_groups": [], + "sortings": [ + { + "id": 20330, + "field_id": 59747, + "order": "ASC" + }, + { + "id": 20331, + "field_id": 59758, + "order": "DESC" + } + ], + "group_bys": [], + "decorations": [], + "public": false, + "row_identifier_type": "count", + "row_height_size": "small", + "field_options": [ + { + "id": 261261, + "field_id": 59747, + "width": 179, + "hidden": false, + "order": 0, + "aggregation_type": "unique_count", + "aggregation_raw_type": "unique_count" + }, + { + "id": 261262, + "field_id": 59759, + "width": 121, + "hidden": false, + "order": 2, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261263, + "field_id": 59748, + "width": 177, + "hidden": false, + "order": 3, + "aggregation_type": "not_empty_percentage", + "aggregation_raw_type": "empty_count" + }, + { + "id": 261264, + "field_id": 59758, + "width": 142, + "hidden": false, + "order": 4, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261265, + "field_id": 59749, + "width": 194, + "hidden": false, + "order": 5, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261266, + "field_id": 59750, + "width": 164, + "hidden": false, + "order": 6, + "aggregation_type": "average", + "aggregation_raw_type": "average" + }, + { + "id": 261267, + "field_id": 59751, + "width": 143, + "hidden": false, + "order": 7, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261268, + "field_id": 59752, + "width": 130, + "hidden": false, + "order": 8, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261269, + "field_id": 59753, + "width": 148, + "hidden": false, + "order": 9, + "aggregation_type": "average", + "aggregation_raw_type": "average" + }, + { + "id": 261270, + "field_id": 59754, + "width": 181, + "hidden": false, + "order": 10, + "aggregation_type": "average", + "aggregation_raw_type": "average" + }, + { + "id": 261271, + "field_id": 59755, + "width": 166, + "hidden": false, + "order": 11, + "aggregation_type": "average", + "aggregation_raw_type": "average" + }, + { + "id": 261272, + "field_id": 59756, + "width": 169, + "hidden": false, + "order": 12, + "aggregation_type": "average", + "aggregation_raw_type": "average" + }, + { + "id": 261273, + "field_id": 59870, + "width": 168, + "hidden": false, + "order": 13, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261274, + "field_id": 59837, + "width": 168, + "hidden": false, + "order": 14, + "aggregation_type": "sum", + "aggregation_raw_type": "sum" + }, + { + "id": 261275, + "field_id": 59757, + "width": 200, + "hidden": false, + "order": 15, + "aggregation_type": "", + "aggregation_raw_type": "" + } + ] + }, + { + "id": 26457, + "type": "grid", + "name": "All models grouped by brand", + "order": 2, + "ownership_type": "collaborative", + "owned_by": null, + "filter_type": "AND", + "filters_disabled": false, + "filters": [], + "filter_groups": [], + "sortings": [ + { + "id": 20332, + "field_id": 59747, + "order": "ASC" + }, + { + "id": 20333, + "field_id": 59758, + "order": "DESC" + } + ], + "group_bys": [ + { + "id": 3628, + "field_id": 59759, + "order": "ASC" + } + ], + "decorations": [], + "public": false, + "row_identifier_type": "count", + "row_height_size": "small", + "field_options": [ + { + "id": 261276, + "field_id": 59747, + "width": 179, + "hidden": false, + "order": 0, + "aggregation_type": "unique_count", + "aggregation_raw_type": "unique_count" + }, + { + "id": 261277, + "field_id": 59759, + "width": 121, + "hidden": true, + "order": 2, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261278, + "field_id": 59748, + "width": 177, + "hidden": false, + "order": 3, + "aggregation_type": "not_empty_percentage", + "aggregation_raw_type": "empty_count" + }, + { + "id": 261279, + "field_id": 59758, + "width": 142, + "hidden": false, + "order": 4, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261280, + "field_id": 59749, + "width": 194, + "hidden": false, + "order": 5, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261281, + "field_id": 59750, + "width": 164, + "hidden": false, + "order": 6, + "aggregation_type": "average", + "aggregation_raw_type": "average" + }, + { + "id": 261282, + "field_id": 59751, + "width": 143, + "hidden": false, + "order": 7, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261283, + "field_id": 59752, + "width": 130, + "hidden": false, + "order": 8, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261284, + "field_id": 59753, + "width": 148, + "hidden": false, + "order": 9, + "aggregation_type": "average", + "aggregation_raw_type": "average" + }, + { + "id": 261285, + "field_id": 59754, + "width": 169, + "hidden": false, + "order": 10, + "aggregation_type": "average", + "aggregation_raw_type": "average" + }, + { + "id": 261286, + "field_id": 59755, + "width": 166, + "hidden": false, + "order": 11, + "aggregation_type": "average", + "aggregation_raw_type": "average" + }, + { + "id": 261287, + "field_id": 59756, + "width": 169, + "hidden": false, + "order": 12, + "aggregation_type": "average", + "aggregation_raw_type": "average" + }, + { + "id": 261288, + "field_id": 59870, + "width": 168, + "hidden": false, + "order": 13, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261289, + "field_id": 59837, + "width": 168, + "hidden": false, + "order": 14, + "aggregation_type": "sum", + "aggregation_raw_type": "sum" + }, + { + "id": 261290, + "field_id": 59757, + "width": 200, + "hidden": false, + "order": 15, + "aggregation_type": "", + "aggregation_raw_type": "" + } + ] + }, + { + "id": 26458, + "type": "grid", + "name": "All models grouped by type", + "order": 3, + "ownership_type": "collaborative", + "owned_by": null, + "filter_type": "AND", + "filters_disabled": false, + "filters": [], + "filter_groups": [], + "sortings": [ + { + "id": 20334, + "field_id": 59747, + "order": "ASC" + }, + { + "id": 20335, + "field_id": 59758, + "order": "DESC" + } + ], + "group_bys": [ + { + "id": 3629, + "field_id": 59749, + "order": "ASC" + } + ], + "decorations": [], + "public": false, + "row_identifier_type": "count", + "row_height_size": "small", + "field_options": [ + { + "id": 261291, + "field_id": 59747, + "width": 179, + "hidden": false, + "order": 0, + "aggregation_type": "unique_count", + "aggregation_raw_type": "unique_count" + }, + { + "id": 261292, + "field_id": 59759, + "width": 121, + "hidden": false, + "order": 2, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261293, + "field_id": 59748, + "width": 177, + "hidden": false, + "order": 3, + "aggregation_type": "not_empty_percentage", + "aggregation_raw_type": "empty_count" + }, + { + "id": 261294, + "field_id": 59758, + "width": 142, + "hidden": false, + "order": 4, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261295, + "field_id": 59749, + "width": 194, + "hidden": true, + "order": 5, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261296, + "field_id": 59750, + "width": 164, + "hidden": false, + "order": 6, + "aggregation_type": "average", + "aggregation_raw_type": "average" + }, + { + "id": 261297, + "field_id": 59751, + "width": 143, + "hidden": false, + "order": 7, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261298, + "field_id": 59752, + "width": 130, + "hidden": false, + "order": 8, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261299, + "field_id": 59753, + "width": 148, + "hidden": false, + "order": 9, + "aggregation_type": "average", + "aggregation_raw_type": "average" + }, + { + "id": 261300, + "field_id": 59754, + "width": 169, + "hidden": false, + "order": 10, + "aggregation_type": "average", + "aggregation_raw_type": "average" + }, + { + "id": 261301, + "field_id": 59755, + "width": 166, + "hidden": false, + "order": 11, + "aggregation_type": "average", + "aggregation_raw_type": "average" + }, + { + "id": 261302, + "field_id": 59756, + "width": 169, + "hidden": false, + "order": 12, + "aggregation_type": "average", + "aggregation_raw_type": "average" + }, + { + "id": 261303, + "field_id": 59870, + "width": 168, + "hidden": false, + "order": 13, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261304, + "field_id": 59837, + "width": 168, + "hidden": false, + "order": 14, + "aggregation_type": "sum", + "aggregation_raw_type": "sum" + }, + { + "id": 261305, + "field_id": 59757, + "width": 200, + "hidden": false, + "order": 15, + "aggregation_type": "", + "aggregation_raw_type": "" + } + ] + }, + { + "id": 26459, + "type": "grid", + "name": "All models grouped by transmission", + "order": 4, + "ownership_type": "collaborative", + "owned_by": null, + "filter_type": "AND", + "filters_disabled": false, + "filters": [], + "filter_groups": [], + "sortings": [ + { + "id": 20336, + "field_id": 59747, + "order": "ASC" + }, + { + "id": 20337, + "field_id": 59758, + "order": "DESC" + } + ], + "group_bys": [ + { + "id": 3630, + "field_id": 59751, + "order": "ASC" + } + ], + "decorations": [], + "public": false, + "row_identifier_type": "count", + "row_height_size": "small", + "field_options": [ + { + "id": 261306, + "field_id": 59747, + "width": 179, + "hidden": false, + "order": 0, + "aggregation_type": "unique_count", + "aggregation_raw_type": "unique_count" + }, + { + "id": 261307, + "field_id": 59759, + "width": 121, + "hidden": false, + "order": 2, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261308, + "field_id": 59748, + "width": 177, + "hidden": false, + "order": 3, + "aggregation_type": "not_empty_percentage", + "aggregation_raw_type": "empty_count" + }, + { + "id": 261309, + "field_id": 59758, + "width": 142, + "hidden": false, + "order": 4, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261310, + "field_id": 59749, + "width": 194, + "hidden": false, + "order": 5, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261311, + "field_id": 59750, + "width": 164, + "hidden": false, + "order": 6, + "aggregation_type": "average", + "aggregation_raw_type": "average" + }, + { + "id": 261312, + "field_id": 59751, + "width": 143, + "hidden": true, + "order": 7, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261313, + "field_id": 59752, + "width": 130, + "hidden": false, + "order": 8, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261314, + "field_id": 59753, + "width": 148, + "hidden": false, + "order": 9, + "aggregation_type": "average", + "aggregation_raw_type": "average" + }, + { + "id": 261315, + "field_id": 59754, + "width": 169, + "hidden": false, + "order": 10, + "aggregation_type": "average", + "aggregation_raw_type": "average" + }, + { + "id": 261316, + "field_id": 59755, + "width": 166, + "hidden": false, + "order": 11, + "aggregation_type": "average", + "aggregation_raw_type": "average" + }, + { + "id": 261317, + "field_id": 59756, + "width": 169, + "hidden": false, + "order": 12, + "aggregation_type": "average", + "aggregation_raw_type": "average" + }, + { + "id": 261318, + "field_id": 59870, + "width": 168, + "hidden": false, + "order": 13, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261319, + "field_id": 59837, + "width": 168, + "hidden": false, + "order": 14, + "aggregation_type": "sum", + "aggregation_raw_type": "sum" + }, + { + "id": 261320, + "field_id": 59757, + "width": 200, + "hidden": false, + "order": 15, + "aggregation_type": "", + "aggregation_raw_type": "" + } + ] + }, + { + "id": 26460, + "type": "grid", + "name": "All models grouped by fuel type", + "order": 5, + "ownership_type": "collaborative", + "owned_by": null, + "filter_type": "AND", + "filters_disabled": false, + "filters": [], + "filter_groups": [], + "sortings": [ + { + "id": 20338, + "field_id": 59747, + "order": "ASC" + }, + { + "id": 20339, + "field_id": 59758, + "order": "DESC" + } + ], + "group_bys": [ + { + "id": 3631, + "field_id": 59752, + "order": "ASC" + } + ], + "decorations": [], + "public": false, + "row_identifier_type": "count", + "row_height_size": "small", + "field_options": [ + { + "id": 261321, + "field_id": 59747, + "width": 179, + "hidden": false, + "order": 0, + "aggregation_type": "unique_count", + "aggregation_raw_type": "unique_count" + }, + { + "id": 261322, + "field_id": 59759, + "width": 121, + "hidden": false, + "order": 2, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261323, + "field_id": 59748, + "width": 177, + "hidden": false, + "order": 3, + "aggregation_type": "not_empty_percentage", + "aggregation_raw_type": "empty_count" + }, + { + "id": 261324, + "field_id": 59758, + "width": 142, + "hidden": false, + "order": 4, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261325, + "field_id": 59749, + "width": 194, + "hidden": false, + "order": 5, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261326, + "field_id": 59750, + "width": 164, + "hidden": false, + "order": 6, + "aggregation_type": "average", + "aggregation_raw_type": "average" + }, + { + "id": 261327, + "field_id": 59751, + "width": 143, + "hidden": false, + "order": 7, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261328, + "field_id": 59752, + "width": 130, + "hidden": true, + "order": 8, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261329, + "field_id": 59753, + "width": 148, + "hidden": false, + "order": 9, + "aggregation_type": "average", + "aggregation_raw_type": "average" + }, + { + "id": 261330, + "field_id": 59754, + "width": 169, + "hidden": false, + "order": 10, + "aggregation_type": "average", + "aggregation_raw_type": "average" + }, + { + "id": 261331, + "field_id": 59755, + "width": 166, + "hidden": false, + "order": 11, + "aggregation_type": "average", + "aggregation_raw_type": "average" + }, + { + "id": 261332, + "field_id": 59756, + "width": 169, + "hidden": false, + "order": 12, + "aggregation_type": "average", + "aggregation_raw_type": "average" + }, + { + "id": 261333, + "field_id": 59870, + "width": 168, + "hidden": false, + "order": 13, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261334, + "field_id": 59837, + "width": 168, + "hidden": false, + "order": 14, + "aggregation_type": "sum", + "aggregation_raw_type": "sum" + }, + { + "id": 261335, + "field_id": 59757, + "width": 200, + "hidden": false, + "order": 15, + "aggregation_type": "", + "aggregation_raw_type": "" + } + ] + }, + { + "id": 26461, + "type": "grid", + "name": "Models with 1 car in stock", + "order": 6, + "ownership_type": "collaborative", + "owned_by": null, + "filter_type": "AND", + "filters_disabled": false, + "filters": [ + { + "id": 13967, + "field_id": 59870, + "type": "equal", + "value": "1", + "group": null + } + ], + "filter_groups": [], + "sortings": [ + { + "id": 20340, + "field_id": 59747, + "order": "ASC" + }, + { + "id": 20341, + "field_id": 59758, + "order": "DESC" + } + ], + "group_bys": [], + "decorations": [], + "public": false, + "row_identifier_type": "count", + "row_height_size": "small", + "field_options": [ + { + "id": 261336, + "field_id": 59747, + "width": 179, + "hidden": false, + "order": 0, + "aggregation_type": "unique_count", + "aggregation_raw_type": "unique_count" + }, + { + "id": 261337, + "field_id": 59759, + "width": 121, + "hidden": false, + "order": 2, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261338, + "field_id": 59748, + "width": 177, + "hidden": false, + "order": 3, + "aggregation_type": "not_empty_percentage", + "aggregation_raw_type": "empty_count" + }, + { + "id": 261339, + "field_id": 59758, + "width": 142, + "hidden": false, + "order": 4, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261340, + "field_id": 59749, + "width": 194, + "hidden": false, + "order": 5, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261341, + "field_id": 59750, + "width": 164, + "hidden": false, + "order": 6, + "aggregation_type": "average", + "aggregation_raw_type": "average" + }, + { + "id": 261342, + "field_id": 59751, + "width": 143, + "hidden": false, + "order": 7, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261343, + "field_id": 59752, + "width": 130, + "hidden": false, + "order": 8, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261344, + "field_id": 59753, + "width": 148, + "hidden": false, + "order": 9, + "aggregation_type": "average", + "aggregation_raw_type": "average" + }, + { + "id": 261345, + "field_id": 59754, + "width": 169, + "hidden": false, + "order": 10, + "aggregation_type": "average", + "aggregation_raw_type": "average" + }, + { + "id": 261346, + "field_id": 59755, + "width": 166, + "hidden": false, + "order": 11, + "aggregation_type": "average", + "aggregation_raw_type": "average" + }, + { + "id": 261347, + "field_id": 59756, + "width": 169, + "hidden": false, + "order": 12, + "aggregation_type": "average", + "aggregation_raw_type": "average" + }, + { + "id": 261348, + "field_id": 59870, + "width": 168, + "hidden": false, + "order": 13, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261349, + "field_id": 59837, + "width": 168, + "hidden": false, + "order": 14, + "aggregation_type": "sum", + "aggregation_raw_type": "sum" + }, + { + "id": 261350, + "field_id": 59757, + "width": 200, + "hidden": false, + "order": 15, + "aggregation_type": "", + "aggregation_raw_type": "" + } + ] + }, + { + "id": 26462, + "type": "grid", + "name": "Models with multiple cars in stock", + "order": 7, + "ownership_type": "collaborative", + "owned_by": null, + "filter_type": "AND", + "filters_disabled": false, + "filters": [ + { + "id": 13968, + "field_id": 59870, + "type": "higher_than", + "value": "1", + "group": null + } + ], + "filter_groups": [], + "sortings": [ + { + "id": 20342, + "field_id": 59747, + "order": "ASC" + }, + { + "id": 20343, + "field_id": 59758, + "order": "DESC" + } + ], + "group_bys": [], + "decorations": [], + "public": false, + "row_identifier_type": "count", + "row_height_size": "small", + "field_options": [ + { + "id": 261351, + "field_id": 59747, + "width": 179, + "hidden": false, + "order": 0, + "aggregation_type": "unique_count", + "aggregation_raw_type": "unique_count" + }, + { + "id": 261352, + "field_id": 59759, + "width": 121, + "hidden": false, + "order": 2, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261353, + "field_id": 59748, + "width": 177, + "hidden": false, + "order": 3, + "aggregation_type": "not_empty_percentage", + "aggregation_raw_type": "empty_count" + }, + { + "id": 261354, + "field_id": 59758, + "width": 142, + "hidden": false, + "order": 4, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261355, + "field_id": 59749, + "width": 194, + "hidden": false, + "order": 5, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261356, + "field_id": 59750, + "width": 164, + "hidden": false, + "order": 6, + "aggregation_type": "average", + "aggregation_raw_type": "average" + }, + { + "id": 261357, + "field_id": 59751, + "width": 143, + "hidden": false, + "order": 7, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261358, + "field_id": 59752, + "width": 130, + "hidden": false, + "order": 8, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261359, + "field_id": 59753, + "width": 148, + "hidden": false, + "order": 9, + "aggregation_type": "average", + "aggregation_raw_type": "average" + }, + { + "id": 261360, + "field_id": 59754, + "width": 169, + "hidden": false, + "order": 10, + "aggregation_type": "average", + "aggregation_raw_type": "average" + }, + { + "id": 261361, + "field_id": 59755, + "width": 166, + "hidden": false, + "order": 11, + "aggregation_type": "average", + "aggregation_raw_type": "average" + }, + { + "id": 261362, + "field_id": 59756, + "width": 169, + "hidden": false, + "order": 12, + "aggregation_type": "average", + "aggregation_raw_type": "average" + }, + { + "id": 261363, + "field_id": 59870, + "width": 168, + "hidden": false, + "order": 13, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261364, + "field_id": 59837, + "width": 168, + "hidden": false, + "order": 14, + "aggregation_type": "sum", + "aggregation_raw_type": "sum" + }, + { + "id": 261365, + "field_id": 59757, + "width": 200, + "hidden": false, + "order": 15, + "aggregation_type": "", + "aggregation_raw_type": "" + } + ] + }, + { + "id": 26463, + "type": "grid", + "name": "Models with no cars in stock", + "order": 8, + "ownership_type": "collaborative", + "owned_by": null, + "filter_type": "AND", + "filters_disabled": false, + "filters": [ + { + "id": 13969, + "field_id": 59870, + "type": "equal", + "value": "0", + "group": null + } + ], + "filter_groups": [], + "sortings": [ + { + "id": 20344, + "field_id": 59747, + "order": "ASC" + }, + { + "id": 20345, + "field_id": 59758, + "order": "DESC" + } + ], + "group_bys": [], + "decorations": [], + "public": false, + "row_identifier_type": "count", + "row_height_size": "small", + "field_options": [ + { + "id": 261366, + "field_id": 59747, + "width": 179, + "hidden": false, + "order": 0, + "aggregation_type": "unique_count", + "aggregation_raw_type": "unique_count" + }, + { + "id": 261367, + "field_id": 59759, + "width": 121, + "hidden": false, + "order": 2, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261368, + "field_id": 59748, + "width": 177, + "hidden": false, + "order": 3, + "aggregation_type": "not_empty_percentage", + "aggregation_raw_type": "empty_count" + }, + { + "id": 261369, + "field_id": 59758, + "width": 142, + "hidden": false, + "order": 4, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261370, + "field_id": 59749, + "width": 194, + "hidden": false, + "order": 5, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261371, + "field_id": 59750, + "width": 164, + "hidden": false, + "order": 6, + "aggregation_type": "average", + "aggregation_raw_type": "average" + }, + { + "id": 261372, + "field_id": 59751, + "width": 143, + "hidden": false, + "order": 7, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261373, + "field_id": 59752, + "width": 130, + "hidden": false, + "order": 8, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261374, + "field_id": 59753, + "width": 148, + "hidden": false, + "order": 9, + "aggregation_type": "average", + "aggregation_raw_type": "average" + }, + { + "id": 261375, + "field_id": 59754, + "width": 169, + "hidden": false, + "order": 10, + "aggregation_type": "average", + "aggregation_raw_type": "average" + }, + { + "id": 261376, + "field_id": 59755, + "width": 166, + "hidden": false, + "order": 11, + "aggregation_type": "average", + "aggregation_raw_type": "average" + }, + { + "id": 261377, + "field_id": 59756, + "width": 169, + "hidden": false, + "order": 12, + "aggregation_type": "average", + "aggregation_raw_type": "average" + }, + { + "id": 261378, + "field_id": 59870, + "width": 168, + "hidden": false, + "order": 13, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261379, + "field_id": 59837, + "width": 168, + "hidden": false, + "order": 14, + "aggregation_type": "sum", + "aggregation_raw_type": "sum" + }, + { + "id": 261380, + "field_id": 59757, + "width": 200, + "hidden": false, + "order": 15, + "aggregation_type": "", + "aggregation_raw_type": "" + } + ] + }, + { + "id": 26464, + "type": "gallery", + "name": "All models", + "order": 9, + "ownership_type": "collaborative", + "owned_by": null, + "filter_type": "AND", + "filters_disabled": false, + "filters": [], + "filter_groups": [], + "sortings": [ + { + "id": 20346, + "field_id": 59747, + "order": "ASC" + }, + { + "id": 20347, + "field_id": 59758, + "order": "DESC" + } + ], + "decorations": [], + "public": false, + "card_cover_image_field_id": 59748, + "field_options": [ + { + "id": 25465, + "field_id": 59758, + "hidden": false, + "order": 1 + }, + { + "id": 25466, + "field_id": 59747, + "hidden": false, + "order": 3 + }, + { + "id": 25467, + "field_id": 59748, + "hidden": true, + "order": 4 + }, + { + "id": 25468, + "field_id": 59749, + "hidden": false, + "order": 5 + }, + { + "id": 25469, + "field_id": 59750, + "hidden": false, + "order": 6 + }, + { + "id": 25470, + "field_id": 59751, + "hidden": false, + "order": 7 + }, + { + "id": 25471, + "field_id": 59752, + "hidden": false, + "order": 8 + }, + { + "id": 25472, + "field_id": 59753, + "hidden": false, + "order": 9 + }, + { + "id": 25473, + "field_id": 59754, + "hidden": false, + "order": 10 + }, + { + "id": 25474, + "field_id": 59755, + "hidden": false, + "order": 11 + }, + { + "id": 25475, + "field_id": 59756, + "hidden": false, + "order": 12 + }, + { + "id": 25476, + "field_id": 59870, + "hidden": false, + "order": 13 + }, + { + "id": 25477, + "field_id": 59837, + "hidden": true, + "order": 14 + }, + { + "id": 25478, + "field_id": 59757, + "hidden": true, + "order": 15 + }, + { + "id": 25479, + "field_id": 59759, + "hidden": true, + "order": 32767 + } + ] + } + ], + "rows": [ + { + "id": 1, + "order": "1.00000000000000000000", + "created_on": "2022-11-02T13:06:50.953041+00:00", + "updated_on": "2025-02-07T09:03:34.169191+00:00", + "last_modified_by": "frederik@baserow.io", + "field_59747": "Hilux Conquest 4x4", + "field_59748": [ + { + "name": "vgfuBJ6EhUe4GlifON1vKv8mt0dT1R4y_ca313dee2900ed76a0a5b361a3d81ed1bf4db348099559d7bae030f9c7889e13.jpg", + "visible_name": "W.Toyota.HiluxConquest4x4.EmotionalRed.jpg", + "original_name": "vgfuBJ6EhUe4GlifON1vKv8mt0dT1R4y_ca313dee2900ed76a0a5b361a3d81ed1bf4db348099559d7bae030f9c7889e13.jpg" + }, + { + "name": "XxhrwL7iwfbh7xGYSSB2xedXabgIaRkV_463242210ca93e61cc3fcade96df10c494cf1e3c17738fc861eb23d016f16dd3.jpg", + "visible_name": "W.Toyota.HiluxConquest4x4.SilverMetallic3.jpg", + "original_name": "XxhrwL7iwfbh7xGYSSB2xedXabgIaRkV_463242210ca93e61cc3fcade96df10c494cf1e3c17738fc861eb23d016f16dd3.jpg" + } + ], + "field_59749": 21041, + "field_59750": "2.80", + "field_59751": 21043, + "field_59752": 21047, + "field_59753": "5", + "field_59754": "5325", + "field_59755": "1900", + "field_59756": "1845", + "field_59870": null, + "field_59837": null, + "field_59757": [ + 1, + 2 + ], + "field_59758": "2025", + "field_59759": [ + 4 + ] + }, + { + "id": 2, + "order": "2.00000000000000000000", + "created_on": "2022-11-02T13:06:50.953123+00:00", + "updated_on": "2025-02-07T09:03:35.789118+00:00", + "last_modified_by": "frederik@baserow.io", + "field_59747": "Hilux E 4x2", + "field_59748": [ + { + "name": "xcSdi7nPqoMFg4jWdgl3KlDQ1FleC3gB_00cd9281d06e88536f994eaecd27abc2892dc4b598b2fe57e89045e395084cb0.jpg", + "visible_name": "W.Toyota.HiluxE4x2.SuperWhiteII.jpg", + "original_name": "xcSdi7nPqoMFg4jWdgl3KlDQ1FleC3gB_00cd9281d06e88536f994eaecd27abc2892dc4b598b2fe57e89045e395084cb0.jpg" + } + ], + "field_59749": 21041, + "field_59750": "2.40", + "field_59751": 21045, + "field_59752": 21047, + "field_59753": "5", + "field_59754": "5325", + "field_59755": "1855", + "field_59756": "1815", + "field_59870": null, + "field_59837": null, + "field_59757": [ + 3 + ], + "field_59758": "2025", + "field_59759": [ + 4 + ] + }, + { + "id": 3, + "order": "3.00000000000000000000", + "created_on": "2022-11-14T17:10:24.965898+00:00", + "updated_on": "2025-02-07T09:03:47.973853+00:00", + "last_modified_by": "frederik@baserow.io", + "field_59747": "Wigo TRD S", + "field_59748": [ + { + "name": "jkrX2KAJMrkxHO6VDy4GftKwvxk9udsr_56a17da6477b2e7d836de89b1c5f1da16478bf8f25598e0ce43bf9b901631e51.jpg", + "visible_name": "W.Toyota.WigoVVT-iG.YellowSE.jpg", + "original_name": "jkrX2KAJMrkxHO6VDy4GftKwvxk9udsr_56a17da6477b2e7d836de89b1c5f1da16478bf8f25598e0ce43bf9b901631e51.jpg" + }, + { + "name": "LRvq71iSNhQLBie78pfEsgjRgZJJ3rxe_c182124d365de839c8dee6f907302e44ea6cec7c9e9d5166ffb5e3260432d702.jpg", + "visible_name": "W.Toyota.WigoVVT-iG.OrangeMetallic2.jpg", + "original_name": "LRvq71iSNhQLBie78pfEsgjRgZJJ3rxe_c182124d365de839c8dee6f907302e44ea6cec7c9e9d5166ffb5e3260432d702.jpg" + } + ], + "field_59749": 21037, + "field_59750": "1.00", + "field_59751": 21043, + "field_59752": 21046, + "field_59753": "5", + "field_59754": "3700", + "field_59755": "1600", + "field_59756": "1520", + "field_59870": null, + "field_59837": null, + "field_59757": [ + 15, + 16 + ], + "field_59758": "2024", + "field_59759": [ + 4 + ] + }, + { + "id": 4, + "order": "4.00000000000000000000", + "created_on": "2022-11-14T17:12:57.270164+00:00", + "updated_on": "2025-02-07T09:03:49.519877+00:00", + "last_modified_by": "frederik@baserow.io", + "field_59747": "Wigo VVT-i G", + "field_59748": [ + { + "name": "B3WHnIiwFxJSpIbveAC0Xg9y4j2wAqJN_ea9b1bce8af01bf92b955937c170016aab6ee24390ba29d76b5fd34320837337.jpg", + "visible_name": "W.Toyota.WigoVVT-iG.SilverMetallic4.jpg", + "original_name": "B3WHnIiwFxJSpIbveAC0Xg9y4j2wAqJN_ea9b1bce8af01bf92b955937c170016aab6ee24390ba29d76b5fd34320837337.jpg" + }, + { + "name": "P9ju6OXajUhbu6A5kYD25stcF5S3rlao_a7455fa871b37d2fc2c62ea07e3a89144eaf794a35c8c274ef028cc470b7766b.jpg", + "visible_name": "W.Toyota.WigoVVT-iG.White2.jpg", + "original_name": "P9ju6OXajUhbu6A5kYD25stcF5S3rlao_a7455fa871b37d2fc2c62ea07e3a89144eaf794a35c8c274ef028cc470b7766b.jpg" + }, + { + "name": "8drR7hvqHt8F3g1sAvkiMp4Stxm31dFW_7729717ff60436cf63ef1fb59b7070531edcb3257ca7c98f707f7540d856fd36.jpg", + "visible_name": "W.Toyota.WigoVVT-iG.Black2.jpg", + "original_name": "8drR7hvqHt8F3g1sAvkiMp4Stxm31dFW_7729717ff60436cf63ef1fb59b7070531edcb3257ca7c98f707f7540d856fd36.jpg" + }, + { + "name": "b36UxiYGmgHH4KyxHRalqglL5oGLv5id_1dbc8731469dd3cc6409718ae730bd2e0b4d0f23b44f2ddc5b9d842fc0292ae3.jpg", + "visible_name": "W.Toyota.WigoVVT-iG.GrayMetallic.jpg", + "original_name": "b36UxiYGmgHH4KyxHRalqglL5oGLv5id_1dbc8731469dd3cc6409718ae730bd2e0b4d0f23b44f2ddc5b9d842fc0292ae3.jpg" + } + ], + "field_59749": 21037, + "field_59750": "1.00", + "field_59751": 21045, + "field_59752": 21046, + "field_59753": "5", + "field_59754": "3660", + "field_59755": "1600", + "field_59756": "1520", + "field_59870": null, + "field_59837": null, + "field_59757": [ + 11, + 12, + 13, + 14 + ], + "field_59758": "2024", + "field_59759": [ + 4 + ] + }, + { + "id": 5, + "order": "5.00000000000000000000", + "created_on": "2022-11-14T17:16:25.031648+00:00", + "updated_on": "2025-02-07T09:03:39.456008+00:00", + "last_modified_by": "frederik@baserow.io", + "field_59747": "Montero Sport GT 4WD", + "field_59748": [ + { + "name": "F1EwQzZbGCteQtygr8LH0ZinvOCIIIpE_611f54e37c09e874e0d3de0fd22917d18d23a0818b983a92cee6117ff7170be6.jpg", + "visible_name": "W.Mitsubishi.MonteroSportGT4WD.WhiteDiamond.jpg", + "original_name": "F1EwQzZbGCteQtygr8LH0ZinvOCIIIpE_611f54e37c09e874e0d3de0fd22917d18d23a0818b983a92cee6117ff7170be6.jpg" + } + ], + "field_59749": 21040, + "field_59750": "2.40", + "field_59751": 21043, + "field_59752": 21047, + "field_59753": "7", + "field_59754": "4825", + "field_59755": "1815", + "field_59756": "1835", + "field_59870": null, + "field_59837": null, + "field_59757": [ + 5, + 21 + ], + "field_59758": "2025", + "field_59759": [ + 3 + ] + }, + { + "id": 6, + "order": "6.00000000000000000000", + "created_on": "2022-11-14T17:16:26.330754+00:00", + "updated_on": "2025-02-07T09:03:37.349528+00:00", + "last_modified_by": "frederik@baserow.io", + "field_59747": "Montero Sport GLX 2WD", + "field_59748": [ + { + "name": "2mCiOLjywcG9Pxp3ScVH6i4R6qUJkokn_d78d7df18c4caa44154c400abfbcc66d8e96d16b3cf1470bf1d192bbe9bb5b13.jpg", + "visible_name": "W.Mitsubishi.MonteroSportGLX2WD.MediumRedMica.jpg", + "original_name": "2mCiOLjywcG9Pxp3ScVH6i4R6qUJkokn_d78d7df18c4caa44154c400abfbcc66d8e96d16b3cf1470bf1d192bbe9bb5b13.jpg" + } + ], + "field_59749": 21040, + "field_59750": "2.40", + "field_59751": 21045, + "field_59752": 21047, + "field_59753": "7", + "field_59754": "4825", + "field_59755": "1815", + "field_59756": "1835", + "field_59870": null, + "field_59837": null, + "field_59757": [ + 4, + 22 + ], + "field_59758": "2025", + "field_59759": [ + 3 + ] + }, + { + "id": 7, + "order": "6.00000000000000000000", + "created_on": "2022-11-14T17:16:27.141475+00:00", + "updated_on": "2025-02-07T09:05:59.440667+00:00", + "last_modified_by": "frederik@baserow.io", + "field_59747": "BR-V S", + "field_59748": [ + { + "name": "rlgcsGuezY0lUM3qmyoIjy1ogJ6oOg9q_0a27ed86416f028b55f7bf9b0d83eecc0758787fa5b5c6dcc4a570a68f892d54.jpg", + "visible_name": "W.Honda.BR-V.PassionRedPearl.jpg", + "original_name": "rlgcsGuezY0lUM3qmyoIjy1ogJ6oOg9q_0a27ed86416f028b55f7bf9b0d83eecc0758787fa5b5c6dcc4a570a68f892d54.jpg" + }, + { + "name": "OvWjzjlgF8HTWvPtZYQ0RCPpwPDkgxR1_ffbcaa5898e351ea7647b2624c725132bf311134c6867010e56a3ebf04a3bd3b.jpg", + "visible_name": "W.Honda.BR-V.LunarSilverMetallic.jpg", + "original_name": "OvWjzjlgF8HTWvPtZYQ0RCPpwPDkgxR1_ffbcaa5898e351ea7647b2624c725132bf311134c6867010e56a3ebf04a3bd3b.jpg" + }, + { + "name": "UiKZDI1h4b3E3eSEFKuDKPtNNnkRFFvN_278a4fe9762f86a26a72f1716d383e628970c28904fa9f177166d09a321450c9.jpg", + "visible_name": "W.Honda.BR-V.ModernSteelMetallic.jpg", + "original_name": "UiKZDI1h4b3E3eSEFKuDKPtNNnkRFFvN_278a4fe9762f86a26a72f1716d383e628970c28904fa9f177166d09a321450c9.jpg" + }, + { + "name": "hz0LOZs75tQjdtivb6HsMFHF3yQ9H4a0_a4d2f742193e21749c1cf1520b67ca43f6d5e21a80b0cf127c21f046b44ab3a0.jpg", + "visible_name": "W.Honda.BR-V.PlatinumWhitePearl.jpg", + "original_name": "hz0LOZs75tQjdtivb6HsMFHF3yQ9H4a0_a4d2f742193e21749c1cf1520b67ca43f6d5e21a80b0cf127c21f046b44ab3a0.jpg" + } + ], + "field_59749": 21038, + "field_59750": "1.50", + "field_59751": 21044, + "field_59752": 21046, + "field_59753": "7", + "field_59754": "4456", + "field_59755": "1735", + "field_59756": "1677", + "field_59870": null, + "field_59837": null, + "field_59757": [ + 8, + 9, + 17, + 18, + 19, + 25 + ], + "field_59758": "2021", + "field_59759": [ + 1 + ] + }, + { + "id": 8, + "order": "7.00000000000000000000", + "created_on": "2022-11-14T17:29:50.141041+00:00", + "updated_on": "2025-02-07T09:03:28.450903+00:00", + "last_modified_by": "frederik@baserow.io", + "field_59747": "BR-V V", + "field_59748": [ + { + "name": "OvWjzjlgF8HTWvPtZYQ0RCPpwPDkgxR1_ffbcaa5898e351ea7647b2624c725132bf311134c6867010e56a3ebf04a3bd3b.jpg", + "visible_name": "W.Honda.BR-V.LunarSilverMetallic.jpg", + "original_name": "OvWjzjlgF8HTWvPtZYQ0RCPpwPDkgxR1_ffbcaa5898e351ea7647b2624c725132bf311134c6867010e56a3ebf04a3bd3b.jpg" + }, + { + "name": "UiKZDI1h4b3E3eSEFKuDKPtNNnkRFFvN_278a4fe9762f86a26a72f1716d383e628970c28904fa9f177166d09a321450c9.jpg", + "visible_name": "W.Honda.BR-V.ModernSteelMetallic.jpg", + "original_name": "UiKZDI1h4b3E3eSEFKuDKPtNNnkRFFvN_278a4fe9762f86a26a72f1716d383e628970c28904fa9f177166d09a321450c9.jpg" + }, + { + "name": "rlgcsGuezY0lUM3qmyoIjy1ogJ6oOg9q_0a27ed86416f028b55f7bf9b0d83eecc0758787fa5b5c6dcc4a570a68f892d54.jpg", + "visible_name": "W.Honda.BR-V.PassionRedPearl.jpg", + "original_name": "rlgcsGuezY0lUM3qmyoIjy1ogJ6oOg9q_0a27ed86416f028b55f7bf9b0d83eecc0758787fa5b5c6dcc4a570a68f892d54.jpg" + }, + { + "name": "hz0LOZs75tQjdtivb6HsMFHF3yQ9H4a0_a4d2f742193e21749c1cf1520b67ca43f6d5e21a80b0cf127c21f046b44ab3a0.jpg", + "visible_name": "W.Honda.BR-V.PlatinumWhitePearl.jpg", + "original_name": "hz0LOZs75tQjdtivb6HsMFHF3yQ9H4a0_a4d2f742193e21749c1cf1520b67ca43f6d5e21a80b0cf127c21f046b44ab3a0.jpg" + } + ], + "field_59749": 21038, + "field_59750": "1.50", + "field_59751": 21044, + "field_59752": 21046, + "field_59753": "7", + "field_59754": "4456", + "field_59755": "1735", + "field_59756": "1677", + "field_59870": null, + "field_59837": null, + "field_59757": [ + 10, + 20, + 23, + 24 + ], + "field_59758": "2021", + "field_59759": [ + 1 + ] + }, + { + "id": 9, + "order": "7.00000000000000000000", + "created_on": "2022-11-14T17:29:50.849226+00:00", + "updated_on": "2025-02-07T09:03:44.261093+00:00", + "last_modified_by": "frederik@baserow.io", + "field_59747": "MX-5 Soft Top Skyactiv MT", + "field_59748": [ + { + "name": "T06UoJoSj72Rjy0OsFgScvhR8zNuxdX9_37c52f4247a412bac564abbffa4286a4e99f366d27f9184bfa72b6af8856ae93.jpg", + "visible_name": "W.Mazda.MX-5SoftTopSkyactiv.JetBlack.jpg", + "original_name": "T06UoJoSj72Rjy0OsFgScvhR8zNuxdX9_37c52f4247a412bac564abbffa4286a4e99f366d27f9184bfa72b6af8856ae93.jpg" + } + ], + "field_59749": 21035, + "field_59750": "2.00", + "field_59751": 21045, + "field_59752": 21046, + "field_59753": "2", + "field_59754": "3915", + "field_59755": "1735", + "field_59756": "1230", + "field_59870": null, + "field_59837": null, + "field_59757": [ + 7 + ], + "field_59758": "2022", + "field_59759": [ + 2 + ] + }, + { + "id": 10, + "order": "7.00000000000000000000", + "created_on": "2022-11-14T17:29:51.589942+00:00", + "updated_on": "2025-02-07T09:03:42.593612+00:00", + "last_modified_by": "frederik@baserow.io", + "field_59747": "MX-5 Soft Top Skyactiv AT", + "field_59748": [ + { + "name": "xTBjItLJMLlgyMtt1I1l3rj8jMr3zdDr_83b50585af3ae83f658fae94afde8a098a5988d5114841936ae7f64cd72eacf5.jpg", + "visible_name": "W.Mazda.MX-5SoftTopSkyactiv.SoulRedCrystal.jpg", + "original_name": "xTBjItLJMLlgyMtt1I1l3rj8jMr3zdDr_83b50585af3ae83f658fae94afde8a098a5988d5114841936ae7f64cd72eacf5.jpg" + } + ], + "field_59749": 21035, + "field_59750": "2.00", + "field_59751": 21043, + "field_59752": 21046, + "field_59753": "2", + "field_59754": "3915", + "field_59755": "1735", + "field_59756": "1230", + "field_59870": null, + "field_59837": null, + "field_59757": [ + 6 + ], + "field_59758": "2022", + "field_59759": [ + 2 + ] + } + ], + "data_sync": null + }, + { + "id": 5697, + "name": "Cars", + "order": 3, + "fields": [ + { + "id": 59760, + "type": "formula", + "name": "ID", + "description": null, + "order": 0, + "primary": true, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "number_suffix": "", + "number_separator": "", + "date_include_time": null, + "duration_format": null, + "date_force_timezone": null, + "date_show_tzinfo": null, + "array_formula_type": null, + "error": null, + "number_decimal_places": null, + "date_time_format": null, + "number_prefix": "", + "nullable": false, + "date_format": null, "formula": "concat( \n \"C\", \n if( \n row_id() < 10, \n concat(\"0000\", row_id()), \n if( \n row_id() < 100, \n concat(\"000\", row_id()), \n if( \n row_id() < 1000, \n concat(\"00\", row_id()), \n if( \n row_id() < 10000, \n concat(\"0\", row_id()), \n row_id() \n ) \n ) \n ) \n ) \n)", "formula_type": "text" }, { - "id": 705224, + "id": 59761, "type": "file", "name": "Photo", + "description": null, "order": 1, - "primary": false + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false }, { - "id": 705225, + "id": 59762, "type": "link_row", "name": "Model", + "description": null, "order": 2, "primary": false, - "link_row_table_id": 111552, - "link_row_related_field_id": 725741, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "link_row_table_id": 5696, + "link_row_related_field_id": 59757, + "link_row_limit_selection_view_id": null, "has_related_field": true }, { - "id": 725742, + "id": 59840, "type": "lookup", - "name": "Make", + "name": "Brand", + "description": null, "order": 3, "primary": false, - "error": null, - "date_format": null, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "number_suffix": "", + "number_separator": "", "date_include_time": null, - "date_time_format": null, + "duration_format": null, + "date_force_timezone": null, + "date_show_tzinfo": null, + "array_formula_type": "text", + "error": null, "number_decimal_places": null, - "array_formula_type": "single_select", - "through_field_id": 705225, + "date_time_format": null, + "number_prefix": "", + "nullable": true, + "date_format": null, + "through_field_id": 59762, "through_field_name": "Model", - "target_field_id": 705227, - "target_field_name": "Make" + "target_field_id": 59759, + "target_field_name": "Brand" }, { - "id": 725743, - "type": "number", + "id": 59841, + "type": "lookup", "name": "Year", + "description": null, "order": 4, "primary": false, - "number_decimal_places": 0, - "number_negative": false - }, - { - "id": 725744, - "type": "lookup", - "name": "Type", - "order": 5, - "primary": false, - "error": null, - "date_format": null, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "number_suffix": "", + "number_separator": "", "date_include_time": null, + "duration_format": null, + "date_force_timezone": null, + "date_show_tzinfo": null, + "array_formula_type": "number", + "error": null, + "number_decimal_places": 0, "date_time_format": null, - "number_decimal_places": null, - "array_formula_type": "single_select", - "through_field_id": 705225, + "number_prefix": "", + "nullable": true, + "date_format": null, + "through_field_id": 59762, "through_field_name": "Model", - "target_field_id": 705238, - "target_field_name": "Type" + "target_field_id": 59758, + "target_field_name": "Year model" }, { - "id": 725745, + "id": 59763, "type": "single_select", "name": "Condition", + "description": null, "order": 6, "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, "select_options": [ { - "id": 313850, + "id": 21052, "value": "Brand new", "color": "dark-green", "order": 0 }, { - "id": 313851, + "id": 21053, "value": "New old stock", "color": "green", "order": 1 }, { - "id": 313852, + "id": 21054, "value": "Refurbished", "color": "light-green", "order": 2 }, { - "id": 313853, + "id": 21055, "value": "Pre-owned", "color": "dark-orange", "order": 3 }, { - "id": 313854, + "id": 21056, "value": "Repossessed", "color": "orange", "order": 4 }, { - "id": 313855, + "id": 21057, "value": "Modified", "color": "dark-gray", "order": 5 @@ -150,329 +2612,501 @@ ] }, { - "id": 725746, + "id": 59764, "type": "number", "name": "Mileage", + "description": null, "order": 7, "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, "number_decimal_places": 0, - "number_negative": false + "number_negative": false, + "number_prefix": "", + "number_suffix": "", + "number_separator": "" }, { - "id": 725747, + "id": 59765, "type": "text", "name": "Color", + "description": null, "order": 8, "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, "text_default": "" }, { - "id": 725748, + "id": 59766, "type": "number", "name": "Breakeven cost", + "description": null, "order": 9, "primary": false, - "number_decimal_places": 2, - "number_negative": false + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "number_decimal_places": 0, + "number_negative": false, + "number_prefix": "$", + "number_suffix": "", + "number_separator": "SPACE_COMMA" }, { - "id": 725749, - "type": "single_select", + "id": 59867, + "type": "formula", "name": "Status", + "description": null, "order": 10, "primary": false, - "select_options": [ - { - "id": 313856, - "value": "Available", - "color": "dark-green", - "order": 0 - }, - { - "id": 313857, - "value": "Reserved", - "color": "light-gray", - "order": 1 - }, - { - "id": 313858, - "value": "For releasing", - "color": "gray", - "order": 2 - }, - { - "id": 313859, - "value": "Sold", - "color": "dark-gray", - "order": 3 - }, - { - "id": 313860, - "value": "On PMS", - "color": "red", - "order": 4 - }, - { - "id": 313861, - "value": "Under repair", - "color": "dark-red", - "order": 5 - } - ] + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "number_suffix": "", + "number_separator": "", + "date_include_time": null, + "duration_format": null, + "date_force_timezone": null, + "date_show_tzinfo": null, + "array_formula_type": null, + "error": null, + "number_decimal_places": null, + "date_time_format": null, + "number_prefix": "", + "nullable": false, + "date_format": null, + "formula": "if(field('Accepted offer') > 0,'Sold',if(field('Offers considered') > 0,'Under consideration','Available'))", + "formula_type": "text" }, { - "id": 725750, + "id": 59767, "type": "link_row", - "name": "Sale reference", + "name": "Offers", + "description": null, "order": 11, "primary": false, - "link_row_table_id": 114523, - "link_row_related_field_id": 725851, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "link_row_table_id": 5698, + "link_row_related_field_id": 59781, + "link_row_limit_selection_view_id": null, "has_related_field": true }, { - "id": 725751, + "id": 59768, "type": "number", - "name": "Suggested markup (%)", + "name": "Profit margin", + "description": null, "order": 12, "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, "number_decimal_places": 0, - "number_negative": false + "number_negative": false, + "number_prefix": "", + "number_suffix": "%", + "number_separator": "" }, { - "id": 725752, + "id": 59842, "type": "formula", "name": "Suggested price", + "description": null, "order": 13, "primary": false, - "error": null, - "date_format": null, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "number_suffix": "", + "number_separator": "SPACE_COMMA", "date_include_time": null, - "date_time_format": null, - "number_decimal_places": 2, + "duration_format": null, + "date_force_timezone": null, + "date_show_tzinfo": null, "array_formula_type": null, - "formula": "divide( \n multiply( \n field(\"Breakeven cost\"), \n add( \n field(\"Suggested markup (%)\"), \n 100 \n ) \n ), \n 100\n)", + "error": null, + "number_decimal_places": 0, + "date_time_format": null, + "number_prefix": "$", + "nullable": false, + "date_format": null, + "formula": "field('Breakeven cost') + (field('Breakeven cost') * (field('Profit margin') / 100))", "formula_type": "number" }, { - "id": 725753, + "id": 59769, "type": "long_text", "name": "Accessories", + "description": null, "order": 14, - "primary": false + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "long_text_enable_rich_text": false }, { - "id": 725755, + "id": 59770, "type": "text", "name": "Plate number", + "description": null, "order": 16, "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, "text_default": "" }, { - "id": 725756, + "id": 59771, "type": "text", "name": "VIN", + "description": null, "order": 17, "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, "text_default": "" }, { - "id": 725757, + "id": 59772, "type": "file", "name": "Certificate of title", + "description": null, "order": 18, - "primary": false + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false }, { - "id": 725758, + "id": 59773, "type": "date", "name": "Date acquired", + "description": null, "order": 19, "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, "date_format": "ISO", "date_include_time": false, - "date_time_format": "24" + "date_time_format": "24", + "date_show_tzinfo": false, + "date_force_timezone": null }, { - "id": 725759, + "id": 59774, "type": "link_row", "name": "Acquired by", + "description": null, "order": 20, "primary": false, - "link_row_table_id": 114512, - "link_row_related_field_id": 725868, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "link_row_table_id": 5700, + "link_row_related_field_id": 59804, + "link_row_limit_selection_view_id": null, "has_related_field": true }, { - "id": 725788, + "id": 59775, "type": "link_row", "name": "Branch", + "description": null, "order": 21, "primary": false, - "link_row_table_id": 111553, - "link_row_related_field_id": 725789, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "link_row_table_id": 5699, + "link_row_related_field_id": 59797, + "link_row_limit_selection_view_id": null, "has_related_field": true }, { - "id": 725869, + "id": 59776, "type": "long_text", "name": "Remarks", + "description": null, "order": 22, - "primary": false + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "long_text_enable_rich_text": false }, { - "id": 725899, + "id": 59866, "type": "formula", "name": "Actual profit", + "description": null, "order": 23, "primary": false, - "error": null, - "date_format": null, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "number_suffix": "", + "number_separator": "SPACE_COMMA", "date_include_time": null, - "date_time_format": null, - "number_decimal_places": 2, - "array_formula_type": "number", - "formula": "minus( \n lookup(\"Sale reference\", \"Price sold\"), \n field(\"Breakeven cost\") \n)", - "formula_type": "array" - }, - { - "id": 735944, - "type": "formula", - "name": "In stock", - "order": 24, - "primary": false, - "error": null, - "date_format": null, - "date_include_time": null, - "date_time_format": null, - "number_decimal_places": null, + "duration_format": null, + "date_force_timezone": null, + "date_show_tzinfo": null, "array_formula_type": null, - "formula": "if( \n or( \n totext(field(\"Status\"))=\"For releasing\", \n totext(field(\"Status\"))=\"Sold\" \n ), \n false, \n true \n)", - "formula_type": "boolean" + "error": null, + "number_decimal_places": 0, + "date_time_format": null, + "number_prefix": "$", + "nullable": false, + "date_format": null, + "formula": "if(isblank(field('Accepted offer')),0,sum(filter(lookup('Offers','Price offer'),totext(lookup('Offers','Status')) = 'Offer accepted')) - field('Breakeven cost'))", + "formula_type": "number" }, { - "id": 738833, + "id": 59777, "type": "text", "name": "Engine number", + "description": null, "order": 25, "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, "text_default": "" }, { - "id": 738895, + "id": 59843, "type": "formula", - "name": "Model for sorting", + "name": "Accepted offer", + "description": null, "order": 26, "primary": false, - "error": null, - "date_format": null, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "number_suffix": "", + "number_separator": "SPACE_COMMA", "date_include_time": null, - "date_time_format": null, - "number_decimal_places": null, + "duration_format": null, + "date_force_timezone": null, + "date_show_tzinfo": null, "array_formula_type": null, - "formula": "totext(join(field(\"Model\"), \"\"))", + "error": null, + "number_decimal_places": 0, + "date_time_format": null, + "number_prefix": "$", + "nullable": false, + "date_format": null, + "formula": "min(filter(lookup('Offers','Price offer'),totext(lookup('Offers','Status')) = 'Offer accepted'))", + "formula_type": "number" + }, + { + "id": 59844, + "type": "formula", + "name": "Offers considered", + "description": null, + "order": 27, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "number_suffix": "", + "number_separator": "", + "date_include_time": null, + "duration_format": null, + "date_force_timezone": null, + "date_show_tzinfo": null, + "array_formula_type": null, + "error": null, + "number_decimal_places": 0, + "date_time_format": null, + "number_prefix": "", + "nullable": false, + "date_format": null, + "formula": "count(filter(lookup('Offers','ID'),totext(lookup('Offers','Status')) = 'Under consideration'))", + "formula_type": "number" + }, + { + "id": 59848, + "type": "lookup", + "name": "Type", + "description": null, + "order": 28, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "number_suffix": "", + "number_separator": "", + "date_include_time": null, + "duration_format": null, + "date_force_timezone": null, + "date_show_tzinfo": null, + "array_formula_type": "single_select", + "error": null, + "number_decimal_places": null, + "date_time_format": null, + "number_prefix": "", + "nullable": true, + "date_format": null, + "through_field_id": 59762, + "through_field_name": "Model", + "target_field_id": 59749, + "target_field_name": "Type" + }, + { + "id": 59849, + "type": "formula", + "name": "Dimensions", + "description": null, + "order": 29, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "number_suffix": "", + "number_separator": "", + "date_include_time": null, + "duration_format": null, + "date_force_timezone": null, + "date_show_tzinfo": null, + "array_formula_type": null, + "error": null, + "number_decimal_places": null, + "date_time_format": null, + "number_prefix": "", + "nullable": false, + "date_format": null, + "formula": "concat(min(lookup('Model','Body length')),'mm x ',min(lookup('Model','Body width')),'mm x ',min(lookup('Model','Body height')),'mm')", "formula_type": "text" }, { - "id": 738896, - "type": "formula", - "name": "Make for sorting", - "order": 27, + "id": 59778, + "type": "link_row", + "name": "Reviews", + "description": null, + "order": 30, "primary": false, - "error": null, - "date_format": null, - "date_include_time": null, - "date_time_format": null, - "number_decimal_places": null, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "link_row_table_id": 5702, + "link_row_related_field_id": 59826, + "link_row_limit_selection_view_id": null, + "has_related_field": true + }, + { + "id": 59779, + "type": "formula", + "name": "Today", + "description": null, + "order": 31, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "number_suffix": "", + "number_separator": "", + "date_include_time": false, + "duration_format": null, + "date_force_timezone": "UTC", + "date_show_tzinfo": false, "array_formula_type": null, - "formula": "join(totext(field(\"Make\")), \"\")", - "formula_type": "text" + "error": null, + "number_decimal_places": null, + "date_time_format": "24", + "number_prefix": "", + "nullable": true, + "date_format": "ISO", + "formula": "today()", + "formula_type": "date" } ], "views": [ { - "id": 164490, + "id": 26465, "type": "grid", "name": "All vehicles", "order": 1, + "ownership_type": "collaborative", + "owned_by": null, "filter_type": "AND", "filters_disabled": false, "filters": [], + "filter_groups": [], "sortings": [ { - "id": 53130, - "field_id": 738896, + "id": 20348, + "field_id": 59762, "order": "ASC" }, { - "id": 53131, - "field_id": 738895, - "order": "ASC" - }, - { - "id": 53132, - "field_id": 725743, + "id": 20349, + "field_id": 59841, "order": "DESC" }, { - "id": 53133, - "field_id": 725749, + "id": 20350, + "field_id": 59867, "order": "ASC" } ], + "group_bys": [], "decorations": [ { - "id": 6984, + "id": 8728, "type": "left_border_color", "value_provider_type": "conditional_color", "value_provider_conf": { "colors": [ { - "color": "dark-green", + "id": "54f93ff9-a65a-4ee5-8b9d-791af0cdb89f", + "color": "deep-dark-green", "filters": [ { - "id": "7777904c-d041-4484-973d-1556329b8128", - "type": "single_select_equal", - "field": 725749, - "value": "313856" + "id": "8d8e010f-1f78-4729-87ff-f3d0667e600f", + "type": "equal", + "field": 59867, + "group": null, + "value": "Available" } ], "operator": "AND" }, { - "color": "dark-gray", + "id": "5904e484-67ba-421d-94be-2e0f499c0bde", + "color": "darker-yellow", "filters": [ { - "id": "24f4f264-42e7-4fa6-852a-10f34270e0b3", - "type": "single_select_equal", - "field": 725749, - "value": "313859" + "id": "8706a911-a742-41b0-9839-ebdde5e2f83a", + "type": "equal", + "field": 59867, + "group": null, + "value": "Under consideration" } ], "operator": "AND" - } - ] - }, - "order": 1 - }, - { - "id": 6985, - "type": "background_color", - "value_provider_type": "conditional_color", - "value_provider_conf": { - "colors": [ + }, { - "color": "light-gray", + "id": "9b24c3b6-912c-4c52-a2a0-b37fbc00f20b", + "color": "darker-red", "filters": [ { - "id": "dbebd8a4-9c7d-4cca-ae5f-dc18435cd2ff", - "type": "not_empty", - "field": 725750, - "value": "" + "id": "cee21683-e704-4ec9-9d37-6ff2961fb64e", + "type": "equal", + "field": 59867, + "group": null, + "value": "Sold" } ], - "operator": "OR" + "operator": "AND" } ] }, @@ -480,11 +3114,12 @@ } ], "public": false, - "row_identifier_type": "count", + "row_identifier_type": "id", + "row_height_size": "small", "field_options": [ { - "id": 1001353, - "field_id": 705223, + "id": 261381, + "field_id": 59760, "width": 100, "hidden": false, "order": 0, @@ -492,17 +3127,17 @@ "aggregation_raw_type": "unique_count" }, { - "id": 1001351, - "field_id": 705224, - "width": 100, + "id": 261382, + "field_id": 59761, + "width": 113, "hidden": false, "order": 1, "aggregation_type": "not_empty_percentage", "aggregation_raw_type": "empty_count" }, { - "id": 1001352, - "field_id": 705225, + "id": 261383, + "field_id": 59762, "width": 169, "hidden": false, "order": 2, @@ -510,312 +3145,326 @@ "aggregation_raw_type": "empty_count" }, { - "id": 1041771, - "field_id": 725742, - "width": 100, + "id": 261384, + "field_id": 59840, + "width": 125, "hidden": false, "order": 3, "aggregation_type": "", "aggregation_raw_type": "" }, { - "id": 1041772, - "field_id": 725743, + "id": 261385, + "field_id": 59841, "width": 100, "hidden": false, "order": 4, - "aggregation_type": "not_empty_percentage", - "aggregation_raw_type": "empty_count" + "aggregation_type": "", + "aggregation_raw_type": "" }, { - "id": 1041773, - "field_id": 725744, - "width": 178, + "id": 261386, + "field_id": 59848, + "width": 200, "hidden": false, "order": 5, "aggregation_type": "", "aggregation_raw_type": "" }, { - "id": 1041774, - "field_id": 725745, - "width": 120, + "id": 261387, + "field_id": 59849, + "width": 234, + "hidden": true, + "order": 6, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261388, + "field_id": 59867, + "width": 114, "hidden": false, "order": 7, "aggregation_type": "", "aggregation_raw_type": "" }, { - "id": 1041775, - "field_id": 725746, - "width": 110, + "id": 261389, + "field_id": 59763, + "width": 132, "hidden": false, "order": 8, "aggregation_type": "", "aggregation_raw_type": "" }, { - "id": 1041776, - "field_id": 725747, - "width": 154, + "id": 261390, + "field_id": 59764, + "width": 132, "hidden": false, "order": 9, "aggregation_type": "", "aggregation_raw_type": "" }, { - "id": 1041777, - "field_id": 725748, - "width": 155, + "id": 261391, + "field_id": 59765, + "width": 154, "hidden": false, - "order": 11, - "aggregation_type": "sum", - "aggregation_raw_type": "sum" - }, - { - "id": 1041778, - "field_id": 725749, - "width": 114, - "hidden": false, - "order": 6, + "order": 10, "aggregation_type": "", "aggregation_raw_type": "" }, { - "id": 1041779, - "field_id": 725750, - "width": 149, + "id": 261392, + "field_id": 59770, + "width": 153, "hidden": false, - "order": 14, - "aggregation_type": "not_empty_percentage", - "aggregation_raw_type": "empty_count" + "order": 11, + "aggregation_type": "unique_count", + "aggregation_raw_type": "unique_count" }, { - "id": 1041780, - "field_id": 725751, - "width": 199, + "id": 261393, + "field_id": 59766, + "width": 174, "hidden": false, "order": 12, - "aggregation_type": "average", - "aggregation_raw_type": "average" - }, - { - "id": 1041781, - "field_id": 725752, - "width": 159, - "hidden": false, - "order": 13, "aggregation_type": "sum", "aggregation_raw_type": "sum" }, { - "id": 1041789, - "field_id": 725753, - "width": 200, + "id": 261394, + "field_id": 59768, + "width": 152, + "hidden": false, + "order": 13, + "aggregation_type": "average", + "aggregation_raw_type": "average" + }, + { + "id": 261395, + "field_id": 59842, + "width": 179, + "hidden": false, + "order": 14, + "aggregation_type": "sum", + "aggregation_raw_type": "sum" + }, + { + "id": 261396, + "field_id": 59767, + "width": 167, + "hidden": false, + "order": 15, + "aggregation_type": "not_empty_percentage", + "aggregation_raw_type": "empty_count" + }, + { + "id": 261397, + "field_id": 59844, + "width": 186, "hidden": false, "order": 16, "aggregation_type": "", "aggregation_raw_type": "" }, { - "id": 1041791, - "field_id": 725755, - "width": 144, - "hidden": false, - "order": 10, - "aggregation_type": "unique_count", - "aggregation_raw_type": "unique_count" - }, - { - "id": 1041792, - "field_id": 725756, - "width": 163, + "id": 261398, + "field_id": 59843, + "width": 174, "hidden": false, "order": 17, - "aggregation_type": "unique_count", - "aggregation_raw_type": "unique_count" + "aggregation_type": "", + "aggregation_raw_type": "" }, { - "id": 1041793, - "field_id": 725757, - "width": 165, + "id": 261399, + "field_id": 59866, + "width": 160, "hidden": false, - "order": 23, - "aggregation_type": "not_empty_percentage", - "aggregation_raw_type": "empty_count" + "order": 18, + "aggregation_type": "", + "aggregation_raw_type": "" }, { - "id": 1041794, - "field_id": 725758, - "width": 147, + "id": 261400, + "field_id": 59769, + "width": 200, "hidden": false, "order": 19, "aggregation_type": "", "aggregation_raw_type": "" }, { - "id": 1041795, - "field_id": 725759, - "width": 152, - "hidden": false, - "order": 21, - "aggregation_type": "not_empty_percentage", - "aggregation_raw_type": "empty_count" - }, - { - "id": 1041812, - "field_id": 725788, - "width": 138, + "id": 261401, + "field_id": 59771, + "width": 163, "hidden": false, "order": 20, - "aggregation_type": "not_empty_percentage", - "aggregation_raw_type": "empty_count" + "aggregation_type": "unique_count", + "aggregation_raw_type": "unique_count" }, { - "id": 1041982, - "field_id": 725869, - "width": 173, + "id": 261402, + "field_id": 59777, + "width": 154, + "hidden": false, + "order": 21, + "aggregation_type": "unique_count", + "aggregation_raw_type": "unique_count" + }, + { + "id": 261403, + "field_id": 59773, + "width": 162, "hidden": false, "order": 22, "aggregation_type": "", "aggregation_raw_type": "" }, { - "id": 1042013, - "field_id": 725899, - "width": 136, + "id": 261404, + "field_id": 59775, + "width": 138, "hidden": false, - "order": 15, - "aggregation_type": "", - "aggregation_raw_type": "" - }, - { - "id": 1059310, - "field_id": 735944, - "width": 108, - "hidden": true, - "order": 24, - "aggregation_type": "checked_count", + "order": 23, + "aggregation_type": "not_empty_percentage", "aggregation_raw_type": "empty_count" }, { - "id": 1063744, - "field_id": 738833, - "width": 154, + "id": 261405, + "field_id": 59774, + "width": 152, "hidden": false, - "order": 18, - "aggregation_type": "unique_count", - "aggregation_raw_type": "unique_count" + "order": 24, + "aggregation_type": "not_empty_percentage", + "aggregation_raw_type": "empty_count" }, { - "id": 1063858, - "field_id": 738895, - "width": 181, - "hidden": true, + "id": 261406, + "field_id": 59776, + "width": 173, + "hidden": false, "order": 25, "aggregation_type": "", "aggregation_raw_type": "" }, { - "id": 1063859, - "field_id": 738896, - "width": 161, - "hidden": true, + "id": 261407, + "field_id": 59772, + "width": 194, + "hidden": false, "order": 26, + "aggregation_type": "not_empty_percentage", + "aggregation_raw_type": "empty_count" + }, + { + "id": 261408, + "field_id": 59778, + "width": 200, + "hidden": true, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261409, + "field_id": 59779, + "width": 200, + "hidden": true, + "order": 32767, "aggregation_type": "", "aggregation_raw_type": "" } ] }, { - "id": 174128, + "id": 26466, "type": "grid", - "name": "In stock", + "name": "Available vehicles without considered offer(s)", "order": 2, + "ownership_type": "collaborative", + "owned_by": null, "filter_type": "AND", "filters_disabled": false, "filters": [ { - "id": 68732, - "field_id": 735944, - "type": "boolean", - "value": "1" + "id": 13970, + "field_id": 59867, + "type": "equal", + "value": "Available", + "group": null } ], + "filter_groups": [], "sortings": [ { - "id": 53141, - "field_id": 738896, + "id": 20351, + "field_id": 59762, "order": "ASC" }, { - "id": 53142, - "field_id": 738895, - "order": "ASC" - }, - { - "id": 53143, - "field_id": 725743, + "id": 20352, + "field_id": 59841, "order": "DESC" }, { - "id": 53144, - "field_id": 725749, + "id": 20353, + "field_id": 59867, "order": "ASC" } ], + "group_bys": [], "decorations": [ { - "id": 6986, + "id": 8729, "type": "left_border_color", "value_provider_type": "conditional_color", "value_provider_conf": { "colors": [ { - "color": "dark-green", + "id": "54f93ff9-a65a-4ee5-8b9d-791af0cdb89f", + "color": "deep-dark-green", "filters": [ { - "id": "7777904c-d041-4484-973d-1556329b8128", - "type": "single_select_equal", - "field": 725749, - "value": "313856" + "id": "8d8e010f-1f78-4729-87ff-f3d0667e600f", + "type": "equal", + "field": 59867, + "group": null, + "value": "Available" } ], "operator": "AND" }, { - "color": "dark-gray", + "id": "5904e484-67ba-421d-94be-2e0f499c0bde", + "color": "darker-yellow", "filters": [ { - "id": "24f4f264-42e7-4fa6-852a-10f34270e0b3", - "type": "single_select_equal", - "field": 725749, - "value": "313859" + "id": "8706a911-a742-41b0-9839-ebdde5e2f83a", + "type": "equal", + "field": 59867, + "group": null, + "value": "Under consideration" } ], "operator": "AND" - } - ] - }, - "order": 1 - }, - { - "id": 6987, - "type": "background_color", - "value_provider_type": "conditional_color", - "value_provider_conf": { - "colors": [ + }, { - "color": "light-gray", + "id": "9b24c3b6-912c-4c52-a2a0-b37fbc00f20b", + "color": "darker-red", "filters": [ { - "id": "dbebd8a4-9c7d-4cca-ae5f-dc18435cd2ff", - "type": "not_empty", - "field": 725750, - "value": "" + "id": "cee21683-e704-4ec9-9d37-6ff2961fb64e", + "type": "equal", + "field": 59867, + "group": null, + "value": "Sold" } ], - "operator": "OR" + "operator": "AND" } ] }, @@ -824,10 +3473,11 @@ ], "public": false, "row_identifier_type": "count", + "row_height_size": "small", "field_options": [ { - "id": 1063943, - "field_id": 705223, + "id": 261410, + "field_id": 59760, "width": 100, "hidden": false, "order": 0, @@ -835,17 +3485,17 @@ "aggregation_raw_type": "unique_count" }, { - "id": 1063944, - "field_id": 705224, - "width": 100, + "id": 261411, + "field_id": 59761, + "width": 113, "hidden": false, "order": 1, "aggregation_type": "not_empty_percentage", "aggregation_raw_type": "empty_count" }, { - "id": 1063945, - "field_id": 705225, + "id": 261412, + "field_id": 59762, "width": 169, "hidden": false, "order": 2, @@ -853,71 +3503,35 @@ "aggregation_raw_type": "empty_count" }, { - "id": 1063946, - "field_id": 725742, - "width": 100, + "id": 261413, + "field_id": 59840, + "width": 125, "hidden": false, "order": 3, "aggregation_type": "", "aggregation_raw_type": "" }, { - "id": 1063947, - "field_id": 725743, + "id": 261414, + "field_id": 59841, "width": 100, "hidden": false, "order": 4, - "aggregation_type": "not_empty_percentage", - "aggregation_raw_type": "empty_count" + "aggregation_type": "", + "aggregation_raw_type": "" }, { - "id": 1063948, - "field_id": 725744, - "width": 178, + "id": 261415, + "field_id": 59848, + "width": 200, "hidden": false, "order": 5, "aggregation_type": "", "aggregation_raw_type": "" }, { - "id": 1063949, - "field_id": 725745, - "width": 120, - "hidden": false, - "order": 7, - "aggregation_type": "", - "aggregation_raw_type": "" - }, - { - "id": 1063950, - "field_id": 725746, - "width": 110, - "hidden": false, - "order": 8, - "aggregation_type": "", - "aggregation_raw_type": "" - }, - { - "id": 1063951, - "field_id": 725747, - "width": 154, - "hidden": false, - "order": 9, - "aggregation_type": "", - "aggregation_raw_type": "" - }, - { - "id": 1063952, - "field_id": 725748, - "width": 154, - "hidden": false, - "order": 11, - "aggregation_type": "sum", - "aggregation_raw_type": "sum" - }, - { - "id": 1063953, - "field_id": 725749, + "id": 261416, + "field_id": 59867, "width": 114, "hidden": false, "order": 6, @@ -925,240 +3539,272 @@ "aggregation_raw_type": "" }, { - "id": 1063954, - "field_id": 725750, - "width": 149, + "id": 261417, + "field_id": 59763, + "width": 132, "hidden": false, - "order": 14, - "aggregation_type": "not_empty_percentage", - "aggregation_raw_type": "empty_count" - }, - { - "id": 1063955, - "field_id": 725751, - "width": 199, - "hidden": false, - "order": 12, - "aggregation_type": "average", - "aggregation_raw_type": "average" - }, - { - "id": 1063956, - "field_id": 725752, - "width": 159, - "hidden": false, - "order": 13, - "aggregation_type": "sum", - "aggregation_raw_type": "sum" - }, - { - "id": 1063957, - "field_id": 725753, - "width": 200, - "hidden": false, - "order": 16, + "order": 7, "aggregation_type": "", "aggregation_raw_type": "" }, { - "id": 1063958, - "field_id": 725755, - "width": 144, + "id": 261418, + "field_id": 59764, + "width": 132, + "hidden": false, + "order": 8, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261419, + "field_id": 59765, + "width": 154, + "hidden": false, + "order": 9, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261420, + "field_id": 59770, + "width": 153, "hidden": false, "order": 10, "aggregation_type": "unique_count", "aggregation_raw_type": "unique_count" }, { - "id": 1063959, - "field_id": 725756, - "width": 163, + "id": 261421, + "field_id": 59766, + "width": 174, "hidden": false, - "order": 17, - "aggregation_type": "unique_count", - "aggregation_raw_type": "unique_count" + "order": 11, + "aggregation_type": "sum", + "aggregation_raw_type": "sum" }, { - "id": 1063960, - "field_id": 725757, - "width": 165, - "hidden": false, - "order": 23, - "aggregation_type": "not_empty_percentage", - "aggregation_raw_type": "empty_count" - }, - { - "id": 1063961, - "field_id": 725758, - "width": 147, - "hidden": false, - "order": 19, - "aggregation_type": "", - "aggregation_raw_type": "" - }, - { - "id": 1063962, - "field_id": 725759, + "id": 261422, + "field_id": 59768, "width": 152, "hidden": false, - "order": 21, + "order": 12, + "aggregation_type": "average", + "aggregation_raw_type": "average" + }, + { + "id": 261423, + "field_id": 59842, + "width": 179, + "hidden": false, + "order": 13, + "aggregation_type": "sum", + "aggregation_raw_type": "sum" + }, + { + "id": 261424, + "field_id": 59767, + "width": 167, + "hidden": false, + "order": 14, "aggregation_type": "not_empty_percentage", "aggregation_raw_type": "empty_count" }, { - "id": 1063963, - "field_id": 725788, - "width": 138, - "hidden": false, - "order": 20, - "aggregation_type": "not_empty_percentage", - "aggregation_raw_type": "empty_count" - }, - { - "id": 1063964, - "field_id": 725869, - "width": 173, - "hidden": false, - "order": 22, - "aggregation_type": "", - "aggregation_raw_type": "" - }, - { - "id": 1063965, - "field_id": 725899, - "width": 136, + "id": 261425, + "field_id": 59844, + "width": 186, "hidden": false, "order": 15, "aggregation_type": "", "aggregation_raw_type": "" }, { - "id": 1063966, - "field_id": 735944, - "width": 108, - "hidden": true, - "order": 24, - "aggregation_type": "checked_count", - "aggregation_raw_type": "empty_count" - }, - { - "id": 1063967, - "field_id": 738833, - "width": 154, + "id": 261426, + "field_id": 59843, + "width": 174, "hidden": false, - "order": 18, - "aggregation_type": "unique_count", - "aggregation_raw_type": "unique_count" - }, - { - "id": 1063968, - "field_id": 738895, - "width": 181, - "hidden": true, - "order": 25, + "order": 16, "aggregation_type": "", "aggregation_raw_type": "" }, { - "id": 1063969, - "field_id": 738896, - "width": 161, + "id": 261427, + "field_id": 59866, + "width": 160, + "hidden": false, + "order": 17, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261428, + "field_id": 59769, + "width": 200, + "hidden": false, + "order": 18, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261429, + "field_id": 59771, + "width": 163, + "hidden": false, + "order": 19, + "aggregation_type": "unique_count", + "aggregation_raw_type": "unique_count" + }, + { + "id": 261430, + "field_id": 59777, + "width": 154, + "hidden": false, + "order": 20, + "aggregation_type": "unique_count", + "aggregation_raw_type": "unique_count" + }, + { + "id": 261431, + "field_id": 59773, + "width": 162, + "hidden": false, + "order": 21, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261432, + "field_id": 59775, + "width": 138, + "hidden": false, + "order": 22, + "aggregation_type": "not_empty_percentage", + "aggregation_raw_type": "empty_count" + }, + { + "id": 261433, + "field_id": 59774, + "width": 152, + "hidden": false, + "order": 23, + "aggregation_type": "not_empty_percentage", + "aggregation_raw_type": "empty_count" + }, + { + "id": 261434, + "field_id": 59776, + "width": 173, + "hidden": false, + "order": 24, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261435, + "field_id": 59772, + "width": 194, + "hidden": false, + "order": 25, + "aggregation_type": "not_empty_percentage", + "aggregation_raw_type": "empty_count" + }, + { + "id": 261436, + "field_id": 59849, + "width": 200, "hidden": true, - "order": 26, + "order": 32767, "aggregation_type": "", "aggregation_raw_type": "" } ] }, { - "id": 174129, + "id": 26467, "type": "grid", - "name": "Sold", + "name": "Available vehicles with considered offer(s)", "order": 3, + "ownership_type": "collaborative", + "owned_by": null, "filter_type": "AND", "filters_disabled": false, "filters": [ { - "id": 68733, - "field_id": 735944, - "type": "boolean", - "value": "0" + "id": 13971, + "field_id": 59867, + "type": "equal", + "value": "Under consideration", + "group": null } ], + "filter_groups": [], "sortings": [ { - "id": 53145, - "field_id": 738896, + "id": 20354, + "field_id": 59762, "order": "ASC" }, { - "id": 53146, - "field_id": 738895, - "order": "ASC" - }, - { - "id": 53147, - "field_id": 725743, + "id": 20355, + "field_id": 59841, "order": "DESC" }, { - "id": 53148, - "field_id": 725749, + "id": 20356, + "field_id": 59867, "order": "ASC" } ], + "group_bys": [], "decorations": [ { - "id": 6988, + "id": 8730, "type": "left_border_color", "value_provider_type": "conditional_color", "value_provider_conf": { "colors": [ { - "color": "dark-green", + "id": "54f93ff9-a65a-4ee5-8b9d-791af0cdb89f", + "color": "deep-dark-green", "filters": [ { - "id": "7777904c-d041-4484-973d-1556329b8128", - "type": "single_select_equal", - "field": 725749, - "value": "313856" + "id": "8d8e010f-1f78-4729-87ff-f3d0667e600f", + "type": "equal", + "field": 59867, + "group": null, + "value": "Available" } ], "operator": "AND" }, { - "color": "dark-gray", + "id": "5904e484-67ba-421d-94be-2e0f499c0bde", + "color": "darker-yellow", "filters": [ { - "id": "24f4f264-42e7-4fa6-852a-10f34270e0b3", - "type": "single_select_equal", - "field": 725749, - "value": "313859" + "id": "8706a911-a742-41b0-9839-ebdde5e2f83a", + "type": "equal", + "field": 59867, + "group": null, + "value": "Under consideration" } ], "operator": "AND" - } - ] - }, - "order": 1 - }, - { - "id": 6989, - "type": "background_color", - "value_provider_type": "conditional_color", - "value_provider_conf": { - "colors": [ + }, { - "color": "light-gray", + "id": "9b24c3b6-912c-4c52-a2a0-b37fbc00f20b", + "color": "darker-red", "filters": [ { - "id": "dbebd8a4-9c7d-4cca-ae5f-dc18435cd2ff", - "type": "not_empty", - "field": 725750, - "value": "" + "id": "cee21683-e704-4ec9-9d37-6ff2961fb64e", + "type": "equal", + "field": 59867, + "group": null, + "value": "Sold" } ], - "operator": "OR" + "operator": "AND" } ] }, @@ -1167,10 +3813,11 @@ ], "public": false, "row_identifier_type": "count", + "row_height_size": "small", "field_options": [ { - "id": 1063971, - "field_id": 705223, + "id": 261437, + "field_id": 59760, "width": 100, "hidden": false, "order": 0, @@ -1178,17 +3825,17 @@ "aggregation_raw_type": "unique_count" }, { - "id": 1063972, - "field_id": 705224, - "width": 100, + "id": 261438, + "field_id": 59761, + "width": 113, "hidden": false, "order": 1, "aggregation_type": "not_empty_percentage", "aggregation_raw_type": "empty_count" }, { - "id": 1063973, - "field_id": 705225, + "id": 261439, + "field_id": 59762, "width": 169, "hidden": false, "order": 2, @@ -1196,71 +3843,35 @@ "aggregation_raw_type": "empty_count" }, { - "id": 1063974, - "field_id": 725742, - "width": 100, + "id": 261440, + "field_id": 59840, + "width": 125, "hidden": false, "order": 3, "aggregation_type": "", "aggregation_raw_type": "" }, { - "id": 1063975, - "field_id": 725743, + "id": 261441, + "field_id": 59841, "width": 100, "hidden": false, "order": 4, - "aggregation_type": "not_empty_percentage", - "aggregation_raw_type": "empty_count" + "aggregation_type": "", + "aggregation_raw_type": "" }, { - "id": 1063976, - "field_id": 725744, - "width": 178, + "id": 261442, + "field_id": 59848, + "width": 200, "hidden": false, "order": 5, "aggregation_type": "", "aggregation_raw_type": "" }, { - "id": 1063977, - "field_id": 725745, - "width": 120, - "hidden": false, - "order": 7, - "aggregation_type": "", - "aggregation_raw_type": "" - }, - { - "id": 1063978, - "field_id": 725746, - "width": 110, - "hidden": false, - "order": 8, - "aggregation_type": "", - "aggregation_raw_type": "" - }, - { - "id": 1063979, - "field_id": 725747, - "width": 154, - "hidden": false, - "order": 9, - "aggregation_type": "", - "aggregation_raw_type": "" - }, - { - "id": 1063980, - "field_id": 725748, - "width": 154, - "hidden": false, - "order": 11, - "aggregation_type": "sum", - "aggregation_raw_type": "sum" - }, - { - "id": 1063981, - "field_id": 725749, + "id": 261443, + "field_id": 59867, "width": 114, "hidden": false, "order": 6, @@ -1268,240 +3879,272 @@ "aggregation_raw_type": "" }, { - "id": 1063982, - "field_id": 725750, - "width": 149, + "id": 261444, + "field_id": 59763, + "width": 132, "hidden": false, - "order": 14, - "aggregation_type": "not_empty_percentage", - "aggregation_raw_type": "empty_count" - }, - { - "id": 1063983, - "field_id": 725751, - "width": 199, - "hidden": false, - "order": 12, - "aggregation_type": "average", - "aggregation_raw_type": "average" - }, - { - "id": 1063984, - "field_id": 725752, - "width": 159, - "hidden": false, - "order": 13, - "aggregation_type": "sum", - "aggregation_raw_type": "sum" - }, - { - "id": 1063985, - "field_id": 725753, - "width": 200, - "hidden": false, - "order": 16, + "order": 7, "aggregation_type": "", "aggregation_raw_type": "" }, { - "id": 1063986, - "field_id": 725755, - "width": 144, + "id": 261445, + "field_id": 59764, + "width": 132, + "hidden": false, + "order": 8, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261446, + "field_id": 59765, + "width": 154, + "hidden": false, + "order": 9, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261447, + "field_id": 59770, + "width": 153, "hidden": false, "order": 10, "aggregation_type": "unique_count", "aggregation_raw_type": "unique_count" }, { - "id": 1063987, - "field_id": 725756, - "width": 163, + "id": 261448, + "field_id": 59766, + "width": 174, "hidden": false, - "order": 17, - "aggregation_type": "unique_count", - "aggregation_raw_type": "unique_count" + "order": 11, + "aggregation_type": "sum", + "aggregation_raw_type": "sum" }, { - "id": 1063988, - "field_id": 725757, - "width": 165, - "hidden": false, - "order": 23, - "aggregation_type": "not_empty_percentage", - "aggregation_raw_type": "empty_count" - }, - { - "id": 1063989, - "field_id": 725758, - "width": 147, - "hidden": false, - "order": 19, - "aggregation_type": "", - "aggregation_raw_type": "" - }, - { - "id": 1063990, - "field_id": 725759, + "id": 261449, + "field_id": 59768, "width": 152, "hidden": false, - "order": 21, + "order": 12, + "aggregation_type": "average", + "aggregation_raw_type": "average" + }, + { + "id": 261450, + "field_id": 59842, + "width": 179, + "hidden": false, + "order": 13, + "aggregation_type": "sum", + "aggregation_raw_type": "sum" + }, + { + "id": 261451, + "field_id": 59767, + "width": 167, + "hidden": false, + "order": 14, "aggregation_type": "not_empty_percentage", "aggregation_raw_type": "empty_count" }, { - "id": 1063991, - "field_id": 725788, - "width": 138, - "hidden": false, - "order": 20, - "aggregation_type": "not_empty_percentage", - "aggregation_raw_type": "empty_count" - }, - { - "id": 1063992, - "field_id": 725869, - "width": 173, - "hidden": false, - "order": 22, - "aggregation_type": "", - "aggregation_raw_type": "" - }, - { - "id": 1063993, - "field_id": 725899, - "width": 136, + "id": 261452, + "field_id": 59844, + "width": 186, "hidden": false, "order": 15, "aggregation_type": "", "aggregation_raw_type": "" }, { - "id": 1063994, - "field_id": 735944, - "width": 108, - "hidden": true, - "order": 24, - "aggregation_type": "checked_count", - "aggregation_raw_type": "empty_count" - }, - { - "id": 1063995, - "field_id": 738833, - "width": 154, + "id": 261453, + "field_id": 59843, + "width": 174, "hidden": false, - "order": 18, - "aggregation_type": "unique_count", - "aggregation_raw_type": "unique_count" - }, - { - "id": 1063996, - "field_id": 738895, - "width": 181, - "hidden": true, - "order": 25, + "order": 16, "aggregation_type": "", "aggregation_raw_type": "" }, { - "id": 1063997, - "field_id": 738896, - "width": 161, + "id": 261454, + "field_id": 59866, + "width": 160, + "hidden": false, + "order": 17, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261455, + "field_id": 59769, + "width": 200, + "hidden": false, + "order": 18, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261456, + "field_id": 59771, + "width": 163, + "hidden": false, + "order": 19, + "aggregation_type": "unique_count", + "aggregation_raw_type": "unique_count" + }, + { + "id": 261457, + "field_id": 59777, + "width": 154, + "hidden": false, + "order": 20, + "aggregation_type": "unique_count", + "aggregation_raw_type": "unique_count" + }, + { + "id": 261458, + "field_id": 59773, + "width": 162, + "hidden": false, + "order": 21, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261459, + "field_id": 59775, + "width": 138, + "hidden": false, + "order": 22, + "aggregation_type": "not_empty_percentage", + "aggregation_raw_type": "empty_count" + }, + { + "id": 261460, + "field_id": 59774, + "width": 152, + "hidden": false, + "order": 23, + "aggregation_type": "not_empty_percentage", + "aggregation_raw_type": "empty_count" + }, + { + "id": 261461, + "field_id": 59776, + "width": 173, + "hidden": false, + "order": 24, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261462, + "field_id": 59772, + "width": 194, + "hidden": false, + "order": 25, + "aggregation_type": "not_empty_percentage", + "aggregation_raw_type": "empty_count" + }, + { + "id": 261463, + "field_id": 59849, + "width": 200, "hidden": true, - "order": 26, + "order": 32767, "aggregation_type": "", "aggregation_raw_type": "" } ] }, { - "id": 174132, + "id": 26468, "type": "grid", - "name": "On PMS", + "name": "Available vehicles", "order": 4, + "ownership_type": "collaborative", + "owned_by": null, "filter_type": "AND", "filters_disabled": false, "filters": [ { - "id": 68734, - "field_id": 725749, - "type": "single_select_equal", - "value": "313860" + "id": 13972, + "field_id": 59867, + "type": "not_equal", + "value": "Sold", + "group": null } ], + "filter_groups": [], "sortings": [ { - "id": 53149, - "field_id": 738896, + "id": 20357, + "field_id": 59762, "order": "ASC" }, { - "id": 53150, - "field_id": 738895, - "order": "ASC" - }, - { - "id": 53151, - "field_id": 725743, + "id": 20358, + "field_id": 59841, "order": "DESC" }, { - "id": 53152, - "field_id": 725749, + "id": 20359, + "field_id": 59867, "order": "ASC" } ], + "group_bys": [], "decorations": [ { - "id": 6990, + "id": 8731, "type": "left_border_color", "value_provider_type": "conditional_color", "value_provider_conf": { "colors": [ { - "color": "dark-green", + "id": "54f93ff9-a65a-4ee5-8b9d-791af0cdb89f", + "color": "deep-dark-green", "filters": [ { - "id": "7777904c-d041-4484-973d-1556329b8128", - "type": "single_select_equal", - "field": 725749, - "value": "313856" + "id": "8d8e010f-1f78-4729-87ff-f3d0667e600f", + "type": "equal", + "field": 59867, + "group": null, + "value": "Available" } ], "operator": "AND" }, { - "color": "dark-gray", + "id": "5904e484-67ba-421d-94be-2e0f499c0bde", + "color": "darker-yellow", "filters": [ { - "id": "24f4f264-42e7-4fa6-852a-10f34270e0b3", - "type": "single_select_equal", - "field": 725749, - "value": "313859" + "id": "8706a911-a742-41b0-9839-ebdde5e2f83a", + "type": "equal", + "field": 59867, + "group": null, + "value": "Under consideration" } ], "operator": "AND" - } - ] - }, - "order": 1 - }, - { - "id": 6991, - "type": "background_color", - "value_provider_type": "conditional_color", - "value_provider_conf": { - "colors": [ + }, { - "color": "light-gray", + "id": "9b24c3b6-912c-4c52-a2a0-b37fbc00f20b", + "color": "darker-red", "filters": [ { - "id": "dbebd8a4-9c7d-4cca-ae5f-dc18435cd2ff", - "type": "not_empty", - "field": 725750, - "value": "" + "id": "cee21683-e704-4ec9-9d37-6ff2961fb64e", + "type": "equal", + "field": 59867, + "group": null, + "value": "Sold" } ], - "operator": "OR" + "operator": "AND" } ] }, @@ -1510,10 +4153,11 @@ ], "public": false, "row_identifier_type": "count", + "row_height_size": "small", "field_options": [ { - "id": 1064003, - "field_id": 705223, + "id": 261464, + "field_id": 59760, "width": 100, "hidden": false, "order": 0, @@ -1521,17 +4165,17 @@ "aggregation_raw_type": "unique_count" }, { - "id": 1064004, - "field_id": 705224, - "width": 100, + "id": 261465, + "field_id": 59761, + "width": 113, "hidden": false, "order": 1, "aggregation_type": "not_empty_percentage", "aggregation_raw_type": "empty_count" }, { - "id": 1064005, - "field_id": 705225, + "id": 261466, + "field_id": 59762, "width": 169, "hidden": false, "order": 2, @@ -1539,53 +4183,62 @@ "aggregation_raw_type": "empty_count" }, { - "id": 1064006, - "field_id": 725742, - "width": 100, + "id": 261467, + "field_id": 59840, + "width": 125, "hidden": false, "order": 3, "aggregation_type": "", "aggregation_raw_type": "" }, { - "id": 1064007, - "field_id": 725743, + "id": 261468, + "field_id": 59841, "width": 100, "hidden": false, "order": 4, - "aggregation_type": "not_empty_percentage", - "aggregation_raw_type": "empty_count" + "aggregation_type": "", + "aggregation_raw_type": "" }, { - "id": 1064008, - "field_id": 725744, - "width": 178, + "id": 261469, + "field_id": 59848, + "width": 200, "hidden": false, "order": 5, "aggregation_type": "", "aggregation_raw_type": "" }, { - "id": 1064009, - "field_id": 725745, - "width": 120, + "id": 261470, + "field_id": 59867, + "width": 170, + "hidden": false, + "order": 6, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261471, + "field_id": 59763, + "width": 132, "hidden": false, "order": 7, "aggregation_type": "", "aggregation_raw_type": "" }, { - "id": 1064010, - "field_id": 725746, - "width": 110, + "id": 261472, + "field_id": 59764, + "width": 132, "hidden": false, "order": 8, "aggregation_type": "", "aggregation_raw_type": "" }, { - "id": 1064011, - "field_id": 725747, + "id": 261473, + "field_id": 59765, "width": 154, "hidden": false, "order": 9, @@ -1593,258 +4246,263 @@ "aggregation_raw_type": "" }, { - "id": 1064012, - "field_id": 725748, - "width": 154, - "hidden": false, - "order": 11, - "aggregation_type": "sum", - "aggregation_raw_type": "sum" - }, - { - "id": 1064013, - "field_id": 725749, - "width": 114, - "hidden": false, - "order": 6, - "aggregation_type": "", - "aggregation_raw_type": "" - }, - { - "id": 1064014, - "field_id": 725750, - "width": 149, - "hidden": false, - "order": 14, - "aggregation_type": "not_empty_percentage", - "aggregation_raw_type": "empty_count" - }, - { - "id": 1064015, - "field_id": 725751, - "width": 199, - "hidden": false, - "order": 12, - "aggregation_type": "average", - "aggregation_raw_type": "average" - }, - { - "id": 1064016, - "field_id": 725752, - "width": 159, - "hidden": false, - "order": 13, - "aggregation_type": "sum", - "aggregation_raw_type": "sum" - }, - { - "id": 1064017, - "field_id": 725753, - "width": 200, - "hidden": false, - "order": 16, - "aggregation_type": "", - "aggregation_raw_type": "" - }, - { - "id": 1064018, - "field_id": 725755, - "width": 144, + "id": 261474, + "field_id": 59770, + "width": 153, "hidden": false, "order": 10, "aggregation_type": "unique_count", "aggregation_raw_type": "unique_count" }, { - "id": 1064019, - "field_id": 725756, - "width": 163, + "id": 261475, + "field_id": 59766, + "width": 174, "hidden": false, - "order": 17, - "aggregation_type": "unique_count", - "aggregation_raw_type": "unique_count" + "order": 11, + "aggregation_type": "sum", + "aggregation_raw_type": "sum" }, { - "id": 1064020, - "field_id": 725757, - "width": 165, - "hidden": false, - "order": 23, - "aggregation_type": "not_empty_percentage", - "aggregation_raw_type": "empty_count" - }, - { - "id": 1064021, - "field_id": 725758, - "width": 147, - "hidden": false, - "order": 19, - "aggregation_type": "", - "aggregation_raw_type": "" - }, - { - "id": 1064022, - "field_id": 725759, + "id": 261476, + "field_id": 59768, "width": 152, "hidden": false, - "order": 21, + "order": 12, + "aggregation_type": "average", + "aggregation_raw_type": "average" + }, + { + "id": 261477, + "field_id": 59842, + "width": 179, + "hidden": false, + "order": 13, + "aggregation_type": "sum", + "aggregation_raw_type": "sum" + }, + { + "id": 261478, + "field_id": 59767, + "width": 167, + "hidden": false, + "order": 14, "aggregation_type": "not_empty_percentage", "aggregation_raw_type": "empty_count" }, { - "id": 1064023, - "field_id": 725788, - "width": 138, - "hidden": false, - "order": 20, - "aggregation_type": "not_empty_percentage", - "aggregation_raw_type": "empty_count" - }, - { - "id": 1064024, - "field_id": 725869, - "width": 173, - "hidden": false, - "order": 22, - "aggregation_type": "", - "aggregation_raw_type": "" - }, - { - "id": 1064025, - "field_id": 725899, - "width": 136, + "id": 261479, + "field_id": 59844, + "width": 186, "hidden": false, "order": 15, "aggregation_type": "", "aggregation_raw_type": "" }, { - "id": 1064026, - "field_id": 735944, - "width": 108, - "hidden": true, - "order": 24, - "aggregation_type": "checked_count", - "aggregation_raw_type": "empty_count" - }, - { - "id": 1064027, - "field_id": 738833, - "width": 154, + "id": 261480, + "field_id": 59843, + "width": 174, "hidden": false, - "order": 18, - "aggregation_type": "unique_count", - "aggregation_raw_type": "unique_count" - }, - { - "id": 1064028, - "field_id": 738895, - "width": 181, - "hidden": true, - "order": 25, + "order": 16, "aggregation_type": "", "aggregation_raw_type": "" }, { - "id": 1064029, - "field_id": 738896, - "width": 161, + "id": 261481, + "field_id": 59866, + "width": 160, + "hidden": false, + "order": 17, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261482, + "field_id": 59769, + "width": 200, + "hidden": false, + "order": 18, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261483, + "field_id": 59771, + "width": 163, + "hidden": false, + "order": 19, + "aggregation_type": "unique_count", + "aggregation_raw_type": "unique_count" + }, + { + "id": 261484, + "field_id": 59777, + "width": 154, + "hidden": false, + "order": 20, + "aggregation_type": "unique_count", + "aggregation_raw_type": "unique_count" + }, + { + "id": 261485, + "field_id": 59773, + "width": 162, + "hidden": false, + "order": 21, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261486, + "field_id": 59775, + "width": 138, + "hidden": false, + "order": 22, + "aggregation_type": "not_empty_percentage", + "aggregation_raw_type": "empty_count" + }, + { + "id": 261487, + "field_id": 59774, + "width": 152, + "hidden": false, + "order": 23, + "aggregation_type": "not_empty_percentage", + "aggregation_raw_type": "empty_count" + }, + { + "id": 261488, + "field_id": 59776, + "width": 173, + "hidden": false, + "order": 24, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261489, + "field_id": 59772, + "width": 194, + "hidden": false, + "order": 25, + "aggregation_type": "not_empty_percentage", + "aggregation_raw_type": "empty_count" + }, + { + "id": 261490, + "field_id": 59778, + "width": 200, "hidden": true, - "order": 26, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261491, + "field_id": 59779, + "width": 200, + "hidden": true, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261492, + "field_id": 59849, + "width": 200, + "hidden": true, + "order": 32767, "aggregation_type": "", "aggregation_raw_type": "" } ] }, { - "id": 174134, + "id": 26469, "type": "grid", - "name": "Under repair", + "name": "Sold vehicles", "order": 5, + "ownership_type": "collaborative", + "owned_by": null, "filter_type": "AND", "filters_disabled": false, "filters": [ { - "id": 68735, - "field_id": 725749, - "type": "single_select_equal", - "value": "313861" + "id": 13973, + "field_id": 59867, + "type": "equal", + "value": "Sold", + "group": null } ], + "filter_groups": [], "sortings": [ { - "id": 53153, - "field_id": 738896, + "id": 20360, + "field_id": 59762, "order": "ASC" }, { - "id": 53154, - "field_id": 738895, - "order": "ASC" - }, - { - "id": 53155, - "field_id": 725743, + "id": 20361, + "field_id": 59841, "order": "DESC" }, { - "id": 53156, - "field_id": 725749, + "id": 20362, + "field_id": 59867, "order": "ASC" } ], + "group_bys": [], "decorations": [ { - "id": 6992, + "id": 8732, "type": "left_border_color", "value_provider_type": "conditional_color", "value_provider_conf": { "colors": [ { - "color": "dark-green", + "id": "54f93ff9-a65a-4ee5-8b9d-791af0cdb89f", + "color": "deep-dark-green", "filters": [ { - "id": "7777904c-d041-4484-973d-1556329b8128", - "type": "single_select_equal", - "field": 725749, - "value": "313856" + "id": "8d8e010f-1f78-4729-87ff-f3d0667e600f", + "type": "equal", + "field": 59867, + "group": null, + "value": "Available" } ], "operator": "AND" }, { - "color": "dark-gray", + "id": "5904e484-67ba-421d-94be-2e0f499c0bde", + "color": "darker-yellow", "filters": [ { - "id": "24f4f264-42e7-4fa6-852a-10f34270e0b3", - "type": "single_select_equal", - "field": 725749, - "value": "313859" + "id": "8706a911-a742-41b0-9839-ebdde5e2f83a", + "type": "equal", + "field": 59867, + "group": null, + "value": "Under consideration" } ], "operator": "AND" - } - ] - }, - "order": 1 - }, - { - "id": 6993, - "type": "background_color", - "value_provider_type": "conditional_color", - "value_provider_conf": { - "colors": [ + }, { - "color": "light-gray", + "id": "9b24c3b6-912c-4c52-a2a0-b37fbc00f20b", + "color": "darker-red", "filters": [ { - "id": "dbebd8a4-9c7d-4cca-ae5f-dc18435cd2ff", - "type": "not_empty", - "field": 725750, - "value": "" + "id": "cee21683-e704-4ec9-9d37-6ff2961fb64e", + "type": "equal", + "field": 59867, + "group": null, + "value": "Sold" } ], - "operator": "OR" + "operator": "AND" } ] }, @@ -1853,10 +4511,11 @@ ], "public": false, "row_identifier_type": "count", + "row_height_size": "small", "field_options": [ { - "id": 1064040, - "field_id": 705223, + "id": 261493, + "field_id": 59760, "width": 100, "hidden": false, "order": 0, @@ -1864,17 +4523,17 @@ "aggregation_raw_type": "unique_count" }, { - "id": 1064041, - "field_id": 705224, - "width": 100, + "id": 261494, + "field_id": 59761, + "width": 113, "hidden": false, "order": 1, "aggregation_type": "not_empty_percentage", "aggregation_raw_type": "empty_count" }, { - "id": 1064042, - "field_id": 705225, + "id": 261495, + "field_id": 59762, "width": 169, "hidden": false, "order": 2, @@ -1882,71 +4541,35 @@ "aggregation_raw_type": "empty_count" }, { - "id": 1064043, - "field_id": 725742, - "width": 100, + "id": 261496, + "field_id": 59840, + "width": 125, "hidden": false, "order": 3, "aggregation_type": "", "aggregation_raw_type": "" }, { - "id": 1064044, - "field_id": 725743, + "id": 261497, + "field_id": 59841, "width": 100, "hidden": false, "order": 4, - "aggregation_type": "not_empty_percentage", - "aggregation_raw_type": "empty_count" + "aggregation_type": "", + "aggregation_raw_type": "" }, { - "id": 1064045, - "field_id": 725744, - "width": 178, + "id": 261498, + "field_id": 59848, + "width": 200, "hidden": false, "order": 5, "aggregation_type": "", "aggregation_raw_type": "" }, { - "id": 1064046, - "field_id": 725745, - "width": 120, - "hidden": false, - "order": 7, - "aggregation_type": "", - "aggregation_raw_type": "" - }, - { - "id": 1064047, - "field_id": 725746, - "width": 110, - "hidden": false, - "order": 8, - "aggregation_type": "", - "aggregation_raw_type": "" - }, - { - "id": 1064048, - "field_id": 725747, - "width": 154, - "hidden": false, - "order": 9, - "aggregation_type": "", - "aggregation_raw_type": "" - }, - { - "id": 1064049, - "field_id": 725748, - "width": 154, - "hidden": false, - "order": 11, - "aggregation_type": "sum", - "aggregation_raw_type": "sum" - }, - { - "id": 1064050, - "field_id": 725749, + "id": 261499, + "field_id": 59867, "width": 114, "hidden": false, "order": 6, @@ -1954,1539 +4577,2225 @@ "aggregation_raw_type": "" }, { - "id": 1064051, - "field_id": 725750, - "width": 149, + "id": 261500, + "field_id": 59763, + "width": 132, "hidden": false, - "order": 14, - "aggregation_type": "not_empty_percentage", - "aggregation_raw_type": "empty_count" - }, - { - "id": 1064052, - "field_id": 725751, - "width": 199, - "hidden": false, - "order": 12, - "aggregation_type": "average", - "aggregation_raw_type": "average" - }, - { - "id": 1064053, - "field_id": 725752, - "width": 159, - "hidden": false, - "order": 13, - "aggregation_type": "sum", - "aggregation_raw_type": "sum" - }, - { - "id": 1064054, - "field_id": 725753, - "width": 200, - "hidden": false, - "order": 16, + "order": 7, "aggregation_type": "", "aggregation_raw_type": "" }, { - "id": 1064055, - "field_id": 725755, - "width": 144, + "id": 261501, + "field_id": 59764, + "width": 132, + "hidden": false, + "order": 8, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261502, + "field_id": 59765, + "width": 154, + "hidden": false, + "order": 9, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261503, + "field_id": 59770, + "width": 153, "hidden": false, "order": 10, "aggregation_type": "unique_count", "aggregation_raw_type": "unique_count" }, { - "id": 1064056, - "field_id": 725756, - "width": 163, + "id": 261504, + "field_id": 59766, + "width": 174, "hidden": false, - "order": 17, - "aggregation_type": "unique_count", - "aggregation_raw_type": "unique_count" + "order": 11, + "aggregation_type": "sum", + "aggregation_raw_type": "sum" }, { - "id": 1064057, - "field_id": 725757, - "width": 165, - "hidden": false, - "order": 23, - "aggregation_type": "not_empty_percentage", - "aggregation_raw_type": "empty_count" - }, - { - "id": 1064058, - "field_id": 725758, - "width": 147, - "hidden": false, - "order": 19, - "aggregation_type": "", - "aggregation_raw_type": "" - }, - { - "id": 1064059, - "field_id": 725759, + "id": 261505, + "field_id": 59768, "width": 152, "hidden": false, - "order": 21, + "order": 12, + "aggregation_type": "average", + "aggregation_raw_type": "average" + }, + { + "id": 261506, + "field_id": 59842, + "width": 179, + "hidden": false, + "order": 13, + "aggregation_type": "sum", + "aggregation_raw_type": "sum" + }, + { + "id": 261507, + "field_id": 59767, + "width": 167, + "hidden": false, + "order": 14, "aggregation_type": "not_empty_percentage", "aggregation_raw_type": "empty_count" }, { - "id": 1064060, - "field_id": 725788, - "width": 138, - "hidden": false, - "order": 20, - "aggregation_type": "not_empty_percentage", - "aggregation_raw_type": "empty_count" - }, - { - "id": 1064061, - "field_id": 725869, - "width": 173, - "hidden": false, - "order": 22, - "aggregation_type": "", - "aggregation_raw_type": "" - }, - { - "id": 1064062, - "field_id": 725899, - "width": 136, + "id": 261508, + "field_id": 59844, + "width": 186, "hidden": false, "order": 15, "aggregation_type": "", "aggregation_raw_type": "" }, { - "id": 1064063, - "field_id": 735944, - "width": 108, - "hidden": true, - "order": 24, - "aggregation_type": "checked_count", - "aggregation_raw_type": "empty_count" - }, - { - "id": 1064064, - "field_id": 738833, - "width": 154, + "id": 261509, + "field_id": 59843, + "width": 174, "hidden": false, - "order": 18, - "aggregation_type": "unique_count", - "aggregation_raw_type": "unique_count" - }, - { - "id": 1064065, - "field_id": 738895, - "width": 181, - "hidden": true, - "order": 25, + "order": 16, "aggregation_type": "", "aggregation_raw_type": "" }, { - "id": 1064066, - "field_id": 738896, - "width": 161, + "id": 261510, + "field_id": 59866, + "width": 160, + "hidden": false, + "order": 17, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261511, + "field_id": 59769, + "width": 200, + "hidden": false, + "order": 18, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261512, + "field_id": 59771, + "width": 163, + "hidden": false, + "order": 19, + "aggregation_type": "unique_count", + "aggregation_raw_type": "unique_count" + }, + { + "id": 261513, + "field_id": 59777, + "width": 154, + "hidden": false, + "order": 20, + "aggregation_type": "unique_count", + "aggregation_raw_type": "unique_count" + }, + { + "id": 261514, + "field_id": 59773, + "width": 162, + "hidden": false, + "order": 21, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261515, + "field_id": 59775, + "width": 138, + "hidden": false, + "order": 22, + "aggregation_type": "not_empty_percentage", + "aggregation_raw_type": "empty_count" + }, + { + "id": 261516, + "field_id": 59774, + "width": 152, + "hidden": false, + "order": 23, + "aggregation_type": "not_empty_percentage", + "aggregation_raw_type": "empty_count" + }, + { + "id": 261517, + "field_id": 59776, + "width": 173, + "hidden": false, + "order": 24, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261518, + "field_id": 59772, + "width": 194, + "hidden": false, + "order": 25, + "aggregation_type": "not_empty_percentage", + "aggregation_raw_type": "empty_count" + }, + { + "id": 261519, + "field_id": 59849, + "width": 200, "hidden": true, - "order": 26, + "order": 32767, "aggregation_type": "", "aggregation_raw_type": "" } ] }, { - "id": 173716, + "id": 26470, + "type": "grid", + "name": "All vehicles grouped by model", + "order": 6, + "ownership_type": "collaborative", + "owned_by": null, + "filter_type": "AND", + "filters_disabled": false, + "filters": [], + "filter_groups": [], + "sortings": [ + { + "id": 20363, + "field_id": 59762, + "order": "ASC" + }, + { + "id": 20364, + "field_id": 59841, + "order": "DESC" + }, + { + "id": 20365, + "field_id": 59867, + "order": "ASC" + } + ], + "group_bys": [ + { + "id": 3632, + "field_id": 59762, + "order": "ASC" + } + ], + "decorations": [ + { + "id": 8733, + "type": "left_border_color", + "value_provider_type": "conditional_color", + "value_provider_conf": { + "colors": [ + { + "id": "54f93ff9-a65a-4ee5-8b9d-791af0cdb89f", + "color": "deep-dark-green", + "filters": [ + { + "id": "8d8e010f-1f78-4729-87ff-f3d0667e600f", + "type": "equal", + "field": 59867, + "group": null, + "value": "Available" + } + ], + "operator": "AND" + }, + { + "id": "5904e484-67ba-421d-94be-2e0f499c0bde", + "color": "darker-yellow", + "filters": [ + { + "id": "8706a911-a742-41b0-9839-ebdde5e2f83a", + "type": "equal", + "field": 59867, + "group": null, + "value": "Under consideration" + } + ], + "operator": "AND" + }, + { + "id": "9b24c3b6-912c-4c52-a2a0-b37fbc00f20b", + "color": "darker-red", + "filters": [ + { + "id": "cee21683-e704-4ec9-9d37-6ff2961fb64e", + "type": "equal", + "field": 59867, + "group": null, + "value": "Sold" + } + ], + "operator": "AND" + } + ] + }, + "order": 2 + } + ], + "public": false, + "row_identifier_type": "count", + "row_height_size": "small", + "field_options": [ + { + "id": 261520, + "field_id": 59760, + "width": 100, + "hidden": false, + "order": 0, + "aggregation_type": "unique_count", + "aggregation_raw_type": "unique_count" + }, + { + "id": 261521, + "field_id": 59761, + "width": 113, + "hidden": false, + "order": 1, + "aggregation_type": "not_empty_percentage", + "aggregation_raw_type": "empty_count" + }, + { + "id": 261522, + "field_id": 59762, + "width": 169, + "hidden": true, + "order": 2, + "aggregation_type": "not_empty_percentage", + "aggregation_raw_type": "empty_count" + }, + { + "id": 261523, + "field_id": 59840, + "width": 125, + "hidden": false, + "order": 3, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261524, + "field_id": 59841, + "width": 100, + "hidden": false, + "order": 4, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261525, + "field_id": 59848, + "width": 200, + "hidden": false, + "order": 5, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261526, + "field_id": 59867, + "width": 114, + "hidden": false, + "order": 6, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261527, + "field_id": 59763, + "width": 132, + "hidden": false, + "order": 7, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261528, + "field_id": 59764, + "width": 132, + "hidden": false, + "order": 8, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261529, + "field_id": 59765, + "width": 154, + "hidden": false, + "order": 9, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261530, + "field_id": 59770, + "width": 153, + "hidden": false, + "order": 10, + "aggregation_type": "unique_count", + "aggregation_raw_type": "unique_count" + }, + { + "id": 261531, + "field_id": 59766, + "width": 174, + "hidden": false, + "order": 11, + "aggregation_type": "sum", + "aggregation_raw_type": "sum" + }, + { + "id": 261532, + "field_id": 59768, + "width": 152, + "hidden": false, + "order": 12, + "aggregation_type": "average", + "aggregation_raw_type": "average" + }, + { + "id": 261533, + "field_id": 59842, + "width": 179, + "hidden": false, + "order": 13, + "aggregation_type": "sum", + "aggregation_raw_type": "sum" + }, + { + "id": 261534, + "field_id": 59767, + "width": 167, + "hidden": false, + "order": 14, + "aggregation_type": "not_empty_percentage", + "aggregation_raw_type": "empty_count" + }, + { + "id": 261535, + "field_id": 59844, + "width": 186, + "hidden": false, + "order": 15, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261536, + "field_id": 59843, + "width": 174, + "hidden": false, + "order": 16, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261537, + "field_id": 59866, + "width": 160, + "hidden": false, + "order": 17, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261538, + "field_id": 59769, + "width": 200, + "hidden": false, + "order": 18, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261539, + "field_id": 59771, + "width": 163, + "hidden": false, + "order": 19, + "aggregation_type": "unique_count", + "aggregation_raw_type": "unique_count" + }, + { + "id": 261540, + "field_id": 59777, + "width": 154, + "hidden": false, + "order": 20, + "aggregation_type": "unique_count", + "aggregation_raw_type": "unique_count" + }, + { + "id": 261541, + "field_id": 59773, + "width": 162, + "hidden": false, + "order": 21, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261542, + "field_id": 59775, + "width": 138, + "hidden": false, + "order": 22, + "aggregation_type": "not_empty_percentage", + "aggregation_raw_type": "empty_count" + }, + { + "id": 261543, + "field_id": 59774, + "width": 152, + "hidden": false, + "order": 23, + "aggregation_type": "not_empty_percentage", + "aggregation_raw_type": "empty_count" + }, + { + "id": 261544, + "field_id": 59776, + "width": 173, + "hidden": false, + "order": 24, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261545, + "field_id": 59772, + "width": 194, + "hidden": false, + "order": 25, + "aggregation_type": "not_empty_percentage", + "aggregation_raw_type": "empty_count" + }, + { + "id": 261546, + "field_id": 59849, + "width": 200, + "hidden": true, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + } + ] + }, + { + "id": 26471, + "type": "grid", + "name": "All vehicles grouped by branch", + "order": 7, + "ownership_type": "collaborative", + "owned_by": null, + "filter_type": "AND", + "filters_disabled": false, + "filters": [], + "filter_groups": [], + "sortings": [ + { + "id": 20366, + "field_id": 59762, + "order": "ASC" + }, + { + "id": 20367, + "field_id": 59841, + "order": "DESC" + }, + { + "id": 20368, + "field_id": 59867, + "order": "ASC" + } + ], + "group_bys": [ + { + "id": 3633, + "field_id": 59775, + "order": "ASC" + } + ], + "decorations": [ + { + "id": 8734, + "type": "left_border_color", + "value_provider_type": "conditional_color", + "value_provider_conf": { + "colors": [ + { + "id": "54f93ff9-a65a-4ee5-8b9d-791af0cdb89f", + "color": "deep-dark-green", + "filters": [ + { + "id": "8d8e010f-1f78-4729-87ff-f3d0667e600f", + "type": "equal", + "field": 59867, + "group": null, + "value": "Available" + } + ], + "operator": "AND" + }, + { + "id": "5904e484-67ba-421d-94be-2e0f499c0bde", + "color": "darker-yellow", + "filters": [ + { + "id": "8706a911-a742-41b0-9839-ebdde5e2f83a", + "type": "equal", + "field": 59867, + "group": null, + "value": "Under consideration" + } + ], + "operator": "AND" + }, + { + "id": "9b24c3b6-912c-4c52-a2a0-b37fbc00f20b", + "color": "darker-red", + "filters": [ + { + "id": "cee21683-e704-4ec9-9d37-6ff2961fb64e", + "type": "equal", + "field": 59867, + "group": null, + "value": "Sold" + } + ], + "operator": "AND" + } + ] + }, + "order": 2 + } + ], + "public": false, + "row_identifier_type": "count", + "row_height_size": "small", + "field_options": [ + { + "id": 261547, + "field_id": 59760, + "width": 100, + "hidden": false, + "order": 0, + "aggregation_type": "unique_count", + "aggregation_raw_type": "unique_count" + }, + { + "id": 261548, + "field_id": 59761, + "width": 113, + "hidden": false, + "order": 1, + "aggregation_type": "not_empty_percentage", + "aggregation_raw_type": "empty_count" + }, + { + "id": 261549, + "field_id": 59762, + "width": 169, + "hidden": false, + "order": 2, + "aggregation_type": "not_empty_percentage", + "aggregation_raw_type": "empty_count" + }, + { + "id": 261550, + "field_id": 59840, + "width": 125, + "hidden": false, + "order": 3, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261551, + "field_id": 59841, + "width": 100, + "hidden": false, + "order": 4, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261552, + "field_id": 59848, + "width": 200, + "hidden": false, + "order": 5, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261553, + "field_id": 59867, + "width": 114, + "hidden": false, + "order": 6, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261554, + "field_id": 59763, + "width": 132, + "hidden": false, + "order": 7, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261555, + "field_id": 59764, + "width": 132, + "hidden": false, + "order": 8, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261556, + "field_id": 59765, + "width": 154, + "hidden": false, + "order": 9, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261557, + "field_id": 59770, + "width": 153, + "hidden": false, + "order": 10, + "aggregation_type": "unique_count", + "aggregation_raw_type": "unique_count" + }, + { + "id": 261558, + "field_id": 59766, + "width": 174, + "hidden": false, + "order": 11, + "aggregation_type": "sum", + "aggregation_raw_type": "sum" + }, + { + "id": 261559, + "field_id": 59768, + "width": 152, + "hidden": false, + "order": 12, + "aggregation_type": "average", + "aggregation_raw_type": "average" + }, + { + "id": 261560, + "field_id": 59842, + "width": 179, + "hidden": false, + "order": 13, + "aggregation_type": "sum", + "aggregation_raw_type": "sum" + }, + { + "id": 261561, + "field_id": 59767, + "width": 167, + "hidden": false, + "order": 14, + "aggregation_type": "not_empty_percentage", + "aggregation_raw_type": "empty_count" + }, + { + "id": 261562, + "field_id": 59844, + "width": 186, + "hidden": false, + "order": 15, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261563, + "field_id": 59843, + "width": 174, + "hidden": false, + "order": 16, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261564, + "field_id": 59866, + "width": 160, + "hidden": false, + "order": 17, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261565, + "field_id": 59769, + "width": 200, + "hidden": false, + "order": 18, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261566, + "field_id": 59771, + "width": 163, + "hidden": false, + "order": 19, + "aggregation_type": "unique_count", + "aggregation_raw_type": "unique_count" + }, + { + "id": 261567, + "field_id": 59777, + "width": 154, + "hidden": false, + "order": 20, + "aggregation_type": "unique_count", + "aggregation_raw_type": "unique_count" + }, + { + "id": 261568, + "field_id": 59773, + "width": 162, + "hidden": false, + "order": 21, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261569, + "field_id": 59775, + "width": 138, + "hidden": true, + "order": 22, + "aggregation_type": "not_empty_percentage", + "aggregation_raw_type": "empty_count" + }, + { + "id": 261570, + "field_id": 59774, + "width": 152, + "hidden": false, + "order": 23, + "aggregation_type": "not_empty_percentage", + "aggregation_raw_type": "empty_count" + }, + { + "id": 261571, + "field_id": 59776, + "width": 173, + "hidden": false, + "order": 24, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261572, + "field_id": 59772, + "width": 194, + "hidden": false, + "order": 25, + "aggregation_type": "not_empty_percentage", + "aggregation_raw_type": "empty_count" + }, + { + "id": 261573, + "field_id": 59849, + "width": 200, + "hidden": true, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + } + ] + }, + { + "id": 26472, + "type": "grid", + "name": "All vehicles grouped by status", + "order": 8, + "ownership_type": "collaborative", + "owned_by": null, + "filter_type": "AND", + "filters_disabled": false, + "filters": [], + "filter_groups": [], + "sortings": [ + { + "id": 20369, + "field_id": 59762, + "order": "ASC" + }, + { + "id": 20370, + "field_id": 59841, + "order": "DESC" + }, + { + "id": 20371, + "field_id": 59867, + "order": "ASC" + } + ], + "group_bys": [ + { + "id": 3634, + "field_id": 59867, + "order": "ASC" + } + ], + "decorations": [ + { + "id": 8735, + "type": "left_border_color", + "value_provider_type": "conditional_color", + "value_provider_conf": { + "colors": [ + { + "id": "54f93ff9-a65a-4ee5-8b9d-791af0cdb89f", + "color": "deep-dark-green", + "filters": [ + { + "id": "8d8e010f-1f78-4729-87ff-f3d0667e600f", + "type": "equal", + "field": 59867, + "group": null, + "value": "Available" + } + ], + "operator": "AND" + }, + { + "id": "5904e484-67ba-421d-94be-2e0f499c0bde", + "color": "darker-yellow", + "filters": [ + { + "id": "8706a911-a742-41b0-9839-ebdde5e2f83a", + "type": "equal", + "field": 59867, + "group": null, + "value": "Under consideration" + } + ], + "operator": "AND" + }, + { + "id": "9b24c3b6-912c-4c52-a2a0-b37fbc00f20b", + "color": "darker-red", + "filters": [ + { + "id": "cee21683-e704-4ec9-9d37-6ff2961fb64e", + "type": "equal", + "field": 59867, + "group": null, + "value": "Sold" + } + ], + "operator": "AND" + } + ] + }, + "order": 2 + } + ], + "public": false, + "row_identifier_type": "count", + "row_height_size": "small", + "field_options": [ + { + "id": 261574, + "field_id": 59760, + "width": 100, + "hidden": false, + "order": 0, + "aggregation_type": "unique_count", + "aggregation_raw_type": "unique_count" + }, + { + "id": 261575, + "field_id": 59761, + "width": 113, + "hidden": false, + "order": 1, + "aggregation_type": "not_empty_percentage", + "aggregation_raw_type": "empty_count" + }, + { + "id": 261576, + "field_id": 59762, + "width": 169, + "hidden": false, + "order": 2, + "aggregation_type": "not_empty_percentage", + "aggregation_raw_type": "empty_count" + }, + { + "id": 261577, + "field_id": 59840, + "width": 125, + "hidden": false, + "order": 3, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261578, + "field_id": 59841, + "width": 100, + "hidden": false, + "order": 4, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261579, + "field_id": 59848, + "width": 200, + "hidden": false, + "order": 5, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261580, + "field_id": 59867, + "width": 114, + "hidden": true, + "order": 6, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261581, + "field_id": 59763, + "width": 132, + "hidden": false, + "order": 7, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261582, + "field_id": 59764, + "width": 132, + "hidden": false, + "order": 8, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261583, + "field_id": 59765, + "width": 154, + "hidden": false, + "order": 9, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261584, + "field_id": 59770, + "width": 153, + "hidden": false, + "order": 10, + "aggregation_type": "unique_count", + "aggregation_raw_type": "unique_count" + }, + { + "id": 261585, + "field_id": 59766, + "width": 174, + "hidden": false, + "order": 11, + "aggregation_type": "sum", + "aggregation_raw_type": "sum" + }, + { + "id": 261586, + "field_id": 59768, + "width": 152, + "hidden": false, + "order": 12, + "aggregation_type": "average", + "aggregation_raw_type": "average" + }, + { + "id": 261587, + "field_id": 59842, + "width": 179, + "hidden": false, + "order": 13, + "aggregation_type": "sum", + "aggregation_raw_type": "sum" + }, + { + "id": 261588, + "field_id": 59767, + "width": 167, + "hidden": false, + "order": 14, + "aggregation_type": "not_empty_percentage", + "aggregation_raw_type": "empty_count" + }, + { + "id": 261589, + "field_id": 59844, + "width": 186, + "hidden": false, + "order": 15, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261590, + "field_id": 59843, + "width": 174, + "hidden": false, + "order": 16, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261591, + "field_id": 59866, + "width": 160, + "hidden": false, + "order": 17, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261592, + "field_id": 59769, + "width": 200, + "hidden": false, + "order": 18, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261593, + "field_id": 59771, + "width": 163, + "hidden": false, + "order": 19, + "aggregation_type": "unique_count", + "aggregation_raw_type": "unique_count" + }, + { + "id": 261594, + "field_id": 59777, + "width": 154, + "hidden": false, + "order": 20, + "aggregation_type": "unique_count", + "aggregation_raw_type": "unique_count" + }, + { + "id": 261595, + "field_id": 59773, + "width": 162, + "hidden": false, + "order": 21, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261596, + "field_id": 59775, + "width": 138, + "hidden": false, + "order": 22, + "aggregation_type": "not_empty_percentage", + "aggregation_raw_type": "empty_count" + }, + { + "id": 261597, + "field_id": 59774, + "width": 152, + "hidden": false, + "order": 23, + "aggregation_type": "not_empty_percentage", + "aggregation_raw_type": "empty_count" + }, + { + "id": 261598, + "field_id": 59776, + "width": 173, + "hidden": false, + "order": 24, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261599, + "field_id": 59772, + "width": 194, + "hidden": false, + "order": 25, + "aggregation_type": "not_empty_percentage", + "aggregation_raw_type": "empty_count" + } + ] + }, + { + "id": 26473, + "type": "grid", + "name": "All vehicles grouped by branch and status", + "order": 9, + "ownership_type": "collaborative", + "owned_by": null, + "filter_type": "AND", + "filters_disabled": false, + "filters": [], + "filter_groups": [], + "sortings": [ + { + "id": 20372, + "field_id": 59762, + "order": "ASC" + }, + { + "id": 20373, + "field_id": 59841, + "order": "DESC" + }, + { + "id": 20374, + "field_id": 59867, + "order": "ASC" + } + ], + "group_bys": [ + { + "id": 3635, + "field_id": 59775, + "order": "ASC" + }, + { + "id": 3636, + "field_id": 59867, + "order": "ASC" + } + ], + "decorations": [ + { + "id": 8736, + "type": "left_border_color", + "value_provider_type": "conditional_color", + "value_provider_conf": { + "colors": [ + { + "id": "54f93ff9-a65a-4ee5-8b9d-791af0cdb89f", + "color": "deep-dark-green", + "filters": [ + { + "id": "8d8e010f-1f78-4729-87ff-f3d0667e600f", + "type": "equal", + "field": 59867, + "group": null, + "value": "Available" + } + ], + "operator": "AND" + }, + { + "id": "5904e484-67ba-421d-94be-2e0f499c0bde", + "color": "darker-yellow", + "filters": [ + { + "id": "8706a911-a742-41b0-9839-ebdde5e2f83a", + "type": "equal", + "field": 59867, + "group": null, + "value": "Under consideration" + } + ], + "operator": "AND" + }, + { + "id": "9b24c3b6-912c-4c52-a2a0-b37fbc00f20b", + "color": "darker-red", + "filters": [ + { + "id": "cee21683-e704-4ec9-9d37-6ff2961fb64e", + "type": "equal", + "field": 59867, + "group": null, + "value": "Sold" + } + ], + "operator": "AND" + } + ] + }, + "order": 2 + } + ], + "public": false, + "row_identifier_type": "count", + "row_height_size": "small", + "field_options": [ + { + "id": 261600, + "field_id": 59760, + "width": 100, + "hidden": false, + "order": 0, + "aggregation_type": "unique_count", + "aggregation_raw_type": "unique_count" + }, + { + "id": 261601, + "field_id": 59761, + "width": 113, + "hidden": false, + "order": 1, + "aggregation_type": "not_empty_percentage", + "aggregation_raw_type": "empty_count" + }, + { + "id": 261602, + "field_id": 59762, + "width": 169, + "hidden": false, + "order": 2, + "aggregation_type": "not_empty_percentage", + "aggregation_raw_type": "empty_count" + }, + { + "id": 261603, + "field_id": 59840, + "width": 125, + "hidden": false, + "order": 3, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261604, + "field_id": 59841, + "width": 100, + "hidden": false, + "order": 4, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261605, + "field_id": 59848, + "width": 200, + "hidden": false, + "order": 5, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261606, + "field_id": 59867, + "width": 114, + "hidden": true, + "order": 6, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261607, + "field_id": 59763, + "width": 132, + "hidden": false, + "order": 7, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261608, + "field_id": 59764, + "width": 132, + "hidden": false, + "order": 8, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261609, + "field_id": 59765, + "width": 154, + "hidden": false, + "order": 9, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261610, + "field_id": 59770, + "width": 153, + "hidden": false, + "order": 10, + "aggregation_type": "unique_count", + "aggregation_raw_type": "unique_count" + }, + { + "id": 261611, + "field_id": 59766, + "width": 174, + "hidden": false, + "order": 11, + "aggregation_type": "sum", + "aggregation_raw_type": "sum" + }, + { + "id": 261612, + "field_id": 59768, + "width": 152, + "hidden": false, + "order": 12, + "aggregation_type": "average", + "aggregation_raw_type": "average" + }, + { + "id": 261613, + "field_id": 59842, + "width": 179, + "hidden": false, + "order": 13, + "aggregation_type": "sum", + "aggregation_raw_type": "sum" + }, + { + "id": 261614, + "field_id": 59767, + "width": 167, + "hidden": false, + "order": 14, + "aggregation_type": "not_empty_percentage", + "aggregation_raw_type": "empty_count" + }, + { + "id": 261615, + "field_id": 59844, + "width": 186, + "hidden": false, + "order": 15, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261616, + "field_id": 59843, + "width": 174, + "hidden": false, + "order": 16, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261617, + "field_id": 59866, + "width": 160, + "hidden": false, + "order": 17, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261618, + "field_id": 59769, + "width": 200, + "hidden": false, + "order": 18, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261619, + "field_id": 59771, + "width": 163, + "hidden": false, + "order": 19, + "aggregation_type": "unique_count", + "aggregation_raw_type": "unique_count" + }, + { + "id": 261620, + "field_id": 59777, + "width": 154, + "hidden": false, + "order": 20, + "aggregation_type": "unique_count", + "aggregation_raw_type": "unique_count" + }, + { + "id": 261621, + "field_id": 59773, + "width": 162, + "hidden": false, + "order": 21, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261622, + "field_id": 59775, + "width": 138, + "hidden": true, + "order": 22, + "aggregation_type": "not_empty_percentage", + "aggregation_raw_type": "empty_count" + }, + { + "id": 261623, + "field_id": 59774, + "width": 152, + "hidden": false, + "order": 23, + "aggregation_type": "not_empty_percentage", + "aggregation_raw_type": "empty_count" + }, + { + "id": 261624, + "field_id": 59776, + "width": 173, + "hidden": false, + "order": 24, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261625, + "field_id": 59772, + "width": 194, + "hidden": false, + "order": 25, + "aggregation_type": "not_empty_percentage", + "aggregation_raw_type": "empty_count" + } + ] + }, + { + "id": 26474, + "type": "grid", + "name": "All vehicles grouped by condition", + "order": 10, + "ownership_type": "collaborative", + "owned_by": null, + "filter_type": "AND", + "filters_disabled": false, + "filters": [], + "filter_groups": [], + "sortings": [ + { + "id": 20375, + "field_id": 59762, + "order": "ASC" + }, + { + "id": 20376, + "field_id": 59841, + "order": "DESC" + }, + { + "id": 20377, + "field_id": 59867, + "order": "ASC" + } + ], + "group_bys": [ + { + "id": 3637, + "field_id": 59763, + "order": "ASC" + } + ], + "decorations": [ + { + "id": 8737, + "type": "left_border_color", + "value_provider_type": "conditional_color", + "value_provider_conf": { + "colors": [ + { + "id": "54f93ff9-a65a-4ee5-8b9d-791af0cdb89f", + "color": "deep-dark-green", + "filters": [ + { + "id": "8d8e010f-1f78-4729-87ff-f3d0667e600f", + "type": "equal", + "field": 59867, + "group": null, + "value": "Available" + } + ], + "operator": "AND" + }, + { + "id": "5904e484-67ba-421d-94be-2e0f499c0bde", + "color": "darker-yellow", + "filters": [ + { + "id": "8706a911-a742-41b0-9839-ebdde5e2f83a", + "type": "equal", + "field": 59867, + "group": null, + "value": "Under consideration" + } + ], + "operator": "AND" + }, + { + "id": "9b24c3b6-912c-4c52-a2a0-b37fbc00f20b", + "color": "darker-red", + "filters": [ + { + "id": "cee21683-e704-4ec9-9d37-6ff2961fb64e", + "type": "equal", + "field": 59867, + "group": null, + "value": "Sold" + } + ], + "operator": "AND" + } + ] + }, + "order": 2 + } + ], + "public": false, + "row_identifier_type": "count", + "row_height_size": "small", + "field_options": [ + { + "id": 261626, + "field_id": 59760, + "width": 100, + "hidden": false, + "order": 0, + "aggregation_type": "unique_count", + "aggregation_raw_type": "unique_count" + }, + { + "id": 261627, + "field_id": 59761, + "width": 113, + "hidden": false, + "order": 1, + "aggregation_type": "not_empty_percentage", + "aggregation_raw_type": "empty_count" + }, + { + "id": 261628, + "field_id": 59762, + "width": 169, + "hidden": false, + "order": 2, + "aggregation_type": "not_empty_percentage", + "aggregation_raw_type": "empty_count" + }, + { + "id": 261629, + "field_id": 59840, + "width": 125, + "hidden": false, + "order": 3, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261630, + "field_id": 59841, + "width": 100, + "hidden": false, + "order": 4, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261631, + "field_id": 59848, + "width": 200, + "hidden": false, + "order": 5, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261632, + "field_id": 59867, + "width": 114, + "hidden": false, + "order": 6, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261633, + "field_id": 59763, + "width": 132, + "hidden": true, + "order": 7, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261634, + "field_id": 59764, + "width": 132, + "hidden": false, + "order": 8, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261635, + "field_id": 59765, + "width": 154, + "hidden": false, + "order": 9, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261636, + "field_id": 59770, + "width": 153, + "hidden": false, + "order": 10, + "aggregation_type": "unique_count", + "aggregation_raw_type": "unique_count" + }, + { + "id": 261637, + "field_id": 59766, + "width": 174, + "hidden": false, + "order": 11, + "aggregation_type": "sum", + "aggregation_raw_type": "sum" + }, + { + "id": 261638, + "field_id": 59768, + "width": 152, + "hidden": false, + "order": 12, + "aggregation_type": "average", + "aggregation_raw_type": "average" + }, + { + "id": 261639, + "field_id": 59842, + "width": 179, + "hidden": false, + "order": 13, + "aggregation_type": "sum", + "aggregation_raw_type": "sum" + }, + { + "id": 261640, + "field_id": 59767, + "width": 167, + "hidden": false, + "order": 14, + "aggregation_type": "not_empty_percentage", + "aggregation_raw_type": "empty_count" + }, + { + "id": 261641, + "field_id": 59844, + "width": 186, + "hidden": false, + "order": 15, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261642, + "field_id": 59843, + "width": 174, + "hidden": false, + "order": 16, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261643, + "field_id": 59866, + "width": 160, + "hidden": false, + "order": 17, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261644, + "field_id": 59769, + "width": 200, + "hidden": false, + "order": 18, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261645, + "field_id": 59771, + "width": 163, + "hidden": false, + "order": 19, + "aggregation_type": "unique_count", + "aggregation_raw_type": "unique_count" + }, + { + "id": 261646, + "field_id": 59777, + "width": 154, + "hidden": false, + "order": 20, + "aggregation_type": "unique_count", + "aggregation_raw_type": "unique_count" + }, + { + "id": 261647, + "field_id": 59773, + "width": 162, + "hidden": false, + "order": 21, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261648, + "field_id": 59775, + "width": 138, + "hidden": false, + "order": 22, + "aggregation_type": "not_empty_percentage", + "aggregation_raw_type": "empty_count" + }, + { + "id": 261649, + "field_id": 59774, + "width": 152, + "hidden": false, + "order": 23, + "aggregation_type": "not_empty_percentage", + "aggregation_raw_type": "empty_count" + }, + { + "id": 261650, + "field_id": 59776, + "width": 173, + "hidden": false, + "order": 24, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261651, + "field_id": 59772, + "width": 194, + "hidden": false, + "order": 25, + "aggregation_type": "not_empty_percentage", + "aggregation_raw_type": "empty_count" + }, + { + "id": 261652, + "field_id": 59849, + "width": 200, + "hidden": true, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + } + ] + }, + { + "id": 26475, "type": "gallery", "name": "All vehicles gallery", - "order": 6, - "filter_type": "AND", - "filters_disabled": false, - "filters": [], - "sortings": [ - { - "id": 52977, - "field_id": 735944, - "order": "DESC" - }, - { - "id": 52978, - "field_id": 738896, - "order": "ASC" - }, - { - "id": 53160, - "field_id": 738895, - "order": "ASC" - }, - { - "id": 53161, - "field_id": 725743, - "order": "DESC" - } - ], - "decorations": [], - "public": false, - "card_cover_image_field_id": 705224, - "field_options": [ - { - "id": 78205, - "field_id": 705223, - "hidden": false, - "order": 1 - }, - { - "id": 78206, - "field_id": 705224, - "hidden": true, - "order": 2 - }, - { - "id": 78208, - "field_id": 725742, - "hidden": false, - "order": 3 - }, - { - "id": 78209, - "field_id": 725743, - "hidden": false, - "order": 4 - }, - { - "id": 78207, - "field_id": 705225, - "hidden": false, - "order": 5 - }, - { - "id": 78210, - "field_id": 725744, - "hidden": true, - "order": 6 - }, - { - "id": 78211, - "field_id": 725745, - "hidden": false, - "order": 7 - }, - { - "id": 78212, - "field_id": 725746, - "hidden": true, - "order": 8 - }, - { - "id": 78213, - "field_id": 725747, - "hidden": true, - "order": 9 - }, - { - "id": 78214, - "field_id": 725748, - "hidden": true, - "order": 10 - }, - { - "id": 78215, - "field_id": 725749, - "hidden": false, - "order": 11 - }, - { - "id": 78216, - "field_id": 725750, - "hidden": true, - "order": 12 - }, - { - "id": 78217, - "field_id": 725751, - "hidden": true, - "order": 13 - }, - { - "id": 78218, - "field_id": 725752, - "hidden": false, - "order": 14 - }, - { - "id": 78219, - "field_id": 725753, - "hidden": true, - "order": 15 - }, - { - "id": 78220, - "field_id": 725755, - "hidden": true, - "order": 16 - }, - { - "id": 78221, - "field_id": 725756, - "hidden": true, - "order": 17 - }, - { - "id": 78222, - "field_id": 725757, - "hidden": true, - "order": 18 - }, - { - "id": 78223, - "field_id": 725758, - "hidden": true, - "order": 19 - }, - { - "id": 78224, - "field_id": 725759, - "hidden": true, - "order": 20 - }, - { - "id": 78225, - "field_id": 725788, - "hidden": false, - "order": 21 - }, - { - "id": 78226, - "field_id": 725869, - "hidden": true, - "order": 22 - }, - { - "id": 78227, - "field_id": 725899, - "hidden": true, - "order": 23 - }, - { - "id": 78228, - "field_id": 735944, - "hidden": true, - "order": 24 - }, - { - "id": 78644, - "field_id": 738833, - "hidden": true, - "order": 25 - }, - { - "id": 78645, - "field_id": 738895, - "hidden": true, - "order": 26 - }, - { - "id": 78646, - "field_id": 738896, - "hidden": true, - "order": 27 - } - ] - }, - { - "id": 174137, - "type": "gallery", - "name": "In stock in CD Fremont", - "order": 7, - "filter_type": "AND", - "filters_disabled": false, - "filters": [ - { - "id": 68736, - "field_id": 725788, - "type": "link_row_has", - "value": "2" - }, - { - "id": 68739, - "field_id": 735944, - "type": "boolean", - "value": "1" - } - ], - "sortings": [ - { - "id": 53159, - "field_id": 738896, - "order": "ASC" - }, - { - "id": 53162, - "field_id": 738895, - "order": "ASC" - }, - { - "id": 53163, - "field_id": 725743, - "order": "DESC" - } - ], - "decorations": [], - "public": false, - "card_cover_image_field_id": 705224, - "field_options": [ - { - "id": 78647, - "field_id": 705223, - "hidden": false, - "order": 1 - }, - { - "id": 78648, - "field_id": 705224, - "hidden": true, - "order": 2 - }, - { - "id": 78649, - "field_id": 725742, - "hidden": false, - "order": 3 - }, - { - "id": 78650, - "field_id": 725743, - "hidden": false, - "order": 4 - }, - { - "id": 78651, - "field_id": 705225, - "hidden": false, - "order": 5 - }, - { - "id": 78652, - "field_id": 725744, - "hidden": true, - "order": 6 - }, - { - "id": 78653, - "field_id": 725745, - "hidden": false, - "order": 7 - }, - { - "id": 78654, - "field_id": 725746, - "hidden": true, - "order": 8 - }, - { - "id": 78655, - "field_id": 725747, - "hidden": true, - "order": 9 - }, - { - "id": 78656, - "field_id": 725748, - "hidden": true, - "order": 10 - }, - { - "id": 78657, - "field_id": 725749, - "hidden": false, - "order": 11 - }, - { - "id": 78658, - "field_id": 725750, - "hidden": true, - "order": 12 - }, - { - "id": 78659, - "field_id": 725751, - "hidden": true, - "order": 13 - }, - { - "id": 78660, - "field_id": 725752, - "hidden": false, - "order": 14 - }, - { - "id": 78661, - "field_id": 725753, - "hidden": true, - "order": 15 - }, - { - "id": 78662, - "field_id": 725755, - "hidden": true, - "order": 16 - }, - { - "id": 78663, - "field_id": 725756, - "hidden": true, - "order": 17 - }, - { - "id": 78664, - "field_id": 725757, - "hidden": true, - "order": 18 - }, - { - "id": 78665, - "field_id": 725758, - "hidden": true, - "order": 19 - }, - { - "id": 78666, - "field_id": 725759, - "hidden": true, - "order": 20 - }, - { - "id": 78667, - "field_id": 725788, - "hidden": true, - "order": 21 - }, - { - "id": 78668, - "field_id": 725869, - "hidden": true, - "order": 22 - }, - { - "id": 78669, - "field_id": 725899, - "hidden": true, - "order": 23 - }, - { - "id": 78670, - "field_id": 735944, - "hidden": true, - "order": 24 - }, - { - "id": 78671, - "field_id": 738833, - "hidden": true, - "order": 25 - }, - { - "id": 78672, - "field_id": 738895, - "hidden": true, - "order": 26 - }, - { - "id": 78673, - "field_id": 738896, - "hidden": true, - "order": 27 - } - ] - }, - { - "id": 174142, - "type": "gallery", - "name": "In stock in CD La Mesa", - "order": 8, - "filter_type": "AND", - "filters_disabled": false, - "filters": [ - { - "id": 68740, - "field_id": 725788, - "type": "link_row_has", - "value": "1" - }, - { - "id": 68741, - "field_id": 735944, - "type": "boolean", - "value": "1" - } - ], - "sortings": [ - { - "id": 53164, - "field_id": 738896, - "order": "ASC" - }, - { - "id": 53165, - "field_id": 738895, - "order": "ASC" - }, - { - "id": 53166, - "field_id": 725743, - "order": "DESC" - } - ], - "decorations": [], - "public": false, - "card_cover_image_field_id": 705224, - "field_options": [ - { - "id": 78705, - "field_id": 705223, - "hidden": false, - "order": 1 - }, - { - "id": 78706, - "field_id": 705224, - "hidden": true, - "order": 2 - }, - { - "id": 78707, - "field_id": 725742, - "hidden": false, - "order": 3 - }, - { - "id": 78708, - "field_id": 725743, - "hidden": false, - "order": 4 - }, - { - "id": 78709, - "field_id": 705225, - "hidden": false, - "order": 5 - }, - { - "id": 78710, - "field_id": 725744, - "hidden": true, - "order": 6 - }, - { - "id": 78711, - "field_id": 725745, - "hidden": false, - "order": 7 - }, - { - "id": 78712, - "field_id": 725746, - "hidden": true, - "order": 8 - }, - { - "id": 78713, - "field_id": 725747, - "hidden": true, - "order": 9 - }, - { - "id": 78714, - "field_id": 725748, - "hidden": true, - "order": 10 - }, - { - "id": 78715, - "field_id": 725749, - "hidden": false, - "order": 11 - }, - { - "id": 78716, - "field_id": 725750, - "hidden": true, - "order": 12 - }, - { - "id": 78717, - "field_id": 725751, - "hidden": true, - "order": 13 - }, - { - "id": 78718, - "field_id": 725752, - "hidden": false, - "order": 14 - }, - { - "id": 78719, - "field_id": 725753, - "hidden": true, - "order": 15 - }, - { - "id": 78720, - "field_id": 725755, - "hidden": true, - "order": 16 - }, - { - "id": 78721, - "field_id": 725756, - "hidden": true, - "order": 17 - }, - { - "id": 78722, - "field_id": 725757, - "hidden": true, - "order": 18 - }, - { - "id": 78723, - "field_id": 725758, - "hidden": true, - "order": 19 - }, - { - "id": 78724, - "field_id": 725759, - "hidden": true, - "order": 20 - }, - { - "id": 78725, - "field_id": 725788, - "hidden": true, - "order": 21 - }, - { - "id": 78726, - "field_id": 725869, - "hidden": true, - "order": 22 - }, - { - "id": 78727, - "field_id": 725899, - "hidden": true, - "order": 23 - }, - { - "id": 78728, - "field_id": 735944, - "hidden": true, - "order": 24 - }, - { - "id": 78729, - "field_id": 738833, - "hidden": true, - "order": 25 - }, - { - "id": 78730, - "field_id": 738895, - "hidden": true, - "order": 26 - }, - { - "id": 78731, - "field_id": 738896, - "hidden": true, - "order": 27 - } - ] - }, - { - "id": 174143, - "type": "gallery", - "name": "In stock in CD Pomona", - "order": 9, - "filter_type": "AND", - "filters_disabled": false, - "filters": [ - { - "id": 68742, - "field_id": 725788, - "type": "link_row_has", - "value": "4" - }, - { - "id": 68743, - "field_id": 735944, - "type": "boolean", - "value": "1" - } - ], - "sortings": [ - { - "id": 53167, - "field_id": 738896, - "order": "ASC" - }, - { - "id": 53168, - "field_id": 738895, - "order": "ASC" - }, - { - "id": 53169, - "field_id": 725743, - "order": "DESC" - } - ], - "decorations": [], - "public": false, - "card_cover_image_field_id": 705224, - "field_options": [ - { - "id": 78732, - "field_id": 705223, - "hidden": false, - "order": 1 - }, - { - "id": 78733, - "field_id": 705224, - "hidden": true, - "order": 2 - }, - { - "id": 78734, - "field_id": 725742, - "hidden": false, - "order": 3 - }, - { - "id": 78735, - "field_id": 725743, - "hidden": false, - "order": 4 - }, - { - "id": 78736, - "field_id": 705225, - "hidden": false, - "order": 5 - }, - { - "id": 78737, - "field_id": 725744, - "hidden": true, - "order": 6 - }, - { - "id": 78738, - "field_id": 725745, - "hidden": false, - "order": 7 - }, - { - "id": 78739, - "field_id": 725746, - "hidden": true, - "order": 8 - }, - { - "id": 78740, - "field_id": 725747, - "hidden": true, - "order": 9 - }, - { - "id": 78741, - "field_id": 725748, - "hidden": true, - "order": 10 - }, - { - "id": 78742, - "field_id": 725749, - "hidden": false, - "order": 11 - }, - { - "id": 78743, - "field_id": 725750, - "hidden": true, - "order": 12 - }, - { - "id": 78744, - "field_id": 725751, - "hidden": true, - "order": 13 - }, - { - "id": 78745, - "field_id": 725752, - "hidden": false, - "order": 14 - }, - { - "id": 78746, - "field_id": 725753, - "hidden": true, - "order": 15 - }, - { - "id": 78747, - "field_id": 725755, - "hidden": true, - "order": 16 - }, - { - "id": 78748, - "field_id": 725756, - "hidden": true, - "order": 17 - }, - { - "id": 78749, - "field_id": 725757, - "hidden": true, - "order": 18 - }, - { - "id": 78750, - "field_id": 725758, - "hidden": true, - "order": 19 - }, - { - "id": 78751, - "field_id": 725759, - "hidden": true, - "order": 20 - }, - { - "id": 78752, - "field_id": 725788, - "hidden": true, - "order": 21 - }, - { - "id": 78753, - "field_id": 725869, - "hidden": true, - "order": 22 - }, - { - "id": 78754, - "field_id": 725899, - "hidden": true, - "order": 23 - }, - { - "id": 78755, - "field_id": 735944, - "hidden": true, - "order": 24 - }, - { - "id": 78756, - "field_id": 738833, - "hidden": true, - "order": 25 - }, - { - "id": 78757, - "field_id": 738895, - "hidden": true, - "order": 26 - }, - { - "id": 78758, - "field_id": 738896, - "hidden": true, - "order": 27 - } - ] - }, - { - "id": 174144, - "type": "gallery", - "name": "In stock in CD San Leandro", - "order": 10, - "filter_type": "AND", - "filters_disabled": false, - "filters": [ - { - "id": 68744, - "field_id": 725788, - "type": "link_row_has", - "value": "3" - }, - { - "id": 68745, - "field_id": 735944, - "type": "boolean", - "value": "1" - } - ], - "sortings": [ - { - "id": 53170, - "field_id": 738896, - "order": "ASC" - }, - { - "id": 53171, - "field_id": 738895, - "order": "ASC" - }, - { - "id": 53172, - "field_id": 725743, - "order": "DESC" - } - ], - "decorations": [], - "public": false, - "card_cover_image_field_id": 705224, - "field_options": [ - { - "id": 78759, - "field_id": 705223, - "hidden": false, - "order": 1 - }, - { - "id": 78760, - "field_id": 705224, - "hidden": true, - "order": 2 - }, - { - "id": 78761, - "field_id": 725742, - "hidden": false, - "order": 3 - }, - { - "id": 78762, - "field_id": 725743, - "hidden": false, - "order": 4 - }, - { - "id": 78763, - "field_id": 705225, - "hidden": false, - "order": 5 - }, - { - "id": 78764, - "field_id": 725744, - "hidden": true, - "order": 6 - }, - { - "id": 78765, - "field_id": 725745, - "hidden": false, - "order": 7 - }, - { - "id": 78766, - "field_id": 725746, - "hidden": true, - "order": 8 - }, - { - "id": 78767, - "field_id": 725747, - "hidden": true, - "order": 9 - }, - { - "id": 78768, - "field_id": 725748, - "hidden": true, - "order": 10 - }, - { - "id": 78769, - "field_id": 725749, - "hidden": false, - "order": 11 - }, - { - "id": 78770, - "field_id": 725750, - "hidden": true, - "order": 12 - }, - { - "id": 78771, - "field_id": 725751, - "hidden": true, - "order": 13 - }, - { - "id": 78772, - "field_id": 725752, - "hidden": false, - "order": 14 - }, - { - "id": 78773, - "field_id": 725753, - "hidden": true, - "order": 15 - }, - { - "id": 78774, - "field_id": 725755, - "hidden": true, - "order": 16 - }, - { - "id": 78775, - "field_id": 725756, - "hidden": true, - "order": 17 - }, - { - "id": 78776, - "field_id": 725757, - "hidden": true, - "order": 18 - }, - { - "id": 78777, - "field_id": 725758, - "hidden": true, - "order": 19 - }, - { - "id": 78778, - "field_id": 725759, - "hidden": true, - "order": 20 - }, - { - "id": 78779, - "field_id": 725788, - "hidden": true, - "order": 21 - }, - { - "id": 78780, - "field_id": 725869, - "hidden": true, - "order": 22 - }, - { - "id": 78781, - "field_id": 725899, - "hidden": true, - "order": 23 - }, - { - "id": 78782, - "field_id": 735944, - "hidden": true, - "order": 24 - }, - { - "id": 78783, - "field_id": 738833, - "hidden": true, - "order": 25 - }, - { - "id": 78784, - "field_id": 738895, - "hidden": true, - "order": 26 - }, - { - "id": 78785, - "field_id": 738896, - "hidden": true, - "order": 27 - } - ] - }, - { - "id": 174135, - "type": "kanban", - "name": "By status", "order": 11, + "ownership_type": "collaborative", + "owned_by": null, "filter_type": "AND", "filters_disabled": false, "filters": [], - "sortings": [], + "filter_groups": [], + "sortings": [ + { + "id": 20378, + "field_id": 59841, + "order": "DESC" + } + ], "decorations": [], "public": false, - "single_select_field_id": 725749, - "card_cover_image_field_id": 705224, + "card_cover_image_field_id": 59761, "field_options": [ { - "id": 43609, - "field_id": 705223, - "hidden": false, + "id": 25480, + "field_id": 59760, + "hidden": true, "order": 1 }, { - "id": 43610, - "field_id": 705224, + "id": 25481, + "field_id": 59761, "hidden": true, "order": 2 }, { - "id": 43612, - "field_id": 725742, + "id": 25482, + "field_id": 59762, "hidden": false, "order": 3 }, { - "id": 43613, - "field_id": 725743, + "id": 25483, + "field_id": 59840, "hidden": false, "order": 4 }, { - "id": 43611, - "field_id": 705225, + "id": 25484, + "field_id": 59841, "hidden": false, "order": 5 }, { - "id": 43614, - "field_id": 725744, - "hidden": true, + "id": 25485, + "field_id": 59848, + "hidden": false, "order": 6 }, { - "id": 43615, - "field_id": 725745, + "id": 25486, + "field_id": 59763, "hidden": false, "order": 7 }, { - "id": 43616, - "field_id": 725746, - "hidden": true, + "id": 25487, + "field_id": 59764, + "hidden": false, "order": 8 }, { - "id": 43617, - "field_id": 725747, - "hidden": true, + "id": 25488, + "field_id": 59765, + "hidden": false, "order": 9 }, { - "id": 43618, - "field_id": 725748, + "id": 25489, + "field_id": 59766, "hidden": true, "order": 10 }, { - "id": 43619, - "field_id": 725749, - "hidden": true, + "id": 25490, + "field_id": 59867, + "hidden": false, "order": 11 }, { - "id": 43620, - "field_id": 725750, + "id": 25491, + "field_id": 59767, "hidden": true, "order": 12 }, { - "id": 43621, - "field_id": 725751, + "id": 25492, + "field_id": 59768, "hidden": true, "order": 13 }, { - "id": 43622, - "field_id": 725752, - "hidden": true, + "id": 25493, + "field_id": 59842, + "hidden": false, "order": 14 }, { - "id": 43623, - "field_id": 725753, + "id": 25494, + "field_id": 59769, "hidden": true, "order": 15 }, { - "id": 43624, - "field_id": 725755, + "id": 25495, + "field_id": 59770, "hidden": true, "order": 16 }, { - "id": 43625, - "field_id": 725756, + "id": 25496, + "field_id": 59771, "hidden": true, "order": 17 }, { - "id": 43626, - "field_id": 725757, + "id": 25497, + "field_id": 59772, "hidden": true, "order": 18 }, { - "id": 43627, - "field_id": 725758, + "id": 25498, + "field_id": 59773, "hidden": true, "order": 19 }, { - "id": 43628, - "field_id": 725759, + "id": 25499, + "field_id": 59774, "hidden": true, "order": 20 }, { - "id": 43629, - "field_id": 725788, - "hidden": true, + "id": 25500, + "field_id": 59775, + "hidden": false, "order": 21 }, { - "id": 43630, - "field_id": 725869, + "id": 25501, + "field_id": 59776, "hidden": true, "order": 22 }, { - "id": 43631, - "field_id": 725899, + "id": 25502, + "field_id": 59866, "hidden": true, "order": 23 }, { - "id": 43632, - "field_id": 735944, + "id": 25503, + "field_id": 59777, "hidden": true, "order": 24 }, { - "id": 43633, - "field_id": 738833, + "id": 25504, + "field_id": 59843, "hidden": true, "order": 25 }, { - "id": 43634, - "field_id": 738895, + "id": 25505, + "field_id": 59844, "hidden": true, "order": 26 - }, - { - "id": 43635, - "field_id": 738896, - "hidden": true, - "order": 27 } ] }, { - "id": 174136, + "id": 26476, "type": "kanban", - "name": "By condition", + "name": "All vehicles stacked by condition", "order": 12, + "ownership_type": "collaborative", + "owned_by": null, "filter_type": "AND", "filters_disabled": false, "filters": [], + "filter_groups": [], "sortings": [], "decorations": [], "public": false, - "single_select_field_id": 725745, - "card_cover_image_field_id": 705224, + "single_select_field_id": 59763, + "card_cover_image_field_id": 59761, "field_options": [ { - "id": 43636, - "field_id": 705223, + "id": 35141, + "field_id": 59760, "hidden": false, "order": 1 }, { - "id": 43637, - "field_id": 705224, + "id": 35142, + "field_id": 59761, "hidden": true, "order": 2 }, { - "id": 43638, - "field_id": 725742, + "id": 35143, + "field_id": 59840, "hidden": false, "order": 3 }, { - "id": 43639, - "field_id": 725743, + "id": 35144, + "field_id": 59841, "hidden": false, "order": 4 }, { - "id": 43640, - "field_id": 705225, + "id": 35145, + "field_id": 59762, "hidden": false, "order": 5 }, { - "id": 43641, - "field_id": 725744, - "hidden": true, - "order": 6 - }, - { - "id": 43642, - "field_id": 725745, + "id": 35146, + "field_id": 59763, "hidden": false, "order": 7 }, { - "id": 43643, - "field_id": 725746, + "id": 35147, + "field_id": 59764, "hidden": true, "order": 8 }, { - "id": 43644, - "field_id": 725747, + "id": 35148, + "field_id": 59765, "hidden": true, "order": 9 }, { - "id": 43645, - "field_id": 725748, + "id": 35149, + "field_id": 59766, "hidden": true, "order": 10 }, { - "id": 43646, - "field_id": 725749, + "id": 35150, + "field_id": 59867, "hidden": true, "order": 11 }, { - "id": 43647, - "field_id": 725750, + "id": 35151, + "field_id": 59767, "hidden": true, "order": 12 }, { - "id": 43648, - "field_id": 725751, + "id": 35152, + "field_id": 59768, "hidden": true, "order": 13 }, { - "id": 43649, - "field_id": 725752, + "id": 35153, + "field_id": 59842, "hidden": true, "order": 14 }, { - "id": 43650, - "field_id": 725753, + "id": 35154, + "field_id": 59769, "hidden": true, "order": 15 }, { - "id": 43651, - "field_id": 725755, + "id": 35155, + "field_id": 59770, "hidden": true, "order": 16 }, { - "id": 43652, - "field_id": 725756, + "id": 35156, + "field_id": 59771, "hidden": true, "order": 17 }, { - "id": 43653, - "field_id": 725757, + "id": 35157, + "field_id": 59772, "hidden": true, "order": 18 }, { - "id": 43654, - "field_id": 725758, + "id": 35158, + "field_id": 59773, "hidden": true, "order": 19 }, { - "id": 43655, - "field_id": 725759, + "id": 35159, + "field_id": 59774, "hidden": true, "order": 20 }, { - "id": 43656, - "field_id": 725788, + "id": 35160, + "field_id": 59775, "hidden": true, "order": 21 }, { - "id": 43657, - "field_id": 725869, + "id": 35161, + "field_id": 59776, "hidden": true, "order": 22 }, { - "id": 43658, - "field_id": 725899, + "id": 35162, + "field_id": 59866, "hidden": true, "order": 23 }, { - "id": 43659, - "field_id": 735944, - "hidden": true, - "order": 24 - }, - { - "id": 43660, - "field_id": 738833, + "id": 35163, + "field_id": 59777, "hidden": true, "order": 25 }, { - "id": 43661, - "field_id": 738895, + "id": 35164, + "field_id": 59843, "hidden": true, - "order": 26 + "order": 32767 }, { - "id": 43662, - "field_id": 738896, + "id": 35165, + "field_id": 59844, "hidden": true, - "order": 27 + "order": 32767 } ] }, { - "id": 174145, + "id": 26477, "type": "form", "name": "Add vehicle", "order": 13, + "ownership_type": "collaborative", + "owned_by": null, "public": false, "title": "Add a new vehicle", "description": "", "cover_image": { - "name": "0Aq0U0C91BByoilrOjWtWYrAWJSKp9qx_26800c52d7db8004bfb88a9d384bf835025a27b47a3b8e41028d0d121a23bf56.jpg", + "name": "4gp8dLy2dm0lDYs1vurX7Qta8I1rBJpA_26800c52d7db8004bfb88a9d384bf835025a27b47a3b8e41028d0d121a23bf56.jpg", "original_name": "Header_CarDealership.01.jpg" }, "logo_image": null, @@ -3496,8 +6805,8 @@ "submit_action_redirect_url": "", "field_options": [ { - "id": 100732, - "field_id": 705224, + "id": 25254, + "field_id": 59761, "name": "", "description": "Please upload any photo or photos of the actual vehicle/stock/unit here. You may include photos of this vehicle's engraved ID numbers.", "enabled": true, @@ -3505,11 +6814,15 @@ "order": 0, "show_when_matching_conditions": false, "condition_type": "AND", - "conditions": [] + "conditions": [], + "condition_groups": [], + "field_component": "default", + "include_all_select_options": true, + "allowed_select_options": [] }, { - "id": 100733, - "field_id": 705225, + "id": 25255, + "field_id": 59762, "name": "", "description": "Please state the vehicle's model and variant/trim.", "enabled": true, @@ -3517,35 +6830,47 @@ "order": 1, "show_when_matching_conditions": false, "condition_type": "AND", - "conditions": [] + "conditions": [], + "condition_groups": [], + "field_component": "default", + "include_all_select_options": true, + "allowed_select_options": [] }, { - "id": 100735, - "field_id": 725743, + "id": 25256, + "field_id": 59841, "name": "", "description": "Enter the year this vehicle was manufactured or released from factory.", - "enabled": true, + "enabled": false, "required": true, "order": 2, "show_when_matching_conditions": false, "condition_type": "AND", - "conditions": [] + "conditions": [], + "condition_groups": [], + "field_component": "default", + "include_all_select_options": true, + "allowed_select_options": [] }, { - "id": 100741, - "field_id": 725749, + "id": 25257, + "field_id": 59867, "name": "", "description": "Please select the current inventory status of this vehicle.", - "enabled": true, + "enabled": false, "required": true, "order": 3, "show_when_matching_conditions": false, "condition_type": "AND", - "conditions": [] + "conditions": [], + "condition_groups": [], + "field_component": "default", + "include_all_select_options": true, + "allowed_select_options": [] }, { - "id": 100737, - "field_id": 725745, + "id": 25258, + "field_id": 59763, "name": "", "description": "Select the vehicle's current condition.", "enabled": true, @@ -3553,11 +6878,15 @@ "order": 4, "show_when_matching_conditions": false, "condition_type": "AND", - "conditions": [] + "conditions": [], + "condition_groups": [], + "field_component": "default", + "include_all_select_options": true, + "allowed_select_options": [] }, { - "id": 100738, - "field_id": 725746, + "id": 25259, + "field_id": 59764, "name": "", "description": "Enter the current number of miles on this vehicle's odometer.", "enabled": true, @@ -3565,11 +6894,15 @@ "order": 5, "show_when_matching_conditions": false, "condition_type": "AND", - "conditions": [] + "conditions": [], + "condition_groups": [], + "field_component": "default", + "include_all_select_options": true, + "allowed_select_options": [] }, { - "id": 100739, - "field_id": 725747, + "id": 25260, + "field_id": 59765, "name": "", "description": "Enter the vehicle's exact color name defined by the manufacturer.", "enabled": true, @@ -3577,11 +6910,15 @@ "order": 6, "show_when_matching_conditions": false, "condition_type": "AND", - "conditions": [] + "conditions": [], + "condition_groups": [], + "field_component": "default", + "include_all_select_options": true, + "allowed_select_options": [] }, { - "id": 100746, - "field_id": 725755, + "id": 25261, + "field_id": 59770, "name": "", "description": "Enter the vehicle's specific registration plate number.", "enabled": true, @@ -3589,11 +6926,15 @@ "order": 7, "show_when_matching_conditions": false, "condition_type": "AND", - "conditions": [] + "conditions": [], + "condition_groups": [], + "field_component": "default", + "include_all_select_options": true, + "allowed_select_options": [] }, { - "id": 100740, - "field_id": 725748, + "id": 25262, + "field_id": 59766, "name": "", "description": "Enter the overall cost of this vehicle's acquisition, maintenance, storage fee, and repairs.", "enabled": true, @@ -3601,11 +6942,15 @@ "order": 8, "show_when_matching_conditions": false, "condition_type": "AND", - "conditions": [] + "conditions": [], + "condition_groups": [], + "field_component": "default", + "include_all_select_options": true, + "allowed_select_options": [] }, { - "id": 100743, - "field_id": 725751, + "id": 25263, + "field_id": 59768, "name": "", "description": "Enter the suggested percentage over the cost for this vehicle.", "enabled": true, @@ -3613,23 +6958,31 @@ "order": 9, "show_when_matching_conditions": false, "condition_type": "AND", - "conditions": [] + "conditions": [], + "condition_groups": [], + "field_component": "default", + "include_all_select_options": true, + "allowed_select_options": [] }, { - "id": 100742, - "field_id": 725750, + "id": 25264, + "field_id": 59767, "name": "", "description": "If this vehicle has been sold, you can link the details of the sale to this vehicle by selecting the transaction record.", - "enabled": true, + "enabled": false, "required": false, "order": 10, "show_when_matching_conditions": false, "condition_type": "AND", - "conditions": [] + "conditions": [], + "condition_groups": [], + "field_component": "default", + "include_all_select_options": true, + "allowed_select_options": [] }, { - "id": 100745, - "field_id": 725753, + "id": 25265, + "field_id": 59769, "name": "", "description": "Enumerate all accessories or modifications on this vehicle.", "enabled": true, @@ -3637,11 +6990,15 @@ "order": 11, "show_when_matching_conditions": false, "condition_type": "AND", - "conditions": [] + "conditions": [], + "condition_groups": [], + "field_component": "default", + "include_all_select_options": true, + "allowed_select_options": [] }, { - "id": 100747, - "field_id": 725756, + "id": 25266, + "field_id": 59771, "name": "", "description": "Please enter the vehicle's unique chassis number or frame number.", "enabled": true, @@ -3649,11 +7006,15 @@ "order": 12, "show_when_matching_conditions": false, "condition_type": "AND", - "conditions": [] + "conditions": [], + "condition_groups": [], + "field_component": "default", + "include_all_select_options": true, + "allowed_select_options": [] }, { - "id": 100755, - "field_id": 738833, + "id": 25267, + "field_id": 59777, "name": "", "description": "Please enter the vehicle's unique engine block identification number.", "enabled": true, @@ -3661,11 +7022,15 @@ "order": 13, "show_when_matching_conditions": false, "condition_type": "AND", - "conditions": [] + "conditions": [], + "condition_groups": [], + "field_component": "default", + "include_all_select_options": true, + "allowed_select_options": [] }, { - "id": 100749, - "field_id": 725758, + "id": 25268, + "field_id": 59773, "name": "", "description": "Please enter the date this vehicle was acquired by your dealership.", "enabled": true, @@ -3673,11 +7038,15 @@ "order": 14, "show_when_matching_conditions": false, "condition_type": "AND", - "conditions": [] + "conditions": [], + "condition_groups": [], + "field_component": "default", + "include_all_select_options": true, + "allowed_select_options": [] }, { - "id": 100751, - "field_id": 725788, + "id": 25269, + "field_id": 59775, "name": "", "description": "Please select the dealership where this vehicle is located or stored.", "enabled": true, @@ -3685,23 +7054,31 @@ "order": 15, "show_when_matching_conditions": false, "condition_type": "AND", - "conditions": [] + "conditions": [], + "condition_groups": [], + "field_component": "default", + "include_all_select_options": true, + "allowed_select_options": [] }, { - "id": 100750, - "field_id": 725759, + "id": 25270, + "field_id": 59774, "name": "", - "description": "Please select the staff member in charge of getting this vehicle.", + "description": "Please select the staff\u00a0member in\u00a0charge\u00a0of\u00a0getting\u00a0this\u00a0vehicle.", "enabled": true, "required": true, "order": 16, "show_when_matching_conditions": false, "condition_type": "AND", - "conditions": [] + "conditions": [], + "condition_groups": [], + "field_component": "default", + "include_all_select_options": true, + "allowed_select_options": [] }, { - "id": 100752, - "field_id": 725869, + "id": 25271, + "field_id": 59776, "name": "", "description": "Enter any other notes or brief description about this vehicle.", "enabled": true, @@ -3709,11 +7086,15 @@ "order": 17, "show_when_matching_conditions": false, "condition_type": "AND", - "conditions": [] + "conditions": [], + "condition_groups": [], + "field_component": "default", + "include_all_select_options": true, + "allowed_select_options": [] }, { - "id": 100748, - "field_id": 725757, + "id": 25272, + "field_id": 59772, "name": "", "description": "Upload all legal documents associated with this vehicle.", "enabled": true, @@ -3721,11 +7102,15 @@ "order": 18, "show_when_matching_conditions": false, "condition_type": "AND", - "conditions": [] + "conditions": [], + "condition_groups": [], + "field_component": "default", + "include_all_select_options": true, + "allowed_select_options": [] }, { - "id": 100731, - "field_id": 705223, + "id": 25273, + "field_id": 59760, "name": "", "description": "", "enabled": false, @@ -3733,11 +7118,15 @@ "order": 19, "show_when_matching_conditions": false, "condition_type": "AND", - "conditions": [] + "conditions": [], + "condition_groups": [], + "field_component": "default", + "include_all_select_options": true, + "allowed_select_options": [] }, { - "id": 100734, - "field_id": 725742, + "id": 25274, + "field_id": 59840, "name": "", "description": "", "enabled": false, @@ -3745,23 +7134,15 @@ "order": 20, "show_when_matching_conditions": false, "condition_type": "AND", - "conditions": [] + "conditions": [], + "condition_groups": [], + "field_component": "default", + "include_all_select_options": true, + "allowed_select_options": [] }, { - "id": 100736, - "field_id": 725744, - "name": "", - "description": "", - "enabled": false, - "required": true, - "order": 21, - "show_when_matching_conditions": false, - "condition_type": "AND", - "conditions": [] - }, - { - "id": 100744, - "field_id": 725752, + "id": 25275, + "field_id": 59842, "name": "", "description": "", "enabled": false, @@ -3769,11 +7150,15 @@ "order": 22, "show_when_matching_conditions": false, "condition_type": "AND", - "conditions": [] + "conditions": [], + "condition_groups": [], + "field_component": "default", + "include_all_select_options": true, + "allowed_select_options": [] }, { - "id": 100753, - "field_id": 725899, + "id": 25276, + "field_id": 59866, "name": "", "description": "", "enabled": false, @@ -3781,43 +7166,43 @@ "order": 23, "show_when_matching_conditions": false, "condition_type": "AND", - "conditions": [] + "conditions": [], + "condition_groups": [], + "field_component": "default", + "include_all_select_options": true, + "allowed_select_options": [] }, { - "id": 100754, - "field_id": 735944, + "id": 25277, + "field_id": 59843, "name": "", "description": "", "enabled": false, "required": true, - "order": 24, + "order": 32767, "show_when_matching_conditions": false, "condition_type": "AND", - "conditions": [] + "conditions": [], + "condition_groups": [], + "field_component": "default", + "include_all_select_options": true, + "allowed_select_options": [] }, { - "id": 100756, - "field_id": 738895, + "id": 25278, + "field_id": 59844, "name": "", "description": "", "enabled": false, "required": true, - "order": 25, + "order": 32767, "show_when_matching_conditions": false, "condition_type": "AND", - "conditions": [] - }, - { - "id": 100757, - "field_id": 738896, - "name": "", - "description": "", - "enabled": false, - "required": true, - "order": 26, - "show_when_matching_conditions": false, - "condition_type": "AND", - "conditions": [] + "conditions": [], + "condition_groups": [], + "field_component": "default", + "include_all_select_options": true, + "allowed_select_options": [] } ] } @@ -3828,1971 +7213,2037 @@ "order": "1.00000000000000000000", "created_on": "2022-11-02T13:06:26.404591+00:00", "updated_on": "2022-11-20T21:10:58.529445+00:00", - "field_705223": null, - "field_705224": [ + "field_59760": null, + "field_59761": [ { - "name": "MHlDkmgGxE5OAlTvYGMSBjKPow2Fghcj_238b76a9d3d8d4c813a5f71b29f8c9565037f526a8d553595f268a97b657b7bf.jpg", + "name": "Pk1g6HuhihODsQd5xQjfuHXsJbx1l3Qn_238b76a9d3d8d4c813a5f71b29f8c9565037f526a8d553595f268a97b657b7bf.jpg", "visible_name": "OR.Toyota.HiluxConquest4x4.EmotionalRed.jpg", - "original_name": "OR.Toyota.HiluxConquest4x4.EmotionalRed.jpg" + "original_name": "Pk1g6HuhihODsQd5xQjfuHXsJbx1l3Qn_238b76a9d3d8d4c813a5f71b29f8c9565037f526a8d553595f268a97b657b7bf.jpg" } ], - "field_705225": [ + "field_59762": [ 1 ], - "field_725742": null, - "field_725743": "2022", - "field_725744": null, - "field_725745": 313850, - "field_725746": "3", - "field_725747": "Emotional red", - "field_725748": "27000.00", - "field_725749": 313857, - "field_725750": [], - "field_725751": "20", - "field_725752": null, - "field_725753": "• Free 15gal fuel\n• Windshield and window tints\n• Reverse parking sensor\n• Toolbox\n• Floor matting", - "field_725755": "WAD8792", - "field_725756": "4T1BG22K6VR3P2NHM", - "field_725757": [ + "field_59840": null, + "field_59841": null, + "field_59763": 21052, + "field_59764": "3", + "field_59765": "Emotional red", + "field_59766": "27000", + "field_59867": null, + "field_59767": [], + "field_59768": "20", + "field_59842": null, + "field_59769": "\u2022 Free 15gal fuel\n\u2022 Windshield and window tints\n\u2022 Reverse parking sensor\n\u2022 Toolbox\n\u2022 Floor matting", + "field_59770": "WAD8792", + "field_59771": "4T1BG22K6VR3P2NHM", + "field_59772": [ { - "name": "iQ8EvGq8TSuARN9lajPbnEUQtJq6Y1kM_ac5e07c439066a20b7e755891d10af1c0afd6654e7470ca1129973c94ee60767.jpg", + "name": "psOkzupTYP2Yj5aHa5hAkiEYJ7HU9qum_ac5e07c439066a20b7e755891d10af1c0afd6654e7470ca1129973c94ee60767.jpg", "visible_name": "vehicle_title.jpg", - "original_name": "vehicle_title.jpg" + "original_name": "psOkzupTYP2Yj5aHa5hAkiEYJ7HU9qum_ac5e07c439066a20b7e755891d10af1c0afd6654e7470ca1129973c94ee60767.jpg" } ], - "field_725758": "2022-01-05", - "field_725759": [ + "field_59773": "2022-01-05", + "field_59774": [ 1 ], - "field_725788": [ + "field_59775": [ 2 ], - "field_725869": "This unit is reserved to a customer from a couple of blocks away.", - "field_725899": null, - "field_735944": null, - "field_738833": "VR3P2NHJ", - "field_738895": null, - "field_738896": null + "field_59776": "This unit is reserved to a customer from a couple of blocks away.", + "field_59866": null, + "field_59777": "VR3P2NHJ", + "field_59843": null, + "field_59844": null, + "field_59848": null, + "field_59849": null, + "field_59778": [], + "field_59779": null }, { "id": 2, "order": "2.00000000000000000000", "created_on": "2022-11-02T13:06:26.404656+00:00", "updated_on": "2022-11-20T21:11:26.231719+00:00", - "field_705223": null, - "field_705224": [ + "field_59760": null, + "field_59761": [ { - "name": "C59DDsPcGLyNIVFLZyOHNnglHinhZ0Hg_7882b4916169aa5940f02d2e97fdc6d875df4699ff3b280238f2c27e050cfc4f.jpg", + "name": "E7oVI1hOiqgyDKsExE7EtB8iENSkMQ5w_7882b4916169aa5940f02d2e97fdc6d875df4699ff3b280238f2c27e050cfc4f.jpg", "visible_name": "OR.Toyota.HiluxConquest4x4.SilverMetallic3.jpg", - "original_name": "OR.Toyota.HiluxConquest4x4.SilverMetallic3.jpg" + "original_name": "E7oVI1hOiqgyDKsExE7EtB8iENSkMQ5w_7882b4916169aa5940f02d2e97fdc6d875df4699ff3b280238f2c27e050cfc4f.jpg" } ], - "field_705225": [ + "field_59762": [ 1 ], - "field_725742": null, - "field_725743": "2021", - "field_725744": null, - "field_725745": 313851, - "field_725746": "12", - "field_725747": "Silver Metallic 3", - "field_725748": "27000.00", - "field_725749": 313861, - "field_725750": [], - "field_725751": "15", - "field_725752": null, - "field_725753": "• Free 15gal fuel\n• Windshield and window tints\n• Reverse parking sensor\n• Toolbox\n• Floor matting", - "field_725755": "WDF3287", - "field_725756": "4T1FA38P66CCHVR3U", - "field_725757": [ + "field_59840": null, + "field_59841": null, + "field_59763": 21053, + "field_59764": "12", + "field_59765": "Silver Metallic 3", + "field_59766": "27000", + "field_59867": null, + "field_59767": [], + "field_59768": "15", + "field_59842": null, + "field_59769": "\u2022 Free 15gal fuel\n\u2022 Windshield and window tints\n\u2022 Reverse parking sensor\n\u2022 Toolbox\n\u2022 Floor matting", + "field_59770": "WDF3287", + "field_59771": "4T1FA38P66CCHVR3U", + "field_59772": [ { - "name": "iQ8EvGq8TSuARN9lajPbnEUQtJq6Y1kM_ac5e07c439066a20b7e755891d10af1c0afd6654e7470ca1129973c94ee60767.jpg", + "name": "psOkzupTYP2Yj5aHa5hAkiEYJ7HU9qum_ac5e07c439066a20b7e755891d10af1c0afd6654e7470ca1129973c94ee60767.jpg", "visible_name": "vehicle_title.jpg", - "original_name": "vehicle_title.jpg" + "original_name": "psOkzupTYP2Yj5aHa5hAkiEYJ7HU9qum_ac5e07c439066a20b7e755891d10af1c0afd6654e7470ca1129973c94ee60767.jpg" } ], - "field_725758": "2021-01-11", - "field_725759": [ + "field_59773": "2021-01-11", + "field_59774": [ 8 ], - "field_725788": [ + "field_59775": [ 3 ], - "field_725869": null, - "field_725899": null, - "field_735944": null, - "field_738833": "6CCHVR3O", - "field_738895": null, - "field_738896": null + "field_59776": null, + "field_59866": null, + "field_59777": "6CCHVR3O", + "field_59843": null, + "field_59844": null, + "field_59848": null, + "field_59849": null, + "field_59778": [], + "field_59779": null }, { "id": 3, "order": "3.00000000000000000000", "created_on": "2022-11-18T22:03:06.773821+00:00", "updated_on": "2022-11-20T21:12:51.817147+00:00", - "field_705223": null, - "field_705224": [ + "field_59760": null, + "field_59761": [ { - "name": "MkwB4oVkvBVT9NL2fx1CaSNA0DCRcgpL_379d3ae35805d451b26674f133db2d4d91fda0addfe566064d929ea2855ad5af.jpg", + "name": "8BE41nPO5EZCF9jkb8Wvj22LprDqmoXn_379d3ae35805d451b26674f133db2d4d91fda0addfe566064d929ea2855ad5af.jpg", "visible_name": "OR.Toyota.HiluxE4x2.SuperWhiteII.jpg", - "original_name": "OR.Toyota.HiluxE4x2.SuperWhiteII.jpg" + "original_name": "8BE41nPO5EZCF9jkb8Wvj22LprDqmoXn_379d3ae35805d451b26674f133db2d4d91fda0addfe566064d929ea2855ad5af.jpg" } ], - "field_705225": [ + "field_59762": [ 2 ], - "field_725742": null, - "field_725743": "2022", - "field_725744": null, - "field_725745": 313850, - "field_725746": "3", - "field_725747": "Super White II", - "field_725748": "17000.00", - "field_725749": 313856, - "field_725750": [], - "field_725751": "20", - "field_725752": null, - "field_725753": "• Free 15gal fuel\n• Windshield and window tints\n• Reverse parking sensor\n• Toolbox\n• Floor matting", - "field_725755": "WFA3217", - "field_725756": "4T1BK36B39ZFMJPY8", - "field_725757": [ + "field_59840": null, + "field_59841": null, + "field_59763": 21052, + "field_59764": "3", + "field_59765": "Super White II", + "field_59766": "17000", + "field_59867": null, + "field_59767": [ + 20 + ], + "field_59768": "20", + "field_59842": null, + "field_59769": "\u2022 Free 15gal fuel\n\u2022 Windshield and window tints\n\u2022 Reverse parking sensor\n\u2022 Toolbox\n\u2022 Floor matting", + "field_59770": "WFA3217", + "field_59771": "4T1BK36B39ZFMJPY8", + "field_59772": [ { - "name": "iQ8EvGq8TSuARN9lajPbnEUQtJq6Y1kM_ac5e07c439066a20b7e755891d10af1c0afd6654e7470ca1129973c94ee60767.jpg", + "name": "psOkzupTYP2Yj5aHa5hAkiEYJ7HU9qum_ac5e07c439066a20b7e755891d10af1c0afd6654e7470ca1129973c94ee60767.jpg", "visible_name": "vehicle_title.jpg", - "original_name": "vehicle_title.jpg" + "original_name": "psOkzupTYP2Yj5aHa5hAkiEYJ7HU9qum_ac5e07c439066a20b7e755891d10af1c0afd6654e7470ca1129973c94ee60767.jpg" } ], - "field_725758": "2022-01-05", - "field_725759": [ + "field_59773": "2022-01-05", + "field_59774": [ 2 ], - "field_725788": [ + "field_59775": [ 4 ], - "field_725869": "Processing all legal documents.", - "field_725899": null, - "field_735944": null, - "field_738833": "9ZFMJPYE", - "field_738895": null, - "field_738896": null + "field_59776": "Processing all legal documents.", + "field_59866": null, + "field_59777": "9ZFMJPYE", + "field_59843": null, + "field_59844": null, + "field_59848": null, + "field_59849": null, + "field_59778": [], + "field_59779": null }, { "id": 4, "order": "4.00000000000000000000", "created_on": "2022-11-18T22:48:34.065203+00:00", "updated_on": "2022-11-20T21:10:57.408603+00:00", - "field_705223": null, - "field_705224": [ + "field_59760": null, + "field_59761": [ { - "name": "10zF5xrm5pi5NzxomuhoSPBsjLRmVrlC_28042d7a9ee6e39e060d4f81812f2780e9ef1b0476bdb59759fd277934b8e098.jpg", + "name": "kGXm2qAdZO7uwIKetGEZjpLIRVWhzQjR_28042d7a9ee6e39e060d4f81812f2780e9ef1b0476bdb59759fd277934b8e098.jpg", "visible_name": "OF.Mitsubishi.MonteroSportGLX2WD.MediumRedMica.jpg", - "original_name": "OF.Mitsubishi.MonteroSportGLX2WD.MediumRedMica.jpg" + "original_name": "kGXm2qAdZO7uwIKetGEZjpLIRVWhzQjR_28042d7a9ee6e39e060d4f81812f2780e9ef1b0476bdb59759fd277934b8e098.jpg" } ], - "field_705225": [ + "field_59762": [ 6 ], - "field_725742": null, - "field_725743": "2021", - "field_725744": null, - "field_725745": 313851, - "field_725746": "10", - "field_725747": "Medium Red Mica", - "field_725748": "21500.00", - "field_725749": 313859, - "field_725750": [ + "field_59840": null, + "field_59841": null, + "field_59763": 21053, + "field_59764": "10", + "field_59765": "Medium Red Mica", + "field_59766": "21500", + "field_59867": null, + "field_59767": [ 6 ], - "field_725751": "20", - "field_725752": null, - "field_725753": "• Free 17gal fuel\n• Windshield and window tints\n• Reverse parking sensor\n• Toolbox\n• Floor matting", - "field_725755": "MDA9852", - "field_725756": "1Z5HT48N263VH4ZP3", - "field_725757": [ + "field_59768": "20", + "field_59842": null, + "field_59769": "\u2022 Free 17gal fuel\n\u2022 Windshield and window tints\n\u2022 Reverse parking sensor\n\u2022 Toolbox\n\u2022 Floor matting", + "field_59770": "MDA9852", + "field_59771": "1Z5HT48N263VH4ZP3", + "field_59772": [ { - "name": "iQ8EvGq8TSuARN9lajPbnEUQtJq6Y1kM_ac5e07c439066a20b7e755891d10af1c0afd6654e7470ca1129973c94ee60767.jpg", + "name": "psOkzupTYP2Yj5aHa5hAkiEYJ7HU9qum_ac5e07c439066a20b7e755891d10af1c0afd6654e7470ca1129973c94ee60767.jpg", "visible_name": "vehicle_title.jpg", - "original_name": "vehicle_title.jpg" + "original_name": "psOkzupTYP2Yj5aHa5hAkiEYJ7HU9qum_ac5e07c439066a20b7e755891d10af1c0afd6654e7470ca1129973c94ee60767.jpg" } ], - "field_725758": "2020-10-20", - "field_725759": [ + "field_59773": "2020-10-20", + "field_59774": [ 1 ], - "field_725788": [ + "field_59775": [ 2 ], - "field_725869": "", - "field_725899": null, - "field_735944": null, - "field_738833": "63VH4ZPD", - "field_738895": null, - "field_738896": null + "field_59776": "", + "field_59866": null, + "field_59777": "63VH4ZPD", + "field_59843": null, + "field_59844": null, + "field_59848": null, + "field_59849": null, + "field_59778": [], + "field_59779": null }, { "id": 5, "order": "5.00000000000000000000", "created_on": "2022-11-18T22:48:37.572110+00:00", "updated_on": "2022-11-20T21:14:13.095979+00:00", - "field_705223": null, - "field_705224": [ + "field_59760": null, + "field_59761": [ { - "name": "73avC1A1ljpoppbiQW5hevRta52TT6N2_b8e79c44b179a962f7198bdca3cb1117d3f8cbcdebdf0773d4333efdbcfef05f.jpg", + "name": "sdEY3tiJkXwlGMbHXa1uu68k5jyubjg6_b8e79c44b179a962f7198bdca3cb1117d3f8cbcdebdf0773d4333efdbcfef05f.jpg", "visible_name": "OF.Mitsubishi.MonteroSportGT4WD.WhiteDiamond.jpg", - "original_name": "OF.Mitsubishi.MonteroSportGT4WD.WhiteDiamond.jpg" + "original_name": "sdEY3tiJkXwlGMbHXa1uu68k5jyubjg6_b8e79c44b179a962f7198bdca3cb1117d3f8cbcdebdf0773d4333efdbcfef05f.jpg" } ], - "field_705225": [ + "field_59762": [ 5 ], - "field_725742": null, - "field_725743": "2021", - "field_725744": null, - "field_725745": 313851, - "field_725746": "10", - "field_725747": "White diamond", - "field_725748": "32500.00", - "field_725749": 313860, - "field_725750": [], - "field_725751": "20", - "field_725752": null, - "field_725753": "• Free 17gal fuel\n• Windshield and window tints\n• Reverse parking sensor\n• Toolbox\n• Floor matting", - "field_725755": "MFT1238", - "field_725756": "1Z5HC32N56KLYDLT8", - "field_725757": [ + "field_59840": null, + "field_59841": null, + "field_59763": 21053, + "field_59764": "10", + "field_59765": "White diamond", + "field_59766": "32500", + "field_59867": null, + "field_59767": [], + "field_59768": "20", + "field_59842": null, + "field_59769": "\u2022 Free 17gal fuel\n\u2022 Windshield and window tints\n\u2022 Reverse parking sensor\n\u2022 Toolbox\n\u2022 Floor matting", + "field_59770": "MFT1238", + "field_59771": "1Z5HC32N56KLYDLT8", + "field_59772": [ { - "name": "iQ8EvGq8TSuARN9lajPbnEUQtJq6Y1kM_ac5e07c439066a20b7e755891d10af1c0afd6654e7470ca1129973c94ee60767.jpg", + "name": "psOkzupTYP2Yj5aHa5hAkiEYJ7HU9qum_ac5e07c439066a20b7e755891d10af1c0afd6654e7470ca1129973c94ee60767.jpg", "visible_name": "vehicle_title.jpg", - "original_name": "vehicle_title.jpg" + "original_name": "psOkzupTYP2Yj5aHa5hAkiEYJ7HU9qum_ac5e07c439066a20b7e755891d10af1c0afd6654e7470ca1129973c94ee60767.jpg" } ], - "field_725758": "2020-10-20", - "field_725759": [ + "field_59773": "2020-10-20", + "field_59774": [ 2 ], - "field_725788": [ + "field_59775": [ 4 ], - "field_725869": "Change oil needed.", - "field_725899": null, - "field_735944": null, - "field_738833": "6KLYDLTA", - "field_738895": null, - "field_738896": null + "field_59776": "Change oil needed.", + "field_59866": null, + "field_59777": "6KLYDLTA", + "field_59843": null, + "field_59844": null, + "field_59848": null, + "field_59849": null, + "field_59778": [], + "field_59779": null }, { "id": 6, "order": "6.00000000000000000000", "created_on": "2022-11-18T22:52:27.001935+00:00", "updated_on": "2022-11-20T21:10:20.374004+00:00", - "field_705223": null, - "field_705224": [ + "field_59760": null, + "field_59761": [ { - "name": "DSfnOCUN7dbcsZw0e0quNXanTKeVYHnZ_9fa0480770db0b9339ac594893602f135c9d8e1c36da66079b78df162018b9a5.jpg", + "name": "8FyCOvW5Zp3gFYsMv7WsSjBtRKRlZHaz_9fa0480770db0b9339ac594893602f135c9d8e1c36da66079b78df162018b9a5.jpg", "visible_name": "OF.Mazda.MX-5SoftTopSkyactiv.SoulRedCrystal.jpg", - "original_name": "OF.Mazda.MX-5SoftTopSkyactiv.SoulRedCrystal.jpg" + "original_name": "8FyCOvW5Zp3gFYsMv7WsSjBtRKRlZHaz_9fa0480770db0b9339ac594893602f135c9d8e1c36da66079b78df162018b9a5.jpg" } ], - "field_705225": [ + "field_59762": [ 10 ], - "field_725742": null, - "field_725743": "2020", - "field_725744": null, - "field_725745": 313852, - "field_725746": "25", - "field_725747": "Soul Red Crystal", - "field_725748": "29500.00", - "field_725749": 313859, - "field_725750": [ + "field_59840": null, + "field_59841": null, + "field_59763": 21054, + "field_59764": "25", + "field_59765": "Soul Red Crystal", + "field_59766": "29500", + "field_59867": null, + "field_59767": [ 7 ], - "field_725751": "20", - "field_725752": null, - "field_725753": "• Free 12gal fuel\n• Windshield and window tints\n• Reverse parking sensor\n• Toolbox\n• Floor matting", - "field_725755": "ZDF5379", - "field_725756": "4F4CR16U2X9PLYKFX", - "field_725757": [ + "field_59768": "20", + "field_59842": null, + "field_59769": "\u2022 Free 12gal fuel\n\u2022 Windshield and window tints\n\u2022 Reverse parking sensor\n\u2022 Toolbox\n\u2022 Floor matting", + "field_59770": "ZDF5379", + "field_59771": "4F4CR16U2X9PLYKFX", + "field_59772": [ { - "name": "iQ8EvGq8TSuARN9lajPbnEUQtJq6Y1kM_ac5e07c439066a20b7e755891d10af1c0afd6654e7470ca1129973c94ee60767.jpg", + "name": "psOkzupTYP2Yj5aHa5hAkiEYJ7HU9qum_ac5e07c439066a20b7e755891d10af1c0afd6654e7470ca1129973c94ee60767.jpg", "visible_name": "vehicle_title.jpg", - "original_name": "vehicle_title.jpg" + "original_name": "psOkzupTYP2Yj5aHa5hAkiEYJ7HU9qum_ac5e07c439066a20b7e755891d10af1c0afd6654e7470ca1129973c94ee60767.jpg" } ], - "field_725758": "2020-01-20", - "field_725759": [ + "field_59773": "2020-01-20", + "field_59774": [ 2 ], - "field_725788": [ + "field_59775": [ 1 ], - "field_725869": "", - "field_725899": null, - "field_735944": null, - "field_738833": "X9PLYKFN", - "field_738895": null, - "field_738896": null + "field_59776": "", + "field_59866": null, + "field_59777": "X9PLYKFN", + "field_59843": null, + "field_59844": null, + "field_59848": null, + "field_59849": null, + "field_59778": [ + 4 + ], + "field_59779": null }, { "id": 7, "order": "6.00000000000000000000", "created_on": "2022-11-18T22:52:27.769422+00:00", "updated_on": "2022-11-20T21:13:39.309744+00:00", - "field_705223": null, - "field_705224": [ + "field_59760": null, + "field_59761": [ { - "name": "R6T2tEnhjUAOEpGnqGn8KhhNgOSv7R6y_96a21f78a3d9602fb648e815fd9d7f473470ce7db53ed230207417d7adf098ab.jpg", + "name": "Gm8cp4uTwUQ871rcR8iHJIWiv0wYYUQL_96a21f78a3d9602fb648e815fd9d7f473470ce7db53ed230207417d7adf098ab.jpg", "visible_name": "OF.Mazda.MX-5SoftTopSkyactiv.JetBlack.jpg", - "original_name": "OF.Mazda.MX-5SoftTopSkyactiv.JetBlack.jpg" + "original_name": "Gm8cp4uTwUQ871rcR8iHJIWiv0wYYUQL_96a21f78a3d9602fb648e815fd9d7f473470ce7db53ed230207417d7adf098ab.jpg" } ], - "field_705225": [ + "field_59762": [ 9 ], - "field_725742": null, - "field_725743": "2019", - "field_725744": null, - "field_725745": 313853, - "field_725746": "5250", - "field_725747": "Jet Black", - "field_725748": "20300.00", - "field_725749": 313861, - "field_725750": [], - "field_725751": "15", - "field_725752": null, - "field_725753": "• Free 12gal fuel\n• Windshield and window tints\n• Reverse parking sensor\n• Toolbox\n• Floor matting", - "field_725755": "ZRT3189", - "field_725756": "4F4CR16X1X93DF3GU", - "field_725757": [ + "field_59840": null, + "field_59841": null, + "field_59763": 21055, + "field_59764": "5250", + "field_59765": "Jet Black", + "field_59766": "20300", + "field_59867": null, + "field_59767": [], + "field_59768": "15", + "field_59842": null, + "field_59769": "\u2022 Free 12gal fuel\n\u2022 Windshield and window tints\n\u2022 Reverse parking sensor\n\u2022 Toolbox\n\u2022 Floor matting", + "field_59770": "ZRT3189", + "field_59771": "4F4CR16X1X93DF3GU", + "field_59772": [ { - "name": "iQ8EvGq8TSuARN9lajPbnEUQtJq6Y1kM_ac5e07c439066a20b7e755891d10af1c0afd6654e7470ca1129973c94ee60767.jpg", + "name": "psOkzupTYP2Yj5aHa5hAkiEYJ7HU9qum_ac5e07c439066a20b7e755891d10af1c0afd6654e7470ca1129973c94ee60767.jpg", "visible_name": "vehicle_title.jpg", - "original_name": "vehicle_title.jpg" + "original_name": "psOkzupTYP2Yj5aHa5hAkiEYJ7HU9qum_ac5e07c439066a20b7e755891d10af1c0afd6654e7470ca1129973c94ee60767.jpg" } ], - "field_725758": "2020-01-07", - "field_725759": [ + "field_59773": "2020-01-07", + "field_59774": [ 2 ], - "field_725788": [ + "field_59775": [ 1 ], - "field_725869": "Sent to services for repair.", - "field_725899": null, - "field_735944": null, - "field_738833": "X93DF3GG", - "field_738895": null, - "field_738896": null + "field_59776": "Sent to services for repair.", + "field_59866": null, + "field_59777": "X93DF3GG", + "field_59843": null, + "field_59844": null, + "field_59848": null, + "field_59849": null, + "field_59778": [], + "field_59779": null }, { "id": 8, "order": "7.00000000000000000000", "created_on": "2022-11-18T22:53:33.740108+00:00", "updated_on": "2022-11-20T22:16:18.717521+00:00", - "field_705223": null, - "field_705224": [ + "field_59760": null, + "field_59761": [ { - "name": "VzHVBORgFvmZahMBX1c3PQZA0P1mBxRi_e6952fcc811c73e75a375ed412e7448508f7c3a3299a649c2eb2ee5b417ec154.jpg", + "name": "ZU4unKJk8MIn4bbQ4Q1umxsLPqVYwrG1_e6952fcc811c73e75a375ed412e7448508f7c3a3299a649c2eb2ee5b417ec154.jpg", "visible_name": "OF.Honda.BR-V.ModernSteelMetallic.jpg", - "original_name": "OF.Honda.BR-V.ModernSteelMetallic.jpg" + "original_name": "ZU4unKJk8MIn4bbQ4Q1umxsLPqVYwrG1_e6952fcc811c73e75a375ed412e7448508f7c3a3299a649c2eb2ee5b417ec154.jpg" } ], - "field_705225": [ + "field_59762": [ 7 ], - "field_725742": null, - "field_725743": "2018", - "field_725744": null, - "field_725745": 313851, - "field_725746": "12", - "field_725747": "Modern steel metallic", - "field_725748": "15800.00", - "field_725749": 313859, - "field_725750": [ + "field_59840": null, + "field_59841": null, + "field_59763": 21053, + "field_59764": "12", + "field_59765": "Modern steel metallic", + "field_59766": "15800", + "field_59867": null, + "field_59767": [ 10 ], - "field_725751": "15", - "field_725752": null, - "field_725753": "• Free 10gal fuel\n• Windshield and window tints\n• Reverse parking sensor\n• Toolbox\n• Floor matting", - "field_725755": "NEJ3648", - "field_725756": "3HGCS11319HBC4ER3", - "field_725757": [ + "field_59768": "15", + "field_59842": null, + "field_59769": "\u2022 Free 10gal fuel\n\u2022 Windshield and window tints\n\u2022 Reverse parking sensor\n\u2022 Toolbox\n\u2022 Floor matting", + "field_59770": "NEJ3648", + "field_59771": "3HGCS11319HBC4ER3", + "field_59772": [ { - "name": "iQ8EvGq8TSuARN9lajPbnEUQtJq6Y1kM_ac5e07c439066a20b7e755891d10af1c0afd6654e7470ca1129973c94ee60767.jpg", + "name": "psOkzupTYP2Yj5aHa5hAkiEYJ7HU9qum_ac5e07c439066a20b7e755891d10af1c0afd6654e7470ca1129973c94ee60767.jpg", "visible_name": "vehicle_title.jpg", - "original_name": "vehicle_title.jpg" + "original_name": "psOkzupTYP2Yj5aHa5hAkiEYJ7HU9qum_ac5e07c439066a20b7e755891d10af1c0afd6654e7470ca1129973c94ee60767.jpg" } ], - "field_725758": "2017-10-02", - "field_725759": [ + "field_59773": "2017-10-02", + "field_59774": [ 8 ], - "field_725788": [ + "field_59775": [ 3 ], - "field_725869": "", - "field_725899": null, - "field_735944": null, - "field_738833": "9HBC4ERS", - "field_738895": null, - "field_738896": null + "field_59776": "", + "field_59866": null, + "field_59777": "9HBC4ERS", + "field_59843": null, + "field_59844": null, + "field_59848": null, + "field_59849": null, + "field_59778": [ + 2 + ], + "field_59779": null }, { "id": 9, "order": "8.00000000000000000000", "created_on": "2022-11-18T22:54:37.003714+00:00", "updated_on": "2022-11-20T21:13:22.479302+00:00", - "field_705223": null, - "field_705224": [ + "field_59760": null, + "field_59761": [ { - "name": "xbKMT6tnjPdJQH6A1yTOPHPbK10SfDUY_3509408af0be0e6fb39f8d13c6f4ad127929ca73981f86bc3d71c2733d58f5e5.jpg", + "name": "26BeN3i23mO3lhRLhvZb5VbQLIZvw0DJ_3509408af0be0e6fb39f8d13c6f4ad127929ca73981f86bc3d71c2733d58f5e5.jpg", "visible_name": "OF.Honda.BR-V.PlatinumWhitePearl.jpg", - "original_name": "OF.Honda.BR-V.PlatinumWhitePearl.jpg" + "original_name": "26BeN3i23mO3lhRLhvZb5VbQLIZvw0DJ_3509408af0be0e6fb39f8d13c6f4ad127929ca73981f86bc3d71c2733d58f5e5.jpg" } ], - "field_705225": [ + "field_59762": [ 7 ], - "field_725742": null, - "field_725743": "2019", - "field_725744": null, - "field_725745": 313854, - "field_725746": "12750", - "field_725747": "Platinum White Pearl", - "field_725748": "12700.00", - "field_725749": 313861, - "field_725750": [], - "field_725751": "15", - "field_725752": null, - "field_725753": "• Free 10gal fuel\n• Windshield and window tints\n• Reverse parking sensor\n• Toolbox\n• Floor matting", - "field_725755": "NRA8527", - "field_725756": "3HGCM55806FGG6J1R", - "field_725757": [ + "field_59840": null, + "field_59841": null, + "field_59763": 21056, + "field_59764": "12750", + "field_59765": "Platinum White Pearl", + "field_59766": "12700", + "field_59867": null, + "field_59767": [ + 11, + 23 + ], + "field_59768": "15", + "field_59842": null, + "field_59769": "\u2022 Free 10gal fuel\n\u2022 Windshield and window tints\n\u2022 Reverse parking sensor\n\u2022 Toolbox\n\u2022 Floor matting", + "field_59770": "NRA8527", + "field_59771": "3HGCM55806FGG6J1R", + "field_59772": [ { - "name": "iQ8EvGq8TSuARN9lajPbnEUQtJq6Y1kM_ac5e07c439066a20b7e755891d10af1c0afd6654e7470ca1129973c94ee60767.jpg", + "name": "psOkzupTYP2Yj5aHa5hAkiEYJ7HU9qum_ac5e07c439066a20b7e755891d10af1c0afd6654e7470ca1129973c94ee60767.jpg", "visible_name": "vehicle_title.jpg", - "original_name": "vehicle_title.jpg" + "original_name": "psOkzupTYP2Yj5aHa5hAkiEYJ7HU9qum_ac5e07c439066a20b7e755891d10af1c0afd6654e7470ca1129973c94ee60767.jpg" } ], - "field_725758": "2020-10-08", - "field_725759": [ + "field_59773": "2020-10-08", + "field_59774": [ 1 ], - "field_725788": [ + "field_59775": [ 2 ], - "field_725869": "Sent to services for repair.", - "field_725899": null, - "field_735944": null, - "field_738833": "6FGG6J1I", - "field_738895": null, - "field_738896": null + "field_59776": "Sent to services for repair.", + "field_59866": null, + "field_59777": "6FGG6J1I", + "field_59843": null, + "field_59844": null, + "field_59848": null, + "field_59849": null, + "field_59778": [], + "field_59779": null }, { "id": 10, "order": "9.00000000000000000000", "created_on": "2022-11-18T22:54:39.602401+00:00", "updated_on": "2022-11-20T21:12:47.674320+00:00", - "field_705223": null, - "field_705224": [ + "field_59760": null, + "field_59761": [ { - "name": "7PGWn5D6yjFapuhDqBkI48G9GmI2B3Mu_1f98fb5ba9b5521e045bb3dff6763a24c8002611f55f74de908c86e39cd92b41.jpg", + "name": "UL8Lg48VaTRKngk6HwE1SpEIT1RUPLKL_1f98fb5ba9b5521e045bb3dff6763a24c8002611f55f74de908c86e39cd92b41.jpg", "visible_name": "OF.Honda.BR-V.PassionRedPearl.jpg", - "original_name": "OF.Honda.BR-V.PassionRedPearl.jpg" + "original_name": "UL8Lg48VaTRKngk6HwE1SpEIT1RUPLKL_1f98fb5ba9b5521e045bb3dff6763a24c8002611f55f74de908c86e39cd92b41.jpg" } ], - "field_705225": [ + "field_59762": [ 8 ], - "field_725742": null, - "field_725743": "2022", - "field_725744": null, - "field_725745": 313850, - "field_725746": "3", - "field_725747": "Passion Red Pearl", - "field_725748": "18000.00", - "field_725749": 313856, - "field_725750": [], - "field_725751": "20", - "field_725752": null, - "field_725753": "• Free 10gal fuel\n• Windshield and window tints\n• Reverse parking sensor\n• Toolbox\n• Floor matting", - "field_725755": "NYC1327", - "field_725756": "3HGCG665821P989FA", - "field_725757": [ + "field_59840": null, + "field_59841": null, + "field_59763": 21052, + "field_59764": "3", + "field_59765": "Passion Red Pearl", + "field_59766": "18000", + "field_59867": null, + "field_59767": [ + 21 + ], + "field_59768": "20", + "field_59842": null, + "field_59769": "\u2022 Free 10gal fuel\n\u2022 Windshield and window tints\n\u2022 Reverse parking sensor\n\u2022 Toolbox\n\u2022 Floor matting", + "field_59770": "NYC1327", + "field_59771": "3HGCG665821P989FA", + "field_59772": [ { - "name": "iQ8EvGq8TSuARN9lajPbnEUQtJq6Y1kM_ac5e07c439066a20b7e755891d10af1c0afd6654e7470ca1129973c94ee60767.jpg", + "name": "psOkzupTYP2Yj5aHa5hAkiEYJ7HU9qum_ac5e07c439066a20b7e755891d10af1c0afd6654e7470ca1129973c94ee60767.jpg", "visible_name": "vehicle_title.jpg", - "original_name": "vehicle_title.jpg" + "original_name": "psOkzupTYP2Yj5aHa5hAkiEYJ7HU9qum_ac5e07c439066a20b7e755891d10af1c0afd6654e7470ca1129973c94ee60767.jpg" } ], - "field_725758": "2021-09-20", - "field_725759": [ + "field_59773": "2021-09-20", + "field_59774": [ 8 ], - "field_725788": [ + "field_59775": [ 3 ], - "field_725869": "Processing all legal documents.", - "field_725899": null, - "field_735944": null, - "field_738833": "21P989FO", - "field_738895": null, - "field_738896": null + "field_59776": "Processing all legal documents.", + "field_59866": null, + "field_59777": "21P989FO", + "field_59843": null, + "field_59844": null, + "field_59848": null, + "field_59849": null, + "field_59778": [], + "field_59779": null }, { "id": 11, "order": "10.00000000000000000000", "created_on": "2022-11-18T23:04:06.469639+00:00", "updated_on": "2022-11-20T21:11:38.322560+00:00", - "field_705223": null, - "field_705224": [ + "field_59760": null, + "field_59761": [ { - "name": "uXqRHyzvaFH4t9Q3mBeuQUcRQj9zhaTH_416272739769f05c232bd5bd575f893bf0f90c42b710f9efb3e70506aba0d608.jpg", + "name": "95hTork4gDiyLZm15nlXNedJwU5Doswz_416272739769f05c232bd5bd575f893bf0f90c42b710f9efb3e70506aba0d608.jpg", "visible_name": "OR.Toyota.WigoVVT-iG.Black2.jpg", - "original_name": "OR.Toyota.WigoVVT-iG.Black2.jpg" + "original_name": "95hTork4gDiyLZm15nlXNedJwU5Doswz_416272739769f05c232bd5bd575f893bf0f90c42b710f9efb3e70506aba0d608.jpg" } ], - "field_705225": [ + "field_59762": [ 4 ], - "field_725742": null, - "field_725743": "2022", - "field_725744": null, - "field_725745": 313850, - "field_725746": "3", - "field_725747": "Black 2", - "field_725748": "8875.00", - "field_725749": 313859, - "field_725750": [ + "field_59840": null, + "field_59841": null, + "field_59763": 21052, + "field_59764": "3", + "field_59765": "Black 2", + "field_59766": "8875", + "field_59867": null, + "field_59767": [ 2 ], - "field_725751": "20", - "field_725752": null, - "field_725753": "• Free 8gal fuel\n• Windshield and window tints\n• Reverse parking sensor\n• Toolbox\n• Floor matting", - "field_725755": "GFA9873", - "field_725756": "3TMLU4EN2AA13VSBJ", - "field_725757": [ + "field_59768": "20", + "field_59842": null, + "field_59769": "\u2022 Free 8gal fuel\n\u2022 Windshield and window tints\n\u2022 Reverse parking sensor\n\u2022 Toolbox\n\u2022 Floor matting", + "field_59770": "GFA9873", + "field_59771": "3TMLU4EN2AA13VSBJ", + "field_59772": [ { - "name": "iQ8EvGq8TSuARN9lajPbnEUQtJq6Y1kM_ac5e07c439066a20b7e755891d10af1c0afd6654e7470ca1129973c94ee60767.jpg", + "name": "psOkzupTYP2Yj5aHa5hAkiEYJ7HU9qum_ac5e07c439066a20b7e755891d10af1c0afd6654e7470ca1129973c94ee60767.jpg", "visible_name": "vehicle_title.jpg", - "original_name": "vehicle_title.jpg" + "original_name": "psOkzupTYP2Yj5aHa5hAkiEYJ7HU9qum_ac5e07c439066a20b7e755891d10af1c0afd6654e7470ca1129973c94ee60767.jpg" } ], - "field_725758": "2021-12-20", - "field_725759": [ + "field_59773": "2021-12-20", + "field_59774": [ 2 ], - "field_725788": [ + "field_59775": [ 4 ], - "field_725869": "", - "field_725899": null, - "field_735944": null, - "field_738833": "AA13VSBC", - "field_738895": null, - "field_738896": null + "field_59776": "", + "field_59866": null, + "field_59777": "AA13VSBC", + "field_59843": null, + "field_59844": null, + "field_59848": null, + "field_59849": null, + "field_59778": [ + 3 + ], + "field_59779": null }, { "id": 12, "order": "10.00000000000000000000", "created_on": "2022-11-18T23:04:07.475187+00:00", "updated_on": "2022-11-20T21:11:27.582360+00:00", - "field_705223": null, - "field_705224": [ + "field_59760": null, + "field_59761": [ { - "name": "xHpyJHGqizIpRASAKXgChj4LErW2Svey_63f36d7642b0bfd77deb4acf9367fbe872108200ed2fb3aa992a8ff903b62b9b.jpg", + "name": "HrG6VULsdnXkJlFjLdn86VOCcfTSZAsB_63f36d7642b0bfd77deb4acf9367fbe872108200ed2fb3aa992a8ff903b62b9b.jpg", "visible_name": "OR.Toyota.WigoVVT-iG.SilverMetallic4.jpg", - "original_name": "OR.Toyota.WigoVVT-iG.SilverMetallic4.jpg" + "original_name": "HrG6VULsdnXkJlFjLdn86VOCcfTSZAsB_63f36d7642b0bfd77deb4acf9367fbe872108200ed2fb3aa992a8ff903b62b9b.jpg" } ], - "field_705225": [ + "field_59762": [ 4 ], - "field_725742": null, - "field_725743": "2022", - "field_725744": null, - "field_725745": 313850, - "field_725746": "3", - "field_725747": "Gray Metallic", - "field_725748": "8875.00", - "field_725749": 313856, - "field_725750": [], - "field_725751": "20", - "field_725752": null, - "field_725753": "• Free 8gal fuel\n• Windshield and window tints\n• Reverse parking sensor\n• Toolbox\n• Floor matting", - "field_725755": "GDY1379", - "field_725756": "3TMPX4EN0AX2J7LH7", - "field_725757": [ + "field_59840": null, + "field_59841": null, + "field_59763": 21052, + "field_59764": "3", + "field_59765": "Gray Metallic", + "field_59766": "8875", + "field_59867": null, + "field_59767": [], + "field_59768": "20", + "field_59842": null, + "field_59769": "\u2022 Free 8gal fuel\n\u2022 Windshield and window tints\n\u2022 Reverse parking sensor\n\u2022 Toolbox\n\u2022 Floor matting", + "field_59770": "GDY1379", + "field_59771": "3TMPX4EN0AX2J7LH7", + "field_59772": [ { - "name": "iQ8EvGq8TSuARN9lajPbnEUQtJq6Y1kM_ac5e07c439066a20b7e755891d10af1c0afd6654e7470ca1129973c94ee60767.jpg", + "name": "psOkzupTYP2Yj5aHa5hAkiEYJ7HU9qum_ac5e07c439066a20b7e755891d10af1c0afd6654e7470ca1129973c94ee60767.jpg", "visible_name": "vehicle_title.jpg", - "original_name": "vehicle_title.jpg" + "original_name": "psOkzupTYP2Yj5aHa5hAkiEYJ7HU9qum_ac5e07c439066a20b7e755891d10af1c0afd6654e7470ca1129973c94ee60767.jpg" } ], - "field_725758": "2021-12-20", - "field_725759": [ + "field_59773": "2021-12-20", + "field_59774": [ 8 ], - "field_725788": [ + "field_59775": [ 3 ], - "field_725869": "", - "field_725899": null, - "field_735944": null, - "field_738833": "AX2J7LHO", - "field_738895": null, - "field_738896": null + "field_59776": "", + "field_59866": null, + "field_59777": "AX2J7LHO", + "field_59843": null, + "field_59844": null, + "field_59848": null, + "field_59849": null, + "field_59778": [], + "field_59779": null }, { "id": 13, "order": "10.00000000000000000000", "created_on": "2022-11-18T23:04:07.844473+00:00", "updated_on": "2022-11-20T21:14:22.426990+00:00", - "field_705223": null, - "field_705224": [ + "field_59760": null, + "field_59761": [ { - "name": "O73ow7PUMqnfI4Zcdn7cUzyUSxxR5o02_3072cfa8b9dfa6da36e18f9bb0d055e7402626e993a54d81108c45b89b7bc21f.jpg", + "name": "NJ7uazUU9813pWbJ7C4H7lRrH4HZ8mno_3072cfa8b9dfa6da36e18f9bb0d055e7402626e993a54d81108c45b89b7bc21f.jpg", "visible_name": "OR.Toyota.WigoVVT-iG.White2.jpg", - "original_name": "OR.Toyota.WigoVVT-iG.White2.jpg" + "original_name": "NJ7uazUU9813pWbJ7C4H7lRrH4HZ8mno_3072cfa8b9dfa6da36e18f9bb0d055e7402626e993a54d81108c45b89b7bc21f.jpg" } ], - "field_705225": [ + "field_59762": [ 4 ], - "field_725742": null, - "field_725743": "2021", - "field_725744": null, - "field_725745": 313851, - "field_725746": "5", - "field_725747": "Silver Metallic 4", - "field_725748": "8875.00", - "field_725749": 313860, - "field_725750": [], - "field_725751": "15", - "field_725752": null, - "field_725753": "• Free 8gal fuel\n• Windshield and window tints\n• Reverse parking sensor\n• Toolbox\n• Floor matting", - "field_725755": "GPS9382", - "field_725756": "3TMNX22N39D8Z571K", - "field_725757": [ + "field_59840": null, + "field_59841": null, + "field_59763": 21053, + "field_59764": "5", + "field_59765": "Silver Metallic 4", + "field_59766": "8875", + "field_59867": null, + "field_59767": [], + "field_59768": "15", + "field_59842": null, + "field_59769": "\u2022 Free 8gal fuel\n\u2022 Windshield and window tints\n\u2022 Reverse parking sensor\n\u2022 Toolbox\n\u2022 Floor matting", + "field_59770": "GPS9382", + "field_59771": "3TMNX22N39D8Z571K", + "field_59772": [ { - "name": "iQ8EvGq8TSuARN9lajPbnEUQtJq6Y1kM_ac5e07c439066a20b7e755891d10af1c0afd6654e7470ca1129973c94ee60767.jpg", + "name": "psOkzupTYP2Yj5aHa5hAkiEYJ7HU9qum_ac5e07c439066a20b7e755891d10af1c0afd6654e7470ca1129973c94ee60767.jpg", "visible_name": "vehicle_title.jpg", - "original_name": "vehicle_title.jpg" + "original_name": "psOkzupTYP2Yj5aHa5hAkiEYJ7HU9qum_ac5e07c439066a20b7e755891d10af1c0afd6654e7470ca1129973c94ee60767.jpg" } ], - "field_725758": "2021-01-18", - "field_725759": [ + "field_59773": "2021-01-18", + "field_59774": [ 2 ], - "field_725788": [ + "field_59775": [ 1 ], - "field_725869": "Change oil needed.", - "field_725899": null, - "field_735944": null, - "field_738833": "9D8Z571J", - "field_738895": null, - "field_738896": null + "field_59776": "Change oil needed.", + "field_59866": null, + "field_59777": "9D8Z571J", + "field_59843": null, + "field_59844": null, + "field_59848": null, + "field_59849": null, + "field_59778": [], + "field_59779": null }, { "id": 14, "order": "11.00000000000000000000", "created_on": "2022-11-18T23:04:09.560737+00:00", "updated_on": "2022-11-20T21:11:01.709749+00:00", - "field_705223": null, - "field_705224": [ + "field_59760": null, + "field_59761": [ { - "name": "FNg5CWDEU5HephXfKsa6Sgsq8un1HHq7_83c1c9ea24a831b394e8896e6d4e9aa6cdf631cc354249fba4a8f0967f0fd96c.jpg", + "name": "XrSMeNrKyButLKfhoBY2ArxNAaslkn0b_83c1c9ea24a831b394e8896e6d4e9aa6cdf631cc354249fba4a8f0967f0fd96c.jpg", "visible_name": "OR.Toyota.WigoVVT-iG.OrangeMetallic2.jpg", - "original_name": "OR.Toyota.WigoVVT-iG.OrangeMetallic2.jpg" + "original_name": "XrSMeNrKyButLKfhoBY2ArxNAaslkn0b_83c1c9ea24a831b394e8896e6d4e9aa6cdf631cc354249fba4a8f0967f0fd96c.jpg" } ], - "field_705225": [ + "field_59762": [ 4 ], - "field_725742": null, - "field_725743": "2021", - "field_725744": null, - "field_725745": 313851, - "field_725746": "5", - "field_725747": "White 2", - "field_725748": "8875.00", - "field_725749": 313859, - "field_725750": [ + "field_59840": null, + "field_59841": null, + "field_59763": 21053, + "field_59764": "5", + "field_59765": "White 2", + "field_59766": "8875", + "field_59867": null, + "field_59767": [ 1 ], - "field_725751": "15", - "field_725752": null, - "field_725753": "• Free 8gal fuel\n• Windshield and window tints\n• Reverse parking sensor\n• Toolbox\n• Floor matting", - "field_725755": "GSP7913", - "field_725756": "3TMTX4GN7AXAL1AZF", - "field_725757": [ + "field_59768": "15", + "field_59842": null, + "field_59769": "\u2022 Free 8gal fuel\n\u2022 Windshield and window tints\n\u2022 Reverse parking sensor\n\u2022 Toolbox\n\u2022 Floor matting", + "field_59770": "GSP7913", + "field_59771": "3TMTX4GN7AXAL1AZF", + "field_59772": [ { - "name": "iQ8EvGq8TSuARN9lajPbnEUQtJq6Y1kM_ac5e07c439066a20b7e755891d10af1c0afd6654e7470ca1129973c94ee60767.jpg", + "name": "psOkzupTYP2Yj5aHa5hAkiEYJ7HU9qum_ac5e07c439066a20b7e755891d10af1c0afd6654e7470ca1129973c94ee60767.jpg", "visible_name": "vehicle_title.jpg", - "original_name": "vehicle_title.jpg" + "original_name": "psOkzupTYP2Yj5aHa5hAkiEYJ7HU9qum_ac5e07c439066a20b7e755891d10af1c0afd6654e7470ca1129973c94ee60767.jpg" } ], - "field_725758": "2021-01-18", - "field_725759": [ + "field_59773": "2021-01-18", + "field_59774": [ 1 ], - "field_725788": [ + "field_59775": [ 2 ], - "field_725869": "", - "field_725899": null, - "field_735944": null, - "field_738833": "AXAL1AZO", - "field_738895": null, - "field_738896": null + "field_59776": "", + "field_59866": null, + "field_59777": "AXAL1AZO", + "field_59843": null, + "field_59844": null, + "field_59848": null, + "field_59849": null, + "field_59778": [], + "field_59779": null }, { "id": 15, "order": "11.00000000000000000000", "created_on": "2022-11-18T23:04:10.478581+00:00", "updated_on": "2022-11-20T21:10:24.786516+00:00", - "field_705223": null, - "field_705224": [ + "field_59760": null, + "field_59761": [ { - "name": "eW44aN5s5nIrhuF0FKEpxTikA6kmE8CL_7a70b47b0aa81e772793e54049644af87248d790c3f2ed9ecbb05e00fc141c0c.jpg", + "name": "t8Ew7WaITzVp8a7VdWT8ftg5r5rbVQWg_7a70b47b0aa81e772793e54049644af87248d790c3f2ed9ecbb05e00fc141c0c.jpg", "visible_name": "OR.Toyota.WigoVVT-iG.YellowSE.jpg", - "original_name": "OR.Toyota.WigoVVT-iG.YellowSE.jpg" + "original_name": "t8Ew7WaITzVp8a7VdWT8ftg5r5rbVQWg_7a70b47b0aa81e772793e54049644af87248d790c3f2ed9ecbb05e00fc141c0c.jpg" } ], - "field_705225": [ + "field_59762": [ 3 ], - "field_725742": null, - "field_725743": "2022", - "field_725744": null, - "field_725745": 313850, - "field_725746": "2", - "field_725747": "Orange Metallic 2", - "field_725748": "9800.00", - "field_725749": 313859, - "field_725750": [ + "field_59840": null, + "field_59841": null, + "field_59763": 21052, + "field_59764": "2", + "field_59765": "Orange Metallic 2", + "field_59766": "9800", + "field_59867": null, + "field_59767": [ 4 ], - "field_725751": "20", - "field_725752": null, - "field_725753": "• Free 8gal fuel\n• Windshield and window tints\n• Reverse parking sensor\n• Toolbox\n• Floor matting", - "field_725755": "GDT7193", - "field_725756": "3TMUU42NX81P12KEF", - "field_725757": [ + "field_59768": "20", + "field_59842": null, + "field_59769": "\u2022 Free 8gal fuel\n\u2022 Windshield and window tints\n\u2022 Reverse parking sensor\n\u2022 Toolbox\n\u2022 Floor matting", + "field_59770": "GDT7193", + "field_59771": "3TMUU42NX81P12KEF", + "field_59772": [ { - "name": "iQ8EvGq8TSuARN9lajPbnEUQtJq6Y1kM_ac5e07c439066a20b7e755891d10af1c0afd6654e7470ca1129973c94ee60767.jpg", + "name": "psOkzupTYP2Yj5aHa5hAkiEYJ7HU9qum_ac5e07c439066a20b7e755891d10af1c0afd6654e7470ca1129973c94ee60767.jpg", "visible_name": "vehicle_title.jpg", - "original_name": "vehicle_title.jpg" + "original_name": "psOkzupTYP2Yj5aHa5hAkiEYJ7HU9qum_ac5e07c439066a20b7e755891d10af1c0afd6654e7470ca1129973c94ee60767.jpg" } ], - "field_725758": "2021-12-20", - "field_725759": [ + "field_59773": "2021-12-20", + "field_59774": [ 2 ], - "field_725788": [ + "field_59775": [ 1 ], - "field_725869": "", - "field_725899": null, - "field_735944": null, - "field_738833": "81P12KEE", - "field_738895": null, - "field_738896": null + "field_59776": "", + "field_59866": null, + "field_59777": "81P12KEE", + "field_59843": null, + "field_59844": null, + "field_59848": null, + "field_59849": null, + "field_59778": [ + 1 + ], + "field_59779": null }, { "id": 16, "order": "12.00000000000000000000", "created_on": "2022-11-18T23:04:51.276579+00:00", "updated_on": "2022-11-20T21:10:59.868612+00:00", - "field_705223": null, - "field_705224": [ + "field_59760": null, + "field_59761": [ { - "name": "jJYTVX8QsxbWPuSTaAUoTdFK2bwhWElY_bad5b3b8af588575c92711c5280a024a42336f92556209dc60ff6dc58d884ffd.jpg", + "name": "3WmtMOSrBq0onRbJLcNCXs4hGJ32ydja_bad5b3b8af588575c92711c5280a024a42336f92556209dc60ff6dc58d884ffd.jpg", "visible_name": "OF.Honda.BR-V.LunarSilverMetallic.jpg", - "original_name": "OF.Honda.BR-V.LunarSilverMetallic.jpg" + "original_name": "3WmtMOSrBq0onRbJLcNCXs4hGJ32ydja_bad5b3b8af588575c92711c5280a024a42336f92556209dc60ff6dc58d884ffd.jpg" } ], - "field_705225": [ + "field_59762": [ 3 ], - "field_725742": null, - "field_725743": "2022", - "field_725744": null, - "field_725745": 313850, - "field_725746": "2", - "field_725747": "Yellow SE", - "field_725748": "9800.00", - "field_725749": 313859, - "field_725750": [ - 3 + "field_59840": null, + "field_59841": null, + "field_59763": 21052, + "field_59764": "2", + "field_59765": "Yellow SE", + "field_59766": "9800", + "field_59867": null, + "field_59767": [ + 3, + 13, + 14 ], - "field_725751": "20", - "field_725752": null, - "field_725753": "• Free 8gal fuel\n• Windshield and window tints\n• Reverse parking sensor\n• Toolbox\n• Floor matting", - "field_725755": "GSE2817", - "field_725756": "3TMJX4GN5BXDZZ7GL", - "field_725757": [ + "field_59768": "20", + "field_59842": null, + "field_59769": "\u2022 Free 8gal fuel\n\u2022 Windshield and window tints\n\u2022 Reverse parking sensor\n\u2022 Toolbox\n\u2022 Floor matting", + "field_59770": "GSE2817", + "field_59771": "3TMJX4GN5BXDZZ7GL", + "field_59772": [ { - "name": "iQ8EvGq8TSuARN9lajPbnEUQtJq6Y1kM_ac5e07c439066a20b7e755891d10af1c0afd6654e7470ca1129973c94ee60767.jpg", + "name": "psOkzupTYP2Yj5aHa5hAkiEYJ7HU9qum_ac5e07c439066a20b7e755891d10af1c0afd6654e7470ca1129973c94ee60767.jpg", "visible_name": "vehicle_title.jpg", - "original_name": "vehicle_title.jpg" + "original_name": "psOkzupTYP2Yj5aHa5hAkiEYJ7HU9qum_ac5e07c439066a20b7e755891d10af1c0afd6654e7470ca1129973c94ee60767.jpg" } ], - "field_725758": "2021-12-20", - "field_725759": [ + "field_59773": "2021-12-20", + "field_59774": [ 1 ], - "field_725788": [ + "field_59775": [ 2 ], - "field_725869": "", - "field_725899": null, - "field_735944": null, - "field_738833": "BXDZZ7GD", - "field_738895": null, - "field_738896": null + "field_59776": "", + "field_59866": null, + "field_59777": "BXDZZ7GD", + "field_59843": null, + "field_59844": null, + "field_59848": null, + "field_59849": null, + "field_59778": [ + 5 + ], + "field_59779": null }, { "id": 17, "order": "13.00000000000000000000", "created_on": "2022-11-18T23:09:27.791689+00:00", "updated_on": "2022-11-20T21:12:41.075636+00:00", - "field_705223": null, - "field_705224": [ + "field_59760": null, + "field_59761": [ { - "name": "jJYTVX8QsxbWPuSTaAUoTdFK2bwhWElY_bad5b3b8af588575c92711c5280a024a42336f92556209dc60ff6dc58d884ffd.jpg", + "name": "3WmtMOSrBq0onRbJLcNCXs4hGJ32ydja_bad5b3b8af588575c92711c5280a024a42336f92556209dc60ff6dc58d884ffd.jpg", "visible_name": "OF.Honda.BR-V.LunarSilverMetallic.jpg", - "original_name": "OF.Honda.BR-V.LunarSilverMetallic.jpg" + "original_name": "3WmtMOSrBq0onRbJLcNCXs4hGJ32ydja_bad5b3b8af588575c92711c5280a024a42336f92556209dc60ff6dc58d884ffd.jpg" } ], - "field_705225": [ + "field_59762": [ 7 ], - "field_725742": null, - "field_725743": "2022", - "field_725744": null, - "field_725745": 313850, - "field_725746": "2", - "field_725747": "Lunar Silver Metallic", - "field_725748": "15900.00", - "field_725749": 313856, - "field_725750": [], - "field_725751": "20", - "field_725752": null, - "field_725753": "• Free 10gal fuel\n• Windshield and window tints\n• Reverse parking sensor\n• Toolbox\n• Floor matting", - "field_725755": "NAD7182", - "field_725756": "5FNRL18963D5XMPMH", - "field_725757": [ + "field_59840": null, + "field_59841": null, + "field_59763": 21052, + "field_59764": "2", + "field_59765": "Lunar Silver Metallic", + "field_59766": "15900", + "field_59867": null, + "field_59767": [ + 22 + ], + "field_59768": "20", + "field_59842": null, + "field_59769": "\u2022 Free 10gal fuel\n\u2022 Windshield and window tints\n\u2022 Reverse parking sensor\n\u2022 Toolbox\n\u2022 Floor matting", + "field_59770": "NAD7182", + "field_59771": "5FNRL18963D5XMPMH", + "field_59772": [ { - "name": "iQ8EvGq8TSuARN9lajPbnEUQtJq6Y1kM_ac5e07c439066a20b7e755891d10af1c0afd6654e7470ca1129973c94ee60767.jpg", + "name": "psOkzupTYP2Yj5aHa5hAkiEYJ7HU9qum_ac5e07c439066a20b7e755891d10af1c0afd6654e7470ca1129973c94ee60767.jpg", "visible_name": "vehicle_title.jpg", - "original_name": "vehicle_title.jpg" + "original_name": "psOkzupTYP2Yj5aHa5hAkiEYJ7HU9qum_ac5e07c439066a20b7e755891d10af1c0afd6654e7470ca1129973c94ee60767.jpg" } ], - "field_725758": "2021-12-27", - "field_725759": [ + "field_59773": "2021-12-27", + "field_59774": [ 2 ], - "field_725788": [ + "field_59775": [ 1 ], - "field_725869": "Processing all legal documents.", - "field_725899": null, - "field_735944": null, - "field_738833": "3D5XMPMA", - "field_738895": null, - "field_738896": null + "field_59776": "Processing all legal documents.", + "field_59866": null, + "field_59777": "3D5XMPMA", + "field_59843": null, + "field_59844": null, + "field_59848": null, + "field_59849": null, + "field_59778": [], + "field_59779": null }, { "id": 18, "order": "14.00000000000000000000", "created_on": "2022-11-18T23:09:30.074918+00:00", "updated_on": "2022-11-20T21:12:44.999252+00:00", - "field_705223": null, - "field_705224": [ + "field_59760": null, + "field_59761": [ { - "name": "jJYTVX8QsxbWPuSTaAUoTdFK2bwhWElY_bad5b3b8af588575c92711c5280a024a42336f92556209dc60ff6dc58d884ffd.jpg", + "name": "3WmtMOSrBq0onRbJLcNCXs4hGJ32ydja_bad5b3b8af588575c92711c5280a024a42336f92556209dc60ff6dc58d884ffd.jpg", "visible_name": "OF.Honda.BR-V.LunarSilverMetallic.jpg", - "original_name": "OF.Honda.BR-V.LunarSilverMetallic.jpg" + "original_name": "3WmtMOSrBq0onRbJLcNCXs4hGJ32ydja_bad5b3b8af588575c92711c5280a024a42336f92556209dc60ff6dc58d884ffd.jpg" } ], - "field_705225": [ + "field_59762": [ 7 ], - "field_725742": null, - "field_725743": "2022", - "field_725744": null, - "field_725745": 313850, - "field_725746": "2", - "field_725747": "Lunar Silver Metallic", - "field_725748": "15900.00", - "field_725749": 313856, - "field_725750": [], - "field_725751": "20", - "field_725752": null, - "field_725753": "• Free 10gal fuel\n• Windshield and window tints\n• Reverse parking sensor\n• Toolbox\n• Floor matting", - "field_725755": "NHS9382", - "field_725756": "5FNRL3H54A8T25TZD", - "field_725757": [ + "field_59840": null, + "field_59841": null, + "field_59763": 21052, + "field_59764": "2", + "field_59765": "Lunar Silver Metallic", + "field_59766": "15900", + "field_59867": null, + "field_59767": [ + 12 + ], + "field_59768": "20", + "field_59842": null, + "field_59769": "\u2022 Free 10gal fuel\n\u2022 Windshield and window tints\n\u2022 Reverse parking sensor\n\u2022 Toolbox\n\u2022 Floor matting", + "field_59770": "NHS9382", + "field_59771": "5FNRL3H54A8T25TZD", + "field_59772": [ { - "name": "iQ8EvGq8TSuARN9lajPbnEUQtJq6Y1kM_ac5e07c439066a20b7e755891d10af1c0afd6654e7470ca1129973c94ee60767.jpg", + "name": "psOkzupTYP2Yj5aHa5hAkiEYJ7HU9qum_ac5e07c439066a20b7e755891d10af1c0afd6654e7470ca1129973c94ee60767.jpg", "visible_name": "vehicle_title.jpg", - "original_name": "vehicle_title.jpg" + "original_name": "psOkzupTYP2Yj5aHa5hAkiEYJ7HU9qum_ac5e07c439066a20b7e755891d10af1c0afd6654e7470ca1129973c94ee60767.jpg" } ], - "field_725758": "2021-12-27", - "field_725759": [ + "field_59773": "2021-12-27", + "field_59774": [ 2 ], - "field_725788": [ + "field_59775": [ 1 ], - "field_725869": "Processing all legal documents.", - "field_725899": null, - "field_735944": null, - "field_738833": "A8T25TZN", - "field_738895": null, - "field_738896": null + "field_59776": "Processing all legal documents.", + "field_59866": null, + "field_59777": "A8T25TZN", + "field_59843": null, + "field_59844": null, + "field_59848": null, + "field_59849": null, + "field_59778": [], + "field_59779": null }, { "id": 19, "order": "15.00000000000000000000", "created_on": "2022-11-18T23:09:31.538085+00:00", "updated_on": "2022-11-20T21:10:18.534745+00:00", - "field_705223": null, - "field_705224": [ + "field_59760": null, + "field_59761": [ { - "name": "7PGWn5D6yjFapuhDqBkI48G9GmI2B3Mu_1f98fb5ba9b5521e045bb3dff6763a24c8002611f55f74de908c86e39cd92b41.jpg", + "name": "UL8Lg48VaTRKngk6HwE1SpEIT1RUPLKL_1f98fb5ba9b5521e045bb3dff6763a24c8002611f55f74de908c86e39cd92b41.jpg", "visible_name": "OF.Honda.BR-V.PassionRedPearl.jpg", - "original_name": "OF.Honda.BR-V.PassionRedPearl.jpg" + "original_name": "UL8Lg48VaTRKngk6HwE1SpEIT1RUPLKL_1f98fb5ba9b5521e045bb3dff6763a24c8002611f55f74de908c86e39cd92b41.jpg" } ], - "field_705225": [ + "field_59762": [ 7 ], - "field_725742": null, - "field_725743": "2022", - "field_725744": null, - "field_725745": 313850, - "field_725746": "3", - "field_725747": "Passion Red Pearl", - "field_725748": "15900.00", - "field_725749": 313856, - "field_725750": [], - "field_725751": "20", - "field_725752": null, - "field_725753": "• Free 10gal fuel\n• Windshield and window tints\n• Reverse parking sensor\n• Toolbox\n• Floor matting", - "field_725755": "NKL8271", - "field_725756": "5FNYF488495LXXAHW", - "field_725757": [ + "field_59840": null, + "field_59841": null, + "field_59763": 21052, + "field_59764": "3", + "field_59765": "Passion Red Pearl", + "field_59766": "15900", + "field_59867": null, + "field_59767": [], + "field_59768": "20", + "field_59842": null, + "field_59769": "\u2022 Free 10gal fuel\n\u2022 Windshield and window tints\n\u2022 Reverse parking sensor\n\u2022 Toolbox\n\u2022 Floor matting", + "field_59770": "NKL8271", + "field_59771": "5FNYF488495LXXAHW", + "field_59772": [ { - "name": "iQ8EvGq8TSuARN9lajPbnEUQtJq6Y1kM_ac5e07c439066a20b7e755891d10af1c0afd6654e7470ca1129973c94ee60767.jpg", + "name": "psOkzupTYP2Yj5aHa5hAkiEYJ7HU9qum_ac5e07c439066a20b7e755891d10af1c0afd6654e7470ca1129973c94ee60767.jpg", "visible_name": "vehicle_title.jpg", - "original_name": "vehicle_title.jpg" + "original_name": "psOkzupTYP2Yj5aHa5hAkiEYJ7HU9qum_ac5e07c439066a20b7e755891d10af1c0afd6654e7470ca1129973c94ee60767.jpg" } ], - "field_725758": "2021-12-27", - "field_725759": [ + "field_59773": "2021-12-27", + "field_59774": [ 2 ], - "field_725788": [ + "field_59775": [ 1 ], - "field_725869": "", - "field_725899": null, - "field_735944": null, - "field_738833": "95LXXAHG", - "field_738895": null, - "field_738896": null + "field_59776": "", + "field_59866": null, + "field_59777": "95LXXAHG", + "field_59843": null, + "field_59844": null, + "field_59848": null, + "field_59849": null, + "field_59778": [], + "field_59779": null }, { "id": 20, "order": "16.00000000000000000000", "created_on": "2022-11-18T23:09:34.030488+00:00", "updated_on": "2022-11-20T21:14:03.723118+00:00", - "field_705223": null, - "field_705224": [ + "field_59760": null, + "field_59761": [ { - "name": "xbKMT6tnjPdJQH6A1yTOPHPbK10SfDUY_3509408af0be0e6fb39f8d13c6f4ad127929ca73981f86bc3d71c2733d58f5e5.jpg", + "name": "26BeN3i23mO3lhRLhvZb5VbQLIZvw0DJ_3509408af0be0e6fb39f8d13c6f4ad127929ca73981f86bc3d71c2733d58f5e5.jpg", "visible_name": "OF.Honda.BR-V.PlatinumWhitePearl.jpg", - "original_name": "OF.Honda.BR-V.PlatinumWhitePearl.jpg" + "original_name": "26BeN3i23mO3lhRLhvZb5VbQLIZvw0DJ_3509408af0be0e6fb39f8d13c6f4ad127929ca73981f86bc3d71c2733d58f5e5.jpg" } ], - "field_705225": [ + "field_59762": [ 8 ], - "field_725742": null, - "field_725743": "2021", - "field_725744": null, - "field_725745": 313851, - "field_725746": "5", - "field_725747": "Platinum White Pearl", - "field_725748": "18000.00", - "field_725749": 313860, - "field_725750": [], - "field_725751": "15", - "field_725752": null, - "field_725753": "• Free 10gal fuel\n• Windshield and window tints\n• Reverse parking sensor\n• Toolbox\n• Floor matting", - "field_725755": "NLA3917", - "field_725756": "5FNYF186046P6BNMZ", - "field_725757": [ + "field_59840": null, + "field_59841": null, + "field_59763": 21053, + "field_59764": "5", + "field_59765": "Platinum White Pearl", + "field_59766": "18000", + "field_59867": null, + "field_59767": [], + "field_59768": "15", + "field_59842": null, + "field_59769": "\u2022 Free 10gal fuel\n\u2022 Windshield and window tints\n\u2022 Reverse parking sensor\n\u2022 Toolbox\n\u2022 Floor matting", + "field_59770": "NLA3917", + "field_59771": "5FNYF186046P6BNMZ", + "field_59772": [ { - "name": "iQ8EvGq8TSuARN9lajPbnEUQtJq6Y1kM_ac5e07c439066a20b7e755891d10af1c0afd6654e7470ca1129973c94ee60767.jpg", + "name": "psOkzupTYP2Yj5aHa5hAkiEYJ7HU9qum_ac5e07c439066a20b7e755891d10af1c0afd6654e7470ca1129973c94ee60767.jpg", "visible_name": "vehicle_title.jpg", - "original_name": "vehicle_title.jpg" + "original_name": "psOkzupTYP2Yj5aHa5hAkiEYJ7HU9qum_ac5e07c439066a20b7e755891d10af1c0afd6654e7470ca1129973c94ee60767.jpg" } ], - "field_725758": "2021-01-25", - "field_725759": [ + "field_59773": "2021-01-25", + "field_59774": [ 2 ], - "field_725788": [ + "field_59775": [ 4 ], - "field_725869": "Change oil needed.", - "field_725899": null, - "field_735944": null, - "field_738833": "46P6BNMS", - "field_738895": null, - "field_738896": null + "field_59776": "Change oil needed.", + "field_59866": null, + "field_59777": "46P6BNMS", + "field_59843": null, + "field_59844": null, + "field_59848": null, + "field_59849": null, + "field_59778": [], + "field_59779": null }, { "id": 21, "order": "17.00000000000000000000", "created_on": "2022-11-20T19:14:42.925987+00:00", "updated_on": "2022-11-20T21:11:24.780023+00:00", - "field_705223": null, - "field_705224": [ + "field_59760": null, + "field_59761": [ { - "name": "73avC1A1ljpoppbiQW5hevRta52TT6N2_b8e79c44b179a962f7198bdca3cb1117d3f8cbcdebdf0773d4333efdbcfef05f.jpg", + "name": "sdEY3tiJkXwlGMbHXa1uu68k5jyubjg6_b8e79c44b179a962f7198bdca3cb1117d3f8cbcdebdf0773d4333efdbcfef05f.jpg", "visible_name": "OF.Mitsubishi.MonteroSportGT4WD.WhiteDiamond.jpg", - "original_name": "OF.Mitsubishi.MonteroSportGT4WD.WhiteDiamond.jpg" + "original_name": "sdEY3tiJkXwlGMbHXa1uu68k5jyubjg6_b8e79c44b179a962f7198bdca3cb1117d3f8cbcdebdf0773d4333efdbcfef05f.jpg" } ], - "field_705225": [ + "field_59762": [ 5 ], - "field_725742": null, - "field_725743": "2022", - "field_725744": null, - "field_725745": 313850, - "field_725746": "5", - "field_725747": "White diamond", - "field_725748": "33500.00", - "field_725749": 313859, - "field_725750": [ - 5 + "field_59840": null, + "field_59841": null, + "field_59763": 21052, + "field_59764": "5", + "field_59765": "White diamond", + "field_59766": "33500", + "field_59867": null, + "field_59767": [ + 5, + 17, + 18 ], - "field_725751": "20", - "field_725752": null, - "field_725753": "• Free 17gal fuel\n• Windshield and window tints\n• Reverse parking sensor\n• Toolbox\n• Floor matting", - "field_725755": "MTR5391", - "field_725756": "1Z5HC22K56HGKPKEX", - "field_725757": [ + "field_59768": "20", + "field_59842": null, + "field_59769": "\u2022 Free 17gal fuel\n\u2022 Windshield and window tints\n\u2022 Reverse parking sensor\n\u2022 Toolbox\n\u2022 Floor matting", + "field_59770": "MTR5391", + "field_59771": "1Z5HC22K56HGKPKEX", + "field_59772": [ { - "name": "iQ8EvGq8TSuARN9lajPbnEUQtJq6Y1kM_ac5e07c439066a20b7e755891d10af1c0afd6654e7470ca1129973c94ee60767.jpg", + "name": "psOkzupTYP2Yj5aHa5hAkiEYJ7HU9qum_ac5e07c439066a20b7e755891d10af1c0afd6654e7470ca1129973c94ee60767.jpg", "visible_name": "vehicle_title.jpg", - "original_name": "vehicle_title.jpg" + "original_name": "psOkzupTYP2Yj5aHa5hAkiEYJ7HU9qum_ac5e07c439066a20b7e755891d10af1c0afd6654e7470ca1129973c94ee60767.jpg" } ], - "field_725758": "2021-10-25", - "field_725759": [ + "field_59773": "2021-10-25", + "field_59774": [ 8 ], - "field_725788": [ + "field_59775": [ 3 ], - "field_725869": "", - "field_725899": null, - "field_735944": null, - "field_738833": "6HGKPKEI", - "field_738895": null, - "field_738896": null + "field_59776": "", + "field_59866": null, + "field_59777": "6HGKPKEI", + "field_59843": null, + "field_59844": null, + "field_59848": null, + "field_59849": null, + "field_59778": [], + "field_59779": null }, { "id": 22, "order": "18.00000000000000000000", "created_on": "2022-11-20T19:14:44.509221+00:00", "updated_on": "2022-11-20T21:12:49.593466+00:00", - "field_705223": null, - "field_705224": [ + "field_59760": null, + "field_59761": [ { - "name": "10zF5xrm5pi5NzxomuhoSPBsjLRmVrlC_28042d7a9ee6e39e060d4f81812f2780e9ef1b0476bdb59759fd277934b8e098.jpg", + "name": "kGXm2qAdZO7uwIKetGEZjpLIRVWhzQjR_28042d7a9ee6e39e060d4f81812f2780e9ef1b0476bdb59759fd277934b8e098.jpg", "visible_name": "OF.Mitsubishi.MonteroSportGLX2WD.MediumRedMica.jpg", - "original_name": "OF.Mitsubishi.MonteroSportGLX2WD.MediumRedMica.jpg" + "original_name": "kGXm2qAdZO7uwIKetGEZjpLIRVWhzQjR_28042d7a9ee6e39e060d4f81812f2780e9ef1b0476bdb59759fd277934b8e098.jpg" } ], - "field_705225": [ + "field_59762": [ 6 ], - "field_725742": null, - "field_725743": "2022", - "field_725744": null, - "field_725745": 313850, - "field_725746": "5", - "field_725747": "Medium Red Mica", - "field_725748": "23500.00", - "field_725749": 313856, - "field_725750": [], - "field_725751": "20", - "field_725752": null, - "field_725753": "• Free 17gal fuel\n• Windshield and window tints\n• Reverse parking sensor\n• Toolbox\n• Floor matting", - "field_725755": "MHA5179", - "field_725756": "1Z5HT38K86LDNJ2FL", - "field_725757": [ + "field_59840": null, + "field_59841": null, + "field_59763": 21052, + "field_59764": "5", + "field_59765": "Medium Red Mica", + "field_59766": "23500", + "field_59867": null, + "field_59767": [], + "field_59768": "20", + "field_59842": null, + "field_59769": "\u2022 Free 17gal fuel\n\u2022 Windshield and window tints\n\u2022 Reverse parking sensor\n\u2022 Toolbox\n\u2022 Floor matting", + "field_59770": "MHA5179", + "field_59771": "1Z5HT38K86LDNJ2FL", + "field_59772": [ { - "name": "iQ8EvGq8TSuARN9lajPbnEUQtJq6Y1kM_ac5e07c439066a20b7e755891d10af1c0afd6654e7470ca1129973c94ee60767.jpg", + "name": "psOkzupTYP2Yj5aHa5hAkiEYJ7HU9qum_ac5e07c439066a20b7e755891d10af1c0afd6654e7470ca1129973c94ee60767.jpg", "visible_name": "vehicle_title.jpg", - "original_name": "vehicle_title.jpg" + "original_name": "psOkzupTYP2Yj5aHa5hAkiEYJ7HU9qum_ac5e07c439066a20b7e755891d10af1c0afd6654e7470ca1129973c94ee60767.jpg" } ], - "field_725758": "2021-10-25", - "field_725759": [ + "field_59773": "2021-10-25", + "field_59774": [ 2 ], - "field_725788": [ + "field_59775": [ 1 ], - "field_725869": "Processing all legal documents.", - "field_725899": null, - "field_735944": null, - "field_738833": "6LDNJ2FO", - "field_738895": null, - "field_738896": null + "field_59776": "Processing all legal documents.", + "field_59866": null, + "field_59777": "6LDNJ2FO", + "field_59843": null, + "field_59844": null, + "field_59848": null, + "field_59849": null, + "field_59778": [], + "field_59779": null }, { "id": 23, "order": "19.00000000000000000000", "created_on": "2022-11-20T19:14:45.601921+00:00", "updated_on": "2022-11-20T21:11:22.410123+00:00", - "field_705223": null, - "field_705224": [ + "field_59760": null, + "field_59761": [ { - "name": "7PGWn5D6yjFapuhDqBkI48G9GmI2B3Mu_1f98fb5ba9b5521e045bb3dff6763a24c8002611f55f74de908c86e39cd92b41.jpg", + "name": "UL8Lg48VaTRKngk6HwE1SpEIT1RUPLKL_1f98fb5ba9b5521e045bb3dff6763a24c8002611f55f74de908c86e39cd92b41.jpg", "visible_name": "OF.Honda.BR-V.PassionRedPearl.jpg", - "original_name": "OF.Honda.BR-V.PassionRedPearl.jpg" + "original_name": "UL8Lg48VaTRKngk6HwE1SpEIT1RUPLKL_1f98fb5ba9b5521e045bb3dff6763a24c8002611f55f74de908c86e39cd92b41.jpg" } ], - "field_705225": [ + "field_59762": [ 8 ], - "field_725742": null, - "field_725743": "2022", - "field_725744": null, - "field_725745": 313850, - "field_725746": "3", - "field_725747": "Passion Red Pearl", - "field_725748": "18000.00", - "field_725749": 313859, - "field_725750": [ + "field_59840": null, + "field_59841": null, + "field_59763": 21052, + "field_59764": "3", + "field_59765": "Passion Red Pearl", + "field_59766": "18000", + "field_59867": null, + "field_59767": [ 9 ], - "field_725751": "20", - "field_725752": null, - "field_725753": "• Free 10gal fuel\n• Windshield and window tints\n• Reverse parking sensor\n• Toolbox\n• Floor matting", - "field_725755": "NRT5379", - "field_725756": "3HGCG55692W647XFU", - "field_725757": [ + "field_59768": "20", + "field_59842": null, + "field_59769": "\u2022 Free 10gal fuel\n\u2022 Windshield and window tints\n\u2022 Reverse parking sensor\n\u2022 Toolbox\n\u2022 Floor matting", + "field_59770": "NRT5379", + "field_59771": "3HGCG55692W647XFU", + "field_59772": [ { - "name": "iQ8EvGq8TSuARN9lajPbnEUQtJq6Y1kM_ac5e07c439066a20b7e755891d10af1c0afd6654e7470ca1129973c94ee60767.jpg", + "name": "psOkzupTYP2Yj5aHa5hAkiEYJ7HU9qum_ac5e07c439066a20b7e755891d10af1c0afd6654e7470ca1129973c94ee60767.jpg", "visible_name": "vehicle_title.jpg", - "original_name": "vehicle_title.jpg" + "original_name": "psOkzupTYP2Yj5aHa5hAkiEYJ7HU9qum_ac5e07c439066a20b7e755891d10af1c0afd6654e7470ca1129973c94ee60767.jpg" } ], - "field_725758": "2022-01-10", - "field_725759": [ + "field_59773": "2022-01-10", + "field_59774": [ 8 ], - "field_725788": [ + "field_59775": [ 3 ], - "field_725869": "", - "field_725899": null, - "field_735944": null, - "field_738833": "2W647XFC", - "field_738895": null, - "field_738896": null + "field_59776": "", + "field_59866": null, + "field_59777": "2W647XFC", + "field_59843": null, + "field_59844": null, + "field_59848": null, + "field_59849": null, + "field_59778": [ + 7 + ], + "field_59779": null }, { "id": 24, "order": "20.00000000000000000000", "created_on": "2022-11-20T19:14:48.530158+00:00", "updated_on": "2022-11-20T21:11:34.506738+00:00", - "field_705223": null, - "field_705224": [ + "field_59760": null, + "field_59761": [ { - "name": "xbKMT6tnjPdJQH6A1yTOPHPbK10SfDUY_3509408af0be0e6fb39f8d13c6f4ad127929ca73981f86bc3d71c2733d58f5e5.jpg", + "name": "26BeN3i23mO3lhRLhvZb5VbQLIZvw0DJ_3509408af0be0e6fb39f8d13c6f4ad127929ca73981f86bc3d71c2733d58f5e5.jpg", "visible_name": "OF.Honda.BR-V.PlatinumWhitePearl.jpg", - "original_name": "OF.Honda.BR-V.PlatinumWhitePearl.jpg" + "original_name": "26BeN3i23mO3lhRLhvZb5VbQLIZvw0DJ_3509408af0be0e6fb39f8d13c6f4ad127929ca73981f86bc3d71c2733d58f5e5.jpg" } ], - "field_705225": [ + "field_59762": [ 8 ], - "field_725742": null, - "field_725743": "2021", - "field_725744": null, - "field_725745": 313851, - "field_725746": "12", - "field_725747": "Platinum White Pearl", - "field_725748": "15800.00", - "field_725749": 313859, - "field_725750": [ + "field_59840": null, + "field_59841": null, + "field_59763": 21053, + "field_59764": "12", + "field_59765": "Platinum White Pearl", + "field_59766": "15800", + "field_59867": null, + "field_59767": [ 8 ], - "field_725751": "15", - "field_725752": null, - "field_725753": "• Free 10gal fuel\n• Windshield and window tints\n• Reverse parking sensor\n• Toolbox\n• Floor matting", - "field_725755": "NXL3971", - "field_725756": "3HGCG554025YSENJP", - "field_725757": [ + "field_59768": "15", + "field_59842": null, + "field_59769": "\u2022 Free 10gal fuel\n\u2022 Windshield and window tints\n\u2022 Reverse parking sensor\n\u2022 Toolbox\n\u2022 Floor matting", + "field_59770": "NXL3971", + "field_59771": "3HGCG554025YSENJP", + "field_59772": [ { - "name": "iQ8EvGq8TSuARN9lajPbnEUQtJq6Y1kM_ac5e07c439066a20b7e755891d10af1c0afd6654e7470ca1129973c94ee60767.jpg", + "name": "psOkzupTYP2Yj5aHa5hAkiEYJ7HU9qum_ac5e07c439066a20b7e755891d10af1c0afd6654e7470ca1129973c94ee60767.jpg", "visible_name": "vehicle_title.jpg", - "original_name": "vehicle_title.jpg" + "original_name": "psOkzupTYP2Yj5aHa5hAkiEYJ7HU9qum_ac5e07c439066a20b7e755891d10af1c0afd6654e7470ca1129973c94ee60767.jpg" } ], - "field_725758": "2021-01-18", - "field_725759": [ + "field_59773": "2021-01-18", + "field_59774": [ 2 ], - "field_725788": [ + "field_59775": [ 4 ], - "field_725869": "", - "field_725899": null, - "field_735944": null, - "field_738833": "25YSENJO", - "field_738895": null, - "field_738896": null + "field_59776": "", + "field_59866": null, + "field_59777": "25YSENJO", + "field_59843": null, + "field_59844": null, + "field_59848": null, + "field_59849": null, + "field_59778": [ + 6 + ], + "field_59779": null }, { "id": 25, "order": "21.00000000000000000000", "created_on": "2022-11-20T19:14:50.883911+00:00", "updated_on": "2022-11-20T21:10:45.356919+00:00", - "field_705223": null, - "field_705224": [ + "field_59760": null, + "field_59761": [ { - "name": "VzHVBORgFvmZahMBX1c3PQZA0P1mBxRi_e6952fcc811c73e75a375ed412e7448508f7c3a3299a649c2eb2ee5b417ec154.jpg", + "name": "ZU4unKJk8MIn4bbQ4Q1umxsLPqVYwrG1_e6952fcc811c73e75a375ed412e7448508f7c3a3299a649c2eb2ee5b417ec154.jpg", "visible_name": "OF.Honda.BR-V.ModernSteelMetallic.jpg", - "original_name": "OF.Honda.BR-V.ModernSteelMetallic.jpg" + "original_name": "ZU4unKJk8MIn4bbQ4Q1umxsLPqVYwrG1_e6952fcc811c73e75a375ed412e7448508f7c3a3299a649c2eb2ee5b417ec154.jpg" } ], - "field_705225": [ + "field_59762": [ 7 ], - "field_725742": null, - "field_725743": "2022", - "field_725744": null, - "field_725745": 313850, - "field_725746": "3", - "field_725747": "Modern steel metallic", - "field_725748": "15900.00", - "field_725749": 313856, - "field_725750": [], - "field_725751": "20", - "field_725752": null, - "field_725753": "• Free 10gal fuel\n• Windshield and window tints\n• Reverse parking sensor\n• Toolbox\n• Floor matting", - "field_725755": "NSY1973", - "field_725756": "3HGCP2F64BLMTSH3R", - "field_725757": [ + "field_59840": null, + "field_59841": null, + "field_59763": 21052, + "field_59764": "3", + "field_59765": "Modern steel metallic", + "field_59766": "15900", + "field_59867": null, + "field_59767": [], + "field_59768": "20", + "field_59842": null, + "field_59769": "\u2022 Free 10gal fuel\n\u2022 Windshield and window tints\n\u2022 Reverse parking sensor\n\u2022 Toolbox\n\u2022 Floor matting", + "field_59770": "NSY1973", + "field_59771": "3HGCP2F64BLMTSH3R", + "field_59772": [ { - "name": "iQ8EvGq8TSuARN9lajPbnEUQtJq6Y1kM_ac5e07c439066a20b7e755891d10af1c0afd6654e7470ca1129973c94ee60767.jpg", + "name": "psOkzupTYP2Yj5aHa5hAkiEYJ7HU9qum_ac5e07c439066a20b7e755891d10af1c0afd6654e7470ca1129973c94ee60767.jpg", "visible_name": "vehicle_title.jpg", - "original_name": "vehicle_title.jpg" + "original_name": "psOkzupTYP2Yj5aHa5hAkiEYJ7HU9qum_ac5e07c439066a20b7e755891d10af1c0afd6654e7470ca1129973c94ee60767.jpg" } ], - "field_725758": "2022-01-10", - "field_725759": [ + "field_59773": "2022-01-10", + "field_59774": [ 1 ], - "field_725788": [ + "field_59775": [ 2 ], - "field_725869": "", - "field_725899": null, - "field_735944": null, - "field_738833": "BLMTSH3J", - "field_738895": null, - "field_738896": null + "field_59776": "", + "field_59866": null, + "field_59777": "BLMTSH3J", + "field_59843": null, + "field_59844": null, + "field_59848": null, + "field_59849": null, + "field_59778": [], + "field_59779": null } - ] + ], + "data_sync": null }, { - "id": 111552, - "name": "Makes and models", - "order": 2, + "id": 5698, + "name": "Offers", + "order": 4, "fields": [ { - "id": 705226, - "type": "text", - "name": "Model and variant", + "id": 59780, + "type": "formula", + "name": "ID", + "description": null, "order": 0, "primary": true, - "text_default": "" + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "number_suffix": "", + "number_separator": "", + "date_include_time": null, + "duration_format": null, + "date_force_timezone": null, + "date_show_tzinfo": null, + "array_formula_type": null, + "error": null, + "number_decimal_places": null, + "date_time_format": null, + "number_prefix": "", + "nullable": false, + "date_format": null, + "formula": "concat( \n \"O\", \n if( \n row_id() < 10, \n concat(\"0000\", row_id()), \n if( \n row_id() < 100, \n concat(\"000\", row_id()), \n if( \n row_id() < 1000, \n concat(\"00\", row_id()), \n if( \n row_id() < 10000, \n concat(\"0\", row_id()), \n row_id() \n ) \n ) \n ) \n ) \n)", + "formula_type": "text" }, { - "id": 705227, - "type": "single_select", - "name": "Make", - "order": 1, - "primary": false, - "select_options": [ - { - "id": 295638, - "value": "Alfa Romeo", - "color": "blue", - "order": 0 - }, - { - "id": 295639, - "value": "Aston Martin", - "color": "blue", - "order": 1 - }, - { - "id": 295640, - "value": "Audi", - "color": "blue", - "order": 2 - }, - { - "id": 295641, - "value": "Bentley", - "color": "green", - "order": 3 - }, - { - "id": 295642, - "value": "BMW", - "color": "green", - "order": 4 - }, - { - "id": 295643, - "value": "Cadillac", - "color": "orange", - "order": 5 - }, - { - "id": 295644, - "value": "Chevrolet", - "color": "orange", - "order": 6 - }, - { - "id": 295645, - "value": "Chrysler", - "color": "orange", - "order": 7 - }, - { - "id": 295646, - "value": "Dodge", - "color": "red", - "order": 8 - }, - { - "id": 295647, - "value": "Ferrari", - "color": "gray", - "order": 9 - }, - { - "id": 295648, - "value": "Fiat", - "color": "gray", - "order": 10 - }, - { - "id": 295649, - "value": "Ford", - "color": "gray", - "order": 11 - }, - { - "id": 295650, - "value": "GMC", - "color": "gray", - "order": 12 - }, - { - "id": 295651, - "value": "Honda", - "color": "light-blue", - "order": 13 - }, - { - "id": 295652, - "value": "Hummer", - "color": "light-blue", - "order": 14 - }, - { - "id": 295653, - "value": "Hyundai", - "color": "light-blue", - "order": 15 - }, - { - "id": 295654, - "value": "Isuzu", - "color": "light-green", - "order": 16 - }, - { - "id": 295655, - "value": "Jaguar", - "color": "light-green", - "order": 17 - }, - { - "id": 295656, - "value": "Jeep", - "color": "light-green", - "order": 18 - }, - { - "id": 295657, - "value": "Kia", - "color": "light-green", - "order": 19 - }, - { - "id": 295658, - "value": "Lamborghini", - "color": "light-orange", - "order": 20 - }, - { - "id": 295659, - "value": "Land Rover", - "color": "light-orange", - "order": 21 - }, - { - "id": 295660, - "value": "Lexus", - "color": "light-orange", - "order": 22 - }, - { - "id": 295661, - "value": "Lincoln", - "color": "light-orange", - "order": 23 - }, - { - "id": 295662, - "value": "Lotus", - "color": "light-orange", - "order": 24 - }, - { - "id": 295663, - "value": "Maserati", - "color": "light-red", - "order": 25 - }, - { - "id": 295664, - "value": "Mazda", - "color": "light-red", - "order": 26 - }, - { - "id": 295665, - "value": "Mercedes-Benz", - "color": "light-red", - "order": 27 - }, - { - "id": 295666, - "value": "Mitsubishi", - "color": "light-red", - "order": 28 - }, - { - "id": 295667, - "value": "Nissan", - "color": "light-gray", - "order": 29 - }, - { - "id": 295668, - "value": "Opel", - "color": "light-gray", - "order": 30 - }, - { - "id": 295669, - "value": "Peugeot", - "color": "light-gray", - "order": 31 - }, - { - "id": 295670, - "value": "Porsche", - "color": "light-gray", - "order": 32 - }, - { - "id": 295671, - "value": "RAM", - "color": "light-gray", - "order": 33 - }, - { - "id": 295672, - "value": "Rolls-Royce", - "color": "light-gray", - "order": 34 - }, - { - "id": 295673, - "value": "Scion", - "color": "blue", - "order": 35 - }, - { - "id": 295674, - "value": "Smart", - "color": "blue", - "order": 36 - }, - { - "id": 295675, - "value": "Subaru", - "color": "blue", - "order": 37 - }, - { - "id": 295676, - "value": "Suzuki", - "color": "blue", - "order": 38 - }, - { - "id": 295677, - "value": "Tesla", - "color": "green", - "order": 39 - }, - { - "id": 295678, - "value": "Toyota", - "color": "green", - "order": 40 - }, - { - "id": 295679, - "value": "Volkswagen", - "color": "orange", - "order": 41 - }, - { - "id": 295680, - "value": "Volvo", - "color": "orange", - "order": 42 - } - ] - }, - { - "id": 705228, - "type": "file", - "name": "Photo", - "order": 2, - "primary": false - }, - { - "id": 705238, - "type": "single_select", - "name": "Type", + "id": 59781, + "type": "link_row", + "name": "Car", + "description": null, "order": 3, "primary": false, - "select_options": [ - { - "id": 295681, - "value": "Sedan", - "color": "gray", - "order": 0 - }, - { - "id": 295682, - "value": "Coupe", - "color": "gray", - "order": 1 - }, - { - "id": 295683, - "value": "Convertible", - "color": "gray", - "order": 2 - }, - { - "id": 295684, - "value": "Sports car", - "color": "gray", - "order": 3 - }, - { - "id": 295685, - "value": "Hatchback", - "color": "gray", - "order": 4 - }, - { - "id": 295686, - "value": "Multipurpose vehicle (MPV)", - "color": "gray", - "order": 5 - }, - { - "id": 295687, - "value": "Van", - "color": "gray", - "order": 6 - }, - { - "id": 295688, - "value": "Sport utility vehicle (SUV)", - "color": "gray", - "order": 7 - }, - { - "id": 295689, - "value": "Pickup truck", - "color": "gray", - "order": 8 - }, - { - "id": 295690, - "value": "Motorcycle", - "color": "gray", - "order": 9 - } - ] - }, - { - "id": 705239, - "type": "number", - "name": "Engine size (L)", - "order": 4, - "primary": false, - "number_decimal_places": 2, - "number_negative": false - }, - { - "id": 705240, - "type": "single_select", - "name": "Transmission", - "order": 5, - "primary": false, - "select_options": [ - { - "id": 295691, - "value": "Automatic", - "color": "light-blue", - "order": 0 - }, - { - "id": 295692, - "value": "CVT", - "color": "light-blue", - "order": 1 - }, - { - "id": 295693, - "value": "Manual", - "color": "light-blue", - "order": 2 - } - ] - }, - { - "id": 705241, - "type": "single_select", - "name": "Fuel type", - "order": 6, - "primary": false, - "select_options": [ - { - "id": 295694, - "value": "Gasoline", - "color": "green", - "order": 0 - }, - { - "id": 295695, - "value": "Diesel", - "color": "orange", - "order": 1 - }, - { - "id": 295696, - "value": "Hybrid", - "color": "dark-gray", - "order": 2 - }, - { - "id": 295697, - "value": "Electric", - "color": "red", - "order": 3 - }, - { - "id": 295698, - "value": "Hydrogen", - "color": "dark-blue", - "order": 4 - }, - { - "id": 295699, - "value": "LPG", - "color": "light-blue", - "order": 5 - } - ] - }, - { - "id": 705242, - "type": "number", - "name": "Seat count", - "order": 7, - "primary": false, - "number_decimal_places": 0, - "number_negative": false - }, - { - "id": 705243, - "type": "number", - "name": "Body length (mm)", - "order": 8, - "primary": false, - "number_decimal_places": 2, - "number_negative": false - }, - { - "id": 705244, - "type": "number", - "name": "Body width (mm)", - "order": 9, - "primary": false, - "number_decimal_places": 2, - "number_negative": false - }, - { - "id": 705245, - "type": "number", - "name": "Body height (mm)", - "order": 10, - "primary": false, - "number_decimal_places": 2, - "number_negative": false - }, - { - "id": 705246, - "type": "formula", - "name": "In stock count", - "order": 11, - "primary": false, - "error": null, - "date_format": null, - "date_include_time": null, - "date_time_format": null, - "number_decimal_places": 0, - "array_formula_type": null, - "formula": "count( \n filter( \n lookup(\"Related cars\", \"In stock\"), \n lookup(\"Related cars\", \"In stock\")=true \n ) \n)", - "formula_type": "number" - }, - { - "id": 705247, - "type": "formula", - "name": "History count", - "order": 12, - "primary": false, - "error": null, - "date_format": null, - "date_include_time": null, - "date_time_format": null, - "number_decimal_places": 0, - "array_formula_type": null, - "formula": "count(field(\"Related cars\"))", - "formula_type": "number" - }, - { - "id": 725741, - "type": "link_row", - "name": "Related cars", - "order": 13, - "primary": false, - "link_row_table_id": 111551, - "link_row_related_field_id": 705225, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "link_row_table_id": 5697, + "link_row_related_field_id": 59767, + "link_row_limit_selection_view_id": null, "has_related_field": true }, { - "id": 733934, - "type": "number", - "name": "Year model", - "order": 14, + "id": 59864, + "type": "lookup", + "name": "Year", + "description": null, + "order": 4, "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "number_suffix": "", + "number_separator": "", + "date_include_time": null, + "duration_format": null, + "date_force_timezone": null, + "date_show_tzinfo": null, + "array_formula_type": "number", + "error": null, "number_decimal_places": 0, - "number_negative": false + "date_time_format": null, + "number_prefix": "", + "nullable": true, + "date_format": null, + "through_field_id": 59781, + "through_field_name": "Car", + "target_field_id": 59841, + "target_field_name": "Year" + }, + { + "id": 59863, + "type": "lookup", + "name": "Brand", + "description": null, + "order": 5, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "number_suffix": "", + "number_separator": "", + "date_include_time": null, + "duration_format": null, + "date_force_timezone": null, + "date_show_tzinfo": null, + "array_formula_type": "text", + "error": null, + "number_decimal_places": null, + "date_time_format": null, + "number_prefix": "", + "nullable": true, + "date_format": null, + "through_field_id": 59781, + "through_field_name": "Car", + "target_field_id": 59840, + "target_field_name": "Brand" + }, + { + "id": 59850, + "type": "rollup", + "name": "Model", + "description": null, + "order": 6, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "number_suffix": "", + "number_separator": "", + "date_include_time": null, + "duration_format": null, + "date_force_timezone": null, + "date_show_tzinfo": null, + "array_formula_type": null, + "error": null, + "number_decimal_places": null, + "date_time_format": null, + "number_prefix": "", + "nullable": true, + "date_format": null, + "through_field_id": 59781, + "target_field_id": 59762, + "rollup_function": "min" + }, + { + "id": 59851, + "type": "lookup", + "name": "Color", + "description": null, + "order": 7, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "number_suffix": "", + "number_separator": "", + "date_include_time": null, + "duration_format": null, + "date_force_timezone": null, + "date_show_tzinfo": null, + "array_formula_type": "text", + "error": null, + "number_decimal_places": null, + "date_time_format": null, + "number_prefix": "", + "nullable": true, + "date_format": null, + "through_field_id": 59781, + "through_field_name": "Car", + "target_field_id": 59765, + "target_field_name": "Color" + }, + { + "id": 59782, + "type": "date", + "name": "Date sold", + "description": null, + "order": 12, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "date_format": "ISO", + "date_include_time": false, + "date_time_format": "24", + "date_show_tzinfo": false, + "date_force_timezone": null + }, + { + "id": 59783, + "type": "date", + "name": "Date offer", + "description": null, + "order": 13, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "date_format": "ISO", + "date_include_time": false, + "date_time_format": "24", + "date_show_tzinfo": false, + "date_force_timezone": null + }, + { + "id": 59784, + "type": "number", + "name": "Price offer", + "description": null, + "order": 15, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "number_decimal_places": 0, + "number_negative": false, + "number_prefix": "$", + "number_suffix": "", + "number_separator": "SPACE_COMMA" + }, + { + "id": 59785, + "type": "link_row", + "name": "Customer", + "description": null, + "order": 16, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "link_row_table_id": 5701, + "link_row_related_field_id": 59819, + "link_row_limit_selection_view_id": null, + "has_related_field": true + }, + { + "id": 59786, + "type": "link_row", + "name": "Sold by", + "description": null, + "order": 18, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "link_row_table_id": 5700, + "link_row_related_field_id": 59809, + "link_row_limit_selection_view_id": null, + "has_related_field": true + }, + { + "id": 59787, + "type": "file", + "name": "Transaction docs", + "description": null, + "order": 19, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false + }, + { + "id": 59788, + "type": "link_row", + "name": "Reviews", + "description": null, + "order": 22, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "link_row_table_id": 5702, + "link_row_related_field_id": 59824, + "link_row_limit_selection_view_id": null, + "has_related_field": true + }, + { + "id": 59789, + "type": "link_row", + "name": "Financing", + "description": null, + "order": 23, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "link_row_table_id": 5703, + "link_row_related_field_id": 59828, + "link_row_limit_selection_view_id": null, + "has_related_field": true + }, + { + "id": 59790, + "type": "single_select", + "name": "Status", + "description": null, + "order": 24, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "select_options": [ + { + "id": 21058, + "value": "Offer accepted", + "color": "dark-green", + "order": 0 + }, + { + "id": 21059, + "value": "Offer rejected", + "color": "dark-red", + "order": 1 + }, + { + "id": 21060, + "value": "Under consideration", + "color": "yellow", + "order": 2 + } + ] + }, + { + "id": 59865, + "type": "lookup", + "name": "Price suggested", + "description": null, + "order": 25, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "number_suffix": "", + "number_separator": "SPACE_COMMA", + "date_include_time": null, + "duration_format": null, + "date_force_timezone": null, + "date_show_tzinfo": null, + "array_formula_type": "number", + "error": null, + "number_decimal_places": 0, + "date_time_format": null, + "number_prefix": "$", + "nullable": false, + "date_format": null, + "through_field_id": 59781, + "through_field_name": "Car", + "target_field_id": 59842, + "target_field_name": "Suggested price" + }, + { + "id": 59869, + "type": "formula", + "name": "Price difference", + "description": null, + "order": 27, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "number_suffix": "", + "number_separator": "SPACE_COMMA", + "date_include_time": null, + "duration_format": null, + "date_force_timezone": null, + "date_show_tzinfo": null, + "array_formula_type": null, + "error": null, + "number_decimal_places": 0, + "date_time_format": null, + "number_prefix": "$", + "nullable": false, + "date_format": null, + "formula": "field('Price offer') - min(field('Price suggested'))", + "formula_type": "number" + }, + { + "id": 59852, + "type": "rollup", + "name": "Branch", + "description": null, + "order": 28, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "number_suffix": "", + "number_separator": "", + "date_include_time": null, + "duration_format": null, + "date_force_timezone": null, + "date_show_tzinfo": null, + "array_formula_type": null, + "error": null, + "number_decimal_places": null, + "date_time_format": null, + "number_prefix": "", + "nullable": true, + "date_format": null, + "through_field_id": 59781, + "target_field_id": 59775, + "rollup_function": "min" + }, + { + "id": 59853, + "type": "rollup", + "name": "Staff email", + "description": null, + "order": 29, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "number_suffix": "", + "number_separator": "", + "date_include_time": null, + "duration_format": null, + "date_force_timezone": null, + "date_show_tzinfo": null, + "array_formula_type": null, + "error": null, + "number_decimal_places": null, + "date_time_format": null, + "number_prefix": "", + "nullable": true, + "date_format": null, + "through_field_id": 59786, + "target_field_id": 59807, + "rollup_function": "min" + }, + { + "id": 59854, + "type": "rollup", + "name": "Customer email", + "description": null, + "order": 30, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "number_suffix": "", + "number_separator": "", + "date_include_time": null, + "duration_format": null, + "date_force_timezone": null, + "date_show_tzinfo": null, + "array_formula_type": null, + "error": null, + "number_decimal_places": null, + "date_time_format": null, + "number_prefix": "", + "nullable": true, + "date_format": null, + "through_field_id": 59785, + "target_field_id": 59817, + "rollup_function": "min" } ], "views": [ { - "id": 164492, + "id": 26478, "type": "grid", - "name": "All makes and models", + "name": "All offers", "order": 1, + "ownership_type": "collaborative", + "owned_by": null, "filter_type": "AND", "filters_disabled": false, "filters": [], + "filter_groups": [], "sortings": [ { - "id": 51846, - "field_id": 705227, + "id": 20379, + "field_id": 59783, "order": "ASC" - }, - { - "id": 51847, - "field_id": 705226, - "order": "ASC" - }, - { - "id": 52976, - "field_id": 733934, - "order": "DESC" } ], - "decorations": [], + "group_bys": [], + "decorations": [ + { + "id": 8738, + "type": "left_border_color", + "value_provider_type": "single_select_color", + "value_provider_conf": { + "field_id": 59790 + }, + "order": 1 + }, + { + "id": 8739, + "type": "background_color", + "value_provider_type": "conditional_color", + "value_provider_conf": { + "colors": [ + { + "id": "77aefcee-0c1d-4338-a857-5835055c3cd9", + "color": "light-red", + "filters": [ + { + "id": "31942597-f5fc-4ed1-bf41-424eee0b8270", + "type": "single_select_equal", + "field": 59790, + "group": null, + "value": "21060" + }, + { + "id": "4705601f-2f7f-4c16-9a95-072538d9d873", + "type": "lower_than", + "field": 59869, + "group": null, + "value": "0" + } + ], + "operator": "AND" + }, + { + "id": "279e3abc-9176-446f-9992-7121923b1a9e", + "color": "light-green", + "filters": [ + { + "id": "d3c184d2-c34f-4ff0-af85-7dd2cc650460", + "type": "single_select_equal", + "field": 59790, + "group": null, + "value": "21060" + }, + { + "id": "376837b5-828c-41b9-a700-df5a9df001eb", + "type": "higher_than_or_equal", + "field": 59869, + "group": null, + "value": "0" + } + ], + "operator": "AND" + } + ] + }, + "order": 2 + } + ], "public": false, - "row_identifier_type": "count", + "row_identifier_type": "id", + "row_height_size": "small", "field_options": [ { - "id": 1001493, - "field_id": 705226, - "width": 179, + "id": 261653, + "field_id": 59780, + "width": 100, "hidden": false, "order": 0, "aggregation_type": "unique_count", "aggregation_raw_type": "unique_count" }, { - "id": 1001491, - "field_id": 705227, - "width": 115, + "id": 261654, + "field_id": 59781, + "width": 133, "hidden": false, "order": 1, - "aggregation_type": "", - "aggregation_raw_type": "" - }, - { - "id": 1001492, - "field_id": 705228, - "width": 129, - "hidden": false, - "order": 2, "aggregation_type": "not_empty_percentage", "aggregation_raw_type": "empty_count" }, { - "id": 1001504, - "field_id": 705238, - "width": 194, + "id": 261655, + "field_id": 59863, + "width": 114, + "hidden": false, + "order": 2, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261656, + "field_id": 59850, + "width": 166, + "hidden": false, + "order": 3, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261657, + "field_id": 59864, + "width": 100, "hidden": false, "order": 4, "aggregation_type": "", "aggregation_raw_type": "" }, { - "id": 1001505, - "field_id": 705239, - "width": 146, + "id": 261658, + "field_id": 59851, + "width": 155, "hidden": false, "order": 5, - "aggregation_type": "average", - "aggregation_raw_type": "average" + "aggregation_type": "", + "aggregation_raw_type": "" }, { - "id": 1001506, - "field_id": 705240, - "width": 143, + "id": 261659, + "field_id": 59852, + "width": 200, "hidden": false, "order": 6, "aggregation_type": "", "aggregation_raw_type": "" }, { - "id": 1001507, - "field_id": 705241, - "width": 117, + "id": 261660, + "field_id": 59782, + "width": 148, "hidden": false, "order": 7, "aggregation_type": "", "aggregation_raw_type": "" }, { - "id": 1001508, - "field_id": 705242, - "width": 126, + "id": 261661, + "field_id": 59783, + "width": 175, "hidden": false, "order": 8, - "aggregation_type": "average", - "aggregation_raw_type": "average" + "aggregation_type": "", + "aggregation_raw_type": "" }, { - "id": 1001509, - "field_id": 705243, - "width": 169, + "id": 261662, + "field_id": 59789, + "width": 200, "hidden": false, "order": 9, - "aggregation_type": "average", - "aggregation_raw_type": "average" + "aggregation_type": "", + "aggregation_raw_type": "" }, { - "id": 1001510, - "field_id": 705244, - "width": 166, + "id": 261663, + "field_id": 59865, + "width": 171, "hidden": false, "order": 10, - "aggregation_type": "average", - "aggregation_raw_type": "average" + "aggregation_type": "", + "aggregation_raw_type": "" }, { - "id": 1001511, - "field_id": 705245, - "width": 169, + "id": 261664, + "field_id": 59784, + "width": 139, "hidden": false, "order": 11, - "aggregation_type": "average", - "aggregation_raw_type": "average" + "aggregation_type": "sum", + "aggregation_raw_type": "sum" }, { - "id": 1001512, - "field_id": 705246, - "width": 146, + "id": 261665, + "field_id": 59869, + "width": 200, "hidden": false, "order": 12, - "aggregation_type": "sum", - "aggregation_raw_type": "sum" + "aggregation_type": "", + "aggregation_raw_type": "" }, { - "id": 1001513, - "field_id": 705247, - "width": 143, + "id": 261666, + "field_id": 59785, + "width": 147, "hidden": false, "order": 13, - "aggregation_type": "sum", - "aggregation_raw_type": "sum" + "aggregation_type": "not_empty_percentage", + "aggregation_raw_type": "empty_count" }, { - "id": 1041770, - "field_id": 725741, + "id": 261667, + "field_id": 59854, "width": 200, "hidden": true, "order": 14, @@ -5800,1257 +9251,1761 @@ "aggregation_raw_type": "" }, { - "id": 1055633, - "field_id": 733934, - "width": 130, + "id": 261668, + "field_id": 59786, + "width": 149, "hidden": false, - "order": 3, + "order": 15, + "aggregation_type": "not_empty_percentage", + "aggregation_raw_type": "empty_count" + }, + { + "id": 261669, + "field_id": 59853, + "width": 200, + "hidden": true, + "order": 16, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261670, + "field_id": 59787, + "width": 180, + "hidden": false, + "order": 17, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261671, + "field_id": 59788, + "width": 200, + "hidden": false, + "order": 18, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261672, + "field_id": 59790, + "width": 200, + "hidden": false, + "order": 19, "aggregation_type": "", "aggregation_raw_type": "" } ] }, { - "id": 173713, - "type": "gallery", - "name": "Makes and models", + "id": 26479, + "type": "grid", + "name": "All offers grouped by branch", "order": 2, + "ownership_type": "collaborative", + "owned_by": null, "filter_type": "AND", "filters_disabled": false, "filters": [], + "filter_groups": [], "sortings": [ { - "id": 52973, - "field_id": 705227, + "id": 20380, + "field_id": 59783, "order": "ASC" - }, + } + ], + "group_bys": [ { - "id": 52974, - "field_id": 705226, + "id": 3638, + "field_id": 59852, "order": "ASC" - }, - { - "id": 52975, - "field_id": 733934, - "order": "DESC" } ], - "decorations": [], - "public": false, - "card_cover_image_field_id": 705228, - "field_options": [ + "decorations": [ { - "id": 78204, - "field_id": 733934, - "hidden": false, + "id": 8740, + "type": "left_border_color", + "value_provider_type": "single_select_color", + "value_provider_conf": { + "field_id": 59790 + }, "order": 1 }, { - "id": 78191, - "field_id": 705227, - "hidden": false, + "id": 8741, + "type": "background_color", + "value_provider_type": "conditional_color", + "value_provider_conf": { + "colors": [ + { + "id": "77aefcee-0c1d-4338-a857-5835055c3cd9", + "color": "light-red", + "filters": [ + { + "id": "31942597-f5fc-4ed1-bf41-424eee0b8270", + "type": "single_select_equal", + "field": 59790, + "group": null, + "value": "21060" + }, + { + "id": "4705601f-2f7f-4c16-9a95-072538d9d873", + "type": "lower_than", + "field": 59869, + "group": null, + "value": "0" + } + ], + "operator": "AND" + }, + { + "id": "279e3abc-9176-446f-9992-7121923b1a9e", + "color": "light-green", + "filters": [ + { + "id": "d3c184d2-c34f-4ff0-af85-7dd2cc650460", + "type": "single_select_equal", + "field": 59790, + "group": null, + "value": "21060" + }, + { + "id": "376837b5-828c-41b9-a700-df5a9df001eb", + "type": "higher_than_or_equal", + "field": 59869, + "group": null, + "value": "0" + } + ], + "operator": "AND" + } + ] + }, "order": 2 - }, + } + ], + "public": false, + "row_identifier_type": "count", + "row_height_size": "small", + "field_options": [ { - "id": 78190, - "field_id": 705226, + "id": 261673, + "field_id": 59780, + "width": 100, "hidden": false, - "order": 3 + "order": 0, + "aggregation_type": "unique_count", + "aggregation_raw_type": "unique_count" }, { - "id": 78192, - "field_id": 705228, - "hidden": true, - "order": 4 - }, - { - "id": 78193, - "field_id": 705238, - "hidden": true, - "order": 5 - }, - { - "id": 78194, - "field_id": 705239, - "hidden": true, - "order": 6 - }, - { - "id": 78195, - "field_id": 705240, + "id": 261674, + "field_id": 59781, + "width": 133, "hidden": false, - "order": 7 + "order": 1, + "aggregation_type": "not_empty_percentage", + "aggregation_raw_type": "empty_count" }, { - "id": 78196, - "field_id": 705241, - "hidden": true, - "order": 8 - }, - { - "id": 78197, - "field_id": 705242, - "hidden": true, - "order": 9 - }, - { - "id": 78198, - "field_id": 705243, - "hidden": true, - "order": 10 - }, - { - "id": 78199, - "field_id": 705244, - "hidden": true, - "order": 11 - }, - { - "id": 78200, - "field_id": 705245, - "hidden": true, - "order": 12 - }, - { - "id": 78201, - "field_id": 705246, + "id": 261675, + "field_id": 59863, + "width": 114, "hidden": false, - "order": 13 + "order": 2, + "aggregation_type": "", + "aggregation_raw_type": "" }, { - "id": 78202, - "field_id": 705247, - "hidden": true, - "order": 14 + "id": 261676, + "field_id": 59850, + "width": 166, + "hidden": false, + "order": 3, + "aggregation_type": "", + "aggregation_raw_type": "" }, { - "id": 78203, - "field_id": 725741, + "id": 261677, + "field_id": 59864, + "width": 100, + "hidden": false, + "order": 4, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261678, + "field_id": 59851, + "width": 155, + "hidden": false, + "order": 5, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261679, + "field_id": 59852, + "width": 200, "hidden": true, - "order": 15 + "order": 6, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261680, + "field_id": 59782, + "width": 148, + "hidden": false, + "order": 7, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261681, + "field_id": 59783, + "width": 175, + "hidden": false, + "order": 8, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261682, + "field_id": 59789, + "width": 200, + "hidden": false, + "order": 9, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261683, + "field_id": 59865, + "width": 171, + "hidden": false, + "order": 10, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261684, + "field_id": 59784, + "width": 139, + "hidden": false, + "order": 11, + "aggregation_type": "sum", + "aggregation_raw_type": "sum" + }, + { + "id": 261685, + "field_id": 59869, + "width": 200, + "hidden": false, + "order": 12, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261686, + "field_id": 59785, + "width": 147, + "hidden": false, + "order": 13, + "aggregation_type": "not_empty_percentage", + "aggregation_raw_type": "empty_count" + }, + { + "id": 261687, + "field_id": 59786, + "width": 149, + "hidden": false, + "order": 14, + "aggregation_type": "not_empty_percentage", + "aggregation_raw_type": "empty_count" + }, + { + "id": 261688, + "field_id": 59787, + "width": 180, + "hidden": false, + "order": 15, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261689, + "field_id": 59788, + "width": 200, + "hidden": false, + "order": 16, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261690, + "field_id": 59790, + "width": 200, + "hidden": false, + "order": 17, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261691, + "field_id": 59853, + "width": 200, + "hidden": true, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261692, + "field_id": 59854, + "width": 200, + "hidden": true, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" } ] }, { - "id": 174147, - "type": "kanban", - "name": "By make", + "id": 26480, + "type": "grid", + "name": "All offers grouped by car", "order": 3, + "ownership_type": "collaborative", + "owned_by": null, "filter_type": "AND", "filters_disabled": false, "filters": [], - "sortings": [], - "decorations": [], - "public": false, - "single_select_field_id": 705227, - "card_cover_image_field_id": 705228, - "field_options": [ + "filter_groups": [], + "sortings": [ { - "id": 43677, - "field_id": 733934, - "hidden": false, + "id": 20381, + "field_id": 59783, + "order": "ASC" + } + ], + "group_bys": [ + { + "id": 3639, + "field_id": 59781, + "order": "ASC" + } + ], + "decorations": [ + { + "id": 8742, + "type": "left_border_color", + "value_provider_type": "single_select_color", + "value_provider_conf": { + "field_id": 59790 + }, "order": 1 }, { - "id": 43663, - "field_id": 705226, - "hidden": false, + "id": 8743, + "type": "background_color", + "value_provider_type": "conditional_color", + "value_provider_conf": { + "colors": [ + { + "id": "77aefcee-0c1d-4338-a857-5835055c3cd9", + "color": "light-red", + "filters": [ + { + "id": "31942597-f5fc-4ed1-bf41-424eee0b8270", + "type": "single_select_equal", + "field": 59790, + "group": null, + "value": "21060" + }, + { + "id": "4705601f-2f7f-4c16-9a95-072538d9d873", + "type": "lower_than", + "field": 59869, + "group": null, + "value": "0" + } + ], + "operator": "AND" + }, + { + "id": "279e3abc-9176-446f-9992-7121923b1a9e", + "color": "light-green", + "filters": [ + { + "id": "d3c184d2-c34f-4ff0-af85-7dd2cc650460", + "type": "single_select_equal", + "field": 59790, + "group": null, + "value": "21060" + }, + { + "id": "376837b5-828c-41b9-a700-df5a9df001eb", + "type": "higher_than_or_equal", + "field": 59869, + "group": null, + "value": "0" + } + ], + "operator": "AND" + } + ] + }, "order": 2 - }, + } + ], + "public": false, + "row_identifier_type": "id", + "row_height_size": "small", + "field_options": [ { - "id": 43664, - "field_id": 705227, - "hidden": true, - "order": 3 - }, - { - "id": 43665, - "field_id": 705228, - "hidden": true, - "order": 4 - }, - { - "id": 43666, - "field_id": 705238, + "id": 261693, + "field_id": 59780, + "width": 100, "hidden": false, - "order": 5 + "order": 0, + "aggregation_type": "unique_count", + "aggregation_raw_type": "unique_count" }, { - "id": 43667, - "field_id": 705239, + "id": 261694, + "field_id": 59781, + "width": 133, "hidden": true, - "order": 6 + "order": 1, + "aggregation_type": "not_empty_percentage", + "aggregation_raw_type": "empty_count" }, { - "id": 43668, - "field_id": 705240, + "id": 261695, + "field_id": 59863, + "width": 114, "hidden": false, - "order": 7 + "order": 2, + "aggregation_type": "", + "aggregation_raw_type": "" }, { - "id": 43669, - "field_id": 705241, + "id": 261696, + "field_id": 59850, + "width": 166, "hidden": false, - "order": 8 + "order": 3, + "aggregation_type": "", + "aggregation_raw_type": "" }, { - "id": 43670, - "field_id": 705242, + "id": 261697, + "field_id": 59864, + "width": 100, "hidden": false, - "order": 9 + "order": 4, + "aggregation_type": "", + "aggregation_raw_type": "" }, { - "id": 43671, - "field_id": 705243, - "hidden": true, - "order": 10 - }, - { - "id": 43672, - "field_id": 705244, - "hidden": true, - "order": 11 - }, - { - "id": 43673, - "field_id": 705245, - "hidden": true, - "order": 12 - }, - { - "id": 43674, - "field_id": 705246, + "id": 261698, + "field_id": 59851, + "width": 155, "hidden": false, - "order": 13 + "order": 5, + "aggregation_type": "", + "aggregation_raw_type": "" }, { - "id": 43675, - "field_id": 705247, - "hidden": true, - "order": 14 + "id": 261699, + "field_id": 59852, + "width": 200, + "hidden": false, + "order": 6, + "aggregation_type": "", + "aggregation_raw_type": "" }, { - "id": 43676, - "field_id": 725741, + "id": 261700, + "field_id": 59782, + "width": 148, + "hidden": false, + "order": 7, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261701, + "field_id": 59783, + "width": 175, + "hidden": false, + "order": 8, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261702, + "field_id": 59789, + "width": 200, + "hidden": false, + "order": 9, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261703, + "field_id": 59865, + "width": 171, + "hidden": false, + "order": 10, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261704, + "field_id": 59784, + "width": 139, + "hidden": false, + "order": 11, + "aggregation_type": "sum", + "aggregation_raw_type": "sum" + }, + { + "id": 261705, + "field_id": 59869, + "width": 200, + "hidden": false, + "order": 12, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261706, + "field_id": 59785, + "width": 147, + "hidden": false, + "order": 13, + "aggregation_type": "not_empty_percentage", + "aggregation_raw_type": "empty_count" + }, + { + "id": 261707, + "field_id": 59786, + "width": 149, + "hidden": false, + "order": 14, + "aggregation_type": "not_empty_percentage", + "aggregation_raw_type": "empty_count" + }, + { + "id": 261708, + "field_id": 59787, + "width": 180, + "hidden": false, + "order": 15, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261709, + "field_id": 59788, + "width": 200, + "hidden": false, + "order": 16, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261710, + "field_id": 59790, + "width": 200, + "hidden": false, + "order": 17, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261711, + "field_id": 59853, + "width": 200, "hidden": true, - "order": 15 + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261712, + "field_id": 59854, + "width": 200, + "hidden": true, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" } ] }, { - "id": 174148, - "type": "kanban", - "name": "By type", + "id": 26481, + "type": "grid", + "name": "All offers grouped by car model", "order": 4, + "ownership_type": "collaborative", + "owned_by": null, "filter_type": "AND", "filters_disabled": false, "filters": [], - "sortings": [], - "decorations": [], - "public": false, - "single_select_field_id": 705238, - "card_cover_image_field_id": 705228, - "field_options": [ + "filter_groups": [], + "sortings": [ { - "id": 43678, - "field_id": 733934, - "hidden": false, + "id": 20382, + "field_id": 59783, + "order": "ASC" + } + ], + "group_bys": [ + { + "id": 3640, + "field_id": 59850, + "order": "ASC" + } + ], + "decorations": [ + { + "id": 8744, + "type": "left_border_color", + "value_provider_type": "single_select_color", + "value_provider_conf": { + "field_id": 59790 + }, "order": 1 }, { - "id": 43679, - "field_id": 705226, - "hidden": false, + "id": 8745, + "type": "background_color", + "value_provider_type": "conditional_color", + "value_provider_conf": { + "colors": [ + { + "id": "77aefcee-0c1d-4338-a857-5835055c3cd9", + "color": "light-red", + "filters": [ + { + "id": "31942597-f5fc-4ed1-bf41-424eee0b8270", + "type": "single_select_equal", + "field": 59790, + "group": null, + "value": "21060" + }, + { + "id": "4705601f-2f7f-4c16-9a95-072538d9d873", + "type": "lower_than", + "field": 59869, + "group": null, + "value": "0" + } + ], + "operator": "AND" + }, + { + "id": "279e3abc-9176-446f-9992-7121923b1a9e", + "color": "light-green", + "filters": [ + { + "id": "d3c184d2-c34f-4ff0-af85-7dd2cc650460", + "type": "single_select_equal", + "field": 59790, + "group": null, + "value": "21060" + }, + { + "id": "376837b5-828c-41b9-a700-df5a9df001eb", + "type": "higher_than_or_equal", + "field": 59869, + "group": null, + "value": "0" + } + ], + "operator": "AND" + } + ] + }, "order": 2 - }, + } + ], + "public": false, + "row_identifier_type": "count", + "row_height_size": "small", + "field_options": [ { - "id": 43680, - "field_id": 705227, + "id": 261713, + "field_id": 59780, + "width": 100, "hidden": false, - "order": 3 + "order": 0, + "aggregation_type": "unique_count", + "aggregation_raw_type": "unique_count" }, { - "id": 43681, - "field_id": 705228, - "hidden": true, - "order": 4 - }, - { - "id": 43682, - "field_id": 705238, - "hidden": true, - "order": 5 - }, - { - "id": 43683, - "field_id": 705239, - "hidden": true, - "order": 6 - }, - { - "id": 43684, - "field_id": 705240, + "id": 261714, + "field_id": 59781, + "width": 133, "hidden": false, - "order": 7 + "order": 1, + "aggregation_type": "not_empty_percentage", + "aggregation_raw_type": "empty_count" }, { - "id": 43685, - "field_id": 705241, + "id": 261715, + "field_id": 59863, + "width": 114, "hidden": false, - "order": 8 + "order": 2, + "aggregation_type": "", + "aggregation_raw_type": "" }, { - "id": 43686, - "field_id": 705242, + "id": 261716, + "field_id": 59850, + "width": 166, + "hidden": true, + "order": 3, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261717, + "field_id": 59864, + "width": 100, "hidden": false, - "order": 9 + "order": 4, + "aggregation_type": "", + "aggregation_raw_type": "" }, { - "id": 43687, - "field_id": 705243, - "hidden": true, - "order": 10 - }, - { - "id": 43688, - "field_id": 705244, - "hidden": true, - "order": 11 - }, - { - "id": 43689, - "field_id": 705245, - "hidden": true, - "order": 12 - }, - { - "id": 43690, - "field_id": 705246, + "id": 261718, + "field_id": 59851, + "width": 155, "hidden": false, - "order": 13 + "order": 5, + "aggregation_type": "", + "aggregation_raw_type": "" }, { - "id": 43691, - "field_id": 705247, - "hidden": true, - "order": 14 + "id": 261719, + "field_id": 59852, + "width": 200, + "hidden": false, + "order": 6, + "aggregation_type": "", + "aggregation_raw_type": "" }, { - "id": 43692, - "field_id": 725741, - "hidden": true, - "order": 15 + "id": 261720, + "field_id": 59782, + "width": 148, + "hidden": false, + "order": 7, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261721, + "field_id": 59783, + "width": 175, + "hidden": false, + "order": 8, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261722, + "field_id": 59789, + "width": 200, + "hidden": false, + "order": 9, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261723, + "field_id": 59865, + "width": 171, + "hidden": false, + "order": 10, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261724, + "field_id": 59784, + "width": 139, + "hidden": false, + "order": 11, + "aggregation_type": "sum", + "aggregation_raw_type": "sum" + }, + { + "id": 261725, + "field_id": 59869, + "width": 200, + "hidden": false, + "order": 12, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261726, + "field_id": 59785, + "width": 147, + "hidden": false, + "order": 13, + "aggregation_type": "not_empty_percentage", + "aggregation_raw_type": "empty_count" + }, + { + "id": 261727, + "field_id": 59786, + "width": 149, + "hidden": false, + "order": 14, + "aggregation_type": "not_empty_percentage", + "aggregation_raw_type": "empty_count" + }, + { + "id": 261728, + "field_id": 59787, + "width": 180, + "hidden": false, + "order": 15, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261729, + "field_id": 59788, + "width": 200, + "hidden": false, + "order": 16, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261730, + "field_id": 59790, + "width": 200, + "hidden": false, + "order": 17, + "aggregation_type": "", + "aggregation_raw_type": "" } ] }, { - "id": 174149, - "type": "kanban", - "name": "By transmission", + "id": 26482, + "type": "grid", + "name": "Accepted offers", "order": 5, + "ownership_type": "collaborative", + "owned_by": null, "filter_type": "AND", "filters_disabled": false, - "filters": [], - "sortings": [], - "decorations": [], - "public": false, - "single_select_field_id": 705240, - "card_cover_image_field_id": 705228, - "field_options": [ + "filters": [ { - "id": 43693, - "field_id": 733934, - "hidden": false, + "id": 13974, + "field_id": 59790, + "type": "single_select_equal", + "value": "21058", + "group": null + } + ], + "filter_groups": [], + "sortings": [ + { + "id": 20383, + "field_id": 59783, + "order": "ASC" + } + ], + "group_bys": [], + "decorations": [ + { + "id": 8746, + "type": "left_border_color", + "value_provider_type": "single_select_color", + "value_provider_conf": { + "field_id": 59790 + }, "order": 1 }, { - "id": 43694, - "field_id": 705226, - "hidden": false, + "id": 8747, + "type": "background_color", + "value_provider_type": "conditional_color", + "value_provider_conf": { + "colors": [ + { + "id": "77aefcee-0c1d-4338-a857-5835055c3cd9", + "color": "light-red", + "filters": [ + { + "id": "31942597-f5fc-4ed1-bf41-424eee0b8270", + "type": "single_select_equal", + "field": 59790, + "group": null, + "value": "21060" + }, + { + "id": "4705601f-2f7f-4c16-9a95-072538d9d873", + "type": "lower_than", + "field": 59869, + "group": null, + "value": "0" + } + ], + "operator": "AND" + }, + { + "id": "279e3abc-9176-446f-9992-7121923b1a9e", + "color": "light-green", + "filters": [ + { + "id": "d3c184d2-c34f-4ff0-af85-7dd2cc650460", + "type": "single_select_equal", + "field": 59790, + "group": null, + "value": "21060" + }, + { + "id": "376837b5-828c-41b9-a700-df5a9df001eb", + "type": "higher_than_or_equal", + "field": 59869, + "group": null, + "value": "0" + } + ], + "operator": "AND" + } + ] + }, "order": 2 - }, + } + ], + "public": false, + "row_identifier_type": "count", + "row_height_size": "small", + "field_options": [ { - "id": 43695, - "field_id": 705227, + "id": 261731, + "field_id": 59780, + "width": 100, "hidden": false, - "order": 3 + "order": 0, + "aggregation_type": "unique_count", + "aggregation_raw_type": "unique_count" }, { - "id": 43696, - "field_id": 705228, - "hidden": true, - "order": 4 - }, - { - "id": 43697, - "field_id": 705238, + "id": 261732, + "field_id": 59781, + "width": 133, "hidden": false, - "order": 5 + "order": 1, + "aggregation_type": "not_empty_percentage", + "aggregation_raw_type": "empty_count" }, { - "id": 43698, - "field_id": 705239, - "hidden": true, - "order": 6 - }, - { - "id": 43699, - "field_id": 705240, - "hidden": true, - "order": 7 - }, - { - "id": 43700, - "field_id": 705241, + "id": 261733, + "field_id": 59863, + "width": 114, "hidden": false, - "order": 8 + "order": 3, + "aggregation_type": "", + "aggregation_raw_type": "" }, { - "id": 43701, - "field_id": 705242, + "id": 261734, + "field_id": 59850, + "width": 166, "hidden": false, - "order": 9 + "order": 4, + "aggregation_type": "", + "aggregation_raw_type": "" }, { - "id": 43702, - "field_id": 705243, - "hidden": true, - "order": 10 - }, - { - "id": 43703, - "field_id": 705244, - "hidden": true, - "order": 11 - }, - { - "id": 43704, - "field_id": 705245, - "hidden": true, - "order": 12 - }, - { - "id": 43705, - "field_id": 705246, + "id": 261735, + "field_id": 59864, + "width": 100, "hidden": false, - "order": 13 + "order": 5, + "aggregation_type": "", + "aggregation_raw_type": "" }, { - "id": 43706, - "field_id": 705247, - "hidden": true, - "order": 14 + "id": 261736, + "field_id": 59851, + "width": 155, + "hidden": false, + "order": 6, + "aggregation_type": "", + "aggregation_raw_type": "" }, { - "id": 43707, - "field_id": 725741, + "id": 261737, + "field_id": 59852, + "width": 200, + "hidden": false, + "order": 7, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261738, + "field_id": 59782, + "width": 148, + "hidden": false, + "order": 8, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261739, + "field_id": 59783, + "width": 175, + "hidden": false, + "order": 9, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261740, + "field_id": 59789, + "width": 200, + "hidden": false, + "order": 10, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261741, + "field_id": 59865, + "width": 171, + "hidden": false, + "order": 11, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261742, + "field_id": 59784, + "width": 139, + "hidden": false, + "order": 12, + "aggregation_type": "sum", + "aggregation_raw_type": "sum" + }, + { + "id": 261743, + "field_id": 59869, + "width": 200, + "hidden": false, + "order": 13, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261744, + "field_id": 59785, + "width": 147, + "hidden": false, + "order": 14, + "aggregation_type": "not_empty_percentage", + "aggregation_raw_type": "empty_count" + }, + { + "id": 261745, + "field_id": 59786, + "width": 149, + "hidden": false, + "order": 15, + "aggregation_type": "not_empty_percentage", + "aggregation_raw_type": "empty_count" + }, + { + "id": 261746, + "field_id": 59787, + "width": 180, + "hidden": false, + "order": 16, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261747, + "field_id": 59788, + "width": 200, + "hidden": false, + "order": 17, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261748, + "field_id": 59790, + "width": 200, + "hidden": false, + "order": 18, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261749, + "field_id": 59853, + "width": 200, "hidden": true, - "order": 15 + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" } ] }, { - "id": 174150, - "type": "kanban", - "name": "By fuel type", + "id": 26483, + "type": "grid", + "name": "Not accepted (yet) offers", "order": 6, + "ownership_type": "collaborative", + "owned_by": null, "filter_type": "AND", "filters_disabled": false, - "filters": [], - "sortings": [], - "decorations": [], - "public": false, - "single_select_field_id": 705241, - "card_cover_image_field_id": 705228, - "field_options": [ + "filters": [ { - "id": 43708, - "field_id": 733934, - "hidden": false, + "id": 13975, + "field_id": 59790, + "type": "single_select_not_equal", + "value": "21058", + "group": null + } + ], + "filter_groups": [], + "sortings": [ + { + "id": 20384, + "field_id": 59783, + "order": "ASC" + } + ], + "group_bys": [], + "decorations": [ + { + "id": 8748, + "type": "left_border_color", + "value_provider_type": "single_select_color", + "value_provider_conf": { + "field_id": 59790 + }, "order": 1 }, { - "id": 43709, - "field_id": 705226, - "hidden": false, + "id": 8749, + "type": "background_color", + "value_provider_type": "conditional_color", + "value_provider_conf": { + "colors": [ + { + "id": "77aefcee-0c1d-4338-a857-5835055c3cd9", + "color": "light-red", + "filters": [ + { + "id": "31942597-f5fc-4ed1-bf41-424eee0b8270", + "type": "single_select_equal", + "field": 59790, + "group": null, + "value": "21060" + }, + { + "id": "4705601f-2f7f-4c16-9a95-072538d9d873", + "type": "lower_than", + "field": 59869, + "group": null, + "value": "0" + } + ], + "operator": "AND" + }, + { + "id": "279e3abc-9176-446f-9992-7121923b1a9e", + "color": "light-green", + "filters": [ + { + "id": "d3c184d2-c34f-4ff0-af85-7dd2cc650460", + "type": "single_select_equal", + "field": 59790, + "group": null, + "value": "21060" + }, + { + "id": "376837b5-828c-41b9-a700-df5a9df001eb", + "type": "higher_than_or_equal", + "field": 59869, + "group": null, + "value": "0" + } + ], + "operator": "AND" + } + ] + }, "order": 2 - }, + } + ], + "public": false, + "row_identifier_type": "count", + "row_height_size": "small", + "field_options": [ { - "id": 43710, - "field_id": 705227, + "id": 261750, + "field_id": 59780, + "width": 100, "hidden": false, - "order": 3 + "order": 0, + "aggregation_type": "unique_count", + "aggregation_raw_type": "unique_count" }, { - "id": 43711, - "field_id": 705228, - "hidden": true, - "order": 4 - }, - { - "id": 43712, - "field_id": 705238, + "id": 261751, + "field_id": 59781, + "width": 133, "hidden": false, - "order": 5 + "order": 1, + "aggregation_type": "not_empty_percentage", + "aggregation_raw_type": "empty_count" }, { - "id": 43713, - "field_id": 705239, - "hidden": true, - "order": 6 - }, - { - "id": 43714, - "field_id": 705240, + "id": 261752, + "field_id": 59863, + "width": 114, "hidden": false, - "order": 7 + "order": 3, + "aggregation_type": "", + "aggregation_raw_type": "" }, { - "id": 43715, - "field_id": 705241, - "hidden": true, - "order": 8 - }, - { - "id": 43716, - "field_id": 705242, + "id": 261753, + "field_id": 59850, + "width": 166, "hidden": false, - "order": 9 + "order": 4, + "aggregation_type": "", + "aggregation_raw_type": "" }, { - "id": 43717, - "field_id": 705243, - "hidden": true, - "order": 10 - }, - { - "id": 43718, - "field_id": 705244, - "hidden": true, - "order": 11 - }, - { - "id": 43719, - "field_id": 705245, - "hidden": true, - "order": 12 - }, - { - "id": 43720, - "field_id": 705246, + "id": 261754, + "field_id": 59864, + "width": 100, "hidden": false, - "order": 13 + "order": 5, + "aggregation_type": "", + "aggregation_raw_type": "" }, { - "id": 43721, - "field_id": 705247, - "hidden": true, - "order": 14 + "id": 261755, + "field_id": 59851, + "width": 155, + "hidden": false, + "order": 6, + "aggregation_type": "", + "aggregation_raw_type": "" }, { - "id": 43722, - "field_id": 725741, + "id": 261756, + "field_id": 59852, + "width": 200, + "hidden": false, + "order": 7, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261757, + "field_id": 59782, + "width": 148, + "hidden": false, + "order": 8, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261758, + "field_id": 59783, + "width": 175, + "hidden": false, + "order": 9, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261759, + "field_id": 59789, + "width": 200, + "hidden": false, + "order": 10, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261760, + "field_id": 59865, + "width": 171, + "hidden": false, + "order": 11, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261761, + "field_id": 59784, + "width": 139, + "hidden": false, + "order": 12, + "aggregation_type": "sum", + "aggregation_raw_type": "sum" + }, + { + "id": 261762, + "field_id": 59869, + "width": 200, + "hidden": false, + "order": 13, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261763, + "field_id": 59785, + "width": 147, + "hidden": false, + "order": 14, + "aggregation_type": "not_empty_percentage", + "aggregation_raw_type": "empty_count" + }, + { + "id": 261764, + "field_id": 59786, + "width": 149, + "hidden": false, + "order": 15, + "aggregation_type": "not_empty_percentage", + "aggregation_raw_type": "empty_count" + }, + { + "id": 261765, + "field_id": 59787, + "width": 180, + "hidden": false, + "order": 16, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261766, + "field_id": 59788, + "width": 200, + "hidden": false, + "order": 17, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261767, + "field_id": 59790, + "width": 200, + "hidden": false, + "order": 18, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261768, + "field_id": 59853, + "width": 200, "hidden": true, - "order": 15 + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" } ] - } - ], - "rows": [ - { - "id": 1, - "order": "1.00000000000000000000", - "created_on": "2022-11-02T13:06:50.953041+00:00", - "updated_on": "2022-11-19T20:42:56.382439+00:00", - "field_705226": "Hilux Conquest 4x4", - "field_705227": 295678, - "field_705228": [ - { - "name": "irjn6egUzys9nLZUb14LKqExOqHLdslg_ca313dee2900ed76a0a5b361a3d81ed1bf4db348099559d7bae030f9c7889e13.jpg", - "visible_name": "W.Toyota.HiluxConquest4x4.EmotionalRed.jpg", - "original_name": "W.Toyota.HiluxConquest4x4.EmotionalRed.jpg" - }, - { - "name": "dglyGAl0LDfRQLU1TWZrEetm1Ys6YA1o_463242210ca93e61cc3fcade96df10c494cf1e3c17738fc861eb23d016f16dd3.jpg", - "visible_name": "W.Toyota.HiluxConquest4x4.SilverMetallic3.jpg", - "original_name": "W.Toyota.HiluxConquest4x4.SilverMetallic3.jpg" - } - ], - "field_705238": 295689, - "field_705239": "2.80", - "field_705240": 295691, - "field_705241": 295695, - "field_705242": "5", - "field_705243": "5325.00", - "field_705244": "1900.00", - "field_705245": "1845.00", - "field_705246": null, - "field_705247": null, - "field_725741": [ - 1, - 2 - ], - "field_733934": "2021" }, { - "id": 2, - "order": "2.00000000000000000000", - "created_on": "2022-11-02T13:06:50.953123+00:00", - "updated_on": "2022-11-19T20:43:03.290347+00:00", - "field_705226": "Hilux E 4x2", - "field_705227": 295678, - "field_705228": [ - { - "name": "epE6B1tyObEx1UtSu60jXKPMDGqsGoAK_00cd9281d06e88536f994eaecd27abc2892dc4b598b2fe57e89045e395084cb0.jpg", - "visible_name": "W.Toyota.HiluxE4x2.SuperWhiteII.jpg", - "original_name": "W.Toyota.HiluxE4x2.SuperWhiteII.jpg" - } - ], - "field_705238": 295689, - "field_705239": "2.40", - "field_705240": 295693, - "field_705241": 295695, - "field_705242": "5", - "field_705243": "5325.00", - "field_705244": "1855.00", - "field_705245": "1815.00", - "field_705246": null, - "field_705247": null, - "field_725741": [ - 3 - ], - "field_733934": "2021" - }, - { - "id": 3, - "order": "3.00000000000000000000", - "created_on": "2022-11-14T17:10:24.965898+00:00", - "updated_on": "2022-11-19T20:43:26.468037+00:00", - "field_705226": "Wigo TRD S", - "field_705227": 295678, - "field_705228": [ - { - "name": "DAjGD02fGMzvteNEzrweQgZQgcfbyNuu_56a17da6477b2e7d836de89b1c5f1da16478bf8f25598e0ce43bf9b901631e51.jpg", - "visible_name": "W.Toyota.WigoVVT-iG.YellowSE.jpg", - "original_name": "W.Toyota.WigoVVT-iG.YellowSE.jpg" - }, - { - "name": "NR4031s1tRJCrL3QwUu6jbfhl4LvK0Cu_c182124d365de839c8dee6f907302e44ea6cec7c9e9d5166ffb5e3260432d702.jpg", - "visible_name": "W.Toyota.WigoVVT-iG.OrangeMetallic2.jpg", - "original_name": "W.Toyota.WigoVVT-iG.OrangeMetallic2.jpg" - } - ], - "field_705238": 295685, - "field_705239": "1.00", - "field_705240": 295691, - "field_705241": 295694, - "field_705242": "5", - "field_705243": "3700.00", - "field_705244": "1600.00", - "field_705245": "1520.00", - "field_705246": null, - "field_705247": null, - "field_725741": [ - 15, - 16 - ], - "field_733934": "2020" - }, - { - "id": 4, - "order": "4.00000000000000000000", - "created_on": "2022-11-14T17:12:57.270164+00:00", - "updated_on": "2022-11-19T20:43:49.817127+00:00", - "field_705226": "Wigo VVT-i G", - "field_705227": 295678, - "field_705228": [ - { - "name": "DncUbN9FUt1qyyNwSEOECsqNqlusFjAY_ea9b1bce8af01bf92b955937c170016aab6ee24390ba29d76b5fd34320837337.jpg", - "visible_name": "W.Toyota.WigoVVT-iG.SilverMetallic4.jpg", - "original_name": "W.Toyota.WigoVVT-iG.SilverMetallic4.jpg" - }, - { - "name": "rfXXhKZPvxdyMIfsMVHP4YAzHURVQNwU_a7455fa871b37d2fc2c62ea07e3a89144eaf794a35c8c274ef028cc470b7766b.jpg", - "visible_name": "W.Toyota.WigoVVT-iG.White2.jpg", - "original_name": "W.Toyota.WigoVVT-iG.White2.jpg" - }, - { - "name": "6DImsBPK7SiCR2EUeKo0LIReeHkrcgzi_7729717ff60436cf63ef1fb59b7070531edcb3257ca7c98f707f7540d856fd36.jpg", - "visible_name": "W.Toyota.WigoVVT-iG.Black2.jpg", - "original_name": "W.Toyota.WigoVVT-iG.Black2.jpg" - }, - { - "name": "Xx7YYy12ZOFGMd9nxgFNwGQfn1OJSmQT_1dbc8731469dd3cc6409718ae730bd2e0b4d0f23b44f2ddc5b9d842fc0292ae3.jpg", - "visible_name": "W.Toyota.WigoVVT-iG.GrayMetallic.jpg", - "original_name": "W.Toyota.WigoVVT-iG.GrayMetallic.jpg" - } - ], - "field_705238": 295685, - "field_705239": "1.00", - "field_705240": 295693, - "field_705241": 295694, - "field_705242": "5", - "field_705243": "3660.00", - "field_705244": "1600.00", - "field_705245": "1520.00", - "field_705246": null, - "field_705247": null, - "field_725741": [ - 11, - 12, - 13, - 14 - ], - "field_733934": "2020" - }, - { - "id": 5, - "order": "5.00000000000000000000", - "created_on": "2022-11-14T17:16:25.031648+00:00", - "updated_on": "2022-11-19T20:42:43.766729+00:00", - "field_705226": "Montero Sport GT 4WD", - "field_705227": 295666, - "field_705228": [ - { - "name": "2gCMbHn4LQJQcpz3ao42umGiAyCmaN4z_611f54e37c09e874e0d3de0fd22917d18d23a0818b983a92cee6117ff7170be6.jpg", - "visible_name": "W.Mitsubishi.MonteroSportGT4WD.WhiteDiamond.jpg", - "original_name": "W.Mitsubishi.MonteroSportGT4WD.WhiteDiamond.jpg" - } - ], - "field_705238": 295688, - "field_705239": "2.40", - "field_705240": 295691, - "field_705241": 295695, - "field_705242": "7", - "field_705243": "4825.00", - "field_705244": "1815.00", - "field_705245": "1835.00", - "field_705246": null, - "field_705247": null, - "field_725741": [ - 5, - 21 - ], - "field_733934": "2021" - }, - { - "id": 6, - "order": "6.00000000000000000000", - "created_on": "2022-11-14T17:16:26.330754+00:00", - "updated_on": "2022-11-19T20:42:35.530493+00:00", - "field_705226": "Montero Sport GLX 2WD", - "field_705227": 295666, - "field_705228": [ - { - "name": "CHaviagwFxUMc2LaHi5QYnFfaST9U1PS_d78d7df18c4caa44154c400abfbcc66d8e96d16b3cf1470bf1d192bbe9bb5b13.jpg", - "visible_name": "W.Mitsubishi.MonteroSportGLX2WD.MediumRedMica.jpg", - "original_name": "W.Mitsubishi.MonteroSportGLX2WD.MediumRedMica.jpg" - } - ], - "field_705238": 295688, - "field_705239": "2.40", - "field_705240": 295693, - "field_705241": 295695, - "field_705242": "7", - "field_705243": "4825.00", - "field_705244": "1815.00", - "field_705245": "1835.00", - "field_705246": null, - "field_705247": null, - "field_725741": [ - 4, - 22 - ], - "field_733934": "2021" - }, - { - "id": 7, - "order": "6.00000000000000000000", - "created_on": "2022-11-14T17:16:27.141475+00:00", - "updated_on": "2022-11-19T20:40:53.840779+00:00", - "field_705226": "BR-V S", - "field_705227": 295651, - "field_705228": [ - { - "name": "wsHrQq9WvWhB5nj7D6HEKk1VRSCIS0t3_0a27ed86416f028b55f7bf9b0d83eecc0758787fa5b5c6dcc4a570a68f892d54.jpg", - "visible_name": "W.Honda.BR-V.PassionRedPearl.jpg", - "original_name": "W.Honda.BR-V.PassionRedPearl.jpg" - }, - { - "name": "wXxMCR074v0Th1KxqyORHMQTnVCjYqL4_ffbcaa5898e351ea7647b2624c725132bf311134c6867010e56a3ebf04a3bd3b.jpg", - "visible_name": "W.Honda.BR-V.LunarSilverMetallic.jpg", - "original_name": "W.Honda.BR-V.LunarSilverMetallic.jpg" - }, - { - "name": "F7lp1BCAtag5mc3bHS5Lbtycd9akrfV7_278a4fe9762f86a26a72f1716d383e628970c28904fa9f177166d09a321450c9.jpg", - "visible_name": "W.Honda.BR-V.ModernSteelMetallic.jpg", - "original_name": "W.Honda.BR-V.ModernSteelMetallic.jpg" - }, - { - "name": "iehFICyK6FrPvGXsJwpNVWnEENVcrQtj_a4d2f742193e21749c1cf1520b67ca43f6d5e21a80b0cf127c21f046b44ab3a0.jpg", - "visible_name": "W.Honda.BR-V.PlatinumWhitePearl.jpg", - "original_name": "W.Honda.BR-V.PlatinumWhitePearl.jpg" - } - ], - "field_705238": 295686, - "field_705239": "1.50", - "field_705240": 295692, - "field_705241": 295694, - "field_705242": "7", - "field_705243": "4456.00", - "field_705244": "1735.00", - "field_705245": "1677.00", - "field_705246": null, - "field_705247": null, - "field_725741": [ - 8, - 9, - 17, - 18, - 19, - 25 - ], - "field_733934": "2017" - }, - { - "id": 8, - "order": "7.00000000000000000000", - "created_on": "2022-11-14T17:29:50.141041+00:00", - "updated_on": "2022-11-19T20:41:29.511573+00:00", - "field_705226": "BR-V V", - "field_705227": 295651, - "field_705228": [ - { - "name": "wXxMCR074v0Th1KxqyORHMQTnVCjYqL4_ffbcaa5898e351ea7647b2624c725132bf311134c6867010e56a3ebf04a3bd3b.jpg", - "visible_name": "W.Honda.BR-V.LunarSilverMetallic.jpg", - "original_name": "W.Honda.BR-V.LunarSilverMetallic.jpg" - }, - { - "name": "F7lp1BCAtag5mc3bHS5Lbtycd9akrfV7_278a4fe9762f86a26a72f1716d383e628970c28904fa9f177166d09a321450c9.jpg", - "visible_name": "W.Honda.BR-V.ModernSteelMetallic.jpg", - "original_name": "W.Honda.BR-V.ModernSteelMetallic.jpg" - }, - { - "name": "wsHrQq9WvWhB5nj7D6HEKk1VRSCIS0t3_0a27ed86416f028b55f7bf9b0d83eecc0758787fa5b5c6dcc4a570a68f892d54.jpg", - "visible_name": "W.Honda.BR-V.PassionRedPearl.jpg", - "original_name": "W.Honda.BR-V.PassionRedPearl.jpg" - }, - { - "name": "iehFICyK6FrPvGXsJwpNVWnEENVcrQtj_a4d2f742193e21749c1cf1520b67ca43f6d5e21a80b0cf127c21f046b44ab3a0.jpg", - "visible_name": "W.Honda.BR-V.PlatinumWhitePearl.jpg", - "original_name": "W.Honda.BR-V.PlatinumWhitePearl.jpg" - } - ], - "field_705238": 295686, - "field_705239": "1.50", - "field_705240": 295692, - "field_705241": 295694, - "field_705242": "7", - "field_705243": "4456.00", - "field_705244": "1735.00", - "field_705245": "1677.00", - "field_705246": null, - "field_705247": null, - "field_725741": [ - 10, - 20, - 23, - 24 - ], - "field_733934": "2017" - }, - { - "id": 9, - "order": "7.00000000000000000000", - "created_on": "2022-11-14T17:29:50.849226+00:00", - "updated_on": "2022-11-19T20:41:56.336995+00:00", - "field_705226": "MX-5 Soft Top Skyactiv MT", - "field_705227": 295664, - "field_705228": [ - { - "name": "i8wAzE5UYXjson1zLqwGQGGedI9J0yvY_37c52f4247a412bac564abbffa4286a4e99f366d27f9184bfa72b6af8856ae93.jpg", - "visible_name": "W.Mazda.MX-5SoftTopSkyactiv.JetBlack.jpg", - "original_name": "W.Mazda.MX-5SoftTopSkyactiv.JetBlack.jpg" - } - ], - "field_705238": 295683, - "field_705239": "2.00", - "field_705240": 295693, - "field_705241": 295694, - "field_705242": "2", - "field_705243": "3915.00", - "field_705244": "1735.00", - "field_705245": "1230.00", - "field_705246": null, - "field_705247": null, - "field_725741": [ - 7 - ], - "field_733934": "2018" - }, - { - "id": 10, - "order": "7.00000000000000000000", - "created_on": "2022-11-14T17:29:51.589942+00:00", - "updated_on": "2022-11-19T20:41:49.093658+00:00", - "field_705226": "MX-5 Soft Top Skyactiv AT", - "field_705227": 295664, - "field_705228": [ - { - "name": "WoHEXVDD5kMb6hJmn14Pqtb7zpa5UgUc_83b50585af3ae83f658fae94afde8a098a5988d5114841936ae7f64cd72eacf5.jpg", - "visible_name": "W.Mazda.MX-5SoftTopSkyactiv.SoulRedCrystal.jpg", - "original_name": "W.Mazda.MX-5SoftTopSkyactiv.SoulRedCrystal.jpg" - } - ], - "field_705238": 295683, - "field_705239": "2.00", - "field_705240": 295691, - "field_705241": 295694, - "field_705242": "2", - "field_705243": "3915.00", - "field_705244": "1735.00", - "field_705245": "1230.00", - "field_705246": null, - "field_705247": null, - "field_725741": [ - 6 - ], - "field_733934": "2018" - } - ] - }, - { - "id": 114523, - "name": "Sales", - "order": 3, - "fields": [ - { - "id": 725837, - "type": "formula", - "name": "ID", - "order": 0, - "primary": true, - "error": null, - "date_format": null, - "date_include_time": null, - "date_time_format": null, - "number_decimal_places": null, - "array_formula_type": null, - "formula": "concat( \n \"S\", \n if( \n row_id() < 10, \n concat(\"0000\", row_id()), \n if( \n row_id() < 100, \n concat(\"000\", row_id()), \n if( \n row_id() < 1000, \n concat(\"00\", row_id()), \n if( \n row_id() < 10000, \n concat(\"0\", row_id()), \n row_id() \n ) \n ) \n ) \n ) \n)", - "formula_type": "text" - }, - { - "id": 725851, - "type": "link_row", - "name": "Car ID", - "order": 3, - "primary": false, - "link_row_table_id": 111551, - "link_row_related_field_id": 725750, - "has_related_field": true - }, - { - "id": 725877, - "type": "lookup", - "name": "Year", - "order": 4, - "primary": false, - "error": null, - "date_format": null, - "date_include_time": null, - "date_time_format": null, - "number_decimal_places": 0, - "array_formula_type": "number", - "through_field_id": 725851, - "through_field_name": "Car ID", - "target_field_id": 725743, - "target_field_name": "Year" - }, - { - "id": 725878, - "type": "lookup", - "name": "Make", - "order": 5, - "primary": false, - "error": null, - "date_format": null, - "date_include_time": null, - "date_time_format": null, - "number_decimal_places": null, - "array_formula_type": "single_select", - "through_field_id": 725851, - "through_field_name": "Car ID", - "target_field_id": 725742, - "target_field_name": "Make" - }, - { - "id": 725879, - "type": "lookup", - "name": "Model", - "order": 6, - "primary": false, - "error": null, - "date_format": null, - "date_include_time": null, - "date_time_format": null, - "number_decimal_places": null, - "array_formula_type": "text", - "through_field_id": 725851, - "through_field_name": "Car ID", - "target_field_id": 705225, - "target_field_name": "Model" - }, - { - "id": 725881, - "type": "lookup", - "name": "Color", + "id": 26484, + "type": "grid", + "name": "Offers under consideration", "order": 7, - "primary": false, - "error": null, - "date_format": null, - "date_include_time": null, - "date_time_format": null, - "number_decimal_places": null, - "array_formula_type": "text", - "through_field_id": 725851, - "through_field_name": "Car ID", - "target_field_id": 725747, - "target_field_name": "Color" + "ownership_type": "collaborative", + "owned_by": null, + "filter_type": "AND", + "filters_disabled": false, + "filters": [ + { + "id": 13976, + "field_id": 59790, + "type": "single_select_equal", + "value": "21060", + "group": null + } + ], + "filter_groups": [], + "sortings": [ + { + "id": 20385, + "field_id": 59783, + "order": "ASC" + } + ], + "group_bys": [], + "decorations": [ + { + "id": 8750, + "type": "left_border_color", + "value_provider_type": "single_select_color", + "value_provider_conf": { + "field_id": 59790 + }, + "order": 1 + }, + { + "id": 8751, + "type": "background_color", + "value_provider_type": "conditional_color", + "value_provider_conf": { + "colors": [ + { + "id": "77aefcee-0c1d-4338-a857-5835055c3cd9", + "color": "light-red", + "filters": [ + { + "id": "31942597-f5fc-4ed1-bf41-424eee0b8270", + "type": "single_select_equal", + "field": 59790, + "group": null, + "value": "21060" + }, + { + "id": "4705601f-2f7f-4c16-9a95-072538d9d873", + "type": "lower_than", + "field": 59869, + "group": null, + "value": "0" + } + ], + "operator": "AND" + }, + { + "id": "279e3abc-9176-446f-9992-7121923b1a9e", + "color": "light-green", + "filters": [ + { + "id": "d3c184d2-c34f-4ff0-af85-7dd2cc650460", + "type": "single_select_equal", + "field": 59790, + "group": null, + "value": "21060" + }, + { + "id": "376837b5-828c-41b9-a700-df5a9df001eb", + "type": "higher_than_or_equal", + "field": 59869, + "group": null, + "value": "0" + } + ], + "operator": "AND" + } + ] + }, + "order": 2 + } + ], + "public": false, + "row_identifier_type": "count", + "row_height_size": "small", + "field_options": [ + { + "id": 261769, + "field_id": 59780, + "width": 100, + "hidden": false, + "order": 0, + "aggregation_type": "unique_count", + "aggregation_raw_type": "unique_count" + }, + { + "id": 261770, + "field_id": 59781, + "width": 133, + "hidden": false, + "order": 1, + "aggregation_type": "not_empty_percentage", + "aggregation_raw_type": "empty_count" + }, + { + "id": 261771, + "field_id": 59863, + "width": 114, + "hidden": false, + "order": 3, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261772, + "field_id": 59850, + "width": 166, + "hidden": false, + "order": 4, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261773, + "field_id": 59864, + "width": 100, + "hidden": false, + "order": 5, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261774, + "field_id": 59851, + "width": 155, + "hidden": false, + "order": 6, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261775, + "field_id": 59852, + "width": 200, + "hidden": false, + "order": 7, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261776, + "field_id": 59782, + "width": 148, + "hidden": false, + "order": 8, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261777, + "field_id": 59783, + "width": 175, + "hidden": false, + "order": 9, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261778, + "field_id": 59789, + "width": 200, + "hidden": false, + "order": 10, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261779, + "field_id": 59865, + "width": 171, + "hidden": false, + "order": 11, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261780, + "field_id": 59784, + "width": 139, + "hidden": false, + "order": 12, + "aggregation_type": "sum", + "aggregation_raw_type": "sum" + }, + { + "id": 261781, + "field_id": 59869, + "width": 200, + "hidden": false, + "order": 13, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261782, + "field_id": 59785, + "width": 147, + "hidden": false, + "order": 14, + "aggregation_type": "not_empty_percentage", + "aggregation_raw_type": "empty_count" + }, + { + "id": 261783, + "field_id": 59786, + "width": 149, + "hidden": false, + "order": 15, + "aggregation_type": "not_empty_percentage", + "aggregation_raw_type": "empty_count" + }, + { + "id": 261784, + "field_id": 59787, + "width": 180, + "hidden": false, + "order": 16, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261785, + "field_id": 59788, + "width": 200, + "hidden": false, + "order": 17, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261786, + "field_id": 59790, + "width": 200, + "hidden": false, + "order": 18, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261787, + "field_id": 59853, + "width": 200, + "hidden": true, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + } + ] }, { - "id": 725883, - "type": "lookup", - "name": "Type", + "id": 26485, + "type": "grid", + "name": "Offers under consideration with offer > suggested", "order": 8, - "primary": false, - "error": null, - "date_format": null, - "date_include_time": null, - "date_time_format": null, - "number_decimal_places": null, - "array_formula_type": "single_select", - "through_field_id": 725851, - "through_field_name": "Car ID", - "target_field_id": 725744, - "target_field_name": "Type" - }, - { - "id": 725884, - "type": "lookup", - "name": "Plate number", - "order": 9, - "primary": false, - "error": null, - "date_format": null, - "date_include_time": null, - "date_time_format": null, - "number_decimal_places": null, - "array_formula_type": "text", - "through_field_id": 725851, - "through_field_name": "Car ID", - "target_field_id": 725755, - "target_field_name": "Plate number" - }, - { - "id": 725885, - "type": "lookup", - "name": "VIN", - "order": 10, - "primary": false, - "error": null, - "date_format": null, - "date_include_time": null, - "date_time_format": null, - "number_decimal_places": null, - "array_formula_type": "text", - "through_field_id": 725851, - "through_field_name": "Car ID", - "target_field_id": 725756, - "target_field_name": "VIN" - }, - { - "id": 725886, - "type": "lookup", - "name": "Branch sold", - "order": 11, - "primary": false, - "error": null, - "date_format": null, - "date_include_time": null, - "date_time_format": null, - "number_decimal_places": null, - "array_formula_type": "text", - "through_field_id": 725851, - "through_field_name": "Car ID", - "target_field_id": 725788, - "target_field_name": "Branch" - }, - { - "id": 725887, - "type": "date", - "name": "Date sold", - "order": 12, - "primary": false, - "date_format": "ISO", - "date_include_time": true, - "date_time_format": "24" - }, - { - "id": 725888, - "type": "date", - "name": "Date released", - "order": 13, - "primary": false, - "date_format": "ISO", - "date_include_time": true, - "date_time_format": "24" - }, - { - "id": 725889, - "type": "single_select", - "name": "Financing option", - "order": 14, - "primary": false, - "select_options": [ + "ownership_type": "collaborative", + "owned_by": null, + "filter_type": "AND", + "filters_disabled": false, + "filters": [ { - "id": 313894, - "value": "Full cash", - "color": "dark-blue", - "order": 0 + "id": 13977, + "field_id": 59790, + "type": "single_select_equal", + "value": "21060", + "group": null }, { - "id": 313895, - "value": "Full cheque", - "color": "blue", + "id": 13978, + "field_id": 59869, + "type": "higher_than_or_equal", + "value": "0", + "group": null + } + ], + "filter_groups": [], + "sortings": [ + { + "id": 20386, + "field_id": 59783, + "order": "ASC" + } + ], + "group_bys": [], + "decorations": [ + { + "id": 8752, + "type": "left_border_color", + "value_provider_type": "single_select_color", + "value_provider_conf": { + "field_id": 59790 + }, "order": 1 }, { - "id": 313896, - "value": "Full credit card", - "color": "light-blue", + "id": 8753, + "type": "background_color", + "value_provider_type": "conditional_color", + "value_provider_conf": { + "colors": [ + { + "id": "77aefcee-0c1d-4338-a857-5835055c3cd9", + "color": "light-red", + "filters": [ + { + "id": "31942597-f5fc-4ed1-bf41-424eee0b8270", + "type": "single_select_equal", + "field": 59790, + "group": null, + "value": "21060" + }, + { + "id": "4705601f-2f7f-4c16-9a95-072538d9d873", + "type": "lower_than", + "field": 59869, + "group": null, + "value": "0" + } + ], + "operator": "AND" + }, + { + "id": "279e3abc-9176-446f-9992-7121923b1a9e", + "color": "light-green", + "filters": [ + { + "id": "d3c184d2-c34f-4ff0-af85-7dd2cc650460", + "type": "single_select_equal", + "field": 59790, + "group": null, + "value": "21060" + }, + { + "id": "376837b5-828c-41b9-a700-df5a9df001eb", + "type": "higher_than_or_equal", + "field": 59869, + "group": null, + "value": "0" + } + ], + "operator": "AND" + } + ] + }, "order": 2 - }, - { - "id": 313897, - "value": "Bank loan", - "color": "green", - "order": 3 - }, - { - "id": 313898, - "value": "In-house financing", - "color": "dark-green", - "order": 4 - } - ] - }, - { - "id": 725890, - "type": "number", - "name": "Price sold", - "order": 15, - "primary": false, - "number_decimal_places": 2, - "number_negative": false - }, - { - "id": 725893, - "type": "link_row", - "name": "Customer", - "order": 16, - "primary": false, - "link_row_table_id": 114524, - "link_row_related_field_id": 725894, - "has_related_field": true - }, - { - "id": 725895, - "type": "formula", - "name": "Customer address", - "order": 17, - "primary": false, - "error": null, - "date_format": null, - "date_include_time": null, - "date_time_format": null, - "number_decimal_places": null, - "array_formula_type": "text", - "formula": "concat( \n lookup(\"Customer\", \"Street\"), \", \", \n lookup(\"Customer\", \"City\"), \", \", \n lookup(\"Customer\", \"State\"), \", \", \n lookup(\"Customer\", \"Zip code\") \n)", - "formula_type": "array" - }, - { - "id": 725896, - "type": "link_row", - "name": "Sold by", - "order": 18, - "primary": false, - "link_row_table_id": 114512, - "link_row_related_field_id": 725897, - "has_related_field": true - }, - { - "id": 725898, - "type": "file", - "name": "Transaction docs", - "order": 19, - "primary": false - }, - { - "id": 738834, - "type": "lookup", - "name": "Engine number", - "order": 20, - "primary": false, - "error": null, - "date_format": null, - "date_include_time": null, - "date_time_format": null, - "number_decimal_places": null, - "array_formula_type": "text", - "through_field_id": 725851, - "through_field_name": "Car ID", - "target_field_id": 738833, - "target_field_name": "Engine number" - }, - { - "id": 739115, - "type": "formula", - "name": "Branch for filtering", - "order": 21, - "primary": false, - "error": null, - "date_format": null, - "date_include_time": null, - "date_time_format": null, - "number_decimal_places": null, - "array_formula_type": null, - "formula": "join(totext(field(\"Branch sold\")), \"\")", - "formula_type": "text" - } - ], - "views": [ - { - "id": 170689, - "type": "grid", - "name": "All sales", - "order": 1, - "filter_type": "AND", - "filters_disabled": false, - "filters": [], - "sortings": [ - { - "id": 55273, - "field_id": 725887, - "order": "ASC" } ], - "decorations": [], "public": false, "row_identifier_type": "count", + "row_height_size": "small", "field_options": [ { - "id": 1041942, - "field_id": 725837, + "id": 261788, + "field_id": 59780, "width": 100, "hidden": false, "order": 0, @@ -7058,35 +11013,26 @@ "aggregation_raw_type": "unique_count" }, { - "id": 1041963, - "field_id": 725851, - "width": 100, + "id": 261789, + "field_id": 59781, + "width": 133, "hidden": false, "order": 1, "aggregation_type": "not_empty_percentage", "aggregation_raw_type": "empty_count" }, { - "id": 1041994, - "field_id": 725877, - "width": 100, - "hidden": false, - "order": 2, - "aggregation_type": "", - "aggregation_raw_type": "" - }, - { - "id": 1041995, - "field_id": 725878, - "width": 100, + "id": 261790, + "field_id": 59863, + "width": 114, "hidden": false, "order": 3, "aggregation_type": "", "aggregation_raw_type": "" }, { - "id": 1041996, - "field_id": 725879, + "id": 261791, + "field_id": 59850, "width": 166, "hidden": false, "order": 4, @@ -7094,171 +11040,237 @@ "aggregation_raw_type": "" }, { - "id": 1041998, - "field_id": 725881, - "width": 155, + "id": 261792, + "field_id": 59864, + "width": 100, "hidden": false, "order": 5, "aggregation_type": "", "aggregation_raw_type": "" }, { - "id": 1042000, - "field_id": 725883, - "width": 178, + "id": 261793, + "field_id": 59851, + "width": 155, "hidden": false, "order": 6, "aggregation_type": "", "aggregation_raw_type": "" }, { - "id": 1042001, - "field_id": 725884, - "width": 145, + "id": 261794, + "field_id": 59852, + "width": 200, "hidden": false, "order": 7, "aggregation_type": "", "aggregation_raw_type": "" }, { - "id": 1042002, - "field_id": 725885, - "width": 158, + "id": 261795, + "field_id": 59782, + "width": 148, "hidden": false, "order": 8, "aggregation_type": "", "aggregation_raw_type": "" }, { - "id": 1042003, - "field_id": 725886, - "width": 133, - "hidden": false, - "order": 10, - "aggregation_type": "", - "aggregation_raw_type": "" - }, - { - "id": 1042004, - "field_id": 725887, - "width": 148, - "hidden": false, - "order": 11, - "aggregation_type": "", - "aggregation_raw_type": "" - }, - { - "id": 1042005, - "field_id": 725888, - "width": 148, - "hidden": false, - "order": 12, - "aggregation_type": "", - "aggregation_raw_type": "" - }, - { - "id": 1042006, - "field_id": 725889, - "width": 163, - "hidden": false, - "order": 13, - "aggregation_type": "", - "aggregation_raw_type": "" - }, - { - "id": 1042007, - "field_id": 725890, - "width": 120, - "hidden": false, - "order": 14, - "aggregation_type": "sum", - "aggregation_raw_type": "sum" - }, - { - "id": 1042008, - "field_id": 725893, - "width": 126, - "hidden": false, - "order": 15, - "aggregation_type": "not_empty_percentage", - "aggregation_raw_type": "empty_count" - }, - { - "id": 1042009, - "field_id": 725895, - "width": 172, - "hidden": false, - "order": 16, - "aggregation_type": "", - "aggregation_raw_type": "" - }, - { - "id": 1042010, - "field_id": 725896, - "width": 149, - "hidden": false, - "order": 17, - "aggregation_type": "not_empty_percentage", - "aggregation_raw_type": "empty_count" - }, - { - "id": 1042012, - "field_id": 725898, - "width": 164, - "hidden": false, - "order": 18, - "aggregation_type": "", - "aggregation_raw_type": "" - }, - { - "id": 1063745, - "field_id": 738834, - "width": 155, + "id": 261796, + "field_id": 59783, + "width": 175, "hidden": false, "order": 9, "aggregation_type": "", "aggregation_raw_type": "" }, { - "id": 1064096, - "field_id": 739115, - "width": 176, - "hidden": true, - "order": 32767, + "id": 261797, + "field_id": 59789, + "width": 200, + "hidden": false, + "order": 10, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261798, + "field_id": 59865, + "width": 171, + "hidden": false, + "order": 11, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261799, + "field_id": 59784, + "width": 139, + "hidden": false, + "order": 12, + "aggregation_type": "sum", + "aggregation_raw_type": "sum" + }, + { + "id": 261800, + "field_id": 59869, + "width": 200, + "hidden": false, + "order": 13, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261801, + "field_id": 59785, + "width": 147, + "hidden": false, + "order": 14, + "aggregation_type": "not_empty_percentage", + "aggregation_raw_type": "empty_count" + }, + { + "id": 261802, + "field_id": 59786, + "width": 149, + "hidden": false, + "order": 15, + "aggregation_type": "not_empty_percentage", + "aggregation_raw_type": "empty_count" + }, + { + "id": 261803, + "field_id": 59787, + "width": 180, + "hidden": false, + "order": 16, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261804, + "field_id": 59788, + "width": 200, + "hidden": false, + "order": 17, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261805, + "field_id": 59790, + "width": 200, + "hidden": false, + "order": 18, "aggregation_type": "", "aggregation_raw_type": "" } ] }, { - "id": 174154, + "id": 26486, "type": "grid", - "name": "Sales in CD Fremont", - "order": 2, + "name": "Offers under consideration with offer < suggested", + "order": 9, + "ownership_type": "collaborative", + "owned_by": null, "filter_type": "AND", "filters_disabled": false, "filters": [ { - "id": 68751, - "field_id": 739115, - "type": "equal", - "value": "CD Fremont" + "id": 13979, + "field_id": 59790, + "type": "single_select_equal", + "value": "21060", + "group": null + }, + { + "id": 13980, + "field_id": 59869, + "type": "lower_than", + "value": "0", + "group": null } ], + "filter_groups": [], "sortings": [ { - "id": 53173, - "field_id": 725887, + "id": 20387, + "field_id": 59783, "order": "ASC" } ], - "decorations": [], + "group_bys": [], + "decorations": [ + { + "id": 8754, + "type": "left_border_color", + "value_provider_type": "single_select_color", + "value_provider_conf": { + "field_id": 59790 + }, + "order": 1 + }, + { + "id": 8755, + "type": "background_color", + "value_provider_type": "conditional_color", + "value_provider_conf": { + "colors": [ + { + "id": "77aefcee-0c1d-4338-a857-5835055c3cd9", + "color": "light-red", + "filters": [ + { + "id": "31942597-f5fc-4ed1-bf41-424eee0b8270", + "type": "single_select_equal", + "field": 59790, + "group": null, + "value": "21060" + }, + { + "id": "4705601f-2f7f-4c16-9a95-072538d9d873", + "type": "lower_than", + "field": 59869, + "group": null, + "value": "0" + } + ], + "operator": "AND" + }, + { + "id": "279e3abc-9176-446f-9992-7121923b1a9e", + "color": "light-green", + "filters": [ + { + "id": "d3c184d2-c34f-4ff0-af85-7dd2cc650460", + "type": "single_select_equal", + "field": 59790, + "group": null, + "value": "21060" + }, + { + "id": "376837b5-828c-41b9-a700-df5a9df001eb", + "type": "higher_than_or_equal", + "field": 59869, + "group": null, + "value": "0" + } + ], + "operator": "AND" + } + ] + }, + "order": 2 + } + ], "public": false, "row_identifier_type": "count", + "row_height_size": "small", "field_options": [ { - "id": 1064100, - "field_id": 725837, + "id": 261806, + "field_id": 59780, "width": 100, "hidden": false, "order": 0, @@ -7266,35 +11278,26 @@ "aggregation_raw_type": "unique_count" }, { - "id": 1064101, - "field_id": 725851, - "width": 100, + "id": 261807, + "field_id": 59781, + "width": 133, "hidden": false, "order": 1, "aggregation_type": "not_empty_percentage", "aggregation_raw_type": "empty_count" }, { - "id": 1064102, - "field_id": 725877, - "width": 100, - "hidden": false, - "order": 2, - "aggregation_type": "", - "aggregation_raw_type": "" - }, - { - "id": 1064103, - "field_id": 725878, - "width": 100, + "id": 261808, + "field_id": 59863, + "width": 114, "hidden": false, "order": 3, "aggregation_type": "", "aggregation_raw_type": "" }, { - "id": 1064104, - "field_id": 725879, + "id": 261809, + "field_id": 59850, "width": 166, "hidden": false, "order": 4, @@ -7302,171 +11305,230 @@ "aggregation_raw_type": "" }, { - "id": 1064105, - "field_id": 725881, - "width": 155, + "id": 261810, + "field_id": 59864, + "width": 100, "hidden": false, "order": 5, "aggregation_type": "", "aggregation_raw_type": "" }, { - "id": 1064106, - "field_id": 725883, - "width": 178, + "id": 261811, + "field_id": 59851, + "width": 155, "hidden": false, "order": 6, "aggregation_type": "", "aggregation_raw_type": "" }, { - "id": 1064107, - "field_id": 725884, - "width": 145, + "id": 261812, + "field_id": 59852, + "width": 200, "hidden": false, "order": 7, "aggregation_type": "", "aggregation_raw_type": "" }, { - "id": 1064108, - "field_id": 725885, - "width": 158, + "id": 261813, + "field_id": 59782, + "width": 148, "hidden": false, "order": 8, "aggregation_type": "", "aggregation_raw_type": "" }, { - "id": 1064109, - "field_id": 725886, - "width": 133, - "hidden": false, - "order": 10, - "aggregation_type": "", - "aggregation_raw_type": "" - }, - { - "id": 1064110, - "field_id": 725887, - "width": 148, - "hidden": false, - "order": 11, - "aggregation_type": "", - "aggregation_raw_type": "" - }, - { - "id": 1064111, - "field_id": 725888, - "width": 148, - "hidden": false, - "order": 12, - "aggregation_type": "", - "aggregation_raw_type": "" - }, - { - "id": 1064112, - "field_id": 725889, - "width": 163, - "hidden": false, - "order": 13, - "aggregation_type": "", - "aggregation_raw_type": "" - }, - { - "id": 1064113, - "field_id": 725890, - "width": 120, - "hidden": false, - "order": 14, - "aggregation_type": "sum", - "aggregation_raw_type": "sum" - }, - { - "id": 1064114, - "field_id": 725893, - "width": 126, - "hidden": false, - "order": 15, - "aggregation_type": "not_empty_percentage", - "aggregation_raw_type": "empty_count" - }, - { - "id": 1064115, - "field_id": 725895, - "width": 172, - "hidden": false, - "order": 16, - "aggregation_type": "", - "aggregation_raw_type": "" - }, - { - "id": 1064116, - "field_id": 725896, - "width": 149, - "hidden": false, - "order": 17, - "aggregation_type": "not_empty_percentage", - "aggregation_raw_type": "empty_count" - }, - { - "id": 1064117, - "field_id": 725898, - "width": 164, - "hidden": false, - "order": 18, - "aggregation_type": "", - "aggregation_raw_type": "" - }, - { - "id": 1064118, - "field_id": 738834, - "width": 155, + "id": 261814, + "field_id": 59783, + "width": 175, "hidden": false, "order": 9, "aggregation_type": "", "aggregation_raw_type": "" }, { - "id": 1064119, - "field_id": 739115, - "width": 176, - "hidden": true, - "order": 32767, + "id": 261815, + "field_id": 59789, + "width": 200, + "hidden": false, + "order": 10, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261816, + "field_id": 59865, + "width": 171, + "hidden": false, + "order": 11, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261817, + "field_id": 59784, + "width": 139, + "hidden": false, + "order": 12, + "aggregation_type": "sum", + "aggregation_raw_type": "sum" + }, + { + "id": 261818, + "field_id": 59869, + "width": 200, + "hidden": false, + "order": 13, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261819, + "field_id": 59785, + "width": 147, + "hidden": false, + "order": 14, + "aggregation_type": "not_empty_percentage", + "aggregation_raw_type": "empty_count" + }, + { + "id": 261820, + "field_id": 59786, + "width": 149, + "hidden": false, + "order": 15, + "aggregation_type": "not_empty_percentage", + "aggregation_raw_type": "empty_count" + }, + { + "id": 261821, + "field_id": 59787, + "width": 180, + "hidden": false, + "order": 16, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261822, + "field_id": 59788, + "width": 200, + "hidden": false, + "order": 17, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261823, + "field_id": 59790, + "width": 200, + "hidden": false, + "order": 18, "aggregation_type": "", "aggregation_raw_type": "" } ] }, { - "id": 174155, + "id": 26487, "type": "grid", - "name": "Sales in CD La Mesa", - "order": 3, + "name": "Rejected offers", + "order": 10, + "ownership_type": "collaborative", + "owned_by": null, "filter_type": "AND", "filters_disabled": false, "filters": [ { - "id": 68752, - "field_id": 739115, - "type": "equal", - "value": "CD La Mesa" + "id": 13981, + "field_id": 59790, + "type": "single_select_equal", + "value": "21059", + "group": null } ], + "filter_groups": [], "sortings": [ { - "id": 53174, - "field_id": 725887, + "id": 20388, + "field_id": 59783, "order": "ASC" } ], - "decorations": [], + "group_bys": [], + "decorations": [ + { + "id": 8756, + "type": "left_border_color", + "value_provider_type": "single_select_color", + "value_provider_conf": { + "field_id": 59790 + }, + "order": 1 + }, + { + "id": 8757, + "type": "background_color", + "value_provider_type": "conditional_color", + "value_provider_conf": { + "colors": [ + { + "id": "77aefcee-0c1d-4338-a857-5835055c3cd9", + "color": "light-red", + "filters": [ + { + "id": "31942597-f5fc-4ed1-bf41-424eee0b8270", + "type": "single_select_equal", + "field": 59790, + "group": null, + "value": "21060" + }, + { + "id": "4705601f-2f7f-4c16-9a95-072538d9d873", + "type": "lower_than", + "field": 59869, + "group": null, + "value": "0" + } + ], + "operator": "AND" + }, + { + "id": "279e3abc-9176-446f-9992-7121923b1a9e", + "color": "light-green", + "filters": [ + { + "id": "d3c184d2-c34f-4ff0-af85-7dd2cc650460", + "type": "single_select_equal", + "field": 59790, + "group": null, + "value": "21060" + }, + { + "id": "376837b5-828c-41b9-a700-df5a9df001eb", + "type": "higher_than_or_equal", + "field": 59869, + "group": null, + "value": "0" + } + ], + "operator": "AND" + } + ] + }, + "order": 2 + } + ], "public": false, "row_identifier_type": "count", + "row_height_size": "small", "field_options": [ { - "id": 1064120, - "field_id": 725837, + "id": 261824, + "field_id": 59780, "width": 100, "hidden": false, "order": 0, @@ -7474,35 +11536,26 @@ "aggregation_raw_type": "unique_count" }, { - "id": 1064121, - "field_id": 725851, - "width": 100, + "id": 261825, + "field_id": 59781, + "width": 133, "hidden": false, "order": 1, "aggregation_type": "not_empty_percentage", "aggregation_raw_type": "empty_count" }, { - "id": 1064122, - "field_id": 725877, - "width": 100, - "hidden": false, - "order": 2, - "aggregation_type": "", - "aggregation_raw_type": "" - }, - { - "id": 1064123, - "field_id": 725878, - "width": 100, + "id": 261826, + "field_id": 59863, + "width": 114, "hidden": false, "order": 3, "aggregation_type": "", "aggregation_raw_type": "" }, { - "id": 1064124, - "field_id": 725879, + "id": 261827, + "field_id": 59850, "width": 166, "hidden": false, "order": 4, @@ -7510,135 +11563,135 @@ "aggregation_raw_type": "" }, { - "id": 1064125, - "field_id": 725881, - "width": 155, + "id": 261828, + "field_id": 59864, + "width": 100, "hidden": false, "order": 5, "aggregation_type": "", "aggregation_raw_type": "" }, { - "id": 1064126, - "field_id": 725883, - "width": 178, + "id": 261829, + "field_id": 59851, + "width": 155, "hidden": false, "order": 6, "aggregation_type": "", "aggregation_raw_type": "" }, { - "id": 1064127, - "field_id": 725884, - "width": 145, + "id": 261830, + "field_id": 59852, + "width": 200, "hidden": false, "order": 7, "aggregation_type": "", "aggregation_raw_type": "" }, { - "id": 1064128, - "field_id": 725885, - "width": 158, + "id": 261831, + "field_id": 59782, + "width": 148, "hidden": false, "order": 8, "aggregation_type": "", "aggregation_raw_type": "" }, { - "id": 1064129, - "field_id": 725886, - "width": 133, - "hidden": false, - "order": 10, - "aggregation_type": "", - "aggregation_raw_type": "" - }, - { - "id": 1064130, - "field_id": 725887, - "width": 148, - "hidden": false, - "order": 11, - "aggregation_type": "", - "aggregation_raw_type": "" - }, - { - "id": 1064131, - "field_id": 725888, - "width": 148, - "hidden": false, - "order": 12, - "aggregation_type": "", - "aggregation_raw_type": "" - }, - { - "id": 1064132, - "field_id": 725889, - "width": 163, - "hidden": false, - "order": 13, - "aggregation_type": "", - "aggregation_raw_type": "" - }, - { - "id": 1064133, - "field_id": 725890, - "width": 120, - "hidden": false, - "order": 14, - "aggregation_type": "sum", - "aggregation_raw_type": "sum" - }, - { - "id": 1064134, - "field_id": 725893, - "width": 126, - "hidden": false, - "order": 15, - "aggregation_type": "not_empty_percentage", - "aggregation_raw_type": "empty_count" - }, - { - "id": 1064135, - "field_id": 725895, - "width": 172, - "hidden": false, - "order": 16, - "aggregation_type": "", - "aggregation_raw_type": "" - }, - { - "id": 1064136, - "field_id": 725896, - "width": 149, - "hidden": false, - "order": 17, - "aggregation_type": "not_empty_percentage", - "aggregation_raw_type": "empty_count" - }, - { - "id": 1064137, - "field_id": 725898, - "width": 164, - "hidden": false, - "order": 18, - "aggregation_type": "", - "aggregation_raw_type": "" - }, - { - "id": 1064138, - "field_id": 738834, - "width": 155, + "id": 261832, + "field_id": 59783, + "width": 175, "hidden": false, "order": 9, "aggregation_type": "", "aggregation_raw_type": "" }, { - "id": 1064139, - "field_id": 739115, - "width": 176, + "id": 261833, + "field_id": 59789, + "width": 200, + "hidden": false, + "order": 10, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261834, + "field_id": 59865, + "width": 171, + "hidden": false, + "order": 11, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261835, + "field_id": 59784, + "width": 139, + "hidden": false, + "order": 12, + "aggregation_type": "sum", + "aggregation_raw_type": "sum" + }, + { + "id": 261836, + "field_id": 59869, + "width": 200, + "hidden": false, + "order": 13, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261837, + "field_id": 59785, + "width": 147, + "hidden": false, + "order": 14, + "aggregation_type": "not_empty_percentage", + "aggregation_raw_type": "empty_count" + }, + { + "id": 261838, + "field_id": 59786, + "width": 149, + "hidden": false, + "order": 15, + "aggregation_type": "not_empty_percentage", + "aggregation_raw_type": "empty_count" + }, + { + "id": 261839, + "field_id": 59787, + "width": 180, + "hidden": false, + "order": 16, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261840, + "field_id": 59788, + "width": 200, + "hidden": false, + "order": 17, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261841, + "field_id": 59790, + "width": 200, + "hidden": false, + "order": 18, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261842, + "field_id": 59853, + "width": 200, "hidden": true, "order": 32767, "aggregation_type": "", @@ -7647,813 +11700,128 @@ ] }, { - "id": 174158, - "type": "grid", - "name": "Sales in CD Pomona", - "order": 4, - "filter_type": "AND", - "filters_disabled": false, - "filters": [ - { - "id": 68753, - "field_id": 739115, - "type": "equal", - "value": "CD Pomona" - } - ], - "sortings": [ - { - "id": 53175, - "field_id": 725887, - "order": "ASC" - } - ], - "decorations": [], - "public": false, - "row_identifier_type": "count", - "field_options": [ - { - "id": 1064143, - "field_id": 725837, - "width": 100, - "hidden": false, - "order": 0, - "aggregation_type": "unique_count", - "aggregation_raw_type": "unique_count" - }, - { - "id": 1064144, - "field_id": 725851, - "width": 100, - "hidden": false, - "order": 1, - "aggregation_type": "not_empty_percentage", - "aggregation_raw_type": "empty_count" - }, - { - "id": 1064145, - "field_id": 725877, - "width": 100, - "hidden": false, - "order": 2, - "aggregation_type": "", - "aggregation_raw_type": "" - }, - { - "id": 1064146, - "field_id": 725878, - "width": 100, - "hidden": false, - "order": 3, - "aggregation_type": "", - "aggregation_raw_type": "" - }, - { - "id": 1064147, - "field_id": 725879, - "width": 166, - "hidden": false, - "order": 4, - "aggregation_type": "", - "aggregation_raw_type": "" - }, - { - "id": 1064148, - "field_id": 725881, - "width": 155, - "hidden": false, - "order": 5, - "aggregation_type": "", - "aggregation_raw_type": "" - }, - { - "id": 1064149, - "field_id": 725883, - "width": 178, - "hidden": false, - "order": 6, - "aggregation_type": "", - "aggregation_raw_type": "" - }, - { - "id": 1064150, - "field_id": 725884, - "width": 145, - "hidden": false, - "order": 7, - "aggregation_type": "", - "aggregation_raw_type": "" - }, - { - "id": 1064151, - "field_id": 725885, - "width": 158, - "hidden": false, - "order": 8, - "aggregation_type": "", - "aggregation_raw_type": "" - }, - { - "id": 1064152, - "field_id": 725886, - "width": 133, - "hidden": false, - "order": 10, - "aggregation_type": "", - "aggregation_raw_type": "" - }, - { - "id": 1064153, - "field_id": 725887, - "width": 148, - "hidden": false, - "order": 11, - "aggregation_type": "", - "aggregation_raw_type": "" - }, - { - "id": 1064154, - "field_id": 725888, - "width": 148, - "hidden": false, - "order": 12, - "aggregation_type": "", - "aggregation_raw_type": "" - }, - { - "id": 1064155, - "field_id": 725889, - "width": 163, - "hidden": false, - "order": 13, - "aggregation_type": "", - "aggregation_raw_type": "" - }, - { - "id": 1064156, - "field_id": 725890, - "width": 120, - "hidden": false, - "order": 14, - "aggregation_type": "sum", - "aggregation_raw_type": "sum" - }, - { - "id": 1064157, - "field_id": 725893, - "width": 126, - "hidden": false, - "order": 15, - "aggregation_type": "not_empty_percentage", - "aggregation_raw_type": "empty_count" - }, - { - "id": 1064158, - "field_id": 725895, - "width": 172, - "hidden": false, - "order": 16, - "aggregation_type": "", - "aggregation_raw_type": "" - }, - { - "id": 1064159, - "field_id": 725896, - "width": 149, - "hidden": false, - "order": 17, - "aggregation_type": "not_empty_percentage", - "aggregation_raw_type": "empty_count" - }, - { - "id": 1064160, - "field_id": 725898, - "width": 164, - "hidden": false, - "order": 18, - "aggregation_type": "", - "aggregation_raw_type": "" - }, - { - "id": 1064161, - "field_id": 738834, - "width": 155, - "hidden": false, - "order": 9, - "aggregation_type": "", - "aggregation_raw_type": "" - }, - { - "id": 1064162, - "field_id": 739115, - "width": 176, - "hidden": true, - "order": 32767, - "aggregation_type": "", - "aggregation_raw_type": "" - } - ] - }, - { - "id": 174159, - "type": "grid", - "name": "Sales in CD San Leandro", - "order": 5, - "filter_type": "AND", - "filters_disabled": false, - "filters": [ - { - "id": 68754, - "field_id": 739115, - "type": "equal", - "value": "CD San Leandro" - } - ], - "sortings": [ - { - "id": 53176, - "field_id": 725887, - "order": "ASC" - } - ], - "decorations": [], - "public": false, - "row_identifier_type": "count", - "field_options": [ - { - "id": 1064163, - "field_id": 725837, - "width": 100, - "hidden": false, - "order": 0, - "aggregation_type": "unique_count", - "aggregation_raw_type": "unique_count" - }, - { - "id": 1064164, - "field_id": 725851, - "width": 100, - "hidden": false, - "order": 1, - "aggregation_type": "not_empty_percentage", - "aggregation_raw_type": "empty_count" - }, - { - "id": 1064165, - "field_id": 725877, - "width": 100, - "hidden": false, - "order": 2, - "aggregation_type": "", - "aggregation_raw_type": "" - }, - { - "id": 1064166, - "field_id": 725878, - "width": 100, - "hidden": false, - "order": 3, - "aggregation_type": "", - "aggregation_raw_type": "" - }, - { - "id": 1064167, - "field_id": 725879, - "width": 166, - "hidden": false, - "order": 4, - "aggregation_type": "", - "aggregation_raw_type": "" - }, - { - "id": 1064168, - "field_id": 725881, - "width": 155, - "hidden": false, - "order": 5, - "aggregation_type": "", - "aggregation_raw_type": "" - }, - { - "id": 1064169, - "field_id": 725883, - "width": 178, - "hidden": false, - "order": 6, - "aggregation_type": "", - "aggregation_raw_type": "" - }, - { - "id": 1064170, - "field_id": 725884, - "width": 145, - "hidden": false, - "order": 7, - "aggregation_type": "", - "aggregation_raw_type": "" - }, - { - "id": 1064171, - "field_id": 725885, - "width": 158, - "hidden": false, - "order": 8, - "aggregation_type": "", - "aggregation_raw_type": "" - }, - { - "id": 1064172, - "field_id": 725886, - "width": 133, - "hidden": false, - "order": 10, - "aggregation_type": "", - "aggregation_raw_type": "" - }, - { - "id": 1064173, - "field_id": 725887, - "width": 148, - "hidden": false, - "order": 11, - "aggregation_type": "", - "aggregation_raw_type": "" - }, - { - "id": 1064174, - "field_id": 725888, - "width": 148, - "hidden": false, - "order": 12, - "aggregation_type": "", - "aggregation_raw_type": "" - }, - { - "id": 1064175, - "field_id": 725889, - "width": 163, - "hidden": false, - "order": 13, - "aggregation_type": "", - "aggregation_raw_type": "" - }, - { - "id": 1064176, - "field_id": 725890, - "width": 120, - "hidden": false, - "order": 14, - "aggregation_type": "sum", - "aggregation_raw_type": "sum" - }, - { - "id": 1064177, - "field_id": 725893, - "width": 126, - "hidden": false, - "order": 15, - "aggregation_type": "not_empty_percentage", - "aggregation_raw_type": "empty_count" - }, - { - "id": 1064178, - "field_id": 725895, - "width": 172, - "hidden": false, - "order": 16, - "aggregation_type": "", - "aggregation_raw_type": "" - }, - { - "id": 1064179, - "field_id": 725896, - "width": 149, - "hidden": false, - "order": 17, - "aggregation_type": "not_empty_percentage", - "aggregation_raw_type": "empty_count" - }, - { - "id": 1064180, - "field_id": 725898, - "width": 164, - "hidden": false, - "order": 18, - "aggregation_type": "", - "aggregation_raw_type": "" - }, - { - "id": 1064181, - "field_id": 738834, - "width": 155, - "hidden": false, - "order": 9, - "aggregation_type": "", - "aggregation_raw_type": "" - }, - { - "id": 1064182, - "field_id": 739115, - "width": 176, - "hidden": true, - "order": 32767, - "aggregation_type": "", - "aggregation_raw_type": "" - } - ] - }, - { - "id": 174151, + "id": 26488, "type": "kanban", - "name": "By financing option", - "order": 7, + "name": "All offers stacked by status", + "order": 11, + "ownership_type": "collaborative", + "owned_by": "frederik@baserow.io", "filter_type": "AND", "filters_disabled": false, "filters": [], + "filter_groups": [], "sortings": [], "decorations": [], "public": false, - "single_select_field_id": 725889, + "single_select_field_id": 59790, "field_options": [ { - "id": 43723, - "field_id": 725837, + "id": 35166, + "field_id": 59780, "hidden": false, "order": 1 }, { - "id": 43724, - "field_id": 725851, + "id": 35167, + "field_id": 59781, "hidden": false, "order": 2 }, { - "id": 43726, - "field_id": 725878, + "id": 35168, + "field_id": 59863, "hidden": false, "order": 3 }, { - "id": 43725, - "field_id": 725877, + "id": 35169, + "field_id": 59850, "hidden": false, "order": 4 }, { - "id": 43727, - "field_id": 725879, + "id": 35170, + "field_id": 59864, "hidden": false, "order": 5 }, { - "id": 43728, - "field_id": 725881, - "hidden": true, + "id": 35171, + "field_id": 59851, + "hidden": false, "order": 6 }, { - "id": 43729, - "field_id": 725883, + "id": 35172, + "field_id": 59782, "hidden": true, "order": 7 }, { - "id": 43730, - "field_id": 725884, - "hidden": false, + "id": 35173, + "field_id": 59783, + "hidden": true, "order": 8 }, { - "id": 43731, - "field_id": 725885, - "hidden": true, + "id": 35174, + "field_id": 59785, + "hidden": false, "order": 9 }, { - "id": 43732, - "field_id": 725886, + "id": 35175, + "field_id": 59865, "hidden": false, "order": 10 }, { - "id": 43733, - "field_id": 725887, + "id": 35176, + "field_id": 59784, "hidden": false, "order": 11 }, { - "id": 43734, - "field_id": 725888, - "hidden": true, + "id": 35177, + "field_id": 59869, + "hidden": false, "order": 12 }, { - "id": 43735, - "field_id": 725889, + "id": 35178, + "field_id": 59786, "hidden": true, "order": 13 }, { - "id": 43736, - "field_id": 725890, + "id": 35179, + "field_id": 59787, "hidden": true, "order": 14 }, { - "id": 43737, - "field_id": 725893, - "hidden": false, + "id": 35180, + "field_id": 59788, + "hidden": true, "order": 15 }, { - "id": 43738, - "field_id": 725895, - "hidden": true, + "id": 35181, + "field_id": 59789, + "hidden": false, "order": 16 }, { - "id": 43739, - "field_id": 725896, - "hidden": false, + "id": 35182, + "field_id": 59790, + "hidden": true, "order": 17 }, { - "id": 43740, - "field_id": 725898, - "hidden": true, - "order": 18 - }, - { - "id": 43741, - "field_id": 738834, + "id": 35183, + "field_id": 59852, "hidden": true, "order": 19 - }, - { - "id": 44226, - "field_id": 739115, - "hidden": true, - "order": 32767 - } - ] - }, - { - "id": 174152, - "type": "form", - "name": "Add sale information", - "order": 8, - "public": false, - "title": "Add sale transaction details", - "description": "", - "cover_image": { - "name": "zO86dBtAtDWFyQPGQMVqhiJ37lzsZZ2C_9ed4ca91bc68f43a8b38ef9079ac5aecfe82010cf41b3b5b8325a84900caf509.jpg", - "original_name": "Header.CashRegister.01.jpg" - }, - "logo_image": null, - "submit_text": "Submit", - "submit_action": "MESSAGE", - "submit_action_message": "A sale was successfully added to the database. To add more, please reload this page.", - "submit_action_redirect_url": "", - "field_options": [ - { - "id": 100758, - "field_id": 725837, - "name": "", - "description": "", - "enabled": false, - "required": true, - "order": 32767, - "show_when_matching_conditions": false, - "condition_type": "AND", - "conditions": [] - }, - { - "id": 100759, - "field_id": 725851, - "name": "", - "description": "Please select the exact vehicle sold in this transaction.", - "enabled": true, - "required": true, - "order": 32767, - "show_when_matching_conditions": false, - "condition_type": "AND", - "conditions": [] - }, - { - "id": 100760, - "field_id": 725877, - "name": "", - "description": "", - "enabled": false, - "required": true, - "order": 32767, - "show_when_matching_conditions": false, - "condition_type": "AND", - "conditions": [] - }, - { - "id": 100761, - "field_id": 725878, - "name": "", - "description": "", - "enabled": false, - "required": true, - "order": 32767, - "show_when_matching_conditions": false, - "condition_type": "AND", - "conditions": [] - }, - { - "id": 100762, - "field_id": 725879, - "name": "", - "description": "", - "enabled": false, - "required": true, - "order": 32767, - "show_when_matching_conditions": false, - "condition_type": "AND", - "conditions": [] - }, - { - "id": 100763, - "field_id": 725881, - "name": "", - "description": "", - "enabled": false, - "required": true, - "order": 32767, - "show_when_matching_conditions": false, - "condition_type": "AND", - "conditions": [] - }, - { - "id": 100764, - "field_id": 725883, - "name": "", - "description": "", - "enabled": false, - "required": true, - "order": 32767, - "show_when_matching_conditions": false, - "condition_type": "AND", - "conditions": [] - }, - { - "id": 100765, - "field_id": 725884, - "name": "", - "description": "", - "enabled": false, - "required": true, - "order": 32767, - "show_when_matching_conditions": false, - "condition_type": "AND", - "conditions": [] - }, - { - "id": 100766, - "field_id": 725885, - "name": "", - "description": "", - "enabled": false, - "required": true, - "order": 32767, - "show_when_matching_conditions": false, - "condition_type": "AND", - "conditions": [] - }, - { - "id": 100767, - "field_id": 725886, - "name": "", - "description": "", - "enabled": false, - "required": true, - "order": 32767, - "show_when_matching_conditions": false, - "condition_type": "AND", - "conditions": [] - }, - { - "id": 100768, - "field_id": 725887, - "name": "", - "description": "Please enter the date this vehicle was sold to the customer.", - "enabled": true, - "required": true, - "order": 32767, - "show_when_matching_conditions": false, - "condition_type": "AND", - "conditions": [] - }, - { - "id": 100769, - "field_id": 725888, - "name": "", - "description": "Enter the date this vehicle was released or delivered to the customer.", - "enabled": true, - "required": false, - "order": 32767, - "show_when_matching_conditions": false, - "condition_type": "AND", - "conditions": [] - }, - { - "id": 100770, - "field_id": 725889, - "name": "", - "description": "Please select the type of payment used in this transaction.", - "enabled": true, - "required": true, - "order": 32767, - "show_when_matching_conditions": false, - "condition_type": "AND", - "conditions": [] - }, - { - "id": 100771, - "field_id": 725890, - "name": "", - "description": "Please enter the actual price of this vehicle paid by the customer.", - "enabled": true, - "required": true, - "order": 32767, - "show_when_matching_conditions": false, - "condition_type": "AND", - "conditions": [] - }, - { - "id": 100772, - "field_id": 725893, - "name": "", - "description": "Please select the customer who bought the vehicle in this transaction.", - "enabled": true, - "required": true, - "order": 32767, - "show_when_matching_conditions": false, - "condition_type": "AND", - "conditions": [] - }, - { - "id": 100773, - "field_id": 725895, - "name": "", - "description": "", - "enabled": false, - "required": true, - "order": 32767, - "show_when_matching_conditions": false, - "condition_type": "AND", - "conditions": [] - }, - { - "id": 100774, - "field_id": 725896, - "name": "", - "description": "Please select the staff member who sold the vehicle to the customer in this transaction.", - "enabled": true, - "required": true, - "order": 32767, - "show_when_matching_conditions": false, - "condition_type": "AND", - "conditions": [] - }, - { - "id": 100775, - "field_id": 725898, - "name": "", - "description": "Upload any or all transaction documents related to this sale.", - "enabled": true, - "required": false, - "order": 32767, - "show_when_matching_conditions": false, - "condition_type": "AND", - "conditions": [] - }, - { - "id": 100776, - "field_id": 738834, - "name": "", - "description": "", - "enabled": false, - "required": true, - "order": 32767, - "show_when_matching_conditions": false, - "condition_type": "AND", - "conditions": [] - }, - { - "id": 101238, - "field_id": 739115, - "name": "", - "description": "", - "enabled": false, - "required": true, - "order": 32767, - "show_when_matching_conditions": false, - "condition_type": "AND", - "conditions": [] } ] } @@ -8463,592 +11831,946 @@ "id": 1, "order": "1.00000000000000000000", "created_on": "2022-11-13T16:50:33.040830+00:00", - "updated_on": "2022-11-20T21:43:57.434616+00:00", - "field_725837": null, - "field_725851": [ + "updated_on": "2025-02-11T14:15:23.353020+00:00", + "last_modified_by": "frederik@baserow.io", + "field_59780": null, + "field_59781": [ 14 ], - "field_725877": null, - "field_725878": null, - "field_725879": null, - "field_725881": null, - "field_725883": null, - "field_725884": null, - "field_725885": null, - "field_725886": null, - "field_725887": "2021-05-10T10:00:00+00:00", - "field_725888": "2021-05-12T17:30:00+00:00", - "field_725889": 313898, - "field_725890": "10200.00", - "field_725893": [ + "field_59864": null, + "field_59863": null, + "field_59850": null, + "field_59851": null, + "field_59782": null, + "field_59783": "2024-05-12", + "field_59784": "10200", + "field_59785": [ 3 ], - "field_725895": null, - "field_725896": [ - 1 + "field_59786": [], + "field_59787": [], + "field_59788": [], + "field_59789": [ + 5 ], - "field_725898": [ - { - "name": "RtffplvDjbSYtaGHrZhZwSdyO3vDguc4_05be97d3499f4665c556dc2bd0e32b275d30dfd0dde1c0e69875eee7fbc59cdd.jpg", - "visible_name": "deed_of_sale.jpg", - "original_name": "deed_of_sale.jpg" - }, - { - "name": "iQ8EvGq8TSuARN9lajPbnEUQtJq6Y1kM_ac5e07c439066a20b7e755891d10af1c0afd6654e7470ca1129973c94ee60767.jpg", - "visible_name": "vehicle_title.jpg", - "original_name": "vehicle_title.jpg" - } - ], - "field_738834": null, - "field_739115": null + "field_59790": 21059, + "field_59865": null, + "field_59869": null, + "field_59852": null, + "field_59853": null, + "field_59854": null }, { "id": 2, "order": "2.00000000000000000000", "created_on": "2022-11-13T16:50:33.040916+00:00", - "updated_on": "2022-11-20T21:44:00.096141+00:00", - "field_725837": null, - "field_725851": [ + "updated_on": "2025-02-11T14:16:15.843219+00:00", + "last_modified_by": "frederik@baserow.io", + "field_59780": null, + "field_59781": [ 11 ], - "field_725877": null, - "field_725878": null, - "field_725879": null, - "field_725881": null, - "field_725883": null, - "field_725884": null, - "field_725885": null, - "field_725886": null, - "field_725887": "2022-07-18T09:30:00+00:00", - "field_725888": "2022-07-21T10:00:00+00:00", - "field_725889": 313895, - "field_725890": "10550.00", - "field_725893": [ + "field_59864": null, + "field_59863": null, + "field_59850": null, + "field_59851": null, + "field_59782": null, + "field_59783": "2025-07-21", + "field_59784": "10550", + "field_59785": [ 1 ], - "field_725895": null, - "field_725896": [ - 4 + "field_59786": [], + "field_59787": [], + "field_59788": [ + 3 ], - "field_725898": [ - { - "name": "RtffplvDjbSYtaGHrZhZwSdyO3vDguc4_05be97d3499f4665c556dc2bd0e32b275d30dfd0dde1c0e69875eee7fbc59cdd.jpg", - "visible_name": "deed_of_sale.jpg", - "original_name": "deed_of_sale.jpg" - }, - { - "name": "iQ8EvGq8TSuARN9lajPbnEUQtJq6Y1kM_ac5e07c439066a20b7e755891d10af1c0afd6654e7470ca1129973c94ee60767.jpg", - "visible_name": "vehicle_title.jpg", - "original_name": "vehicle_title.jpg" - } + "field_59789": [ + 2 ], - "field_738834": null, - "field_739115": null + "field_59790": 21060, + "field_59865": null, + "field_59869": null, + "field_59852": null, + "field_59853": null, + "field_59854": null }, { "id": 3, "order": "3.00000000000000000000", "created_on": "2022-11-20T20:33:35.586365+00:00", - "updated_on": "2022-11-20T21:44:00.448825+00:00", - "field_725837": null, - "field_725851": [ + "updated_on": "2025-02-11T14:15:39.460623+00:00", + "last_modified_by": "frederik@baserow.io", + "field_59780": null, + "field_59781": [ 16 ], - "field_725877": null, - "field_725878": null, - "field_725879": null, - "field_725881": null, - "field_725883": null, - "field_725884": null, - "field_725885": null, - "field_725886": null, - "field_725887": "2022-01-17T11:00:00+00:00", - "field_725888": "2022-01-17T13:30:00+00:00", - "field_725889": 313896, - "field_725890": "11750.00", - "field_725893": [ + "field_59864": null, + "field_59863": null, + "field_59850": null, + "field_59851": null, + "field_59782": null, + "field_59783": "2025-01-17", + "field_59784": "11750", + "field_59785": [ 3 ], - "field_725895": null, - "field_725896": [ + "field_59786": [], + "field_59787": [], + "field_59788": [ 5 ], - "field_725898": [ - { - "name": "RtffplvDjbSYtaGHrZhZwSdyO3vDguc4_05be97d3499f4665c556dc2bd0e32b275d30dfd0dde1c0e69875eee7fbc59cdd.jpg", - "visible_name": "deed_of_sale.jpg", - "original_name": "deed_of_sale.jpg" - }, - { - "name": "iQ8EvGq8TSuARN9lajPbnEUQtJq6Y1kM_ac5e07c439066a20b7e755891d10af1c0afd6654e7470ca1129973c94ee60767.jpg", - "visible_name": "vehicle_title.jpg", - "original_name": "vehicle_title.jpg" - } + "field_59789": [ + 3 ], - "field_738834": null, - "field_739115": null + "field_59790": 21060, + "field_59865": null, + "field_59869": null, + "field_59852": null, + "field_59853": null, + "field_59854": null + }, + { + "id": 17, + "order": "3.50000000000000000000", + "created_on": "2025-02-11T14:13:25.367178+00:00", + "updated_on": "2025-02-11T14:15:55.674130+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59780": null, + "field_59781": [ + 21 + ], + "field_59864": null, + "field_59863": null, + "field_59850": null, + "field_59851": null, + "field_59782": null, + "field_59783": "2025-03-08", + "field_59784": "38000", + "field_59785": [ + 5 + ], + "field_59786": [], + "field_59787": [], + "field_59788": [], + "field_59789": [ + 4 + ], + "field_59790": 21059, + "field_59865": null, + "field_59869": null, + "field_59852": null, + "field_59853": null, + "field_59854": null }, { "id": 4, "order": "4.00000000000000000000", "created_on": "2022-11-20T20:33:37.942258+00:00", - "updated_on": "2022-11-20T21:44:00.743670+00:00", - "field_725837": null, - "field_725851": [ + "updated_on": "2025-02-11T14:16:10.784314+00:00", + "last_modified_by": "frederik@baserow.io", + "field_59780": null, + "field_59781": [ 15 ], - "field_725877": null, - "field_725878": null, - "field_725879": null, - "field_725881": null, - "field_725883": null, - "field_725884": null, - "field_725885": null, - "field_725886": null, - "field_725887": "2022-05-09T11:30:00+00:00", - "field_725888": "2022-05-09T12:30:00+00:00", - "field_725889": 313894, - "field_725890": "11750.00", - "field_725893": [ + "field_59864": null, + "field_59863": null, + "field_59850": null, + "field_59851": null, + "field_59782": "2022-05-09", + "field_59783": "2025-05-09", + "field_59784": "11750", + "field_59785": [ 5 ], - "field_725895": null, - "field_725896": [ + "field_59786": [ 7 ], - "field_725898": [ + "field_59787": [ { - "name": "RtffplvDjbSYtaGHrZhZwSdyO3vDguc4_05be97d3499f4665c556dc2bd0e32b275d30dfd0dde1c0e69875eee7fbc59cdd.jpg", + "name": "gHAteg8yynJ9f9YUkea1KhwXHTU9OC1z_05be97d3499f4665c556dc2bd0e32b275d30dfd0dde1c0e69875eee7fbc59cdd.jpg", "visible_name": "deed_of_sale.jpg", - "original_name": "deed_of_sale.jpg" - }, - { - "name": "iQ8EvGq8TSuARN9lajPbnEUQtJq6Y1kM_ac5e07c439066a20b7e755891d10af1c0afd6654e7470ca1129973c94ee60767.jpg", - "visible_name": "vehicle_title.jpg", - "original_name": "vehicle_title.jpg" + "original_name": "gHAteg8yynJ9f9YUkea1KhwXHTU9OC1z_05be97d3499f4665c556dc2bd0e32b275d30dfd0dde1c0e69875eee7fbc59cdd.jpg" } ], - "field_738834": null, - "field_739115": null + "field_59788": [ + 1 + ], + "field_59789": [ + 1 + ], + "field_59790": 21058, + "field_59865": null, + "field_59869": null, + "field_59852": null, + "field_59853": null, + "field_59854": null + }, + { + "id": 18, + "order": "4.50000000000000000000", + "created_on": "2025-02-11T14:13:28.144644+00:00", + "updated_on": "2025-02-11T14:16:00.483026+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59780": null, + "field_59781": [ + 21 + ], + "field_59864": null, + "field_59863": null, + "field_59850": null, + "field_59851": null, + "field_59782": null, + "field_59783": "2025-03-08", + "field_59784": "40200", + "field_59785": [ + 2 + ], + "field_59786": [], + "field_59787": [], + "field_59788": [], + "field_59789": [ + 4 + ], + "field_59790": 21060, + "field_59865": null, + "field_59869": null, + "field_59852": null, + "field_59853": null, + "field_59854": null }, { "id": 5, "order": "5.00000000000000000000", "created_on": "2022-11-20T20:33:39.594808+00:00", - "updated_on": "2022-11-20T21:44:01.251608+00:00", - "field_725837": null, - "field_725851": [ + "updated_on": "2025-02-11T14:16:03.920722+00:00", + "last_modified_by": "frederik@baserow.io", + "field_59780": null, + "field_59781": [ 21 ], - "field_725877": null, - "field_725878": null, - "field_725879": null, - "field_725881": null, - "field_725883": null, - "field_725884": null, - "field_725885": null, - "field_725886": null, - "field_725887": "2022-03-07T09:00:00+00:00", - "field_725888": "2022-03-08T09:30:00+00:00", - "field_725889": 313897, - "field_725890": "40200.00", - "field_725893": [ - 2 + "field_59864": null, + "field_59863": null, + "field_59850": null, + "field_59851": null, + "field_59782": null, + "field_59783": "2025-03-08", + "field_59784": "23000", + "field_59785": [ + 1 ], - "field_725895": null, - "field_725896": [ - 2 + "field_59786": [], + "field_59787": [], + "field_59788": [], + "field_59789": [ + 4 ], - "field_725898": [ - { - "name": "RtffplvDjbSYtaGHrZhZwSdyO3vDguc4_05be97d3499f4665c556dc2bd0e32b275d30dfd0dde1c0e69875eee7fbc59cdd.jpg", - "visible_name": "deed_of_sale.jpg", - "original_name": "deed_of_sale.jpg" - }, - { - "name": "iQ8EvGq8TSuARN9lajPbnEUQtJq6Y1kM_ac5e07c439066a20b7e755891d10af1c0afd6654e7470ca1129973c94ee60767.jpg", - "visible_name": "vehicle_title.jpg", - "original_name": "vehicle_title.jpg" - } - ], - "field_738834": null, - "field_739115": null + "field_59790": 21059, + "field_59865": null, + "field_59869": null, + "field_59852": null, + "field_59853": null, + "field_59854": null }, { "id": 6, "order": "6.00000000000000000000", "created_on": "2022-11-20T20:33:41.466217+00:00", - "updated_on": "2022-11-20T21:44:01.841914+00:00", - "field_725837": null, - "field_725851": [ + "updated_on": "2025-02-11T14:15:28.238120+00:00", + "last_modified_by": "frederik@baserow.io", + "field_59780": null, + "field_59781": [ 4 ], - "field_725877": null, - "field_725878": null, - "field_725879": null, - "field_725881": null, - "field_725883": null, - "field_725884": null, - "field_725885": null, - "field_725886": null, - "field_725887": "2021-09-20T08:30:00+00:00", - "field_725888": "2021-09-21T09:00:00+00:00", - "field_725889": 313897, - "field_725890": "25800.00", - "field_725893": [ + "field_59864": null, + "field_59863": null, + "field_59850": null, + "field_59851": null, + "field_59782": null, + "field_59783": "2025-09-21", + "field_59784": "25800", + "field_59785": [ 4 ], - "field_725895": null, - "field_725896": [ - 5 + "field_59786": [], + "field_59787": [], + "field_59788": [], + "field_59789": [ + 4 ], - "field_725898": [ - { - "name": "RtffplvDjbSYtaGHrZhZwSdyO3vDguc4_05be97d3499f4665c556dc2bd0e32b275d30dfd0dde1c0e69875eee7fbc59cdd.jpg", - "visible_name": "deed_of_sale.jpg", - "original_name": "deed_of_sale.jpg" - }, - { - "name": "iQ8EvGq8TSuARN9lajPbnEUQtJq6Y1kM_ac5e07c439066a20b7e755891d10af1c0afd6654e7470ca1129973c94ee60767.jpg", - "visible_name": "vehicle_title.jpg", - "original_name": "vehicle_title.jpg" - } - ], - "field_738834": null, - "field_739115": null + "field_59790": 21060, + "field_59865": null, + "field_59869": null, + "field_59852": null, + "field_59853": null, + "field_59854": null }, { "id": 7, "order": "7.00000000000000000000", "created_on": "2022-11-20T20:33:44.066196+00:00", - "updated_on": "2022-11-20T21:44:02.324500+00:00", - "field_725837": null, - "field_725851": [ + "updated_on": "2025-02-11T14:15:09.981389+00:00", + "last_modified_by": "frederik@baserow.io", + "field_59780": null, + "field_59781": [ 6 ], - "field_725877": null, - "field_725878": null, - "field_725879": null, - "field_725881": null, - "field_725883": null, - "field_725884": null, - "field_725885": null, - "field_725886": null, - "field_725887": "2020-05-25T10:30:00+00:00", - "field_725888": "2020-05-27T11:00:00+00:00", - "field_725889": 313897, - "field_725890": "35300.00", - "field_725893": [ + "field_59864": null, + "field_59863": null, + "field_59850": null, + "field_59851": null, + "field_59782": "2025-05-25", + "field_59783": "2025-05-22", + "field_59784": "35300", + "field_59785": [ 5 ], - "field_725895": null, - "field_725896": [ + "field_59786": [ 9 ], - "field_725898": [ + "field_59787": [ { - "name": "RtffplvDjbSYtaGHrZhZwSdyO3vDguc4_05be97d3499f4665c556dc2bd0e32b275d30dfd0dde1c0e69875eee7fbc59cdd.jpg", + "name": "gHAteg8yynJ9f9YUkea1KhwXHTU9OC1z_05be97d3499f4665c556dc2bd0e32b275d30dfd0dde1c0e69875eee7fbc59cdd.jpg", "visible_name": "deed_of_sale.jpg", - "original_name": "deed_of_sale.jpg" - }, - { - "name": "iQ8EvGq8TSuARN9lajPbnEUQtJq6Y1kM_ac5e07c439066a20b7e755891d10af1c0afd6654e7470ca1129973c94ee60767.jpg", - "visible_name": "vehicle_title.jpg", - "original_name": "vehicle_title.jpg" + "original_name": "gHAteg8yynJ9f9YUkea1KhwXHTU9OC1z_05be97d3499f4665c556dc2bd0e32b275d30dfd0dde1c0e69875eee7fbc59cdd.jpg" } ], - "field_738834": null, - "field_739115": null + "field_59788": [ + 4 + ], + "field_59789": [ + 4 + ], + "field_59790": 21058, + "field_59865": null, + "field_59869": null, + "field_59852": null, + "field_59853": null, + "field_59854": null }, { "id": 8, "order": "8.00000000000000000000", "created_on": "2022-11-20T20:33:46.230296+00:00", - "updated_on": "2022-11-20T21:44:02.750895+00:00", - "field_725837": null, - "field_725851": [ + "updated_on": "2025-02-11T14:16:43.882523+00:00", + "last_modified_by": "frederik@baserow.io", + "field_59780": null, + "field_59781": [ 24 ], - "field_725877": null, - "field_725878": null, - "field_725879": null, - "field_725881": null, - "field_725883": null, - "field_725884": null, - "field_725885": null, - "field_725886": null, - "field_725887": "2021-10-25T10:00:00+00:00", - "field_725888": "2021-10-28T10:30:00+00:00", - "field_725889": 313895, - "field_725890": "18000.00", - "field_725893": [ + "field_59864": null, + "field_59863": null, + "field_59850": null, + "field_59851": null, + "field_59782": "2024-10-31", + "field_59783": "2024-10-28", + "field_59784": "18000", + "field_59785": [ 1 ], - "field_725895": null, - "field_725896": [ + "field_59786": [ 6 ], - "field_725898": [ + "field_59787": [ { - "name": "RtffplvDjbSYtaGHrZhZwSdyO3vDguc4_05be97d3499f4665c556dc2bd0e32b275d30dfd0dde1c0e69875eee7fbc59cdd.jpg", + "name": "gHAteg8yynJ9f9YUkea1KhwXHTU9OC1z_05be97d3499f4665c556dc2bd0e32b275d30dfd0dde1c0e69875eee7fbc59cdd.jpg", "visible_name": "deed_of_sale.jpg", - "original_name": "deed_of_sale.jpg" - }, - { - "name": "iQ8EvGq8TSuARN9lajPbnEUQtJq6Y1kM_ac5e07c439066a20b7e755891d10af1c0afd6654e7470ca1129973c94ee60767.jpg", - "visible_name": "vehicle_title.jpg", - "original_name": "vehicle_title.jpg" + "original_name": "gHAteg8yynJ9f9YUkea1KhwXHTU9OC1z_05be97d3499f4665c556dc2bd0e32b275d30dfd0dde1c0e69875eee7fbc59cdd.jpg" } ], - "field_738834": null, - "field_739115": null + "field_59788": [ + 6 + ], + "field_59789": [ + 2 + ], + "field_59790": 21058, + "field_59865": null, + "field_59869": null, + "field_59852": null, + "field_59853": null, + "field_59854": null }, { "id": 9, "order": "9.00000000000000000000", "created_on": "2022-11-20T20:33:48.837938+00:00", - "updated_on": "2022-11-20T21:44:03.274373+00:00", - "field_725837": null, - "field_725851": [ + "updated_on": "2025-02-11T14:16:36.494538+00:00", + "last_modified_by": "frederik@baserow.io", + "field_59780": null, + "field_59781": [ 23 ], - "field_725877": null, - "field_725878": null, - "field_725879": null, - "field_725881": null, - "field_725883": null, - "field_725884": null, - "field_725885": null, - "field_725886": null, - "field_725887": "2022-02-21T11:30:00+00:00", - "field_725888": "2022-02-25T12:00:00+00:00", - "field_725889": 313895, - "field_725890": "21550.00", - "field_725893": [ + "field_59864": null, + "field_59863": null, + "field_59850": null, + "field_59851": null, + "field_59782": "2025-03-01", + "field_59783": "2025-02-25", + "field_59784": "21550", + "field_59785": [ 2 ], - "field_725895": null, - "field_725896": [ + "field_59786": [ 8 ], - "field_725898": [ + "field_59787": [ { - "name": "RtffplvDjbSYtaGHrZhZwSdyO3vDguc4_05be97d3499f4665c556dc2bd0e32b275d30dfd0dde1c0e69875eee7fbc59cdd.jpg", + "name": "gHAteg8yynJ9f9YUkea1KhwXHTU9OC1z_05be97d3499f4665c556dc2bd0e32b275d30dfd0dde1c0e69875eee7fbc59cdd.jpg", "visible_name": "deed_of_sale.jpg", - "original_name": "deed_of_sale.jpg" - }, - { - "name": "iQ8EvGq8TSuARN9lajPbnEUQtJq6Y1kM_ac5e07c439066a20b7e755891d10af1c0afd6654e7470ca1129973c94ee60767.jpg", - "visible_name": "vehicle_title.jpg", - "original_name": "vehicle_title.jpg" + "original_name": "gHAteg8yynJ9f9YUkea1KhwXHTU9OC1z_05be97d3499f4665c556dc2bd0e32b275d30dfd0dde1c0e69875eee7fbc59cdd.jpg" } ], - "field_738834": null, - "field_739115": null + "field_59788": [ + 7 + ], + "field_59789": [ + 2 + ], + "field_59790": 21058, + "field_59865": null, + "field_59869": null, + "field_59852": null, + "field_59853": null, + "field_59854": null }, { "id": 10, "order": "10.00000000000000000000", "created_on": "2022-11-20T20:33:52.258175+00:00", - "updated_on": "2022-11-20T21:44:03.638217+00:00", - "field_725837": null, - "field_725851": [ + "updated_on": "2025-02-11T14:15:17.984049+00:00", + "last_modified_by": "frederik@baserow.io", + "field_59780": null, + "field_59781": [ 8 ], - "field_725877": null, - "field_725878": null, - "field_725879": null, - "field_725881": null, - "field_725883": null, - "field_725884": null, - "field_725885": null, - "field_725886": null, - "field_725887": "2018-07-23T09:30:00+00:00", - "field_725888": "2018-07-23T10:30:00+00:00", - "field_725889": 313894, - "field_725890": "18170.00", - "field_725893": [ + "field_59864": null, + "field_59863": null, + "field_59850": null, + "field_59851": null, + "field_59782": null, + "field_59783": "2025-07-23", + "field_59784": "18170", + "field_59785": [ 5 ], - "field_725895": null, - "field_725896": [ + "field_59786": [], + "field_59787": [], + "field_59788": [ + 2 + ], + "field_59789": [ + 1 + ], + "field_59790": 21060, + "field_59865": null, + "field_59869": null, + "field_59852": null, + "field_59853": null, + "field_59854": null + }, + { + "id": 11, + "order": "11.00000000000000000000", + "created_on": "2025-02-11T14:08:57.339569+00:00", + "updated_on": "2025-02-11T14:26:54.737995+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59780": null, + "field_59781": [ + 9 + ], + "field_59864": null, + "field_59863": null, + "field_59850": null, + "field_59851": null, + "field_59782": null, + "field_59783": "2025-02-11", + "field_59784": "14605", + "field_59785": [ + 2 + ], + "field_59786": [], + "field_59787": [], + "field_59788": [], + "field_59789": [ + 1 + ], + "field_59790": 21060, + "field_59865": null, + "field_59869": null, + "field_59852": null, + "field_59853": null, + "field_59854": null + }, + { + "id": 13, + "order": "11.50000000000000000000", + "created_on": "2025-02-11T14:09:54.462950+00:00", + "updated_on": "2025-02-11T14:15:43.515780+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59780": null, + "field_59781": [ + 16 + ], + "field_59864": null, + "field_59863": null, + "field_59850": null, + "field_59851": null, + "field_59782": null, + "field_59783": "2025-01-17", + "field_59784": "11000", + "field_59785": [ 3 ], - "field_725898": [ - { - "name": "RtffplvDjbSYtaGHrZhZwSdyO3vDguc4_05be97d3499f4665c556dc2bd0e32b275d30dfd0dde1c0e69875eee7fbc59cdd.jpg", - "visible_name": "deed_of_sale.jpg", - "original_name": "deed_of_sale.jpg" - }, - { - "name": "iQ8EvGq8TSuARN9lajPbnEUQtJq6Y1kM_ac5e07c439066a20b7e755891d10af1c0afd6654e7470ca1129973c94ee60767.jpg", - "visible_name": "vehicle_title.jpg", - "original_name": "vehicle_title.jpg" - } + "field_59786": [], + "field_59787": [], + "field_59788": [ + 5 ], - "field_738834": null, - "field_739115": null + "field_59789": [ + 5 + ], + "field_59790": 21060, + "field_59865": null, + "field_59869": null, + "field_59852": null, + "field_59853": null, + "field_59854": null + }, + { + "id": 14, + "order": "11.66666666666666607455", + "created_on": "2025-02-11T14:09:58.635530+00:00", + "updated_on": "2025-02-11T14:15:47.538230+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59780": null, + "field_59781": [ + 16 + ], + "field_59864": null, + "field_59863": null, + "field_59850": null, + "field_59851": null, + "field_59782": null, + "field_59783": "2025-01-17", + "field_59784": "12000", + "field_59785": [ + 2 + ], + "field_59786": [], + "field_59787": [], + "field_59788": [ + 5 + ], + "field_59789": [ + 3 + ], + "field_59790": 21060, + "field_59865": null, + "field_59869": null, + "field_59852": null, + "field_59853": null, + "field_59854": null + }, + { + "id": 12, + "order": "12.00000000000000000000", + "created_on": "2025-02-11T14:09:24.998376+00:00", + "updated_on": "2025-02-11T14:26:58.948801+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59780": null, + "field_59781": [ + 18 + ], + "field_59864": null, + "field_59863": null, + "field_59850": null, + "field_59851": null, + "field_59782": null, + "field_59783": "2025-02-28", + "field_59784": "20000", + "field_59785": [ + 2 + ], + "field_59786": [], + "field_59787": [], + "field_59788": [], + "field_59789": [ + 4 + ], + "field_59790": 21060, + "field_59865": null, + "field_59869": null, + "field_59852": null, + "field_59853": null, + "field_59854": null + }, + { + "id": 20, + "order": "14.00000000000000000000", + "created_on": "2025-02-11T14:30:10.543997+00:00", + "updated_on": "2025-02-11T14:34:07.222881+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59780": null, + "field_59781": [ + 3 + ], + "field_59864": null, + "field_59863": null, + "field_59850": null, + "field_59851": null, + "field_59782": null, + "field_59783": "2025-02-11", + "field_59784": "19080", + "field_59785": [ + 2 + ], + "field_59786": [], + "field_59787": [], + "field_59788": [], + "field_59789": [ + 2 + ], + "field_59790": 21059, + "field_59865": null, + "field_59869": null, + "field_59852": null, + "field_59853": null, + "field_59854": null + }, + { + "id": 21, + "order": "15.00000000000000000000", + "created_on": "2025-02-11T14:33:32.211437+00:00", + "updated_on": "2025-02-11T14:34:09.109268+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59780": null, + "field_59781": [ + 10 + ], + "field_59864": null, + "field_59863": null, + "field_59850": null, + "field_59851": null, + "field_59782": null, + "field_59783": "2025-02-11", + "field_59784": "19080", + "field_59785": [ + 2 + ], + "field_59786": [], + "field_59787": [], + "field_59788": [], + "field_59789": [ + 1 + ], + "field_59790": 21059, + "field_59865": null, + "field_59869": null, + "field_59852": null, + "field_59853": null, + "field_59854": null + }, + { + "id": 22, + "order": "16.00000000000000000000", + "created_on": "2025-02-11T14:39:35.952755+00:00", + "updated_on": "2025-02-11T14:39:35.952755+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59780": null, + "field_59781": [ + 17 + ], + "field_59864": null, + "field_59863": null, + "field_59850": null, + "field_59851": null, + "field_59782": null, + "field_59783": "2025-02-11", + "field_59784": "19080", + "field_59785": [ + 4 + ], + "field_59786": [], + "field_59787": [], + "field_59788": [], + "field_59789": [ + 3 + ], + "field_59790": 21060, + "field_59865": null, + "field_59869": null, + "field_59852": null, + "field_59853": null, + "field_59854": null + }, + { + "id": 23, + "order": "17.00000000000000000000", + "created_on": "2025-02-11T14:47:28.216357+00:00", + "updated_on": "2025-02-11T14:47:28.216357+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59780": null, + "field_59781": [ + 9 + ], + "field_59864": null, + "field_59863": null, + "field_59850": null, + "field_59851": null, + "field_59782": null, + "field_59783": "2025-02-11", + "field_59784": "19080", + "field_59785": [ + 4 + ], + "field_59786": [], + "field_59787": [], + "field_59788": [], + "field_59789": [ + 4 + ], + "field_59790": 21060, + "field_59865": null, + "field_59869": null, + "field_59852": null, + "field_59853": null, + "field_59854": null } - ] + ], + "data_sync": null }, { - "id": 111553, + "id": 5699, "name": "Branches", - "order": 4, + "order": 5, "fields": [ { - "id": 705229, + "id": 59791, "type": "text", - "name": "Location", + "name": "Name", + "description": null, "order": 0, "primary": true, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, "text_default": "" }, { - "id": 705230, + "id": 59792, "type": "file", "name": "Photo", + "description": null, "order": 1, - "primary": false + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false }, { - "id": 725760, + "id": 59793, "type": "text", - "name": "Street", + "name": "Address", + "description": null, "order": 3, "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, "text_default": "" }, { - "id": 725761, + "id": 59794, "type": "text", "name": "City", + "description": null, "order": 4, "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, "text_default": "" }, { - "id": 725762, - "type": "text", - "name": "State", - "order": 5, - "primary": false, - "text_default": "" - }, - { - "id": 725763, + "id": 59795, "type": "text", "name": "Zip code", + "description": null, "order": 6, "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, "text_default": "" }, { - "id": 725764, + "id": 59796, "type": "phone_number", "name": "Phone number", + "description": null, "order": 7, - "primary": false + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false }, { - "id": 725765, - "type": "formula", - "name": "Personnel count", + "id": 59855, + "type": "count", + "name": "Count staff", + "description": null, "order": 8, "primary": false, - "error": null, - "date_format": null, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "number_suffix": "", + "number_separator": "", "date_include_time": null, - "date_time_format": null, - "number_decimal_places": 0, + "duration_format": null, + "date_force_timezone": null, + "date_show_tzinfo": null, "array_formula_type": null, - "formula": "count(field(\"Related staff\"))", - "formula_type": "number" + "error": null, + "number_decimal_places": 0, + "date_time_format": null, + "number_prefix": "", + "nullable": false, + "date_format": null, + "through_field_id": 59798 }, { - "id": 725787, + "id": 59871, "type": "formula", "name": "Cars in stock", + "description": null, "order": 9, "primary": false, - "error": null, - "date_format": null, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "number_suffix": "", + "number_separator": "", "date_include_time": null, - "date_time_format": null, - "number_decimal_places": 0, + "duration_format": null, + "date_force_timezone": null, + "date_show_tzinfo": null, "array_formula_type": null, - "formula": "count(filter(field(\"Related cars\"), lookup(\"Related cars\", \"In stock\")=true))", + "error": null, + "number_decimal_places": 0, + "date_time_format": null, + "number_prefix": "", + "nullable": false, + "date_format": null, + "formula": "count(filter(field('Related cars'), lookup('Related cars', 'Status') != 'Sold'))", "formula_type": "number" }, { - "id": 725789, + "id": 59797, "type": "link_row", "name": "Related cars", + "description": null, "order": 10, "primary": false, - "link_row_table_id": 111551, - "link_row_related_field_id": 725788, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "link_row_table_id": 5697, + "link_row_related_field_id": 59775, + "link_row_limit_selection_view_id": null, "has_related_field": true }, { - "id": 725791, + "id": 59798, "type": "link_row", "name": "Related staff", + "description": null, "order": 11, "primary": false, - "link_row_table_id": 114512, - "link_row_related_field_id": 725790, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "link_row_table_id": 5700, + "link_row_related_field_id": 59803, + "link_row_limit_selection_view_id": null, "has_related_field": true }, { - "id": 740388, - "type": "formula", + "id": 59838, + "type": "count", "name": "History count", + "description": null, "order": 12, "primary": false, - "error": null, - "date_format": null, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "number_suffix": "", + "number_separator": "", "date_include_time": null, - "date_time_format": null, - "number_decimal_places": 0, + "duration_format": null, + "date_force_timezone": null, + "date_show_tzinfo": null, "array_formula_type": null, - "formula": "count(field(\"Related cars\"))", - "formula_type": "number" + "error": null, + "number_decimal_places": 0, + "date_time_format": null, + "number_prefix": "", + "nullable": false, + "date_format": null, + "through_field_id": 59797 + }, + { + "id": 59799, + "type": "email", + "name": "Email", + "description": null, + "order": 13, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false } ], "views": [ { - "id": 164493, + "id": 26489, "type": "grid", "name": "All branches", "order": 1, + "ownership_type": "collaborative", + "owned_by": null, "filter_type": "AND", "filters_disabled": false, "filters": [], + "filter_groups": [], "sortings": [ { - "id": 53135, - "field_id": 725762, - "order": "ASC" - }, - { - "id": 53136, - "field_id": 725761, - "order": "ASC" - }, - { - "id": 53137, - "field_id": 705229, - "order": "ASC" + "id": 20389, + "field_id": 59871, + "order": "DESC" } ], + "group_bys": [], "decorations": [], "public": false, "row_identifier_type": "count", + "row_height_size": "small", "field_options": [ { - "id": 1001496, - "field_id": 705229, + "id": 261843, + "field_id": 59791, "width": 128, "hidden": false, "order": 0, @@ -9056,26 +12778,26 @@ "aggregation_raw_type": "unique_count" }, { - "id": 1001494, - "field_id": 705230, - "width": 100, + "id": 261844, + "field_id": 59792, + "width": 112, "hidden": false, "order": 1, "aggregation_type": "", "aggregation_raw_type": "" }, { - "id": 1041796, - "field_id": 725760, - "width": 148, + "id": 261845, + "field_id": 59793, + "width": 192, "hidden": false, "order": 2, "aggregation_type": "", "aggregation_raw_type": "" }, { - "id": 1041797, - "field_id": 725761, + "id": 261846, + "field_id": 59794, "width": 100, "hidden": false, "order": 3, @@ -9083,169 +12805,172 @@ "aggregation_raw_type": "" }, { - "id": 1041798, - "field_id": 725762, - "width": 100, + "id": 261847, + "field_id": 59795, + "width": 124, "hidden": false, "order": 4, "aggregation_type": "", "aggregation_raw_type": "" }, { - "id": 1041799, - "field_id": 725763, - "width": 113, + "id": 261848, + "field_id": 59799, + "width": 200, "hidden": false, "order": 5, "aggregation_type": "", "aggregation_raw_type": "" }, { - "id": 1041800, - "field_id": 725764, - "width": 152, + "id": 261849, + "field_id": 59796, + "width": 166, "hidden": false, "order": 6, "aggregation_type": "", "aggregation_raw_type": "" }, { - "id": 1041801, - "field_id": 725765, - "width": 160, - "hidden": false, - "order": 9, - "aggregation_type": "sum", - "aggregation_raw_type": "sum" - }, - { - "id": 1041811, - "field_id": 725787, - "width": 138, + "id": 261850, + "field_id": 59871, + "width": 153, "hidden": false, "order": 7, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261851, + "field_id": 59838, + "width": 156, + "hidden": false, + "order": 8, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261852, + "field_id": 59797, + "width": 170, + "hidden": false, + "order": 9, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261853, + "field_id": 59855, + "width": 176, + "hidden": false, + "order": 10, "aggregation_type": "sum", "aggregation_raw_type": "sum" }, { - "id": 1041813, - "field_id": 725789, - "width": 136, - "hidden": true, - "order": 10, - "aggregation_type": "", - "aggregation_raw_type": "" - }, - { - "id": 1041815, - "field_id": 725791, + "id": 261854, + "field_id": 59798, "width": 200, - "hidden": true, - "order": 11, - "aggregation_type": "", - "aggregation_raw_type": "" - }, - { - "id": 1066981, - "field_id": 740388, - "width": 144, "hidden": false, - "order": 8, + "order": 11, "aggregation_type": "", "aggregation_raw_type": "" } ] }, { - "id": 171183, + "id": 26490, "type": "gallery", "name": "Branches", "order": 2, + "ownership_type": "collaborative", + "owned_by": null, "filter_type": "AND", "filters_disabled": false, "filters": [], + "filter_groups": [], "sortings": [ { - "id": 53501, - "field_id": 705229, + "id": 20390, + "field_id": 59791, "order": "ASC" } ], "decorations": [], "public": false, - "card_cover_image_field_id": 705230, + "card_cover_image_field_id": 59792, "field_options": [ { - "id": 76045, - "field_id": 705229, + "id": 25506, + "field_id": 59791, "hidden": false, - "order": 32767 + "order": 1 }, { - "id": 76046, - "field_id": 705230, + "id": 25507, + "field_id": 59792, "hidden": true, - "order": 32767 + "order": 2 }, { - "id": 76047, - "field_id": 725760, - "hidden": true, - "order": 32767 - }, - { - "id": 76048, - "field_id": 725761, + "id": 25508, + "field_id": 59793, "hidden": false, - "order": 32767 + "order": 3 }, { - "id": 76049, - "field_id": 725762, + "id": 25509, + "field_id": 59794, "hidden": false, - "order": 32767 + "order": 4 }, { - "id": 76050, - "field_id": 725763, + "id": 25510, + "field_id": 59795, "hidden": true, - "order": 32767 + "order": 5 }, { - "id": 76051, - "field_id": 725764, - "hidden": true, - "order": 32767 - }, - { - "id": 76052, - "field_id": 725765, - "hidden": true, - "order": 32767 - }, - { - "id": 76053, - "field_id": 725787, + "id": 25511, + "field_id": 59796, "hidden": false, - "order": 32767 + "order": 6 }, { - "id": 76054, - "field_id": 725789, - "hidden": true, - "order": 32767 + "id": 25512, + "field_id": 59799, + "hidden": false, + "order": 7 }, { - "id": 76055, - "field_id": 725791, + "id": 25513, + "field_id": 59797, "hidden": true, - "order": 32767 + "order": 8 }, { - "id": 79353, - "field_id": 740388, + "id": 25514, + "field_id": 59798, "hidden": true, - "order": 32767 + "order": 9 + }, + { + "id": 25515, + "field_id": 59855, + "hidden": true, + "order": 10 + }, + { + "id": 25516, + "field_id": 59838, + "hidden": true, + "order": 11 + }, + { + "id": 25517, + "field_id": 59871, + "hidden": false, + "order": 12 } ] } @@ -9255,213 +12980,230 @@ "id": 1, "order": "1.00000000000000000000", "created_on": "2022-11-02T13:07:11.704542+00:00", - "updated_on": "2022-11-14T16:55:50.997168+00:00", - "field_705229": "CD La Mesa", - "field_705230": [ + "updated_on": "2025-02-07T13:43:07.344763+00:00", + "last_modified_by": "frederik@baserow.io", + "field_59791": "CD La Mesa", + "field_59792": [ { - "name": "CPmOfwJhZWYzviNUh8v5zxy8DNebkO2P_1b2bec9b6217efe686b71f50cab1bccb4938ccad5e05cd322e05dca949d6a4a2.jpg", + "name": "YOkc55VyjWpBH5Y9rb2ebNnwiSjd44ND_1b2bec9b6217efe686b71f50cab1bccb4938ccad5e05cd322e05dca949d6a4a2.jpg", "visible_name": "car_park.02.jpg", - "original_name": "car_park.02.jpg" + "original_name": "YOkc55VyjWpBH5Y9rb2ebNnwiSjd44ND_1b2bec9b6217efe686b71f50cab1bccb4938ccad5e05cd322e05dca949d6a4a2.jpg" } ], - "field_725760": "2547 Parkway Street", - "field_725761": "La Mesa", - "field_725762": "California", - "field_725763": "91941", - "field_725764": "(213) 375-9873", - "field_725765": null, - "field_725787": null, - "field_725789": [ + "field_59793": "2547 Parkway Street", + "field_59794": "La Mesa", + "field_59795": "91941", + "field_59796": "(213) 375-9873", + "field_59855": null, + "field_59871": null, + "field_59797": [ + 6, + 7, + 13, + 15, 17, 18, 19, - 6, - 7, - 22, - 15, - 13 + 22 ], - "field_725791": [ + "field_59798": [ 2, 7, 9 ], - "field_740388": null + "field_59838": null, + "field_59799": "lamesa@example.com" }, { "id": 2, "order": "2.00000000000000000000", "created_on": "2022-11-02T13:07:11.704617+00:00", - "updated_on": "2022-11-14T16:55:59.287130+00:00", - "field_705229": "CD Fremont", - "field_705230": [ + "updated_on": "2025-02-07T13:43:01.811116+00:00", + "last_modified_by": "frederik@baserow.io", + "field_59791": "CD Fremont", + "field_59792": [ { - "name": "KoHgxf3gyG2Ug4q5qEnm7A1Kfw8T098J_fc411a34726e182d3f58c86f920f5419fd3bf55c1d24ed1ae8fc3296ff0fccfb.jpg", + "name": "aPFVzAo8zcIxmFVfZCVxVzxT8PAfMTOQ_fc411a34726e182d3f58c86f920f5419fd3bf55c1d24ed1ae8fc3296ff0fccfb.jpg", "visible_name": "car_park.04.jpg", - "original_name": "car_park.04.jpg" + "original_name": "aPFVzAo8zcIxmFVfZCVxVzxT8PAfMTOQ_fc411a34726e182d3f58c86f920f5419fd3bf55c1d24ed1ae8fc3296ff0fccfb.jpg" } ], - "field_725760": "5014 Beech Street", - "field_725761": "Fremont", - "field_725762": "California", - "field_725763": "94539", - "field_725764": "(213) 375-9875", - "field_725765": null, - "field_725787": null, - "field_725789": [ - 25, - 9, - 4, + "field_59793": "5014 Beech Street", + "field_59794": "Fremont", + "field_59795": "94539", + "field_59796": "(213) 375-9875", + "field_59855": null, + "field_59871": null, + "field_59797": [ 1, + 4, + 9, + 14, 16, - 14 + 25 ], - "field_725791": [ + "field_59798": [ 5, 1 ], - "field_740388": null + "field_59838": null, + "field_59799": "fremont@example.com" }, { "id": 3, "order": "3.00000000000000000000", "created_on": "2022-11-14T15:16:56.256376+00:00", - "updated_on": "2022-11-14T16:55:43.397539+00:00", - "field_705229": "CD San Leandro", - "field_705230": [ + "updated_on": "2025-02-07T13:43:21.714706+00:00", + "last_modified_by": "frederik@baserow.io", + "field_59791": "CD San Leandro", + "field_59792": [ { - "name": "HdQqx55lZFbcN24Ub4jQTCvuIQ64MjCh_c0ae051e6b05543f719b9851e7ffdfb4474f77c5b85f0f4fd1d45497412fd008.jpg", + "name": "1WAr5tm18K5fcrWXVOIdpYjEJWYx4rZ6_c0ae051e6b05543f719b9851e7ffdfb4474f77c5b85f0f4fd1d45497412fd008.jpg", "visible_name": "car_park.01.jpg", - "original_name": "car_park.01.jpg" + "original_name": "1WAr5tm18K5fcrWXVOIdpYjEJWYx4rZ6_c0ae051e6b05543f719b9851e7ffdfb4474f77c5b85f0f4fd1d45497412fd008.jpg" } ], - "field_725760": "3671 Clifford Street", - "field_725761": "San Leandro", - "field_725762": "California", - "field_725763": "94578", - "field_725764": "(213) 375-9877", - "field_725765": null, - "field_725787": null, - "field_725789": [ + "field_59793": "3671 Clifford Street", + "field_59794": "San Leandro", + "field_59795": "94578", + "field_59796": "(213) 375-9877", + "field_59855": null, + "field_59871": null, + "field_59797": [ + 2, 8, 10, - 23, + 12, 21, - 2, - 12 + 23 ], - "field_725791": [ + "field_59798": [ 3, 8 ], - "field_740388": null + "field_59838": null, + "field_59799": "sanleandro@example.com" }, { "id": 4, "order": "4.00000000000000000000", "created_on": "2022-11-14T15:16:59.504335+00:00", - "updated_on": "2022-11-14T16:56:05.410981+00:00", - "field_705229": "CD Pomona", - "field_705230": [ + "updated_on": "2025-02-07T13:43:14.986551+00:00", + "last_modified_by": "frederik@baserow.io", + "field_59791": "CD Pomona", + "field_59792": [ { - "name": "4IufcLs1gv6u9Ro8O5Enhv6RaKB6jICo_683fe002414fd35112affcfcd0eabfbee3fe3d65cdee3be5fde5d1111bf28cd8.jpg", + "name": "GFuwdVnyTudRhBruOXYnVgsUXdBxLR5L_683fe002414fd35112affcfcd0eabfbee3fe3d65cdee3be5fde5d1111bf28cd8.jpg", "visible_name": "car_park.03.jpg", - "original_name": "car_park.03.jpg" + "original_name": "GFuwdVnyTudRhBruOXYnVgsUXdBxLR5L_683fe002414fd35112affcfcd0eabfbee3fe3d65cdee3be5fde5d1111bf28cd8.jpg" } ], - "field_725760": "2709 Bel Meadow Drive", - "field_725761": "Pomona", - "field_725762": "California", - "field_725763": "91755", - "field_725764": "(519) 587-3851", - "field_725765": null, - "field_725787": null, - "field_725789": [ - 20, - 24, - 5, + "field_59793": "2709 Bel Meadow Drive", + "field_59794": "Pomona", + "field_59795": "91755", + "field_59796": "(519) 587-3851", + "field_59855": null, + "field_59871": null, + "field_59797": [ 3, - 11 + 5, + 11, + 20, + 24 ], - "field_725791": [ + "field_59798": [ 4, 6 ], - "field_740388": null + "field_59838": null, + "field_59799": "pomona@example.com" } - ] + ], + "data_sync": null }, { - "id": 114512, + "id": 5700, "name": "Staff", - "order": 5, + "order": 6, "fields": [ { - "id": 725766, + "id": 59800, "type": "text", "name": "Name", + "description": null, "order": 0, "primary": true, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, "text_default": "" }, { - "id": 725767, + "id": 59801, "type": "file", "name": "Photo", + "description": null, "order": 1, - "primary": false + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false }, { - "id": 725768, + "id": 59802, "type": "single_select", "name": "Role", + "description": null, "order": 2, "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, "select_options": [ { - "id": 313868, + "id": 21061, "value": "Branch manager", "color": "blue", "order": 0 }, { - "id": 313869, + "id": 21062, "value": "Sales manager", "color": "blue", "order": 1 }, { - "id": 313870, + "id": 21063, "value": "Finance manager", "color": "blue", "order": 2 }, { - "id": 313871, + "id": 21064, "value": "Sales representative", "color": "blue", "order": 3 }, { - "id": 313872, + "id": 21065, "value": "Customer service representative", "color": "blue", "order": 4 }, { - "id": 313873, + "id": 21066, "value": "Service technician", "color": "blue", "order": 5 }, { - "id": 313874, + "id": 21067, "value": "Parts technician", "color": "blue", "order": 6 }, { - "id": 313875, + "id": 21068, "value": "Security", "color": "blue", "order": 7 @@ -9469,110 +13211,190 @@ ] }, { - "id": 725790, + "id": 59803, "type": "link_row", "name": "Branch", + "description": null, "order": 3, "primary": false, - "link_row_table_id": 111553, - "link_row_related_field_id": 725791, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "link_row_table_id": 5699, + "link_row_related_field_id": 59798, + "link_row_limit_selection_view_id": null, "has_related_field": true }, { - "id": 725868, + "id": 59804, "type": "link_row", "name": "Related acquired cars", + "description": null, "order": 4, "primary": false, - "link_row_table_id": 111551, - "link_row_related_field_id": 725759, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "link_row_table_id": 5697, + "link_row_related_field_id": 59774, + "link_row_limit_selection_view_id": null, "has_related_field": true }, { - "id": 725872, + "id": 59805, "type": "text", "name": "Local extension number", + "description": null, "order": 5, "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, "text_default": "" }, { - "id": 725873, + "id": 59806, "type": "phone_number", "name": "Phone number", + "description": null, "order": 6, - "primary": false + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false }, { - "id": 725874, + "id": 59807, "type": "email", "name": "Email address", + "description": null, "order": 7, - "primary": false + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false }, { - "id": 725875, + "id": 59808, "type": "long_text", "name": "Remarks", + "description": null, "order": 8, - "primary": false + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "long_text_enable_rich_text": false }, { - "id": 725876, - "type": "boolean", - "name": "Is active", - "order": 9, - "primary": false - }, - { - "id": 725897, + "id": 59809, "type": "link_row", "name": "Related sales", + "description": null, "order": 10, "primary": false, - "link_row_table_id": 114523, - "link_row_related_field_id": 725896, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "link_row_table_id": 5698, + "link_row_related_field_id": 59786, + "link_row_limit_selection_view_id": null, "has_related_field": true }, { - "id": 727692, - "type": "formula", - "name": "Sales count", + "id": 59845, + "type": "count", + "name": "Count sales", + "description": null, "order": 11, "primary": false, - "error": null, - "date_format": null, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "number_suffix": "", + "number_separator": "", "date_include_time": null, - "date_time_format": null, - "number_decimal_places": 0, + "duration_format": null, + "date_force_timezone": null, + "date_show_tzinfo": null, "array_formula_type": null, - "formula": "count(field(\"Related sales\"))", - "formula_type": "number" + "error": null, + "number_decimal_places": 0, + "date_time_format": null, + "number_prefix": "", + "nullable": false, + "date_format": null, + "through_field_id": 59809 + }, + { + "id": 59839, + "type": "count", + "name": "Count acquisitions", + "description": null, + "order": 12, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "number_suffix": "", + "number_separator": "", + "date_include_time": null, + "duration_format": null, + "date_force_timezone": null, + "date_show_tzinfo": null, + "array_formula_type": null, + "error": null, + "number_decimal_places": 0, + "date_time_format": null, + "number_prefix": "", + "nullable": false, + "date_format": null, + "through_field_id": 59804 + }, + { + "id": 59810, + "type": "link_row", + "name": "Prospects", + "description": null, + "order": 13, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "link_row_table_id": 5704, + "link_row_related_field_id": 59833, + "link_row_limit_selection_view_id": null, + "has_related_field": true } ], "views": [ { - "id": 170669, + "id": 26491, "type": "grid", "name": "All staff", "order": 1, + "ownership_type": "collaborative", + "owned_by": null, "filter_type": "AND", "filters_disabled": false, "filters": [], + "filter_groups": [], "sortings": [ { - "id": 53139, - "field_id": 725766, + "id": 20391, + "field_id": 59800, "order": "ASC" } ], + "group_bys": [], "decorations": [], "public": false, "row_identifier_type": "count", + "row_height_size": "small", "field_options": [ { - "id": 1041804, - "field_id": 725766, + "id": 261855, + "field_id": 59800, "width": 144, "hidden": false, "order": 0, @@ -9580,17 +13402,17 @@ "aggregation_raw_type": "unique_count" }, { - "id": 1041802, - "field_id": 725767, - "width": 100, + "id": 261856, + "field_id": 59801, + "width": 115, "hidden": false, "order": 1, "aggregation_type": "", "aggregation_raw_type": "" }, { - "id": 1041803, - "field_id": 725768, + "id": 261857, + "field_id": 59802, "width": 156, "hidden": false, "order": 2, @@ -9598,8 +13420,8 @@ "aggregation_raw_type": "" }, { - "id": 1041814, - "field_id": 725790, + "id": 261858, + "field_id": 59803, "width": 125, "hidden": false, "order": 3, @@ -9607,17 +13429,8 @@ "aggregation_raw_type": "empty_count" }, { - "id": 1041987, - "field_id": 725868, - "width": 192, - "hidden": true, - "order": 10, - "aggregation_type": "", - "aggregation_raw_type": "" - }, - { - "id": 1041988, - "field_id": 725872, + "id": 261859, + "field_id": 59805, "width": 208, "hidden": false, "order": 4, @@ -9625,8 +13438,8 @@ "aggregation_raw_type": "unique_count" }, { - "id": 1041989, - "field_id": 725873, + "id": 261860, + "field_id": 59806, "width": 152, "hidden": false, "order": 5, @@ -9634,8 +13447,8 @@ "aggregation_raw_type": "unique_count" }, { - "id": 1041990, - "field_id": 725874, + "id": 261861, + "field_id": 59807, "width": 223, "hidden": false, "order": 6, @@ -9643,248 +13456,449 @@ "aggregation_raw_type": "unique_count" }, { - "id": 1041991, - "field_id": 725875, - "width": 160, + "id": 261862, + "field_id": 59808, + "width": 192, "hidden": false, "order": 7, "aggregation_type": "", "aggregation_raw_type": "" }, { - "id": 1041993, - "field_id": 725876, - "width": 110, + "id": 261863, + "field_id": 59845, + "width": 146, "hidden": false, - "order": 9, - "aggregation_type": "checked_percentage", - "aggregation_raw_type": "empty_count" + "order": 8, + "aggregation_type": "average", + "aggregation_raw_type": "average" }, { - "id": 1042011, - "field_id": 725897, - "width": 141, - "hidden": true, + "id": 261864, + "field_id": 59839, + "width": 200, + "hidden": false, + "order": 9, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261865, + "field_id": 59804, + "width": 192, + "hidden": false, "order": 11, "aggregation_type": "", "aggregation_raw_type": "" }, { - "id": 1045231, - "field_id": 727692, - "width": 131, + "id": 261866, + "field_id": 59809, + "width": 160, "hidden": false, - "order": 8, - "aggregation_type": "average", - "aggregation_raw_type": "average" + "order": 12, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261867, + "field_id": 59810, + "width": 200, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" } ] }, { - "id": 174163, - "type": "kanban", - "name": "By role", + "id": 26492, + "type": "grid", + "name": "All staff grouped by role", "order": 2, + "ownership_type": "collaborative", + "owned_by": null, "filter_type": "AND", "filters_disabled": false, - "filters": [ - { - "id": 68759, - "field_id": 725876, - "type": "boolean", - "value": "1" - } - ], - "sortings": [], - "decorations": [], - "public": false, - "single_select_field_id": 725768, - "card_cover_image_field_id": 725767, - "field_options": [ - { - "id": 43742, - "field_id": 725766, - "hidden": false, - "order": 32767 - }, - { - "id": 43743, - "field_id": 725767, - "hidden": true, - "order": 32767 - }, - { - "id": 43744, - "field_id": 725768, - "hidden": true, - "order": 32767 - }, - { - "id": 43745, - "field_id": 725790, - "hidden": false, - "order": 32767 - }, - { - "id": 43746, - "field_id": 725868, - "hidden": true, - "order": 32767 - }, - { - "id": 43747, - "field_id": 725872, - "hidden": false, - "order": 32767 - }, - { - "id": 43748, - "field_id": 725873, - "hidden": false, - "order": 32767 - }, - { - "id": 43749, - "field_id": 725874, - "hidden": false, - "order": 32767 - }, - { - "id": 43750, - "field_id": 725875, - "hidden": true, - "order": 32767 - }, - { - "id": 43751, - "field_id": 725876, - "hidden": true, - "order": 32767 - }, - { - "id": 43752, - "field_id": 725897, - "hidden": true, - "order": 32767 - }, - { - "id": 43753, - "field_id": 727692, - "hidden": true, - "order": 32767 - } - ] - }, - { - "id": 171181, - "type": "gallery", - "name": "Staff members", - "order": 3, - "filter_type": "AND", - "filters_disabled": false, - "filters": [ - { - "id": 67324, - "field_id": 725876, - "type": "boolean", - "value": "1" - } - ], + "filters": [], + "filter_groups": [], "sortings": [ { - "id": 51837, - "field_id": 725766, + "id": 20392, + "field_id": 59800, + "order": "ASC" + } + ], + "group_bys": [ + { + "id": 3641, + "field_id": 59802, "order": "ASC" } ], "decorations": [], "public": false, - "card_cover_image_field_id": 725767, + "row_identifier_type": "count", + "row_height_size": "small", "field_options": [ { - "id": 76022, - "field_id": 725766, + "id": 261868, + "field_id": 59800, + "width": 144, + "hidden": false, + "order": 0, + "aggregation_type": "unique_count", + "aggregation_raw_type": "unique_count" + }, + { + "id": 261869, + "field_id": 59801, + "width": 115, + "hidden": false, + "order": 1, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261870, + "field_id": 59802, + "width": 156, + "hidden": true, + "order": 2, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261871, + "field_id": 59803, + "width": 125, + "hidden": false, + "order": 3, + "aggregation_type": "not_empty_percentage", + "aggregation_raw_type": "empty_count" + }, + { + "id": 261872, + "field_id": 59805, + "width": 208, + "hidden": false, + "order": 4, + "aggregation_type": "unique_count", + "aggregation_raw_type": "unique_count" + }, + { + "id": 261873, + "field_id": 59806, + "width": 152, + "hidden": false, + "order": 5, + "aggregation_type": "unique_count", + "aggregation_raw_type": "unique_count" + }, + { + "id": 261874, + "field_id": 59807, + "width": 223, + "hidden": false, + "order": 6, + "aggregation_type": "unique_count", + "aggregation_raw_type": "unique_count" + }, + { + "id": 261875, + "field_id": 59808, + "width": 192, + "hidden": false, + "order": 7, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261876, + "field_id": 59845, + "width": 146, + "hidden": false, + "order": 8, + "aggregation_type": "average", + "aggregation_raw_type": "average" + }, + { + "id": 261877, + "field_id": 59839, + "width": 200, + "hidden": false, + "order": 9, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261878, + "field_id": 59804, + "width": 192, + "hidden": false, + "order": 11, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261879, + "field_id": 59809, + "width": 141, + "hidden": false, + "order": 12, + "aggregation_type": "", + "aggregation_raw_type": "" + } + ] + }, + { + "id": 26493, + "type": "grid", + "name": "All staff grouped by branch", + "order": 3, + "ownership_type": "collaborative", + "owned_by": null, + "filter_type": "AND", + "filters_disabled": false, + "filters": [], + "filter_groups": [], + "sortings": [ + { + "id": 20393, + "field_id": 59800, + "order": "ASC" + } + ], + "group_bys": [ + { + "id": 3642, + "field_id": 59803, + "order": "ASC" + } + ], + "decorations": [], + "public": false, + "row_identifier_type": "count", + "row_height_size": "small", + "field_options": [ + { + "id": 261880, + "field_id": 59800, + "width": 144, + "hidden": false, + "order": 0, + "aggregation_type": "unique_count", + "aggregation_raw_type": "unique_count" + }, + { + "id": 261881, + "field_id": 59801, + "width": 115, + "hidden": false, + "order": 1, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261882, + "field_id": 59802, + "width": 156, + "hidden": false, + "order": 2, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261883, + "field_id": 59803, + "width": 125, + "hidden": true, + "order": 3, + "aggregation_type": "not_empty_percentage", + "aggregation_raw_type": "empty_count" + }, + { + "id": 261884, + "field_id": 59805, + "width": 208, + "hidden": false, + "order": 4, + "aggregation_type": "unique_count", + "aggregation_raw_type": "unique_count" + }, + { + "id": 261885, + "field_id": 59806, + "width": 152, + "hidden": false, + "order": 5, + "aggregation_type": "unique_count", + "aggregation_raw_type": "unique_count" + }, + { + "id": 261886, + "field_id": 59807, + "width": 223, + "hidden": false, + "order": 6, + "aggregation_type": "unique_count", + "aggregation_raw_type": "unique_count" + }, + { + "id": 261887, + "field_id": 59808, + "width": 192, + "hidden": false, + "order": 7, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261888, + "field_id": 59845, + "width": 146, + "hidden": false, + "order": 8, + "aggregation_type": "average", + "aggregation_raw_type": "average" + }, + { + "id": 261889, + "field_id": 59839, + "width": 200, + "hidden": false, + "order": 9, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261890, + "field_id": 59804, + "width": 192, + "hidden": false, + "order": 11, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261891, + "field_id": 59809, + "width": 141, + "hidden": false, + "order": 12, + "aggregation_type": "", + "aggregation_raw_type": "" + } + ] + }, + { + "id": 26494, + "type": "gallery", + "name": "Staff members", + "order": 4, + "ownership_type": "collaborative", + "owned_by": null, + "filter_type": "AND", + "filters_disabled": false, + "filters": [], + "filter_groups": [], + "sortings": [ + { + "id": 20394, + "field_id": 59800, + "order": "ASC" + } + ], + "decorations": [], + "public": false, + "card_cover_image_field_id": 59801, + "field_options": [ + { + "id": 25518, + "field_id": 59800, "hidden": false, "order": 32767 }, { - "id": 76023, - "field_id": 725767, + "id": 25519, + "field_id": 59801, "hidden": true, "order": 32767 }, { - "id": 76024, - "field_id": 725768, + "id": 25520, + "field_id": 59802, "hidden": false, "order": 32767 }, { - "id": 76025, - "field_id": 725790, + "id": 25521, + "field_id": 59803, "hidden": false, "order": 32767 }, { - "id": 76026, - "field_id": 725868, + "id": 25522, + "field_id": 59804, "hidden": true, "order": 32767 }, { - "id": 76027, - "field_id": 725872, + "id": 25523, + "field_id": 59805, "hidden": false, "order": 32767 }, { - "id": 76028, - "field_id": 725873, + "id": 25524, + "field_id": 59806, "hidden": false, "order": 32767 }, { - "id": 76029, - "field_id": 725874, + "id": 25525, + "field_id": 59807, + "hidden": false, + "order": 32767 + }, + { + "id": 25526, + "field_id": 59808, "hidden": true, "order": 32767 }, { - "id": 76030, - "field_id": 725875, + "id": 25527, + "field_id": 59809, "hidden": true, "order": 32767 }, { - "id": 76031, - "field_id": 725876, - "hidden": true, + "id": 25528, + "field_id": 59839, + "hidden": false, "order": 32767 }, { - "id": 76032, - "field_id": 725897, - "hidden": true, - "order": 32767 - }, - { - "id": 76033, - "field_id": 727692, + "id": 25529, + "field_id": 59845, "hidden": false, "order": 32767 } ] }, { - "id": 174164, + "id": 26495, "type": "form", "name": "Add staff member", - "order": 4, + "order": 5, + "ownership_type": "collaborative", + "owned_by": null, "public": false, "title": "Add a staff member", "description": "", "cover_image": { - "name": "qC083nsJZM9nvNWSFebTrvFheOpYjyOS_d820f1a973e5c2cfe734b244e7c3121902bdfacf77573df1a546b26d4fc08117.jpg", + "name": "n2mHb0pA2VuSA4JVoi65hqH2PDp0dvxz_d820f1a973e5c2cfe734b244e7c3121902bdfacf77573df1a546b26d4fc08117.jpg", "original_name": "Header.FormalStaff.01.jpg" }, "logo_image": null, @@ -9894,8 +13908,8 @@ "submit_action_redirect_url": "", "field_options": [ { - "id": 100788, - "field_id": 725766, + "id": 25279, + "field_id": 59800, "name": "", "description": "Please enter the full name of the staff member.", "enabled": true, @@ -9903,11 +13917,15 @@ "order": 32767, "show_when_matching_conditions": false, "condition_type": "AND", - "conditions": [] + "conditions": [], + "condition_groups": [], + "field_component": "default", + "include_all_select_options": true, + "allowed_select_options": [] }, { - "id": 100789, - "field_id": 725767, + "id": 25280, + "field_id": 59801, "name": "", "description": "Upload any photo or photos of the staff member.", "enabled": true, @@ -9915,11 +13933,15 @@ "order": 32767, "show_when_matching_conditions": false, "condition_type": "AND", - "conditions": [] + "conditions": [], + "condition_groups": [], + "field_component": "default", + "include_all_select_options": true, + "allowed_select_options": [] }, { - "id": 100790, - "field_id": 725768, + "id": 25281, + "field_id": 59802, "name": "", "description": "Please select the role, title, or responsibility of this staff member.", "enabled": true, @@ -9927,11 +13949,15 @@ "order": 32767, "show_when_matching_conditions": false, "condition_type": "AND", - "conditions": [] + "conditions": [], + "condition_groups": [], + "field_component": "default", + "include_all_select_options": true, + "allowed_select_options": [] }, { - "id": 100791, - "field_id": 725790, + "id": 25282, + "field_id": 59803, "name": "", "description": "Please select the dealership branch this staff member is currently assigned.", "enabled": true, @@ -9939,11 +13965,15 @@ "order": 32767, "show_when_matching_conditions": false, "condition_type": "AND", - "conditions": [] + "conditions": [], + "condition_groups": [], + "field_component": "default", + "include_all_select_options": true, + "allowed_select_options": [] }, { - "id": 100792, - "field_id": 725868, + "id": 25283, + "field_id": 59804, "name": "", "description": "", "enabled": false, @@ -9951,11 +13981,15 @@ "order": 32767, "show_when_matching_conditions": false, "condition_type": "AND", - "conditions": [] + "conditions": [], + "condition_groups": [], + "field_component": "default", + "include_all_select_options": true, + "allowed_select_options": [] }, { - "id": 100793, - "field_id": 725872, + "id": 25284, + "field_id": 59805, "name": "", "description": "Please enter the staff member's local extension number.", "enabled": true, @@ -9963,11 +13997,15 @@ "order": 32767, "show_when_matching_conditions": false, "condition_type": "AND", - "conditions": [] + "conditions": [], + "condition_groups": [], + "field_component": "default", + "include_all_select_options": true, + "allowed_select_options": [] }, { - "id": 100794, - "field_id": 725873, + "id": 25285, + "field_id": 59806, "name": "", "description": "Enter the staff member's phone number.", "enabled": true, @@ -9975,11 +14013,15 @@ "order": 32767, "show_when_matching_conditions": false, "condition_type": "AND", - "conditions": [] + "conditions": [], + "condition_groups": [], + "field_component": "default", + "include_all_select_options": true, + "allowed_select_options": [] }, { - "id": 100795, - "field_id": 725874, + "id": 25286, + "field_id": 59807, "name": "", "description": "Enter the staff member's email address.", "enabled": true, @@ -9987,11 +14029,15 @@ "order": 32767, "show_when_matching_conditions": false, "condition_type": "AND", - "conditions": [] + "conditions": [], + "condition_groups": [], + "field_component": "default", + "include_all_select_options": true, + "allowed_select_options": [] }, { - "id": 100796, - "field_id": 725875, + "id": 25287, + "field_id": 59808, "name": "", "description": "Enter any other notes or brief description about this staff member.", "enabled": true, @@ -9999,23 +14045,15 @@ "order": 32767, "show_when_matching_conditions": false, "condition_type": "AND", - "conditions": [] + "conditions": [], + "condition_groups": [], + "field_component": "default", + "include_all_select_options": true, + "allowed_select_options": [] }, { - "id": 100797, - "field_id": 725876, - "name": "", - "description": "Tick the checkbox below to indicate that this staff member is still actively employed to your organization.", - "enabled": true, - "required": true, - "order": 32767, - "show_when_matching_conditions": false, - "condition_type": "AND", - "conditions": [] - }, - { - "id": 100798, - "field_id": 725897, + "id": 25288, + "field_id": 59809, "name": "", "description": "", "enabled": false, @@ -10023,11 +14061,15 @@ "order": 32767, "show_when_matching_conditions": false, "condition_type": "AND", - "conditions": [] + "conditions": [], + "condition_groups": [], + "field_component": "default", + "include_all_select_options": true, + "allowed_select_options": [] }, { - "id": 100799, - "field_id": 727692, + "id": 25289, + "field_id": 59839, "name": "", "description": "", "enabled": false, @@ -10035,7 +14077,27 @@ "order": 32767, "show_when_matching_conditions": false, "condition_type": "AND", - "conditions": [] + "conditions": [], + "condition_groups": [], + "field_component": "default", + "include_all_select_options": true, + "allowed_select_options": [] + }, + { + "id": 25290, + "field_id": 59845, + "name": "", + "description": "", + "enabled": false, + "required": true, + "order": 32767, + "show_when_matching_conditions": false, + "condition_type": "AND", + "conditions": [], + "condition_groups": [], + "field_component": "default", + "include_all_select_options": true, + "allowed_select_options": [] } ] } @@ -10045,407 +14107,563 @@ "id": 1, "order": "1.00000000000000000000", "created_on": "2022-11-13T16:24:50.967308+00:00", - "updated_on": "2022-11-20T21:46:22.093766+00:00", - "field_725766": "Terrence Hernandez", - "field_725767": [ + "updated_on": "2025-02-11T08:59:48.622009+00:00", + "last_modified_by": "frederik@baserow.io", + "field_59800": "Terrence Hernandez", + "field_59801": [ { - "name": "mLsl2tI3Wy5gX2agnrjIkyCteju9rtrl_5af29ecc21ebf5294f34d9be647d2b4fba54757dd420ed3cb2d3192dd9747159.jpg", + "name": "GR6hRHu4QB7xH0m320GwJyYLUzjS7VH3_5af29ecc21ebf5294f34d9be647d2b4fba54757dd420ed3cb2d3192dd9747159.jpg", "visible_name": "Man.44.jpg", - "original_name": "Man.44.jpg" + "original_name": "GR6hRHu4QB7xH0m320GwJyYLUzjS7VH3_5af29ecc21ebf5294f34d9be647d2b4fba54757dd420ed3cb2d3192dd9747159.jpg" } ], - "field_725768": 313871, - "field_725790": [ + "field_59802": 21064, + "field_59803": [ 2 ], - "field_725868": [ - 25, - 9, - 4, + "field_59804": [ 1, + 4, + 9, + 14, 16, - 14 + 25 ], - "field_725872": "x9115", - "field_725873": "(515) 931-7937", - "field_725874": "terrence.hernandez@cardealzbr.biz", - "field_725875": "Trusted to acquire a few vehicles for the dealership.", - "field_725876": "true", - "field_725897": [ - 1 - ], - "field_727692": null + "field_59805": "x9115", + "field_59806": "(515) 931-7937", + "field_59807": "terrence.hernandez@example.com", + "field_59808": "Trusted to acquire a few vehicles for the dealership.", + "field_59809": [], + "field_59845": null, + "field_59839": null, + "field_59810": [] }, { "id": 2, "order": "2.00000000000000000000", "created_on": "2022-11-13T16:24:50.967386+00:00", - "updated_on": "2022-11-20T21:46:44.817436+00:00", - "field_725766": "John Hendrickson", - "field_725767": [ + "updated_on": "2025-02-11T08:59:48.622048+00:00", + "last_modified_by": "frederik@baserow.io", + "field_59800": "John Hendrickson", + "field_59801": [ { - "name": "aYgEEYmhNdW43yVVuSXwE3ZBAH6xXIhR_7d55a7f32efd179a5dd35d905c33a80528c84e057c8c6ad07a6f190fd8a135b8.jpg", + "name": "ThdMK1yyzhBquIX06XKBfpAEc6kStB9L_7d55a7f32efd179a5dd35d905c33a80528c84e057c8c6ad07a6f190fd8a135b8.jpg", "visible_name": "Man.18.jpg", - "original_name": "Man.18.jpg" + "original_name": "ThdMK1yyzhBquIX06XKBfpAEc6kStB9L_7d55a7f32efd179a5dd35d905c33a80528c84e057c8c6ad07a6f190fd8a135b8.jpg" } ], - "field_725768": 313869, - "field_725790": [ + "field_59802": 21062, + "field_59803": [ 1 ], - "field_725868": [ + "field_59804": [ + 3, + 5, + 6, + 7, + 11, + 13, + 15, 17, 18, 19, - 6, - 7, - 22, - 15, - 13, 20, - 24, - 5, - 3, - 11 + 22, + 24 ], - "field_725872": "x9007", - "field_725873": "(713) 507-3707", - "field_725874": "john.hendrickson@cardealzbr.biz", - "field_725875": "Partially owned a couple of dealerships.", - "field_725876": "true", - "field_725897": [ - 5 - ], - "field_727692": null + "field_59805": "x9007", + "field_59806": "(713) 507-3707", + "field_59807": "john.hendrickson@example.com", + "field_59808": "Partially owned a couple of dealerships.", + "field_59809": [], + "field_59845": null, + "field_59839": null, + "field_59810": [] }, { "id": 3, "order": "3.00000000000000000000", "created_on": "2022-11-14T15:53:58.655253+00:00", - "updated_on": "2022-11-14T16:15:22.560764+00:00", - "field_725766": "Gregory Martin", - "field_725767": [ + "updated_on": "2025-02-11T09:02:20.793940+00:00", + "last_modified_by": "frederik@baserow.io", + "field_59800": "Gregory Martin", + "field_59801": [ { - "name": "0fJxhhSbffUgv19GbYVFG9FGZBMOhMRd_9280c14e270c9e641b748ecfe5da0b4a3d4ba5b141a394a249febc2bb7ebb19c.jpg", + "name": "D87ZpPC9583ZxjYqdF2WyNpYl3i8DrsA_9280c14e270c9e641b748ecfe5da0b4a3d4ba5b141a394a249febc2bb7ebb19c.jpg", "visible_name": "Man.30.jpg", - "original_name": "Man.30.jpg" + "original_name": "D87ZpPC9583ZxjYqdF2WyNpYl3i8DrsA_9280c14e270c9e641b748ecfe5da0b4a3d4ba5b141a394a249febc2bb7ebb19c.jpg" } ], - "field_725768": 313871, - "field_725790": [ + "field_59802": 21062, + "field_59803": [ 3 ], - "field_725868": [], - "field_725872": "x9027", - "field_725873": "(310) 323-0083", - "field_725874": "gregory.martin@cardealzbr.biz", - "field_725875": "", - "field_725876": "true", - "field_725897": [ - 10 - ], - "field_727692": null + "field_59804": [], + "field_59805": "x9027", + "field_59806": "(310) 323-0083", + "field_59807": "gregory.martin@example.com", + "field_59808": "", + "field_59809": [], + "field_59845": null, + "field_59839": null, + "field_59810": [ + 13, + 15 + ] }, { "id": 4, "order": "3.00000000000000000000", "created_on": "2022-11-14T15:53:58.855608+00:00", - "updated_on": "2022-12-01T22:49:08.628732+00:00", - "field_725766": "Baldovín Delgado", - "field_725767": [ + "updated_on": "2025-02-11T09:02:19.639035+00:00", + "last_modified_by": "frederik@baserow.io", + "field_59800": "Baldov\u00edn Delgado", + "field_59801": [ { - "name": "c5bo3rb3mL3Y8yYpis5M6SLgJxAuESzN_3e4ea491bc171831d98bd16209e167056256efec656b03792cc985f56c52d625.jpg", + "name": "g28NsirFNliHiDiJnC0muq3rLlNCiURU_3e4ea491bc171831d98bd16209e167056256efec656b03792cc985f56c52d625.jpg", "visible_name": "Man.27.jpg", - "original_name": "Man.27.jpg" + "original_name": "g28NsirFNliHiDiJnC0muq3rLlNCiURU_3e4ea491bc171831d98bd16209e167056256efec656b03792cc985f56c52d625.jpg" } ], - "field_725768": 313871, - "field_725790": [ + "field_59802": 21062, + "field_59803": [ 4 ], - "field_725868": [], - "field_725872": "x9772", - "field_725873": "(739) 257-7172", - "field_725874": "baldovín.delgado@cardealzbr.biz", - "field_725875": "Great business background.", - "field_725876": "true", - "field_725897": [ - 2 - ], - "field_727692": null + "field_59804": [], + "field_59805": "x9772", + "field_59806": "(739) 257-7172", + "field_59807": "baldov\u00edn.delgado@example.com", + "field_59808": "Great business background.", + "field_59809": [], + "field_59845": null, + "field_59839": null, + "field_59810": [ + 6, + 8, + 9, + 12, + 14 + ] }, { "id": 5, "order": "4.00000000000000000000", "created_on": "2022-11-14T15:53:59.601549+00:00", - "updated_on": "2022-11-20T21:47:11.128059+00:00", - "field_725766": "Lori Bradley", - "field_725767": [ + "updated_on": "2025-02-11T09:02:16.184969+00:00", + "last_modified_by": "frederik@baserow.io", + "field_59800": "Lori Bradley", + "field_59801": [ { - "name": "CE3z3vdCpC3GpxuOa4xkPi3XaoiaFfAx_46f5081557b701f74b5d9d6b4d0e05ccc805e654ce316722f5e2e4b51fa2994b.jpg", + "name": "P3C1KD0u8dO2ldbPhrCOTSHT04C2IbY0_46f5081557b701f74b5d9d6b4d0e05ccc805e654ce316722f5e2e4b51fa2994b.jpg", "visible_name": "Woman.57.jpg", - "original_name": "Woman.57.jpg" + "original_name": "P3C1KD0u8dO2ldbPhrCOTSHT04C2IbY0_46f5081557b701f74b5d9d6b4d0e05ccc805e654ce316722f5e2e4b51fa2994b.jpg" } ], - "field_725768": 313871, - "field_725790": [ + "field_59802": 21062, + "field_59803": [ 2 ], - "field_725868": [], - "field_725872": "x9358", - "field_725873": "(750) 923-3271", - "field_725874": "lori.bradley@cardealzbr.biz", - "field_725875": "Has been selling vehicles.", - "field_725876": "true", - "field_725897": [ - 3, - 6 - ], - "field_727692": null + "field_59804": [], + "field_59805": "x9358", + "field_59806": "(750) 923-3271", + "field_59807": "lori.bradley@example.com", + "field_59808": "Has been selling vehicles.", + "field_59809": [], + "field_59845": null, + "field_59839": null, + "field_59810": [ + 7, + 10, + 11 + ] }, { "id": 6, "order": "5.00000000000000000000", "created_on": "2022-11-14T15:54:00.295308+00:00", - "updated_on": "2022-11-20T21:47:35.818218+00:00", - "field_725766": "Dorothy Dade", - "field_725767": [ + "updated_on": "2025-02-11T08:59:48.622086+00:00", + "last_modified_by": "frederik@baserow.io", + "field_59800": "Dorothy Dade", + "field_59801": [ { - "name": "GNrOyTGNwetIQkTcz60mqDEIXWW5ETd1_454da00f71f877a9fc6e009fd2baf224b64739d11fe6bc00c1858d9160c3842d.jpg", + "name": "AkxFtptZ5urw0nmXMHsvhKZhMqjujiLr_454da00f71f877a9fc6e009fd2baf224b64739d11fe6bc00c1858d9160c3842d.jpg", "visible_name": "Woman.53.jpg", - "original_name": "Woman.53.jpg" + "original_name": "AkxFtptZ5urw0nmXMHsvhKZhMqjujiLr_454da00f71f877a9fc6e009fd2baf224b64739d11fe6bc00c1858d9160c3842d.jpg" } ], - "field_725768": 313871, - "field_725790": [ + "field_59802": 21064, + "field_59803": [ 4 ], - "field_725868": [], - "field_725872": "x9103", - "field_725873": "(707) 398-3753", - "field_725874": "dorothy.dade@cardealzbr.biz", - "field_725875": "Has a lot of good contacts.", - "field_725876": "true", - "field_725897": [ + "field_59804": [], + "field_59805": "x9103", + "field_59806": "(707) 398-3753", + "field_59807": "dorothy.dade@example.com", + "field_59808": "Has a lot of good contacts.", + "field_59809": [ 8 ], - "field_727692": null + "field_59845": null, + "field_59839": null, + "field_59810": [] }, { "id": 7, "order": "6.00000000000000000000", "created_on": "2022-11-14T15:54:01.032949+00:00", - "updated_on": "2022-11-20T21:47:56.570640+00:00", - "field_725766": "Joyce Lacy", - "field_725767": [ + "updated_on": "2025-02-11T08:59:48.622094+00:00", + "last_modified_by": "frederik@baserow.io", + "field_59800": "Joyce Lacy", + "field_59801": [ { - "name": "0uyDkdfXKGHcByvKOkAByVdQ7BSOHCAr_256ba7a31422ce6ac6ad24491ee05567f3cd4a2c048b2f3da8e249c3bb9c4fd2.jpg", + "name": "c63SxInhWcJfF0H5aoJRlHG9Vegzoz8M_256ba7a31422ce6ac6ad24491ee05567f3cd4a2c048b2f3da8e249c3bb9c4fd2.jpg", "visible_name": "Woman.50.jpg", - "original_name": "Woman.50.jpg" + "original_name": "c63SxInhWcJfF0H5aoJRlHG9Vegzoz8M_256ba7a31422ce6ac6ad24491ee05567f3cd4a2c048b2f3da8e249c3bb9c4fd2.jpg" } ], - "field_725768": 313871, - "field_725790": [ + "field_59802": 21064, + "field_59803": [ 1 ], - "field_725868": [], - "field_725872": "x9002", - "field_725873": "(310) 208-7512", - "field_725874": "joyce.lacy@cardealzbr.biz", - "field_725875": "Knows how to talk to customers effectively.", - "field_725876": "true", - "field_725897": [ + "field_59804": [], + "field_59805": "x9002", + "field_59806": "(310) 208-7512", + "field_59807": "joyce.lacy@example.com", + "field_59808": "Knows how to talk to customers effectively.", + "field_59809": [ 4 ], - "field_727692": null + "field_59845": null, + "field_59839": null, + "field_59810": [] }, { "id": 8, "order": "7.00000000000000000000", "created_on": "2022-11-14T15:56:23.296499+00:00", - "updated_on": "2022-11-20T21:45:55.414465+00:00", - "field_725766": "Ida Rizzo", - "field_725767": [ + "updated_on": "2025-02-11T08:59:48.622102+00:00", + "last_modified_by": "frederik@baserow.io", + "field_59800": "Ida Rizzo", + "field_59801": [ { - "name": "k8wOHRNmh7kAcDPzGRNKCLVGUbOn2vgg_f4f3a606aa392f97d54e76e58891f161bb2d917c1eb2b3d878a324529303d828.jpg", + "name": "GjlVu466E6KW5cwkWFe693A5Jn6erDlv_f4f3a606aa392f97d54e76e58891f161bb2d917c1eb2b3d878a324529303d828.jpg", "visible_name": "Woman.05.jpg", - "original_name": "Woman.05.jpg" + "original_name": "GjlVu466E6KW5cwkWFe693A5Jn6erDlv_f4f3a606aa392f97d54e76e58891f161bb2d917c1eb2b3d878a324529303d828.jpg" } ], - "field_725768": 313871, - "field_725790": [ + "field_59802": 21064, + "field_59803": [ 3 ], - "field_725868": [ + "field_59804": [ + 2, 8, 10, - 23, + 12, 21, - 2, - 12 + 23 ], - "field_725872": "x9205", - "field_725873": "(780) 530-3957", - "field_725874": "ida.rizzo@cardealzbr.biz", - "field_725875": "Tasked to acquire some vehicles by the manager.", - "field_725876": "true", - "field_725897": [ + "field_59805": "x9205", + "field_59806": "(780) 530-3957", + "field_59807": "ida.rizzo@example.com", + "field_59808": "Tasked to acquire some vehicles by the manager.", + "field_59809": [ 9 ], - "field_727692": null + "field_59845": null, + "field_59839": null, + "field_59810": [] }, { "id": 9, "order": "8.00000000000000000000", "created_on": "2022-11-14T15:56:57.212301+00:00", - "updated_on": "2022-11-14T16:15:25.914851+00:00", - "field_725766": "Laura Dieter", - "field_725767": [ + "updated_on": "2025-02-11T08:59:48.622109+00:00", + "last_modified_by": "frederik@baserow.io", + "field_59800": "Laura Dieter", + "field_59801": [ { - "name": "aZDE3HkmA3ZcvVoPgoDlbTGEyxtBcS4G_e1e35baaeb2ce8e682bd3e235200517910d33302a554ad2e3bb2ec1847680ea2.jpg", + "name": "mrZhP5yPZoC6dzQXv4thpbv4MgLpfAd7_e1e35baaeb2ce8e682bd3e235200517910d33302a554ad2e3bb2ec1847680ea2.jpg", "visible_name": "Woman.29.jpg", - "original_name": "Woman.29.jpg" + "original_name": "mrZhP5yPZoC6dzQXv4thpbv4MgLpfAd7_e1e35baaeb2ce8e682bd3e235200517910d33302a554ad2e3bb2ec1847680ea2.jpg" } ], - "field_725768": 313871, - "field_725790": [ + "field_59802": 21064, + "field_59803": [ 1 ], - "field_725868": [], - "field_725872": "x9505", - "field_725873": "(508-392-8227)", - "field_725874": "laura.dieter@cardealzbr.biz", - "field_725875": "", - "field_725876": "true", - "field_725897": [ + "field_59804": [], + "field_59805": "x9505", + "field_59806": "(508-392-8227)", + "field_59807": "laura.dieter@example.com", + "field_59808": "", + "field_59809": [ 7 ], - "field_727692": null + "field_59845": null, + "field_59839": null, + "field_59810": [] } - ] + ], + "data_sync": null }, { - "id": 114524, + "id": 5701, "name": "Customers", - "order": 6, + "order": 7, "fields": [ { - "id": 725840, + "id": 59811, "type": "text", "name": "Name", + "description": null, "order": 0, "primary": true, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, "text_default": "" }, { - "id": 725841, - "type": "file", - "name": "Photo", - "order": 1, - "primary": false - }, - { - "id": 725842, + "id": 59812, "type": "text", - "name": "Street", + "name": "Address", + "description": null, "order": 2, "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, "text_default": "" }, { - "id": 725845, + "id": 59813, "type": "text", "name": "City", + "description": null, "order": 3, "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, "text_default": "" }, { - "id": 725846, + "id": 59814, "type": "text", "name": "State", + "description": null, "order": 4, "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, "text_default": "" }, { - "id": 725847, + "id": 59815, "type": "text", "name": "Zip code", + "description": null, "order": 5, "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, "text_default": "" }, { - "id": 725848, + "id": 59816, "type": "phone_number", "name": "Phone number", + "description": null, "order": 6, - "primary": false + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false }, { - "id": 725849, + "id": 59817, "type": "email", "name": "Email address", + "description": null, "order": 7, - "primary": false + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false }, { - "id": 725850, + "id": 59818, "type": "long_text", "name": "Remarks", + "description": null, "order": 8, - "primary": false + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "long_text_enable_rich_text": false }, { - "id": 725894, + "id": 59819, "type": "link_row", - "name": "Related sales", + "name": "Related offers", + "description": null, "order": 9, "primary": false, - "link_row_table_id": 114523, - "link_row_related_field_id": 725893, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "link_row_table_id": 5698, + "link_row_related_field_id": 59785, + "link_row_limit_selection_view_id": null, "has_related_field": true }, { - "id": 727685, - "type": "formula", - "name": "Transaction count", + "id": 59846, + "type": "count", + "name": "Offers count", + "description": null, "order": 10, "primary": false, - "error": null, - "date_format": null, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "number_suffix": "", + "number_separator": "", "date_include_time": null, - "date_time_format": null, - "number_decimal_places": 0, + "duration_format": null, + "date_force_timezone": null, + "date_show_tzinfo": null, "array_formula_type": null, - "formula": "count(field(\"Related sales\"))", + "error": null, + "number_decimal_places": 0, + "date_time_format": null, + "number_prefix": "", + "nullable": false, + "date_format": null, + "through_field_id": 59819 + }, + { + "id": 59820, + "type": "password", + "name": "Password", + "description": null, + "order": 11, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false + }, + { + "id": 59856, + "type": "formula", + "name": "Accepted offers", + "description": null, + "order": 12, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "number_suffix": "", + "number_separator": "", + "date_include_time": null, + "duration_format": null, + "date_force_timezone": null, + "date_show_tzinfo": null, + "array_formula_type": null, + "error": null, + "number_decimal_places": 0, + "date_time_format": null, + "number_prefix": "", + "nullable": false, + "date_format": null, + "formula": "count(filter(field('Related offers'),totext(lookup('Related offers','Status')) = 'Offer accepted'))", + "formula_type": "number" + }, + { + "id": 59857, + "type": "formula", + "name": "Considered offers", + "description": null, + "order": 13, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "number_suffix": "", + "number_separator": "", + "date_include_time": null, + "duration_format": null, + "date_force_timezone": null, + "date_show_tzinfo": null, + "array_formula_type": null, + "error": null, + "number_decimal_places": 0, + "date_time_format": null, + "number_prefix": "", + "nullable": false, + "date_format": null, + "formula": "count(filter(field('Related offers'),totext(lookup('Related offers','Status')) = 'Under consideration'))", + "formula_type": "number" + }, + { + "id": 59858, + "type": "formula", + "name": "Rejected offers", + "description": null, + "order": 14, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "number_suffix": "", + "number_separator": "", + "date_include_time": null, + "duration_format": null, + "date_force_timezone": null, + "date_show_tzinfo": null, + "array_formula_type": null, + "error": null, + "number_decimal_places": 0, + "date_time_format": null, + "number_prefix": "", + "nullable": false, + "date_format": null, + "formula": "count(filter(field('Related offers'),totext(lookup('Related offers','Status')) = 'Offer rejected'))", "formula_type": "number" } ], "views": [ { - "id": 170690, + "id": 26496, "type": "grid", "name": "All customers", "order": 1, + "ownership_type": "collaborative", + "owned_by": null, "filter_type": "AND", "filters_disabled": false, "filters": [], + "filter_groups": [], "sortings": [ { - "id": 51834, - "field_id": 725840, + "id": 20395, + "field_id": 59811, "order": "ASC" } ], + "group_bys": [], "decorations": [], "public": false, "row_identifier_type": "count", + "row_height_size": "small", "field_options": [ { - "id": 1041945, - "field_id": 725840, + "id": 261892, + "field_id": 59811, "width": 120, "hidden": false, "order": 0, @@ -10453,17 +14671,8 @@ "aggregation_raw_type": "unique_count" }, { - "id": 1041943, - "field_id": 725841, - "width": 100, - "hidden": false, - "order": 1, - "aggregation_type": "", - "aggregation_raw_type": "" - }, - { - "id": 1041944, - "field_id": 725842, + "id": 261893, + "field_id": 59812, "width": 150, "hidden": false, "order": 2, @@ -10471,8 +14680,8 @@ "aggregation_raw_type": "" }, { - "id": 1041948, - "field_id": 725845, + "id": 261894, + "field_id": 59813, "width": 100, "hidden": false, "order": 3, @@ -10480,26 +14689,26 @@ "aggregation_raw_type": "" }, { - "id": 1041949, - "field_id": 725846, - "width": 100, + "id": 261895, + "field_id": 59814, + "width": 137, "hidden": false, "order": 4, "aggregation_type": "", "aggregation_raw_type": "" }, { - "id": 1041950, - "field_id": 725847, - "width": 113, + "id": 261896, + "field_id": 59815, + "width": 129, "hidden": false, "order": 5, "aggregation_type": "", "aggregation_raw_type": "" }, { - "id": 1041951, - "field_id": 725848, + "id": 261897, + "field_id": 59816, "width": 153, "hidden": false, "order": 6, @@ -10507,140 +14716,409 @@ "aggregation_raw_type": "" }, { - "id": 1041952, - "field_id": 725849, - "width": 217, + "id": 261898, + "field_id": 59817, + "width": 320, "hidden": false, "order": 7, "aggregation_type": "", "aggregation_raw_type": "" }, { - "id": 1041953, - "field_id": 725850, - "width": 161, + "id": 261899, + "field_id": 59820, + "width": 134, + "hidden": false, + "order": 8, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261900, + "field_id": 59818, + "width": 219, "hidden": false, "order": 9, "aggregation_type": "", "aggregation_raw_type": "" }, { - "id": 1042014, - "field_id": 725894, + "id": 261901, + "field_id": 59819, "width": 200, - "hidden": true, + "hidden": false, "order": 10, "aggregation_type": "", "aggregation_raw_type": "" }, { - "id": 1045222, - "field_id": 727685, - "width": 172, + "id": 261902, + "field_id": 59846, + "width": 190, "hidden": false, - "order": 8, + "order": 11, "aggregation_type": "average", "aggregation_raw_type": "average" + }, + { + "id": 261903, + "field_id": 59856, + "width": 200, + "hidden": false, + "order": 12, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261904, + "field_id": 59857, + "width": 200, + "hidden": false, + "order": 13, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261905, + "field_id": 59858, + "width": 200, + "hidden": false, + "order": 14, + "aggregation_type": "", + "aggregation_raw_type": "" } ] }, { - "id": 171182, - "type": "gallery", - "name": "Customers", + "id": 26497, + "type": "grid", + "name": "All customers grouped by city", "order": 2, + "ownership_type": "collaborative", + "owned_by": null, "filter_type": "AND", "filters_disabled": false, "filters": [], + "filter_groups": [], "sortings": [ { - "id": 51838, - "field_id": 725840, + "id": 20396, + "field_id": 59811, + "order": "ASC" + } + ], + "group_bys": [ + { + "id": 3643, + "field_id": 59813, "order": "ASC" } ], "decorations": [], "public": false, - "card_cover_image_field_id": 725841, + "row_identifier_type": "count", + "row_height_size": "small", "field_options": [ { - "id": 76034, - "field_id": 725840, + "id": 261906, + "field_id": 59811, + "width": 120, "hidden": false, - "order": 32767 + "order": 0, + "aggregation_type": "unique_count", + "aggregation_raw_type": "unique_count" }, { - "id": 76035, - "field_id": 725841, - "hidden": true, - "order": 32767 - }, - { - "id": 76036, - "field_id": 725842, - "hidden": true, - "order": 32767 - }, - { - "id": 76037, - "field_id": 725845, + "id": 261907, + "field_id": 59812, + "width": 150, "hidden": false, - "order": 32767 + "order": 2, + "aggregation_type": "", + "aggregation_raw_type": "" }, { - "id": 76038, - "field_id": 725846, + "id": 261908, + "field_id": 59813, + "width": 100, "hidden": true, - "order": 32767 + "order": 3, + "aggregation_type": "", + "aggregation_raw_type": "" }, { - "id": 76039, - "field_id": 725847, - "hidden": true, - "order": 32767 - }, - { - "id": 76040, - "field_id": 725848, + "id": 261909, + "field_id": 59814, + "width": 137, "hidden": false, - "order": 32767 + "order": 4, + "aggregation_type": "", + "aggregation_raw_type": "" }, { - "id": 76041, - "field_id": 725849, + "id": 261910, + "field_id": 59815, + "width": 129, "hidden": false, - "order": 32767 + "order": 5, + "aggregation_type": "", + "aggregation_raw_type": "" }, { - "id": 76042, - "field_id": 725850, - "hidden": true, - "order": 32767 - }, - { - "id": 76043, - "field_id": 725894, - "hidden": true, - "order": 32767 - }, - { - "id": 76044, - "field_id": 727685, + "id": 261911, + "field_id": 59816, + "width": 153, "hidden": false, - "order": 32767 + "order": 6, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261912, + "field_id": 59817, + "width": 320, + "hidden": false, + "order": 7, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261913, + "field_id": 59820, + "width": 134, + "hidden": true, + "order": 8, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261914, + "field_id": 59818, + "width": 219, + "hidden": false, + "order": 9, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261915, + "field_id": 59819, + "width": 200, + "hidden": false, + "order": 10, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261916, + "field_id": 59846, + "width": 190, + "hidden": false, + "order": 11, + "aggregation_type": "average", + "aggregation_raw_type": "average" + }, + { + "id": 261917, + "field_id": 59856, + "width": 200, + "hidden": false, + "order": 12, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261918, + "field_id": 59857, + "width": 200, + "hidden": false, + "order": 13, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261919, + "field_id": 59858, + "width": 200, + "hidden": false, + "order": 14, + "aggregation_type": "", + "aggregation_raw_type": "" } ] }, { - "id": 174161, + "id": 26498, + "type": "grid", + "name": "Customers with considered offers", + "order": 3, + "ownership_type": "collaborative", + "owned_by": null, + "filter_type": "AND", + "filters_disabled": false, + "filters": [ + { + "id": 13982, + "field_id": 59857, + "type": "higher_than", + "value": "0", + "group": null + } + ], + "filter_groups": [], + "sortings": [ + { + "id": 20397, + "field_id": 59811, + "order": "ASC" + } + ], + "group_bys": [], + "decorations": [], + "public": false, + "row_identifier_type": "count", + "row_height_size": "small", + "field_options": [ + { + "id": 261920, + "field_id": 59811, + "width": 120, + "hidden": false, + "order": 0, + "aggregation_type": "unique_count", + "aggregation_raw_type": "unique_count" + }, + { + "id": 261921, + "field_id": 59812, + "width": 150, + "hidden": false, + "order": 2, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261922, + "field_id": 59813, + "width": 100, + "hidden": true, + "order": 3, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261923, + "field_id": 59814, + "width": 137, + "hidden": false, + "order": 4, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261924, + "field_id": 59815, + "width": 129, + "hidden": false, + "order": 5, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261925, + "field_id": 59816, + "width": 153, + "hidden": false, + "order": 6, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261926, + "field_id": 59817, + "width": 320, + "hidden": false, + "order": 7, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261927, + "field_id": 59820, + "width": 134, + "hidden": true, + "order": 8, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261928, + "field_id": 59818, + "width": 219, + "hidden": false, + "order": 9, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261929, + "field_id": 59819, + "width": 200, + "hidden": false, + "order": 10, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261930, + "field_id": 59846, + "width": 190, + "hidden": false, + "order": 11, + "aggregation_type": "average", + "aggregation_raw_type": "average" + }, + { + "id": 261931, + "field_id": 59856, + "width": 200, + "hidden": false, + "order": 12, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261932, + "field_id": 59857, + "width": 200, + "hidden": false, + "order": 13, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261933, + "field_id": 59858, + "width": 200, + "hidden": false, + "order": 14, + "aggregation_type": "", + "aggregation_raw_type": "" + } + ] + }, + { + "id": 26499, "type": "form", "name": "Add customer", - "order": 3, + "order": 4, + "ownership_type": "collaborative", + "owned_by": null, "public": false, "title": "Add a customer", "description": "", "cover_image": { - "name": "MYJ10jotRznoaN5TvIdxsFqlFmzTTgub_ba840af86db7cce209087d53ec7dac47cef5bd6935161ca50b59e0e4c511434b.jpg", + "name": "PV5FDliaCb2TsubWCwyjxzMrbmPDg2dk_ba840af86db7cce209087d53ec7dac47cef5bd6935161ca50b59e0e4c511434b.jpg", "original_name": "Header.Clients.02.jpg" }, "logo_image": null, @@ -10650,8 +15128,8 @@ "submit_action_redirect_url": "", "field_options": [ { - "id": 100777, - "field_id": 725840, + "id": 25291, + "field_id": 59811, "name": "", "description": "Please enter the customer's full name.", "enabled": true, @@ -10659,23 +15137,15 @@ "order": 32767, "show_when_matching_conditions": false, "condition_type": "AND", - "conditions": [] + "conditions": [], + "condition_groups": [], + "field_component": "default", + "include_all_select_options": true, + "allowed_select_options": [] }, { - "id": 100778, - "field_id": 725841, - "name": "", - "description": "Upload any photo or photos of this customer.", - "enabled": true, - "required": false, - "order": 32767, - "show_when_matching_conditions": false, - "condition_type": "AND", - "conditions": [] - }, - { - "id": 100779, - "field_id": 725842, + "id": 25292, + "field_id": 59812, "name": "", "description": "Please enter the street of the customer's address.", "enabled": true, @@ -10683,11 +15153,15 @@ "order": 32767, "show_when_matching_conditions": false, "condition_type": "AND", - "conditions": [] + "conditions": [], + "condition_groups": [], + "field_component": "default", + "include_all_select_options": true, + "allowed_select_options": [] }, { - "id": 100780, - "field_id": 725845, + "id": 25293, + "field_id": 59813, "name": "", "description": "Please enter the city of the customer's address.", "enabled": true, @@ -10695,11 +15169,15 @@ "order": 32767, "show_when_matching_conditions": false, "condition_type": "AND", - "conditions": [] + "conditions": [], + "condition_groups": [], + "field_component": "default", + "include_all_select_options": true, + "allowed_select_options": [] }, { - "id": 100781, - "field_id": 725846, + "id": 25294, + "field_id": 59814, "name": "", "description": "Please enter the state of the customer's address.", "enabled": true, @@ -10707,11 +15185,15 @@ "order": 32767, "show_when_matching_conditions": false, "condition_type": "AND", - "conditions": [] + "conditions": [], + "condition_groups": [], + "field_component": "default", + "include_all_select_options": true, + "allowed_select_options": [] }, { - "id": 100782, - "field_id": 725847, + "id": 25295, + "field_id": 59815, "name": "", "description": "Enter the zip code of the customer's address.", "enabled": true, @@ -10719,11 +15201,15 @@ "order": 32767, "show_when_matching_conditions": false, "condition_type": "AND", - "conditions": [] + "conditions": [], + "condition_groups": [], + "field_component": "default", + "include_all_select_options": true, + "allowed_select_options": [] }, { - "id": 100783, - "field_id": 725848, + "id": 25296, + "field_id": 59816, "name": "", "description": "Enter the customer's phone number.", "enabled": true, @@ -10731,11 +15217,15 @@ "order": 32767, "show_when_matching_conditions": false, "condition_type": "AND", - "conditions": [] + "conditions": [], + "condition_groups": [], + "field_component": "default", + "include_all_select_options": true, + "allowed_select_options": [] }, { - "id": 100784, - "field_id": 725849, + "id": 25297, + "field_id": 59817, "name": "", "description": "Enter the customer's email address.", "enabled": true, @@ -10743,11 +15233,15 @@ "order": 32767, "show_when_matching_conditions": false, "condition_type": "AND", - "conditions": [] + "conditions": [], + "condition_groups": [], + "field_component": "default", + "include_all_select_options": true, + "allowed_select_options": [] }, { - "id": 100785, - "field_id": 725850, + "id": 25298, + "field_id": 59818, "name": "", "description": "Enter any other notes or brief description about this customer.", "enabled": true, @@ -10755,11 +15249,15 @@ "order": 32767, "show_when_matching_conditions": false, "condition_type": "AND", - "conditions": [] + "conditions": [], + "condition_groups": [], + "field_component": "default", + "include_all_select_options": true, + "allowed_select_options": [] }, { - "id": 100786, - "field_id": 725894, + "id": 25299, + "field_id": 59819, "name": "", "description": "", "enabled": false, @@ -10767,11 +15265,15 @@ "order": 32767, "show_when_matching_conditions": false, "condition_type": "AND", - "conditions": [] + "conditions": [], + "condition_groups": [], + "field_component": "default", + "include_all_select_options": true, + "allowed_select_options": [] }, { - "id": 100787, - "field_id": 727685, + "id": 25300, + "field_id": 59846, "name": "", "description": "", "enabled": false, @@ -10779,7 +15281,11 @@ "order": 32767, "show_when_matching_conditions": false, "condition_type": "AND", - "conditions": [] + "conditions": [], + "condition_groups": [], + "field_component": "default", + "include_all_select_options": true, + "allowed_select_options": [] } ] } @@ -10789,135 +15295,15072 @@ "id": 1, "order": "1.00000000000000000000", "created_on": "2022-11-13T16:50:42.333351+00:00", - "updated_on": "2022-11-20T21:26:46.856038+00:00", - "field_725840": "Marcus Presley", - "field_725841": [ - { - "name": "DpAJbcKkEftBO3d6kQ5Dp0JpnoRc2WQn_5826600e4f0d54d9d75ed7d1505705b09c94c2a738c09ae76a4bbc5ccce67b26.jpg", - "visible_name": "Man.05.jpg", - "original_name": "Man.05.jpg" - } - ], - "field_725842": "5217 Poplar Avenue", - "field_725845": "San Diego", - "field_725846": "California", - "field_725847": "92101", - "field_725848": "(519) 515-3059", - "field_725849": "marcus.presley@geemailzbr.net", - "field_725850": "Let's get back to this customer and upsale.", - "field_725894": [ + "updated_on": "2025-03-05T16:17:25.843902+00:00", + "last_modified_by": "frederik@baserow.io", + "field_59811": "Marcus Presley", + "field_59812": "5217 Poplar Avenue", + "field_59813": "San Diego", + "field_59814": "California", + "field_59815": "92101", + "field_59816": "(519) 515-3059", + "field_59817": "marcus.presley@example.com", + "field_59818": "Let's get back to this customer and upsale.", + "field_59819": [ 2, + 5, 8 ], - "field_727685": null + "field_59846": null, + "field_59820": "pbkdf2_sha256$720000$mwaRhcfCSNM9kI3Xqnr4fm$o5pcwEMh9Ga/cfk/vGkPZF5wygLb8yo8y1ZOBMN5XU8=", + "field_59856": null, + "field_59857": null, + "field_59858": null }, { "id": 2, "order": "2.00000000000000000000", "created_on": "2022-11-13T16:50:42.333438+00:00", - "updated_on": "2022-11-20T21:26:59.833610+00:00", - "field_725840": "Homer Bradley", - "field_725841": [ - { - "name": "bd7cJ6y2KsjkZ2NH4xSZxqAhju0WKTqC_73a71c3d3fcae5a76985bc5e909cee392fe098a6ca874509d0f8b4b826ec725a.jpg", - "visible_name": "Man.50.jpg", - "original_name": "Man.50.jpg" - } + "updated_on": "2025-03-05T16:17:24.056267+00:00", + "last_modified_by": "frederik@baserow.io", + "field_59811": "Homer Bradley", + "field_59812": "2753 Fincham Road", + "field_59813": "San Diego", + "field_59814": "California", + "field_59815": "92117", + "field_59816": "(750) 470-3937", + "field_59817": "homer.bradley@example.com", + "field_59818": "Happy customer.", + "field_59819": [ + 18, + 9, + 11, + 14, + 12, + 20, + 21 ], - "field_725842": "2753 Fincham Road", - "field_725845": "San Diego", - "field_725846": "California", - "field_725847": "92117", - "field_725848": "(750) 470-3937", - "field_725849": "homer.bradley@geemailzbr.net", - "field_725850": "Happy customer.", - "field_725894": [ - 5, - 9 - ], - "field_727685": null + "field_59846": null, + "field_59820": "pbkdf2_sha256$720000$m5JWSoe2CqXV7JsxYyYtBj$wXWUfzkJ9Gc6FMXEsX3SyUgRoJrKrjUWwKqKNt1Py4Q=", + "field_59856": null, + "field_59857": null, + "field_59858": null }, { "id": 3, "order": "3.00000000000000000000", "created_on": "2022-11-14T15:35:38.886481+00:00", - "updated_on": "2022-11-20T21:27:14.272420+00:00", - "field_725840": "Peggy Jordan", - "field_725841": [ - { - "name": "YTj8EMBtiF8PivKpwynpWxQ9lzotd9cd_7d8fcdd9a406997bfc59d87ef2fa2407e184c86a0eefc106ca70a6b45cb5efe9.jpg", - "visible_name": "Woman.56.jpg", - "original_name": "Woman.56.jpg" - } - ], - "field_725842": "3861 Sunny Day Drive", - "field_725845": "Irvine", - "field_725846": "California", - "field_725847": "92513", - "field_725848": "(713) 853-2923", - "field_725849": "peggy.jordan@geemailzbr.net", - "field_725850": "Promised to be back for more.", - "field_725894": [ + "updated_on": "2025-03-05T16:17:27.515300+00:00", + "last_modified_by": "frederik@baserow.io", + "field_59811": "Peggy Jordan", + "field_59812": "3861 Sunny Day Drive", + "field_59813": "Irvine", + "field_59814": "California", + "field_59815": "92513", + "field_59816": "(713) 853-2923", + "field_59817": "peggy.jordan@example.com", + "field_59818": "Promised to be back for more.", + "field_59819": [ 1, - 3 + 3, + 13 ], - "field_727685": null + "field_59846": null, + "field_59820": "pbkdf2_sha256$720000$nTayZfrSHT67Uxf9FchySf$bjoDgBAcuNedoRkdspwBT+0x5N3a/t2R2wvq4WOGO5k=", + "field_59856": null, + "field_59857": null, + "field_59858": null }, { "id": 4, "order": "4.00000000000000000000", "created_on": "2022-11-14T15:35:39.351599+00:00", - "updated_on": "2022-11-20T21:26:35.590233+00:00", - "field_725840": "Ada Johnson", - "field_725841": [ - { - "name": "DKFi5uEhnKedpIoqMp1EBq2xuKBIKXHu_567504f73c70405771879c6331ab20c2a1121d5fa1240e3af31d40fc86d3ed32.jpg", - "visible_name": "Woman.48.jpg", - "original_name": "Woman.48.jpg" - } + "updated_on": "2025-03-05T16:17:20.079381+00:00", + "last_modified_by": "frederik@baserow.io", + "field_59811": "Ada Johnson", + "field_59812": "2239 Brookview Drive", + "field_59813": "San Jose", + "field_59814": "California", + "field_59815": "95113", + "field_59816": "342543254", + "field_59817": "ada.johnson@example.com", + "field_59818": "Let's get back to this customer and upsale.", + "field_59819": [ + 6, + 22, + 23 ], - "field_725842": "2239 Brookview Drive", - "field_725845": "San Jose", - "field_725846": "California", - "field_725847": "95113", - "field_725848": "(308) 998-0917", - "field_725849": "ada.johnson@geemailzbr.net", - "field_725850": "Let's get back to this customer and upsale.", - "field_725894": [ - 6 - ], - "field_727685": null + "field_59846": null, + "field_59820": "pbkdf2_sha256$720000$KwqGbrxpQbRzra7WH3VJgm$8Hf9Y2yH0zRUjYUz3nE0KExIXr/A196oZD2OVpTpt+g=", + "field_59856": null, + "field_59857": null, + "field_59858": null }, { "id": 5, "order": "5.00000000000000000000", "created_on": "2022-11-14T15:35:40.639494+00:00", - "updated_on": "2022-11-20T21:26:21.896417+00:00", - "field_725840": "Gladys Quintero", - "field_725841": [ - { - "name": "LXEFNBAttGS4H34P5zXPSphL2T42e4hb_19f16bd8440e44b1dd11c837172c9b9a2c4784fa94442e631dc94a56c4c1227e.jpg", - "visible_name": "Woman.43.jpg", - "original_name": "Woman.43.jpg" - } - ], - "field_725842": "510 Diane Street", - "field_725845": "Oxnard", - "field_725846": "California", - "field_725847": "93030", - "field_725848": "(805) 319-9132", - "field_725849": "gladys.quintero@geemailzbr.net", - "field_725850": "Frequent buyer.", - "field_725894": [ + "updated_on": "2025-03-05T16:17:22.147589+00:00", + "last_modified_by": "frederik@baserow.io", + "field_59811": "Gladys Quintero", + "field_59812": "510 Diane Street", + "field_59813": "Oxnard", + "field_59814": "California", + "field_59815": "93030", + "field_59816": "(805) 319-9132", + "field_59817": "gladys.quintero@example.com", + "field_59818": "Frequent buyer.", + "field_59819": [ + 17, 4, 7, 10 ], - "field_727685": null + "field_59846": null, + "field_59820": "pbkdf2_sha256$720000$ztBjhsxWvblqt4JoHuwAif$LBSpMLzGSF6pdgdy+HsCZGpifLB6GUO19RISQY/6o1k=", + "field_59856": null, + "field_59857": null, + "field_59858": null } - ] + ], + "data_sync": null + }, + { + "id": 5702, + "name": "Reviews", + "order": 8, + "fields": [ + { + "id": 59821, + "type": "text", + "name": "Title", + "description": null, + "order": 0, + "primary": true, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "text_default": "" + }, + { + "id": 59822, + "type": "long_text", + "name": "Description", + "description": null, + "order": 1, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "long_text_enable_rich_text": false + }, + { + "id": 59823, + "type": "single_select", + "name": "Stars", + "description": null, + "order": 2, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "select_options": [ + { + "id": 21069, + "value": "\u2b50\u2b50\u2b50\u2b50\u2b50", + "color": "dark-green", + "order": 0 + }, + { + "id": 21070, + "value": "\u2b50\u2b50\u2b50\u2b50", + "color": "light-green", + "order": 1 + }, + { + "id": 21071, + "value": "\u2b50\u2b50\u2b50", + "color": "yellow", + "order": 2 + }, + { + "id": 21072, + "value": "\u2b50\u2b50", + "color": "red", + "order": 3 + }, + { + "id": 21073, + "value": "\u2b50", + "color": "darker-red", + "order": 4 + } + ] + }, + { + "id": 59859, + "type": "formula", + "name": "Score", + "description": null, + "order": 3, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "number_suffix": "", + "number_separator": "", + "date_include_time": null, + "duration_format": null, + "date_force_timezone": null, + "date_show_tzinfo": null, + "array_formula_type": null, + "error": null, + "number_decimal_places": 0, + "date_time_format": null, + "number_prefix": "", + "nullable": false, + "date_format": null, + "formula": "length(totext(field('Stars')))", + "formula_type": "number" + }, + { + "id": 59824, + "type": "link_row", + "name": "Sale", + "description": null, + "order": 4, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "link_row_table_id": 5698, + "link_row_related_field_id": 59788, + "link_row_limit_selection_view_id": null, + "has_related_field": true + }, + { + "id": 59860, + "type": "rollup", + "name": "Customer name", + "description": null, + "order": 5, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "number_suffix": "", + "number_separator": "", + "date_include_time": null, + "duration_format": null, + "date_force_timezone": null, + "date_show_tzinfo": null, + "array_formula_type": null, + "error": null, + "number_decimal_places": null, + "date_time_format": null, + "number_prefix": "", + "nullable": true, + "date_format": null, + "through_field_id": 59824, + "target_field_id": 59785, + "rollup_function": "min" + }, + { + "id": 59825, + "type": "created_on", + "name": "Created on", + "description": null, + "order": 6, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "date_format": "ISO", + "date_include_time": true, + "date_time_format": "24", + "date_show_tzinfo": false, + "date_force_timezone": null + }, + { + "id": 59861, + "type": "formula", + "name": "Created on (format)", + "description": null, + "order": 7, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "number_suffix": "", + "number_separator": "", + "date_include_time": null, + "duration_format": null, + "date_force_timezone": null, + "date_show_tzinfo": null, + "array_formula_type": null, + "error": null, + "number_decimal_places": null, + "date_time_format": null, + "number_prefix": "", + "nullable": true, + "date_format": null, + "formula": "datetime_format(field('Created on'),'YYYY - MM - DD')", + "formula_type": "text" + }, + { + "id": 59868, + "type": "rollup", + "name": "Customer email", + "description": null, + "order": 8, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "number_suffix": "", + "number_separator": "", + "date_include_time": null, + "duration_format": null, + "date_force_timezone": null, + "date_show_tzinfo": null, + "array_formula_type": null, + "error": null, + "number_decimal_places": null, + "date_time_format": null, + "number_prefix": "", + "nullable": true, + "date_format": null, + "through_field_id": 59824, + "target_field_id": 59854, + "rollup_function": "min" + }, + { + "id": 59826, + "type": "link_row", + "name": "Car", + "description": null, + "order": 10, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "link_row_table_id": 5697, + "link_row_related_field_id": 59778, + "link_row_limit_selection_view_id": null, + "has_related_field": true + } + ], + "views": [ + { + "id": 26500, + "type": "grid", + "name": "All reviews", + "order": 1, + "ownership_type": "collaborative", + "owned_by": "frederik@baserow.io", + "filter_type": "AND", + "filters_disabled": false, + "filters": [], + "filter_groups": [], + "sortings": [ + { + "id": 20398, + "field_id": 59825, + "order": "DESC" + } + ], + "group_bys": [], + "decorations": [], + "public": false, + "row_identifier_type": "id", + "row_height_size": "small", + "field_options": [ + { + "id": 261934, + "field_id": 59821, + "width": 200, + "hidden": false, + "order": 0, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261935, + "field_id": 59822, + "width": 200, + "hidden": false, + "order": 1, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261936, + "field_id": 59823, + "width": 137, + "hidden": false, + "order": 2, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261937, + "field_id": 59824, + "width": 131, + "hidden": false, + "order": 3, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261938, + "field_id": 59826, + "width": 200, + "hidden": false, + "order": 4, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261939, + "field_id": 59860, + "width": 200, + "hidden": false, + "order": 5, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261940, + "field_id": 59868, + "width": 200, + "hidden": true, + "order": 6, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261941, + "field_id": 59859, + "width": 119, + "hidden": false, + "order": 7, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261942, + "field_id": 59825, + "width": 200, + "hidden": false, + "order": 8, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261943, + "field_id": 59861, + "width": 200, + "hidden": true, + "order": 9, + "aggregation_type": "", + "aggregation_raw_type": "" + } + ] + }, + { + "id": 26501, + "type": "grid", + "name": "All reviews grouped by score", + "order": 2, + "ownership_type": "collaborative", + "owned_by": "frederik@baserow.io", + "filter_type": "AND", + "filters_disabled": false, + "filters": [], + "filter_groups": [], + "sortings": [ + { + "id": 20399, + "field_id": 59825, + "order": "DESC" + } + ], + "group_bys": [ + { + "id": 3644, + "field_id": 59859, + "order": "DESC" + } + ], + "decorations": [], + "public": false, + "row_identifier_type": "id", + "row_height_size": "small", + "field_options": [ + { + "id": 261944, + "field_id": 59821, + "width": 200, + "hidden": false, + "order": 0, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261945, + "field_id": 59822, + "width": 200, + "hidden": false, + "order": 1, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261946, + "field_id": 59823, + "width": 137, + "hidden": false, + "order": 2, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261947, + "field_id": 59824, + "width": 131, + "hidden": false, + "order": 3, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261948, + "field_id": 59826, + "width": 200, + "hidden": false, + "order": 4, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261949, + "field_id": 59860, + "width": 200, + "hidden": false, + "order": 6, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261950, + "field_id": 59859, + "width": 119, + "hidden": true, + "order": 7, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261951, + "field_id": 59825, + "width": 200, + "hidden": false, + "order": 8, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261952, + "field_id": 59861, + "width": 200, + "hidden": true, + "order": 9, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261953, + "field_id": 59868, + "width": 200, + "hidden": true, + "order": 10, + "aggregation_type": "", + "aggregation_raw_type": "" + } + ] + }, + { + "id": 26502, + "type": "grid", + "name": "All reviews grouped by customer", + "order": 3, + "ownership_type": "collaborative", + "owned_by": "frederik@baserow.io", + "filter_type": "AND", + "filters_disabled": false, + "filters": [], + "filter_groups": [], + "sortings": [ + { + "id": 20400, + "field_id": 59825, + "order": "DESC" + } + ], + "group_bys": [ + { + "id": 3645, + "field_id": 59860, + "order": "DESC" + } + ], + "decorations": [], + "public": false, + "row_identifier_type": "id", + "row_height_size": "small", + "field_options": [ + { + "id": 261954, + "field_id": 59821, + "width": 200, + "hidden": false, + "order": 0, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261955, + "field_id": 59822, + "width": 200, + "hidden": false, + "order": 1, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261956, + "field_id": 59823, + "width": 137, + "hidden": false, + "order": 2, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261957, + "field_id": 59824, + "width": 131, + "hidden": false, + "order": 3, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261958, + "field_id": 59826, + "width": 200, + "hidden": false, + "order": 4, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261959, + "field_id": 59860, + "width": 200, + "hidden": false, + "order": 5, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261960, + "field_id": 59859, + "width": 119, + "hidden": true, + "order": 6, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261961, + "field_id": 59825, + "width": 200, + "hidden": false, + "order": 7, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261962, + "field_id": 59861, + "width": 200, + "hidden": true, + "order": 8, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261963, + "field_id": 59868, + "width": 200, + "hidden": true, + "order": 9, + "aggregation_type": "", + "aggregation_raw_type": "" + } + ] + }, + { + "id": 26503, + "type": "grid", + "name": "Top reviews", + "order": 4, + "ownership_type": "collaborative", + "owned_by": "frederik@baserow.io", + "filter_type": "AND", + "filters_disabled": false, + "filters": [], + "filter_groups": [], + "sortings": [ + { + "id": 20401, + "field_id": 59859, + "order": "DESC" + }, + { + "id": 20402, + "field_id": 59825, + "order": "ASC" + } + ], + "group_bys": [], + "decorations": [], + "public": false, + "row_identifier_type": "id", + "row_height_size": "small", + "field_options": [ + { + "id": 261964, + "field_id": 59821, + "width": 200, + "hidden": false, + "order": 0, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261965, + "field_id": 59822, + "width": 200, + "hidden": false, + "order": 1, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261966, + "field_id": 59823, + "width": 137, + "hidden": false, + "order": 2, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261967, + "field_id": 59824, + "width": 131, + "hidden": false, + "order": 3, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261968, + "field_id": 59860, + "width": 200, + "hidden": false, + "order": 4, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261969, + "field_id": 59859, + "width": 119, + "hidden": false, + "order": 5, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261970, + "field_id": 59825, + "width": 200, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261971, + "field_id": 59861, + "width": 200, + "hidden": true, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + } + ] + } + ], + "rows": [ + { + "id": 1, + "order": "1.00000000000000000000", + "created_on": "2025-02-07T14:01:40.619892+00:00", + "updated_on": "2025-02-11T13:59:25.923213+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59821": "Amazing Experience!", + "field_59822": "I had a fantastic experience buying my new car at ABC Motors. The staff was incredibly friendly and knowledgeable, guiding me through every step of the process. They answered all my questions and made sure I felt comfortable with my purchase. Highly recommend!", + "field_59823": 21069, + "field_59859": null, + "field_59824": [ + 4 + ], + "field_59860": null, + "field_59825": null, + "field_59861": null, + "field_59868": null, + "field_59826": [ + 15 + ] + }, + { + "id": 2, + "order": "2.00000000000000000000", + "created_on": "2025-02-07T14:01:40.619931+00:00", + "updated_on": "2025-02-11T13:59:25.923258+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59821": "Great Selection and Service", + "field_59822": "I found the perfect SUV at XYZ Dealership. The selection was impressive, and the sales team was attentive without being pushy. I appreciate how they worked with my budget to find the right financing option. Very happy with my new vehicle!", + "field_59823": 21070, + "field_59859": null, + "field_59824": [ + 10 + ], + "field_59860": null, + "field_59825": null, + "field_59861": null, + "field_59868": null, + "field_59826": [ + 8 + ] + }, + { + "id": 3, + "order": "3.00000000000000000000", + "created_on": "2025-02-07T14:01:40.619940+00:00", + "updated_on": "2025-02-11T13:59:25.923272+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59821": "Smooth and Easy Process", + "field_59822": "Buying my first car was a breeze thanks to the amazing team at 123 Auto Sales. They made the entire process smooth and easy, and I walked away with a great deal. The follow-up service has been excellent as well. I couldn\u2019t be happier!", + "field_59823": 21069, + "field_59859": null, + "field_59824": [ + 2 + ], + "field_59860": null, + "field_59825": null, + "field_59861": null, + "field_59868": null, + "field_59826": [ + 11 + ] + }, + { + "id": 4, + "order": "4.00000000000000000000", + "created_on": "2025-02-07T14:01:40.619946+00:00", + "updated_on": "2025-02-11T13:59:25.923284+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59821": "Disappointed with the Follow-Up", + "field_59822": "While the initial purchase experience was okay, I was disappointed with the follow-up after the sale. I had some questions about the car features, and it took longer than expected to get a response. The car itself is great, but the service could improve.", + "field_59823": 21071, + "field_59859": null, + "field_59824": [ + 7 + ], + "field_59860": null, + "field_59825": null, + "field_59861": null, + "field_59868": null, + "field_59826": [ + 6 + ] + }, + { + "id": 5, + "order": "5.00000000000000000000", + "created_on": "2025-02-07T14:01:40.619952+00:00", + "updated_on": "2025-02-11T13:59:25.923296+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59821": "Great Financing Options", + "field_59822": "I was pleasantly surprised by the financing options available at LMN Motors. They helped me find a plan that fit my budget perfectly. The staff was patient and took the time to explain everything. I love my new car and would definitely return!", + "field_59823": 21069, + "field_59859": null, + "field_59824": [ + 3, + 13, + 14 + ], + "field_59860": null, + "field_59825": null, + "field_59861": null, + "field_59868": null, + "field_59826": [ + 16 + ] + }, + { + "id": 6, + "order": "6.00000000000000000000", + "created_on": "2025-02-07T14:01:40.619958+00:00", + "updated_on": "2025-02-11T13:59:25.923307+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59821": "A Bit of a Wait, but Worth It", + "field_59822": "I had to wait a little longer than I expected for my car to be ready, but the staff kept me informed throughout the process. When I finally picked it up, I could see it was worth the wait. The car runs beautifully, and I\u2019m thrilled with my purchase!", + "field_59823": 21070, + "field_59859": null, + "field_59824": [ + 8 + ], + "field_59860": null, + "field_59825": null, + "field_59861": null, + "field_59868": null, + "field_59826": [ + 24 + ] + }, + { + "id": 7, + "order": "7.00000000000000000000", + "created_on": "2025-02-07T14:01:40.619964+00:00", + "updated_on": "2025-02-11T13:59:25.923318+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59821": "Highly Recommend This Dealership!", + "field_59822": "If you're looking for a car, look no further than PQR Auto Sales! The team was professional, friendly, and genuinely cared about helping me find the right vehicle. The whole experience was stress-free, and I absolutely love my new sedan!", + "field_59823": 21069, + "field_59859": null, + "field_59824": [ + 9 + ], + "field_59860": null, + "field_59825": null, + "field_59861": null, + "field_59868": null, + "field_59826": [ + 23 + ] + } + ], + "data_sync": null + }, + { + "id": 5703, + "name": "Financing options", + "order": 9, + "fields": [ + { + "id": 59827, + "type": "text", + "name": "Name", + "description": null, + "order": 0, + "primary": true, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "text_default": "" + }, + { + "id": 59828, + "type": "link_row", + "name": "Offers", + "description": null, + "order": 3, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "link_row_table_id": 5698, + "link_row_related_field_id": 59789, + "link_row_limit_selection_view_id": null, + "has_related_field": true + }, + { + "id": 59847, + "type": "count", + "name": "Count offers", + "description": null, + "order": 4, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "number_suffix": "", + "number_separator": "", + "date_include_time": null, + "duration_format": null, + "date_force_timezone": null, + "date_show_tzinfo": null, + "array_formula_type": null, + "error": null, + "number_decimal_places": 0, + "date_time_format": null, + "number_prefix": "", + "nullable": false, + "date_format": null, + "through_field_id": 59828 + }, + { + "id": 59862, + "type": "formula", + "name": "Count sales", + "description": null, + "order": 5, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "number_suffix": "", + "number_separator": "", + "date_include_time": null, + "duration_format": null, + "date_force_timezone": null, + "date_show_tzinfo": null, + "array_formula_type": null, + "error": null, + "number_decimal_places": 0, + "date_time_format": null, + "number_prefix": "", + "nullable": false, + "date_format": null, + "formula": "count(filter(field('Offers'),totext(lookup('Offers','Status')) = 'Offer accepted'))", + "formula_type": "number" + } + ], + "views": [ + { + "id": 26504, + "type": "grid", + "name": "All financing options", + "order": 1, + "ownership_type": "collaborative", + "owned_by": "frederik@baserow.io", + "filter_type": "AND", + "filters_disabled": false, + "filters": [], + "filter_groups": [], + "sortings": [ + { + "id": 20403, + "field_id": 59862, + "order": "DESC" + } + ], + "group_bys": [], + "decorations": [], + "public": false, + "row_identifier_type": "id", + "row_height_size": "small", + "field_options": [ + { + "id": 261972, + "field_id": 59827, + "width": 200, + "hidden": false, + "order": 0, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261973, + "field_id": 59828, + "width": 200, + "hidden": false, + "order": 1, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261974, + "field_id": 59847, + "width": 154, + "hidden": false, + "order": 2, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261975, + "field_id": 59862, + "width": 149, + "hidden": false, + "order": 3, + "aggregation_type": "", + "aggregation_raw_type": "" + } + ] + } + ], + "rows": [ + { + "id": 1, + "order": "1.00000000000000000000", + "created_on": "2025-02-07T14:11:32.596634+00:00", + "updated_on": "2025-02-07T14:11:38.671439+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59827": "Full cash", + "field_59828": [ + 4, + 10, + 11, + 21 + ], + "field_59847": null, + "field_59862": null + }, + { + "id": 2, + "order": "2.00000000000000000000", + "created_on": "2025-02-07T14:11:32.596664+00:00", + "updated_on": "2025-02-07T14:11:43.528827+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59827": "Full cheque", + "field_59828": [ + 2, + 8, + 9, + 20 + ], + "field_59847": null, + "field_59862": null + }, + { + "id": 3, + "order": "3.00000000000000000000", + "created_on": "2025-02-07T14:11:43.528562+00:00", + "updated_on": "2025-02-07T14:11:48.514758+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59827": "Full credit card", + "field_59828": [ + 3, + 14, + 22 + ], + "field_59847": null, + "field_59862": null + }, + { + "id": 4, + "order": "4.00000000000000000000", + "created_on": "2025-02-07T14:11:48.553011+00:00", + "updated_on": "2025-02-07T14:11:50.747333+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59827": "Bank loan", + "field_59828": [ + 17, + 18, + 5, + 6, + 7, + 12, + 23 + ], + "field_59847": null, + "field_59862": null + }, + { + "id": 5, + "order": "5.00000000000000000000", + "created_on": "2025-02-07T14:11:50.747028+00:00", + "updated_on": "2025-02-07T14:12:00.300374+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59827": "In-house financing", + "field_59828": [ + 1, + 13 + ], + "field_59847": null, + "field_59862": null + } + ], + "data_sync": null + }, + { + "id": 5704, + "name": "Prospects", + "order": 11, + "fields": [ + { + "id": 59829, + "type": "text", + "name": "Name", + "description": null, + "order": 0, + "primary": true, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "text_default": "" + }, + { + "id": 59830, + "type": "email", + "name": "Email", + "description": null, + "order": 1, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false + }, + { + "id": 59831, + "type": "phone_number", + "name": "Phone", + "description": null, + "order": 2, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false + }, + { + "id": 59832, + "type": "long_text", + "name": "Message", + "description": null, + "order": 3, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "long_text_enable_rich_text": true + }, + { + "id": 59833, + "type": "link_row", + "name": "Staff member", + "description": null, + "order": 4, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "link_row_table_id": 5700, + "link_row_related_field_id": 59810, + "link_row_limit_selection_view_id": null, + "has_related_field": true + }, + { + "id": 59834, + "type": "single_select", + "name": "Follow up", + "description": null, + "order": 5, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "select_options": [ + { + "id": 21074, + "value": "Answered", + "color": "green", + "order": 0 + }, + { + "id": 21075, + "value": "Open", + "color": "yellow", + "order": 1 + } + ] + }, + { + "id": 59835, + "type": "created_on", + "name": "Created on", + "description": null, + "order": 6, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "date_format": "ISO", + "date_include_time": true, + "date_time_format": "24", + "date_show_tzinfo": false, + "date_force_timezone": null + } + ], + "views": [ + { + "id": 26505, + "type": "grid", + "name": "All prospects", + "order": 1, + "ownership_type": "collaborative", + "owned_by": "frederik@baserow.io", + "filter_type": "AND", + "filters_disabled": false, + "filters": [], + "filter_groups": [], + "sortings": [], + "group_bys": [], + "decorations": [], + "public": false, + "row_identifier_type": "id", + "row_height_size": "small", + "field_options": [ + { + "id": 261976, + "field_id": 59829, + "width": 151, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261977, + "field_id": 59830, + "width": 223, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261978, + "field_id": 59831, + "width": 135, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261979, + "field_id": 59832, + "width": 383, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261980, + "field_id": 59833, + "width": 200, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261981, + "field_id": 59834, + "width": 145, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261982, + "field_id": 59835, + "width": 169, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + } + ] + }, + { + "id": 26506, + "type": "grid", + "name": "All prospects grouped by email", + "order": 2, + "ownership_type": "collaborative", + "owned_by": "frederik@baserow.io", + "filter_type": "AND", + "filters_disabled": false, + "filters": [], + "filter_groups": [], + "sortings": [], + "group_bys": [ + { + "id": 3646, + "field_id": 59830, + "order": "ASC" + } + ], + "decorations": [], + "public": false, + "row_identifier_type": "id", + "row_height_size": "small", + "field_options": [ + { + "id": 261983, + "field_id": 59829, + "width": 200, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261984, + "field_id": 59830, + "width": 223, + "hidden": true, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261985, + "field_id": 59831, + "width": 135, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261986, + "field_id": 59832, + "width": 200, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261987, + "field_id": 59833, + "width": 200, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261988, + "field_id": 59834, + "width": 200, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261989, + "field_id": 59835, + "width": 200, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + } + ] + }, + { + "id": 26507, + "type": "grid", + "name": "All prospects grouped by staff member", + "order": 3, + "ownership_type": "collaborative", + "owned_by": "frederik@baserow.io", + "filter_type": "AND", + "filters_disabled": false, + "filters": [], + "filter_groups": [], + "sortings": [], + "group_bys": [ + { + "id": 3647, + "field_id": 59833, + "order": "ASC" + } + ], + "decorations": [], + "public": false, + "row_identifier_type": "id", + "row_height_size": "small", + "field_options": [ + { + "id": 261990, + "field_id": 59829, + "width": 200, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261991, + "field_id": 59830, + "width": 223, + "hidden": true, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261992, + "field_id": 59831, + "width": 135, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261993, + "field_id": 59832, + "width": 200, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261994, + "field_id": 59833, + "width": 200, + "hidden": true, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261995, + "field_id": 59834, + "width": 200, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261996, + "field_id": 59835, + "width": 200, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + } + ] + }, + { + "id": 26508, + "type": "kanban", + "name": "All prospects stacked by Follow up", + "order": 4, + "ownership_type": "collaborative", + "owned_by": "frederik@baserow.io", + "filter_type": "AND", + "filters_disabled": false, + "filters": [], + "filter_groups": [], + "sortings": [], + "decorations": [], + "public": false, + "single_select_field_id": 59834, + "field_options": [ + { + "id": 35184, + "field_id": 59829, + "hidden": false, + "order": 32767 + }, + { + "id": 35185, + "field_id": 59830, + "hidden": false, + "order": 32767 + }, + { + "id": 35186, + "field_id": 59831, + "hidden": false, + "order": 32767 + }, + { + "id": 35187, + "field_id": 59832, + "hidden": true, + "order": 32767 + }, + { + "id": 35188, + "field_id": 59833, + "hidden": true, + "order": 32767 + }, + { + "id": 35189, + "field_id": 59834, + "hidden": true, + "order": 32767 + }, + { + "id": 35190, + "field_id": 59835, + "hidden": true, + "order": 32767 + } + ] + } + ], + "rows": [ + { + "id": 6, + "order": "2.00000000000000000000", + "created_on": "2025-02-11T14:19:52.590683+00:00", + "updated_on": "2025-02-11T14:21:20.093780+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59829": "Alice Johnson", + "field_59830": "alice.johnson@example.com", + "field_59831": "+14155551234", + "field_59832": "I am interested in learning more about your services.", + "field_59833": [ + 4 + ], + "field_59834": 21074, + "field_59835": null + }, + { + "id": 7, + "order": "3.00000000000000000000", + "created_on": "2025-02-11T14:19:52.590722+00:00", + "updated_on": "2025-02-11T14:22:09.948385+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59829": "George Black", + "field_59830": "george.black@example.com", + "field_59831": "+5511998765432", + "field_59832": "Can you provide pricing details?", + "field_59833": [ + 5 + ], + "field_59834": 21074, + "field_59835": null + }, + { + "id": 8, + "order": "4.00000000000000000000", + "created_on": "2025-02-11T14:19:52.590731+00:00", + "updated_on": "2025-02-11T14:21:21.567243+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59829": "Charlie Brown", + "field_59830": "charlie.brown@example.com", + "field_59831": "+33123456789", + "field_59832": "Do you offer international shipping?", + "field_59833": [ + 4 + ], + "field_59834": 21074, + "field_59835": null + }, + { + "id": 9, + "order": "5.00000000000000000000", + "created_on": "2025-02-11T14:19:52.590738+00:00", + "updated_on": "2025-02-11T14:21:57.043721+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59829": "Charlie Brown", + "field_59830": "charlie.brown@example.com", + "field_59831": "+33123456789", + "field_59832": "I need support with my recent order.", + "field_59833": [ + 4 + ], + "field_59834": 21075, + "field_59835": null + }, + { + "id": 10, + "order": "6.00000000000000000000", + "created_on": "2025-02-11T14:19:52.590744+00:00", + "updated_on": "2025-02-11T14:21:22.031335+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59829": "Edward Green", + "field_59830": "edward.green@example.com", + "field_59831": "+390612345678", + "field_59832": "How can I schedule a consultation?", + "field_59833": [ + 5 + ], + "field_59834": 21074, + "field_59835": null + }, + { + "id": 11, + "order": "7.00000000000000000000", + "created_on": "2025-02-11T14:19:52.590750+00:00", + "updated_on": "2025-02-11T14:21:25.926695+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59829": "Fiona White", + "field_59830": "fiona.white@example.com", + "field_59831": "+81312345678", + "field_59832": "Are there any discounts available for bulk purchases?", + "field_59833": [ + 5 + ], + "field_59834": 21075, + "field_59835": null + }, + { + "id": 12, + "order": "8.00000000000000000000", + "created_on": "2025-02-11T14:19:52.590757+00:00", + "updated_on": "2025-02-11T14:21:26.236588+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59829": "George Black", + "field_59830": "george.black@example.com", + "field_59831": "+5511998765432", + "field_59832": "What are your business hours?", + "field_59833": [ + 4 + ], + "field_59834": 21075, + "field_59835": null + }, + { + "id": 13, + "order": "9.00000000000000000000", + "created_on": "2025-02-11T14:19:52.590763+00:00", + "updated_on": "2025-02-11T14:22:01.437193+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59829": "George Black", + "field_59830": "george.black@example.com", + "field_59831": "+5511998765432", + "field_59832": "Do you have a physical store location?", + "field_59833": [ + 3 + ], + "field_59834": 21075, + "field_59835": null + }, + { + "id": 14, + "order": "10.00000000000000000000", + "created_on": "2025-02-11T14:19:52.590769+00:00", + "updated_on": "2025-02-11T14:21:22.853854+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59829": "Ian Clarke", + "field_59830": "ian.clarke@example.com", + "field_59831": "+27123456789", + "field_59832": "I would like to partner with your company.", + "field_59833": [ + 4 + ], + "field_59834": 21074, + "field_59835": null + }, + { + "id": 15, + "order": "11.00000000000000000000", + "created_on": "2025-02-11T14:19:52.590775+00:00", + "updated_on": "2025-02-11T14:21:27.211469+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59829": "Julia Adams", + "field_59830": "julia.adams@example.com", + "field_59831": "+6591234567", + "field_59832": "Can I modify my recent order?", + "field_59833": [ + 3 + ], + "field_59834": 21075, + "field_59835": null + } + ], + "data_sync": null } ] + }, + { + "pages": [ + { + "id": 6667, + "name": "__shared__", + "order": 1, + "path": "__shared__", + "path_params": [], + "query_params": [], + "shared": true, + "elements": [ + { + "id": 106690, + "order": "1.00000000000000000000", + "type": "header", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 30, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "share_type": "all", + "pages": [] + }, + { + "id": 106693, + "order": "1.00000000000000000000", + "type": "image", + "parent_element_id": 106690, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "image": {} + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "image_source_type": "upload", + "image_file_id": { + "name": "rDpQhVNe3ZnIRQ9USl44F8uKDyi0N1mP_521f9d1b8e16da1dd8d9f3a1fbf4f4032b440ac7c511cfbd13fa42192b981300.png", + "original_name": "evertrust-header.png" + }, + "image_url": "", + "alt_text": "" + }, + { + "id": 106694, + "order": "1.00000000000000000000", + "type": "link", + "parent_element_id": 106692, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "button": { + "button_width": "full", + "button_alignment": "center", + "button_font_size": 14, + "button_font_weight": "semi-bold" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "navigation_type": "page", + "navigate_to_page_id": 6668, + "page_parameters": [], + "query_parameters": [], + "navigate_to_url": "", + "target": "self", + "value": "'HOME'", + "variant": "button" + }, + { + "id": 106695, + "order": "1.00000000000000000000", + "type": "link", + "parent_element_id": 106692, + "place_in_container": "1", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "button": { + "button_width": "full", + "button_alignment": "center", + "button_font_size": 14, + "button_font_weight": "semi-bold" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "navigation_type": "page", + "navigate_to_page_id": 6673, + "page_parameters": [], + "query_parameters": [ + { + "name": "model", + "value": "" + }, + { + "name": "condition", + "value": "" + }, + { + "name": "max_price", + "value": "get('data_source.12170.result')" + }, + { + "name": "milage", + "value": "get('data_source.12171.result')" + } + ], + "navigate_to_url": "", + "target": "self", + "value": "'OUR INVENTORY'", + "variant": "button" + }, + { + "id": 106696, + "order": "1.00000000000000000000", + "type": "link", + "parent_element_id": 106692, + "place_in_container": "2", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "button": { + "button_width": "full", + "button_alignment": "center", + "button_font_size": 14, + "button_font_weight": "semi-bold" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "navigation_type": "page", + "navigate_to_page_id": 6671, + "page_parameters": [], + "query_parameters": [], + "navigate_to_url": "", + "target": "self", + "value": "'CONTACT US'", + "variant": "button" + }, + { + "id": 106697, + "order": "1.00000000000000000000", + "type": "link", + "parent_element_id": 106692, + "place_in_container": "3", + "visibility": "not-logged", + "role_type": "allow_all", + "roles": [], + "styles": { + "button": { + "button_width": "full", + "button_alignment": "center", + "button_font_size": 14, + "button_font_weight": "semi-bold" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "navigation_type": "page", + "navigate_to_page_id": 6669, + "page_parameters": [], + "query_parameters": [], + "navigate_to_url": "", + "target": "self", + "value": "'LOGIN'", + "variant": "button" + }, + { + "id": 106699, + "order": "1.00000000000000000000", + "type": "column", + "parent_element_id": 106691, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 50, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "color", + "style_background_color": "primary", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "column_amount": 3, + "column_gap": 20, + "alignment": "top" + }, + { + "id": 106700, + "order": "1.00000000000000000000", + "type": "heading", + "parent_element_id": 106699, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "heading_3_text_color": "border" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Socials'", + "level": 3 + }, + { + "id": 106701, + "order": "1.00000000000000000000", + "type": "heading", + "parent_element_id": 106699, + "place_in_container": "1", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "heading_3_text_color": "border" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Legal'", + "level": 3 + }, + { + "id": 106702, + "order": "1.00000000000000000000", + "type": "heading", + "parent_element_id": 106699, + "place_in_container": "2", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "heading_3_text_color": "border" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Visit our showroom'", + "level": 3 + }, + { + "id": 106691, + "order": "2.00000000000000000000", + "type": "footer", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 50, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "share_type": "all", + "pages": [] + }, + { + "id": 106692, + "order": "2.00000000000000000000", + "type": "column", + "parent_element_id": 106690, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "column_amount": 4, + "column_gap": 20, + "alignment": "top" + }, + { + "id": 106698, + "order": "2.00000000000000000000", + "type": "link", + "parent_element_id": 106692, + "place_in_container": "3", + "visibility": "logged-in", + "role_type": "allow_all", + "roles": [], + "styles": { + "button": { + "button_width": "full", + "button_alignment": "center", + "button_font_size": 14, + "button_font_weight": "semi-bold" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "navigation_type": "page", + "navigate_to_page_id": 6670, + "page_parameters": [], + "query_parameters": [], + "navigate_to_url": "", + "target": "self", + "value": "concat(' \ud83d\udc64 ',get('user.username'),' ')", + "variant": "button" + }, + { + "id": 106703, + "order": "2.00000000000000000000", + "type": "text", + "parent_element_id": 106699, + "place_in_container": "2", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_color": "border" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "concat('Mon - Fri: 9am - 12am | 1pm - 7pm','\n','Saturday: 9am - 12am | 1pm - 5pm','\n','Sunday : 9am - 12am')", + "format": "plain" + }, + { + "id": 106704, + "order": "2.00000000000000000000", + "type": "link", + "parent_element_id": 106699, + "place_in_container": "1", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "link": { + "link_text_color": "border", + "link_hover_text_color": "#fbfbfb" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "navigation_type": "page", + "navigate_to_page_id": 6668, + "page_parameters": [], + "query_parameters": [], + "navigate_to_url": "", + "target": "self", + "value": "'Privacy policy'", + "variant": "link" + }, + { + "id": 106705, + "order": "2.00000000000000000000", + "type": "link", + "parent_element_id": 106699, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "link": { + "link_text_color": "border", + "link_hover_text_color": "#fbfbfb" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "navigation_type": "page", + "navigate_to_page_id": 6668, + "page_parameters": [], + "query_parameters": [], + "navigate_to_url": "", + "target": "self", + "value": "'Facebook'", + "variant": "link" + }, + { + "id": 106706, + "order": "3.00000000000000000000", + "type": "link", + "parent_element_id": 106699, + "place_in_container": "1", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "link": { + "link_text_color": "border", + "link_hover_text_color": "#fbfbfb" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "navigation_type": "page", + "navigate_to_page_id": 6668, + "page_parameters": [], + "query_parameters": [], + "navigate_to_url": "", + "target": "self", + "value": "'Terms of service'", + "variant": "link" + }, + { + "id": 106707, + "order": "3.00000000000000000000", + "type": "link", + "parent_element_id": 106699, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "link": { + "link_text_color": "border", + "link_hover_text_color": "#fbfbfb" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "navigation_type": "page", + "navigate_to_page_id": 6668, + "page_parameters": [], + "query_parameters": [], + "navigate_to_url": "", + "target": "self", + "value": "'Instagram'", + "variant": "link" + }, + { + "id": 106708, + "order": "4.00000000000000000000", + "type": "link", + "parent_element_id": 106699, + "place_in_container": "1", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "link": { + "link_text_color": "border", + "link_hover_text_color": "#fbfbfb" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "navigation_type": "page", + "navigate_to_page_id": 6668, + "page_parameters": [], + "query_parameters": [], + "navigate_to_url": "", + "target": "self", + "value": "'Disclaimer'", + "variant": "link" + }, + { + "id": 106709, + "order": "4.00000000000000000000", + "type": "link", + "parent_element_id": 106699, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "link": { + "link_text_color": "border", + "link_hover_text_color": "#fbfbfb" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "navigation_type": "page", + "navigate_to_page_id": 6668, + "page_parameters": [], + "query_parameters": [], + "navigate_to_url": "", + "target": "self", + "value": "'LinkedIn'", + "variant": "link" + }, + { + "id": 106710, + "order": "5.00000000000000000000", + "type": "link", + "parent_element_id": 106699, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "link": { + "link_text_color": "border", + "link_hover_text_color": "#fbfbfb" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "navigation_type": "page", + "navigate_to_page_id": 6668, + "page_parameters": [], + "query_parameters": [], + "navigate_to_url": "", + "target": "self", + "value": "'Youtube'", + "variant": "link" + } + ], + "data_sources": [ + { + "id": 12170, + "name": "Maximum price", + "order": "1.00000000000000000000", + "service": { + "id": 15031, + "integration_id": 900, + "type": "local_baserow_aggregate_rows", + "table_id": 5697, + "view_id": 26465, + "search_query": "", + "filter_type": "AND", + "filters": [], + "field_id": 59842, + "aggregation_type": "max" + } + }, + { + "id": 12171, + "name": "Maximum milage", + "order": "2.00000000000000000000", + "service": { + "id": 15032, + "integration_id": 900, + "type": "local_baserow_aggregate_rows", + "table_id": 5697, + "view_id": 26465, + "search_query": "", + "filter_type": "AND", + "filters": [], + "field_id": 59764, + "aggregation_type": "max" + } + } + ], + "workflow_actions": [], + "visibility": "all", + "role_type": "allow_all", + "roles": [] + }, + { + "id": 6668, + "name": "Homepage", + "order": 1, + "path": "/", + "path_params": [], + "query_params": [], + "shared": false, + "elements": [ + { + "id": 106715, + "order": "0.20000000000000001110", + "type": "text", + "parent_element_id": 106712, + "place_in_container": "2", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 20, + "body_text_alignment": "center" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 2, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 2, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 2, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "get('data_source.12150.2.field_59823.value')", + "format": "plain" + }, + { + "id": 106716, + "order": "0.25000000000000000000", + "type": "text", + "parent_element_id": 106712, + "place_in_container": "2", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_text_alignment": "center" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 2, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 2, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "concat('**',get('data_source.12150.2.field_59821'),'**')", + "format": "markdown" + }, + { + "id": 106717, + "order": "0.33333333333333331483", + "type": "text", + "parent_element_id": 106712, + "place_in_container": "2", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_alignment": "center" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 2, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 2, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "concat('*',get('data_source.12150.2.field_59860'),' (',get('data_source.12150.2.field_59861'),')*')", + "format": "markdown" + }, + { + "id": 106718, + "order": "0.50000000000000000000", + "type": "text", + "parent_element_id": 106712, + "place_in_container": "2", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 2, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 2, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 2, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "get('data_source.12150.2.field_59822')", + "format": "plain" + }, + { + "id": 106740, + "order": "0.50000000000000000000", + "type": "heading", + "parent_element_id": 106738, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "heading_3_font_weight": "bold", + "heading_3_text_alignment": "center" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "get('current_record.field_59791')", + "level": 3 + }, + { + "id": 106741, + "order": "0.66666666666666662966", + "type": "text", + "parent_element_id": 106738, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_text_alignment": "center" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "concat(get('current_record.field_59793'),', ',get('current_record.field_59795'),' ',get('current_record.field_59794'))", + "format": "plain" + }, + { + "id": 106711, + "order": "1.00000000000000000000", + "type": "column", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "column_amount": 2, + "column_gap": 20, + "alignment": "top" + }, + { + "id": 106719, + "order": "1.00000000000000000000", + "type": "heading", + "parent_element_id": 106711, + "place_in_container": "1", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "heading_1_font_size": 28, + "heading_1_text_alignment": "center" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 16, + "style_border_radius": 0, + "style_background": "color", + "style_background_color": "#eae0d580", + "style_background_file_id": null, + "style_background_mode": "fit", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Driven by Trust, Powered by Excellence'", + "level": 1 + }, + { + "id": 106720, + "order": "1.00000000000000000000", + "type": "image", + "parent_element_id": 106711, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "image": { + "image_border_radius": 8 + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "image_source_type": "upload", + "image_file_id": { + "name": "0s7dTvmlvQzmDQAO3k7ZZmXRw6cPjWFI_e1dd9d5f08d3b16340bafcadd14d38993cc8a9bce1a40703b29e0a0d1c3e8a20.png", + "original_name": "header-image.png" + }, + "image_url": "", + "alt_text": "" + }, + { + "id": 106721, + "order": "1.00000000000000000000", + "type": "text", + "parent_element_id": 106712, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 20, + "body_text_alignment": "center" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 2, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 2, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 2, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "get('data_source.12150.0.field_59823.value')", + "format": "plain" + }, + { + "id": 106722, + "order": "1.00000000000000000000", + "type": "text", + "parent_element_id": 106712, + "place_in_container": "1", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 20, + "body_text_alignment": "center" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 2, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 2, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 2, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "get('data_source.12150.1.field_59823.value')", + "format": "plain" + }, + { + "id": 106738, + "order": "1.00000000000000000000", + "type": "column", + "parent_element_id": 106713, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 24, + "style_border_radius": 0, + "style_background": "color", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "column_amount": 1, + "column_gap": 20, + "alignment": "top" + }, + { + "id": 106739, + "order": "1.00000000000000000000", + "type": "column", + "parent_element_id": 106714, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "color", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "column_amount": 5, + "column_gap": 10, + "alignment": "center" + }, + { + "id": 106742, + "order": "1.00000000000000000000", + "type": "image", + "parent_element_id": 106738, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "image": { + "image_border_radius": 8 + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 15, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 15, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "image_source_type": "url", + "image_file_id": null, + "image_url": "get('current_record.field_59792.0.url')", + "alt_text": "" + }, + { + "id": 106743, + "order": "1.00000000000000000000", + "type": "image", + "parent_element_id": 106739, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "image": { + "image_border_radius": 8 + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 10, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "image_source_type": "url", + "image_file_id": null, + "image_url": "get('current_record.field_59801.0.url')", + "alt_text": "" + }, + { + "id": 106744, + "order": "1.00000000000000000000", + "type": "heading", + "parent_element_id": 106739, + "place_in_container": "1", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "get('current_record.field_59800')", + "level": 3 + }, + { + "id": 106723, + "order": "1.50000000000000000000", + "type": "heading", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "heading_2_font_size": 24 + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 50, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'\u276e\u276e\u276e\u276e What our customers say \u276f\u276f\u276f\u276f'", + "level": 2 + }, + { + "id": 106712, + "order": "1.66666666666666674068", + "type": "column", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 40, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 40, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 40, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 40, + "style_margin_right": 0, + "style_background_radius": 24, + "style_border_radius": 0, + "style_background": "color", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "column_amount": 3, + "column_gap": 40, + "alignment": "top" + }, + { + "id": 106724, + "order": "2.00000000000000000000", + "type": "text", + "parent_element_id": 106711, + "place_in_container": "1", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Buying a car should be as smooth and reliable as the vehicles we sell. Our commitment to quality, transparency, and customer satisfaction sets us apart, ensuring you drive away with confidence. Your journey starts with trust\u2014let\u2019s make it a great one'", + "format": "plain" + }, + { + "id": 106725, + "order": "2.00000000000000000000", + "type": "heading", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "heading_2_font_size": 24 + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 50, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'\u276e\u276e\u276e\u276e Our Branches \u276f\u276f\u276f\u276f'", + "level": 2 + }, + { + "id": 106726, + "order": "2.00000000000000000000", + "type": "text", + "parent_element_id": 106712, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_text_alignment": "center" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 2, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 2, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "concat('**',get('data_source.12150.0.field_59821'),'**')", + "format": "markdown" + }, + { + "id": 106727, + "order": "2.00000000000000000000", + "type": "text", + "parent_element_id": 106712, + "place_in_container": "1", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_text_alignment": "center" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 2, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 2, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "concat('**',get('data_source.12150.1.field_59821'),'**')", + "format": "markdown" + }, + { + "id": 106745, + "order": "2.00000000000000000000", + "type": "link", + "parent_element_id": 106738, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "navigation_type": "custom", + "navigate_to_page_id": null, + "page_parameters": [], + "query_parameters": [], + "navigate_to_url": "concat('mailto:',get('current_record.field_59799'))", + "target": "self", + "value": "concat('\u2709\ufe0f ',get('current_record.field_59799'))", + "variant": "link" + }, + { + "id": 106746, + "order": "2.00000000000000000000", + "type": "text", + "parent_element_id": 106739, + "place_in_container": "1", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12 + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "concat(get('current_record.field_59802.value'),' ')", + "format": "plain" + }, + { + "id": 106728, + "order": "2.50000000000000000000", + "type": "text", + "parent_element_id": 106712, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_alignment": "center" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 2, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 2, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "concat('*',get('data_source.12150.0.field_59860'),' (',get('data_source.12150.0.field_59861'),')*')", + "format": "markdown" + }, + { + "id": 106747, + "order": "2.50000000000000000000", + "type": "text", + "parent_element_id": 106739, + "place_in_container": "1", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12 + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "concat(get('current_record.field_59803.*.value'),' branch')", + "format": "plain" + }, + { + "id": 106713, + "order": "3.00000000000000000000", + "type": "repeat", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "data_source_id": 12148, + "items_per_page": 20, + "button_load_more_label": "", + "schema_property": null, + "property_options": [], + "orientation": "horizontal", + "items_per_row": { + "tablet": 2, + "desktop": 4, + "smartphone": 2 + }, + "horizontal_gap": 20, + "vertical_gap": 0 + }, + { + "id": 106729, + "order": "3.00000000000000000000", + "type": "link", + "parent_element_id": 106711, + "place_in_container": "1", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "button": { + "button_alignment": "center", + "button_font_size": 24, + "button_vertical_padding": 24, + "button_horizontal_padding": 24 + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 20, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 20, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "navigation_type": "page", + "navigate_to_page_id": 6673, + "page_parameters": [], + "query_parameters": [], + "navigate_to_url": "", + "target": "self", + "value": "'\u27a4 CHECK OUT OUR LATEST DEALS'", + "variant": "button" + }, + { + "id": 106730, + "order": "3.00000000000000000000", + "type": "text", + "parent_element_id": 106712, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 2, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 2, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 2, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "get('data_source.12150.0.field_59822')", + "format": "plain" + }, + { + "id": 106731, + "order": "3.00000000000000000000", + "type": "text", + "parent_element_id": 106712, + "place_in_container": "1", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_alignment": "center" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 2, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 2, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "concat('*',get('data_source.12150.1.field_59860'),' (',get('data_source.12150.1.field_59861'),')*')", + "format": "markdown" + }, + { + "id": 106748, + "order": "3.00000000000000000000", + "type": "link", + "parent_element_id": 106738, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "navigation_type": "custom", + "navigate_to_page_id": null, + "page_parameters": [], + "query_parameters": [], + "navigate_to_url": "concat('tel:',get('current_record.field_59796'))", + "target": "self", + "value": "concat('\ud83d\udcde ',get('current_record.field_59796'))", + "variant": "link" + }, + { + "id": 106749, + "order": "3.00000000000000000000", + "type": "link", + "parent_element_id": 106739, + "place_in_container": "1", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "navigation_type": "custom", + "navigate_to_page_id": null, + "page_parameters": [], + "query_parameters": [], + "navigate_to_url": "concat('mailto:',get('current_record.field_59807'))", + "target": "self", + "value": "concat('\u2709\ufe0f ',get('current_record.field_59807'))", + "variant": "link" + }, + { + "id": 106732, + "order": "4.00000000000000000000", + "type": "text", + "parent_element_id": 106711, + "place_in_container": "1", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_text_color": "secondary", + "body_text_alignment": "center" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'**Concerned about financing your new car? Don\\'t worry, we offer:**'", + "format": "markdown" + }, + { + "id": 106733, + "order": "4.00000000000000000000", + "type": "text", + "parent_element_id": 106712, + "place_in_container": "1", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 2, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 2, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 2, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "get('data_source.12150.1.field_59822')", + "format": "plain" + }, + { + "id": 106734, + "order": "4.00000000000000000000", + "type": "heading", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "heading_2_font_size": 24 + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 50, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'\u276e\u276e\u276e\u276e Meet Our Team \u276f\u276f\u276f\u276f'", + "level": 2 + }, + { + "id": 106750, + "order": "4.00000000000000000000", + "type": "link", + "parent_element_id": 106739, + "place_in_container": "1", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "navigation_type": "custom", + "navigate_to_page_id": null, + "page_parameters": [], + "query_parameters": [], + "navigate_to_url": "concat('tel:',get('current_record.field_59806'))", + "target": "self", + "value": "concat('\ud83d\udcde ',get('current_record.field_59806'))", + "variant": "link" + }, + { + "id": 106735, + "order": "4.33333333333333303727", + "type": "text", + "parent_element_id": 106711, + "place_in_container": "1", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_text_alignment": "center" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 1, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 1, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 50, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 50, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "get('data_source.12149.*.field_59827')", + "format": "markdown" + }, + { + "id": 106736, + "order": "4.50000000000000000000", + "type": "text", + "parent_element_id": 106711, + "place_in_container": "1", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_text_color": "secondary", + "body_text_alignment": "center" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'**Have questions or need help finding the perfect car? Let our friendly team help you.**'", + "format": "markdown" + }, + { + "id": 106714, + "order": "5.00000000000000000000", + "type": "repeat", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "data_source_id": 12151, + "items_per_page": 3, + "button_load_more_label": "'Show more'", + "schema_property": null, + "property_options": [], + "orientation": "vertical", + "items_per_row": { + "tablet": 2, + "desktop": 2, + "smartphone": 2 + }, + "horizontal_gap": 0, + "vertical_gap": 20 + }, + { + "id": 106737, + "order": "6.00000000000000000000", + "type": "link", + "parent_element_id": 106711, + "place_in_container": "1", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "link": { + "link_text_alignment": "center" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 1, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 1, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 150, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 150, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "navigation_type": "custom", + "navigate_to_page_id": 6668, + "page_parameters": [], + "query_parameters": [], + "navigate_to_url": "'mailto:cars@example.com'", + "target": "self", + "value": "'\u2709\ufe0f Contact us'", + "variant": "link" + } + ], + "data_sources": [ + { + "id": 12148, + "name": "All branches", + "order": "1.00000000000000000000", + "service": { + "id": 15004, + "integration_id": 900, + "type": "local_baserow_list_rows", + "table_id": 5699, + "view_id": 26489, + "sortings": [], + "search_query": "", + "filter_type": "AND", + "filters": [] + } + }, + { + "id": 12149, + "name": "All financing", + "order": "2.00000000000000000000", + "service": { + "id": 15005, + "integration_id": 900, + "type": "local_baserow_list_rows", + "table_id": 5703, + "view_id": 26504, + "sortings": [], + "search_query": "", + "filter_type": "AND", + "filters": [] + } + }, + { + "id": 12150, + "name": "Top reviews", + "order": "3.00000000000000000000", + "service": { + "id": 15006, + "integration_id": 900, + "type": "local_baserow_list_rows", + "table_id": 5702, + "view_id": 26503, + "sortings": [], + "search_query": "", + "filter_type": "AND", + "filters": [] + } + }, + { + "id": 12151, + "name": "Our staff", + "order": "4.00000000000000000000", + "service": { + "id": 15007, + "integration_id": 900, + "type": "local_baserow_list_rows", + "table_id": 5700, + "view_id": 26491, + "sortings": [], + "search_query": "", + "filter_type": "AND", + "filters": [] + } + } + ], + "workflow_actions": [], + "visibility": "all", + "role_type": "allow_all", + "roles": [] + }, + { + "id": 6669, + "name": "Login", + "order": 2, + "path": "/login", + "path_params": [], + "query_params": [], + "shared": false, + "elements": [ + { + "id": 106751, + "order": "0.50000000000000000000", + "type": "heading", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Drive into your account'", + "level": 1 + }, + { + "id": 106752, + "order": "0.66666666666666662966", + "type": "text", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Get in touch with our customer services to set up your account if you do not already have one. This step is required since we want all offers and reviews to come from genuine buyers.'", + "format": "plain" + }, + { + "id": 106753, + "order": "0.75000000000000000000", + "type": "link", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "navigation_type": "page", + "navigate_to_page_id": 6671, + "page_parameters": [], + "query_parameters": [], + "navigate_to_url": "", + "target": "self", + "value": "'\u2709\ufe0f Contact us'", + "variant": "link" + }, + { + "id": 106754, + "order": "1.00000000000000000000", + "type": "auth_form", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "input": {}, + "login_button": { + "button_alignment": "center", + "button_horizontal_padding": 36 + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 150, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 150, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 100, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 100, + "style_margin_right": 0, + "style_background_radius": 8, + "style_border_radius": 0, + "style_background": "color", + "style_background_color": "#eae0d580", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "small", + "style_width_child": "normal", + "user_source_id": 672, + "login_button_label": "'Sign in'" + } + ], + "data_sources": [], + "workflow_actions": [ + { + "id": 13949, + "type": "open_page", + "order": 1, + "page_id": 6669, + "element_id": 106754, + "event": "after_login", + "navigation_type": "page", + "navigate_to_page_id": 6673, + "page_parameters": [], + "query_parameters": [ + { + "name": "model", + "value": "" + }, + { + "name": "condition", + "value": "" + }, + { + "name": "max_price", + "value": "get('data_source.12170.result')" + }, + { + "name": "milage", + "value": "get('data_source.12171.result')" + } + ], + "navigate_to_url": "", + "target": "self" + } + ], + "visibility": "all", + "role_type": "allow_all", + "roles": [] + }, + { + "id": 6670, + "name": "Profile", + "order": 3, + "path": "/profile", + "path_params": [], + "query_params": [], + "shared": false, + "elements": [ + { + "id": 106755, + "order": "0.50000000000000000000", + "type": "column", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "column_amount": 2, + "column_gap": 20, + "alignment": "center" + }, + { + "id": 106758, + "order": "1.00000000000000000000", + "type": "input_text", + "parent_element_id": 106757, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "label": "'NAME:'", + "required": true, + "validation_type": "any", + "placeholder": "", + "default_value": "get('data_source.12152.field_59811')", + "is_multiline": false, + "rows": 3, + "input_type": "text" + }, + { + "id": 106766, + "order": "1.00000000000000000000", + "type": "heading", + "parent_element_id": 106755, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Profile information'", + "level": 1 + }, + { + "id": 106767, + "order": "1.00000000000000000000", + "type": "button", + "parent_element_id": 106755, + "place_in_container": "1", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "button": { + "button_alignment": "right" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'LOGOUT'" + }, + { + "id": 106768, + "order": "2.00000000000000000000", + "type": "heading", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'My account'", + "level": 2 + }, + { + "id": 106756, + "order": "2.25000000000000000000", + "type": "form_container", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "button": { + "button_alignment": "center", + "button_horizontal_padding": 36 + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 20, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 20, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 40, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 40, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "color", + "style_background_color": "#eae0d580", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "small", + "style_width_child": "normal", + "submit_button_label": "'UPDATE ACCOUNT '", + "reset_initial_values_post_submission": false + }, + { + "id": 106759, + "order": "2.25000000000000000000", + "type": "input_text", + "parent_element_id": 106756, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "label": "'EMAIL:'", + "required": true, + "validation_type": "email", + "placeholder": "", + "default_value": "get('data_source.12152.field_59817')", + "is_multiline": false, + "rows": 3, + "input_type": "text" + }, + { + "id": 106769, + "order": "2.33333333333333348136", + "type": "heading", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 50, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'My contact information'", + "level": 2 + }, + { + "id": 106760, + "order": "2.39999999999999991118", + "type": "input_text", + "parent_element_id": 106756, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "label": "'PASSWORD:'", + "required": true, + "validation_type": "any", + "placeholder": "", + "default_value": "'Thisisarandompasswordtofillinthebox'", + "is_multiline": false, + "rows": 3, + "input_type": "password" + }, + { + "id": 106757, + "order": "2.50000000000000000000", + "type": "form_container", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "button": { + "button_alignment": "center", + "button_horizontal_padding": 36 + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 20, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 20, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 40, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 40, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "color", + "style_background_color": "#eae0d580", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "small", + "style_width_child": "normal", + "submit_button_label": "'UPDATE PROFILE '", + "reset_initial_values_post_submission": false + }, + { + "id": 106761, + "order": "2.50000000000000000000", + "type": "input_text", + "parent_element_id": 106757, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "label": "'PHONE:'", + "required": true, + "validation_type": "any", + "placeholder": "", + "default_value": "get('data_source.12152.field_59816')", + "is_multiline": false, + "rows": 3, + "input_type": "text" + }, + { + "id": 106762, + "order": "3.00000000000000000000", + "type": "input_text", + "parent_element_id": 106757, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "label": "'ADDRESS:'", + "required": true, + "validation_type": "any", + "placeholder": "", + "default_value": "get('data_source.12152.field_59812')", + "is_multiline": false, + "rows": 3, + "input_type": "text" + }, + { + "id": 106770, + "order": "3.00000000000000000000", + "type": "heading", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 50, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'My offers'", + "level": 2 + }, + { + "id": 106771, + "order": "3.33333333333333348136", + "type": "heading", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Accepted'", + "level": 3 + }, + { + "id": 106772, + "order": "3.50000000000000000000", + "type": "table", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "data_source_id": 12153, + "items_per_page": 20, + "button_load_more_label": "", + "schema_property": null, + "property_options": [], + "fields": [ + { + "uid": "5c3bfc69-8109-4aa3-8965-09815b8ad5b7", + "name": "Car", + "type": "link", + "styles": {}, + "config": { + "navigation_type": "page", + "navigate_to_page_id": 6677, + "page_parameters": [ + { + "name": "car_id", + "value": "get('current_record.field_59781.0.id')" + } + ], + "query_parameters": [], + "navigate_to_url": "", + "target": "self", + "link_name": "concat(get('current_record.field_59863.*.value'),' - ',get('current_record.field_59850'),' (',get('current_record.field_59864.*.value'),')')", + "variant": "link" + } + }, + { + "uid": "634226ce-68f7-4b93-ab66-2b767ee8775e", + "name": "Date", + "type": "text", + "styles": {}, + "config": { + "value": "get('current_record.field_59782')" + } + }, + { + "uid": "68bb9942-e9ac-4372-8ea2-a0b996e44478", + "name": "Price", + "type": "text", + "styles": {}, + "config": { + "value": "concat('$',get('current_record.field_59784'))" + } + }, + { + "uid": "1ef8c3bf-9219-4599-865c-bd1d911e3277", + "name": "Contact", + "type": "link", + "styles": {}, + "config": { + "navigation_type": "custom", + "navigate_to_page_id": null, + "page_parameters": [], + "query_parameters": [], + "navigate_to_url": "concat('mailto:',get('current_record.field_59853'))", + "target": "self", + "link_name": "get('current_record.field_59786.*.value')", + "variant": "link" + } + }, + { + "uid": "f3f8eeb5-b491-4620-a7bc-ea73aefb3b67", + "name": "Financing", + "type": "text", + "styles": {}, + "config": { + "value": "get('current_record.field_59789.*.value')" + } + }, + { + "uid": "fcc9c52a-9183-41a3-8b08-fae541ca4771", + "name": "Branch", + "type": "text", + "styles": {}, + "config": { + "value": "get('current_record.field_59852')" + } + }, + { + "uid": "db0b4985-824a-44b9-998c-f301b03801cd", + "name": "-", + "type": "link", + "styles": {}, + "config": { + "navigation_type": "page", + "navigate_to_page_id": 6678, + "page_parameters": [ + { + "name": "car_id", + "value": "get('current_record.field_59781.0.id')" + }, + { + "name": "offer_id", + "value": "get('current_record.id')" + } + ], + "query_parameters": [], + "navigate_to_url": "", + "target": "self", + "link_name": "'Details'", + "variant": "button" + } + } + ], + "orientation": { + "tablet": "horizontal", + "desktop": "horizontal", + "smartphone": "horizontal" + } + }, + { + "id": 106773, + "order": "3.66666666666666651864", + "type": "heading", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Pending / Rejected'", + "level": 3 + }, + { + "id": 106774, + "order": "3.75000000000000000000", + "type": "table", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 8, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "data_source_id": 12154, + "items_per_page": 20, + "button_load_more_label": "", + "schema_property": null, + "property_options": [], + "fields": [ + { + "uid": "e895bc3b-9a13-4393-9b28-a1c09afb05e0", + "name": "Car", + "type": "link", + "styles": {}, + "config": { + "navigation_type": "page", + "navigate_to_page_id": 6677, + "page_parameters": [ + { + "name": "car_id", + "value": "get('current_record.field_59781.0.id')" + } + ], + "query_parameters": [], + "navigate_to_url": "", + "target": "self", + "link_name": "concat(get('current_record.field_59863.*.value'),' - ',get('current_record.field_59850'),' (',get('current_record.field_59864.*.value'),')')", + "variant": "link" + } + }, + { + "uid": "1aaccc17-87af-4f70-a3fd-0c3aff8ff629", + "name": "Date", + "type": "text", + "styles": {}, + "config": { + "value": "get('current_record.field_59783')" + } + }, + { + "uid": "97746ab7-3697-4002-ad76-3d20e7b21a77", + "name": "Price offered", + "type": "text", + "styles": {}, + "config": { + "value": "concat('$',get('current_record.field_59784'))" + } + }, + { + "uid": "538eaa76-df6e-4b71-8036-74b26b97d1ff", + "name": "Financing", + "type": "text", + "styles": {}, + "config": { + "value": "get('current_record.field_59789.*.value')" + } + }, + { + "uid": "fb0925e4-aa46-4a0b-9bf3-f83ff245a3ab", + "name": "Branch", + "type": "text", + "styles": {}, + "config": { + "value": "get('current_record.field_59852')" + } + }, + { + "uid": "bf4c10b7-1ceb-4e45-81af-e8e9f4fbaf34", + "name": "Status", + "type": "tags", + "styles": {}, + "config": { + "values": "get('current_record.field_59790.value')", + "colors_is_formula": true, + "colors": "get('current_record.field_59790.color')" + } + } + ], + "orientation": { + "tablet": "vertical", + "desktop": "horizontal", + "smartphone": "vertical" + } + }, + { + "id": 106763, + "order": "4.00000000000000000000", + "type": "input_text", + "parent_element_id": 106757, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "label": "'ZIP CODE:'", + "required": true, + "validation_type": "any", + "placeholder": "", + "default_value": "get('data_source.12152.field_59815')", + "is_multiline": false, + "rows": 3, + "input_type": "text" + }, + { + "id": 106775, + "order": "4.00000000000000000000", + "type": "heading", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 50, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'My reviews'", + "level": 2 + }, + { + "id": 106764, + "order": "5.00000000000000000000", + "type": "input_text", + "parent_element_id": 106757, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "label": "'CITY:'", + "required": true, + "validation_type": "any", + "placeholder": "", + "default_value": "get('data_source.12152.field_59813')", + "is_multiline": false, + "rows": 3, + "input_type": "text" + }, + { + "id": 106776, + "order": "5.00000000000000000000", + "type": "table", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "data_source_id": 12155, + "items_per_page": 20, + "button_load_more_label": "", + "schema_property": null, + "property_options": [], + "fields": [ + { + "uid": "51a150a3-cedf-4d68-af1f-bd7b0922c9a3", + "name": "Title", + "type": "text", + "styles": {}, + "config": { + "value": "get('current_record.field_59821')" + } + }, + { + "uid": "115aa607-b1ec-4bc5-b7b0-ba6fdd07ca59", + "name": "Description", + "type": "text", + "styles": {}, + "config": { + "value": "get('current_record.field_59822')" + } + }, + { + "uid": "2846f6c9-98ba-4822-8fb4-ed1515b127d1", + "name": "Stars", + "type": "text", + "styles": {}, + "config": { + "value": "get('current_record.field_59823.value')" + } + }, + { + "uid": "682d7096-7ebb-4359-aa40-4460aa428131", + "name": "-", + "type": "link", + "styles": {}, + "config": { + "navigation_type": "page", + "navigate_to_page_id": 6678, + "page_parameters": [ + { + "name": "car_id", + "value": "get('current_record.field_59826.0.id')" + }, + { + "name": "offer_id", + "value": "get('current_record.field_59824.0.id')" + } + ], + "query_parameters": [], + "navigate_to_url": "", + "target": "self", + "link_name": "'Sale details'", + "variant": "button" + } + } + ], + "orientation": { + "tablet": "horizontal", + "desktop": "horizontal", + "smartphone": "horizontal" + } + }, + { + "id": 106765, + "order": "6.00000000000000000000", + "type": "input_text", + "parent_element_id": 106757, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "label": "'STATE:'", + "required": true, + "validation_type": "any", + "placeholder": "", + "default_value": "get('data_source.12152.field_59814')", + "is_multiline": false, + "rows": 3, + "input_type": "text" + } + ], + "data_sources": [ + { + "id": 12152, + "name": "Customer details", + "order": "1.00000000000000000000", + "service": { + "id": 15008, + "integration_id": 900, + "type": "local_baserow_get_row", + "table_id": 5701, + "view_id": 26496, + "search_query": "", + "filter_type": "AND", + "filters": [], + "row_id": "get('user.id')" + } + }, + { + "id": 12153, + "name": "My accepted offers", + "order": "2.00000000000000000000", + "service": { + "id": 15009, + "integration_id": 900, + "type": "local_baserow_list_rows", + "table_id": 5698, + "view_id": 26482, + "sortings": [], + "search_query": "", + "filter_type": "AND", + "filters": [ + { + "field_id": 59785, + "type": "link_row_has", + "value": "get('user.id')", + "value_is_formula": true + } + ] + } + }, + { + "id": 12154, + "name": "Not accepted (yet) offers", + "order": "3.00000000000000000000", + "service": { + "id": 15010, + "integration_id": 900, + "type": "local_baserow_list_rows", + "table_id": 5698, + "view_id": 26483, + "sortings": [], + "search_query": "", + "filter_type": "AND", + "filters": [ + { + "field_id": 59785, + "type": "link_row_has", + "value": "get('user.id')", + "value_is_formula": true + } + ] + } + }, + { + "id": 12155, + "name": "My reviews", + "order": "4.00000000000000000000", + "service": { + "id": 15011, + "integration_id": 900, + "type": "local_baserow_list_rows", + "table_id": 5702, + "view_id": 26500, + "sortings": [], + "search_query": "", + "filter_type": "AND", + "filters": [ + { + "field_id": 59868, + "type": "equal", + "value": "get('user.email')", + "value_is_formula": true + } + ] + } + } + ], + "workflow_actions": [ + { + "id": 13950, + "type": "update_row", + "order": 1, + "page_id": 6670, + "element_id": 106757, + "event": "submit", + "service": { + "id": 15025, + "integration_id": 900, + "type": "local_baserow_upsert_row", + "table_id": 5701, + "row_id": "get('data_source.12152.id')", + "field_mappings": [ + { + "field_id": 59811, + "value": "get('form_data.106758')", + "enabled": true + }, + { + "field_id": 59812, + "value": "get('form_data.106762')", + "enabled": true + }, + { + "field_id": 59813, + "value": "get('form_data.106764')", + "enabled": true + }, + { + "field_id": 59814, + "value": "get('form_data.106765')", + "enabled": true + }, + { + "field_id": 59815, + "value": "get('form_data.106763')", + "enabled": true + }, + { + "field_id": 59816, + "value": "get('form_data.106761')", + "enabled": true + }, + { + "field_id": 59817, + "value": "", + "enabled": false + }, + { + "field_id": 59818, + "value": "", + "enabled": false + }, + { + "field_id": 59819, + "value": "", + "enabled": false + }, + { + "field_id": 59820, + "value": "", + "enabled": false + } + ] + } + }, + { + "id": 13951, + "type": "update_row", + "order": 1, + "page_id": 6670, + "element_id": 106756, + "event": "submit", + "service": { + "id": 15026, + "integration_id": 900, + "type": "local_baserow_upsert_row", + "table_id": 5701, + "row_id": "get('data_source.12152.id')", + "field_mappings": [ + { + "field_id": 59811, + "value": "", + "enabled": true + }, + { + "field_id": 59812, + "value": "", + "enabled": true + }, + { + "field_id": 59813, + "value": "", + "enabled": true + }, + { + "field_id": 59814, + "value": "", + "enabled": true + }, + { + "field_id": 59815, + "value": "", + "enabled": true + }, + { + "field_id": 59816, + "value": "", + "enabled": true + }, + { + "field_id": 59817, + "value": "get('form_data.106759')", + "enabled": true + }, + { + "field_id": 59818, + "value": "", + "enabled": false + }, + { + "field_id": 59819, + "value": "", + "enabled": false + }, + { + "field_id": 59820, + "value": "get('form_data.106760')", + "enabled": true + } + ] + } + }, + { + "id": 13952, + "type": "logout", + "order": 1, + "page_id": 6670, + "element_id": 106767, + "event": "click" + }, + { + "id": 13953, + "type": "open_page", + "order": 2, + "page_id": 6670, + "element_id": 106767, + "event": "click", + "navigation_type": "page", + "navigate_to_page_id": 6668, + "page_parameters": [], + "query_parameters": [], + "navigate_to_url": "", + "target": "self" + }, + { + "id": 13954, + "type": "notification", + "order": 2, + "page_id": 6670, + "element_id": 106757, + "event": "submit", + "title": "'\u2705 Success'", + "description": "'Your contact information has been updated'" + }, + { + "id": 13955, + "type": "notification", + "order": 2, + "page_id": 6670, + "element_id": 106756, + "event": "submit", + "title": "'\u2705 Success'", + "description": "'Your account has been updated'" + } + ], + "visibility": "logged-in", + "role_type": "allow_all", + "roles": [] + }, + { + "id": 6671, + "name": "Contact", + "order": 4, + "path": "/contact", + "path_params": [], + "query_params": [], + "shared": false, + "elements": [ + { + "id": 106778, + "order": "1.00000000000000000000", + "type": "input_text", + "parent_element_id": 106777, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "label": "'NAME'", + "required": true, + "validation_type": "any", + "placeholder": "", + "default_value": "", + "is_multiline": false, + "rows": 3, + "input_type": "text" + }, + { + "id": 106782, + "order": "1.00000000000000000000", + "type": "heading", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Get in touch'", + "level": 1 + }, + { + "id": 106777, + "order": "2.00000000000000000000", + "type": "form_container", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "button": { + "button_alignment": "center", + "button_horizontal_padding": 36 + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 20, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 20, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 40, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 40, + "style_margin_right": 0, + "style_background_radius": 8, + "style_border_radius": 0, + "style_background": "color", + "style_background_color": "#eae0d580", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "small", + "style_width_child": "normal", + "submit_button_label": "'Send your message'", + "reset_initial_values_post_submission": false + }, + { + "id": 106779, + "order": "2.00000000000000000000", + "type": "input_text", + "parent_element_id": 106777, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "label": "'EMAIL'", + "required": true, + "validation_type": "any", + "placeholder": "", + "default_value": "", + "is_multiline": false, + "rows": 3, + "input_type": "text" + }, + { + "id": 106780, + "order": "3.00000000000000000000", + "type": "input_text", + "parent_element_id": 106777, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "label": "'PHONE'", + "required": false, + "validation_type": "any", + "placeholder": "", + "default_value": "", + "is_multiline": false, + "rows": 3, + "input_type": "text" + }, + { + "id": 106781, + "order": "4.00000000000000000000", + "type": "input_text", + "parent_element_id": 106777, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "label": "'YOUR MESSAGE'", + "required": true, + "validation_type": "any", + "placeholder": "", + "default_value": "", + "is_multiline": true, + "rows": 5, + "input_type": "password" + } + ], + "data_sources": [], + "workflow_actions": [ + { + "id": 13956, + "type": "create_row", + "order": 1, + "page_id": 6671, + "element_id": 106777, + "event": "submit", + "service": { + "id": 15027, + "integration_id": 900, + "type": "local_baserow_upsert_row", + "table_id": 5704, + "row_id": "", + "field_mappings": [ + { + "field_id": 59832, + "value": "get('form_data.106781')", + "enabled": true + }, + { + "field_id": 59829, + "value": "get('form_data.106778')", + "enabled": true + }, + { + "field_id": 59830, + "value": "get('form_data.106779')", + "enabled": true + }, + { + "field_id": 59831, + "value": "get('form_data.106780')", + "enabled": true + } + ] + } + }, + { + "id": 13957, + "type": "open_page", + "order": 2, + "page_id": 6671, + "element_id": 106777, + "event": "submit", + "navigation_type": "page", + "navigate_to_page_id": 6672, + "page_parameters": [ + { + "name": "contact_id", + "value": "get('previous_action.13956.id')" + } + ], + "query_parameters": [], + "navigate_to_url": "", + "target": "self" + } + ], + "visibility": "all", + "role_type": "allow_all", + "roles": [] + }, + { + "id": 6672, + "name": "Contact confirmation", + "order": 5, + "path": "/contact-confirmation/:contact_id", + "path_params": [ + { + "name": "contact_id", + "type": "numeric" + } + ], + "query_params": [], + "shared": false, + "elements": [ + { + "id": 106783, + "order": "1.00000000000000000000", + "type": "heading", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Thank you for your message'", + "level": 1 + }, + { + "id": 106784, + "order": "2.00000000000000000000", + "type": "text", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_weight": "bold" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 1, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'We will contact you as soon as possible to answer your question or feedback.'", + "format": "plain" + }, + { + "id": 106785, + "order": "3.00000000000000000000", + "type": "text", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_color": "secondary" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'YOUR NAME'", + "format": "plain" + }, + { + "id": 106786, + "order": "3.50000000000000000000", + "type": "text", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 30, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "get('data_source.12156.field_59829')", + "format": "plain" + }, + { + "id": 106787, + "order": "4.00000000000000000000", + "type": "text", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_color": "secondary" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'YOUR EMAIL'", + "format": "plain" + }, + { + "id": 106788, + "order": "4.50000000000000000000", + "type": "text", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 30, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "get('data_source.12156.field_59830')", + "format": "plain" + }, + { + "id": 106789, + "order": "5.00000000000000000000", + "type": "text", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_color": "secondary" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'YOUR PHONE NUMBER'", + "format": "plain" + }, + { + "id": 106790, + "order": "5.50000000000000000000", + "type": "text", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 30, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "concat(get('data_source.12156.field_59829'),get('data_source.12156.field_59831'))", + "format": "plain" + }, + { + "id": 106791, + "order": "6.00000000000000000000", + "type": "text", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_color": "secondary" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'YOUR MESSAGE'", + "format": "plain" + }, + { + "id": 106792, + "order": "7.00000000000000000000", + "type": "text", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 1, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 30, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "get('data_source.12156.field_59832')", + "format": "plain" + } + ], + "data_sources": [ + { + "id": 12156, + "name": "Get contact information", + "order": "1.00000000000000000000", + "service": { + "id": 15012, + "integration_id": 900, + "type": "local_baserow_get_row", + "table_id": 5704, + "view_id": 26505, + "search_query": "", + "filter_type": "AND", + "filters": [], + "row_id": "get('page_parameter.contact_id')" + } + } + ], + "workflow_actions": [], + "visibility": "all", + "role_type": "allow_all", + "roles": [] + }, + { + "id": 6673, + "name": "Cars", + "order": 6, + "path": "/cars", + "path_params": [], + "query_params": [ + { + "name": "model", + "type": "numeric" + }, + { + "name": "condition", + "type": "numeric" + }, + { + "name": "max_price", + "type": "numeric" + }, + { + "name": "milage", + "type": "numeric" + } + ], + "shared": false, + "elements": [ + { + "id": 106794, + "order": "1.00000000000000000000", + "type": "heading", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 16, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "border", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Explore Our Inventory'", + "level": 1 + }, + { + "id": 106795, + "order": "1.00000000000000000000", + "type": "repeat", + "parent_element_id": 106793, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "data_source_id": 12157, + "items_per_page": 20, + "button_load_more_label": "", + "schema_property": null, + "property_options": [ + { + "schema_property": "field_59762", + "filterable": false, + "sortable": false, + "searchable": false + }, + { + "schema_property": "field_59840", + "filterable": false, + "sortable": false, + "searchable": false + }, + { + "schema_property": "field_59841", + "filterable": false, + "sortable": false, + "searchable": false + }, + { + "schema_property": "field_59763", + "filterable": false, + "sortable": false, + "searchable": false + } + ], + "orientation": "horizontal", + "items_per_row": { + "tablet": 2, + "desktop": 4, + "smartphone": 2 + }, + "horizontal_gap": 30, + "vertical_gap": 30 + }, + { + "id": 106796, + "order": "1.00000000000000000000", + "type": "heading", + "parent_element_id": 106795, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "heading_2_text_alignment": "left" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 10, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "color", + "style_background_color": "#eae0d580", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "concat(get('current_record.field_59840.*.value'),' - ',get('current_record.field_59762.*.value'))", + "level": 2 + }, + { + "id": 106963, + "order": "1.00000000000000000000", + "type": "column", + "parent_element_id": 106962, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "column_amount": 4, + "column_gap": 20, + "alignment": "top" + }, + { + "id": 106964, + "order": "1.00000000000000000000", + "type": "record_selector", + "parent_element_id": 106963, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "data_source_id": 12169, + "items_per_page": 20, + "button_load_more_label": "", + "schema_property": null, + "property_options": [], + "required": false, + "label": "'MODEL'", + "default_value": "get('page_parameter.model')", + "placeholder": "", + "multiple": false, + "option_name_suffix": "" + }, + { + "id": 106965, + "order": "1.00000000000000000000", + "type": "choice", + "parent_element_id": 106963, + "place_in_container": "1", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "label": "'CONDITION'", + "required": false, + "placeholder": "", + "default_value": "get('page_parameter.condition')", + "options": [], + "multiple": false, + "show_as_dropdown": true, + "option_type": "formulas", + "formula_value": "get('data_source_context.12157.field_59763.*.id')", + "formula_name": "get('data_source_context.12157.field_59763.*.value')" + }, + { + "id": 106966, + "order": "1.00000000000000000000", + "type": "input_text", + "parent_element_id": 106963, + "place_in_container": "2", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "label": "'MAXIMUM PRICE ($)'", + "required": false, + "validation_type": "integer", + "placeholder": "", + "default_value": "get('page_parameter.max_price')", + "is_multiline": false, + "rows": 3, + "input_type": "text" + }, + { + "id": 106967, + "order": "1.00000000000000000000", + "type": "input_text", + "parent_element_id": 106963, + "place_in_container": "3", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "label": "'MAXIMUM MILAGE'", + "required": false, + "validation_type": "integer", + "placeholder": "", + "default_value": "get('page_parameter.milage')", + "is_multiline": false, + "rows": 3, + "input_type": "text" + }, + { + "id": 106962, + "order": "1.50000000000000000000", + "type": "form_container", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "submit_button_label": "'FILTER'", + "reset_initial_values_post_submission": false + }, + { + "id": 106793, + "order": "2.00000000000000000000", + "type": "column", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "column_amount": 1, + "column_gap": 20, + "alignment": "top" + }, + { + "id": 106797, + "order": "2.00000000000000000000", + "type": "image", + "parent_element_id": 106795, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "image": {} + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 10, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "color", + "style_background_color": "#eae0d580", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "image_source_type": "url", + "image_file_id": null, + "image_url": "get('current_record.field_59761.*.url')", + "alt_text": "" + }, + { + "id": 106798, + "order": "2.50000000000000000000", + "type": "link", + "parent_element_id": 106795, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "button": { + "button_width": "full", + "button_font_size": 14, + "button_text_color": "#ffffff", + "button_border_size": 0, + "button_font_weight": "semi-bold", + "button_border_radius": 0, + "button_background_color": "primary" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 10, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "color", + "style_background_color": "#eae0d580", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "navigation_type": "page", + "navigate_to_page_id": 6674, + "page_parameters": [ + { + "name": "car_id", + "value": "get('current_record.id')" + } + ], + "query_parameters": [], + "navigate_to_url": "", + "target": "self", + "value": "'DETAILS'", + "variant": "button" + }, + { + "id": 106799, + "order": "3.00000000000000000000", + "type": "text", + "parent_element_id": 106795, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 18, + "body_text_color": "primary", + "body_font_weight": "bold" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 5, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 5, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "color", + "style_background_color": "#eae0d580", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "concat('$ ',get('current_record.field_59842'))", + "format": "plain" + }, + { + "id": 106800, + "order": "3.50000000000000000000", + "type": "text", + "parent_element_id": 106795, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_color": "secondary" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "color", + "style_background_color": "#eae0d580", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'YEAR'", + "format": "plain" + }, + { + "id": 106801, + "order": "3.60000000000000008882", + "type": "text", + "parent_element_id": 106795, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": {} + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "color", + "style_background_color": "#eae0d580", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "get('current_record.field_59841.*.value')", + "format": "plain" + }, + { + "id": 106802, + "order": "3.66666666666666651864", + "type": "text", + "parent_element_id": 106795, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_color": "secondary" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "color", + "style_background_color": "#eae0d580", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'TYPE'", + "format": "plain" + }, + { + "id": 106803, + "order": "3.71428571428571441260", + "type": "text", + "parent_element_id": 106795, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": {} + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "color", + "style_background_color": "#eae0d580", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "get('current_record.field_59848.*.value.value')", + "format": "plain" + }, + { + "id": 106804, + "order": "3.79999999999999982236", + "type": "text", + "parent_element_id": 106795, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_color": "secondary" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "color", + "style_background_color": "#eae0d580", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'CONDITION'", + "format": "plain" + }, + { + "id": 106805, + "order": "3.83333333333333348136", + "type": "text", + "parent_element_id": 106795, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": {} + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "color", + "style_background_color": "#eae0d580", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "get('current_record.field_59763.value')", + "format": "plain" + }, + { + "id": 106806, + "order": "4.00000000000000000000", + "type": "text", + "parent_element_id": 106795, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_color": "secondary" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "color", + "style_background_color": "#eae0d580", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'AVAILABLE AT'", + "format": "plain" + }, + { + "id": 106807, + "order": "5.00000000000000000000", + "type": "text", + "parent_element_id": 106795, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_text_color": "#070810" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "color", + "style_background_color": "#eae0d580", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "concat(get('current_record.field_59775.*.value'),' branch')", + "format": "plain" + } + ], + "data_sources": [ + { + "id": 12157, + "name": "Our cars", + "order": "1.00000000000000000000", + "service": { + "id": 15013, + "integration_id": 900, + "type": "local_baserow_list_rows", + "table_id": 5697, + "view_id": 26468, + "sortings": [], + "search_query": "", + "filter_type": "AND", + "filters": [ + { + "field_id": 59764, + "type": "lower_than_or_equal", + "value": "get('page_parameter.milage')", + "value_is_formula": true + }, + { + "field_id": 59842, + "type": "lower_than_or_equal", + "value": "get('page_parameter.max_price')", + "value_is_formula": true + }, + { + "field_id": 59762, + "type": "link_row_has", + "value": "get('page_parameter.model')", + "value_is_formula": true + }, + { + "field_id": 59763, + "type": "single_select_equal", + "value": "get('page_parameter.condition')", + "value_is_formula": true + } + ] + } + }, + { + "id": 12169, + "name": "All models", + "order": "2.00000000000000000000", + "service": { + "id": 15030, + "integration_id": 900, + "type": "local_baserow_list_rows", + "table_id": 5696, + "view_id": 26456, + "sortings": [], + "search_query": "", + "filter_type": "AND", + "filters": [] + } + } + ], + "workflow_actions": [ + { + "id": 13963, + "type": "open_page", + "order": 1, + "page_id": 6673, + "element_id": 106962, + "event": "submit", + "navigation_type": "page", + "navigate_to_page_id": 6673, + "page_parameters": [], + "query_parameters": [ + { + "name": "model", + "value": "get('form_data.106964')" + }, + { + "name": "condition", + "value": "get('form_data.106965')" + }, + { + "name": "max_price", + "value": "get('form_data.106966')" + }, + { + "name": "milage", + "value": "get('form_data.106967')" + } + ], + "navigate_to_url": "", + "target": "self" + } + ], + "visibility": "all", + "role_type": "allow_all", + "roles": [] + }, + { + "id": 6674, + "name": "Car details", + "order": 7, + "path": "/car-details/:car_id", + "path_params": [ + { + "name": "car_id", + "type": "numeric" + } + ], + "query_params": [], + "shared": false, + "elements": [ + { + "id": 106809, + "order": "0.50000000000000000000", + "type": "text", + "parent_element_id": 106808, + "place_in_container": "1", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 22, + "body_text_color": "primary", + "body_font_weight": "bold" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "concat('$ ',get('data_source.12158.field_59842'))", + "format": "plain" + }, + { + "id": 106810, + "order": "0.66666666666666662966", + "type": "link", + "parent_element_id": 106808, + "place_in_container": "1", + "visibility": "logged-in", + "role_type": "allow_all", + "roles": [], + "styles": { + "button": { + "button_width": "full", + "button_font_size": 16, + "button_text_color": "#ffffff", + "button_font_weight": "semi-bold", + "button_background_color": "primary", + "button_hover_border_color": "secondary", + "button_hover_background_color": "secondary" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "navigation_type": "page", + "navigate_to_page_id": 6675, + "page_parameters": [ + { + "name": "car_id", + "value": "get('data_source.12158.id')" + } + ], + "query_parameters": [], + "navigate_to_url": "", + "target": "self", + "value": "'MAKE OFFER'", + "variant": "button" + }, + { + "id": 106811, + "order": "0.75000000000000000000", + "type": "link", + "parent_element_id": 106808, + "place_in_container": "1", + "visibility": "not-logged", + "role_type": "allow_all", + "roles": [], + "styles": { + "button": { + "button_width": "full", + "button_font_size": 16, + "button_text_color": "#ffffff", + "button_font_weight": "semi-bold", + "button_background_color": "primary", + "button_hover_border_color": "secondary", + "button_hover_background_color": "secondary" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "navigation_type": "page", + "navigate_to_page_id": 6669, + "page_parameters": [], + "query_parameters": [], + "navigate_to_url": "", + "target": "self", + "value": "'Log in to make an offer'", + "variant": "link" + }, + { + "id": 106812, + "order": "1.00000000000000000000", + "type": "heading", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "concat(get('data_source.12158.field_59840.*.value'),' - ',get('data_source.12158.field_59762.*.value'))", + "level": 1 + }, + { + "id": 106813, + "order": "1.00000000000000000000", + "type": "image", + "parent_element_id": 106808, + "place_in_container": "1", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "image": { + "image_border_radius": 8 + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "image_source_type": "url", + "image_file_id": null, + "image_url": "get('data_source.12158.field_59761.*.url')", + "alt_text": "" + }, + { + "id": 106814, + "order": "1.00000000000000000000", + "type": "text", + "parent_element_id": 106808, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_color": "secondary" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'YEAR'", + "format": "plain" + }, + { + "id": 106808, + "order": "2.00000000000000000000", + "type": "column", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "column_amount": 2, + "column_gap": 20, + "alignment": "top" + }, + { + "id": 106815, + "order": "2.00000000000000000000", + "type": "text", + "parent_element_id": 106808, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": {} + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "get('data_source.12158.field_59841.*.value')", + "format": "plain" + }, + { + "id": 106816, + "order": "3.00000000000000000000", + "type": "text", + "parent_element_id": 106808, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_color": "secondary" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'TYPE'", + "format": "plain" + }, + { + "id": 106817, + "order": "4.00000000000000000000", + "type": "text", + "parent_element_id": 106808, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": {} + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "get('data_source.12158.field_59848.*.value.value')", + "format": "plain" + }, + { + "id": 106818, + "order": "4.50000000000000000000", + "type": "text", + "parent_element_id": 106808, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_color": "secondary" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'DIMENSIONS'", + "format": "plain" + }, + { + "id": 106819, + "order": "4.66666666666666696273", + "type": "text", + "parent_element_id": 106808, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": {} + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "get('data_source.12158.field_59849')", + "format": "plain" + }, + { + "id": 106820, + "order": "5.00000000000000000000", + "type": "text", + "parent_element_id": 106808, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_color": "secondary" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'CONDITION'", + "format": "plain" + }, + { + "id": 106821, + "order": "6.00000000000000000000", + "type": "text", + "parent_element_id": 106808, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": {} + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "get('data_source.12158.field_59763.value')", + "format": "plain" + }, + { + "id": 106822, + "order": "6.33333333333333303727", + "type": "text", + "parent_element_id": 106808, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_color": "secondary" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'DATE ACQUIRED'", + "format": "plain" + }, + { + "id": 106823, + "order": "6.40000000000000035527", + "type": "text", + "parent_element_id": 106808, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": {} + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "get('data_source.12158.field_59773')", + "format": "plain" + }, + { + "id": 106824, + "order": "6.50000000000000000000", + "type": "text", + "parent_element_id": 106808, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_color": "secondary" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'AVAILABLE AT'", + "format": "plain" + }, + { + "id": 106825, + "order": "6.66666666666666696273", + "type": "text", + "parent_element_id": 106808, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": {} + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "concat(get('data_source.12158.field_59775.*.value'),' branch')", + "format": "plain" + }, + { + "id": 106826, + "order": "7.00000000000000000000", + "type": "text", + "parent_element_id": 106808, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_color": "secondary" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'MILAGE'", + "format": "plain" + }, + { + "id": 106827, + "order": "8.00000000000000000000", + "type": "text", + "parent_element_id": 106808, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": {} + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "concat(get('data_source.12158.field_59764'),' miles')", + "format": "plain" + }, + { + "id": 106828, + "order": "9.00000000000000000000", + "type": "text", + "parent_element_id": 106808, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_color": "secondary" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'COLOR'", + "format": "plain" + }, + { + "id": 106829, + "order": "10.00000000000000000000", + "type": "text", + "parent_element_id": 106808, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": {} + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "concat(get('data_source.12158.field_59765'),' miles')", + "format": "plain" + }, + { + "id": 106830, + "order": "11.00000000000000000000", + "type": "text", + "parent_element_id": 106808, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_color": "secondary" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'ACCESSORIES'", + "format": "plain" + }, + { + "id": 106831, + "order": "12.00000000000000000000", + "type": "text", + "parent_element_id": 106808, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": {} + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "concat(get('data_source.12158.field_59769'),' miles')", + "format": "plain" + } + ], + "data_sources": [ + { + "id": 12158, + "name": "Car details", + "order": "1.00000000000000000000", + "service": { + "id": 15014, + "integration_id": 900, + "type": "local_baserow_get_row", + "table_id": 5697, + "view_id": 26465, + "search_query": "", + "filter_type": "AND", + "filters": [], + "row_id": "get('page_parameter.car_id')" + } + } + ], + "workflow_actions": [], + "visibility": "all", + "role_type": "allow_all", + "roles": [] + }, + { + "id": 6675, + "name": "Car offer", + "order": 8, + "path": "/car-offer/:car_id", + "path_params": [ + { + "name": "car_id", + "type": "numeric" + } + ], + "query_params": [], + "shared": false, + "elements": [ + { + "id": 106833, + "order": "0.50000000000000000000", + "type": "image", + "parent_element_id": 106832, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "image": { + "image_border_radius": 8 + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "image_source_type": "url", + "image_file_id": null, + "image_url": "get('data_source.12159.field_59761.*.url')", + "alt_text": "" + }, + { + "id": 106834, + "order": "0.50000000000000000000", + "type": "text", + "parent_element_id": 106832, + "place_in_container": "1", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_text_color": "primary", + "body_font_weight": "bold" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "concat('You have currently ',get('data_source.12161.result'),' offer(s) on this car.')", + "format": "plain" + }, + { + "id": 106835, + "order": "1.00000000000000000000", + "type": "heading", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "concat('Make an offer for ',get('data_source.12159.field_59840.*.value'),' - ',get('data_source.12159.field_59762.*.value'))", + "level": 1 + }, + { + "id": 106836, + "order": "1.00000000000000000000", + "type": "text", + "parent_element_id": 106832, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_color": "secondary" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'YEAR'", + "format": "plain" + }, + { + "id": 106854, + "order": "1.00000000000000000000", + "type": "form_container", + "parent_element_id": 106832, + "place_in_container": "1", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "button": { + "button_horizontal_padding": 36 + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 20, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 20, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 40, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 40, + "style_margin_right": 0, + "style_background_radius": 8, + "style_border_radius": 0, + "style_background": "color", + "style_background_color": "#eae0d580", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "submit_button_label": "'SEND OFFER'", + "reset_initial_values_post_submission": false + }, + { + "id": 106855, + "order": "1.00000000000000000000", + "type": "input_text", + "parent_element_id": 106854, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "label": "'YOUR OFFERED PRICE ($)'", + "required": true, + "validation_type": "integer", + "placeholder": "", + "default_value": "get('data_source.12159.field_59842')", + "is_multiline": false, + "rows": 3, + "input_type": "text" + }, + { + "id": 106832, + "order": "2.00000000000000000000", + "type": "column", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "column_amount": 2, + "column_gap": 20, + "alignment": "top" + }, + { + "id": 106837, + "order": "2.00000000000000000000", + "type": "text", + "parent_element_id": 106832, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": {} + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "get('data_source.12159.field_59841.*.value')", + "format": "plain" + }, + { + "id": 106856, + "order": "2.00000000000000000000", + "type": "record_selector", + "parent_element_id": 106854, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "data_source_id": 12160, + "items_per_page": 20, + "button_load_more_label": "", + "schema_property": null, + "property_options": [], + "required": true, + "label": "'FINANCING'", + "default_value": "", + "placeholder": "", + "multiple": false, + "option_name_suffix": "" + }, + { + "id": 106838, + "order": "3.00000000000000000000", + "type": "text", + "parent_element_id": 106832, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_color": "secondary" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'TYPE'", + "format": "plain" + }, + { + "id": 106839, + "order": "4.00000000000000000000", + "type": "text", + "parent_element_id": 106832, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": {} + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "get('data_source.12159.field_59848.*.value.value')", + "format": "plain" + }, + { + "id": 106840, + "order": "4.50000000000000000000", + "type": "text", + "parent_element_id": 106832, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_color": "secondary" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'DIMENSIONS'", + "format": "plain" + }, + { + "id": 106841, + "order": "4.66666666666666696273", + "type": "text", + "parent_element_id": 106832, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": {} + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "get('data_source.12159.field_59849')", + "format": "plain" + }, + { + "id": 106842, + "order": "5.00000000000000000000", + "type": "text", + "parent_element_id": 106832, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_color": "secondary" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'CONDITION'", + "format": "plain" + }, + { + "id": 106843, + "order": "6.00000000000000000000", + "type": "text", + "parent_element_id": 106832, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": {} + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "get('data_source.12159.field_59763.value')", + "format": "plain" + }, + { + "id": 106844, + "order": "6.33333333333333303727", + "type": "text", + "parent_element_id": 106832, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_color": "secondary" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'DATE ACQUIRED'", + "format": "plain" + }, + { + "id": 106845, + "order": "6.40000000000000035527", + "type": "text", + "parent_element_id": 106832, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": {} + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "get('data_source.12159.field_59773')", + "format": "plain" + }, + { + "id": 106846, + "order": "6.50000000000000000000", + "type": "text", + "parent_element_id": 106832, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_color": "secondary" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'AVAILABLE AT'", + "format": "plain" + }, + { + "id": 106847, + "order": "6.66666666666666696273", + "type": "text", + "parent_element_id": 106832, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": {} + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "concat(get('data_source.12159.field_59775.*.value'),' branch')", + "format": "plain" + }, + { + "id": 106848, + "order": "7.00000000000000000000", + "type": "text", + "parent_element_id": 106832, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_color": "secondary" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'MILAGE'", + "format": "plain" + }, + { + "id": 106849, + "order": "8.00000000000000000000", + "type": "text", + "parent_element_id": 106832, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": {} + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "concat(get('data_source.12159.field_59764'),' miles')", + "format": "plain" + }, + { + "id": 106850, + "order": "9.00000000000000000000", + "type": "text", + "parent_element_id": 106832, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_color": "secondary" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'COLOR'", + "format": "plain" + }, + { + "id": 106851, + "order": "10.00000000000000000000", + "type": "text", + "parent_element_id": 106832, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": {} + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "concat(get('data_source.12159.field_59765'),' miles')", + "format": "plain" + }, + { + "id": 106852, + "order": "11.00000000000000000000", + "type": "text", + "parent_element_id": 106832, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_color": "secondary" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'ACCESSORIES'", + "format": "plain" + }, + { + "id": 106853, + "order": "12.00000000000000000000", + "type": "text", + "parent_element_id": 106832, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": {} + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "concat(get('data_source.12159.field_59769'),' miles')", + "format": "plain" + } + ], + "data_sources": [ + { + "id": 12159, + "name": "Car details", + "order": "1.00000000000000000000", + "service": { + "id": 15015, + "integration_id": 900, + "type": "local_baserow_get_row", + "table_id": 5697, + "view_id": 26465, + "search_query": "", + "filter_type": "AND", + "filters": [], + "row_id": "get('page_parameter.car_id')" + } + }, + { + "id": 12160, + "name": "Financing options", + "order": "2.00000000000000000000", + "service": { + "id": 15016, + "integration_id": 900, + "type": "local_baserow_list_rows", + "table_id": 5703, + "view_id": 26504, + "sortings": [], + "search_query": "", + "filter_type": "AND", + "filters": [] + } + }, + { + "id": 12161, + "name": "Current offers", + "order": "3.00000000000000000000", + "service": { + "id": 15017, + "integration_id": 900, + "type": "local_baserow_aggregate_rows", + "table_id": 5698, + "view_id": 26484, + "search_query": "", + "filter_type": "AND", + "filters": [ + { + "field_id": 59785, + "type": "link_row_has", + "value": "get('user.id')", + "value_is_formula": true + }, + { + "field_id": 59781, + "type": "link_row_has", + "value": "get('page_parameter.car_id')", + "value_is_formula": true + } + ], + "field_id": 59780, + "aggregation_type": "count" + } + } + ], + "workflow_actions": [ + { + "id": 13958, + "type": "create_row", + "order": 1, + "page_id": 6675, + "element_id": 106854, + "event": "submit", + "service": { + "id": 15028, + "integration_id": 900, + "type": "local_baserow_upsert_row", + "table_id": 5698, + "row_id": "", + "field_mappings": [ + { + "field_id": 59790, + "value": "'Under consideration'", + "enabled": true + }, + { + "field_id": 59789, + "value": "get('form_data.106856')", + "enabled": true + }, + { + "field_id": 59784, + "value": "get('form_data.106855')", + "enabled": true + }, + { + "field_id": 59783, + "value": "get('data_source.12159.field_59779')", + "enabled": true + }, + { + "field_id": 59782, + "value": "", + "enabled": false + }, + { + "field_id": 59781, + "value": "get('page_parameter.car_id')", + "enabled": true + }, + { + "field_id": 59785, + "value": "get('user.id')", + "enabled": true + }, + { + "field_id": 59786, + "value": "", + "enabled": false + }, + { + "field_id": 59787, + "value": "", + "enabled": false + }, + { + "field_id": 59788, + "value": "", + "enabled": false + } + ] + } + }, + { + "id": 13959, + "type": "open_page", + "order": 2, + "page_id": 6675, + "element_id": 106854, + "event": "submit", + "navigation_type": "page", + "navigate_to_page_id": 6676, + "page_parameters": [ + { + "name": "car_id", + "value": "get('page_parameter.car_id')" + }, + { + "name": "offer_id", + "value": "get('previous_action.13958.id')" + } + ], + "query_parameters": [], + "navigate_to_url": "", + "target": "self" + } + ], + "visibility": "logged-in", + "role_type": "allow_all", + "roles": [] + }, + { + "id": 6676, + "name": "Car offer confirmation", + "order": 9, + "path": "/car-offer/:car_id/:offer_id", + "path_params": [ + { + "name": "car_id", + "type": "numeric" + }, + { + "name": "offer_id", + "type": "numeric" + } + ], + "query_params": [], + "shared": false, + "elements": [ + { + "id": 106858, + "order": "0.33333333333333331483", + "type": "heading", + "parent_element_id": 106857, + "place_in_container": "1", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "heading_2_text_alignment": "left" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Offer confirmation'", + "level": 2 + }, + { + "id": 106859, + "order": "0.50000000000000000000", + "type": "image", + "parent_element_id": 106857, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "image": { + "image_border_radius": 8 + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "image_source_type": "url", + "image_file_id": null, + "image_url": "get('data_source.12162.field_59761.*.url')", + "alt_text": "" + }, + { + "id": 106860, + "order": "0.50000000000000000000", + "type": "text", + "parent_element_id": 106857, + "place_in_container": "1", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_text_color": "primary", + "body_font_weight": "bold" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Thank you for your offer. We will get in touch with you soon.'", + "format": "plain" + }, + { + "id": 106861, + "order": "1.00000000000000000000", + "type": "heading", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "concat('Make an offer for ',get('data_source.12162.field_59840.*.value'),' - ',get('data_source.12162.field_59762.*.value'))", + "level": 1 + }, + { + "id": 106862, + "order": "1.00000000000000000000", + "type": "text", + "parent_element_id": 106857, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_color": "secondary" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'YEAR'", + "format": "plain" + }, + { + "id": 106857, + "order": "2.00000000000000000000", + "type": "column", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "column_amount": 2, + "column_gap": 20, + "alignment": "top" + }, + { + "id": 106863, + "order": "2.00000000000000000000", + "type": "text", + "parent_element_id": 106857, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": {} + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "get('data_source.12162.field_59841.*.value')", + "format": "plain" + }, + { + "id": 106864, + "order": "2.00000000000000000000", + "type": "text", + "parent_element_id": 106857, + "place_in_container": "1", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_color": "secondary" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'DATE OFFER'", + "format": "plain" + }, + { + "id": 106865, + "order": "3.00000000000000000000", + "type": "text", + "parent_element_id": 106857, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_color": "secondary" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'TYPE'", + "format": "plain" + }, + { + "id": 106866, + "order": "4.00000000000000000000", + "type": "text", + "parent_element_id": 106857, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": {} + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "get('data_source.12162.field_59848.*.value.value')", + "format": "plain" + }, + { + "id": 106867, + "order": "4.00000000000000000000", + "type": "text", + "parent_element_id": 106857, + "place_in_container": "1", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": {} + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "get('data_source.12163.field_59783')", + "format": "plain" + }, + { + "id": 106868, + "order": "4.50000000000000000000", + "type": "text", + "parent_element_id": 106857, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_color": "secondary" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'DIMENSIONS'", + "format": "plain" + }, + { + "id": 106869, + "order": "4.50000000000000000000", + "type": "text", + "parent_element_id": 106857, + "place_in_container": "1", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_color": "secondary" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'FINANCING'", + "format": "plain" + }, + { + "id": 106870, + "order": "4.66666666666666696273", + "type": "text", + "parent_element_id": 106857, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": {} + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "get('data_source.12162.field_59849')", + "format": "plain" + }, + { + "id": 106871, + "order": "4.66666666666666696273", + "type": "text", + "parent_element_id": 106857, + "place_in_container": "1", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": {} + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "get('data_source.12163.field_59789.0.value')", + "format": "plain" + }, + { + "id": 106872, + "order": "5.00000000000000000000", + "type": "text", + "parent_element_id": 106857, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_color": "secondary" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'CONDITION'", + "format": "plain" + }, + { + "id": 106873, + "order": "5.00000000000000000000", + "type": "text", + "parent_element_id": 106857, + "place_in_container": "1", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_color": "secondary" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'PRICE OFFERED'", + "format": "plain" + }, + { + "id": 106874, + "order": "6.00000000000000000000", + "type": "text", + "parent_element_id": 106857, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": {} + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "get('data_source.12162.field_59763.value')", + "format": "plain" + }, + { + "id": 106875, + "order": "6.00000000000000000000", + "type": "text", + "parent_element_id": 106857, + "place_in_container": "1", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": {} + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "concat('$ ',get('data_source.12163.field_59784'))", + "format": "plain" + }, + { + "id": 106876, + "order": "6.33333333333333303727", + "type": "text", + "parent_element_id": 106857, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_color": "secondary" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'DATE ACQUIRED'", + "format": "plain" + }, + { + "id": 106877, + "order": "6.40000000000000035527", + "type": "text", + "parent_element_id": 106857, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": {} + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "get('data_source.12162.field_59773')", + "format": "plain" + }, + { + "id": 106878, + "order": "6.50000000000000000000", + "type": "text", + "parent_element_id": 106857, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_color": "secondary" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'AVAILABLE AT'", + "format": "plain" + }, + { + "id": 106879, + "order": "6.66666666666666696273", + "type": "text", + "parent_element_id": 106857, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": {} + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "concat(get('data_source.12162.field_59775.*.value'),' branch')", + "format": "plain" + }, + { + "id": 106880, + "order": "7.00000000000000000000", + "type": "text", + "parent_element_id": 106857, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_color": "secondary" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'MILAGE'", + "format": "plain" + }, + { + "id": 106881, + "order": "8.00000000000000000000", + "type": "text", + "parent_element_id": 106857, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": {} + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "concat(get('data_source.12162.field_59764'),' miles')", + "format": "plain" + }, + { + "id": 106882, + "order": "9.00000000000000000000", + "type": "text", + "parent_element_id": 106857, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_color": "secondary" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'COLOR'", + "format": "plain" + }, + { + "id": 106883, + "order": "10.00000000000000000000", + "type": "text", + "parent_element_id": 106857, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": {} + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "concat(get('data_source.12162.field_59765'),' miles')", + "format": "plain" + }, + { + "id": 106884, + "order": "11.00000000000000000000", + "type": "text", + "parent_element_id": 106857, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_color": "secondary" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'ACCESSORIES'", + "format": "plain" + }, + { + "id": 106885, + "order": "12.00000000000000000000", + "type": "text", + "parent_element_id": 106857, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": {} + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "concat(get('data_source.12162.field_59769'),' miles')", + "format": "plain" + } + ], + "data_sources": [ + { + "id": 12162, + "name": "Car details", + "order": "1.00000000000000000000", + "service": { + "id": 15018, + "integration_id": 900, + "type": "local_baserow_get_row", + "table_id": 5697, + "view_id": 26465, + "search_query": "", + "filter_type": "AND", + "filters": [], + "row_id": "" + } + }, + { + "id": 12163, + "name": "Offer details", + "order": "4.00000000000000000000", + "service": { + "id": 15019, + "integration_id": 900, + "type": "local_baserow_get_row", + "table_id": 5698, + "view_id": 26478, + "search_query": "", + "filter_type": "AND", + "filters": [], + "row_id": "get('page_parameter.offer_id')" + } + } + ], + "workflow_actions": [], + "visibility": "logged-in", + "role_type": "allow_all", + "roles": [] + }, + { + "id": 6677, + "name": "Car details without offer", + "order": 10, + "path": "/car-details-without-offer/:car_id", + "path_params": [ + { + "name": "car_id", + "type": "numeric" + } + ], + "query_params": [], + "shared": false, + "elements": [ + { + "id": 106887, + "order": "0.50000000000000000000", + "type": "text", + "parent_element_id": 106886, + "place_in_container": "1", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 22, + "body_text_color": "primary", + "body_font_weight": "bold" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "concat('Status: ',get('data_source.12164.field_59867'))", + "format": "plain" + }, + { + "id": 106888, + "order": "1.00000000000000000000", + "type": "heading", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "concat(get('data_source.12164.field_59840.*.value'),' - ',get('data_source.12164.field_59762.*.value'))", + "level": 1 + }, + { + "id": 106889, + "order": "1.00000000000000000000", + "type": "image", + "parent_element_id": 106886, + "place_in_container": "1", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "image": { + "image_border_radius": 8 + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "image_source_type": "url", + "image_file_id": null, + "image_url": "get('data_source.12164.field_59761.*.url')", + "alt_text": "" + }, + { + "id": 106890, + "order": "1.00000000000000000000", + "type": "text", + "parent_element_id": 106886, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_color": "secondary" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'YEAR'", + "format": "plain" + }, + { + "id": 106886, + "order": "2.00000000000000000000", + "type": "column", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "column_amount": 2, + "column_gap": 20, + "alignment": "top" + }, + { + "id": 106891, + "order": "2.00000000000000000000", + "type": "text", + "parent_element_id": 106886, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": {} + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "get('data_source.12164.field_59841.*.value')", + "format": "plain" + }, + { + "id": 106892, + "order": "3.00000000000000000000", + "type": "text", + "parent_element_id": 106886, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_color": "secondary" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'TYPE'", + "format": "plain" + }, + { + "id": 106893, + "order": "4.00000000000000000000", + "type": "text", + "parent_element_id": 106886, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": {} + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "get('data_source.12164.field_59848.*.value.value')", + "format": "plain" + }, + { + "id": 106894, + "order": "4.50000000000000000000", + "type": "text", + "parent_element_id": 106886, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_color": "secondary" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'DIMENSIONS'", + "format": "plain" + }, + { + "id": 106895, + "order": "4.66666666666666696273", + "type": "text", + "parent_element_id": 106886, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": {} + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "get('data_source.12164.field_59849')", + "format": "plain" + }, + { + "id": 106896, + "order": "5.00000000000000000000", + "type": "text", + "parent_element_id": 106886, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_color": "secondary" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'CONDITION'", + "format": "plain" + }, + { + "id": 106897, + "order": "6.00000000000000000000", + "type": "text", + "parent_element_id": 106886, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": {} + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "get('data_source.12164.field_59763.value')", + "format": "plain" + }, + { + "id": 106898, + "order": "6.33333333333333303727", + "type": "text", + "parent_element_id": 106886, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_color": "secondary" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'DATE ACQUIRED'", + "format": "plain" + }, + { + "id": 106899, + "order": "6.40000000000000035527", + "type": "text", + "parent_element_id": 106886, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": {} + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "get('data_source.12164.field_59773')", + "format": "plain" + }, + { + "id": 106900, + "order": "6.50000000000000000000", + "type": "text", + "parent_element_id": 106886, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_color": "secondary" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'AVAILABLE AT'", + "format": "plain" + }, + { + "id": 106901, + "order": "6.66666666666666696273", + "type": "text", + "parent_element_id": 106886, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": {} + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "concat(get('data_source.12164.field_59775.*.value'),' branch')", + "format": "plain" + }, + { + "id": 106902, + "order": "7.00000000000000000000", + "type": "text", + "parent_element_id": 106886, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_color": "secondary" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'MILAGE'", + "format": "plain" + }, + { + "id": 106903, + "order": "8.00000000000000000000", + "type": "text", + "parent_element_id": 106886, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": {} + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "concat(get('data_source.12164.field_59764'),' miles')", + "format": "plain" + }, + { + "id": 106904, + "order": "9.00000000000000000000", + "type": "text", + "parent_element_id": 106886, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_color": "secondary" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'COLOR'", + "format": "plain" + }, + { + "id": 106905, + "order": "10.00000000000000000000", + "type": "text", + "parent_element_id": 106886, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": {} + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "concat(get('data_source.12164.field_59765'),' miles')", + "format": "plain" + }, + { + "id": 106906, + "order": "11.00000000000000000000", + "type": "text", + "parent_element_id": 106886, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_color": "secondary" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'ACCESSORIES'", + "format": "plain" + }, + { + "id": 106907, + "order": "12.00000000000000000000", + "type": "text", + "parent_element_id": 106886, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": {} + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "concat(get('data_source.12164.field_59769'),' miles')", + "format": "plain" + } + ], + "data_sources": [ + { + "id": 12164, + "name": "Car details", + "order": "1.00000000000000000000", + "service": { + "id": 15020, + "integration_id": 900, + "type": "local_baserow_get_row", + "table_id": 5697, + "view_id": 26465, + "search_query": "", + "filter_type": "AND", + "filters": [], + "row_id": "get('page_parameter.car_id')" + } + } + ], + "workflow_actions": [], + "visibility": "logged-in", + "role_type": "allow_all", + "roles": [] + }, + { + "id": 6678, + "name": "Car details sold", + "order": 11, + "path": "/car-details-sold/:car_id/:offer_id", + "path_params": [ + { + "name": "car_id", + "type": "numeric" + }, + { + "name": "offer_id", + "type": "numeric" + } + ], + "query_params": [], + "shared": false, + "elements": [ + { + "id": 106908, + "order": "0.50000000000000000000", + "type": "column", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "color", + "style_background_color": "#eae0d580", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "column_amount": 1, + "column_gap": 20, + "alignment": "top" + }, + { + "id": 106910, + "order": "0.50000000000000000000", + "type": "image", + "parent_element_id": 106909, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "image": { + "image_border_radius": 8 + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "image_source_type": "url", + "image_file_id": null, + "image_url": "get('data_source.12165.field_59761.*.url')", + "alt_text": "" + }, + { + "id": 106911, + "order": "0.50000000000000000000", + "type": "heading", + "parent_element_id": 106909, + "place_in_container": "1", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "heading_2_text_alignment": "left" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Sale details'", + "level": 2 + }, + { + "id": 106912, + "order": "1.00000000000000000000", + "type": "heading", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "concat(get('data_source.12165.field_59840.*.value'),' - ',get('data_source.12165.field_59762.*.value'))", + "level": 1 + }, + { + "id": 106913, + "order": "1.00000000000000000000", + "type": "text", + "parent_element_id": 106909, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_color": "secondary" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'YEAR'", + "format": "plain" + }, + { + "id": 106914, + "order": "1.00000000000000000000", + "type": "text", + "parent_element_id": 106909, + "place_in_container": "1", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_color": "secondary" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'DATE OFFER'", + "format": "plain" + }, + { + "id": 106915, + "order": "1.00000000000000000000", + "type": "text", + "parent_element_id": 106908, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_text_color": "primary", + "body_font_weight": "bold" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "concat('Congratulations with the purchase of the ',get('data_source.12165.field_59840.*.value'),' - ',get('data_source.12165.field_59762.*.value'),' (',get('data_source.12165.field_59841.*.value'),')')", + "format": "plain" + }, + { + "id": 106916, + "order": "1.50000000000000000000", + "type": "text", + "parent_element_id": 106909, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": {} + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "get('data_source.12165.field_59841.*.value')", + "format": "plain" + }, + { + "id": 106909, + "order": "2.00000000000000000000", + "type": "column", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "column_amount": 2, + "column_gap": 20, + "alignment": "top" + }, + { + "id": 106917, + "order": "2.00000000000000000000", + "type": "text", + "parent_element_id": 106908, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Please let us know how you like your new car and how the purchasing process went for you but adding a review.'", + "format": "plain" + }, + { + "id": 106918, + "order": "3.00000000000000000000", + "type": "text", + "parent_element_id": 106909, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_color": "secondary" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'TYPE'", + "format": "plain" + }, + { + "id": 106919, + "order": "3.00000000000000000000", + "type": "text", + "parent_element_id": 106909, + "place_in_container": "1", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": {} + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "get('data_source.12166.field_59783')", + "format": "plain" + }, + { + "id": 106920, + "order": "3.00000000000000000000", + "type": "link", + "parent_element_id": 106908, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "navigation_type": "page", + "navigate_to_page_id": 6679, + "page_parameters": [ + { + "name": "sale_id", + "value": "get('data_source.12166.id')" + }, + { + "name": "car_id", + "value": "get('data_source.12165.id')" + } + ], + "query_parameters": [], + "navigate_to_url": "", + "target": "self", + "value": "'Add a review'", + "variant": "link" + }, + { + "id": 106921, + "order": "4.00000000000000000000", + "type": "text", + "parent_element_id": 106909, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": {} + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "get('data_source.12165.field_59848.*.value.value')", + "format": "plain" + }, + { + "id": 106922, + "order": "4.00000000000000000000", + "type": "text", + "parent_element_id": 106909, + "place_in_container": "1", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_color": "secondary" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'DATE SOLD'", + "format": "plain" + }, + { + "id": 106923, + "order": "4.50000000000000000000", + "type": "text", + "parent_element_id": 106909, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_color": "secondary" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'DIMENSIONS'", + "format": "plain" + }, + { + "id": 106924, + "order": "4.50000000000000000000", + "type": "text", + "parent_element_id": 106909, + "place_in_container": "1", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": {} + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "get('data_source.12166.field_59782')", + "format": "plain" + }, + { + "id": 106925, + "order": "4.59999999999999964473", + "type": "text", + "parent_element_id": 106909, + "place_in_container": "1", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_color": "secondary" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'FINANCING'", + "format": "plain" + }, + { + "id": 106926, + "order": "4.62500000000000000000", + "type": "text", + "parent_element_id": 106909, + "place_in_container": "1", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": {} + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "get('data_source.12166.field_59789.*.value')", + "format": "plain" + }, + { + "id": 106927, + "order": "4.63636363636363668661", + "type": "text", + "parent_element_id": 106909, + "place_in_container": "1", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_color": "secondary" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'PRICE'", + "format": "plain" + }, + { + "id": 106928, + "order": "4.64285714285714323779", + "type": "text", + "parent_element_id": 106909, + "place_in_container": "1", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": {} + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "concat('$ ',get('data_source.12166.field_59784'))", + "format": "plain" + }, + { + "id": 106929, + "order": "4.64705882352941213043", + "type": "text", + "parent_element_id": 106909, + "place_in_container": "1", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_color": "secondary" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'SALESMAN'", + "format": "plain" + }, + { + "id": 106930, + "order": "4.65000000000000035527", + "type": "link", + "parent_element_id": 106909, + "place_in_container": "1", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "navigation_type": "custom", + "navigate_to_page_id": null, + "page_parameters": [], + "query_parameters": [], + "navigate_to_url": "concat('mailto:',get('data_source.12166.field_59853'))", + "target": "self", + "value": "get('data_source.12166.field_59786.0.value')", + "variant": "link" + }, + { + "id": 106931, + "order": "4.65217391304347849257", + "type": "text", + "parent_element_id": 106909, + "place_in_container": "1", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_color": "secondary" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'TRANSITION DOCUMENT'", + "format": "plain" + }, + { + "id": 106932, + "order": "4.65384615384615418776", + "type": "link", + "parent_element_id": 106909, + "place_in_container": "1", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "navigation_type": "custom", + "navigate_to_page_id": null, + "page_parameters": [], + "query_parameters": [], + "navigate_to_url": "get('data_source.12166.field_59787.0.url')", + "target": "blank", + "value": "get('data_source.12166.field_59787.0.visible_name')", + "variant": "link" + }, + { + "id": 106933, + "order": "4.66666666666666696273", + "type": "text", + "parent_element_id": 106909, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": {} + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "get('data_source.12165.field_59849')", + "format": "plain" + }, + { + "id": 106934, + "order": "4.66666666666666696273", + "type": "heading", + "parent_element_id": 106909, + "place_in_container": "1", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "heading_2_text_alignment": "left" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 31, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Full car details'", + "level": 2 + }, + { + "id": 106935, + "order": "4.75000000000000000000", + "type": "text", + "parent_element_id": 106909, + "place_in_container": "1", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_color": "secondary" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'PLATE NUMBER'", + "format": "plain" + }, + { + "id": 106936, + "order": "4.79999999999999982236", + "type": "text", + "parent_element_id": 106909, + "place_in_container": "1", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": {} + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "get('data_source.12165.field_59770')", + "format": "plain" + }, + { + "id": 106937, + "order": "4.83333333333333303727", + "type": "text", + "parent_element_id": 106909, + "place_in_container": "1", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_color": "secondary" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'VIN'", + "format": "plain" + }, + { + "id": 106938, + "order": "4.85714285714285676221", + "type": "text", + "parent_element_id": 106909, + "place_in_container": "1", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": {} + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "get('data_source.12165.field_59771')", + "format": "plain" + }, + { + "id": 106939, + "order": "4.87500000000000000000", + "type": "text", + "parent_element_id": 106909, + "place_in_container": "1", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_color": "secondary" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'ENGINE NUMBER'", + "format": "plain" + }, + { + "id": 106940, + "order": "5.00000000000000000000", + "type": "text", + "parent_element_id": 106909, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_color": "secondary" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'CONDITION'", + "format": "plain" + }, + { + "id": 106941, + "order": "5.33333333333333303727", + "type": "text", + "parent_element_id": 106909, + "place_in_container": "1", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": {} + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "get('data_source.12165.field_59777')", + "format": "plain" + }, + { + "id": 106942, + "order": "5.40000000000000035527", + "type": "text", + "parent_element_id": 106909, + "place_in_container": "1", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_color": "secondary" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'CERTIFICATE'", + "format": "plain" + }, + { + "id": 106943, + "order": "5.41666666666666696273", + "type": "link", + "parent_element_id": 106909, + "place_in_container": "1", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "navigation_type": "custom", + "navigate_to_page_id": null, + "page_parameters": [], + "query_parameters": [], + "navigate_to_url": "get('data_source.12165.field_59772.0.url')", + "target": "blank", + "value": "get('data_source.12165.field_59772.0.visible_name')", + "variant": "link" + }, + { + "id": 106944, + "order": "6.00000000000000000000", + "type": "text", + "parent_element_id": 106909, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": {} + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "get('data_source.12165.field_59763.value')", + "format": "plain" + }, + { + "id": 106945, + "order": "6.33333333333333303727", + "type": "text", + "parent_element_id": 106909, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_color": "secondary" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'DATE ACQUIRED'", + "format": "plain" + }, + { + "id": 106946, + "order": "6.40000000000000035527", + "type": "text", + "parent_element_id": 106909, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": {} + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "get('data_source.12165.field_59773')", + "format": "plain" + }, + { + "id": 106947, + "order": "6.50000000000000000000", + "type": "text", + "parent_element_id": 106909, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_color": "secondary" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'AVAILABLE AT'", + "format": "plain" + }, + { + "id": 106948, + "order": "6.66666666666666696273", + "type": "text", + "parent_element_id": 106909, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": {} + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "concat(get('data_source.12165.field_59775.*.value'),' branch')", + "format": "plain" + }, + { + "id": 106949, + "order": "7.00000000000000000000", + "type": "text", + "parent_element_id": 106909, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_color": "secondary" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'MILAGE'", + "format": "plain" + }, + { + "id": 106950, + "order": "8.00000000000000000000", + "type": "text", + "parent_element_id": 106909, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": {} + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "concat(get('data_source.12165.field_59764'),' miles')", + "format": "plain" + }, + { + "id": 106951, + "order": "9.00000000000000000000", + "type": "text", + "parent_element_id": 106909, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_color": "secondary" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'COLOR'", + "format": "plain" + }, + { + "id": 106952, + "order": "10.00000000000000000000", + "type": "text", + "parent_element_id": 106909, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": {} + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "concat(get('data_source.12165.field_59765'),' miles')", + "format": "plain" + }, + { + "id": 106953, + "order": "11.00000000000000000000", + "type": "text", + "parent_element_id": 106909, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_color": "secondary" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'ACCESSORIES'", + "format": "plain" + }, + { + "id": 106954, + "order": "12.00000000000000000000", + "type": "text", + "parent_element_id": 106909, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": {} + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "concat(get('data_source.12165.field_59769'),' miles')", + "format": "plain" + } + ], + "data_sources": [ + { + "id": 12165, + "name": "Car details", + "order": "1.00000000000000000000", + "service": { + "id": 15021, + "integration_id": 900, + "type": "local_baserow_get_row", + "table_id": 5697, + "view_id": 26465, + "search_query": "", + "filter_type": "AND", + "filters": [], + "row_id": "get('page_parameter.car_id')" + } + }, + { + "id": 12166, + "name": "Offer details", + "order": "2.00000000000000000000", + "service": { + "id": 15022, + "integration_id": 900, + "type": "local_baserow_get_row", + "table_id": 5698, + "view_id": 26478, + "search_query": "", + "filter_type": "AND", + "filters": [], + "row_id": "get('page_parameter.offer_id')" + } + } + ], + "workflow_actions": [], + "visibility": "logged-in", + "role_type": "allow_all", + "roles": [] + }, + { + "id": 6679, + "name": "Add review", + "order": 12, + "path": "/review/:sale_id/:car_id", + "path_params": [ + { + "name": "sale_id", + "type": "numeric" + }, + { + "name": "car_id", + "type": "numeric" + } + ], + "query_params": [], + "shared": false, + "elements": [ + { + "id": 106956, + "order": "1.00000000000000000000", + "type": "input_text", + "parent_element_id": 106955, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "label": "'TITLE'", + "required": true, + "validation_type": "any", + "placeholder": "", + "default_value": "", + "is_multiline": false, + "rows": 3, + "input_type": "text" + }, + { + "id": 106959, + "order": "1.00000000000000000000", + "type": "heading", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Leave us a review'", + "level": 1 + }, + { + "id": 106960, + "order": "1.50000000000000000000", + "type": "heading", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "concat('Sale: ',get('data_source.12168.field_59863.*.value'),' - ',get('data_source.12168.field_59850'),' (',get('data_source.12168.field_59864.*.value'),')')", + "level": 2 + }, + { + "id": 106955, + "order": "2.00000000000000000000", + "type": "form_container", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "button": { + "button_alignment": "center", + "button_horizontal_padding": 36 + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 20, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 20, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 40, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 40, + "style_margin_right": 0, + "style_background_radius": 8, + "style_border_radius": 0, + "style_background": "color", + "style_background_color": "#eae0d580", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "small", + "style_width_child": "normal", + "submit_button_label": "'Add your review'", + "reset_initial_values_post_submission": false + }, + { + "id": 106957, + "order": "4.00000000000000000000", + "type": "input_text", + "parent_element_id": 106955, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "label": "'YOUR REVIEW'", + "required": true, + "validation_type": "any", + "placeholder": "", + "default_value": "", + "is_multiline": true, + "rows": 5, + "input_type": "password" + }, + { + "id": 106958, + "order": "5.00000000000000000000", + "type": "choice", + "parent_element_id": 106955, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "label": "'YOUR RATING'", + "required": true, + "placeholder": "", + "default_value": "", + "options": [], + "multiple": false, + "show_as_dropdown": true, + "option_type": "formulas", + "formula_value": "get('data_source_context.12167.field_59823.*.id')", + "formula_name": "get('data_source_context.12167.field_59823.*.value')" + } + ], + "data_sources": [ + { + "id": 12167, + "name": "Reviews", + "order": "1.00000000000000000000", + "service": { + "id": 15023, + "integration_id": 900, + "type": "local_baserow_list_rows", + "table_id": 5702, + "view_id": 26501, + "sortings": [], + "search_query": "", + "filter_type": "AND", + "filters": [] + } + }, + { + "id": 12168, + "name": "Get sale details", + "order": "2.00000000000000000000", + "service": { + "id": 15024, + "integration_id": 900, + "type": "local_baserow_get_row", + "table_id": 5698, + "view_id": 26478, + "search_query": "", + "filter_type": "AND", + "filters": [], + "row_id": "get('page_parameter.sale_id')" + } + } + ], + "workflow_actions": [ + { + "id": 13960, + "type": "create_row", + "order": 1, + "page_id": 6679, + "element_id": 106955, + "event": "submit", + "service": { + "id": 15029, + "integration_id": 900, + "type": "local_baserow_upsert_row", + "table_id": 5702, + "row_id": "", + "field_mappings": [ + { + "field_id": 59821, + "value": "get('form_data.106956')", + "enabled": true + }, + { + "field_id": 59822, + "value": "get('form_data.106957')", + "enabled": true + }, + { + "field_id": 59823, + "value": "get('form_data.106958')", + "enabled": true + }, + { + "field_id": 59824, + "value": "get('data_source.12168.id')", + "enabled": true + }, + { + "field_id": 59826, + "value": "get('page_parameter.car_id')", + "enabled": true + } + ] + } + }, + { + "id": 13961, + "type": "open_page", + "order": 2, + "page_id": 6679, + "element_id": 106955, + "event": "submit", + "navigation_type": "page", + "navigate_to_page_id": 6670, + "page_parameters": [], + "query_parameters": [], + "navigate_to_url": "", + "target": "self" + } + ], + "visibility": "logged-in", + "role_type": "allow_all", + "roles": [] + } + ], + "integrations": [ + { + "id": 900, + "name": "Local Baserow", + "order": "1.00000000000000000000", + "type": "local_baserow", + "authorized_user": null + } + ], + "theme": { + "primary_color": "#1e3a8a", + "secondary_color": "#007acc", + "border_color": "#eae0d5", + "main_success_color": "#12D452", + "main_warning_color": "#FCC74A", + "main_error_color": "#FF5A4A", + "custom_colors": [], + "body_font_family": "tahoma", + "body_font_size": 14, + "body_font_weight": "regular", + "body_text_color": "#070810ff", + "body_text_alignment": "left", + "heading_1_font_family": "trebuchet_ms", + "heading_1_font_size": 24, + "heading_1_font_weight": "bold", + "heading_1_text_color": "#070810ff", + "heading_1_text_alignment": "left", + "heading_2_font_family": "trebuchet_ms", + "heading_2_font_size": 20, + "heading_2_font_weight": "bold", + "heading_2_text_color": "secondary", + "heading_2_text_alignment": "center", + "heading_3_font_family": "trebuchet_ms", + "heading_3_font_size": 16, + "heading_3_font_weight": "regular", + "heading_3_text_color": "#070810ff", + "heading_3_text_alignment": "left", + "heading_4_font_family": "trebuchet_ms", + "heading_4_font_size": 16, + "heading_4_font_weight": "regular", + "heading_4_text_color": "#070810ff", + "heading_4_text_alignment": "left", + "heading_5_font_family": "trebuchet_ms", + "heading_5_font_size": 14, + "heading_5_font_weight": "regular", + "heading_5_text_color": "#070810ff", + "heading_5_text_alignment": "left", + "heading_6_font_family": "trebuchet_ms", + "heading_6_font_size": 14, + "heading_6_font_weight": "regular", + "heading_6_text_color": "#202128", + "heading_6_text_alignment": "left", + "button_font_family": "inter", + "button_font_size": 13, + "button_font_weight": "regular", + "button_alignment": "left", + "button_text_alignment": "center", + "button_width": "auto", + "button_background_color": "transparent", + "button_text_color": "primary", + "button_border_color": "primary", + "button_border_size": 2, + "button_border_radius": 8, + "button_vertical_padding": 12, + "button_horizontal_padding": 12, + "button_hover_background_color": "primary", + "button_hover_text_color": "#ffffff", + "button_hover_border_color": "transparent", + "link_font_family": "inter", + "link_font_size": 13, + "link_font_weight": "regular", + "link_text_alignment": "left", + "link_text_color": "primary", + "link_hover_text_color": "#96baf6ff", + "image_alignment": "left", + "image_max_width": 100, + "image_max_height": null, + "image_border_radius": 0, + "image_constraint": "contain", + "page_background_color": "#fafafa", + "page_background_file_id": null, + "page_background_mode": "tile", + "label_font_family": "tahoma", + "label_text_color": "secondary", + "label_font_size": 12, + "label_font_weight": "regular", + "input_font_family": "inter", + "input_font_size": 13, + "input_font_weight": "regular", + "input_text_color": "#070810FF", + "input_background_color": "#FFFFFFFF", + "input_border_color": "primary", + "input_border_size": 1, + "input_border_radius": 4, + "input_vertical_padding": 8, + "input_horizontal_padding": 12, + "table_border_color": "border", + "table_border_size": 0, + "table_border_radius": 8, + "table_header_background_color": "secondary", + "table_header_text_color": "#ffffff", + "table_header_font_size": 13, + "table_header_font_weight": "semi-bold", + "table_header_font_family": "inter", + "table_header_text_alignment": "left", + "table_cell_background_color": "#ffffffff", + "table_cell_alternate_background_color": "#ffffffff", + "table_cell_alignment": "left", + "table_cell_vertical_padding": 10, + "table_cell_horizontal_padding": 20, + "table_vertical_separator_color": "border", + "table_vertical_separator_size": 0, + "table_horizontal_separator_color": "border", + "table_horizontal_separator_size": 1 + }, + "user_sources": [ + { + "id": 672, + "name": "Cusomers", + "order": "1.00000000000000000000", + "type": "local_baserow", + "uid": "4d098b09242b467690f5aeceff2c329d", + "integration_id": 900, + "auth_providers": [ + { + "id": 675, + "type": "local_baserow_password", + "domain": null, + "enabled": true, + "password_field_id": 59820 + } + ], + "table_id": 5701, + "email_field_id": 59817, + "name_field_id": 59811, + "role_field_id": null + } + ], + "favicon_file": null, + "login_page": { + "id": 6669, + "name": "Login", + "order": 2, + "path": "/login", + "path_params": [], + "query_params": [], + "shared": false, + "elements": [ + { + "id": 106751, + "order": "0.50000000000000000000", + "type": "heading", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Drive into your account'", + "level": 1 + }, + { + "id": 106752, + "order": "0.66666666666666662966", + "type": "text", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Get in touch with our customer services to set up your account if you do not already have one. This step is required since we want all offers and reviews to come from genuine buyers.'", + "format": "plain" + }, + { + "id": 106753, + "order": "0.75000000000000000000", + "type": "link", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "navigation_type": "page", + "navigate_to_page_id": 6671, + "page_parameters": [], + "query_parameters": [], + "navigate_to_url": "", + "target": "self", + "value": "'\u2709\ufe0f Contact us'", + "variant": "link" + }, + { + "id": 106754, + "order": "1.00000000000000000000", + "type": "auth_form", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "input": {}, + "login_button": { + "button_alignment": "center", + "button_horizontal_padding": 36 + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 150, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 150, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 100, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 100, + "style_margin_right": 0, + "style_background_radius": 8, + "style_border_radius": 0, + "style_background": "color", + "style_background_color": "#eae0d580", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "small", + "style_width_child": "normal", + "user_source_id": 672, + "login_button_label": "'Sign in'" + } + ], + "data_sources": [], + "workflow_actions": [ + { + "id": 13949, + "type": "open_page", + "order": 1, + "page_id": 6669, + "element_id": 106754, + "event": "after_login", + "navigation_type": "page", + "navigate_to_page_id": 6673, + "page_parameters": [], + "query_parameters": [ + { + "name": "model", + "value": "" + }, + { + "name": "condition", + "value": "" + }, + { + "name": "max_price", + "value": "get('data_source.12170.result')" + }, + { + "name": "milage", + "value": "get('data_source.12171.result')" + } + ], + "navigate_to_url": "", + "target": "self" + } + ], + "visibility": "all", + "role_type": "allow_all", + "roles": [] + }, + "id": 2170, + "name": "Car Dealership Web Application", + "order": 2, + "type": "builder" } ] } \ No newline at end of file diff --git a/backend/templates/car-dealership-inventory.zip b/backend/templates/car-dealership-inventory.zip index f9b92a9b7..e8657b356 100644 Binary files a/backend/templates/car-dealership-inventory.zip and b/backend/templates/car-dealership-inventory.zip differ diff --git a/backend/templates/formulas.json b/backend/templates/formulas.json new file mode 100644 index 000000000..5a335929d --- /dev/null +++ b/backend/templates/formulas.json @@ -0,0 +1,18179 @@ +{ + "baserow_template_version": 1, + "name": "Formula demo", + "icon": "iconoir-sigma-function", + "keywords": [ + "All", + "Formulas", + "Formula", + "Functions", + "Baserow" + ], + "categories": [ + "Baserow" + ], + "export": [ + { + "id": 2157, + "name": "Case 1 - Task Management", + "order": 1, + "type": "database", + "tables": [ + { + "id": 5672, + "name": "Tasks", + "order": 2, + "fields": [ + { + "id": 59500, + "type": "formula", + "name": "Name", + "description": null, + "order": 0, + "primary": true, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "duration_format": null, + "date_include_time": null, + "date_show_tzinfo": null, + "number_prefix": "", + "array_formula_type": null, + "nullable": false, + "date_format": null, + "date_time_format": null, + "date_force_timezone": null, + "number_suffix": "", + "number_separator": "", + "error": null, + "number_decimal_places": null, + "formula": "concat(field('Title'),'-',row_id())", + "formula_type": "text" + }, + { + "id": 59495, + "type": "single_select", + "name": "Category", + "description": null, + "order": 1, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "select_options": [ + { + "id": 20953, + "value": "Operations", + "color": "darker-gray", + "order": 0 + }, + { + "id": 20954, + "value": "Management", + "color": "dark-brown", + "order": 1 + }, + { + "id": 20955, + "value": "Marketing", + "color": "light-cyan", + "order": 2 + }, + { + "id": 20956, + "value": "Finance", + "color": "darker-yellow", + "order": 3 + }, + { + "id": 20957, + "value": "Human Resources", + "color": "light-yellow", + "order": 4 + } + ] + }, + { + "id": 59496, + "type": "text", + "name": "Description", + "description": null, + "order": 2, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "text_default": "" + }, + { + "id": 59497, + "type": "text", + "name": "Title", + "description": null, + "order": 3, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "text_default": "" + }, + { + "id": 59498, + "type": "formula", + "name": "Name - 1", + "description": null, + "order": 4, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "duration_format": null, + "date_include_time": null, + "date_show_tzinfo": null, + "number_prefix": "", + "array_formula_type": null, + "nullable": false, + "date_format": null, + "date_time_format": null, + "date_force_timezone": null, + "number_suffix": "", + "number_separator": "", + "error": null, + "number_decimal_places": 0, + "formula": "row_id()", + "formula_type": "number" + }, + { + "id": 59501, + "type": "formula", + "name": "Name - 2", + "description": null, + "order": 5, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "duration_format": null, + "date_include_time": null, + "date_show_tzinfo": null, + "number_prefix": "", + "array_formula_type": null, + "nullable": false, + "date_format": null, + "date_time_format": null, + "date_force_timezone": null, + "number_suffix": "", + "number_separator": "", + "error": null, + "number_decimal_places": null, + "formula": "concat(field('Title'),'-',row_id())", + "formula_type": "text" + }, + { + "id": 59502, + "type": "formula", + "name": "Name - 3", + "description": null, + "order": 6, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "duration_format": null, + "date_include_time": null, + "date_show_tzinfo": null, + "number_prefix": "", + "array_formula_type": null, + "nullable": false, + "date_format": null, + "date_time_format": null, + "date_force_timezone": null, + "number_suffix": "", + "number_separator": "", + "error": null, + "number_decimal_places": null, + "formula": "concat(left(upper(totext(field('Category'))),3),'-',row_id())", + "formula_type": "text" + }, + { + "id": 59503, + "type": "formula", + "name": "Name - 4", + "description": null, + "order": 7, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "duration_format": null, + "date_include_time": null, + "date_show_tzinfo": null, + "number_prefix": "", + "array_formula_type": null, + "nullable": false, + "date_format": null, + "date_time_format": null, + "date_force_timezone": null, + "number_suffix": "", + "number_separator": "", + "error": null, + "number_decimal_places": null, + "formula": "concat(left(upper(totext(field('Category'))),3),'-',year(field('Created on')),'-',row_id())", + "formula_type": "text" + }, + { + "id": 59499, + "type": "created_on", + "name": "Created on", + "description": null, + "order": 8, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "date_format": "ISO", + "date_include_time": false, + "date_time_format": "24", + "date_show_tzinfo": false, + "date_force_timezone": null + } + ], + "views": [ + { + "id": 26404, + "type": "grid", + "name": "All tasks", + "order": 1, + "ownership_type": "collaborative", + "owned_by": "frederik@baserow.io", + "filter_type": "AND", + "filters_disabled": false, + "filters": [], + "filter_groups": [], + "sortings": [], + "group_bys": [], + "decorations": [], + "public": false, + "row_identifier_type": "id", + "row_height_size": "medium", + "field_options": [ + { + "id": 260727, + "field_id": 59500, + "width": 200, + "hidden": false, + "order": 0, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260728, + "field_id": 59498, + "width": 126, + "hidden": false, + "order": 1, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260729, + "field_id": 59501, + "width": 188, + "hidden": false, + "order": 2, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260730, + "field_id": 59502, + "width": 200, + "hidden": false, + "order": 3, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260731, + "field_id": 59503, + "width": 200, + "hidden": false, + "order": 4, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260732, + "field_id": 59497, + "width": 171, + "hidden": false, + "order": 7, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260733, + "field_id": 59495, + "width": 140, + "hidden": false, + "order": 8, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260734, + "field_id": 59496, + "width": 554, + "hidden": false, + "order": 9, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260735, + "field_id": 59499, + "width": 200, + "hidden": false, + "order": 10, + "aggregation_type": "", + "aggregation_raw_type": "" + } + ] + } + ], + "rows": [ + { + "id": 1, + "order": "1.00000000000000000000", + "created_on": "2025-02-05T07:48:00.081133+00:00", + "updated_on": "2025-02-05T07:57:28.506186+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59500": null, + "field_59495": 20957, + "field_59496": "Conduct onboarding for a new hire, including setting up payroll in the HR system, scheduling a welcome meeting with the team, providing access to company tools, and assigning required training materials.", + "field_59497": "Employee Onboarding", + "field_59498": null, + "field_59501": null, + "field_59502": null, + "field_59503": null, + "field_59499": null + }, + { + "id": 2, + "order": "2.00000000000000000000", + "created_on": "2025-02-05T07:48:00.081208+00:00", + "updated_on": "2025-02-05T07:57:28.506260+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59500": null, + "field_59495": 20956, + "field_59496": "Process and approve five supplier invoices by verifying amounts, ensuring correct account allocation, obtaining necessary approvals, and scheduling payment in the financial system.", + "field_59497": "Invoice Processing", + "field_59498": null, + "field_59501": null, + "field_59502": null, + "field_59503": null, + "field_59499": null + }, + { + "id": 3, + "order": "3.00000000000000000000", + "created_on": "2025-02-05T07:48:00.081236+00:00", + "updated_on": "2025-02-05T07:57:28.506285+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59500": null, + "field_59495": 20955, + "field_59496": "Write, design, and schedule three social media posts promoting the company\u2019s latest product update, ensuring alignment with brand guidelines and marketing strategy.", + "field_59497": "Social Media Posts", + "field_59498": null, + "field_59501": null, + "field_59502": null, + "field_59503": null, + "field_59499": null + }, + { + "id": 4, + "order": "4.00000000000000000000", + "created_on": "2025-02-05T07:48:00.081262+00:00", + "updated_on": "2025-02-05T07:57:28.506305+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59500": null, + "field_59495": 20953, + "field_59496": "Resolve 15 customer support tickets by diagnosing issues, providing solutions, updating ticket statuses, and following up to ensure customer satisfaction.", + "field_59497": "Customer Ticketing", + "field_59498": null, + "field_59501": null, + "field_59502": null, + "field_59503": null, + "field_59499": null + }, + { + "id": 5, + "order": "5.00000000000000000000", + "created_on": "2025-02-05T07:48:00.081289+00:00", + "updated_on": "2025-02-05T07:57:28.506345+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59500": null, + "field_59495": 20954, + "field_59496": "Break down an upcoming project into five key tasks, assign them to team members, set deadlines in the project management system, and communicate expectations to stakeholders.", + "field_59497": "Task Assignment", + "field_59498": null, + "field_59501": null, + "field_59502": null, + "field_59503": null, + "field_59499": null + }, + { + "id": 6, + "order": "6.00000000000000000000", + "created_on": "2025-02-05T07:48:00.081315+00:00", + "updated_on": "2025-02-05T07:57:28.506363+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59500": null, + "field_59495": 20953, + "field_59496": "Install security patches and update software on all employee workstations, ensuring compatibility, testing functionality, and documenting changes for compliance.", + "field_59497": "System Updates", + "field_59498": null, + "field_59501": null, + "field_59502": null, + "field_59503": null, + "field_59499": null + }, + { + "id": 7, + "order": "7.00000000000000000000", + "created_on": "2025-02-05T07:48:00.081340+00:00", + "updated_on": "2025-02-05T07:57:28.506391+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59500": null, + "field_59495": 20953, + "field_59496": "Conduct a physical inventory count of all high-value products, compare results with digital records, report discrepancies, and update the inventory management system.", + "field_59497": "Inventory Check", + "field_59498": null, + "field_59501": null, + "field_59502": null, + "field_59503": null, + "field_59499": null + }, + { + "id": 8, + "order": "8.00000000000000000000", + "created_on": "2025-02-05T07:48:00.081365+00:00", + "updated_on": "2025-02-05T07:57:28.506408+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59500": null, + "field_59495": 20955, + "field_59496": "Follow up with five potential clients via email or phone, answer questions, provide additional information, and schedule meetings to move them through the sales pipeline.", + "field_59497": "Client Follow-Up", + "field_59498": null, + "field_59501": null, + "field_59502": null, + "field_59503": null, + "field_59499": null + }, + { + "id": 9, + "order": "9.00000000000000000000", + "created_on": "2025-02-05T07:48:00.081389+00:00", + "updated_on": "2025-02-05T07:57:28.506428+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59500": null, + "field_59495": 20954, + "field_59496": "Review and update one company policy by assessing current regulations, identifying gaps, revising wording, obtaining approval, and publishing the final version.", + "field_59497": "Policy Review", + "field_59498": null, + "field_59501": null, + "field_59502": null, + "field_59503": null, + "field_59499": null + }, + { + "id": 10, + "order": "10.00000000000000000000", + "created_on": "2025-02-05T07:48:00.081413+00:00", + "updated_on": "2025-02-05T07:57:28.506445+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59500": null, + "field_59495": 20954, + "field_59496": "Conduct one-on-one performance reviews with three employees, discuss achievements and challenges, document feedback, and outline action steps for improvement.", + "field_59497": "Performance Reviews", + "field_59498": null, + "field_59501": null, + "field_59502": null, + "field_59503": null, + "field_59499": null + } + ], + "data_sync": null + } + ] + }, + { + "id": 2158, + "name": "Case 2 - Task Management", + "order": 2, + "type": "database", + "tables": [ + { + "id": 5673, + "name": "Tasks", + "order": 2, + "fields": [ + { + "id": 59509, + "type": "formula", + "name": "Name", + "description": null, + "order": 10, + "primary": true, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "duration_format": null, + "date_include_time": null, + "date_show_tzinfo": null, + "number_prefix": "", + "array_formula_type": null, + "nullable": false, + "date_format": null, + "date_time_format": null, + "date_force_timezone": null, + "number_suffix": "", + "number_separator": "", + "error": null, + "number_decimal_places": null, + "formula": "concat(left(upper(totext(field('Category'))),3),'-',year(field('Created on')),'-',field('ID'))", + "formula_type": "text" + }, + { + "id": 59504, + "type": "single_select", + "name": "Category", + "description": null, + "order": 1, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "select_options": [ + { + "id": 20958, + "value": "Operations", + "color": "darker-gray", + "order": 0 + }, + { + "id": 20959, + "value": "Management", + "color": "dark-brown", + "order": 1 + }, + { + "id": 20960, + "value": "Marketing", + "color": "light-cyan", + "order": 2 + }, + { + "id": 20961, + "value": "Finance", + "color": "darker-yellow", + "order": 3 + }, + { + "id": 20962, + "value": "Human Resources", + "color": "light-yellow", + "order": 4 + } + ] + }, + { + "id": 59505, + "type": "text", + "name": "Description", + "description": null, + "order": 2, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "text_default": "" + }, + { + "id": 59506, + "type": "text", + "name": "Title", + "description": null, + "order": 3, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "text_default": "" + }, + { + "id": 59507, + "type": "created_on", + "name": "Created on", + "description": null, + "order": 8, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "date_format": "ISO", + "date_include_time": false, + "date_time_format": "24", + "date_show_tzinfo": false, + "date_force_timezone": null + }, + { + "id": 59508, + "type": "formula", + "name": "ID", + "description": null, + "order": 9, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "duration_format": null, + "date_include_time": null, + "date_show_tzinfo": null, + "number_prefix": "", + "array_formula_type": null, + "nullable": false, + "date_format": null, + "date_time_format": null, + "date_force_timezone": null, + "number_suffix": "", + "number_separator": "", + "error": null, + "number_decimal_places": null, + "formula": "if(row_id() < 10,concat('0000',row_id()),if(row_id() < 100,concat('000',row_id()),if(row_id() < 1000,concat('00',row_id()),if(row_id() < 10000,concat('0',row_id()),row_id()))))", + "formula_type": "text" + } + ], + "views": [ + { + "id": 26405, + "type": "grid", + "name": "All tasks", + "order": 1, + "ownership_type": "collaborative", + "owned_by": "frederik@baserow.io", + "filter_type": "AND", + "filters_disabled": false, + "filters": [], + "filter_groups": [], + "sortings": [], + "group_bys": [], + "decorations": [], + "public": false, + "row_identifier_type": "id", + "row_height_size": "medium", + "field_options": [ + { + "id": 260736, + "field_id": 59509, + "width": 200, + "hidden": false, + "order": 5, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260737, + "field_id": 59508, + "width": 200, + "hidden": false, + "order": 6, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260738, + "field_id": 59506, + "width": 171, + "hidden": false, + "order": 7, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260739, + "field_id": 59504, + "width": 140, + "hidden": false, + "order": 8, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260740, + "field_id": 59505, + "width": 554, + "hidden": false, + "order": 9, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260741, + "field_id": 59507, + "width": 200, + "hidden": false, + "order": 10, + "aggregation_type": "", + "aggregation_raw_type": "" + } + ] + } + ], + "rows": [ + { + "id": 1, + "order": "1.00000000000000000000", + "created_on": "2025-02-05T07:48:00.081133+00:00", + "updated_on": "2025-02-05T07:57:28.506186+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59509": null, + "field_59504": 20962, + "field_59505": "Conduct onboarding for a new hire, including setting up payroll in the HR system, scheduling a welcome meeting with the team, providing access to company tools, and assigning required training materials.", + "field_59506": "Employee Onboarding", + "field_59507": null, + "field_59508": null + }, + { + "id": 2, + "order": "2.00000000000000000000", + "created_on": "2025-02-05T07:48:00.081208+00:00", + "updated_on": "2025-02-05T07:57:28.506260+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59509": null, + "field_59504": 20961, + "field_59505": "Process and approve five supplier invoices by verifying amounts, ensuring correct account allocation, obtaining necessary approvals, and scheduling payment in the financial system.", + "field_59506": "Invoice Processing", + "field_59507": null, + "field_59508": null + }, + { + "id": 3, + "order": "3.00000000000000000000", + "created_on": "2025-02-05T07:48:00.081236+00:00", + "updated_on": "2025-02-05T07:57:28.506285+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59509": null, + "field_59504": 20960, + "field_59505": "Write, design, and schedule three social media posts promoting the company\u2019s latest product update, ensuring alignment with brand guidelines and marketing strategy.", + "field_59506": "Social Media Posts", + "field_59507": null, + "field_59508": null + }, + { + "id": 4, + "order": "4.00000000000000000000", + "created_on": "2025-02-05T07:48:00.081262+00:00", + "updated_on": "2025-02-05T07:57:28.506305+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59509": null, + "field_59504": 20958, + "field_59505": "Resolve 15 customer support tickets by diagnosing issues, providing solutions, updating ticket statuses, and following up to ensure customer satisfaction.", + "field_59506": "Customer Ticketing", + "field_59507": null, + "field_59508": null + }, + { + "id": 5, + "order": "5.00000000000000000000", + "created_on": "2025-02-05T07:48:00.081289+00:00", + "updated_on": "2025-02-05T07:57:28.506345+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59509": null, + "field_59504": 20959, + "field_59505": "Break down an upcoming project into five key tasks, assign them to team members, set deadlines in the project management system, and communicate expectations to stakeholders.", + "field_59506": "Task Assignment", + "field_59507": null, + "field_59508": null + }, + { + "id": 6, + "order": "6.00000000000000000000", + "created_on": "2025-02-05T07:48:00.081315+00:00", + "updated_on": "2025-02-05T07:57:28.506363+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59509": null, + "field_59504": 20958, + "field_59505": "Install security patches and update software on all employee workstations, ensuring compatibility, testing functionality, and documenting changes for compliance.", + "field_59506": "System Updates", + "field_59507": null, + "field_59508": null + }, + { + "id": 7, + "order": "7.00000000000000000000", + "created_on": "2025-02-05T07:48:00.081340+00:00", + "updated_on": "2025-02-05T07:57:28.506391+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59509": null, + "field_59504": 20958, + "field_59505": "Conduct a physical inventory count of all high-value products, compare results with digital records, report discrepancies, and update the inventory management system.", + "field_59506": "Inventory Check", + "field_59507": null, + "field_59508": null + }, + { + "id": 8, + "order": "8.00000000000000000000", + "created_on": "2025-02-05T07:48:00.081365+00:00", + "updated_on": "2025-02-05T07:57:28.506408+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59509": null, + "field_59504": 20960, + "field_59505": "Follow up with five potential clients via email or phone, answer questions, provide additional information, and schedule meetings to move them through the sales pipeline.", + "field_59506": "Client Follow-Up", + "field_59507": null, + "field_59508": null + }, + { + "id": 9, + "order": "9.00000000000000000000", + "created_on": "2025-02-05T07:48:00.081389+00:00", + "updated_on": "2025-02-05T07:57:28.506428+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59509": null, + "field_59504": 20959, + "field_59505": "Review and update one company policy by assessing current regulations, identifying gaps, revising wording, obtaining approval, and publishing the final version.", + "field_59506": "Policy Review", + "field_59507": null, + "field_59508": null + }, + { + "id": 10, + "order": "10.00000000000000000000", + "created_on": "2025-02-05T07:48:00.081413+00:00", + "updated_on": "2025-02-05T07:57:28.506445+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59509": null, + "field_59504": 20959, + "field_59505": "Conduct one-on-one performance reviews with three employees, discuss achievements and challenges, document feedback, and outline action steps for improvement.", + "field_59506": "Performance Reviews", + "field_59507": null, + "field_59508": null + } + ], + "data_sync": null + } + ] + }, + { + "id": 2159, + "name": "Case 3 - Task Management", + "order": 3, + "type": "database", + "tables": [ + { + "id": 5674, + "name": "Tasks", + "order": 2, + "fields": [ + { + "id": 59517, + "type": "formula", + "name": "Name", + "description": null, + "order": 10, + "primary": true, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "duration_format": null, + "date_include_time": null, + "date_show_tzinfo": null, + "number_prefix": "", + "array_formula_type": null, + "nullable": false, + "date_format": null, + "date_time_format": null, + "date_force_timezone": null, + "number_suffix": "", + "number_separator": "", + "error": null, + "number_decimal_places": null, + "formula": "concat(left(upper(totext(field('Category'))),3),'-',year(field('Created on')),'-',field('ID'))", + "formula_type": "text" + }, + { + "id": 59510, + "type": "single_select", + "name": "Category", + "description": null, + "order": 1, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "select_options": [ + { + "id": 20963, + "value": "Operations", + "color": "darker-gray", + "order": 0 + }, + { + "id": 20964, + "value": "Management", + "color": "dark-brown", + "order": 1 + }, + { + "id": 20965, + "value": "Marketing", + "color": "light-cyan", + "order": 2 + }, + { + "id": 20966, + "value": "Finance", + "color": "darker-yellow", + "order": 3 + }, + { + "id": 20967, + "value": "Human Resources", + "color": "light-yellow", + "order": 4 + } + ] + }, + { + "id": 59511, + "type": "text", + "name": "Description", + "description": null, + "order": 2, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "text_default": "" + }, + { + "id": 59512, + "type": "text", + "name": "Title", + "description": null, + "order": 3, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "text_default": "" + }, + { + "id": 59513, + "type": "created_on", + "name": "Created on", + "description": null, + "order": 8, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "date_format": "ISO", + "date_include_time": false, + "date_time_format": "24", + "date_show_tzinfo": false, + "date_force_timezone": null + }, + { + "id": 59514, + "type": "formula", + "name": "ID", + "description": null, + "order": 9, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "duration_format": null, + "date_include_time": null, + "date_show_tzinfo": null, + "number_prefix": "", + "array_formula_type": null, + "nullable": false, + "date_format": null, + "date_time_format": null, + "date_force_timezone": null, + "number_suffix": "", + "number_separator": "", + "error": null, + "number_decimal_places": null, + "formula": "if(row_id() < 10,concat('0000',row_id()),if(row_id() < 100,concat('000',row_id()),if(row_id() < 1000,concat('00',row_id()),if(row_id() < 10000,concat('0',row_id()),row_id()))))", + "formula_type": "text" + }, + { + "id": 59515, + "type": "single_select", + "name": "Importance", + "description": null, + "order": 11, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "select_options": [ + { + "id": 20968, + "value": "Low", + "color": "cyan", + "order": 0 + }, + { + "id": 20969, + "value": "Medium", + "color": "blue", + "order": 1 + }, + { + "id": 20970, + "value": "High", + "color": "red", + "order": 2 + } + ] + }, + { + "id": 59516, + "type": "date", + "name": "Deadline", + "description": null, + "order": 12, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "date_format": "ISO", + "date_include_time": false, + "date_time_format": "24", + "date_show_tzinfo": false, + "date_force_timezone": null + }, + { + "id": 59518, + "type": "formula", + "name": "Is urgent", + "description": null, + "order": 13, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "duration_format": null, + "date_include_time": null, + "date_show_tzinfo": null, + "number_prefix": "", + "array_formula_type": null, + "nullable": false, + "date_format": null, + "date_time_format": null, + "date_force_timezone": null, + "number_suffix": "", + "number_separator": "", + "error": null, + "number_decimal_places": null, + "formula": "field('Deadline') < today() + date_interval('3 days')", + "formula_type": "boolean" + }, + { + "id": 59519, + "type": "formula", + "name": "Is high priority", + "description": null, + "order": 14, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "duration_format": null, + "date_include_time": null, + "date_show_tzinfo": null, + "number_prefix": "", + "array_formula_type": null, + "nullable": false, + "date_format": null, + "date_time_format": null, + "date_force_timezone": null, + "number_suffix": "", + "number_separator": "", + "error": null, + "number_decimal_places": null, + "formula": "field('Importance') = 'High'", + "formula_type": "boolean" + }, + { + "id": 59520, + "type": "formula", + "name": "Desired start date", + "description": null, + "order": 15, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "duration_format": null, + "date_include_time": false, + "date_show_tzinfo": false, + "number_prefix": "", + "array_formula_type": null, + "nullable": true, + "date_format": "ISO", + "date_time_format": "24", + "date_force_timezone": null, + "number_suffix": "", + "number_separator": "", + "error": null, + "number_decimal_places": null, + "formula": "todate(if(and(field('Is urgent'),field('Is high priority')),today(),if(and(field('Is urgent'),not(field('Is high priority'))),today() + date_interval('1 day'),if(and(not(field('Is urgent')),field('Is high priority')),today() + date_interval('3 days'),''))),'YYYY-MM-DD')", + "formula_type": "date" + } + ], + "views": [ + { + "id": 26406, + "type": "grid", + "name": "All tasks", + "order": 1, + "ownership_type": "collaborative", + "owned_by": "frederik@baserow.io", + "filter_type": "AND", + "filters_disabled": false, + "filters": [], + "filter_groups": [], + "sortings": [], + "group_bys": [], + "decorations": [], + "public": false, + "row_identifier_type": "id", + "row_height_size": "medium", + "field_options": [ + { + "id": 260742, + "field_id": 59517, + "width": 200, + "hidden": false, + "order": 0, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260743, + "field_id": 59514, + "width": 200, + "hidden": true, + "order": 1, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260744, + "field_id": 59512, + "width": 171, + "hidden": false, + "order": 2, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260745, + "field_id": 59510, + "width": 157, + "hidden": false, + "order": 3, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260746, + "field_id": 59515, + "width": 143, + "hidden": false, + "order": 4, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260747, + "field_id": 59516, + "width": 141, + "hidden": false, + "order": 5, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260748, + "field_id": 59518, + "width": 125, + "hidden": false, + "order": 6, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260749, + "field_id": 59519, + "width": 200, + "hidden": false, + "order": 7, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260750, + "field_id": 59520, + "width": 200, + "hidden": false, + "order": 8, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260751, + "field_id": 59511, + "width": 554, + "hidden": false, + "order": 9, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260752, + "field_id": 59513, + "width": 200, + "hidden": false, + "order": 10, + "aggregation_type": "", + "aggregation_raw_type": "" + } + ] + }, + { + "id": 26454, + "type": "calendar", + "name": "Calendar: task schedule", + "order": 2, + "ownership_type": "collaborative", + "owned_by": "frederik@baserow.io", + "filter_type": "AND", + "filters_disabled": false, + "filters": [], + "filter_groups": [], + "sortings": [], + "decorations": [], + "public": false, + "date_field_id": 59520, + "field_options": [ + { + "id": 12561, + "field_id": 59510, + "hidden": true, + "order": 32767 + }, + { + "id": 12562, + "field_id": 59511, + "hidden": true, + "order": 32767 + }, + { + "id": 12563, + "field_id": 59512, + "hidden": true, + "order": 32767 + }, + { + "id": 12564, + "field_id": 59513, + "hidden": true, + "order": 32767 + }, + { + "id": 12565, + "field_id": 59514, + "hidden": true, + "order": 32767 + }, + { + "id": 12566, + "field_id": 59515, + "hidden": true, + "order": 32767 + }, + { + "id": 12567, + "field_id": 59516, + "hidden": true, + "order": 32767 + }, + { + "id": 12560, + "field_id": 59517, + "hidden": false, + "order": 32767 + }, + { + "id": 12568, + "field_id": 59518, + "hidden": true, + "order": 32767 + }, + { + "id": 12569, + "field_id": 59519, + "hidden": true, + "order": 32767 + }, + { + "id": 12570, + "field_id": 59520, + "hidden": true, + "order": 32767 + } + ] + } + ], + "rows": [ + { + "id": 1, + "order": "1.00000000000000000000", + "created_on": "2025-02-05T07:48:00.081133+00:00", + "updated_on": "2025-03-05T14:37:46.499200+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59517": null, + "field_59510": 20967, + "field_59511": "Conduct onboarding for a new hire, including setting up payroll in the HR system, scheduling a welcome meeting with the team, providing access to company tools, and assigning required training materials.", + "field_59512": "Employee Onboarding", + "field_59513": null, + "field_59514": null, + "field_59515": 20969, + "field_59516": "2025-03-06", + "field_59518": null, + "field_59519": null, + "field_59520": null + }, + { + "id": 2, + "order": "2.00000000000000000000", + "created_on": "2025-02-05T07:48:00.081208+00:00", + "updated_on": "2025-03-05T14:37:57.135878+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59517": null, + "field_59510": 20966, + "field_59511": "Process and approve five supplier invoices by verifying amounts, ensuring correct account allocation, obtaining necessary approvals, and scheduling payment in the financial system.", + "field_59512": "Invoice Processing", + "field_59513": null, + "field_59514": null, + "field_59515": 20968, + "field_59516": "2025-03-20", + "field_59518": null, + "field_59519": null, + "field_59520": null + }, + { + "id": 3, + "order": "3.00000000000000000000", + "created_on": "2025-02-05T07:48:00.081236+00:00", + "updated_on": "2025-03-05T14:38:01.849996+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59517": null, + "field_59510": 20965, + "field_59511": "Write, design, and schedule three social media posts promoting the company\u2019s latest product update, ensuring alignment with brand guidelines and marketing strategy.", + "field_59512": "Social Media Posts", + "field_59513": null, + "field_59514": null, + "field_59515": 20969, + "field_59516": "2025-03-06", + "field_59518": null, + "field_59519": null, + "field_59520": null + }, + { + "id": 4, + "order": "4.00000000000000000000", + "created_on": "2025-02-05T07:48:00.081262+00:00", + "updated_on": "2025-03-05T14:38:05.386390+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59517": null, + "field_59510": 20963, + "field_59511": "Resolve 15 customer support tickets by diagnosing issues, providing solutions, updating ticket statuses, and following up to ensure customer satisfaction.", + "field_59512": "Customer Ticketing", + "field_59513": null, + "field_59514": null, + "field_59515": 20970, + "field_59516": "2025-03-06", + "field_59518": null, + "field_59519": null, + "field_59520": null + }, + { + "id": 5, + "order": "5.00000000000000000000", + "created_on": "2025-02-05T07:48:00.081289+00:00", + "updated_on": "2025-03-05T14:38:11.201268+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59517": null, + "field_59510": 20964, + "field_59511": "Break down an upcoming project into five key tasks, assign them to team members, set deadlines in the project management system, and communicate expectations to stakeholders.", + "field_59512": "Task Assignment", + "field_59513": null, + "field_59514": null, + "field_59515": 20969, + "field_59516": "2025-03-27", + "field_59518": null, + "field_59519": null, + "field_59520": null + }, + { + "id": 6, + "order": "6.00000000000000000000", + "created_on": "2025-02-05T07:48:00.081315+00:00", + "updated_on": "2025-03-05T14:38:15.494431+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59517": null, + "field_59510": 20963, + "field_59511": "Install security patches and update software on all employee workstations, ensuring compatibility, testing functionality, and documenting changes for compliance.", + "field_59512": "System Updates", + "field_59513": null, + "field_59514": null, + "field_59515": 20968, + "field_59516": "2025-03-11", + "field_59518": null, + "field_59519": null, + "field_59520": null + }, + { + "id": 7, + "order": "7.00000000000000000000", + "created_on": "2025-02-05T07:48:00.081340+00:00", + "updated_on": "2025-02-05T08:27:55.616379+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59517": null, + "field_59510": 20963, + "field_59511": "Conduct a physical inventory count of all high-value products, compare results with digital records, report discrepancies, and update the inventory management system.", + "field_59512": "Inventory Check", + "field_59513": null, + "field_59514": null, + "field_59515": 20969, + "field_59516": "2025-02-08", + "field_59518": null, + "field_59519": null, + "field_59520": null + }, + { + "id": 8, + "order": "8.00000000000000000000", + "created_on": "2025-02-05T07:48:00.081365+00:00", + "updated_on": "2025-02-05T08:24:20.757720+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59517": null, + "field_59510": 20965, + "field_59511": "Follow up with five potential clients via email or phone, answer questions, provide additional information, and schedule meetings to move them through the sales pipeline.", + "field_59512": "Client Follow-Up", + "field_59513": null, + "field_59514": null, + "field_59515": 20970, + "field_59516": "2025-02-07", + "field_59518": null, + "field_59519": null, + "field_59520": null + }, + { + "id": 9, + "order": "9.00000000000000000000", + "created_on": "2025-02-05T07:48:00.081389+00:00", + "updated_on": "2025-02-05T08:24:24.876898+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59517": null, + "field_59510": 20964, + "field_59511": "Review and update one company policy by assessing current regulations, identifying gaps, revising wording, obtaining approval, and publishing the final version.", + "field_59512": "Policy Review", + "field_59513": null, + "field_59514": null, + "field_59515": 20970, + "field_59516": "2025-02-11", + "field_59518": null, + "field_59519": null, + "field_59520": null + }, + { + "id": 10, + "order": "10.00000000000000000000", + "created_on": "2025-02-05T07:48:00.081413+00:00", + "updated_on": "2025-02-05T08:24:38.392668+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59517": null, + "field_59510": 20964, + "field_59511": "Conduct one-on-one performance reviews with three employees, discuss achievements and challenges, document feedback, and outline action steps for improvement.", + "field_59512": "Performance Reviews", + "field_59513": null, + "field_59514": null, + "field_59515": 20970, + "field_59516": "2025-02-28", + "field_59518": null, + "field_59519": null, + "field_59520": null + } + ], + "data_sync": null + } + ] + }, + { + "id": 2160, + "name": "Case 4 - Task Management", + "order": 4, + "type": "database", + "tables": [ + { + "id": 5675, + "name": "Tasks", + "order": 2, + "fields": [ + { + "id": 59536, + "type": "formula", + "name": "Name", + "description": null, + "order": 10, + "primary": true, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "duration_format": null, + "date_include_time": null, + "date_show_tzinfo": null, + "number_prefix": "", + "array_formula_type": null, + "nullable": false, + "date_format": null, + "date_time_format": null, + "date_force_timezone": null, + "number_suffix": "", + "number_separator": "", + "error": null, + "number_decimal_places": null, + "formula": "concat(left(upper(totext(field('Category'))),3),'-',year(field('Created on')),'-',field('ID'))", + "formula_type": "text" + }, + { + "id": 59521, + "type": "single_select", + "name": "Category", + "description": null, + "order": 1, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "select_options": [ + { + "id": 20971, + "value": "Operations", + "color": "darker-gray", + "order": 0 + }, + { + "id": 20972, + "value": "Management", + "color": "dark-brown", + "order": 1 + }, + { + "id": 20973, + "value": "Marketing", + "color": "light-cyan", + "order": 2 + }, + { + "id": 20974, + "value": "Finance", + "color": "darker-yellow", + "order": 3 + }, + { + "id": 20975, + "value": "Human Resources", + "color": "light-yellow", + "order": 4 + } + ] + }, + { + "id": 59522, + "type": "text", + "name": "Description", + "description": null, + "order": 2, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "text_default": "" + }, + { + "id": 59523, + "type": "text", + "name": "Title", + "description": null, + "order": 3, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "text_default": "" + }, + { + "id": 59524, + "type": "created_on", + "name": "Created on", + "description": null, + "order": 8, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "date_format": "ISO", + "date_include_time": false, + "date_time_format": "24", + "date_show_tzinfo": false, + "date_force_timezone": null + }, + { + "id": 59525, + "type": "formula", + "name": "ID", + "description": null, + "order": 9, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "duration_format": null, + "date_include_time": null, + "date_show_tzinfo": null, + "number_prefix": "", + "array_formula_type": null, + "nullable": false, + "date_format": null, + "date_time_format": null, + "date_force_timezone": null, + "number_suffix": "", + "number_separator": "", + "error": null, + "number_decimal_places": null, + "formula": "if(row_id() < 10,concat('0000',row_id()),if(row_id() < 100,concat('000',row_id()),if(row_id() < 1000,concat('00',row_id()),if(row_id() < 10000,concat('0',row_id()),row_id()))))", + "formula_type": "text" + }, + { + "id": 59526, + "type": "single_select", + "name": "Importance", + "description": null, + "order": 11, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "select_options": [ + { + "id": 20976, + "value": "Low", + "color": "cyan", + "order": 0 + }, + { + "id": 20977, + "value": "Medium", + "color": "blue", + "order": 1 + }, + { + "id": 20978, + "value": "High", + "color": "red", + "order": 2 + } + ] + }, + { + "id": 59527, + "type": "date", + "name": "Deadline", + "description": null, + "order": 12, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "date_format": "ISO", + "date_include_time": false, + "date_time_format": "24", + "date_show_tzinfo": false, + "date_force_timezone": null + }, + { + "id": 59537, + "type": "formula", + "name": "Is urgent", + "description": null, + "order": 13, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "duration_format": null, + "date_include_time": null, + "date_show_tzinfo": null, + "number_prefix": "", + "array_formula_type": null, + "nullable": false, + "date_format": null, + "date_time_format": null, + "date_force_timezone": null, + "number_suffix": "", + "number_separator": "", + "error": null, + "number_decimal_places": null, + "formula": "field('Deadline') < today() + date_interval('3 days')", + "formula_type": "boolean" + }, + { + "id": 59538, + "type": "formula", + "name": "Is high priority", + "description": null, + "order": 14, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "duration_format": null, + "date_include_time": null, + "date_show_tzinfo": null, + "number_prefix": "", + "array_formula_type": null, + "nullable": false, + "date_format": null, + "date_time_format": null, + "date_force_timezone": null, + "number_suffix": "", + "number_separator": "", + "error": null, + "number_decimal_places": null, + "formula": "field('Importance') = 'High'", + "formula_type": "boolean" + }, + { + "id": 59542, + "type": "formula", + "name": "Desired start date", + "description": null, + "order": 15, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "duration_format": null, + "date_include_time": null, + "date_show_tzinfo": null, + "number_prefix": "", + "array_formula_type": null, + "nullable": false, + "date_format": null, + "date_time_format": null, + "date_force_timezone": null, + "number_suffix": "", + "number_separator": "", + "error": null, + "number_decimal_places": null, + "formula": "if(and(field('Is urgent'),field('Is high priority')),today(),if(and(field('Is urgent'),not(field('Is high priority'))),today() + date_interval('1 day'),if(and(not(field('Is urgent')),field('Is high priority')),today() + date_interval('3 days'),'')))", + "formula_type": "text" + }, + { + "id": 59528, + "type": "number", + "name": "Expected workload", + "description": null, + "order": 16, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "number_decimal_places": 0, + "number_negative": false, + "number_prefix": "", + "number_suffix": "hours", + "number_separator": "" + }, + { + "id": 59529, + "type": "link_row", + "name": "Contractor", + "description": null, + "order": 17, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "link_row_table_id": 5676, + "link_row_related_field_id": 59535, + "link_row_limit_selection_view_id": null, + "has_related_field": true + }, + { + "id": 59539, + "type": "formula", + "name": "Required fields valid", + "description": null, + "order": 18, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "duration_format": null, + "date_include_time": null, + "date_show_tzinfo": null, + "number_prefix": "", + "array_formula_type": null, + "nullable": false, + "date_format": null, + "date_time_format": null, + "date_force_timezone": null, + "number_suffix": "", + "number_separator": "", + "error": null, + "number_decimal_places": null, + "formula": "and(and(not(isblank(field('Importance'))),not(isblank(field('Deadline')))),not(isblank(field('Expected workload'))))", + "formula_type": "boolean" + }, + { + "id": 59541, + "type": "formula", + "name": "Contractor valid", + "description": null, + "order": 19, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "duration_format": null, + "date_include_time": null, + "date_show_tzinfo": null, + "number_prefix": "", + "array_formula_type": null, + "nullable": false, + "date_format": null, + "date_time_format": null, + "date_force_timezone": null, + "number_suffix": "", + "number_separator": "", + "error": null, + "number_decimal_places": null, + "formula": "or(count(field('Contractor')) = 0,regex_replace(join(lookup('Contractor','VAT Number'),''),'(GB)?([0-9]{9})','valid') = 'valid')", + "formula_type": "boolean" + }, + { + "id": 59543, + "type": "formula", + "name": "Task is valid", + "description": null, + "order": 20, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "duration_format": null, + "date_include_time": null, + "date_show_tzinfo": null, + "number_prefix": "", + "array_formula_type": null, + "nullable": false, + "date_format": null, + "date_time_format": null, + "date_force_timezone": null, + "number_suffix": "", + "number_separator": "", + "error": null, + "number_decimal_places": null, + "formula": "and(field('Required fields valid'),field('Contractor valid'))", + "formula_type": "boolean" + } + ], + "views": [ + { + "id": 26407, + "type": "grid", + "name": "All tasks", + "order": 1, + "ownership_type": "collaborative", + "owned_by": "frederik@baserow.io", + "filter_type": "AND", + "filters_disabled": false, + "filters": [], + "filter_groups": [], + "sortings": [], + "group_bys": [], + "decorations": [], + "public": false, + "row_identifier_type": "id", + "row_height_size": "medium", + "field_options": [ + { + "id": 260753, + "field_id": 59536, + "width": 200, + "hidden": false, + "order": 0, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260754, + "field_id": 59525, + "width": 200, + "hidden": true, + "order": 1, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260755, + "field_id": 59523, + "width": 171, + "hidden": false, + "order": 2, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260756, + "field_id": 59521, + "width": 157, + "hidden": false, + "order": 3, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260757, + "field_id": 59526, + "width": 143, + "hidden": false, + "order": 4, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260758, + "field_id": 59527, + "width": 141, + "hidden": false, + "order": 5, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260759, + "field_id": 59528, + "width": 200, + "hidden": false, + "order": 6, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260760, + "field_id": 59537, + "width": 125, + "hidden": false, + "order": 7, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260761, + "field_id": 59538, + "width": 200, + "hidden": false, + "order": 8, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260762, + "field_id": 59542, + "width": 200, + "hidden": false, + "order": 9, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260763, + "field_id": 59522, + "width": 554, + "hidden": false, + "order": 10, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260764, + "field_id": 59529, + "width": 200, + "hidden": false, + "order": 11, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260765, + "field_id": 59524, + "width": 200, + "hidden": false, + "order": 12, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260766, + "field_id": 59539, + "width": 200, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260767, + "field_id": 59541, + "width": 200, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260768, + "field_id": 59543, + "width": 200, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + } + ] + }, + { + "id": 26408, + "type": "grid", + "name": "Valid tasks", + "order": 2, + "ownership_type": "collaborative", + "owned_by": "frederik@baserow.io", + "filter_type": "AND", + "filters_disabled": false, + "filters": [ + { + "id": 13945, + "field_id": 59543, + "type": "boolean", + "value": "1", + "group": null + } + ], + "filter_groups": [], + "sortings": [], + "group_bys": [], + "decorations": [], + "public": false, + "row_identifier_type": "id", + "row_height_size": "medium", + "field_options": [ + { + "id": 260769, + "field_id": 59536, + "width": 200, + "hidden": false, + "order": 0, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260770, + "field_id": 59525, + "width": 200, + "hidden": true, + "order": 1, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260771, + "field_id": 59523, + "width": 171, + "hidden": false, + "order": 2, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260772, + "field_id": 59521, + "width": 157, + "hidden": false, + "order": 3, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260773, + "field_id": 59526, + "width": 143, + "hidden": false, + "order": 4, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260774, + "field_id": 59527, + "width": 141, + "hidden": false, + "order": 5, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260775, + "field_id": 59528, + "width": 200, + "hidden": false, + "order": 6, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260776, + "field_id": 59537, + "width": 125, + "hidden": false, + "order": 7, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260777, + "field_id": 59538, + "width": 200, + "hidden": false, + "order": 8, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260778, + "field_id": 59542, + "width": 200, + "hidden": false, + "order": 9, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260779, + "field_id": 59522, + "width": 554, + "hidden": false, + "order": 10, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260780, + "field_id": 59529, + "width": 200, + "hidden": false, + "order": 11, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260781, + "field_id": 59524, + "width": 200, + "hidden": false, + "order": 12, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260782, + "field_id": 59539, + "width": 200, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260783, + "field_id": 59541, + "width": 200, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260784, + "field_id": 59543, + "width": 200, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + } + ] + }, + { + "id": 26409, + "type": "grid", + "name": "Invalid tasks", + "order": 3, + "ownership_type": "collaborative", + "owned_by": "frederik@baserow.io", + "filter_type": "AND", + "filters_disabled": false, + "filters": [ + { + "id": 13946, + "field_id": 59543, + "type": "boolean", + "value": "0", + "group": null + } + ], + "filter_groups": [], + "sortings": [], + "group_bys": [], + "decorations": [], + "public": false, + "row_identifier_type": "id", + "row_height_size": "medium", + "field_options": [ + { + "id": 260785, + "field_id": 59536, + "width": 200, + "hidden": false, + "order": 0, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260786, + "field_id": 59525, + "width": 200, + "hidden": true, + "order": 1, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260787, + "field_id": 59523, + "width": 171, + "hidden": false, + "order": 2, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260788, + "field_id": 59521, + "width": 157, + "hidden": false, + "order": 3, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260789, + "field_id": 59526, + "width": 143, + "hidden": false, + "order": 4, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260790, + "field_id": 59527, + "width": 141, + "hidden": false, + "order": 5, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260791, + "field_id": 59528, + "width": 200, + "hidden": false, + "order": 6, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260792, + "field_id": 59537, + "width": 125, + "hidden": false, + "order": 7, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260793, + "field_id": 59538, + "width": 200, + "hidden": false, + "order": 8, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260794, + "field_id": 59542, + "width": 200, + "hidden": false, + "order": 9, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260795, + "field_id": 59522, + "width": 554, + "hidden": false, + "order": 10, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260796, + "field_id": 59529, + "width": 200, + "hidden": false, + "order": 11, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260797, + "field_id": 59524, + "width": 200, + "hidden": false, + "order": 12, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260798, + "field_id": 59539, + "width": 200, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260799, + "field_id": 59541, + "width": 200, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260800, + "field_id": 59543, + "width": 200, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + } + ] + } + ], + "rows": [ + { + "id": 1, + "order": "1.00000000000000000000", + "created_on": "2025-02-05T07:48:00.081133+00:00", + "updated_on": "2025-02-05T08:54:28.198506+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59536": null, + "field_59521": 20975, + "field_59522": "Conduct onboarding for a new hire, including setting up payroll in the HR system, scheduling a welcome meeting with the team, providing access to company tools, and assigning required training materials.", + "field_59523": "Employee Onboarding", + "field_59524": null, + "field_59525": null, + "field_59526": 20977, + "field_59527": "2025-02-06", + "field_59537": null, + "field_59538": null, + "field_59542": null, + "field_59528": "12", + "field_59529": [], + "field_59539": null, + "field_59541": null, + "field_59543": null + }, + { + "id": 2, + "order": "2.00000000000000000000", + "created_on": "2025-02-05T07:48:00.081208+00:00", + "updated_on": "2025-02-05T08:55:14.566113+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59536": null, + "field_59521": 20974, + "field_59522": "Process and approve five supplier invoices by verifying amounts, ensuring correct account allocation, obtaining necessary approvals, and scheduling payment in the financial system.", + "field_59523": "Invoice Processing", + "field_59524": null, + "field_59525": null, + "field_59526": 20976, + "field_59527": "2025-02-20", + "field_59537": null, + "field_59538": null, + "field_59542": null, + "field_59528": "34", + "field_59529": [], + "field_59539": null, + "field_59541": null, + "field_59543": null + }, + { + "id": 3, + "order": "3.00000000000000000000", + "created_on": "2025-02-05T07:48:00.081236+00:00", + "updated_on": "2025-02-05T08:52:13.641485+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59536": null, + "field_59521": 20973, + "field_59522": "Write, design, and schedule three social media posts promoting the company\u2019s latest product update, ensuring alignment with brand guidelines and marketing strategy.", + "field_59523": "Social Media Posts", + "field_59524": null, + "field_59525": null, + "field_59526": 20977, + "field_59527": "2025-02-06", + "field_59537": null, + "field_59538": null, + "field_59542": null, + "field_59528": "53", + "field_59529": [ + 1 + ], + "field_59539": null, + "field_59541": null, + "field_59543": null + }, + { + "id": 4, + "order": "4.00000000000000000000", + "created_on": "2025-02-05T07:48:00.081262+00:00", + "updated_on": "2025-02-05T08:40:03.177446+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59536": null, + "field_59521": 20971, + "field_59522": "Resolve 15 customer support tickets by diagnosing issues, providing solutions, updating ticket statuses, and following up to ensure customer satisfaction.", + "field_59523": "Customer Ticketing", + "field_59524": null, + "field_59525": null, + "field_59526": 20978, + "field_59527": "2025-02-06", + "field_59537": null, + "field_59538": null, + "field_59542": null, + "field_59528": "6", + "field_59529": [], + "field_59539": null, + "field_59541": null, + "field_59543": null + }, + { + "id": 5, + "order": "5.00000000000000000000", + "created_on": "2025-02-05T07:48:00.081289+00:00", + "updated_on": "2025-02-05T08:40:15.433306+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59536": null, + "field_59521": 20972, + "field_59522": "Break down an upcoming project into five key tasks, assign them to team members, set deadlines in the project management system, and communicate expectations to stakeholders.", + "field_59523": "Task Assignment", + "field_59524": null, + "field_59525": null, + "field_59526": 20977, + "field_59527": "2025-02-27", + "field_59537": null, + "field_59538": null, + "field_59542": null, + "field_59528": "11", + "field_59529": [], + "field_59539": null, + "field_59541": null, + "field_59543": null + }, + { + "id": 6, + "order": "6.00000000000000000000", + "created_on": "2025-02-05T07:48:00.081315+00:00", + "updated_on": "2025-03-05T14:39:11.556520+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59536": null, + "field_59521": 20971, + "field_59522": "Install security patches and update software on all employee workstations, ensuring compatibility, testing functionality, and documenting changes for compliance.", + "field_59523": "System Updates", + "field_59524": null, + "field_59525": null, + "field_59526": null, + "field_59527": "2025-02-11", + "field_59537": null, + "field_59538": null, + "field_59542": null, + "field_59528": "9", + "field_59529": [ + 2 + ], + "field_59539": null, + "field_59541": null, + "field_59543": null + }, + { + "id": 7, + "order": "7.00000000000000000000", + "created_on": "2025-02-05T07:48:00.081340+00:00", + "updated_on": "2025-03-05T14:39:38.107347+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59536": null, + "field_59521": 20971, + "field_59522": "Conduct a physical inventory count of all high-value products, compare results with digital records, report discrepancies, and update the inventory management system.", + "field_59523": "Inventory Check", + "field_59524": null, + "field_59525": null, + "field_59526": 20977, + "field_59527": "2025-02-08", + "field_59537": null, + "field_59538": null, + "field_59542": null, + "field_59528": "23", + "field_59529": [ + 3 + ], + "field_59539": null, + "field_59541": null, + "field_59543": null + }, + { + "id": 8, + "order": "8.00000000000000000000", + "created_on": "2025-02-05T07:48:00.081365+00:00", + "updated_on": "2025-02-05T09:05:11.649918+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59536": null, + "field_59521": 20973, + "field_59522": "Follow up with five potential clients via email or phone, answer questions, provide additional information, and schedule meetings to move them through the sales pipeline.", + "field_59523": "Client Follow-Up", + "field_59524": null, + "field_59525": null, + "field_59526": 20978, + "field_59527": "2025-02-07", + "field_59537": null, + "field_59538": null, + "field_59542": null, + "field_59528": "45", + "field_59529": [], + "field_59539": null, + "field_59541": null, + "field_59543": null + }, + { + "id": 9, + "order": "9.00000000000000000000", + "created_on": "2025-02-05T07:48:00.081389+00:00", + "updated_on": "2025-02-05T08:51:47.995170+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59536": null, + "field_59521": 20972, + "field_59522": "Review and update one company policy by assessing current regulations, identifying gaps, revising wording, obtaining approval, and publishing the final version.", + "field_59523": "Policy Review", + "field_59524": null, + "field_59525": null, + "field_59526": 20978, + "field_59527": "2025-02-11", + "field_59537": null, + "field_59538": null, + "field_59542": null, + "field_59528": "16", + "field_59529": [ + 4 + ], + "field_59539": null, + "field_59541": null, + "field_59543": null + }, + { + "id": 10, + "order": "10.00000000000000000000", + "created_on": "2025-02-05T07:48:00.081413+00:00", + "updated_on": "2025-02-05T08:40:34.750926+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59536": null, + "field_59521": 20972, + "field_59522": "Conduct one-on-one performance reviews with three employees, discuss achievements and challenges, document feedback, and outline action steps for improvement.", + "field_59523": "Performance Reviews", + "field_59524": null, + "field_59525": null, + "field_59526": 20978, + "field_59527": "2025-02-28", + "field_59537": null, + "field_59538": null, + "field_59542": null, + "field_59528": "30", + "field_59529": [], + "field_59539": null, + "field_59541": null, + "field_59543": null + } + ], + "data_sync": null + }, + { + "id": 5676, + "name": "Contractors", + "order": 3, + "fields": [ + { + "id": 59530, + "type": "text", + "name": "Company Name", + "description": null, + "order": 0, + "primary": true, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "text_default": "" + }, + { + "id": 59531, + "type": "text", + "name": "Address", + "description": null, + "order": 1, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "text_default": "" + }, + { + "id": 59532, + "type": "email", + "name": "Email", + "description": null, + "order": 2, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false + }, + { + "id": 59533, + "type": "phone_number", + "name": "Phone", + "description": null, + "order": 3, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false + }, + { + "id": 59534, + "type": "text", + "name": "VAT Number", + "description": null, + "order": 4, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "text_default": "" + }, + { + "id": 59540, + "type": "formula", + "name": "Check VAT", + "description": null, + "order": 5, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "duration_format": null, + "date_include_time": null, + "date_show_tzinfo": null, + "number_prefix": "", + "array_formula_type": null, + "nullable": false, + "date_format": null, + "date_time_format": null, + "date_force_timezone": null, + "number_suffix": "", + "number_separator": "", + "error": null, + "number_decimal_places": null, + "formula": "regex_replace(field('VAT Number'),'(GB)?([0-9]{9})','')", + "formula_type": "text" + }, + { + "id": 59535, + "type": "link_row", + "name": "Tasks", + "description": null, + "order": 6, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "link_row_table_id": 5675, + "link_row_related_field_id": 59529, + "link_row_limit_selection_view_id": null, + "has_related_field": true + } + ], + "views": [ + { + "id": 26410, + "type": "grid", + "name": "All contractors", + "order": 1, + "ownership_type": "collaborative", + "owned_by": "frederik@baserow.io", + "filter_type": "AND", + "filters_disabled": false, + "filters": [], + "filter_groups": [], + "sortings": [], + "group_bys": [], + "decorations": [], + "public": false, + "row_identifier_type": "id", + "row_height_size": "small", + "field_options": [ + { + "id": 260801, + "field_id": 59530, + "width": 200, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260802, + "field_id": 59531, + "width": 200, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260803, + "field_id": 59532, + "width": 200, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260804, + "field_id": 59533, + "width": 158, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260805, + "field_id": 59534, + "width": 200, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260807, + "field_id": 59535, + "width": 200, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260806, + "field_id": 59540, + "width": 200, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + } + ] + } + ], + "rows": [ + { + "id": 1, + "order": "1.00000000000000000000", + "created_on": "2025-02-05T08:42:47.025930+00:00", + "updated_on": "2025-02-05T08:50:20.819069+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59530": "BrightBuild Ltd", + "field_59531": "12 Greenway Street, London, SW1A 1AA", + "field_59532": "info@brightbuild.co.uk", + "field_59533": "+44 20 7946 0123", + "field_59534": "GB123456789", + "field_59540": null, + "field_59535": [ + 3 + ] + }, + { + "id": 2, + "order": "2.00000000000000000000", + "created_on": "2025-02-05T08:42:47.025996+00:00", + "updated_on": "2025-03-05T14:40:27.817510+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59530": "ProTech Solutions", + "field_59531": "45 Kings Road, Manchester, M1 3LD", + "field_59532": "contact@protechsolutions.co.uk", + "field_59533": "+44 161 555 6789", + "field_59534": "GB987654321", + "field_59540": null, + "field_59535": [ + 6 + ] + }, + { + "id": 3, + "order": "3.00000000000000000000", + "created_on": "2025-02-05T08:42:47.026022+00:00", + "updated_on": "2025-02-05T08:42:47.026022+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59530": "EcoElectrics UK", + "field_59531": "78 Solar Avenue, Birmingham, B2 4QA", + "field_59532": "support@ecoelectrics.co.uk", + "field_59533": "+44 121 432 8765", + "field_59534": "GB456123789", + "field_59540": null, + "field_59535": [ + 7 + ] + }, + { + "id": 4, + "order": "4.00000000000000000000", + "created_on": "2025-02-05T08:42:47.026045+00:00", + "updated_on": "2025-03-05T14:40:34.632637+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59530": "SwiftLogistics", + "field_59531": "22 Dockside Lane, Liverpool, L3 1AB", + "field_59532": "admin@swiftlogistics.co.uk", + "field_59533": "+44 151 789 6543", + "field_59534": "UK321654987", + "field_59540": null, + "field_59535": [ + 9 + ] + }, + { + "id": 5, + "order": "5.00000000000000000000", + "created_on": "2025-02-05T08:42:47.026069+00:00", + "updated_on": "2025-02-05T08:42:47.026069+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59530": "Regal Interiors", + "field_59531": "89 High Street, Edinburgh, EH2 4PH", + "field_59532": "sales@regalinteriors.co.uk", + "field_59533": "+44 131 246 9870", + "field_59534": "GB654987321", + "field_59540": null, + "field_59535": [] + } + ], + "data_sync": null + } + ] + }, + { + "id": 2161, + "name": "Case 5 - Task Management", + "order": 5, + "type": "database", + "tables": [ + { + "id": 5677, + "name": "Tasks", + "order": 2, + "fields": [ + { + "id": 59559, + "type": "formula", + "name": "Name", + "description": null, + "order": 10, + "primary": true, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "duration_format": null, + "date_include_time": null, + "date_show_tzinfo": null, + "number_prefix": "", + "array_formula_type": null, + "nullable": false, + "date_format": null, + "date_time_format": null, + "date_force_timezone": null, + "number_suffix": "", + "number_separator": "", + "error": null, + "number_decimal_places": null, + "formula": "concat(left(upper(totext(field('Category'))),3),'-',year(field('Created on')),'-',field('ID'))", + "formula_type": "text" + }, + { + "id": 59544, + "type": "single_select", + "name": "Category", + "description": null, + "order": 1, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "select_options": [ + { + "id": 20979, + "value": "Operations", + "color": "darker-gray", + "order": 0 + }, + { + "id": 20980, + "value": "Management", + "color": "dark-brown", + "order": 1 + }, + { + "id": 20981, + "value": "Marketing", + "color": "light-cyan", + "order": 2 + }, + { + "id": 20982, + "value": "Finance", + "color": "darker-yellow", + "order": 3 + }, + { + "id": 20983, + "value": "Human Resources", + "color": "light-yellow", + "order": 4 + } + ] + }, + { + "id": 59545, + "type": "text", + "name": "Description", + "description": null, + "order": 2, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "text_default": "" + }, + { + "id": 59546, + "type": "text", + "name": "Title", + "description": null, + "order": 3, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "text_default": "" + }, + { + "id": 59547, + "type": "created_on", + "name": "Created on", + "description": null, + "order": 8, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "date_format": "ISO", + "date_include_time": false, + "date_time_format": "24", + "date_show_tzinfo": false, + "date_force_timezone": null + }, + { + "id": 59548, + "type": "formula", + "name": "ID", + "description": null, + "order": 9, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "duration_format": null, + "date_include_time": null, + "date_show_tzinfo": null, + "number_prefix": "", + "array_formula_type": null, + "nullable": false, + "date_format": null, + "date_time_format": null, + "date_force_timezone": null, + "number_suffix": "", + "number_separator": "", + "error": null, + "number_decimal_places": null, + "formula": "if(row_id() < 10,concat('0000',row_id()),if(row_id() < 100,concat('000',row_id()),if(row_id() < 1000,concat('00',row_id()),if(row_id() < 10000,concat('0',row_id()),row_id()))))", + "formula_type": "text" + }, + { + "id": 59549, + "type": "single_select", + "name": "Importance", + "description": null, + "order": 11, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "select_options": [ + { + "id": 20984, + "value": "Low", + "color": "cyan", + "order": 0 + }, + { + "id": 20985, + "value": "Medium", + "color": "blue", + "order": 1 + }, + { + "id": 20986, + "value": "High", + "color": "red", + "order": 2 + } + ] + }, + { + "id": 59550, + "type": "date", + "name": "Deadline", + "description": null, + "order": 12, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "date_format": "ISO", + "date_include_time": false, + "date_time_format": "24", + "date_show_tzinfo": false, + "date_force_timezone": null + }, + { + "id": 59560, + "type": "formula", + "name": "Is urgent", + "description": null, + "order": 13, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "duration_format": null, + "date_include_time": null, + "date_show_tzinfo": null, + "number_prefix": "", + "array_formula_type": null, + "nullable": false, + "date_format": null, + "date_time_format": null, + "date_force_timezone": null, + "number_suffix": "", + "number_separator": "", + "error": null, + "number_decimal_places": null, + "formula": "field('Deadline') < today() + date_interval(concat(field('Expected workload') / 6,' days'))", + "formula_type": "boolean" + }, + { + "id": 59562, + "type": "formula", + "name": "Is high priority", + "description": null, + "order": 14, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "duration_format": null, + "date_include_time": null, + "date_show_tzinfo": null, + "number_prefix": "", + "array_formula_type": null, + "nullable": false, + "date_format": null, + "date_time_format": null, + "date_force_timezone": null, + "number_suffix": "", + "number_separator": "", + "error": null, + "number_decimal_places": null, + "formula": "field('Importance') = 'High'", + "formula_type": "boolean" + }, + { + "id": 59566, + "type": "formula", + "name": "Desired start date", + "description": null, + "order": 15, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "duration_format": null, + "date_include_time": null, + "date_show_tzinfo": null, + "number_prefix": "", + "array_formula_type": null, + "nullable": false, + "date_format": null, + "date_time_format": null, + "date_force_timezone": null, + "number_suffix": "", + "number_separator": "", + "error": null, + "number_decimal_places": null, + "formula": "if(and(field('Is urgent'),field('Is high priority')),today(),if(and(field('Is urgent'),not(field('Is high priority'))),today() + date_interval('1 day'),if(and(not(field('Is urgent')),field('Is high priority')),today() + date_interval('3 days'),'')))", + "formula_type": "text" + }, + { + "id": 59551, + "type": "number", + "name": "Expected workload", + "description": null, + "order": 16, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "number_decimal_places": 0, + "number_negative": false, + "number_prefix": "", + "number_suffix": "hours", + "number_separator": "" + }, + { + "id": 59552, + "type": "link_row", + "name": "Contractor", + "description": null, + "order": 17, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "link_row_table_id": 5678, + "link_row_related_field_id": 59558, + "link_row_limit_selection_view_id": null, + "has_related_field": true + }, + { + "id": 59563, + "type": "formula", + "name": "Required fields valid", + "description": null, + "order": 18, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "duration_format": null, + "date_include_time": null, + "date_show_tzinfo": null, + "number_prefix": "", + "array_formula_type": null, + "nullable": false, + "date_format": null, + "date_time_format": null, + "date_force_timezone": null, + "number_suffix": "", + "number_separator": "", + "error": null, + "number_decimal_places": null, + "formula": "and(and(not(isblank(field('Importance'))),not(isblank(field('Deadline')))),not(isblank(field('Expected workload'))))", + "formula_type": "boolean" + }, + { + "id": 59564, + "type": "formula", + "name": "Contractor valid", + "description": null, + "order": 19, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "duration_format": null, + "date_include_time": null, + "date_show_tzinfo": null, + "number_prefix": "", + "array_formula_type": null, + "nullable": false, + "date_format": null, + "date_time_format": null, + "date_force_timezone": null, + "number_suffix": "", + "number_separator": "", + "error": null, + "number_decimal_places": null, + "formula": "or(count(field('Contractor')) = 0,regex_replace(join(lookup('Contractor','VAT Number'),''),'(GB)?([0-9]{9})','valid') = 'valid')", + "formula_type": "boolean" + }, + { + "id": 59567, + "type": "formula", + "name": "Task is valid", + "description": null, + "order": 20, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "duration_format": null, + "date_include_time": null, + "date_show_tzinfo": null, + "number_prefix": "", + "array_formula_type": null, + "nullable": false, + "date_format": null, + "date_time_format": null, + "date_force_timezone": null, + "number_suffix": "", + "number_separator": "", + "error": null, + "number_decimal_places": null, + "formula": "and(field('Required fields valid'),field('Contractor valid'))", + "formula_type": "boolean" + }, + { + "id": 59561, + "type": "formula", + "name": "Final start date", + "description": null, + "order": 21, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "duration_format": null, + "date_include_time": false, + "date_show_tzinfo": false, + "number_prefix": "", + "array_formula_type": null, + "nullable": true, + "date_format": "ISO", + "date_time_format": "24", + "date_force_timezone": null, + "number_suffix": "", + "number_separator": "", + "error": null, + "number_decimal_places": null, + "formula": "field('Deadline') - date_interval(concat(field('Expected workload') / 6 + 1,' days'))", + "formula_type": "date" + } + ], + "views": [ + { + "id": 26411, + "type": "grid", + "name": "All tasks", + "order": 1, + "ownership_type": "collaborative", + "owned_by": "frederik@baserow.io", + "filter_type": "AND", + "filters_disabled": false, + "filters": [], + "filter_groups": [], + "sortings": [], + "group_bys": [], + "decorations": [ + { + "id": 8720, + "type": "background_color", + "value_provider_type": "conditional_color", + "value_provider_conf": { + "colors": [ + { + "id": "77f5ba06-166f-4b45-8c17-ff45cf5d4290", + "color": "light-yellow", + "filters": [ + { + "id": "2c9ff0a1-174b-47e1-8c1b-db6bc8b3f9b9", + "type": "date_is_before", + "field": 59561, + "group": null, + "value": "Europe/Brussels??today" + } + ], + "operator": "AND" + } + ] + }, + "order": 1 + } + ], + "public": false, + "row_identifier_type": "id", + "row_height_size": "medium", + "field_options": [ + { + "id": 260808, + "field_id": 59559, + "width": 200, + "hidden": false, + "order": 0, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260809, + "field_id": 59548, + "width": 200, + "hidden": true, + "order": 1, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260810, + "field_id": 59546, + "width": 171, + "hidden": false, + "order": 2, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260811, + "field_id": 59544, + "width": 157, + "hidden": false, + "order": 3, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260812, + "field_id": 59549, + "width": 143, + "hidden": false, + "order": 4, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260813, + "field_id": 59550, + "width": 141, + "hidden": false, + "order": 5, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260814, + "field_id": 59551, + "width": 200, + "hidden": false, + "order": 6, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260815, + "field_id": 59560, + "width": 125, + "hidden": false, + "order": 7, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260816, + "field_id": 59562, + "width": 200, + "hidden": false, + "order": 8, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260817, + "field_id": 59561, + "width": 200, + "hidden": false, + "order": 9, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260818, + "field_id": 59566, + "width": 200, + "hidden": false, + "order": 10, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260819, + "field_id": 59545, + "width": 554, + "hidden": false, + "order": 11, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260820, + "field_id": 59552, + "width": 200, + "hidden": false, + "order": 12, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260821, + "field_id": 59547, + "width": 200, + "hidden": false, + "order": 13, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260822, + "field_id": 59563, + "width": 200, + "hidden": false, + "order": 14, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260823, + "field_id": 59564, + "width": 200, + "hidden": false, + "order": 15, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260824, + "field_id": 59567, + "width": 200, + "hidden": false, + "order": 16, + "aggregation_type": "", + "aggregation_raw_type": "" + } + ] + }, + { + "id": 26412, + "type": "grid", + "name": "Valid tasks", + "order": 2, + "ownership_type": "collaborative", + "owned_by": "frederik@baserow.io", + "filter_type": "AND", + "filters_disabled": false, + "filters": [ + { + "id": 13947, + "field_id": 59567, + "type": "boolean", + "value": "1", + "group": null + } + ], + "filter_groups": [], + "sortings": [], + "group_bys": [], + "decorations": [], + "public": false, + "row_identifier_type": "id", + "row_height_size": "medium", + "field_options": [ + { + "id": 260825, + "field_id": 59559, + "width": 200, + "hidden": false, + "order": 0, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260826, + "field_id": 59548, + "width": 200, + "hidden": true, + "order": 1, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260827, + "field_id": 59546, + "width": 171, + "hidden": false, + "order": 2, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260828, + "field_id": 59544, + "width": 157, + "hidden": false, + "order": 3, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260829, + "field_id": 59549, + "width": 143, + "hidden": false, + "order": 4, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260830, + "field_id": 59550, + "width": 141, + "hidden": false, + "order": 5, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260831, + "field_id": 59551, + "width": 200, + "hidden": false, + "order": 6, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260832, + "field_id": 59560, + "width": 125, + "hidden": false, + "order": 7, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260833, + "field_id": 59562, + "width": 200, + "hidden": false, + "order": 8, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260834, + "field_id": 59566, + "width": 200, + "hidden": false, + "order": 9, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260835, + "field_id": 59545, + "width": 554, + "hidden": false, + "order": 10, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260836, + "field_id": 59552, + "width": 200, + "hidden": false, + "order": 11, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260837, + "field_id": 59547, + "width": 200, + "hidden": false, + "order": 12, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260838, + "field_id": 59563, + "width": 200, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260839, + "field_id": 59564, + "width": 200, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260840, + "field_id": 59567, + "width": 200, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + } + ] + }, + { + "id": 26413, + "type": "grid", + "name": "Invalid tasks", + "order": 3, + "ownership_type": "collaborative", + "owned_by": "frederik@baserow.io", + "filter_type": "AND", + "filters_disabled": false, + "filters": [ + { + "id": 13948, + "field_id": 59567, + "type": "boolean", + "value": "0", + "group": null + } + ], + "filter_groups": [], + "sortings": [], + "group_bys": [], + "decorations": [], + "public": false, + "row_identifier_type": "id", + "row_height_size": "medium", + "field_options": [ + { + "id": 260841, + "field_id": 59559, + "width": 200, + "hidden": false, + "order": 0, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260842, + "field_id": 59548, + "width": 200, + "hidden": true, + "order": 1, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260843, + "field_id": 59546, + "width": 171, + "hidden": false, + "order": 2, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260844, + "field_id": 59544, + "width": 157, + "hidden": false, + "order": 3, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260845, + "field_id": 59549, + "width": 143, + "hidden": false, + "order": 4, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260846, + "field_id": 59550, + "width": 141, + "hidden": false, + "order": 5, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260847, + "field_id": 59551, + "width": 200, + "hidden": false, + "order": 6, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260848, + "field_id": 59560, + "width": 125, + "hidden": false, + "order": 7, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260849, + "field_id": 59562, + "width": 200, + "hidden": false, + "order": 8, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260850, + "field_id": 59566, + "width": 200, + "hidden": false, + "order": 9, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260851, + "field_id": 59545, + "width": 554, + "hidden": false, + "order": 10, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260852, + "field_id": 59552, + "width": 200, + "hidden": false, + "order": 11, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260853, + "field_id": 59547, + "width": 200, + "hidden": false, + "order": 12, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260854, + "field_id": 59563, + "width": 200, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260855, + "field_id": 59564, + "width": 200, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260856, + "field_id": 59567, + "width": 200, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + } + ] + } + ], + "rows": [ + { + "id": 1, + "order": "1.00000000000000000000", + "created_on": "2025-02-05T07:48:00.081133+00:00", + "updated_on": "2025-03-05T14:41:34.331117+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59559": null, + "field_59544": 20983, + "field_59545": "Conduct onboarding for a new hire, including setting up payroll in the HR system, scheduling a welcome meeting with the team, providing access to company tools, and assigning required training materials.", + "field_59546": "Employee Onboarding", + "field_59547": null, + "field_59548": null, + "field_59549": 20985, + "field_59550": "2025-04-06", + "field_59560": null, + "field_59562": null, + "field_59566": null, + "field_59551": "12", + "field_59552": [], + "field_59563": null, + "field_59564": null, + "field_59567": null, + "field_59561": null + }, + { + "id": 2, + "order": "2.00000000000000000000", + "created_on": "2025-02-05T07:48:00.081208+00:00", + "updated_on": "2025-03-05T14:41:19.031489+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59559": null, + "field_59544": 20982, + "field_59545": "Process and approve five supplier invoices by verifying amounts, ensuring correct account allocation, obtaining necessary approvals, and scheduling payment in the financial system.", + "field_59546": "Invoice Processing", + "field_59547": null, + "field_59548": null, + "field_59549": 20984, + "field_59550": "2025-03-20", + "field_59560": null, + "field_59562": null, + "field_59566": null, + "field_59551": "34", + "field_59552": [], + "field_59563": null, + "field_59564": null, + "field_59567": null, + "field_59561": null + }, + { + "id": 3, + "order": "3.00000000000000000000", + "created_on": "2025-02-05T07:48:00.081236+00:00", + "updated_on": "2025-02-05T08:52:13.641485+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59559": null, + "field_59544": 20981, + "field_59545": "Write, design, and schedule three social media posts promoting the company\u2019s latest product update, ensuring alignment with brand guidelines and marketing strategy.", + "field_59546": "Social Media Posts", + "field_59547": null, + "field_59548": null, + "field_59549": 20985, + "field_59550": "2025-02-06", + "field_59560": null, + "field_59562": null, + "field_59566": null, + "field_59551": "53", + "field_59552": [ + 1 + ], + "field_59563": null, + "field_59564": null, + "field_59567": null, + "field_59561": null + }, + { + "id": 4, + "order": "4.00000000000000000000", + "created_on": "2025-02-05T07:48:00.081262+00:00", + "updated_on": "2025-02-05T08:40:03.177446+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59559": null, + "field_59544": 20979, + "field_59545": "Resolve 15 customer support tickets by diagnosing issues, providing solutions, updating ticket statuses, and following up to ensure customer satisfaction.", + "field_59546": "Customer Ticketing", + "field_59547": null, + "field_59548": null, + "field_59549": 20986, + "field_59550": "2025-02-06", + "field_59560": null, + "field_59562": null, + "field_59566": null, + "field_59551": "6", + "field_59552": [], + "field_59563": null, + "field_59564": null, + "field_59567": null, + "field_59561": null + }, + { + "id": 5, + "order": "5.00000000000000000000", + "created_on": "2025-02-05T07:48:00.081289+00:00", + "updated_on": "2025-03-05T14:41:25.784048+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59559": null, + "field_59544": 20980, + "field_59545": "Break down an upcoming project into five key tasks, assign them to team members, set deadlines in the project management system, and communicate expectations to stakeholders.", + "field_59546": "Task Assignment", + "field_59547": null, + "field_59548": null, + "field_59549": 20985, + "field_59550": "2025-03-27", + "field_59560": null, + "field_59562": null, + "field_59566": null, + "field_59551": "11", + "field_59552": [], + "field_59563": null, + "field_59564": null, + "field_59567": null, + "field_59561": null + }, + { + "id": 6, + "order": "6.00000000000000000000", + "created_on": "2025-02-05T07:48:00.081315+00:00", + "updated_on": "2025-02-05T08:51:34.279762+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59559": null, + "field_59544": 20979, + "field_59545": "Install security patches and update software on all employee workstations, ensuring compatibility, testing functionality, and documenting changes for compliance.", + "field_59546": "System Updates", + "field_59547": null, + "field_59548": null, + "field_59549": 20984, + "field_59550": "2025-02-11", + "field_59560": null, + "field_59562": null, + "field_59566": null, + "field_59551": "9", + "field_59552": [ + 2 + ], + "field_59563": null, + "field_59564": null, + "field_59567": null, + "field_59561": null + }, + { + "id": 7, + "order": "7.00000000000000000000", + "created_on": "2025-02-05T07:48:00.081340+00:00", + "updated_on": "2025-02-05T09:12:33.288350+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59559": null, + "field_59544": 20979, + "field_59545": "Conduct a physical inventory count of all high-value products, compare results with digital records, report discrepancies, and update the inventory management system.", + "field_59546": "Inventory Check", + "field_59547": null, + "field_59548": null, + "field_59549": 20985, + "field_59550": "2025-02-08", + "field_59560": null, + "field_59562": null, + "field_59566": null, + "field_59551": "23", + "field_59552": [ + 3 + ], + "field_59563": null, + "field_59564": null, + "field_59567": null, + "field_59561": null + }, + { + "id": 8, + "order": "8.00000000000000000000", + "created_on": "2025-02-05T07:48:00.081365+00:00", + "updated_on": "2025-02-05T09:05:11.649918+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59559": null, + "field_59544": 20981, + "field_59545": "Follow up with five potential clients via email or phone, answer questions, provide additional information, and schedule meetings to move them through the sales pipeline.", + "field_59546": "Client Follow-Up", + "field_59547": null, + "field_59548": null, + "field_59549": 20986, + "field_59550": "2025-02-07", + "field_59560": null, + "field_59562": null, + "field_59566": null, + "field_59551": "45", + "field_59552": [], + "field_59563": null, + "field_59564": null, + "field_59567": null, + "field_59561": null + }, + { + "id": 9, + "order": "9.00000000000000000000", + "created_on": "2025-02-05T07:48:00.081389+00:00", + "updated_on": "2025-02-05T08:51:47.995170+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59559": null, + "field_59544": 20980, + "field_59545": "Review and update one company policy by assessing current regulations, identifying gaps, revising wording, obtaining approval, and publishing the final version.", + "field_59546": "Policy Review", + "field_59547": null, + "field_59548": null, + "field_59549": 20986, + "field_59550": "2025-02-11", + "field_59560": null, + "field_59562": null, + "field_59566": null, + "field_59551": "16", + "field_59552": [ + 4 + ], + "field_59563": null, + "field_59564": null, + "field_59567": null, + "field_59561": null + }, + { + "id": 10, + "order": "10.00000000000000000000", + "created_on": "2025-02-05T07:48:00.081413+00:00", + "updated_on": "2025-02-05T09:11:31.741326+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59559": null, + "field_59544": 20980, + "field_59545": "Conduct one-on-one performance reviews with three employees, discuss achievements and challenges, document feedback, and outline action steps for improvement.", + "field_59546": "Performance Reviews", + "field_59547": null, + "field_59548": null, + "field_59549": 20986, + "field_59550": "2025-02-28", + "field_59560": null, + "field_59562": null, + "field_59566": null, + "field_59551": "30", + "field_59552": [], + "field_59563": null, + "field_59564": null, + "field_59567": null, + "field_59561": null + } + ], + "data_sync": null + }, + { + "id": 5678, + "name": "Contractors", + "order": 3, + "fields": [ + { + "id": 59553, + "type": "text", + "name": "Company Name", + "description": null, + "order": 0, + "primary": true, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "text_default": "" + }, + { + "id": 59554, + "type": "text", + "name": "Address", + "description": null, + "order": 1, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "text_default": "" + }, + { + "id": 59555, + "type": "email", + "name": "Email", + "description": null, + "order": 2, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false + }, + { + "id": 59556, + "type": "phone_number", + "name": "Phone", + "description": null, + "order": 3, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false + }, + { + "id": 59557, + "type": "text", + "name": "VAT Number", + "description": null, + "order": 4, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "text_default": "" + }, + { + "id": 59565, + "type": "formula", + "name": "Formula", + "description": null, + "order": 5, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "duration_format": null, + "date_include_time": null, + "date_show_tzinfo": null, + "number_prefix": "", + "array_formula_type": null, + "nullable": false, + "date_format": null, + "date_time_format": null, + "date_force_timezone": null, + "number_suffix": "", + "number_separator": "", + "error": null, + "number_decimal_places": null, + "formula": "regex_replace(field('VAT Number'),'(GB)?([0-9]{9})','')", + "formula_type": "text" + }, + { + "id": 59558, + "type": "link_row", + "name": "Tasks", + "description": null, + "order": 6, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "link_row_table_id": 5677, + "link_row_related_field_id": 59552, + "link_row_limit_selection_view_id": null, + "has_related_field": true + } + ], + "views": [ + { + "id": 26414, + "type": "grid", + "name": "All contractors", + "order": 1, + "ownership_type": "collaborative", + "owned_by": "frederik@baserow.io", + "filter_type": "AND", + "filters_disabled": false, + "filters": [], + "filter_groups": [], + "sortings": [], + "group_bys": [], + "decorations": [], + "public": false, + "row_identifier_type": "id", + "row_height_size": "small", + "field_options": [ + { + "id": 260857, + "field_id": 59553, + "width": 200, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260858, + "field_id": 59554, + "width": 200, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260859, + "field_id": 59555, + "width": 200, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260860, + "field_id": 59556, + "width": 158, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260861, + "field_id": 59557, + "width": 200, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260862, + "field_id": 59558, + "width": 200, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260863, + "field_id": 59565, + "width": 200, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + } + ] + } + ], + "rows": [ + { + "id": 1, + "order": "1.00000000000000000000", + "created_on": "2025-02-05T08:42:47.025930+00:00", + "updated_on": "2025-02-05T08:50:20.819069+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59553": "BrightBuild Ltd", + "field_59554": "12 Greenway Street, London, SW1A 1AA", + "field_59555": "info@brightbuild.co.uk", + "field_59556": "+44 20 7946 0123", + "field_59557": "GB123456789", + "field_59565": null, + "field_59558": [ + 3 + ] + }, + { + "id": 2, + "order": "2.00000000000000000000", + "created_on": "2025-02-05T08:42:47.025996+00:00", + "updated_on": "2025-02-05T08:42:47.025996+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59553": "ProTech Solutions", + "field_59554": "45 Kings Road, Manchester, M1 3LD", + "field_59555": "contact@protechsolutions.co.uk", + "field_59556": "+44 161 555 6789", + "field_59557": "GB987654321", + "field_59565": null, + "field_59558": [ + 6 + ] + }, + { + "id": 3, + "order": "3.00000000000000000000", + "created_on": "2025-02-05T08:42:47.026022+00:00", + "updated_on": "2025-02-05T08:42:47.026022+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59553": "EcoElectrics UK", + "field_59554": "78 Solar Avenue, Birmingham, B2 4QA", + "field_59555": "support@ecoelectrics.co.uk", + "field_59556": "+44 121 432 8765", + "field_59557": "GB456123789", + "field_59565": null, + "field_59558": [ + 7 + ] + }, + { + "id": 4, + "order": "4.00000000000000000000", + "created_on": "2025-02-05T08:42:47.026045+00:00", + "updated_on": "2025-02-05T08:42:47.026045+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59553": "SwiftLogistics", + "field_59554": "22 Dockside Lane, Liverpool, L3 1AB", + "field_59555": "admin@swiftlogistics.co.uk", + "field_59556": "+44 151 789 6543", + "field_59557": "GB321654987", + "field_59565": null, + "field_59558": [ + 9 + ] + }, + { + "id": 5, + "order": "5.00000000000000000000", + "created_on": "2025-02-05T08:42:47.026069+00:00", + "updated_on": "2025-02-05T08:42:47.026069+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59553": "Regal Interiors", + "field_59554": "89 High Street, Edinburgh, EH2 4PH", + "field_59555": "sales@regalinteriors.co.uk", + "field_59556": "+44 131 246 9870", + "field_59557": "GB654987321", + "field_59565": null, + "field_59558": [] + } + ], + "data_sync": null + } + ] + }, + { + "id": 2162, + "name": "Case 6 - Task Management", + "order": 6, + "type": "database", + "tables": [ + { + "id": 5679, + "name": "Tasks", + "order": 2, + "fields": [ + { + "id": 59585, + "type": "formula", + "name": "Name", + "description": null, + "order": 10, + "primary": true, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "duration_format": null, + "date_include_time": null, + "date_show_tzinfo": null, + "number_prefix": "", + "array_formula_type": null, + "nullable": false, + "date_format": null, + "date_time_format": null, + "date_force_timezone": null, + "number_suffix": "", + "number_separator": "", + "error": null, + "number_decimal_places": null, + "formula": "concat(left(upper(totext(field('Category'))),3),'-',year(field('Created on')),'-',field('ID'))", + "formula_type": "text" + }, + { + "id": 59568, + "type": "single_select", + "name": "Category", + "description": null, + "order": 1, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "select_options": [ + { + "id": 20987, + "value": "Operations", + "color": "darker-gray", + "order": 0 + }, + { + "id": 20988, + "value": "Management", + "color": "dark-brown", + "order": 1 + }, + { + "id": 20989, + "value": "Marketing", + "color": "light-cyan", + "order": 2 + }, + { + "id": 20990, + "value": "Finance", + "color": "darker-yellow", + "order": 3 + }, + { + "id": 20991, + "value": "Human Resources", + "color": "light-yellow", + "order": 4 + } + ] + }, + { + "id": 59569, + "type": "text", + "name": "Description", + "description": null, + "order": 2, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "text_default": "" + }, + { + "id": 59570, + "type": "text", + "name": "Title", + "description": null, + "order": 3, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "text_default": "" + }, + { + "id": 59571, + "type": "created_on", + "name": "Created on", + "description": null, + "order": 8, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "date_format": "ISO", + "date_include_time": false, + "date_time_format": "24", + "date_show_tzinfo": false, + "date_force_timezone": null + }, + { + "id": 59572, + "type": "formula", + "name": "ID", + "description": null, + "order": 9, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "duration_format": null, + "date_include_time": null, + "date_show_tzinfo": null, + "number_prefix": "", + "array_formula_type": null, + "nullable": false, + "date_format": null, + "date_time_format": null, + "date_force_timezone": null, + "number_suffix": "", + "number_separator": "", + "error": null, + "number_decimal_places": null, + "formula": "if(row_id() < 10,concat('0000',row_id()),if(row_id() < 100,concat('000',row_id()),if(row_id() < 1000,concat('00',row_id()),if(row_id() < 10000,concat('0',row_id()),row_id()))))", + "formula_type": "text" + }, + { + "id": 59573, + "type": "single_select", + "name": "Importance", + "description": null, + "order": 11, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "select_options": [ + { + "id": 20992, + "value": "Low", + "color": "cyan", + "order": 0 + }, + { + "id": 20993, + "value": "Medium", + "color": "blue", + "order": 1 + }, + { + "id": 20994, + "value": "High", + "color": "red", + "order": 2 + } + ] + }, + { + "id": 59574, + "type": "date", + "name": "Deadline", + "description": null, + "order": 12, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "date_format": "ISO", + "date_include_time": false, + "date_time_format": "24", + "date_show_tzinfo": false, + "date_force_timezone": null + }, + { + "id": 59586, + "type": "formula", + "name": "Is urgent", + "description": null, + "order": 13, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "duration_format": null, + "date_include_time": null, + "date_show_tzinfo": null, + "number_prefix": "", + "array_formula_type": null, + "nullable": false, + "date_format": null, + "date_time_format": null, + "date_force_timezone": null, + "number_suffix": "", + "number_separator": "", + "error": null, + "number_decimal_places": null, + "formula": "field('Deadline') < today() + date_interval(concat(field('Expected workload') / 6,' days'))", + "formula_type": "boolean" + }, + { + "id": 59588, + "type": "formula", + "name": "Is high priority", + "description": null, + "order": 14, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "duration_format": null, + "date_include_time": null, + "date_show_tzinfo": null, + "number_prefix": "", + "array_formula_type": null, + "nullable": false, + "date_format": null, + "date_time_format": null, + "date_force_timezone": null, + "number_suffix": "", + "number_separator": "", + "error": null, + "number_decimal_places": null, + "formula": "field('Importance') = 'High'", + "formula_type": "boolean" + }, + { + "id": 59592, + "type": "formula", + "name": "Desired start date", + "description": null, + "order": 15, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "duration_format": null, + "date_include_time": null, + "date_show_tzinfo": null, + "number_prefix": "", + "array_formula_type": null, + "nullable": false, + "date_format": null, + "date_time_format": null, + "date_force_timezone": null, + "number_suffix": "", + "number_separator": "", + "error": null, + "number_decimal_places": null, + "formula": "if(and(field('Is urgent'),field('Is high priority')),today(),if(and(field('Is urgent'),not(field('Is high priority'))),today() + date_interval('1 day'),if(and(not(field('Is urgent')),field('Is high priority')),today() + date_interval('3 days'),'')))", + "formula_type": "text" + }, + { + "id": 59575, + "type": "number", + "name": "Expected workload", + "description": null, + "order": 16, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "number_decimal_places": 0, + "number_negative": false, + "number_prefix": "", + "number_suffix": "hours", + "number_separator": "" + }, + { + "id": 59576, + "type": "link_row", + "name": "Contractor", + "description": null, + "order": 17, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "link_row_table_id": 5680, + "link_row_related_field_id": 59584, + "link_row_limit_selection_view_id": null, + "has_related_field": true + }, + { + "id": 59589, + "type": "formula", + "name": "Required fields valid", + "description": null, + "order": 18, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "duration_format": null, + "date_include_time": null, + "date_show_tzinfo": null, + "number_prefix": "", + "array_formula_type": null, + "nullable": false, + "date_format": null, + "date_time_format": null, + "date_force_timezone": null, + "number_suffix": "", + "number_separator": "", + "error": null, + "number_decimal_places": null, + "formula": "and(and(not(isblank(field('Importance'))),not(isblank(field('Deadline')))),not(isblank(field('Expected workload'))))", + "formula_type": "boolean" + }, + { + "id": 59590, + "type": "formula", + "name": "Contractor valid", + "description": null, + "order": 19, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "duration_format": null, + "date_include_time": null, + "date_show_tzinfo": null, + "number_prefix": "", + "array_formula_type": null, + "nullable": false, + "date_format": null, + "date_time_format": null, + "date_force_timezone": null, + "number_suffix": "", + "number_separator": "", + "error": null, + "number_decimal_places": null, + "formula": "or(count(field('Contractor')) = 0,regex_replace(join(lookup('Contractor','VAT Number'),''),'(GB)?([0-9]{9})','valid') = 'valid')", + "formula_type": "boolean" + }, + { + "id": 59593, + "type": "formula", + "name": "Task is valid", + "description": null, + "order": 20, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "duration_format": null, + "date_include_time": null, + "date_show_tzinfo": null, + "number_prefix": "", + "array_formula_type": null, + "nullable": false, + "date_format": null, + "date_time_format": null, + "date_force_timezone": null, + "number_suffix": "", + "number_separator": "", + "error": null, + "number_decimal_places": null, + "formula": "and(field('Required fields valid'),field('Contractor valid'))", + "formula_type": "boolean" + }, + { + "id": 59587, + "type": "formula", + "name": "Final start date", + "description": null, + "order": 21, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "duration_format": null, + "date_include_time": false, + "date_show_tzinfo": false, + "number_prefix": "", + "array_formula_type": null, + "nullable": true, + "date_format": "ISO", + "date_time_format": "24", + "date_force_timezone": null, + "number_suffix": "", + "number_separator": "", + "error": null, + "number_decimal_places": null, + "formula": "field('Deadline') - date_interval(concat(field('Expected workload') / 6 + 1,' days'))", + "formula_type": "date" + }, + { + "id": 59577, + "type": "formula", + "name": "Details", + "description": null, + "order": 22, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "duration_format": null, + "date_include_time": null, + "date_show_tzinfo": null, + "number_prefix": "", + "array_formula_type": null, + "nullable": false, + "date_format": null, + "date_time_format": null, + "date_force_timezone": null, + "number_suffix": "", + "number_separator": "", + "error": null, + "number_decimal_places": null, + "formula": "button(concat('https://example.com/builder/1056/preview/task-details/',row_id()),'Details')", + "formula_type": "button" + }, + { + "id": 59578, + "type": "date", + "name": "Actual start date", + "description": null, + "order": 23, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "date_format": "ISO", + "date_include_time": false, + "date_time_format": "24", + "date_show_tzinfo": false, + "date_force_timezone": null + }, + { + "id": 59594, + "type": "formula", + "name": "Start task", + "description": null, + "order": 24, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "duration_format": null, + "date_include_time": null, + "date_show_tzinfo": null, + "number_prefix": "", + "array_formula_type": null, + "nullable": false, + "date_format": null, + "date_time_format": null, + "date_force_timezone": null, + "number_suffix": "", + "number_separator": "", + "error": null, + "number_decimal_places": null, + "formula": "if(field('Task is valid'),button(concat('https://n8n.example.com/webhook/set-start-date?id=',row_id()),'Start task'),button('','Task not valid'))", + "formula_type": "button" + } + ], + "views": [ + { + "id": 26415, + "type": "grid", + "name": "All tasks", + "order": 1, + "ownership_type": "collaborative", + "owned_by": "frederik@baserow.io", + "filter_type": "AND", + "filters_disabled": false, + "filters": [], + "filter_groups": [], + "sortings": [], + "group_bys": [], + "decorations": [ + { + "id": 8721, + "type": "background_color", + "value_provider_type": "conditional_color", + "value_provider_conf": { + "colors": [ + { + "id": "77f5ba06-166f-4b45-8c17-ff45cf5d4290", + "color": "light-yellow", + "filters": [ + { + "id": "2c9ff0a1-174b-47e1-8c1b-db6bc8b3f9b9", + "type": "date_is_before", + "field": 59587, + "group": null, + "value": "Europe/Brussels??today" + } + ], + "operator": "AND" + } + ] + }, + "order": 1 + } + ], + "public": false, + "row_identifier_type": "id", + "row_height_size": "medium", + "field_options": [ + { + "id": 260864, + "field_id": 59585, + "width": 200, + "hidden": false, + "order": 0, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260865, + "field_id": 59572, + "width": 200, + "hidden": true, + "order": 1, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260866, + "field_id": 59570, + "width": 171, + "hidden": false, + "order": 2, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260867, + "field_id": 59577, + "width": 138, + "hidden": false, + "order": 3, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260868, + "field_id": 59594, + "width": 200, + "hidden": false, + "order": 4, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260869, + "field_id": 59568, + "width": 152, + "hidden": false, + "order": 5, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260870, + "field_id": 59573, + "width": 143, + "hidden": false, + "order": 6, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260871, + "field_id": 59574, + "width": 141, + "hidden": false, + "order": 7, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260872, + "field_id": 59575, + "width": 200, + "hidden": false, + "order": 8, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260873, + "field_id": 59586, + "width": 125, + "hidden": false, + "order": 9, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260874, + "field_id": 59578, + "width": 200, + "hidden": false, + "order": 10, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260875, + "field_id": 59588, + "width": 200, + "hidden": false, + "order": 11, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260876, + "field_id": 59587, + "width": 200, + "hidden": false, + "order": 12, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260877, + "field_id": 59592, + "width": 200, + "hidden": false, + "order": 13, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260878, + "field_id": 59569, + "width": 554, + "hidden": false, + "order": 14, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260879, + "field_id": 59576, + "width": 200, + "hidden": false, + "order": 15, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260880, + "field_id": 59571, + "width": 200, + "hidden": false, + "order": 16, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260881, + "field_id": 59589, + "width": 200, + "hidden": false, + "order": 17, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260882, + "field_id": 59590, + "width": 200, + "hidden": false, + "order": 18, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260883, + "field_id": 59593, + "width": 200, + "hidden": false, + "order": 19, + "aggregation_type": "", + "aggregation_raw_type": "" + } + ] + }, + { + "id": 26416, + "type": "grid", + "name": "Valid tasks", + "order": 2, + "ownership_type": "collaborative", + "owned_by": "frederik@baserow.io", + "filter_type": "AND", + "filters_disabled": false, + "filters": [ + { + "id": 13949, + "field_id": 59593, + "type": "boolean", + "value": "1", + "group": null + } + ], + "filter_groups": [], + "sortings": [], + "group_bys": [], + "decorations": [], + "public": false, + "row_identifier_type": "id", + "row_height_size": "medium", + "field_options": [ + { + "id": 260884, + "field_id": 59585, + "width": 200, + "hidden": false, + "order": 0, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260885, + "field_id": 59572, + "width": 200, + "hidden": true, + "order": 1, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260886, + "field_id": 59570, + "width": 171, + "hidden": false, + "order": 2, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260887, + "field_id": 59568, + "width": 157, + "hidden": false, + "order": 3, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260888, + "field_id": 59573, + "width": 143, + "hidden": false, + "order": 4, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260889, + "field_id": 59574, + "width": 141, + "hidden": false, + "order": 5, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260890, + "field_id": 59575, + "width": 200, + "hidden": false, + "order": 6, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260891, + "field_id": 59586, + "width": 125, + "hidden": false, + "order": 7, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260892, + "field_id": 59588, + "width": 200, + "hidden": false, + "order": 8, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260893, + "field_id": 59592, + "width": 200, + "hidden": false, + "order": 9, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260894, + "field_id": 59569, + "width": 554, + "hidden": false, + "order": 10, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260895, + "field_id": 59576, + "width": 200, + "hidden": false, + "order": 11, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260896, + "field_id": 59571, + "width": 200, + "hidden": false, + "order": 12, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260897, + "field_id": 59589, + "width": 200, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260898, + "field_id": 59590, + "width": 200, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260899, + "field_id": 59593, + "width": 200, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + } + ] + }, + { + "id": 26417, + "type": "grid", + "name": "Invalid tasks", + "order": 3, + "ownership_type": "collaborative", + "owned_by": "frederik@baserow.io", + "filter_type": "AND", + "filters_disabled": false, + "filters": [ + { + "id": 13950, + "field_id": 59593, + "type": "boolean", + "value": "0", + "group": null + } + ], + "filter_groups": [], + "sortings": [], + "group_bys": [], + "decorations": [], + "public": false, + "row_identifier_type": "id", + "row_height_size": "medium", + "field_options": [ + { + "id": 260900, + "field_id": 59585, + "width": 200, + "hidden": false, + "order": 0, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260901, + "field_id": 59572, + "width": 200, + "hidden": true, + "order": 1, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260902, + "field_id": 59570, + "width": 171, + "hidden": false, + "order": 2, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260903, + "field_id": 59568, + "width": 157, + "hidden": false, + "order": 3, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260904, + "field_id": 59573, + "width": 143, + "hidden": false, + "order": 4, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260905, + "field_id": 59574, + "width": 141, + "hidden": false, + "order": 5, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260906, + "field_id": 59575, + "width": 200, + "hidden": false, + "order": 6, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260907, + "field_id": 59586, + "width": 125, + "hidden": false, + "order": 7, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260908, + "field_id": 59588, + "width": 200, + "hidden": false, + "order": 8, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260909, + "field_id": 59592, + "width": 200, + "hidden": false, + "order": 9, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260910, + "field_id": 59569, + "width": 554, + "hidden": false, + "order": 10, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260911, + "field_id": 59576, + "width": 200, + "hidden": false, + "order": 11, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260912, + "field_id": 59571, + "width": 200, + "hidden": false, + "order": 12, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260913, + "field_id": 59589, + "width": 200, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260914, + "field_id": 59590, + "width": 200, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260915, + "field_id": 59593, + "width": 200, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + } + ] + } + ], + "rows": [ + { + "id": 1, + "order": "1.00000000000000000000", + "created_on": "2025-02-05T07:48:00.081133+00:00", + "updated_on": "2025-02-05T09:59:16.521136+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59585": null, + "field_59568": 20991, + "field_59569": "Conduct onboarding for a new hire, including setting up payroll in the HR system, scheduling a welcome meeting with the team, providing access to company tools, and assigning required training materials.", + "field_59570": "Employee Onboarding", + "field_59571": null, + "field_59572": null, + "field_59573": 20993, + "field_59574": "2025-02-06", + "field_59586": null, + "field_59588": null, + "field_59592": null, + "field_59575": "12", + "field_59576": [], + "field_59589": null, + "field_59590": null, + "field_59593": null, + "field_59587": null, + "field_59577": null, + "field_59578": "2025-02-05", + "field_59594": null + }, + { + "id": 2, + "order": "2.00000000000000000000", + "created_on": "2025-02-05T07:48:00.081208+00:00", + "updated_on": "2025-02-05T09:59:12.070377+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59585": null, + "field_59568": 20990, + "field_59569": "Process and approve five supplier invoices by verifying amounts, ensuring correct account allocation, obtaining necessary approvals, and scheduling payment in the financial system.", + "field_59570": "Invoice Processing", + "field_59571": null, + "field_59572": null, + "field_59573": 20992, + "field_59574": "2025-02-20", + "field_59586": null, + "field_59588": null, + "field_59592": null, + "field_59575": "34", + "field_59576": [], + "field_59589": null, + "field_59590": null, + "field_59593": null, + "field_59587": null, + "field_59577": null, + "field_59578": null, + "field_59594": null + }, + { + "id": 3, + "order": "3.00000000000000000000", + "created_on": "2025-02-05T07:48:00.081236+00:00", + "updated_on": "2025-02-05T09:59:12.070438+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59585": null, + "field_59568": 20989, + "field_59569": "Write, design, and schedule three social media posts promoting the company\u2019s latest product update, ensuring alignment with brand guidelines and marketing strategy.", + "field_59570": "Social Media Posts", + "field_59571": null, + "field_59572": null, + "field_59573": 20993, + "field_59574": "2025-02-06", + "field_59586": null, + "field_59588": null, + "field_59592": null, + "field_59575": "53", + "field_59576": [ + 1 + ], + "field_59589": null, + "field_59590": null, + "field_59593": null, + "field_59587": null, + "field_59577": null, + "field_59578": null, + "field_59594": null + }, + { + "id": 4, + "order": "4.00000000000000000000", + "created_on": "2025-02-05T07:48:00.081262+00:00", + "updated_on": "2025-02-05T09:59:12.070496+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59585": null, + "field_59568": 20987, + "field_59569": "Resolve 15 customer support tickets by diagnosing issues, providing solutions, updating ticket statuses, and following up to ensure customer satisfaction.", + "field_59570": "Customer Ticketing", + "field_59571": null, + "field_59572": null, + "field_59573": 20994, + "field_59574": "2025-02-06", + "field_59586": null, + "field_59588": null, + "field_59592": null, + "field_59575": "6", + "field_59576": [], + "field_59589": null, + "field_59590": null, + "field_59593": null, + "field_59587": null, + "field_59577": null, + "field_59578": null, + "field_59594": null + }, + { + "id": 5, + "order": "5.00000000000000000000", + "created_on": "2025-02-05T07:48:00.081289+00:00", + "updated_on": "2025-02-05T08:40:15.433306+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59585": null, + "field_59568": 20988, + "field_59569": "Break down an upcoming project into five key tasks, assign them to team members, set deadlines in the project management system, and communicate expectations to stakeholders.", + "field_59570": "Task Assignment", + "field_59571": null, + "field_59572": null, + "field_59573": 20993, + "field_59574": "2025-02-27", + "field_59586": null, + "field_59588": null, + "field_59592": null, + "field_59575": "11", + "field_59576": [], + "field_59589": null, + "field_59590": null, + "field_59593": null, + "field_59587": null, + "field_59577": null, + "field_59578": null, + "field_59594": null + }, + { + "id": 6, + "order": "6.00000000000000000000", + "created_on": "2025-02-05T07:48:00.081315+00:00", + "updated_on": "2025-02-05T08:51:34.279762+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59585": null, + "field_59568": 20987, + "field_59569": "Install security patches and update software on all employee workstations, ensuring compatibility, testing functionality, and documenting changes for compliance.", + "field_59570": "System Updates", + "field_59571": null, + "field_59572": null, + "field_59573": 20992, + "field_59574": "2025-02-11", + "field_59586": null, + "field_59588": null, + "field_59592": null, + "field_59575": "9", + "field_59576": [ + 2 + ], + "field_59589": null, + "field_59590": null, + "field_59593": null, + "field_59587": null, + "field_59577": null, + "field_59578": null, + "field_59594": null + }, + { + "id": 7, + "order": "7.00000000000000000000", + "created_on": "2025-02-05T07:48:00.081340+00:00", + "updated_on": "2025-02-05T09:12:33.288350+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59585": null, + "field_59568": 20987, + "field_59569": "Conduct a physical inventory count of all high-value products, compare results with digital records, report discrepancies, and update the inventory management system.", + "field_59570": "Inventory Check", + "field_59571": null, + "field_59572": null, + "field_59573": 20993, + "field_59574": "2025-02-08", + "field_59586": null, + "field_59588": null, + "field_59592": null, + "field_59575": "23", + "field_59576": [ + 3 + ], + "field_59589": null, + "field_59590": null, + "field_59593": null, + "field_59587": null, + "field_59577": null, + "field_59578": null, + "field_59594": null + }, + { + "id": 8, + "order": "8.00000000000000000000", + "created_on": "2025-02-05T07:48:00.081365+00:00", + "updated_on": "2025-02-05T09:05:11.649918+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59585": null, + "field_59568": 20989, + "field_59569": "Follow up with five potential clients via email or phone, answer questions, provide additional information, and schedule meetings to move them through the sales pipeline.", + "field_59570": "Client Follow-Up", + "field_59571": null, + "field_59572": null, + "field_59573": 20994, + "field_59574": "2025-02-07", + "field_59586": null, + "field_59588": null, + "field_59592": null, + "field_59575": "45", + "field_59576": [], + "field_59589": null, + "field_59590": null, + "field_59593": null, + "field_59587": null, + "field_59577": null, + "field_59578": null, + "field_59594": null + }, + { + "id": 9, + "order": "9.00000000000000000000", + "created_on": "2025-02-05T07:48:00.081389+00:00", + "updated_on": "2025-02-05T08:51:47.995170+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59585": null, + "field_59568": 20988, + "field_59569": "Review and update one company policy by assessing current regulations, identifying gaps, revising wording, obtaining approval, and publishing the final version.", + "field_59570": "Policy Review", + "field_59571": null, + "field_59572": null, + "field_59573": 20994, + "field_59574": "2025-02-11", + "field_59586": null, + "field_59588": null, + "field_59592": null, + "field_59575": "16", + "field_59576": [ + 4 + ], + "field_59589": null, + "field_59590": null, + "field_59593": null, + "field_59587": null, + "field_59577": null, + "field_59578": null, + "field_59594": null + }, + { + "id": 10, + "order": "10.00000000000000000000", + "created_on": "2025-02-05T07:48:00.081413+00:00", + "updated_on": "2025-02-05T09:11:31.741326+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59585": null, + "field_59568": 20988, + "field_59569": "Conduct one-on-one performance reviews with three employees, discuss achievements and challenges, document feedback, and outline action steps for improvement.", + "field_59570": "Performance Reviews", + "field_59571": null, + "field_59572": null, + "field_59573": 20994, + "field_59574": "2025-02-28", + "field_59586": null, + "field_59588": null, + "field_59592": null, + "field_59575": "30", + "field_59576": [], + "field_59589": null, + "field_59590": null, + "field_59593": null, + "field_59587": null, + "field_59577": null, + "field_59578": null, + "field_59594": null + } + ], + "data_sync": null + }, + { + "id": 5680, + "name": "Contractors", + "order": 3, + "fields": [ + { + "id": 59579, + "type": "text", + "name": "Company Name", + "description": null, + "order": 0, + "primary": true, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "text_default": "" + }, + { + "id": 59580, + "type": "text", + "name": "Address", + "description": null, + "order": 1, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "text_default": "" + }, + { + "id": 59581, + "type": "email", + "name": "Email", + "description": null, + "order": 2, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false + }, + { + "id": 59582, + "type": "phone_number", + "name": "Phone", + "description": null, + "order": 3, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false + }, + { + "id": 59583, + "type": "text", + "name": "VAT Number", + "description": null, + "order": 4, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "text_default": "" + }, + { + "id": 59591, + "type": "formula", + "name": "Formula", + "description": null, + "order": 5, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "duration_format": null, + "date_include_time": null, + "date_show_tzinfo": null, + "number_prefix": "", + "array_formula_type": null, + "nullable": false, + "date_format": null, + "date_time_format": null, + "date_force_timezone": null, + "number_suffix": "", + "number_separator": "", + "error": null, + "number_decimal_places": null, + "formula": "regex_replace(field('VAT Number'),'(GB)?([0-9]{9})','')", + "formula_type": "text" + }, + { + "id": 59584, + "type": "link_row", + "name": "Tasks", + "description": null, + "order": 6, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "link_row_table_id": 5679, + "link_row_related_field_id": 59576, + "link_row_limit_selection_view_id": null, + "has_related_field": true + } + ], + "views": [ + { + "id": 26418, + "type": "grid", + "name": "Grid", + "order": 1, + "ownership_type": "collaborative", + "owned_by": "frederik@baserow.io", + "filter_type": "AND", + "filters_disabled": false, + "filters": [], + "filter_groups": [], + "sortings": [], + "group_bys": [], + "decorations": [], + "public": false, + "row_identifier_type": "id", + "row_height_size": "small", + "field_options": [ + { + "id": 260916, + "field_id": 59579, + "width": 200, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260917, + "field_id": 59580, + "width": 200, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260918, + "field_id": 59581, + "width": 200, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260919, + "field_id": 59582, + "width": 158, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260920, + "field_id": 59583, + "width": 200, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260921, + "field_id": 59584, + "width": 200, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260922, + "field_id": 59591, + "width": 200, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + } + ] + } + ], + "rows": [ + { + "id": 1, + "order": "1.00000000000000000000", + "created_on": "2025-02-05T08:42:47.025930+00:00", + "updated_on": "2025-02-05T08:50:20.819069+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59579": "BrightBuild Ltd", + "field_59580": "12 Greenway Street, London, SW1A 1AA", + "field_59581": "info@brightbuild.co.uk", + "field_59582": "+44 20 7946 0123", + "field_59583": "GB123456789", + "field_59591": null, + "field_59584": [ + 3 + ] + }, + { + "id": 2, + "order": "2.00000000000000000000", + "created_on": "2025-02-05T08:42:47.025996+00:00", + "updated_on": "2025-02-05T08:42:47.025996+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59579": "ProTech Solutions", + "field_59580": "45 Kings Road, Manchester, M1 3LD", + "field_59581": "contact@protechsolutions.co.uk", + "field_59582": "+44 161 555 6789", + "field_59583": "GB987654321", + "field_59591": null, + "field_59584": [ + 6 + ] + }, + { + "id": 3, + "order": "3.00000000000000000000", + "created_on": "2025-02-05T08:42:47.026022+00:00", + "updated_on": "2025-02-05T08:42:47.026022+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59579": "EcoElectrics UK", + "field_59580": "78 Solar Avenue, Birmingham, B2 4QA", + "field_59581": "support@ecoelectrics.co.uk", + "field_59582": "+44 121 432 8765", + "field_59583": "GB456123789", + "field_59591": null, + "field_59584": [ + 7 + ] + }, + { + "id": 4, + "order": "4.00000000000000000000", + "created_on": "2025-02-05T08:42:47.026045+00:00", + "updated_on": "2025-02-05T08:42:47.026045+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59579": "SwiftLogistics", + "field_59580": "22 Dockside Lane, Liverpool, L3 1AB", + "field_59581": "admin@swiftlogistics.co.uk", + "field_59582": "+44 151 789 6543", + "field_59583": "GB321654987", + "field_59591": null, + "field_59584": [ + 9 + ] + }, + { + "id": 5, + "order": "5.00000000000000000000", + "created_on": "2025-02-05T08:42:47.026069+00:00", + "updated_on": "2025-02-05T08:42:47.026069+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59579": "Regal Interiors", + "field_59580": "89 High Street, Edinburgh, EH2 4PH", + "field_59581": "sales@regalinteriors.co.uk", + "field_59582": "+44 131 246 9870", + "field_59583": "GB654987321", + "field_59591": null, + "field_59584": [] + } + ], + "data_sync": null + } + ] + }, + { + "id": 2163, + "name": "Case 7 - Task Management", + "order": 7, + "type": "database", + "tables": [ + { + "id": 5681, + "name": "Tasks", + "order": 2, + "fields": [ + { + "id": 59615, + "type": "formula", + "name": "Name", + "description": null, + "order": 10, + "primary": true, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "duration_format": null, + "date_include_time": null, + "date_show_tzinfo": null, + "number_prefix": "", + "array_formula_type": null, + "nullable": false, + "date_format": null, + "date_time_format": null, + "date_force_timezone": null, + "number_suffix": "", + "number_separator": "", + "error": null, + "number_decimal_places": null, + "formula": "concat(left(upper(totext(field('Category'))),3),'-',year(field('Created on')),'-',field('ID'))", + "formula_type": "text" + }, + { + "id": 59595, + "type": "single_select", + "name": "Category", + "description": null, + "order": 1, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "select_options": [ + { + "id": 20995, + "value": "Operations", + "color": "darker-gray", + "order": 0 + }, + { + "id": 20996, + "value": "Management", + "color": "dark-brown", + "order": 1 + }, + { + "id": 20997, + "value": "Marketing", + "color": "light-cyan", + "order": 2 + }, + { + "id": 20998, + "value": "Finance", + "color": "darker-yellow", + "order": 3 + }, + { + "id": 20999, + "value": "Human Resources", + "color": "light-yellow", + "order": 4 + } + ] + }, + { + "id": 59596, + "type": "text", + "name": "Description", + "description": null, + "order": 2, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "text_default": "" + }, + { + "id": 59597, + "type": "text", + "name": "Title", + "description": null, + "order": 3, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "text_default": "" + }, + { + "id": 59598, + "type": "created_on", + "name": "Created on", + "description": null, + "order": 8, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "date_format": "ISO", + "date_include_time": false, + "date_time_format": "24", + "date_show_tzinfo": false, + "date_force_timezone": null + }, + { + "id": 59599, + "type": "formula", + "name": "ID", + "description": null, + "order": 9, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "duration_format": null, + "date_include_time": null, + "date_show_tzinfo": null, + "number_prefix": "", + "array_formula_type": null, + "nullable": false, + "date_format": null, + "date_time_format": null, + "date_force_timezone": null, + "number_suffix": "", + "number_separator": "", + "error": null, + "number_decimal_places": null, + "formula": "if(row_id() < 10,concat('0000',row_id()),if(row_id() < 100,concat('000',row_id()),if(row_id() < 1000,concat('00',row_id()),if(row_id() < 10000,concat('0',row_id()),row_id()))))", + "formula_type": "text" + }, + { + "id": 59600, + "type": "single_select", + "name": "Importance", + "description": null, + "order": 11, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "select_options": [ + { + "id": 21000, + "value": "Low", + "color": "cyan", + "order": 0 + }, + { + "id": 21001, + "value": "Medium", + "color": "blue", + "order": 1 + }, + { + "id": 21002, + "value": "High", + "color": "red", + "order": 2 + } + ] + }, + { + "id": 59601, + "type": "date", + "name": "Deadline", + "description": null, + "order": 12, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "date_format": "ISO", + "date_include_time": false, + "date_time_format": "24", + "date_show_tzinfo": false, + "date_force_timezone": null + }, + { + "id": 59616, + "type": "formula", + "name": "Is urgent", + "description": null, + "order": 13, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "duration_format": null, + "date_include_time": null, + "date_show_tzinfo": null, + "number_prefix": "", + "array_formula_type": null, + "nullable": false, + "date_format": null, + "date_time_format": null, + "date_force_timezone": null, + "number_suffix": "", + "number_separator": "", + "error": null, + "number_decimal_places": null, + "formula": "field('Deadline') < today() + date_interval(concat(field('Expected workload') / 6,' days'))", + "formula_type": "boolean" + }, + { + "id": 59618, + "type": "formula", + "name": "Is high priority", + "description": null, + "order": 14, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "duration_format": null, + "date_include_time": null, + "date_show_tzinfo": null, + "number_prefix": "", + "array_formula_type": null, + "nullable": false, + "date_format": null, + "date_time_format": null, + "date_force_timezone": null, + "number_suffix": "", + "number_separator": "", + "error": null, + "number_decimal_places": null, + "formula": "field('Importance') = 'High'", + "formula_type": "boolean" + }, + { + "id": 59624, + "type": "formula", + "name": "Desired start date", + "description": null, + "order": 15, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "duration_format": null, + "date_include_time": null, + "date_show_tzinfo": null, + "number_prefix": "", + "array_formula_type": null, + "nullable": false, + "date_format": null, + "date_time_format": null, + "date_force_timezone": null, + "number_suffix": "", + "number_separator": "", + "error": null, + "number_decimal_places": null, + "formula": "if(and(field('Is urgent'),field('Is high priority')),today(),if(and(field('Is urgent'),not(field('Is high priority'))),today() + date_interval('1 day'),if(and(not(field('Is urgent')),field('Is high priority')),today() + date_interval('3 days'),'')))", + "formula_type": "text" + }, + { + "id": 59602, + "type": "number", + "name": "Expected workload", + "description": null, + "order": 16, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "number_decimal_places": 0, + "number_negative": false, + "number_prefix": "", + "number_suffix": "hours", + "number_separator": "" + }, + { + "id": 59603, + "type": "link_row", + "name": "Contractor", + "description": null, + "order": 17, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "link_row_table_id": 5682, + "link_row_related_field_id": 59612, + "link_row_limit_selection_view_id": null, + "has_related_field": true + }, + { + "id": 59619, + "type": "formula", + "name": "Required fields valid", + "description": null, + "order": 18, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "duration_format": null, + "date_include_time": null, + "date_show_tzinfo": null, + "number_prefix": "", + "array_formula_type": null, + "nullable": false, + "date_format": null, + "date_time_format": null, + "date_force_timezone": null, + "number_suffix": "", + "number_separator": "", + "error": null, + "number_decimal_places": null, + "formula": "and(and(not(isblank(field('Importance'))),not(isblank(field('Deadline')))),not(isblank(field('Expected workload'))))", + "formula_type": "boolean" + }, + { + "id": 59620, + "type": "formula", + "name": "Contractor valid", + "description": null, + "order": 19, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "duration_format": null, + "date_include_time": null, + "date_show_tzinfo": null, + "number_prefix": "", + "array_formula_type": null, + "nullable": false, + "date_format": null, + "date_time_format": null, + "date_force_timezone": null, + "number_suffix": "", + "number_separator": "", + "error": null, + "number_decimal_places": null, + "formula": "or(count(field('Contractor')) = 0,regex_replace(join(lookup('Contractor','VAT Number'),''),'(GB)?([0-9]{9})','valid') = 'valid')", + "formula_type": "boolean" + }, + { + "id": 59625, + "type": "formula", + "name": "Task is valid", + "description": null, + "order": 20, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "duration_format": null, + "date_include_time": null, + "date_show_tzinfo": null, + "number_prefix": "", + "array_formula_type": null, + "nullable": false, + "date_format": null, + "date_time_format": null, + "date_force_timezone": null, + "number_suffix": "", + "number_separator": "", + "error": null, + "number_decimal_places": null, + "formula": "and(field('Required fields valid'),field('Contractor valid'))", + "formula_type": "boolean" + }, + { + "id": 59617, + "type": "formula", + "name": "Final start date", + "description": null, + "order": 21, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "duration_format": null, + "date_include_time": false, + "date_show_tzinfo": false, + "number_prefix": "", + "array_formula_type": null, + "nullable": true, + "date_format": "ISO", + "date_time_format": "24", + "date_force_timezone": null, + "number_suffix": "", + "number_separator": "", + "error": null, + "number_decimal_places": null, + "formula": "field('Deadline') - date_interval(concat(field('Expected workload') / 6 + 1,' days'))", + "formula_type": "date" + }, + { + "id": 59604, + "type": "formula", + "name": "Details", + "description": null, + "order": 22, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "duration_format": null, + "date_include_time": null, + "date_show_tzinfo": null, + "number_prefix": "", + "array_formula_type": null, + "nullable": false, + "date_format": null, + "date_time_format": null, + "date_force_timezone": null, + "number_suffix": "", + "number_separator": "", + "error": null, + "number_decimal_places": null, + "formula": "button(concat('https://example.com/builder/1059/preview/task-details/',row_id()),'Details')", + "formula_type": "button" + }, + { + "id": 59605, + "type": "date", + "name": "Actual start date", + "description": null, + "order": 23, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "date_format": "ISO", + "date_include_time": false, + "date_time_format": "24", + "date_show_tzinfo": false, + "date_force_timezone": null + }, + { + "id": 59626, + "type": "formula", + "name": "Start task", + "description": null, + "order": 24, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "duration_format": null, + "date_include_time": null, + "date_show_tzinfo": null, + "number_prefix": "", + "array_formula_type": null, + "nullable": false, + "date_format": null, + "date_time_format": null, + "date_force_timezone": null, + "number_suffix": "", + "number_separator": "", + "error": null, + "number_decimal_places": null, + "formula": "if(field('Task is valid'),button(concat('https://n8n.cloudron.getbaserow.com/webhook/set-start-date?id=',row_id()),'Start task'),button('','Task not valid'))", + "formula_type": "button" + }, + { + "id": 59606, + "type": "link_row", + "name": "Assets", + "description": null, + "order": 25, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "link_row_table_id": 5683, + "link_row_related_field_id": 59614, + "link_row_limit_selection_view_id": null, + "has_related_field": true + } + ], + "views": [ + { + "id": 26419, + "type": "grid", + "name": "All tasks", + "order": 1, + "ownership_type": "collaborative", + "owned_by": "frederik@baserow.io", + "filter_type": "AND", + "filters_disabled": false, + "filters": [], + "filter_groups": [], + "sortings": [], + "group_bys": [], + "decorations": [ + { + "id": 8722, + "type": "background_color", + "value_provider_type": "conditional_color", + "value_provider_conf": { + "colors": [ + { + "id": "77f5ba06-166f-4b45-8c17-ff45cf5d4290", + "color": "light-yellow", + "filters": [ + { + "id": "2c9ff0a1-174b-47e1-8c1b-db6bc8b3f9b9", + "type": "date_is_before", + "field": 59617, + "group": null, + "value": "Europe/Brussels??today" + } + ], + "operator": "AND" + } + ] + }, + "order": 1 + } + ], + "public": false, + "row_identifier_type": "id", + "row_height_size": "medium", + "field_options": [ + { + "id": 260923, + "field_id": 59615, + "width": 200, + "hidden": false, + "order": 0, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260924, + "field_id": 59599, + "width": 200, + "hidden": true, + "order": 1, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260925, + "field_id": 59597, + "width": 171, + "hidden": false, + "order": 2, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260926, + "field_id": 59604, + "width": 138, + "hidden": false, + "order": 3, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260927, + "field_id": 59626, + "width": 200, + "hidden": true, + "order": 4, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260928, + "field_id": 59595, + "width": 152, + "hidden": false, + "order": 5, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260929, + "field_id": 59600, + "width": 143, + "hidden": false, + "order": 6, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260930, + "field_id": 59601, + "width": 141, + "hidden": false, + "order": 7, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260931, + "field_id": 59602, + "width": 200, + "hidden": false, + "order": 8, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260932, + "field_id": 59616, + "width": 125, + "hidden": false, + "order": 9, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260933, + "field_id": 59605, + "width": 200, + "hidden": false, + "order": 10, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260934, + "field_id": 59618, + "width": 200, + "hidden": false, + "order": 11, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260935, + "field_id": 59617, + "width": 200, + "hidden": false, + "order": 12, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260936, + "field_id": 59624, + "width": 200, + "hidden": false, + "order": 13, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260937, + "field_id": 59596, + "width": 554, + "hidden": false, + "order": 14, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260938, + "field_id": 59603, + "width": 200, + "hidden": false, + "order": 15, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260939, + "field_id": 59598, + "width": 200, + "hidden": false, + "order": 16, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260940, + "field_id": 59619, + "width": 200, + "hidden": false, + "order": 17, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260941, + "field_id": 59620, + "width": 200, + "hidden": false, + "order": 18, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260942, + "field_id": 59625, + "width": 200, + "hidden": false, + "order": 19, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260943, + "field_id": 59606, + "width": 200, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + } + ] + }, + { + "id": 26420, + "type": "grid", + "name": "Valid tasks", + "order": 2, + "ownership_type": "collaborative", + "owned_by": "frederik@baserow.io", + "filter_type": "AND", + "filters_disabled": false, + "filters": [ + { + "id": 13951, + "field_id": 59625, + "type": "boolean", + "value": "1", + "group": null + } + ], + "filter_groups": [], + "sortings": [], + "group_bys": [], + "decorations": [], + "public": false, + "row_identifier_type": "id", + "row_height_size": "medium", + "field_options": [ + { + "id": 260944, + "field_id": 59615, + "width": 200, + "hidden": false, + "order": 0, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260945, + "field_id": 59599, + "width": 200, + "hidden": true, + "order": 1, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260946, + "field_id": 59597, + "width": 171, + "hidden": false, + "order": 2, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260947, + "field_id": 59595, + "width": 157, + "hidden": false, + "order": 3, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260948, + "field_id": 59600, + "width": 143, + "hidden": false, + "order": 4, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260949, + "field_id": 59601, + "width": 141, + "hidden": false, + "order": 5, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260950, + "field_id": 59602, + "width": 200, + "hidden": false, + "order": 6, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260951, + "field_id": 59616, + "width": 125, + "hidden": false, + "order": 7, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260952, + "field_id": 59618, + "width": 200, + "hidden": false, + "order": 8, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260953, + "field_id": 59624, + "width": 200, + "hidden": false, + "order": 9, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260954, + "field_id": 59596, + "width": 554, + "hidden": false, + "order": 10, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260955, + "field_id": 59603, + "width": 200, + "hidden": false, + "order": 11, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260956, + "field_id": 59598, + "width": 200, + "hidden": false, + "order": 12, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260957, + "field_id": 59619, + "width": 200, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260958, + "field_id": 59620, + "width": 200, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260959, + "field_id": 59625, + "width": 200, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + } + ] + }, + { + "id": 26421, + "type": "grid", + "name": "Invalid tasks", + "order": 3, + "ownership_type": "collaborative", + "owned_by": "frederik@baserow.io", + "filter_type": "AND", + "filters_disabled": false, + "filters": [ + { + "id": 13952, + "field_id": 59625, + "type": "boolean", + "value": "0", + "group": null + } + ], + "filter_groups": [], + "sortings": [], + "group_bys": [], + "decorations": [], + "public": false, + "row_identifier_type": "id", + "row_height_size": "medium", + "field_options": [ + { + "id": 260960, + "field_id": 59615, + "width": 200, + "hidden": false, + "order": 0, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260961, + "field_id": 59599, + "width": 200, + "hidden": true, + "order": 1, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260962, + "field_id": 59597, + "width": 171, + "hidden": false, + "order": 2, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260963, + "field_id": 59595, + "width": 157, + "hidden": false, + "order": 3, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260964, + "field_id": 59600, + "width": 143, + "hidden": false, + "order": 4, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260965, + "field_id": 59601, + "width": 141, + "hidden": false, + "order": 5, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260966, + "field_id": 59602, + "width": 200, + "hidden": false, + "order": 6, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260967, + "field_id": 59616, + "width": 125, + "hidden": false, + "order": 7, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260968, + "field_id": 59618, + "width": 200, + "hidden": false, + "order": 8, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260969, + "field_id": 59624, + "width": 200, + "hidden": false, + "order": 9, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260970, + "field_id": 59596, + "width": 554, + "hidden": false, + "order": 10, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260971, + "field_id": 59603, + "width": 200, + "hidden": false, + "order": 11, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260972, + "field_id": 59598, + "width": 200, + "hidden": false, + "order": 12, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260973, + "field_id": 59619, + "width": 200, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260974, + "field_id": 59620, + "width": 200, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260975, + "field_id": 59625, + "width": 200, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + } + ] + } + ], + "rows": [ + { + "id": 1, + "order": "1.00000000000000000000", + "created_on": "2025-02-05T07:48:00.081133+00:00", + "updated_on": "2025-02-05T09:59:16.521136+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59615": null, + "field_59595": 20999, + "field_59596": "Conduct onboarding for a new hire, including setting up payroll in the HR system, scheduling a welcome meeting with the team, providing access to company tools, and assigning required training materials.", + "field_59597": "Employee Onboarding", + "field_59598": null, + "field_59599": null, + "field_59600": 21001, + "field_59601": "2025-02-06", + "field_59616": null, + "field_59618": null, + "field_59624": null, + "field_59602": "12", + "field_59603": [], + "field_59619": null, + "field_59620": null, + "field_59625": null, + "field_59617": null, + "field_59604": null, + "field_59605": "2025-02-05", + "field_59626": null, + "field_59606": [] + }, + { + "id": 2, + "order": "2.00000000000000000000", + "created_on": "2025-02-05T07:48:00.081208+00:00", + "updated_on": "2025-02-05T09:59:12.070377+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59615": null, + "field_59595": 20998, + "field_59596": "Process and approve five supplier invoices by verifying amounts, ensuring correct account allocation, obtaining necessary approvals, and scheduling payment in the financial system.", + "field_59597": "Invoice Processing", + "field_59598": null, + "field_59599": null, + "field_59600": 21000, + "field_59601": "2025-02-20", + "field_59616": null, + "field_59618": null, + "field_59624": null, + "field_59602": "34", + "field_59603": [], + "field_59619": null, + "field_59620": null, + "field_59625": null, + "field_59617": null, + "field_59604": null, + "field_59605": null, + "field_59626": null, + "field_59606": [] + }, + { + "id": 3, + "order": "3.00000000000000000000", + "created_on": "2025-02-05T07:48:00.081236+00:00", + "updated_on": "2025-02-05T09:59:12.070438+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59615": null, + "field_59595": 20997, + "field_59596": "Write, design, and schedule three social media posts promoting the company\u2019s latest product update, ensuring alignment with brand guidelines and marketing strategy.", + "field_59597": "Social Media Posts", + "field_59598": null, + "field_59599": null, + "field_59600": 21001, + "field_59601": "2025-02-06", + "field_59616": null, + "field_59618": null, + "field_59624": null, + "field_59602": "53", + "field_59603": [ + 1 + ], + "field_59619": null, + "field_59620": null, + "field_59625": null, + "field_59617": null, + "field_59604": null, + "field_59605": null, + "field_59626": null, + "field_59606": [ + 5, + 6, + 7, + 8, + 9 + ] + }, + { + "id": 4, + "order": "4.00000000000000000000", + "created_on": "2025-02-05T07:48:00.081262+00:00", + "updated_on": "2025-02-05T09:59:12.070496+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59615": null, + "field_59595": 20995, + "field_59596": "Resolve 15 customer support tickets by diagnosing issues, providing solutions, updating ticket statuses, and following up to ensure customer satisfaction.", + "field_59597": "Customer Ticketing", + "field_59598": null, + "field_59599": null, + "field_59600": 21002, + "field_59601": "2025-02-06", + "field_59616": null, + "field_59618": null, + "field_59624": null, + "field_59602": "6", + "field_59603": [], + "field_59619": null, + "field_59620": null, + "field_59625": null, + "field_59617": null, + "field_59604": null, + "field_59605": null, + "field_59626": null, + "field_59606": [] + }, + { + "id": 5, + "order": "5.00000000000000000000", + "created_on": "2025-02-05T07:48:00.081289+00:00", + "updated_on": "2025-02-05T08:40:15.433306+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59615": null, + "field_59595": 20996, + "field_59596": "Break down an upcoming project into five key tasks, assign them to team members, set deadlines in the project management system, and communicate expectations to stakeholders.", + "field_59597": "Task Assignment", + "field_59598": null, + "field_59599": null, + "field_59600": 21001, + "field_59601": "2025-02-27", + "field_59616": null, + "field_59618": null, + "field_59624": null, + "field_59602": "11", + "field_59603": [], + "field_59619": null, + "field_59620": null, + "field_59625": null, + "field_59617": null, + "field_59604": null, + "field_59605": null, + "field_59626": null, + "field_59606": [] + }, + { + "id": 6, + "order": "6.00000000000000000000", + "created_on": "2025-02-05T07:48:00.081315+00:00", + "updated_on": "2025-02-05T08:51:34.279762+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59615": null, + "field_59595": 20995, + "field_59596": "Install security patches and update software on all employee workstations, ensuring compatibility, testing functionality, and documenting changes for compliance.", + "field_59597": "System Updates", + "field_59598": null, + "field_59599": null, + "field_59600": 21000, + "field_59601": "2025-02-11", + "field_59616": null, + "field_59618": null, + "field_59624": null, + "field_59602": "9", + "field_59603": [ + 2 + ], + "field_59619": null, + "field_59620": null, + "field_59625": null, + "field_59617": null, + "field_59604": null, + "field_59605": null, + "field_59626": null, + "field_59606": [ + 1 + ] + }, + { + "id": 7, + "order": "7.00000000000000000000", + "created_on": "2025-02-05T07:48:00.081340+00:00", + "updated_on": "2025-02-05T09:12:33.288350+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59615": null, + "field_59595": 20995, + "field_59596": "Conduct a physical inventory count of all high-value products, compare results with digital records, report discrepancies, and update the inventory management system.", + "field_59597": "Inventory Check", + "field_59598": null, + "field_59599": null, + "field_59600": 21001, + "field_59601": "2025-02-08", + "field_59616": null, + "field_59618": null, + "field_59624": null, + "field_59602": "23", + "field_59603": [ + 3 + ], + "field_59619": null, + "field_59620": null, + "field_59625": null, + "field_59617": null, + "field_59604": null, + "field_59605": null, + "field_59626": null, + "field_59606": [ + 2, + 3, + 4 + ] + }, + { + "id": 8, + "order": "8.00000000000000000000", + "created_on": "2025-02-05T07:48:00.081365+00:00", + "updated_on": "2025-02-05T09:05:11.649918+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59615": null, + "field_59595": 20997, + "field_59596": "Follow up with five potential clients via email or phone, answer questions, provide additional information, and schedule meetings to move them through the sales pipeline.", + "field_59597": "Client Follow-Up", + "field_59598": null, + "field_59599": null, + "field_59600": 21002, + "field_59601": "2025-02-07", + "field_59616": null, + "field_59618": null, + "field_59624": null, + "field_59602": "45", + "field_59603": [], + "field_59619": null, + "field_59620": null, + "field_59625": null, + "field_59617": null, + "field_59604": null, + "field_59605": null, + "field_59626": null, + "field_59606": [] + }, + { + "id": 9, + "order": "9.00000000000000000000", + "created_on": "2025-02-05T07:48:00.081389+00:00", + "updated_on": "2025-02-05T08:51:47.995170+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59615": null, + "field_59595": 20996, + "field_59596": "Review and update one company policy by assessing current regulations, identifying gaps, revising wording, obtaining approval, and publishing the final version.", + "field_59597": "Policy Review", + "field_59598": null, + "field_59599": null, + "field_59600": 21002, + "field_59601": "2025-02-11", + "field_59616": null, + "field_59618": null, + "field_59624": null, + "field_59602": "16", + "field_59603": [ + 4 + ], + "field_59619": null, + "field_59620": null, + "field_59625": null, + "field_59617": null, + "field_59604": null, + "field_59605": null, + "field_59626": null, + "field_59606": [] + }, + { + "id": 10, + "order": "10.00000000000000000000", + "created_on": "2025-02-05T07:48:00.081413+00:00", + "updated_on": "2025-02-05T09:11:31.741326+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59615": null, + "field_59595": 20996, + "field_59596": "Conduct one-on-one performance reviews with three employees, discuss achievements and challenges, document feedback, and outline action steps for improvement.", + "field_59597": "Performance Reviews", + "field_59598": null, + "field_59599": null, + "field_59600": 21002, + "field_59601": "2025-02-28", + "field_59616": null, + "field_59618": null, + "field_59624": null, + "field_59602": "30", + "field_59603": [], + "field_59619": null, + "field_59620": null, + "field_59625": null, + "field_59617": null, + "field_59604": null, + "field_59605": null, + "field_59626": null, + "field_59606": [] + } + ], + "data_sync": null + }, + { + "id": 5682, + "name": "Contractors", + "order": 3, + "fields": [ + { + "id": 59607, + "type": "text", + "name": "Company Name", + "description": null, + "order": 0, + "primary": true, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "text_default": "" + }, + { + "id": 59608, + "type": "text", + "name": "Address", + "description": null, + "order": 1, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "text_default": "" + }, + { + "id": 59609, + "type": "email", + "name": "Email", + "description": null, + "order": 2, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false + }, + { + "id": 59610, + "type": "phone_number", + "name": "Phone", + "description": null, + "order": 3, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false + }, + { + "id": 59611, + "type": "text", + "name": "VAT Number", + "description": null, + "order": 4, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "text_default": "" + }, + { + "id": 59621, + "type": "formula", + "name": "Formula", + "description": null, + "order": 5, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "duration_format": null, + "date_include_time": null, + "date_show_tzinfo": null, + "number_prefix": "", + "array_formula_type": null, + "nullable": false, + "date_format": null, + "date_time_format": null, + "date_force_timezone": null, + "number_suffix": "", + "number_separator": "", + "error": null, + "number_decimal_places": null, + "formula": "regex_replace(field('VAT Number'),'(GB)?([0-9]{9})','')", + "formula_type": "text" + }, + { + "id": 59612, + "type": "link_row", + "name": "Tasks", + "description": null, + "order": 6, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "link_row_table_id": 5681, + "link_row_related_field_id": 59603, + "link_row_limit_selection_view_id": null, + "has_related_field": true + } + ], + "views": [ + { + "id": 26422, + "type": "grid", + "name": "All contractors", + "order": 1, + "ownership_type": "collaborative", + "owned_by": "frederik@baserow.io", + "filter_type": "AND", + "filters_disabled": false, + "filters": [], + "filter_groups": [], + "sortings": [], + "group_bys": [], + "decorations": [], + "public": false, + "row_identifier_type": "id", + "row_height_size": "small", + "field_options": [ + { + "id": 260976, + "field_id": 59607, + "width": 200, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260977, + "field_id": 59608, + "width": 200, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260978, + "field_id": 59609, + "width": 200, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260979, + "field_id": 59610, + "width": 158, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260980, + "field_id": 59611, + "width": 200, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260981, + "field_id": 59612, + "width": 200, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260982, + "field_id": 59621, + "width": 200, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + } + ] + } + ], + "rows": [ + { + "id": 1, + "order": "1.00000000000000000000", + "created_on": "2025-02-05T08:42:47.025930+00:00", + "updated_on": "2025-02-05T08:50:20.819069+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59607": "BrightBuild Ltd", + "field_59608": "12 Greenway Street, London, SW1A 1AA", + "field_59609": "info@brightbuild.co.uk", + "field_59610": "+44 20 7946 0123", + "field_59611": "GB123456789", + "field_59621": null, + "field_59612": [ + 3 + ] + }, + { + "id": 2, + "order": "2.00000000000000000000", + "created_on": "2025-02-05T08:42:47.025996+00:00", + "updated_on": "2025-02-05T08:42:47.025996+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59607": "ProTech Solutions", + "field_59608": "45 Kings Road, Manchester, M1 3LD", + "field_59609": "contact@protechsolutions.co.uk", + "field_59610": "+44 161 555 6789", + "field_59611": "GB987654321", + "field_59621": null, + "field_59612": [ + 6 + ] + }, + { + "id": 3, + "order": "3.00000000000000000000", + "created_on": "2025-02-05T08:42:47.026022+00:00", + "updated_on": "2025-02-05T08:42:47.026022+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59607": "EcoElectrics UK", + "field_59608": "78 Solar Avenue, Birmingham, B2 4QA", + "field_59609": "support@ecoelectrics.co.uk", + "field_59610": "+44 121 432 8765", + "field_59611": "GB456123789", + "field_59621": null, + "field_59612": [ + 7 + ] + }, + { + "id": 4, + "order": "4.00000000000000000000", + "created_on": "2025-02-05T08:42:47.026045+00:00", + "updated_on": "2025-02-05T08:42:47.026045+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59607": "SwiftLogistics", + "field_59608": "22 Dockside Lane, Liverpool, L3 1AB", + "field_59609": "admin@swiftlogistics.co.uk", + "field_59610": "+44 151 789 6543", + "field_59611": "GB321654987", + "field_59621": null, + "field_59612": [ + 9 + ] + }, + { + "id": 5, + "order": "5.00000000000000000000", + "created_on": "2025-02-05T08:42:47.026069+00:00", + "updated_on": "2025-02-05T08:42:47.026069+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59607": "Regal Interiors", + "field_59608": "89 High Street, Edinburgh, EH2 4PH", + "field_59609": "sales@regalinteriors.co.uk", + "field_59610": "+44 131 246 9870", + "field_59611": "GB654987321", + "field_59621": null, + "field_59612": [] + } + ], + "data_sync": null + }, + { + "id": 5683, + "name": "Asset repository", + "order": 4, + "fields": [ + { + "id": 59622, + "type": "formula", + "name": "Name", + "description": null, + "order": 0, + "primary": true, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "duration_format": null, + "date_include_time": null, + "date_show_tzinfo": null, + "number_prefix": "", + "array_formula_type": null, + "nullable": true, + "date_format": null, + "date_time_format": null, + "date_force_timezone": null, + "number_suffix": "", + "number_separator": "", + "error": null, + "number_decimal_places": null, + "formula": "get_file_visible_name(index(field('File'),0))", + "formula_type": "text" + }, + { + "id": 59613, + "type": "file", + "name": "File", + "description": null, + "order": 1, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false + }, + { + "id": 59623, + "type": "formula", + "name": "is Image", + "description": null, + "order": 2, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "duration_format": null, + "date_include_time": null, + "date_show_tzinfo": null, + "number_prefix": "", + "array_formula_type": null, + "nullable": true, + "date_format": null, + "date_time_format": null, + "date_force_timezone": null, + "number_suffix": "", + "number_separator": "", + "error": null, + "number_decimal_places": null, + "formula": "is_image(index(field('File'),0))", + "formula_type": "boolean" + }, + { + "id": 59614, + "type": "link_row", + "name": "Task", + "description": null, + "order": 3, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "link_row_table_id": 5681, + "link_row_related_field_id": 59606, + "link_row_limit_selection_view_id": null, + "has_related_field": true + } + ], + "views": [ + { + "id": 26423, + "type": "grid", + "name": "All assets", + "order": 1, + "ownership_type": "collaborative", + "owned_by": "frederik@baserow.io", + "filter_type": "AND", + "filters_disabled": false, + "filters": [], + "filter_groups": [], + "sortings": [], + "group_bys": [], + "decorations": [], + "public": false, + "row_identifier_type": "id", + "row_height_size": "small", + "field_options": [ + { + "id": 260983, + "field_id": 59622, + "width": 200, + "hidden": false, + "order": 0, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260984, + "field_id": 59614, + "width": 200, + "hidden": false, + "order": 1, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260985, + "field_id": 59613, + "width": 192, + "hidden": false, + "order": 2, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260986, + "field_id": 59623, + "width": 185, + "hidden": false, + "order": 3, + "aggregation_type": "", + "aggregation_raw_type": "" + } + ] + }, + { + "id": 26424, + "type": "grid", + "name": "Image assets", + "order": 2, + "ownership_type": "collaborative", + "owned_by": "frederik@baserow.io", + "filter_type": "AND", + "filters_disabled": false, + "filters": [ + { + "id": 13953, + "field_id": 59623, + "type": "boolean", + "value": "1", + "group": null + } + ], + "filter_groups": [], + "sortings": [], + "group_bys": [], + "decorations": [], + "public": false, + "row_identifier_type": "id", + "row_height_size": "small", + "field_options": [ + { + "id": 260987, + "field_id": 59622, + "width": 200, + "hidden": false, + "order": 0, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260988, + "field_id": 59614, + "width": 200, + "hidden": false, + "order": 1, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260989, + "field_id": 59613, + "width": 192, + "hidden": false, + "order": 2, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260990, + "field_id": 59623, + "width": 185, + "hidden": false, + "order": 3, + "aggregation_type": "", + "aggregation_raw_type": "" + } + ] + }, + { + "id": 26425, + "type": "grid", + "name": "Other assets", + "order": 3, + "ownership_type": "collaborative", + "owned_by": "frederik@baserow.io", + "filter_type": "AND", + "filters_disabled": false, + "filters": [ + { + "id": 13954, + "field_id": 59623, + "type": "boolean", + "value": "0", + "group": null + } + ], + "filter_groups": [], + "sortings": [], + "group_bys": [], + "decorations": [], + "public": false, + "row_identifier_type": "id", + "row_height_size": "small", + "field_options": [ + { + "id": 260991, + "field_id": 59622, + "width": 200, + "hidden": false, + "order": 0, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260992, + "field_id": 59614, + "width": 200, + "hidden": false, + "order": 1, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260993, + "field_id": 59613, + "width": 192, + "hidden": false, + "order": 2, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260994, + "field_id": 59623, + "width": 185, + "hidden": false, + "order": 3, + "aggregation_type": "", + "aggregation_raw_type": "" + } + ] + }, + { + "id": 26426, + "type": "form", + "name": "Add new asset", + "order": 4, + "ownership_type": "collaborative", + "owned_by": "frederik@baserow.io", + "public": false, + "title": "", + "description": "", + "cover_image": null, + "logo_image": null, + "submit_text": "Submit", + "submit_action": "MESSAGE", + "submit_action_message": "The asset has been added", + "submit_action_redirect_url": "", + "field_options": [ + { + "id": 25238, + "field_id": 59614, + "name": "", + "description": "The task related to the asset", + "enabled": true, + "required": true, + "order": 0, + "show_when_matching_conditions": false, + "condition_type": "AND", + "conditions": [], + "condition_groups": [], + "field_component": "default", + "include_all_select_options": true, + "allowed_select_options": [] + }, + { + "id": 25239, + "field_id": 59613, + "name": "", + "description": "Select a single file to be attached to the task", + "enabled": true, + "required": true, + "order": 1, + "show_when_matching_conditions": false, + "condition_type": "AND", + "conditions": [], + "condition_groups": [], + "field_component": "default", + "include_all_select_options": true, + "allowed_select_options": [] + }, + { + "id": 25240, + "field_id": 59622, + "name": "", + "description": "", + "enabled": false, + "required": true, + "order": 2, + "show_when_matching_conditions": false, + "condition_type": "AND", + "conditions": [], + "condition_groups": [], + "field_component": "default", + "include_all_select_options": true, + "allowed_select_options": [] + }, + { + "id": 25241, + "field_id": 59623, + "name": "", + "description": "", + "enabled": false, + "required": true, + "order": 3, + "show_when_matching_conditions": false, + "condition_type": "AND", + "conditions": [], + "condition_groups": [], + "field_component": "default", + "include_all_select_options": true, + "allowed_select_options": [] + } + ] + } + ], + "rows": [ + { + "id": 1, + "order": "1.00000000000000000000", + "created_on": "2025-02-05T10:02:37.395368+00:00", + "updated_on": "2025-02-05T10:13:44.901137+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59622": null, + "field_59613": [ + { + "name": "WnJgHQmzjyeKVF2EWnOw3JAp0fPIEgfB_e7fa567aac5fdffb5569ad7301a186889981b3f504d39250a6aebbce0ac452d6.pdf", + "visible_name": "contract.pdf", + "original_name": "WnJgHQmzjyeKVF2EWnOw3JAp0fPIEgfB_e7fa567aac5fdffb5569ad7301a186889981b3f504d39250a6aebbce0ac452d6.pdf" + } + ], + "field_59623": null, + "field_59614": [ + 6 + ] + }, + { + "id": 2, + "order": "2.00000000000000000000", + "created_on": "2025-02-05T10:02:37.395435+00:00", + "updated_on": "2025-02-05T10:13:59.627865+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59622": null, + "field_59613": [ + { + "name": "WnJgHQmzjyeKVF2EWnOw3JAp0fPIEgfB_e7fa567aac5fdffb5569ad7301a186889981b3f504d39250a6aebbce0ac452d6.pdf", + "visible_name": "contract.pdf", + "original_name": "WnJgHQmzjyeKVF2EWnOw3JAp0fPIEgfB_e7fa567aac5fdffb5569ad7301a186889981b3f504d39250a6aebbce0ac452d6.pdf" + } + ], + "field_59623": null, + "field_59614": [ + 7 + ] + }, + { + "id": 3, + "order": "3.00000000000000000000", + "created_on": "2025-02-05T10:14:06.969361+00:00", + "updated_on": "2025-02-05T10:14:19.248714+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59622": null, + "field_59613": [ + { + "name": "sv5sVjuuU4vka45DtxdrVEgB41z41kcF_d15e48a86f901b103b995ee1aa8611a5676f234dbec030d7f20a40956610ab55.jpeg", + "visible_name": "pallets.jpeg", + "original_name": "sv5sVjuuU4vka45DtxdrVEgB41z41kcF_d15e48a86f901b103b995ee1aa8611a5676f234dbec030d7f20a40956610ab55.jpeg" + } + ], + "field_59623": null, + "field_59614": [ + 7 + ] + }, + { + "id": 4, + "order": "4.00000000000000000000", + "created_on": "2025-02-05T10:14:21.840714+00:00", + "updated_on": "2025-02-05T10:14:35.405845+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59622": null, + "field_59613": [ + { + "name": "EkOQ883tzFvi17Sg02ARsvmz3kreg5K7_cd993b3a02bdd9f086b6496b2dfd4ad22f245b78458a9aa28c90ba3493188334.jpeg", + "visible_name": "tools.jpeg", + "original_name": "EkOQ883tzFvi17Sg02ARsvmz3kreg5K7_cd993b3a02bdd9f086b6496b2dfd4ad22f245b78458a9aa28c90ba3493188334.jpeg" + } + ], + "field_59623": null, + "field_59614": [ + 7 + ] + }, + { + "id": 5, + "order": "5.00000000000000000000", + "created_on": "2025-02-05T10:14:58.718123+00:00", + "updated_on": "2025-02-05T10:15:11.710567+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59622": null, + "field_59613": [ + { + "name": "WnJgHQmzjyeKVF2EWnOw3JAp0fPIEgfB_e7fa567aac5fdffb5569ad7301a186889981b3f504d39250a6aebbce0ac452d6.pdf", + "visible_name": "contract.pdf", + "original_name": "WnJgHQmzjyeKVF2EWnOw3JAp0fPIEgfB_e7fa567aac5fdffb5569ad7301a186889981b3f504d39250a6aebbce0ac452d6.pdf" + } + ], + "field_59623": null, + "field_59614": [ + 3 + ] + }, + { + "id": 6, + "order": "6.00000000000000000000", + "created_on": "2025-02-05T10:15:06.267566+00:00", + "updated_on": "2025-02-05T10:18:37.530230+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59622": null, + "field_59613": [ + { + "name": "mQO3bvgYePOu0rWoAz7kocRAO2QKN75M_38f6c19434e047b7681f6ef89cd68ba62779308825f039f30d0afa2ef4521b80.webp", + "visible_name": "A 3D render of a rainbow colore...g above a reflective lake.webp", + "original_name": "mQO3bvgYePOu0rWoAz7kocRAO2QKN75M_38f6c19434e047b7681f6ef89cd68ba62779308825f039f30d0afa2ef4521b80.webp" + } + ], + "field_59623": null, + "field_59614": [ + 3 + ] + }, + { + "id": 7, + "order": "7.00000000000000000000", + "created_on": "2025-02-05T10:15:07.735556+00:00", + "updated_on": "2025-02-05T10:18:52.363224+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59622": null, + "field_59613": [ + { + "name": "9wEN1j8G8FM2OvsLeIKejqBZtXXi2wDh_78fd39be87f430673055eb29c12640404a2536ea416a1691672db111e0216d93.webp", + "visible_name": "A blue orange sliced in half la...r in front of a blue wall.webp", + "original_name": "9wEN1j8G8FM2OvsLeIKejqBZtXXi2wDh_78fd39be87f430673055eb29c12640404a2536ea416a1691672db111e0216d93.webp" + } + ], + "field_59623": null, + "field_59614": [ + 3 + ] + }, + { + "id": 8, + "order": "8.00000000000000000000", + "created_on": "2025-02-05T10:15:13.177066+00:00", + "updated_on": "2025-02-05T10:19:03.067117+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59622": null, + "field_59613": [ + { + "name": "y1P9ulM5rL4cQFRcy18vl7lrmF9fa9eX_d6f44caa1e0c26cf4fa6140e6205220b601387af004a2d74cf175746226cfa8a.webp", + "visible_name": "A centered explosion of colorfu...der on a black background.webp", + "original_name": "y1P9ulM5rL4cQFRcy18vl7lrmF9fa9eX_d6f44caa1e0c26cf4fa6140e6205220b601387af004a2d74cf175746226cfa8a.webp" + } + ], + "field_59623": null, + "field_59614": [ + 3 + ] + }, + { + "id": 9, + "order": "9.00000000000000000000", + "created_on": "2025-02-05T10:19:11.863993+00:00", + "updated_on": "2025-02-05T10:19:48.303568+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59622": null, + "field_59613": [ + { + "name": "fPeEzUORQ9ZvGiatPk76YGW2SuSoKRqW_e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855.pdf", + "visible_name": "template.pdf", + "original_name": "fPeEzUORQ9ZvGiatPk76YGW2SuSoKRqW_e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855.pdf" + } + ], + "field_59623": null, + "field_59614": [ + 3 + ] + } + ], + "data_sync": null + } + ] + }, + { + "id": 2164, + "name": "Case 8 - Task Management", + "order": 8, + "type": "database", + "tables": [ + { + "id": 5684, + "name": "Tasks", + "order": 2, + "fields": [ + { + "id": 59647, + "type": "formula", + "name": "Name", + "description": null, + "order": 10, + "primary": true, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "duration_format": null, + "date_include_time": null, + "date_show_tzinfo": null, + "number_prefix": "", + "array_formula_type": null, + "nullable": false, + "date_format": null, + "date_time_format": null, + "date_force_timezone": null, + "number_suffix": "", + "number_separator": "", + "error": null, + "number_decimal_places": null, + "formula": "concat(left(upper(totext(field('Category'))),3),'-',year(field('Created on')),'-',field('ID'))", + "formula_type": "text" + }, + { + "id": 59627, + "type": "single_select", + "name": "Category", + "description": null, + "order": 1, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "select_options": [ + { + "id": 21003, + "value": "Operations", + "color": "darker-gray", + "order": 0 + }, + { + "id": 21004, + "value": "Management", + "color": "dark-brown", + "order": 1 + }, + { + "id": 21005, + "value": "Marketing", + "color": "light-cyan", + "order": 2 + }, + { + "id": 21006, + "value": "Finance", + "color": "darker-yellow", + "order": 3 + }, + { + "id": 21007, + "value": "Human Resources", + "color": "light-yellow", + "order": 4 + } + ] + }, + { + "id": 59628, + "type": "text", + "name": "Description", + "description": null, + "order": 2, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "text_default": "" + }, + { + "id": 59629, + "type": "text", + "name": "Title", + "description": null, + "order": 3, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "text_default": "" + }, + { + "id": 59630, + "type": "created_on", + "name": "Created on", + "description": null, + "order": 8, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "date_format": "ISO", + "date_include_time": false, + "date_time_format": "24", + "date_show_tzinfo": false, + "date_force_timezone": null + }, + { + "id": 59631, + "type": "formula", + "name": "ID", + "description": null, + "order": 9, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "duration_format": null, + "date_include_time": null, + "date_show_tzinfo": null, + "number_prefix": "", + "array_formula_type": null, + "nullable": false, + "date_format": null, + "date_time_format": null, + "date_force_timezone": null, + "number_suffix": "", + "number_separator": "", + "error": null, + "number_decimal_places": null, + "formula": "if(row_id() < 10,concat('0000',row_id()),if(row_id() < 100,concat('000',row_id()),if(row_id() < 1000,concat('00',row_id()),if(row_id() < 10000,concat('0',row_id()),row_id()))))", + "formula_type": "text" + }, + { + "id": 59632, + "type": "single_select", + "name": "Importance", + "description": null, + "order": 11, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "select_options": [ + { + "id": 21008, + "value": "Low", + "color": "cyan", + "order": 0 + }, + { + "id": 21009, + "value": "Medium", + "color": "blue", + "order": 1 + }, + { + "id": 21010, + "value": "High", + "color": "red", + "order": 2 + } + ] + }, + { + "id": 59633, + "type": "date", + "name": "Deadline", + "description": null, + "order": 12, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "date_format": "ISO", + "date_include_time": false, + "date_time_format": "24", + "date_show_tzinfo": false, + "date_force_timezone": null + }, + { + "id": 59648, + "type": "formula", + "name": "Is urgent", + "description": null, + "order": 13, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "duration_format": null, + "date_include_time": null, + "date_show_tzinfo": null, + "number_prefix": "", + "array_formula_type": null, + "nullable": false, + "date_format": null, + "date_time_format": null, + "date_force_timezone": null, + "number_suffix": "", + "number_separator": "", + "error": null, + "number_decimal_places": null, + "formula": "field('Deadline') < today() + date_interval(concat(field('Expected workload') / 6,' days'))", + "formula_type": "boolean" + }, + { + "id": 59650, + "type": "formula", + "name": "Is high priority", + "description": null, + "order": 14, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "duration_format": null, + "date_include_time": null, + "date_show_tzinfo": null, + "number_prefix": "", + "array_formula_type": null, + "nullable": false, + "date_format": null, + "date_time_format": null, + "date_force_timezone": null, + "number_suffix": "", + "number_separator": "", + "error": null, + "number_decimal_places": null, + "formula": "field('Importance') = 'High'", + "formula_type": "boolean" + }, + { + "id": 59657, + "type": "formula", + "name": "Desired start date", + "description": null, + "order": 15, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "duration_format": null, + "date_include_time": null, + "date_show_tzinfo": null, + "number_prefix": "", + "array_formula_type": null, + "nullable": false, + "date_format": null, + "date_time_format": null, + "date_force_timezone": null, + "number_suffix": "", + "number_separator": "", + "error": null, + "number_decimal_places": null, + "formula": "if(and(field('Is urgent'),field('Is high priority')),today(),if(and(field('Is urgent'),not(field('Is high priority'))),today() + date_interval('1 day'),if(and(not(field('Is urgent')),field('Is high priority')),today() + date_interval('3 days'),'')))", + "formula_type": "text" + }, + { + "id": 59634, + "type": "number", + "name": "Expected workload", + "description": null, + "order": 16, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "number_decimal_places": 0, + "number_negative": false, + "number_prefix": "", + "number_suffix": "hours", + "number_separator": "" + }, + { + "id": 59635, + "type": "link_row", + "name": "Contractor", + "description": null, + "order": 17, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "link_row_table_id": 5685, + "link_row_related_field_id": 59644, + "link_row_limit_selection_view_id": null, + "has_related_field": true + }, + { + "id": 59651, + "type": "formula", + "name": "Required fields valid", + "description": null, + "order": 18, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "duration_format": null, + "date_include_time": null, + "date_show_tzinfo": null, + "number_prefix": "", + "array_formula_type": null, + "nullable": false, + "date_format": null, + "date_time_format": null, + "date_force_timezone": null, + "number_suffix": "", + "number_separator": "", + "error": null, + "number_decimal_places": null, + "formula": "and(and(not(isblank(field('Importance'))),not(isblank(field('Deadline')))),not(isblank(field('Expected workload'))))", + "formula_type": "boolean" + }, + { + "id": 59652, + "type": "formula", + "name": "Contractor valid", + "description": null, + "order": 19, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "duration_format": null, + "date_include_time": null, + "date_show_tzinfo": null, + "number_prefix": "", + "array_formula_type": null, + "nullable": false, + "date_format": null, + "date_time_format": null, + "date_force_timezone": null, + "number_suffix": "", + "number_separator": "", + "error": null, + "number_decimal_places": null, + "formula": "or(count(field('Contractor')) = 0,regex_replace(join(lookup('Contractor','VAT Number'),''),'(GB)?([0-9]{9})','valid') = 'valid')", + "formula_type": "boolean" + }, + { + "id": 59658, + "type": "formula", + "name": "Task is valid", + "description": null, + "order": 20, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "duration_format": null, + "date_include_time": null, + "date_show_tzinfo": null, + "number_prefix": "", + "array_formula_type": null, + "nullable": false, + "date_format": null, + "date_time_format": null, + "date_force_timezone": null, + "number_suffix": "", + "number_separator": "", + "error": null, + "number_decimal_places": null, + "formula": "and(field('Required fields valid'),field('Contractor valid'))", + "formula_type": "boolean" + }, + { + "id": 59649, + "type": "formula", + "name": "Final start date", + "description": null, + "order": 21, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "duration_format": null, + "date_include_time": false, + "date_show_tzinfo": false, + "number_prefix": "", + "array_formula_type": null, + "nullable": true, + "date_format": "ISO", + "date_time_format": "24", + "date_force_timezone": null, + "number_suffix": "", + "number_separator": "", + "error": null, + "number_decimal_places": null, + "formula": "field('Deadline') - date_interval(concat(field('Expected workload') / 6 + 1,' days'))", + "formula_type": "date" + }, + { + "id": 59636, + "type": "formula", + "name": "Details", + "description": null, + "order": 22, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "duration_format": null, + "date_include_time": null, + "date_show_tzinfo": null, + "number_prefix": "", + "array_formula_type": null, + "nullable": false, + "date_format": null, + "date_time_format": null, + "date_force_timezone": null, + "number_suffix": "", + "number_separator": "", + "error": null, + "number_decimal_places": null, + "formula": "button(concat('https://example.com/builder/1059/preview/task-details/',row_id()),'Details')", + "formula_type": "button" + }, + { + "id": 59637, + "type": "date", + "name": "Actual start date", + "description": null, + "order": 23, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "date_format": "ISO", + "date_include_time": false, + "date_time_format": "24", + "date_show_tzinfo": false, + "date_force_timezone": null + }, + { + "id": 59659, + "type": "formula", + "name": "Start task", + "description": null, + "order": 24, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "duration_format": null, + "date_include_time": null, + "date_show_tzinfo": null, + "number_prefix": "", + "array_formula_type": null, + "nullable": false, + "date_format": null, + "date_time_format": null, + "date_force_timezone": null, + "number_suffix": "", + "number_separator": "", + "error": null, + "number_decimal_places": null, + "formula": "if(field('Task is valid'),button(concat('https://n8n.cloudron.getbaserow.com/webhook/set-start-date?id=',row_id()),'Start task'),button('','Task not valid'))", + "formula_type": "button" + }, + { + "id": 59638, + "type": "link_row", + "name": "Assets", + "description": null, + "order": 25, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "link_row_table_id": 5686, + "link_row_related_field_id": 59646, + "link_row_limit_selection_view_id": null, + "has_related_field": true + }, + { + "id": 59656, + "type": "formula", + "name": "Add asset", + "description": null, + "order": 26, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "duration_format": null, + "date_include_time": null, + "date_show_tzinfo": null, + "number_prefix": "", + "array_formula_type": null, + "nullable": false, + "date_format": null, + "date_time_format": null, + "date_force_timezone": null, + "number_suffix": "", + "number_separator": "", + "error": null, + "number_decimal_places": null, + "formula": "button(concat('https://example.com/form/iN6i2YJeJcUKB-cuouClfSpmU1LxvSgzWL3Nle5aBwY?prefill_Task=',field('Name'),'&hide_Task'),'Add asset')", + "formula_type": "button" + } + ], + "views": [ + { + "id": 26427, + "type": "grid", + "name": "All tasks", + "order": 1, + "ownership_type": "collaborative", + "owned_by": "frederik@baserow.io", + "filter_type": "AND", + "filters_disabled": false, + "filters": [], + "filter_groups": [], + "sortings": [], + "group_bys": [], + "decorations": [ + { + "id": 8723, + "type": "background_color", + "value_provider_type": "conditional_color", + "value_provider_conf": { + "colors": [ + { + "id": "77f5ba06-166f-4b45-8c17-ff45cf5d4290", + "color": "light-yellow", + "filters": [ + { + "id": "2c9ff0a1-174b-47e1-8c1b-db6bc8b3f9b9", + "type": "date_is_before", + "field": 59649, + "group": null, + "value": "Europe/Brussels??today" + } + ], + "operator": "AND" + } + ] + }, + "order": 1 + } + ], + "public": false, + "row_identifier_type": "id", + "row_height_size": "medium", + "field_options": [ + { + "id": 260995, + "field_id": 59647, + "width": 200, + "hidden": false, + "order": 0, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260996, + "field_id": 59631, + "width": 200, + "hidden": true, + "order": 1, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260997, + "field_id": 59629, + "width": 171, + "hidden": false, + "order": 2, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260998, + "field_id": 59636, + "width": 138, + "hidden": false, + "order": 3, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 260999, + "field_id": 59656, + "width": 200, + "hidden": false, + "order": 4, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261000, + "field_id": 59659, + "width": 200, + "hidden": true, + "order": 5, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261001, + "field_id": 59627, + "width": 152, + "hidden": false, + "order": 6, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261002, + "field_id": 59632, + "width": 143, + "hidden": false, + "order": 7, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261003, + "field_id": 59633, + "width": 141, + "hidden": false, + "order": 8, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261004, + "field_id": 59634, + "width": 200, + "hidden": false, + "order": 9, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261005, + "field_id": 59648, + "width": 125, + "hidden": false, + "order": 10, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261006, + "field_id": 59637, + "width": 200, + "hidden": false, + "order": 11, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261007, + "field_id": 59650, + "width": 200, + "hidden": false, + "order": 12, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261008, + "field_id": 59649, + "width": 200, + "hidden": false, + "order": 13, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261009, + "field_id": 59657, + "width": 200, + "hidden": false, + "order": 14, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261010, + "field_id": 59628, + "width": 554, + "hidden": false, + "order": 15, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261011, + "field_id": 59635, + "width": 200, + "hidden": false, + "order": 16, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261012, + "field_id": 59630, + "width": 200, + "hidden": false, + "order": 17, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261013, + "field_id": 59651, + "width": 200, + "hidden": false, + "order": 18, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261014, + "field_id": 59652, + "width": 200, + "hidden": false, + "order": 19, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261015, + "field_id": 59658, + "width": 200, + "hidden": false, + "order": 20, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261016, + "field_id": 59638, + "width": 200, + "hidden": false, + "order": 21, + "aggregation_type": "", + "aggregation_raw_type": "" + } + ] + }, + { + "id": 26428, + "type": "grid", + "name": "Valid tasks", + "order": 2, + "ownership_type": "collaborative", + "owned_by": "frederik@baserow.io", + "filter_type": "AND", + "filters_disabled": false, + "filters": [ + { + "id": 13955, + "field_id": 59658, + "type": "boolean", + "value": "1", + "group": null + } + ], + "filter_groups": [], + "sortings": [], + "group_bys": [], + "decorations": [], + "public": false, + "row_identifier_type": "id", + "row_height_size": "medium", + "field_options": [ + { + "id": 261017, + "field_id": 59647, + "width": 200, + "hidden": false, + "order": 0, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261018, + "field_id": 59631, + "width": 200, + "hidden": true, + "order": 1, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261019, + "field_id": 59629, + "width": 171, + "hidden": false, + "order": 2, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261020, + "field_id": 59627, + "width": 157, + "hidden": false, + "order": 3, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261021, + "field_id": 59632, + "width": 143, + "hidden": false, + "order": 4, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261022, + "field_id": 59633, + "width": 141, + "hidden": false, + "order": 5, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261023, + "field_id": 59634, + "width": 200, + "hidden": false, + "order": 6, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261024, + "field_id": 59648, + "width": 125, + "hidden": false, + "order": 7, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261025, + "field_id": 59650, + "width": 200, + "hidden": false, + "order": 8, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261026, + "field_id": 59657, + "width": 200, + "hidden": false, + "order": 9, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261027, + "field_id": 59628, + "width": 554, + "hidden": false, + "order": 10, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261028, + "field_id": 59635, + "width": 200, + "hidden": false, + "order": 11, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261029, + "field_id": 59630, + "width": 200, + "hidden": false, + "order": 12, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261030, + "field_id": 59651, + "width": 200, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261031, + "field_id": 59652, + "width": 200, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261032, + "field_id": 59658, + "width": 200, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + } + ] + }, + { + "id": 26429, + "type": "grid", + "name": "Invalid tasks", + "order": 3, + "ownership_type": "collaborative", + "owned_by": "frederik@baserow.io", + "filter_type": "AND", + "filters_disabled": false, + "filters": [ + { + "id": 13956, + "field_id": 59658, + "type": "boolean", + "value": "0", + "group": null + } + ], + "filter_groups": [], + "sortings": [], + "group_bys": [], + "decorations": [], + "public": false, + "row_identifier_type": "id", + "row_height_size": "medium", + "field_options": [ + { + "id": 261033, + "field_id": 59647, + "width": 200, + "hidden": false, + "order": 0, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261034, + "field_id": 59631, + "width": 200, + "hidden": true, + "order": 1, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261035, + "field_id": 59629, + "width": 171, + "hidden": false, + "order": 2, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261036, + "field_id": 59627, + "width": 157, + "hidden": false, + "order": 3, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261037, + "field_id": 59632, + "width": 143, + "hidden": false, + "order": 4, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261038, + "field_id": 59633, + "width": 141, + "hidden": false, + "order": 5, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261039, + "field_id": 59634, + "width": 200, + "hidden": false, + "order": 6, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261040, + "field_id": 59648, + "width": 125, + "hidden": false, + "order": 7, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261041, + "field_id": 59650, + "width": 200, + "hidden": false, + "order": 8, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261042, + "field_id": 59657, + "width": 200, + "hidden": false, + "order": 9, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261043, + "field_id": 59628, + "width": 554, + "hidden": false, + "order": 10, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261044, + "field_id": 59635, + "width": 200, + "hidden": false, + "order": 11, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261045, + "field_id": 59630, + "width": 200, + "hidden": false, + "order": 12, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261046, + "field_id": 59651, + "width": 200, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261047, + "field_id": 59652, + "width": 200, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261048, + "field_id": 59658, + "width": 200, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + } + ] + } + ], + "rows": [ + { + "id": 1, + "order": "1.00000000000000000000", + "created_on": "2025-02-05T07:48:00.081133+00:00", + "updated_on": "2025-02-05T09:59:16.521136+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59647": null, + "field_59627": 21007, + "field_59628": "Conduct onboarding for a new hire, including setting up payroll in the HR system, scheduling a welcome meeting with the team, providing access to company tools, and assigning required training materials.", + "field_59629": "Employee Onboarding", + "field_59630": null, + "field_59631": null, + "field_59632": 21009, + "field_59633": "2025-02-06", + "field_59648": null, + "field_59650": null, + "field_59657": null, + "field_59634": "12", + "field_59635": [], + "field_59651": null, + "field_59652": null, + "field_59658": null, + "field_59649": null, + "field_59636": null, + "field_59637": "2025-02-05", + "field_59659": null, + "field_59638": [], + "field_59656": null + }, + { + "id": 2, + "order": "2.00000000000000000000", + "created_on": "2025-02-05T07:48:00.081208+00:00", + "updated_on": "2025-02-05T09:59:12.070377+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59647": null, + "field_59627": 21006, + "field_59628": "Process and approve five supplier invoices by verifying amounts, ensuring correct account allocation, obtaining necessary approvals, and scheduling payment in the financial system.", + "field_59629": "Invoice Processing", + "field_59630": null, + "field_59631": null, + "field_59632": 21008, + "field_59633": "2025-02-20", + "field_59648": null, + "field_59650": null, + "field_59657": null, + "field_59634": "34", + "field_59635": [], + "field_59651": null, + "field_59652": null, + "field_59658": null, + "field_59649": null, + "field_59636": null, + "field_59637": null, + "field_59659": null, + "field_59638": [], + "field_59656": null + }, + { + "id": 3, + "order": "3.00000000000000000000", + "created_on": "2025-02-05T07:48:00.081236+00:00", + "updated_on": "2025-02-05T10:34:53.036862+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59647": null, + "field_59627": 21005, + "field_59628": "Write, design, and schedule three social media posts promoting the company\u2019s latest product update, ensuring alignment with brand guidelines and marketing strategy.", + "field_59629": "Social Media Posts", + "field_59630": null, + "field_59631": null, + "field_59632": 21009, + "field_59633": "2025-02-06", + "field_59648": null, + "field_59650": null, + "field_59657": null, + "field_59634": "53", + "field_59635": [ + 1 + ], + "field_59651": null, + "field_59652": null, + "field_59658": null, + "field_59649": null, + "field_59636": null, + "field_59637": null, + "field_59659": null, + "field_59638": [ + 5, + 6, + 7, + 8, + 9 + ], + "field_59656": null + }, + { + "id": 4, + "order": "4.00000000000000000000", + "created_on": "2025-02-05T07:48:00.081262+00:00", + "updated_on": "2025-02-05T09:59:12.070496+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59647": null, + "field_59627": 21003, + "field_59628": "Resolve 15 customer support tickets by diagnosing issues, providing solutions, updating ticket statuses, and following up to ensure customer satisfaction.", + "field_59629": "Customer Ticketing", + "field_59630": null, + "field_59631": null, + "field_59632": 21010, + "field_59633": "2025-02-06", + "field_59648": null, + "field_59650": null, + "field_59657": null, + "field_59634": "6", + "field_59635": [], + "field_59651": null, + "field_59652": null, + "field_59658": null, + "field_59649": null, + "field_59636": null, + "field_59637": null, + "field_59659": null, + "field_59638": [], + "field_59656": null + }, + { + "id": 5, + "order": "5.00000000000000000000", + "created_on": "2025-02-05T07:48:00.081289+00:00", + "updated_on": "2025-02-05T08:40:15.433306+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59647": null, + "field_59627": 21004, + "field_59628": "Break down an upcoming project into five key tasks, assign them to team members, set deadlines in the project management system, and communicate expectations to stakeholders.", + "field_59629": "Task Assignment", + "field_59630": null, + "field_59631": null, + "field_59632": 21009, + "field_59633": "2025-02-27", + "field_59648": null, + "field_59650": null, + "field_59657": null, + "field_59634": "11", + "field_59635": [], + "field_59651": null, + "field_59652": null, + "field_59658": null, + "field_59649": null, + "field_59636": null, + "field_59637": null, + "field_59659": null, + "field_59638": [], + "field_59656": null + }, + { + "id": 6, + "order": "6.00000000000000000000", + "created_on": "2025-02-05T07:48:00.081315+00:00", + "updated_on": "2025-02-05T08:51:34.279762+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59647": null, + "field_59627": 21003, + "field_59628": "Install security patches and update software on all employee workstations, ensuring compatibility, testing functionality, and documenting changes for compliance.", + "field_59629": "System Updates", + "field_59630": null, + "field_59631": null, + "field_59632": 21008, + "field_59633": "2025-02-11", + "field_59648": null, + "field_59650": null, + "field_59657": null, + "field_59634": "9", + "field_59635": [ + 2 + ], + "field_59651": null, + "field_59652": null, + "field_59658": null, + "field_59649": null, + "field_59636": null, + "field_59637": null, + "field_59659": null, + "field_59638": [ + 1 + ], + "field_59656": null + }, + { + "id": 7, + "order": "7.00000000000000000000", + "created_on": "2025-02-05T07:48:00.081340+00:00", + "updated_on": "2025-02-05T09:12:33.288350+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59647": null, + "field_59627": 21003, + "field_59628": "Conduct a physical inventory count of all high-value products, compare results with digital records, report discrepancies, and update the inventory management system.", + "field_59629": "Inventory Check", + "field_59630": null, + "field_59631": null, + "field_59632": 21009, + "field_59633": "2025-02-08", + "field_59648": null, + "field_59650": null, + "field_59657": null, + "field_59634": "23", + "field_59635": [ + 3 + ], + "field_59651": null, + "field_59652": null, + "field_59658": null, + "field_59649": null, + "field_59636": null, + "field_59637": null, + "field_59659": null, + "field_59638": [ + 2, + 3, + 4 + ], + "field_59656": null + }, + { + "id": 8, + "order": "8.00000000000000000000", + "created_on": "2025-02-05T07:48:00.081365+00:00", + "updated_on": "2025-02-05T09:05:11.649918+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59647": null, + "field_59627": 21005, + "field_59628": "Follow up with five potential clients via email or phone, answer questions, provide additional information, and schedule meetings to move them through the sales pipeline.", + "field_59629": "Client Follow-Up", + "field_59630": null, + "field_59631": null, + "field_59632": 21010, + "field_59633": "2025-02-07", + "field_59648": null, + "field_59650": null, + "field_59657": null, + "field_59634": "45", + "field_59635": [], + "field_59651": null, + "field_59652": null, + "field_59658": null, + "field_59649": null, + "field_59636": null, + "field_59637": null, + "field_59659": null, + "field_59638": [], + "field_59656": null + }, + { + "id": 9, + "order": "9.00000000000000000000", + "created_on": "2025-02-05T07:48:00.081389+00:00", + "updated_on": "2025-02-05T08:51:47.995170+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59647": null, + "field_59627": 21004, + "field_59628": "Review and update one company policy by assessing current regulations, identifying gaps, revising wording, obtaining approval, and publishing the final version.", + "field_59629": "Policy Review", + "field_59630": null, + "field_59631": null, + "field_59632": 21010, + "field_59633": "2025-02-11", + "field_59648": null, + "field_59650": null, + "field_59657": null, + "field_59634": "16", + "field_59635": [ + 4 + ], + "field_59651": null, + "field_59652": null, + "field_59658": null, + "field_59649": null, + "field_59636": null, + "field_59637": null, + "field_59659": null, + "field_59638": [], + "field_59656": null + }, + { + "id": 10, + "order": "10.00000000000000000000", + "created_on": "2025-02-05T07:48:00.081413+00:00", + "updated_on": "2025-02-05T09:11:31.741326+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59647": null, + "field_59627": 21004, + "field_59628": "Conduct one-on-one performance reviews with three employees, discuss achievements and challenges, document feedback, and outline action steps for improvement.", + "field_59629": "Performance Reviews", + "field_59630": null, + "field_59631": null, + "field_59632": 21010, + "field_59633": "2025-02-28", + "field_59648": null, + "field_59650": null, + "field_59657": null, + "field_59634": "30", + "field_59635": [], + "field_59651": null, + "field_59652": null, + "field_59658": null, + "field_59649": null, + "field_59636": null, + "field_59637": null, + "field_59659": null, + "field_59638": [], + "field_59656": null + } + ], + "data_sync": null + }, + { + "id": 5685, + "name": "Contractors", + "order": 3, + "fields": [ + { + "id": 59639, + "type": "text", + "name": "Company Name", + "description": null, + "order": 0, + "primary": true, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "text_default": "" + }, + { + "id": 59640, + "type": "text", + "name": "Address", + "description": null, + "order": 1, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "text_default": "" + }, + { + "id": 59641, + "type": "email", + "name": "Email", + "description": null, + "order": 2, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false + }, + { + "id": 59642, + "type": "phone_number", + "name": "Phone", + "description": null, + "order": 3, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false + }, + { + "id": 59643, + "type": "text", + "name": "VAT Number", + "description": null, + "order": 4, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "text_default": "" + }, + { + "id": 59653, + "type": "formula", + "name": "Formula", + "description": null, + "order": 5, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "duration_format": null, + "date_include_time": null, + "date_show_tzinfo": null, + "number_prefix": "", + "array_formula_type": null, + "nullable": false, + "date_format": null, + "date_time_format": null, + "date_force_timezone": null, + "number_suffix": "", + "number_separator": "", + "error": null, + "number_decimal_places": null, + "formula": "regex_replace(field('VAT Number'),'(GB)?([0-9]{9})','')", + "formula_type": "text" + }, + { + "id": 59644, + "type": "link_row", + "name": "Tasks", + "description": null, + "order": 6, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "link_row_table_id": 5684, + "link_row_related_field_id": 59635, + "link_row_limit_selection_view_id": null, + "has_related_field": true + } + ], + "views": [ + { + "id": 26430, + "type": "grid", + "name": "All contractors", + "order": 1, + "ownership_type": "collaborative", + "owned_by": "frederik@baserow.io", + "filter_type": "AND", + "filters_disabled": false, + "filters": [], + "filter_groups": [], + "sortings": [], + "group_bys": [], + "decorations": [], + "public": false, + "row_identifier_type": "id", + "row_height_size": "small", + "field_options": [ + { + "id": 261049, + "field_id": 59639, + "width": 200, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261050, + "field_id": 59640, + "width": 200, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261051, + "field_id": 59641, + "width": 200, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261052, + "field_id": 59642, + "width": 158, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261053, + "field_id": 59643, + "width": 200, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261054, + "field_id": 59644, + "width": 200, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261055, + "field_id": 59653, + "width": 200, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + } + ] + } + ], + "rows": [ + { + "id": 1, + "order": "1.00000000000000000000", + "created_on": "2025-02-05T08:42:47.025930+00:00", + "updated_on": "2025-02-05T08:50:20.819069+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59639": "BrightBuild Ltd", + "field_59640": "12 Greenway Street, London, SW1A 1AA", + "field_59641": "info@brightbuild.co.uk", + "field_59642": "+44 20 7946 0123", + "field_59643": "GB123456789", + "field_59653": null, + "field_59644": [ + 3 + ] + }, + { + "id": 2, + "order": "2.00000000000000000000", + "created_on": "2025-02-05T08:42:47.025996+00:00", + "updated_on": "2025-02-05T08:42:47.025996+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59639": "ProTech Solutions", + "field_59640": "45 Kings Road, Manchester, M1 3LD", + "field_59641": "contact@protechsolutions.co.uk", + "field_59642": "+44 161 555 6789", + "field_59643": "GB987654321", + "field_59653": null, + "field_59644": [ + 6 + ] + }, + { + "id": 3, + "order": "3.00000000000000000000", + "created_on": "2025-02-05T08:42:47.026022+00:00", + "updated_on": "2025-02-05T08:42:47.026022+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59639": "EcoElectrics UK", + "field_59640": "78 Solar Avenue, Birmingham, B2 4QA", + "field_59641": "support@ecoelectrics.co.uk", + "field_59642": "+44 121 432 8765", + "field_59643": "GB456123789", + "field_59653": null, + "field_59644": [ + 7 + ] + }, + { + "id": 4, + "order": "4.00000000000000000000", + "created_on": "2025-02-05T08:42:47.026045+00:00", + "updated_on": "2025-02-05T08:42:47.026045+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59639": "SwiftLogistics", + "field_59640": "22 Dockside Lane, Liverpool, L3 1AB", + "field_59641": "admin@swiftlogistics.co.uk", + "field_59642": "+44 151 789 6543", + "field_59643": "GB321654987", + "field_59653": null, + "field_59644": [ + 9 + ] + }, + { + "id": 5, + "order": "5.00000000000000000000", + "created_on": "2025-02-05T08:42:47.026069+00:00", + "updated_on": "2025-02-05T08:42:47.026069+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59639": "Regal Interiors", + "field_59640": "89 High Street, Edinburgh, EH2 4PH", + "field_59641": "sales@regalinteriors.co.uk", + "field_59642": "+44 131 246 9870", + "field_59643": "GB654987321", + "field_59653": null, + "field_59644": [] + } + ], + "data_sync": null + }, + { + "id": 5686, + "name": "Asset repository", + "order": 4, + "fields": [ + { + "id": 59654, + "type": "formula", + "name": "Name", + "description": null, + "order": 0, + "primary": true, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "duration_format": null, + "date_include_time": null, + "date_show_tzinfo": null, + "number_prefix": "", + "array_formula_type": null, + "nullable": true, + "date_format": null, + "date_time_format": null, + "date_force_timezone": null, + "number_suffix": "", + "number_separator": "", + "error": null, + "number_decimal_places": null, + "formula": "get_file_visible_name(index(field('File'),0))", + "formula_type": "text" + }, + { + "id": 59645, + "type": "file", + "name": "File", + "description": null, + "order": 1, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false + }, + { + "id": 59655, + "type": "formula", + "name": "is Image", + "description": null, + "order": 2, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "duration_format": null, + "date_include_time": null, + "date_show_tzinfo": null, + "number_prefix": "", + "array_formula_type": null, + "nullable": true, + "date_format": null, + "date_time_format": null, + "date_force_timezone": null, + "number_suffix": "", + "number_separator": "", + "error": null, + "number_decimal_places": null, + "formula": "is_image(index(field('File'),0))", + "formula_type": "boolean" + }, + { + "id": 59646, + "type": "link_row", + "name": "Task", + "description": null, + "order": 3, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "link_row_table_id": 5684, + "link_row_related_field_id": 59638, + "link_row_limit_selection_view_id": null, + "has_related_field": true + } + ], + "views": [ + { + "id": 26431, + "type": "grid", + "name": "All assets", + "order": 1, + "ownership_type": "collaborative", + "owned_by": "frederik@baserow.io", + "filter_type": "AND", + "filters_disabled": false, + "filters": [], + "filter_groups": [], + "sortings": [], + "group_bys": [], + "decorations": [], + "public": false, + "row_identifier_type": "id", + "row_height_size": "small", + "field_options": [ + { + "id": 261056, + "field_id": 59654, + "width": 200, + "hidden": false, + "order": 0, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261057, + "field_id": 59646, + "width": 200, + "hidden": false, + "order": 1, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261058, + "field_id": 59645, + "width": 192, + "hidden": false, + "order": 2, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261059, + "field_id": 59655, + "width": 185, + "hidden": false, + "order": 3, + "aggregation_type": "", + "aggregation_raw_type": "" + } + ] + }, + { + "id": 26432, + "type": "grid", + "name": "Image assets", + "order": 2, + "ownership_type": "collaborative", + "owned_by": "frederik@baserow.io", + "filter_type": "AND", + "filters_disabled": false, + "filters": [ + { + "id": 13957, + "field_id": 59655, + "type": "boolean", + "value": "1", + "group": null + } + ], + "filter_groups": [], + "sortings": [], + "group_bys": [], + "decorations": [], + "public": false, + "row_identifier_type": "id", + "row_height_size": "small", + "field_options": [ + { + "id": 261060, + "field_id": 59654, + "width": 200, + "hidden": false, + "order": 0, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261061, + "field_id": 59646, + "width": 200, + "hidden": false, + "order": 1, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261062, + "field_id": 59645, + "width": 192, + "hidden": false, + "order": 2, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261063, + "field_id": 59655, + "width": 185, + "hidden": false, + "order": 3, + "aggregation_type": "", + "aggregation_raw_type": "" + } + ] + }, + { + "id": 26433, + "type": "grid", + "name": "Other assets", + "order": 3, + "ownership_type": "collaborative", + "owned_by": "frederik@baserow.io", + "filter_type": "AND", + "filters_disabled": false, + "filters": [ + { + "id": 13958, + "field_id": 59655, + "type": "boolean", + "value": "0", + "group": null + } + ], + "filter_groups": [], + "sortings": [], + "group_bys": [], + "decorations": [], + "public": false, + "row_identifier_type": "id", + "row_height_size": "small", + "field_options": [ + { + "id": 261064, + "field_id": 59654, + "width": 200, + "hidden": false, + "order": 0, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261065, + "field_id": 59646, + "width": 200, + "hidden": false, + "order": 1, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261066, + "field_id": 59645, + "width": 192, + "hidden": false, + "order": 2, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261067, + "field_id": 59655, + "width": 185, + "hidden": false, + "order": 3, + "aggregation_type": "", + "aggregation_raw_type": "" + } + ] + }, + { + "id": 26434, + "type": "form", + "name": "Add new asset", + "order": 4, + "ownership_type": "collaborative", + "owned_by": "frederik@baserow.io", + "public": true, + "title": "", + "description": "", + "cover_image": null, + "logo_image": null, + "submit_text": "Submit", + "submit_action": "MESSAGE", + "submit_action_message": "The asset has been added", + "submit_action_redirect_url": "", + "field_options": [ + { + "id": 25242, + "field_id": 59646, + "name": "", + "description": "The task related to the asset", + "enabled": true, + "required": true, + "order": 0, + "show_when_matching_conditions": false, + "condition_type": "AND", + "conditions": [], + "condition_groups": [], + "field_component": "default", + "include_all_select_options": true, + "allowed_select_options": [] + }, + { + "id": 25243, + "field_id": 59645, + "name": "", + "description": "Select a single file to be attached to the task", + "enabled": true, + "required": true, + "order": 1, + "show_when_matching_conditions": false, + "condition_type": "AND", + "conditions": [], + "condition_groups": [], + "field_component": "default", + "include_all_select_options": true, + "allowed_select_options": [] + }, + { + "id": 25244, + "field_id": 59654, + "name": "", + "description": "", + "enabled": false, + "required": true, + "order": 2, + "show_when_matching_conditions": false, + "condition_type": "AND", + "conditions": [], + "condition_groups": [], + "field_component": "default", + "include_all_select_options": true, + "allowed_select_options": [] + }, + { + "id": 25245, + "field_id": 59655, + "name": "", + "description": "", + "enabled": false, + "required": true, + "order": 3, + "show_when_matching_conditions": false, + "condition_type": "AND", + "conditions": [], + "condition_groups": [], + "field_component": "default", + "include_all_select_options": true, + "allowed_select_options": [] + } + ] + } + ], + "rows": [ + { + "id": 1, + "order": "1.00000000000000000000", + "created_on": "2025-02-05T10:02:37.395368+00:00", + "updated_on": "2025-02-05T10:13:44.901137+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59654": null, + "field_59645": [ + { + "name": "WnJgHQmzjyeKVF2EWnOw3JAp0fPIEgfB_e7fa567aac5fdffb5569ad7301a186889981b3f504d39250a6aebbce0ac452d6.pdf", + "visible_name": "contract.pdf", + "original_name": "WnJgHQmzjyeKVF2EWnOw3JAp0fPIEgfB_e7fa567aac5fdffb5569ad7301a186889981b3f504d39250a6aebbce0ac452d6.pdf" + } + ], + "field_59655": null, + "field_59646": [ + 6 + ] + }, + { + "id": 2, + "order": "2.00000000000000000000", + "created_on": "2025-02-05T10:02:37.395435+00:00", + "updated_on": "2025-02-05T10:13:59.627865+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59654": null, + "field_59645": [ + { + "name": "WnJgHQmzjyeKVF2EWnOw3JAp0fPIEgfB_e7fa567aac5fdffb5569ad7301a186889981b3f504d39250a6aebbce0ac452d6.pdf", + "visible_name": "contract.pdf", + "original_name": "WnJgHQmzjyeKVF2EWnOw3JAp0fPIEgfB_e7fa567aac5fdffb5569ad7301a186889981b3f504d39250a6aebbce0ac452d6.pdf" + } + ], + "field_59655": null, + "field_59646": [ + 7 + ] + }, + { + "id": 3, + "order": "3.00000000000000000000", + "created_on": "2025-02-05T10:14:06.969361+00:00", + "updated_on": "2025-02-05T10:14:19.248714+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59654": null, + "field_59645": [ + { + "name": "sv5sVjuuU4vka45DtxdrVEgB41z41kcF_d15e48a86f901b103b995ee1aa8611a5676f234dbec030d7f20a40956610ab55.jpeg", + "visible_name": "pallets.jpeg", + "original_name": "sv5sVjuuU4vka45DtxdrVEgB41z41kcF_d15e48a86f901b103b995ee1aa8611a5676f234dbec030d7f20a40956610ab55.jpeg" + } + ], + "field_59655": null, + "field_59646": [ + 7 + ] + }, + { + "id": 4, + "order": "4.00000000000000000000", + "created_on": "2025-02-05T10:14:21.840714+00:00", + "updated_on": "2025-02-05T10:14:35.405845+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59654": null, + "field_59645": [ + { + "name": "EkOQ883tzFvi17Sg02ARsvmz3kreg5K7_cd993b3a02bdd9f086b6496b2dfd4ad22f245b78458a9aa28c90ba3493188334.jpeg", + "visible_name": "tools.jpeg", + "original_name": "EkOQ883tzFvi17Sg02ARsvmz3kreg5K7_cd993b3a02bdd9f086b6496b2dfd4ad22f245b78458a9aa28c90ba3493188334.jpeg" + } + ], + "field_59655": null, + "field_59646": [ + 7 + ] + }, + { + "id": 5, + "order": "5.00000000000000000000", + "created_on": "2025-02-05T10:14:58.718123+00:00", + "updated_on": "2025-02-05T10:15:11.710567+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59654": null, + "field_59645": [ + { + "name": "WnJgHQmzjyeKVF2EWnOw3JAp0fPIEgfB_e7fa567aac5fdffb5569ad7301a186889981b3f504d39250a6aebbce0ac452d6.pdf", + "visible_name": "contract.pdf", + "original_name": "WnJgHQmzjyeKVF2EWnOw3JAp0fPIEgfB_e7fa567aac5fdffb5569ad7301a186889981b3f504d39250a6aebbce0ac452d6.pdf" + } + ], + "field_59655": null, + "field_59646": [ + 3 + ] + }, + { + "id": 6, + "order": "6.00000000000000000000", + "created_on": "2025-02-05T10:15:06.267566+00:00", + "updated_on": "2025-02-05T10:18:37.530230+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59654": null, + "field_59645": [ + { + "name": "mQO3bvgYePOu0rWoAz7kocRAO2QKN75M_38f6c19434e047b7681f6ef89cd68ba62779308825f039f30d0afa2ef4521b80.webp", + "visible_name": "A 3D render of a rainbow colore...g above a reflective lake.webp", + "original_name": "mQO3bvgYePOu0rWoAz7kocRAO2QKN75M_38f6c19434e047b7681f6ef89cd68ba62779308825f039f30d0afa2ef4521b80.webp" + } + ], + "field_59655": null, + "field_59646": [ + 3 + ] + }, + { + "id": 7, + "order": "7.00000000000000000000", + "created_on": "2025-02-05T10:15:07.735556+00:00", + "updated_on": "2025-02-05T10:18:52.363224+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59654": null, + "field_59645": [ + { + "name": "9wEN1j8G8FM2OvsLeIKejqBZtXXi2wDh_78fd39be87f430673055eb29c12640404a2536ea416a1691672db111e0216d93.webp", + "visible_name": "A blue orange sliced in half la...r in front of a blue wall.webp", + "original_name": "9wEN1j8G8FM2OvsLeIKejqBZtXXi2wDh_78fd39be87f430673055eb29c12640404a2536ea416a1691672db111e0216d93.webp" + } + ], + "field_59655": null, + "field_59646": [ + 3 + ] + }, + { + "id": 8, + "order": "8.00000000000000000000", + "created_on": "2025-02-05T10:15:13.177066+00:00", + "updated_on": "2025-02-05T10:19:03.067117+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59654": null, + "field_59645": [ + { + "name": "y1P9ulM5rL4cQFRcy18vl7lrmF9fa9eX_d6f44caa1e0c26cf4fa6140e6205220b601387af004a2d74cf175746226cfa8a.webp", + "visible_name": "A centered explosion of colorfu...der on a black background.webp", + "original_name": "y1P9ulM5rL4cQFRcy18vl7lrmF9fa9eX_d6f44caa1e0c26cf4fa6140e6205220b601387af004a2d74cf175746226cfa8a.webp" + } + ], + "field_59655": null, + "field_59646": [ + 3 + ] + }, + { + "id": 9, + "order": "9.00000000000000000000", + "created_on": "2025-02-05T10:19:11.863993+00:00", + "updated_on": "2025-02-05T10:19:48.303568+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59654": null, + "field_59645": [ + { + "name": "fPeEzUORQ9ZvGiatPk76YGW2SuSoKRqW_e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855.pdf", + "visible_name": "template.pdf", + "original_name": "fPeEzUORQ9ZvGiatPk76YGW2SuSoKRqW_e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855.pdf" + } + ], + "field_59655": null, + "field_59646": [ + 3 + ] + } + ], + "data_sync": null + } + ] + }, + { + "id": 2165, + "name": "Case 9 - Task Management", + "order": 9, + "type": "database", + "tables": [ + { + "id": 5687, + "name": "Tasks", + "order": 2, + "fields": [ + { + "id": 59686, + "type": "formula", + "name": "Name", + "description": null, + "order": 10, + "primary": true, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "duration_format": null, + "date_include_time": null, + "date_show_tzinfo": null, + "number_prefix": "", + "array_formula_type": null, + "nullable": false, + "date_format": null, + "date_time_format": null, + "date_force_timezone": null, + "number_suffix": "", + "number_separator": "", + "error": null, + "number_decimal_places": null, + "formula": "concat(left(upper(totext(field('Category'))),3),'-',year(field('Created on')),'-',field('ID'))", + "formula_type": "text" + }, + { + "id": 59660, + "type": "single_select", + "name": "Category", + "description": null, + "order": 1, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "select_options": [ + { + "id": 21011, + "value": "Operations", + "color": "darker-gray", + "order": 0 + }, + { + "id": 21012, + "value": "Management", + "color": "dark-brown", + "order": 1 + }, + { + "id": 21013, + "value": "Marketing", + "color": "light-cyan", + "order": 2 + }, + { + "id": 21014, + "value": "Finance", + "color": "darker-yellow", + "order": 3 + }, + { + "id": 21015, + "value": "Human Resources", + "color": "light-yellow", + "order": 4 + } + ] + }, + { + "id": 59661, + "type": "text", + "name": "Description", + "description": null, + "order": 2, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "text_default": "" + }, + { + "id": 59662, + "type": "text", + "name": "Title", + "description": null, + "order": 3, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "text_default": "" + }, + { + "id": 59663, + "type": "created_on", + "name": "Created on", + "description": null, + "order": 8, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "date_format": "ISO", + "date_include_time": false, + "date_time_format": "24", + "date_show_tzinfo": false, + "date_force_timezone": null + }, + { + "id": 59664, + "type": "formula", + "name": "ID", + "description": null, + "order": 9, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "duration_format": null, + "date_include_time": null, + "date_show_tzinfo": null, + "number_prefix": "", + "array_formula_type": null, + "nullable": false, + "date_format": null, + "date_time_format": null, + "date_force_timezone": null, + "number_suffix": "", + "number_separator": "", + "error": null, + "number_decimal_places": null, + "formula": "if(row_id() < 10,concat('0000',row_id()),if(row_id() < 100,concat('000',row_id()),if(row_id() < 1000,concat('00',row_id()),if(row_id() < 10000,concat('0',row_id()),row_id()))))", + "formula_type": "text" + }, + { + "id": 59665, + "type": "single_select", + "name": "Importance", + "description": null, + "order": 11, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "select_options": [ + { + "id": 21016, + "value": "Low", + "color": "cyan", + "order": 0 + }, + { + "id": 21017, + "value": "Medium", + "color": "blue", + "order": 1 + }, + { + "id": 21018, + "value": "High", + "color": "red", + "order": 2 + } + ] + }, + { + "id": 59666, + "type": "date", + "name": "Deadline", + "description": null, + "order": 12, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "date_format": "ISO", + "date_include_time": false, + "date_time_format": "24", + "date_show_tzinfo": false, + "date_force_timezone": null + }, + { + "id": 59687, + "type": "formula", + "name": "Is urgent", + "description": null, + "order": 13, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "duration_format": null, + "date_include_time": null, + "date_show_tzinfo": null, + "number_prefix": "", + "array_formula_type": null, + "nullable": false, + "date_format": null, + "date_time_format": null, + "date_force_timezone": null, + "number_suffix": "", + "number_separator": "", + "error": null, + "number_decimal_places": null, + "formula": "field('Deadline') < today() + date_interval(concat(field('Expected workload') / 6,' days'))", + "formula_type": "boolean" + }, + { + "id": 59689, + "type": "formula", + "name": "Is high priority", + "description": null, + "order": 14, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "duration_format": null, + "date_include_time": null, + "date_show_tzinfo": null, + "number_prefix": "", + "array_formula_type": null, + "nullable": false, + "date_format": null, + "date_time_format": null, + "date_force_timezone": null, + "number_suffix": "", + "number_separator": "", + "error": null, + "number_decimal_places": null, + "formula": "field('Importance') = 'High'", + "formula_type": "boolean" + }, + { + "id": 59697, + "type": "formula", + "name": "Desired start date", + "description": null, + "order": 15, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "duration_format": null, + "date_include_time": null, + "date_show_tzinfo": null, + "number_prefix": "", + "array_formula_type": null, + "nullable": false, + "date_format": null, + "date_time_format": null, + "date_force_timezone": null, + "number_suffix": "", + "number_separator": "", + "error": null, + "number_decimal_places": null, + "formula": "if(and(field('Is urgent'),field('Is high priority')),today(),if(and(field('Is urgent'),not(field('Is high priority'))),today() + date_interval('1 day'),if(and(not(field('Is urgent')),field('Is high priority')),today() + date_interval('3 days'),'')))", + "formula_type": "text" + }, + { + "id": 59667, + "type": "number", + "name": "Expected workload", + "description": null, + "order": 16, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "number_decimal_places": 0, + "number_negative": false, + "number_prefix": "", + "number_suffix": "hours", + "number_separator": "" + }, + { + "id": 59668, + "type": "link_row", + "name": "Contractor", + "description": null, + "order": 17, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "link_row_table_id": 5688, + "link_row_related_field_id": 59679, + "link_row_limit_selection_view_id": null, + "has_related_field": true + }, + { + "id": 59690, + "type": "formula", + "name": "Required fields valid", + "description": null, + "order": 18, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "duration_format": null, + "date_include_time": null, + "date_show_tzinfo": null, + "number_prefix": "", + "array_formula_type": null, + "nullable": false, + "date_format": null, + "date_time_format": null, + "date_force_timezone": null, + "number_suffix": "", + "number_separator": "", + "error": null, + "number_decimal_places": null, + "formula": "and(and(not(isblank(field('Importance'))),not(isblank(field('Deadline')))),not(isblank(field('Expected workload'))))", + "formula_type": "boolean" + }, + { + "id": 59692, + "type": "formula", + "name": "Contractor valid", + "description": null, + "order": 19, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "duration_format": null, + "date_include_time": null, + "date_show_tzinfo": null, + "number_prefix": "", + "array_formula_type": null, + "nullable": false, + "date_format": null, + "date_time_format": null, + "date_force_timezone": null, + "number_suffix": "", + "number_separator": "", + "error": null, + "number_decimal_places": null, + "formula": "or(count(field('Contractor')) = 0,regex_replace(join(lookup('Contractor','VAT Number'),''),'(GB)?([0-9]{9})','valid') = 'valid')", + "formula_type": "boolean" + }, + { + "id": 59698, + "type": "formula", + "name": "Task is valid", + "description": null, + "order": 20, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "duration_format": null, + "date_include_time": null, + "date_show_tzinfo": null, + "number_prefix": "", + "array_formula_type": null, + "nullable": false, + "date_format": null, + "date_time_format": null, + "date_force_timezone": null, + "number_suffix": "", + "number_separator": "", + "error": null, + "number_decimal_places": null, + "formula": "and(field('Required fields valid'),field('Contractor valid'))", + "formula_type": "boolean" + }, + { + "id": 59688, + "type": "formula", + "name": "Final start date", + "description": null, + "order": 21, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "duration_format": null, + "date_include_time": false, + "date_show_tzinfo": false, + "number_prefix": "", + "array_formula_type": null, + "nullable": true, + "date_format": "ISO", + "date_time_format": "24", + "date_force_timezone": null, + "number_suffix": "", + "number_separator": "", + "error": null, + "number_decimal_places": null, + "formula": "field('Deadline') - date_interval(concat(field('Expected workload') / 6 + 1,' days'))", + "formula_type": "date" + }, + { + "id": 59669, + "type": "formula", + "name": "Details", + "description": null, + "order": 22, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "duration_format": null, + "date_include_time": null, + "date_show_tzinfo": null, + "number_prefix": "", + "array_formula_type": null, + "nullable": false, + "date_format": null, + "date_time_format": null, + "date_force_timezone": null, + "number_suffix": "", + "number_separator": "", + "error": null, + "number_decimal_places": null, + "formula": "button(concat('https://example.com/builder/1059/preview/task-details/',row_id()),'Details')", + "formula_type": "button" + }, + { + "id": 59670, + "type": "date", + "name": "Actual start date", + "description": null, + "order": 23, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "date_format": "ISO", + "date_include_time": false, + "date_time_format": "24", + "date_show_tzinfo": false, + "date_force_timezone": null + }, + { + "id": 59699, + "type": "formula", + "name": "Start task", + "description": null, + "order": 24, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "duration_format": null, + "date_include_time": null, + "date_show_tzinfo": null, + "number_prefix": "", + "array_formula_type": null, + "nullable": false, + "date_format": null, + "date_time_format": null, + "date_force_timezone": null, + "number_suffix": "", + "number_separator": "", + "error": null, + "number_decimal_places": null, + "formula": "if(field('Task is valid'),button(concat('https://n8n.cloudron.getbaserow.com/webhook/set-start-date?id=',row_id()),'Start task'),button('','Task not valid'))", + "formula_type": "button" + }, + { + "id": 59671, + "type": "link_row", + "name": "Assets", + "description": null, + "order": 25, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "link_row_table_id": 5689, + "link_row_related_field_id": 59681, + "link_row_limit_selection_view_id": null, + "has_related_field": true + }, + { + "id": 59696, + "type": "formula", + "name": "Add asset", + "description": null, + "order": 26, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "duration_format": null, + "date_include_time": null, + "date_show_tzinfo": null, + "number_prefix": "", + "array_formula_type": null, + "nullable": false, + "date_format": null, + "date_time_format": null, + "date_force_timezone": null, + "number_suffix": "", + "number_separator": "", + "error": null, + "number_decimal_places": null, + "formula": "button(concat('https://example.com/form/iN6i2YJeJcUKB-cuouClfSpmU1LxvSgzWL3Nle5aBwY?prefill_Task=',field('Name'),'&hide_Task'),'Add asset')", + "formula_type": "button" + }, + { + "id": 59672, + "type": "link_row", + "name": "Assignee", + "description": null, + "order": 27, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "link_row_table_id": 5690, + "link_row_related_field_id": 59685, + "link_row_limit_selection_view_id": null, + "has_related_field": true + }, + { + "id": 59673, + "type": "single_select", + "name": "Status", + "description": null, + "order": 28, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "select_options": [ + { + "id": 21019, + "value": "Not started", + "color": "red", + "order": 0 + }, + { + "id": 21020, + "value": "In progress", + "color": "orange", + "order": 1 + }, + { + "id": 21021, + "value": "Completed", + "color": "green", + "order": 2 + } + ] + } + ], + "views": [ + { + "id": 26435, + "type": "grid", + "name": "All tasks", + "order": 1, + "ownership_type": "collaborative", + "owned_by": "frederik@baserow.io", + "filter_type": "AND", + "filters_disabled": false, + "filters": [], + "filter_groups": [], + "sortings": [], + "group_bys": [], + "decorations": [ + { + "id": 8724, + "type": "background_color", + "value_provider_type": "conditional_color", + "value_provider_conf": { + "colors": [ + { + "id": "77f5ba06-166f-4b45-8c17-ff45cf5d4290", + "color": "light-yellow", + "filters": [ + { + "id": "2c9ff0a1-174b-47e1-8c1b-db6bc8b3f9b9", + "type": "date_is_before", + "field": 59688, + "group": null, + "value": "Europe/Brussels??today" + }, + { + "id": "707a05fc-d2ec-4266-a039-f5705ca95750", + "type": "single_select_not_equal", + "field": 59673, + "group": null, + "value": "21021" + } + ], + "operator": "AND" + } + ] + }, + "order": 1 + } + ], + "public": false, + "row_identifier_type": "id", + "row_height_size": "medium", + "field_options": [ + { + "id": 261068, + "field_id": 59686, + "width": 200, + "hidden": false, + "order": 0, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261069, + "field_id": 59664, + "width": 200, + "hidden": true, + "order": 1, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261070, + "field_id": 59662, + "width": 165, + "hidden": false, + "order": 2, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261071, + "field_id": 59669, + "width": 127, + "hidden": false, + "order": 3, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261072, + "field_id": 59696, + "width": 142, + "hidden": false, + "order": 4, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261073, + "field_id": 59672, + "width": 135, + "hidden": false, + "order": 5, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261074, + "field_id": 59699, + "width": 200, + "hidden": true, + "order": 6, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261075, + "field_id": 59660, + "width": 152, + "hidden": false, + "order": 7, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261076, + "field_id": 59665, + "width": 143, + "hidden": false, + "order": 8, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261077, + "field_id": 59673, + "width": 125, + "hidden": false, + "order": 9, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261078, + "field_id": 59666, + "width": 141, + "hidden": false, + "order": 10, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261079, + "field_id": 59667, + "width": 200, + "hidden": false, + "order": 11, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261080, + "field_id": 59687, + "width": 125, + "hidden": false, + "order": 12, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261081, + "field_id": 59670, + "width": 200, + "hidden": false, + "order": 13, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261082, + "field_id": 59689, + "width": 200, + "hidden": false, + "order": 14, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261083, + "field_id": 59688, + "width": 200, + "hidden": false, + "order": 15, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261084, + "field_id": 59697, + "width": 200, + "hidden": false, + "order": 16, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261085, + "field_id": 59661, + "width": 554, + "hidden": false, + "order": 17, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261086, + "field_id": 59668, + "width": 200, + "hidden": false, + "order": 18, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261087, + "field_id": 59663, + "width": 200, + "hidden": false, + "order": 19, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261088, + "field_id": 59690, + "width": 200, + "hidden": false, + "order": 20, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261089, + "field_id": 59692, + "width": 200, + "hidden": false, + "order": 21, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261090, + "field_id": 59698, + "width": 200, + "hidden": false, + "order": 22, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261091, + "field_id": 59671, + "width": 200, + "hidden": false, + "order": 23, + "aggregation_type": "", + "aggregation_raw_type": "" + } + ] + }, + { + "id": 26436, + "type": "grid", + "name": "Valid tasks", + "order": 2, + "ownership_type": "collaborative", + "owned_by": "frederik@baserow.io", + "filter_type": "AND", + "filters_disabled": false, + "filters": [ + { + "id": 13959, + "field_id": 59698, + "type": "boolean", + "value": "1", + "group": null + } + ], + "filter_groups": [], + "sortings": [], + "group_bys": [], + "decorations": [], + "public": false, + "row_identifier_type": "id", + "row_height_size": "medium", + "field_options": [ + { + "id": 261092, + "field_id": 59686, + "width": 200, + "hidden": false, + "order": 0, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261093, + "field_id": 59664, + "width": 200, + "hidden": true, + "order": 1, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261094, + "field_id": 59662, + "width": 171, + "hidden": false, + "order": 2, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261095, + "field_id": 59660, + "width": 157, + "hidden": false, + "order": 3, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261096, + "field_id": 59665, + "width": 143, + "hidden": false, + "order": 4, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261097, + "field_id": 59666, + "width": 141, + "hidden": false, + "order": 5, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261098, + "field_id": 59667, + "width": 200, + "hidden": false, + "order": 6, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261099, + "field_id": 59687, + "width": 125, + "hidden": false, + "order": 7, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261100, + "field_id": 59689, + "width": 200, + "hidden": false, + "order": 8, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261101, + "field_id": 59697, + "width": 200, + "hidden": false, + "order": 9, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261102, + "field_id": 59661, + "width": 554, + "hidden": false, + "order": 10, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261103, + "field_id": 59668, + "width": 200, + "hidden": false, + "order": 11, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261104, + "field_id": 59663, + "width": 200, + "hidden": false, + "order": 12, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261105, + "field_id": 59690, + "width": 200, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261106, + "field_id": 59692, + "width": 200, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261107, + "field_id": 59698, + "width": 200, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + } + ] + }, + { + "id": 26437, + "type": "grid", + "name": "Invalid tasks", + "order": 3, + "ownership_type": "collaborative", + "owned_by": "frederik@baserow.io", + "filter_type": "AND", + "filters_disabled": false, + "filters": [ + { + "id": 13960, + "field_id": 59698, + "type": "boolean", + "value": "0", + "group": null + } + ], + "filter_groups": [], + "sortings": [], + "group_bys": [], + "decorations": [], + "public": false, + "row_identifier_type": "id", + "row_height_size": "medium", + "field_options": [ + { + "id": 261108, + "field_id": 59686, + "width": 200, + "hidden": false, + "order": 0, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261109, + "field_id": 59664, + "width": 200, + "hidden": true, + "order": 1, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261110, + "field_id": 59662, + "width": 171, + "hidden": false, + "order": 2, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261111, + "field_id": 59660, + "width": 157, + "hidden": false, + "order": 3, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261112, + "field_id": 59665, + "width": 143, + "hidden": false, + "order": 4, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261113, + "field_id": 59666, + "width": 141, + "hidden": false, + "order": 5, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261114, + "field_id": 59667, + "width": 200, + "hidden": false, + "order": 6, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261115, + "field_id": 59687, + "width": 125, + "hidden": false, + "order": 7, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261116, + "field_id": 59689, + "width": 200, + "hidden": false, + "order": 8, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261117, + "field_id": 59697, + "width": 200, + "hidden": false, + "order": 9, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261118, + "field_id": 59661, + "width": 554, + "hidden": false, + "order": 10, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261119, + "field_id": 59668, + "width": 200, + "hidden": false, + "order": 11, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261120, + "field_id": 59663, + "width": 200, + "hidden": false, + "order": 12, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261121, + "field_id": 59690, + "width": 200, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261122, + "field_id": 59692, + "width": 200, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261123, + "field_id": 59698, + "width": 200, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + } + ] + } + ], + "rows": [ + { + "id": 1, + "order": "1.00000000000000000000", + "created_on": "2025-02-05T07:48:00.081133+00:00", + "updated_on": "2025-02-05T10:39:28.148711+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59686": null, + "field_59660": 21015, + "field_59661": "Conduct onboarding for a new hire, including setting up payroll in the HR system, scheduling a welcome meeting with the team, providing access to company tools, and assigning required training materials.", + "field_59662": "Employee Onboarding", + "field_59663": null, + "field_59664": null, + "field_59665": 21017, + "field_59666": "2025-02-06", + "field_59687": null, + "field_59689": null, + "field_59697": null, + "field_59667": "12", + "field_59668": [], + "field_59690": null, + "field_59692": null, + "field_59698": null, + "field_59688": null, + "field_59669": null, + "field_59670": "2025-02-05", + "field_59699": null, + "field_59671": [], + "field_59696": null, + "field_59672": [ + 1 + ], + "field_59673": 21019 + }, + { + "id": 2, + "order": "2.00000000000000000000", + "created_on": "2025-02-05T07:48:00.081208+00:00", + "updated_on": "2025-02-05T10:39:29.443082+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59686": null, + "field_59660": 21014, + "field_59661": "Process and approve five supplier invoices by verifying amounts, ensuring correct account allocation, obtaining necessary approvals, and scheduling payment in the financial system.", + "field_59662": "Invoice Processing", + "field_59663": null, + "field_59664": null, + "field_59665": 21016, + "field_59666": "2025-02-20", + "field_59687": null, + "field_59689": null, + "field_59697": null, + "field_59667": "34", + "field_59668": [], + "field_59690": null, + "field_59692": null, + "field_59698": null, + "field_59688": null, + "field_59669": null, + "field_59670": null, + "field_59699": null, + "field_59671": [], + "field_59696": null, + "field_59672": [ + 2 + ], + "field_59673": 21019 + }, + { + "id": 3, + "order": "3.00000000000000000000", + "created_on": "2025-02-05T07:48:00.081236+00:00", + "updated_on": "2025-02-05T10:39:19.387237+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59686": null, + "field_59660": 21013, + "field_59661": "Write, design, and schedule three social media posts promoting the company\u2019s latest product update, ensuring alignment with brand guidelines and marketing strategy.", + "field_59662": "Social Media Posts", + "field_59663": null, + "field_59664": null, + "field_59665": 21017, + "field_59666": "2025-02-06", + "field_59687": null, + "field_59689": null, + "field_59697": null, + "field_59667": "53", + "field_59668": [ + 1 + ], + "field_59690": null, + "field_59692": null, + "field_59698": null, + "field_59688": null, + "field_59669": null, + "field_59670": null, + "field_59699": null, + "field_59671": [ + 5, + 6, + 7, + 8, + 9 + ], + "field_59696": null, + "field_59672": [ + 3 + ], + "field_59673": 21021 + }, + { + "id": 4, + "order": "4.00000000000000000000", + "created_on": "2025-02-05T07:48:00.081262+00:00", + "updated_on": "2025-02-05T10:39:22.743200+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59686": null, + "field_59660": 21011, + "field_59661": "Resolve 15 customer support tickets by diagnosing issues, providing solutions, updating ticket statuses, and following up to ensure customer satisfaction.", + "field_59662": "Customer Ticketing", + "field_59663": null, + "field_59664": null, + "field_59665": 21018, + "field_59666": "2025-02-06", + "field_59687": null, + "field_59689": null, + "field_59697": null, + "field_59667": "6", + "field_59668": [], + "field_59690": null, + "field_59692": null, + "field_59698": null, + "field_59688": null, + "field_59669": null, + "field_59670": null, + "field_59699": null, + "field_59671": [], + "field_59696": null, + "field_59672": [ + 3 + ], + "field_59673": 21021 + }, + { + "id": 5, + "order": "5.00000000000000000000", + "created_on": "2025-02-05T07:48:00.081289+00:00", + "updated_on": "2025-02-05T10:39:32.932913+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59686": null, + "field_59660": 21012, + "field_59661": "Break down an upcoming project into five key tasks, assign them to team members, set deadlines in the project management system, and communicate expectations to stakeholders.", + "field_59662": "Task Assignment", + "field_59663": null, + "field_59664": null, + "field_59665": 21017, + "field_59666": "2025-02-27", + "field_59687": null, + "field_59689": null, + "field_59697": null, + "field_59667": "11", + "field_59668": [], + "field_59690": null, + "field_59692": null, + "field_59698": null, + "field_59688": null, + "field_59669": null, + "field_59670": null, + "field_59699": null, + "field_59671": [], + "field_59696": null, + "field_59672": [ + 4 + ], + "field_59673": 21020 + }, + { + "id": 6, + "order": "6.00000000000000000000", + "created_on": "2025-02-05T07:48:00.081315+00:00", + "updated_on": "2025-02-05T10:39:34.106501+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59686": null, + "field_59660": 21011, + "field_59661": "Install security patches and update software on all employee workstations, ensuring compatibility, testing functionality, and documenting changes for compliance.", + "field_59662": "System Updates", + "field_59663": null, + "field_59664": null, + "field_59665": 21016, + "field_59666": "2025-02-11", + "field_59687": null, + "field_59689": null, + "field_59697": null, + "field_59667": "9", + "field_59668": [ + 2 + ], + "field_59690": null, + "field_59692": null, + "field_59698": null, + "field_59688": null, + "field_59669": null, + "field_59670": null, + "field_59699": null, + "field_59671": [ + 1 + ], + "field_59696": null, + "field_59672": [ + 3 + ], + "field_59673": 21020 + }, + { + "id": 7, + "order": "7.00000000000000000000", + "created_on": "2025-02-05T07:48:00.081340+00:00", + "updated_on": "2025-02-05T10:39:24.070108+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59686": null, + "field_59660": 21011, + "field_59661": "Conduct a physical inventory count of all high-value products, compare results with digital records, report discrepancies, and update the inventory management system.", + "field_59662": "Inventory Check", + "field_59663": null, + "field_59664": null, + "field_59665": 21017, + "field_59666": "2025-02-08", + "field_59687": null, + "field_59689": null, + "field_59697": null, + "field_59667": "23", + "field_59668": [ + 3 + ], + "field_59690": null, + "field_59692": null, + "field_59698": null, + "field_59688": null, + "field_59669": null, + "field_59670": null, + "field_59699": null, + "field_59671": [ + 2, + 3, + 4 + ], + "field_59696": null, + "field_59672": [ + 3 + ], + "field_59673": 21021 + }, + { + "id": 8, + "order": "8.00000000000000000000", + "created_on": "2025-02-05T07:48:00.081365+00:00", + "updated_on": "2025-02-05T10:39:35.378363+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59686": null, + "field_59660": 21013, + "field_59661": "Follow up with five potential clients via email or phone, answer questions, provide additional information, and schedule meetings to move them through the sales pipeline.", + "field_59662": "Client Follow-Up", + "field_59663": null, + "field_59664": null, + "field_59665": 21018, + "field_59666": "2025-02-07", + "field_59687": null, + "field_59689": null, + "field_59697": null, + "field_59667": "45", + "field_59668": [], + "field_59690": null, + "field_59692": null, + "field_59698": null, + "field_59688": null, + "field_59669": null, + "field_59670": null, + "field_59699": null, + "field_59671": [], + "field_59696": null, + "field_59672": [ + 3 + ], + "field_59673": 21020 + }, + { + "id": 9, + "order": "9.00000000000000000000", + "created_on": "2025-02-05T07:48:00.081389+00:00", + "updated_on": "2025-02-05T10:39:35.770470+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59686": null, + "field_59660": 21012, + "field_59661": "Review and update one company policy by assessing current regulations, identifying gaps, revising wording, obtaining approval, and publishing the final version.", + "field_59662": "Policy Review", + "field_59663": null, + "field_59664": null, + "field_59665": 21018, + "field_59666": "2025-02-11", + "field_59687": null, + "field_59689": null, + "field_59697": null, + "field_59667": "16", + "field_59668": [ + 4 + ], + "field_59690": null, + "field_59692": null, + "field_59698": null, + "field_59688": null, + "field_59669": null, + "field_59670": null, + "field_59699": null, + "field_59671": [], + "field_59696": null, + "field_59672": [ + 4 + ], + "field_59673": 21020 + }, + { + "id": 10, + "order": "10.00000000000000000000", + "created_on": "2025-02-05T07:48:00.081413+00:00", + "updated_on": "2025-02-05T10:39:36.077388+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59686": null, + "field_59660": 21012, + "field_59661": "Conduct one-on-one performance reviews with three employees, discuss achievements and challenges, document feedback, and outline action steps for improvement.", + "field_59662": "Performance Reviews", + "field_59663": null, + "field_59664": null, + "field_59665": 21018, + "field_59666": "2025-02-28", + "field_59687": null, + "field_59689": null, + "field_59697": null, + "field_59667": "30", + "field_59668": [], + "field_59690": null, + "field_59692": null, + "field_59698": null, + "field_59688": null, + "field_59669": null, + "field_59670": null, + "field_59699": null, + "field_59671": [], + "field_59696": null, + "field_59672": [ + 4 + ], + "field_59673": 21020 + } + ], + "data_sync": null + }, + { + "id": 5688, + "name": "Contractors", + "order": 3, + "fields": [ + { + "id": 59674, + "type": "text", + "name": "Company Name", + "description": null, + "order": 0, + "primary": true, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "text_default": "" + }, + { + "id": 59675, + "type": "text", + "name": "Address", + "description": null, + "order": 1, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "text_default": "" + }, + { + "id": 59676, + "type": "email", + "name": "Email", + "description": null, + "order": 2, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false + }, + { + "id": 59677, + "type": "phone_number", + "name": "Phone", + "description": null, + "order": 3, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false + }, + { + "id": 59678, + "type": "text", + "name": "VAT Number", + "description": null, + "order": 4, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "text_default": "" + }, + { + "id": 59691, + "type": "formula", + "name": "Formula", + "description": null, + "order": 5, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "duration_format": null, + "date_include_time": null, + "date_show_tzinfo": null, + "number_prefix": "", + "array_formula_type": null, + "nullable": false, + "date_format": null, + "date_time_format": null, + "date_force_timezone": null, + "number_suffix": "", + "number_separator": "", + "error": null, + "number_decimal_places": null, + "formula": "regex_replace(field('VAT Number'),'(GB)?([0-9]{9})','')", + "formula_type": "text" + }, + { + "id": 59679, + "type": "link_row", + "name": "Tasks", + "description": null, + "order": 6, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "link_row_table_id": 5687, + "link_row_related_field_id": 59668, + "link_row_limit_selection_view_id": null, + "has_related_field": true + } + ], + "views": [ + { + "id": 26438, + "type": "grid", + "name": "All contractors", + "order": 1, + "ownership_type": "collaborative", + "owned_by": "frederik@baserow.io", + "filter_type": "AND", + "filters_disabled": false, + "filters": [], + "filter_groups": [], + "sortings": [], + "group_bys": [], + "decorations": [], + "public": false, + "row_identifier_type": "id", + "row_height_size": "small", + "field_options": [ + { + "id": 261124, + "field_id": 59674, + "width": 200, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261125, + "field_id": 59675, + "width": 200, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261126, + "field_id": 59676, + "width": 200, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261127, + "field_id": 59677, + "width": 158, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261128, + "field_id": 59678, + "width": 200, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261129, + "field_id": 59679, + "width": 200, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261130, + "field_id": 59691, + "width": 200, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + } + ] + } + ], + "rows": [ + { + "id": 1, + "order": "1.00000000000000000000", + "created_on": "2025-02-05T08:42:47.025930+00:00", + "updated_on": "2025-02-05T08:50:20.819069+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59674": "BrightBuild Ltd", + "field_59675": "12 Greenway Street, London, SW1A 1AA", + "field_59676": "info@brightbuild.co.uk", + "field_59677": "+44 20 7946 0123", + "field_59678": "GB123456789", + "field_59691": null, + "field_59679": [ + 3 + ] + }, + { + "id": 2, + "order": "2.00000000000000000000", + "created_on": "2025-02-05T08:42:47.025996+00:00", + "updated_on": "2025-02-05T08:42:47.025996+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59674": "ProTech Solutions", + "field_59675": "45 Kings Road, Manchester, M1 3LD", + "field_59676": "contact@protechsolutions.co.uk", + "field_59677": "+44 161 555 6789", + "field_59678": "GB987654321", + "field_59691": null, + "field_59679": [ + 6 + ] + }, + { + "id": 3, + "order": "3.00000000000000000000", + "created_on": "2025-02-05T08:42:47.026022+00:00", + "updated_on": "2025-02-05T08:42:47.026022+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59674": "EcoElectrics UK", + "field_59675": "78 Solar Avenue, Birmingham, B2 4QA", + "field_59676": "support@ecoelectrics.co.uk", + "field_59677": "+44 121 432 8765", + "field_59678": "GB456123789", + "field_59691": null, + "field_59679": [ + 7 + ] + }, + { + "id": 4, + "order": "4.00000000000000000000", + "created_on": "2025-02-05T08:42:47.026045+00:00", + "updated_on": "2025-02-05T08:42:47.026045+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59674": "SwiftLogistics", + "field_59675": "22 Dockside Lane, Liverpool, L3 1AB", + "field_59676": "admin@swiftlogistics.co.uk", + "field_59677": "+44 151 789 6543", + "field_59678": "GB321654987", + "field_59691": null, + "field_59679": [ + 9 + ] + }, + { + "id": 5, + "order": "5.00000000000000000000", + "created_on": "2025-02-05T08:42:47.026069+00:00", + "updated_on": "2025-02-05T08:42:47.026069+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59674": "Regal Interiors", + "field_59675": "89 High Street, Edinburgh, EH2 4PH", + "field_59676": "sales@regalinteriors.co.uk", + "field_59677": "+44 131 246 9870", + "field_59678": "GB654987321", + "field_59691": null, + "field_59679": [] + } + ], + "data_sync": null + }, + { + "id": 5689, + "name": "Asset repository", + "order": 4, + "fields": [ + { + "id": 59693, + "type": "formula", + "name": "Name", + "description": null, + "order": 0, + "primary": true, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "duration_format": null, + "date_include_time": null, + "date_show_tzinfo": null, + "number_prefix": "", + "array_formula_type": null, + "nullable": true, + "date_format": null, + "date_time_format": null, + "date_force_timezone": null, + "number_suffix": "", + "number_separator": "", + "error": null, + "number_decimal_places": null, + "formula": "get_file_visible_name(index(field('File'),0))", + "formula_type": "text" + }, + { + "id": 59680, + "type": "file", + "name": "File", + "description": null, + "order": 1, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false + }, + { + "id": 59694, + "type": "formula", + "name": "is Image", + "description": null, + "order": 2, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "duration_format": null, + "date_include_time": null, + "date_show_tzinfo": null, + "number_prefix": "", + "array_formula_type": null, + "nullable": true, + "date_format": null, + "date_time_format": null, + "date_force_timezone": null, + "number_suffix": "", + "number_separator": "", + "error": null, + "number_decimal_places": null, + "formula": "is_image(index(field('File'),0))", + "formula_type": "boolean" + }, + { + "id": 59681, + "type": "link_row", + "name": "Task", + "description": null, + "order": 3, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "link_row_table_id": 5687, + "link_row_related_field_id": 59671, + "link_row_limit_selection_view_id": null, + "has_related_field": true + } + ], + "views": [ + { + "id": 26439, + "type": "grid", + "name": "All assets", + "order": 1, + "ownership_type": "collaborative", + "owned_by": "frederik@baserow.io", + "filter_type": "AND", + "filters_disabled": false, + "filters": [], + "filter_groups": [], + "sortings": [], + "group_bys": [], + "decorations": [], + "public": false, + "row_identifier_type": "id", + "row_height_size": "small", + "field_options": [ + { + "id": 261131, + "field_id": 59693, + "width": 200, + "hidden": false, + "order": 0, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261132, + "field_id": 59681, + "width": 200, + "hidden": false, + "order": 1, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261133, + "field_id": 59680, + "width": 192, + "hidden": false, + "order": 2, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261134, + "field_id": 59694, + "width": 185, + "hidden": false, + "order": 3, + "aggregation_type": "", + "aggregation_raw_type": "" + } + ] + }, + { + "id": 26440, + "type": "grid", + "name": "Image assets", + "order": 2, + "ownership_type": "collaborative", + "owned_by": "frederik@baserow.io", + "filter_type": "AND", + "filters_disabled": false, + "filters": [ + { + "id": 13961, + "field_id": 59694, + "type": "boolean", + "value": "1", + "group": null + } + ], + "filter_groups": [], + "sortings": [], + "group_bys": [], + "decorations": [], + "public": false, + "row_identifier_type": "id", + "row_height_size": "small", + "field_options": [ + { + "id": 261135, + "field_id": 59693, + "width": 200, + "hidden": false, + "order": 0, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261136, + "field_id": 59681, + "width": 200, + "hidden": false, + "order": 1, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261137, + "field_id": 59680, + "width": 192, + "hidden": false, + "order": 2, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261138, + "field_id": 59694, + "width": 185, + "hidden": false, + "order": 3, + "aggregation_type": "", + "aggregation_raw_type": "" + } + ] + }, + { + "id": 26441, + "type": "grid", + "name": "Other assets", + "order": 3, + "ownership_type": "collaborative", + "owned_by": "frederik@baserow.io", + "filter_type": "AND", + "filters_disabled": false, + "filters": [ + { + "id": 13962, + "field_id": 59694, + "type": "boolean", + "value": "0", + "group": null + } + ], + "filter_groups": [], + "sortings": [], + "group_bys": [], + "decorations": [], + "public": false, + "row_identifier_type": "id", + "row_height_size": "small", + "field_options": [ + { + "id": 261139, + "field_id": 59693, + "width": 200, + "hidden": false, + "order": 0, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261140, + "field_id": 59681, + "width": 200, + "hidden": false, + "order": 1, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261141, + "field_id": 59680, + "width": 192, + "hidden": false, + "order": 2, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261142, + "field_id": 59694, + "width": 185, + "hidden": false, + "order": 3, + "aggregation_type": "", + "aggregation_raw_type": "" + } + ] + }, + { + "id": 26442, + "type": "form", + "name": "Add new asset", + "order": 4, + "ownership_type": "collaborative", + "owned_by": "frederik@baserow.io", + "public": true, + "title": "", + "description": "", + "cover_image": null, + "logo_image": null, + "submit_text": "Submit", + "submit_action": "MESSAGE", + "submit_action_message": "The asset has been added", + "submit_action_redirect_url": "", + "field_options": [ + { + "id": 25246, + "field_id": 59681, + "name": "", + "description": "The task related to the asset", + "enabled": true, + "required": true, + "order": 0, + "show_when_matching_conditions": false, + "condition_type": "AND", + "conditions": [], + "condition_groups": [], + "field_component": "default", + "include_all_select_options": true, + "allowed_select_options": [] + }, + { + "id": 25247, + "field_id": 59680, + "name": "", + "description": "Select a single file to be attached to the task", + "enabled": true, + "required": true, + "order": 1, + "show_when_matching_conditions": false, + "condition_type": "AND", + "conditions": [], + "condition_groups": [], + "field_component": "default", + "include_all_select_options": true, + "allowed_select_options": [] + }, + { + "id": 25248, + "field_id": 59693, + "name": "", + "description": "", + "enabled": false, + "required": true, + "order": 2, + "show_when_matching_conditions": false, + "condition_type": "AND", + "conditions": [], + "condition_groups": [], + "field_component": "default", + "include_all_select_options": true, + "allowed_select_options": [] + }, + { + "id": 25249, + "field_id": 59694, + "name": "", + "description": "", + "enabled": false, + "required": true, + "order": 3, + "show_when_matching_conditions": false, + "condition_type": "AND", + "conditions": [], + "condition_groups": [], + "field_component": "default", + "include_all_select_options": true, + "allowed_select_options": [] + } + ] + } + ], + "rows": [ + { + "id": 1, + "order": "1.00000000000000000000", + "created_on": "2025-02-05T10:02:37.395368+00:00", + "updated_on": "2025-02-05T10:13:44.901137+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59693": null, + "field_59680": [ + { + "name": "WnJgHQmzjyeKVF2EWnOw3JAp0fPIEgfB_e7fa567aac5fdffb5569ad7301a186889981b3f504d39250a6aebbce0ac452d6.pdf", + "visible_name": "contract.pdf", + "original_name": "WnJgHQmzjyeKVF2EWnOw3JAp0fPIEgfB_e7fa567aac5fdffb5569ad7301a186889981b3f504d39250a6aebbce0ac452d6.pdf" + } + ], + "field_59694": null, + "field_59681": [ + 6 + ] + }, + { + "id": 2, + "order": "2.00000000000000000000", + "created_on": "2025-02-05T10:02:37.395435+00:00", + "updated_on": "2025-02-05T10:13:59.627865+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59693": null, + "field_59680": [ + { + "name": "WnJgHQmzjyeKVF2EWnOw3JAp0fPIEgfB_e7fa567aac5fdffb5569ad7301a186889981b3f504d39250a6aebbce0ac452d6.pdf", + "visible_name": "contract.pdf", + "original_name": "WnJgHQmzjyeKVF2EWnOw3JAp0fPIEgfB_e7fa567aac5fdffb5569ad7301a186889981b3f504d39250a6aebbce0ac452d6.pdf" + } + ], + "field_59694": null, + "field_59681": [ + 7 + ] + }, + { + "id": 3, + "order": "3.00000000000000000000", + "created_on": "2025-02-05T10:14:06.969361+00:00", + "updated_on": "2025-02-05T10:14:19.248714+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59693": null, + "field_59680": [ + { + "name": "sv5sVjuuU4vka45DtxdrVEgB41z41kcF_d15e48a86f901b103b995ee1aa8611a5676f234dbec030d7f20a40956610ab55.jpeg", + "visible_name": "pallets.jpeg", + "original_name": "sv5sVjuuU4vka45DtxdrVEgB41z41kcF_d15e48a86f901b103b995ee1aa8611a5676f234dbec030d7f20a40956610ab55.jpeg" + } + ], + "field_59694": null, + "field_59681": [ + 7 + ] + }, + { + "id": 4, + "order": "4.00000000000000000000", + "created_on": "2025-02-05T10:14:21.840714+00:00", + "updated_on": "2025-02-05T10:14:35.405845+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59693": null, + "field_59680": [ + { + "name": "EkOQ883tzFvi17Sg02ARsvmz3kreg5K7_cd993b3a02bdd9f086b6496b2dfd4ad22f245b78458a9aa28c90ba3493188334.jpeg", + "visible_name": "tools.jpeg", + "original_name": "EkOQ883tzFvi17Sg02ARsvmz3kreg5K7_cd993b3a02bdd9f086b6496b2dfd4ad22f245b78458a9aa28c90ba3493188334.jpeg" + } + ], + "field_59694": null, + "field_59681": [ + 7 + ] + }, + { + "id": 5, + "order": "5.00000000000000000000", + "created_on": "2025-02-05T10:14:58.718123+00:00", + "updated_on": "2025-02-05T10:15:11.710567+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59693": null, + "field_59680": [ + { + "name": "WnJgHQmzjyeKVF2EWnOw3JAp0fPIEgfB_e7fa567aac5fdffb5569ad7301a186889981b3f504d39250a6aebbce0ac452d6.pdf", + "visible_name": "contract.pdf", + "original_name": "WnJgHQmzjyeKVF2EWnOw3JAp0fPIEgfB_e7fa567aac5fdffb5569ad7301a186889981b3f504d39250a6aebbce0ac452d6.pdf" + } + ], + "field_59694": null, + "field_59681": [ + 3 + ] + }, + { + "id": 6, + "order": "6.00000000000000000000", + "created_on": "2025-02-05T10:15:06.267566+00:00", + "updated_on": "2025-02-05T10:18:37.530230+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59693": null, + "field_59680": [ + { + "name": "mQO3bvgYePOu0rWoAz7kocRAO2QKN75M_38f6c19434e047b7681f6ef89cd68ba62779308825f039f30d0afa2ef4521b80.webp", + "visible_name": "A 3D render of a rainbow colore...g above a reflective lake.webp", + "original_name": "mQO3bvgYePOu0rWoAz7kocRAO2QKN75M_38f6c19434e047b7681f6ef89cd68ba62779308825f039f30d0afa2ef4521b80.webp" + } + ], + "field_59694": null, + "field_59681": [ + 3 + ] + }, + { + "id": 7, + "order": "7.00000000000000000000", + "created_on": "2025-02-05T10:15:07.735556+00:00", + "updated_on": "2025-02-05T10:18:52.363224+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59693": null, + "field_59680": [ + { + "name": "9wEN1j8G8FM2OvsLeIKejqBZtXXi2wDh_78fd39be87f430673055eb29c12640404a2536ea416a1691672db111e0216d93.webp", + "visible_name": "A blue orange sliced in half la...r in front of a blue wall.webp", + "original_name": "9wEN1j8G8FM2OvsLeIKejqBZtXXi2wDh_78fd39be87f430673055eb29c12640404a2536ea416a1691672db111e0216d93.webp" + } + ], + "field_59694": null, + "field_59681": [ + 3 + ] + }, + { + "id": 8, + "order": "8.00000000000000000000", + "created_on": "2025-02-05T10:15:13.177066+00:00", + "updated_on": "2025-02-05T10:19:03.067117+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59693": null, + "field_59680": [ + { + "name": "y1P9ulM5rL4cQFRcy18vl7lrmF9fa9eX_d6f44caa1e0c26cf4fa6140e6205220b601387af004a2d74cf175746226cfa8a.webp", + "visible_name": "A centered explosion of colorfu...der on a black background.webp", + "original_name": "y1P9ulM5rL4cQFRcy18vl7lrmF9fa9eX_d6f44caa1e0c26cf4fa6140e6205220b601387af004a2d74cf175746226cfa8a.webp" + } + ], + "field_59694": null, + "field_59681": [ + 3 + ] + }, + { + "id": 9, + "order": "9.00000000000000000000", + "created_on": "2025-02-05T10:19:11.863993+00:00", + "updated_on": "2025-02-05T10:19:48.303568+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59693": null, + "field_59680": [ + { + "name": "fPeEzUORQ9ZvGiatPk76YGW2SuSoKRqW_e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855.pdf", + "visible_name": "template.pdf", + "original_name": "fPeEzUORQ9ZvGiatPk76YGW2SuSoKRqW_e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855.pdf" + } + ], + "field_59694": null, + "field_59681": [ + 3 + ] + } + ], + "data_sync": null + }, + { + "id": 5690, + "name": "Team members", + "order": 5, + "fields": [ + { + "id": 59682, + "type": "text", + "name": "Name", + "description": null, + "order": 0, + "primary": true, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "text_default": "" + }, + { + "id": 59683, + "type": "email", + "name": "Email", + "description": null, + "order": 1, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false + }, + { + "id": 59684, + "type": "phone_number", + "name": "Phone", + "description": null, + "order": 2, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false + }, + { + "id": 59685, + "type": "link_row", + "name": "Tasks", + "description": null, + "order": 3, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "link_row_table_id": 5687, + "link_row_related_field_id": 59672, + "link_row_limit_selection_view_id": null, + "has_related_field": true + }, + { + "id": 59695, + "type": "formula", + "name": "Open expected workload", + "description": null, + "order": 4, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "duration_format": null, + "date_include_time": null, + "date_show_tzinfo": null, + "number_prefix": "", + "array_formula_type": null, + "nullable": false, + "date_format": null, + "date_time_format": null, + "date_force_timezone": null, + "number_suffix": "hours", + "number_separator": "", + "error": null, + "number_decimal_places": 0, + "formula": "sum(filter(lookup('Tasks','Expected workload'),lookup('Tasks','Status') != 'Completed'))", + "formula_type": "number" + } + ], + "views": [ + { + "id": 26443, + "type": "grid", + "name": "All team members", + "order": 1, + "ownership_type": "collaborative", + "owned_by": "frederik@baserow.io", + "filter_type": "AND", + "filters_disabled": false, + "filters": [], + "filter_groups": [], + "sortings": [], + "group_bys": [], + "decorations": [], + "public": false, + "row_identifier_type": "id", + "row_height_size": "small", + "field_options": [ + { + "id": 261143, + "field_id": 59682, + "width": 131, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261144, + "field_id": 59683, + "width": 197, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261145, + "field_id": 59684, + "width": 126, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261146, + "field_id": 59685, + "width": 200, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261147, + "field_id": 59695, + "width": 242, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + } + ] + } + ], + "rows": [ + { + "id": 1, + "order": "1.00000000000000000000", + "created_on": "2025-02-05T10:35:51.289680+00:00", + "updated_on": "2025-02-05T10:36:38.792224+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59682": "Allie Ecker", + "field_59683": "allie.ecker@example.com", + "field_59684": "(949) 873-7292", + "field_59685": [ + 1 + ], + "field_59695": null + }, + { + "id": 2, + "order": "2.00000000000000000000", + "created_on": "2025-02-05T10:35:51.289766+00:00", + "updated_on": "2025-02-05T10:36:38.792329+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59682": "Bran Lopez", + "field_59683": "bran.lopez@example.com", + "field_59684": "(650) 869-3623", + "field_59685": [ + 2 + ], + "field_59695": null + }, + { + "id": 3, + "order": "3.00000000000000000000", + "created_on": "2025-02-05T10:36:38.575119+00:00", + "updated_on": "2025-02-05T10:36:38.792357+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59682": "Cinda Pullen", + "field_59683": "cinda.pullen@example.com", + "field_59684": "(213) 743-1636", + "field_59685": [ + 3, + 4, + 6, + 7, + 8 + ], + "field_59695": null + }, + { + "id": 4, + "order": "4.00000000000000000000", + "created_on": "2025-02-05T10:36:38.575189+00:00", + "updated_on": "2025-02-05T10:36:38.792399+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59682": "Clayton Best", + "field_59683": "clayton.best@example.com", + "field_59684": "(916) 478-0153", + "field_59685": [ + 5, + 9, + 10 + ], + "field_59695": null + } + ], + "data_sync": null + } + ] + }, + { + "id": 2166, + "name": "Case 10 - Task Management", + "order": 10, + "type": "database", + "tables": [ + { + "id": 5691, + "name": "Tasks", + "order": 2, + "fields": [ + { + "id": 59726, + "type": "formula", + "name": "Name", + "description": null, + "order": 10, + "primary": true, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "duration_format": null, + "date_include_time": null, + "date_show_tzinfo": null, + "number_prefix": "", + "array_formula_type": null, + "nullable": false, + "date_format": null, + "date_time_format": null, + "date_force_timezone": null, + "number_suffix": "", + "number_separator": "", + "error": null, + "number_decimal_places": null, + "formula": "concat(left(upper(totext(field('Category'))),3),'-',year(field('Created on')),'-',field('ID'))", + "formula_type": "text" + }, + { + "id": 59700, + "type": "single_select", + "name": "Category", + "description": null, + "order": 1, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "select_options": [ + { + "id": 21022, + "value": "Operations", + "color": "darker-gray", + "order": 0 + }, + { + "id": 21023, + "value": "Management", + "color": "dark-brown", + "order": 1 + }, + { + "id": 21024, + "value": "Marketing", + "color": "light-cyan", + "order": 2 + }, + { + "id": 21025, + "value": "Finance", + "color": "darker-yellow", + "order": 3 + }, + { + "id": 21026, + "value": "Human Resources", + "color": "light-yellow", + "order": 4 + } + ] + }, + { + "id": 59701, + "type": "text", + "name": "Description", + "description": null, + "order": 2, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "text_default": "" + }, + { + "id": 59702, + "type": "text", + "name": "Title", + "description": null, + "order": 3, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "text_default": "" + }, + { + "id": 59703, + "type": "created_on", + "name": "Created on", + "description": null, + "order": 8, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "date_format": "ISO", + "date_include_time": false, + "date_time_format": "24", + "date_show_tzinfo": false, + "date_force_timezone": null + }, + { + "id": 59704, + "type": "formula", + "name": "ID", + "description": null, + "order": 9, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "duration_format": null, + "date_include_time": null, + "date_show_tzinfo": null, + "number_prefix": "", + "array_formula_type": null, + "nullable": false, + "date_format": null, + "date_time_format": null, + "date_force_timezone": null, + "number_suffix": "", + "number_separator": "", + "error": null, + "number_decimal_places": null, + "formula": "if(row_id() < 10,concat('0000',row_id()),if(row_id() < 100,concat('000',row_id()),if(row_id() < 1000,concat('00',row_id()),if(row_id() < 10000,concat('0',row_id()),row_id()))))", + "formula_type": "text" + }, + { + "id": 59705, + "type": "single_select", + "name": "Importance", + "description": null, + "order": 11, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "select_options": [ + { + "id": 21027, + "value": "Low", + "color": "cyan", + "order": 0 + }, + { + "id": 21028, + "value": "Medium", + "color": "blue", + "order": 1 + }, + { + "id": 21029, + "value": "High", + "color": "red", + "order": 2 + } + ] + }, + { + "id": 59706, + "type": "date", + "name": "Deadline", + "description": null, + "order": 12, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "date_format": "ISO", + "date_include_time": false, + "date_time_format": "24", + "date_show_tzinfo": false, + "date_force_timezone": null + }, + { + "id": 59727, + "type": "formula", + "name": "Is urgent", + "description": null, + "order": 13, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "duration_format": null, + "date_include_time": null, + "date_show_tzinfo": null, + "number_prefix": "", + "array_formula_type": null, + "nullable": false, + "date_format": null, + "date_time_format": null, + "date_force_timezone": null, + "number_suffix": "", + "number_separator": "", + "error": null, + "number_decimal_places": null, + "formula": "field('Deadline') < today() + date_interval(concat(field('Expected workload') / 6,' days'))", + "formula_type": "boolean" + }, + { + "id": 59730, + "type": "formula", + "name": "Is high priority", + "description": null, + "order": 14, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "duration_format": null, + "date_include_time": null, + "date_show_tzinfo": null, + "number_prefix": "", + "array_formula_type": null, + "nullable": false, + "date_format": null, + "date_time_format": null, + "date_force_timezone": null, + "number_suffix": "", + "number_separator": "", + "error": null, + "number_decimal_places": null, + "formula": "field('Importance') = 'High'", + "formula_type": "boolean" + }, + { + "id": 59740, + "type": "formula", + "name": "Desired start date", + "description": null, + "order": 15, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "duration_format": null, + "date_include_time": null, + "date_show_tzinfo": null, + "number_prefix": "", + "array_formula_type": null, + "nullable": false, + "date_format": null, + "date_time_format": null, + "date_force_timezone": null, + "number_suffix": "", + "number_separator": "", + "error": null, + "number_decimal_places": null, + "formula": "if(and(field('Is urgent'),field('Is high priority')),today(),if(and(field('Is urgent'),not(field('Is high priority'))),today() + date_interval('1 day'),if(and(not(field('Is urgent')),field('Is high priority')),today() + date_interval('3 days'),'')))", + "formula_type": "text" + }, + { + "id": 59707, + "type": "number", + "name": "Expected workload", + "description": null, + "order": 16, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "number_decimal_places": 0, + "number_negative": false, + "number_prefix": "", + "number_suffix": "hours", + "number_separator": "" + }, + { + "id": 59708, + "type": "link_row", + "name": "Contractor", + "description": null, + "order": 17, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "link_row_table_id": 5692, + "link_row_related_field_id": 59719, + "link_row_limit_selection_view_id": null, + "has_related_field": true + }, + { + "id": 59731, + "type": "formula", + "name": "Required fields valid", + "description": null, + "order": 18, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "duration_format": null, + "date_include_time": null, + "date_show_tzinfo": null, + "number_prefix": "", + "array_formula_type": null, + "nullable": false, + "date_format": null, + "date_time_format": null, + "date_force_timezone": null, + "number_suffix": "", + "number_separator": "", + "error": null, + "number_decimal_places": null, + "formula": "and(and(not(isblank(field('Importance'))),not(isblank(field('Deadline')))),not(isblank(field('Expected workload'))))", + "formula_type": "boolean" + }, + { + "id": 59732, + "type": "formula", + "name": "Contractor valid", + "description": null, + "order": 19, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "duration_format": null, + "date_include_time": null, + "date_show_tzinfo": null, + "number_prefix": "", + "array_formula_type": null, + "nullable": false, + "date_format": null, + "date_time_format": null, + "date_force_timezone": null, + "number_suffix": "", + "number_separator": "", + "error": null, + "number_decimal_places": null, + "formula": "or(count(field('Contractor')) = 0,regex_replace(join(lookup('Contractor','VAT Number'),''),'(GB)?([0-9]{9})','valid') = 'valid')", + "formula_type": "boolean" + }, + { + "id": 59741, + "type": "formula", + "name": "Task is valid", + "description": null, + "order": 20, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "duration_format": null, + "date_include_time": null, + "date_show_tzinfo": null, + "number_prefix": "", + "array_formula_type": null, + "nullable": false, + "date_format": null, + "date_time_format": null, + "date_force_timezone": null, + "number_suffix": "", + "number_separator": "", + "error": null, + "number_decimal_places": null, + "formula": "and(field('Required fields valid'),field('Contractor valid'))", + "formula_type": "boolean" + }, + { + "id": 59728, + "type": "formula", + "name": "Final start date", + "description": null, + "order": 21, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "duration_format": null, + "date_include_time": false, + "date_show_tzinfo": false, + "number_prefix": "", + "array_formula_type": null, + "nullable": true, + "date_format": "ISO", + "date_time_format": "24", + "date_force_timezone": null, + "number_suffix": "", + "number_separator": "", + "error": null, + "number_decimal_places": null, + "formula": "field('Deadline') - date_interval(concat(field('Expected workload') / 6 + 1,' days'))", + "formula_type": "date" + }, + { + "id": 59709, + "type": "formula", + "name": "Details", + "description": null, + "order": 22, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "duration_format": null, + "date_include_time": null, + "date_show_tzinfo": null, + "number_prefix": "", + "array_formula_type": null, + "nullable": false, + "date_format": null, + "date_time_format": null, + "date_force_timezone": null, + "number_suffix": "", + "number_separator": "", + "error": null, + "number_decimal_places": null, + "formula": "button(concat('https://example.com/builder/1059/preview/task-details/',row_id()),'Details')", + "formula_type": "button" + }, + { + "id": 59710, + "type": "date", + "name": "Actual start date", + "description": null, + "order": 23, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "date_format": "ISO", + "date_include_time": false, + "date_time_format": "24", + "date_show_tzinfo": false, + "date_force_timezone": null + }, + { + "id": 59744, + "type": "formula", + "name": "Start task", + "description": null, + "order": 24, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "duration_format": null, + "date_include_time": null, + "date_show_tzinfo": null, + "number_prefix": "", + "array_formula_type": null, + "nullable": false, + "date_format": null, + "date_time_format": null, + "date_force_timezone": null, + "number_suffix": "", + "number_separator": "", + "error": null, + "number_decimal_places": null, + "formula": "if(field('Task is valid'),button(concat('https://n8n.cloudron.getbaserow.com/webhook/set-start-date?id=',row_id()),'Start task'),button('','Task not valid'))", + "formula_type": "button" + }, + { + "id": 59711, + "type": "link_row", + "name": "Assets", + "description": null, + "order": 25, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "link_row_table_id": 5693, + "link_row_related_field_id": 59721, + "link_row_limit_selection_view_id": null, + "has_related_field": true + }, + { + "id": 59737, + "type": "formula", + "name": "Add asset", + "description": null, + "order": 26, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "duration_format": null, + "date_include_time": null, + "date_show_tzinfo": null, + "number_prefix": "", + "array_formula_type": null, + "nullable": false, + "date_format": null, + "date_time_format": null, + "date_force_timezone": null, + "number_suffix": "", + "number_separator": "", + "error": null, + "number_decimal_places": null, + "formula": "button(concat('https://example.com/form/iN6i2YJeJcUKB-cuouClfSpmU1LxvSgzWL3Nle5aBwY?prefill_Task=',field('Name'),'&hide_Task'),'Add asset')", + "formula_type": "button" + }, + { + "id": 59712, + "type": "link_row", + "name": "Assignee", + "description": null, + "order": 27, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "link_row_table_id": 5694, + "link_row_related_field_id": 59725, + "link_row_limit_selection_view_id": null, + "has_related_field": true + }, + { + "id": 59713, + "type": "single_select", + "name": "Status", + "description": null, + "order": 28, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "select_options": [ + { + "id": 21030, + "value": "Not started", + "color": "red", + "order": 0 + }, + { + "id": 21031, + "value": "In progress", + "color": "orange", + "order": 1 + }, + { + "id": 21032, + "value": "Completed", + "color": "green", + "order": 2 + } + ] + }, + { + "id": 59729, + "type": "formula", + "name": "Week", + "description": null, + "order": 29, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "duration_format": null, + "date_include_time": null, + "date_show_tzinfo": null, + "number_prefix": "", + "array_formula_type": null, + "nullable": false, + "date_format": null, + "date_time_format": null, + "date_force_timezone": null, + "number_suffix": "", + "number_separator": "", + "error": null, + "number_decimal_places": 0, + "formula": "tonumber(datetime_format(field('Deadline'),'IW'))", + "formula_type": "number" + } + ], + "views": [ + { + "id": 26444, + "type": "grid", + "name": "All tasks", + "order": 1, + "ownership_type": "collaborative", + "owned_by": "frederik@baserow.io", + "filter_type": "AND", + "filters_disabled": false, + "filters": [], + "filter_groups": [], + "sortings": [], + "group_bys": [], + "decorations": [ + { + "id": 8725, + "type": "background_color", + "value_provider_type": "conditional_color", + "value_provider_conf": { + "colors": [ + { + "id": "77f5ba06-166f-4b45-8c17-ff45cf5d4290", + "color": "light-yellow", + "filters": [ + { + "id": "2c9ff0a1-174b-47e1-8c1b-db6bc8b3f9b9", + "type": "date_is_before", + "field": 59728, + "group": null, + "value": "Europe/Brussels??today" + }, + { + "id": "707a05fc-d2ec-4266-a039-f5705ca95750", + "type": "single_select_not_equal", + "field": 59713, + "group": null, + "value": "21032" + } + ], + "operator": "AND" + } + ] + }, + "order": 1 + } + ], + "public": false, + "row_identifier_type": "id", + "row_height_size": "medium", + "field_options": [ + { + "id": 261148, + "field_id": 59726, + "width": 200, + "hidden": false, + "order": 0, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261149, + "field_id": 59704, + "width": 200, + "hidden": true, + "order": 1, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261150, + "field_id": 59702, + "width": 165, + "hidden": false, + "order": 2, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261151, + "field_id": 59709, + "width": 127, + "hidden": false, + "order": 3, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261152, + "field_id": 59737, + "width": 142, + "hidden": false, + "order": 4, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261153, + "field_id": 59712, + "width": 135, + "hidden": false, + "order": 5, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261154, + "field_id": 59744, + "width": 200, + "hidden": true, + "order": 6, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261155, + "field_id": 59700, + "width": 152, + "hidden": false, + "order": 7, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261156, + "field_id": 59705, + "width": 143, + "hidden": false, + "order": 8, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261157, + "field_id": 59713, + "width": 125, + "hidden": false, + "order": 9, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261158, + "field_id": 59706, + "width": 141, + "hidden": false, + "order": 10, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261159, + "field_id": 59729, + "width": 111, + "hidden": false, + "order": 11, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261160, + "field_id": 59707, + "width": 200, + "hidden": false, + "order": 12, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261161, + "field_id": 59727, + "width": 125, + "hidden": false, + "order": 13, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261162, + "field_id": 59710, + "width": 200, + "hidden": false, + "order": 14, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261163, + "field_id": 59730, + "width": 200, + "hidden": false, + "order": 15, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261164, + "field_id": 59728, + "width": 200, + "hidden": false, + "order": 16, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261165, + "field_id": 59740, + "width": 200, + "hidden": false, + "order": 17, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261166, + "field_id": 59701, + "width": 554, + "hidden": false, + "order": 18, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261167, + "field_id": 59708, + "width": 200, + "hidden": false, + "order": 19, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261168, + "field_id": 59703, + "width": 200, + "hidden": false, + "order": 20, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261169, + "field_id": 59731, + "width": 200, + "hidden": false, + "order": 21, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261170, + "field_id": 59732, + "width": 200, + "hidden": false, + "order": 22, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261171, + "field_id": 59741, + "width": 200, + "hidden": false, + "order": 23, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261172, + "field_id": 59711, + "width": 200, + "hidden": false, + "order": 24, + "aggregation_type": "", + "aggregation_raw_type": "" + } + ] + }, + { + "id": 26445, + "type": "grid", + "name": "All tasks grouped by week", + "order": 2, + "ownership_type": "collaborative", + "owned_by": "frederik@baserow.io", + "filter_type": "AND", + "filters_disabled": false, + "filters": [], + "filter_groups": [], + "sortings": [], + "group_bys": [ + { + "id": 3627, + "field_id": 59729, + "order": "ASC" + } + ], + "decorations": [ + { + "id": 8726, + "type": "background_color", + "value_provider_type": "conditional_color", + "value_provider_conf": { + "colors": [ + { + "id": "77f5ba06-166f-4b45-8c17-ff45cf5d4290", + "color": "light-yellow", + "filters": [ + { + "id": "2c9ff0a1-174b-47e1-8c1b-db6bc8b3f9b9", + "type": "date_is_before", + "field": 59728, + "group": null, + "value": "Europe/Brussels??today" + }, + { + "id": "707a05fc-d2ec-4266-a039-f5705ca95750", + "type": "single_select_not_equal", + "field": 59713, + "group": null, + "value": "21032" + } + ], + "operator": "AND" + } + ] + }, + "order": 1 + } + ], + "public": false, + "row_identifier_type": "id", + "row_height_size": "medium", + "field_options": [ + { + "id": 261173, + "field_id": 59726, + "width": 200, + "hidden": false, + "order": 0, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261174, + "field_id": 59704, + "width": 200, + "hidden": true, + "order": 1, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261175, + "field_id": 59702, + "width": 165, + "hidden": false, + "order": 2, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261176, + "field_id": 59709, + "width": 127, + "hidden": false, + "order": 3, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261177, + "field_id": 59737, + "width": 142, + "hidden": false, + "order": 4, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261178, + "field_id": 59712, + "width": 135, + "hidden": false, + "order": 5, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261179, + "field_id": 59744, + "width": 200, + "hidden": true, + "order": 6, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261180, + "field_id": 59700, + "width": 152, + "hidden": false, + "order": 7, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261181, + "field_id": 59705, + "width": 143, + "hidden": false, + "order": 8, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261182, + "field_id": 59713, + "width": 125, + "hidden": false, + "order": 9, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261183, + "field_id": 59706, + "width": 141, + "hidden": false, + "order": 10, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261184, + "field_id": 59729, + "width": 111, + "hidden": false, + "order": 11, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261185, + "field_id": 59707, + "width": 200, + "hidden": false, + "order": 13, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261186, + "field_id": 59727, + "width": 125, + "hidden": false, + "order": 14, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261187, + "field_id": 59710, + "width": 200, + "hidden": false, + "order": 15, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261188, + "field_id": 59730, + "width": 200, + "hidden": false, + "order": 16, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261189, + "field_id": 59728, + "width": 200, + "hidden": false, + "order": 17, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261190, + "field_id": 59740, + "width": 200, + "hidden": false, + "order": 18, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261191, + "field_id": 59701, + "width": 554, + "hidden": false, + "order": 19, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261192, + "field_id": 59708, + "width": 200, + "hidden": false, + "order": 20, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261193, + "field_id": 59703, + "width": 200, + "hidden": false, + "order": 21, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261194, + "field_id": 59731, + "width": 200, + "hidden": false, + "order": 22, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261195, + "field_id": 59732, + "width": 200, + "hidden": false, + "order": 23, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261196, + "field_id": 59741, + "width": 200, + "hidden": false, + "order": 24, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261197, + "field_id": 59711, + "width": 200, + "hidden": false, + "order": 25, + "aggregation_type": "", + "aggregation_raw_type": "" + } + ] + }, + { + "id": 26446, + "type": "grid", + "name": "Valid tasks", + "order": 3, + "ownership_type": "collaborative", + "owned_by": "frederik@baserow.io", + "filter_type": "AND", + "filters_disabled": false, + "filters": [ + { + "id": 13963, + "field_id": 59741, + "type": "boolean", + "value": "1", + "group": null + } + ], + "filter_groups": [], + "sortings": [], + "group_bys": [], + "decorations": [], + "public": false, + "row_identifier_type": "id", + "row_height_size": "medium", + "field_options": [ + { + "id": 261198, + "field_id": 59726, + "width": 200, + "hidden": false, + "order": 0, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261199, + "field_id": 59704, + "width": 200, + "hidden": true, + "order": 1, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261200, + "field_id": 59702, + "width": 171, + "hidden": false, + "order": 2, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261201, + "field_id": 59700, + "width": 157, + "hidden": false, + "order": 3, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261202, + "field_id": 59705, + "width": 143, + "hidden": false, + "order": 4, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261203, + "field_id": 59706, + "width": 141, + "hidden": false, + "order": 5, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261204, + "field_id": 59707, + "width": 200, + "hidden": false, + "order": 6, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261205, + "field_id": 59727, + "width": 125, + "hidden": false, + "order": 7, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261206, + "field_id": 59730, + "width": 200, + "hidden": false, + "order": 8, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261207, + "field_id": 59740, + "width": 200, + "hidden": false, + "order": 9, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261208, + "field_id": 59701, + "width": 554, + "hidden": false, + "order": 10, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261209, + "field_id": 59708, + "width": 200, + "hidden": false, + "order": 11, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261210, + "field_id": 59703, + "width": 200, + "hidden": false, + "order": 12, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261211, + "field_id": 59731, + "width": 200, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261212, + "field_id": 59732, + "width": 200, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261213, + "field_id": 59741, + "width": 200, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + } + ] + }, + { + "id": 26447, + "type": "grid", + "name": "Invalid tasks", + "order": 4, + "ownership_type": "collaborative", + "owned_by": "frederik@baserow.io", + "filter_type": "AND", + "filters_disabled": false, + "filters": [ + { + "id": 13964, + "field_id": 59741, + "type": "boolean", + "value": "0", + "group": null + } + ], + "filter_groups": [], + "sortings": [], + "group_bys": [], + "decorations": [], + "public": false, + "row_identifier_type": "id", + "row_height_size": "medium", + "field_options": [ + { + "id": 261214, + "field_id": 59726, + "width": 200, + "hidden": false, + "order": 0, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261215, + "field_id": 59704, + "width": 200, + "hidden": true, + "order": 1, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261216, + "field_id": 59702, + "width": 171, + "hidden": false, + "order": 2, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261217, + "field_id": 59700, + "width": 157, + "hidden": false, + "order": 3, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261218, + "field_id": 59705, + "width": 143, + "hidden": false, + "order": 4, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261219, + "field_id": 59706, + "width": 141, + "hidden": false, + "order": 5, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261220, + "field_id": 59707, + "width": 200, + "hidden": false, + "order": 6, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261221, + "field_id": 59727, + "width": 125, + "hidden": false, + "order": 7, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261222, + "field_id": 59730, + "width": 200, + "hidden": false, + "order": 8, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261223, + "field_id": 59740, + "width": 200, + "hidden": false, + "order": 9, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261224, + "field_id": 59701, + "width": 554, + "hidden": false, + "order": 10, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261225, + "field_id": 59708, + "width": 200, + "hidden": false, + "order": 11, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261226, + "field_id": 59703, + "width": 200, + "hidden": false, + "order": 12, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261227, + "field_id": 59731, + "width": 200, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261228, + "field_id": 59732, + "width": 200, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261229, + "field_id": 59741, + "width": 200, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + } + ] + } + ], + "rows": [ + { + "id": 1, + "order": "1.00000000000000000000", + "created_on": "2025-02-05T07:48:00.081133+00:00", + "updated_on": "2025-02-05T10:39:28.148711+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59726": null, + "field_59700": 21026, + "field_59701": "Conduct onboarding for a new hire, including setting up payroll in the HR system, scheduling a welcome meeting with the team, providing access to company tools, and assigning required training materials.", + "field_59702": "Employee Onboarding", + "field_59703": null, + "field_59704": null, + "field_59705": 21028, + "field_59706": "2025-02-06", + "field_59727": null, + "field_59730": null, + "field_59740": null, + "field_59707": "12", + "field_59708": [], + "field_59731": null, + "field_59732": null, + "field_59741": null, + "field_59728": null, + "field_59709": null, + "field_59710": "2025-02-05", + "field_59744": null, + "field_59711": [], + "field_59737": null, + "field_59712": [ + 1 + ], + "field_59713": 21030, + "field_59729": null + }, + { + "id": 2, + "order": "2.00000000000000000000", + "created_on": "2025-02-05T07:48:00.081208+00:00", + "updated_on": "2025-02-05T10:39:29.443082+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59726": null, + "field_59700": 21025, + "field_59701": "Process and approve five supplier invoices by verifying amounts, ensuring correct account allocation, obtaining necessary approvals, and scheduling payment in the financial system.", + "field_59702": "Invoice Processing", + "field_59703": null, + "field_59704": null, + "field_59705": 21027, + "field_59706": "2025-02-20", + "field_59727": null, + "field_59730": null, + "field_59740": null, + "field_59707": "34", + "field_59708": [], + "field_59731": null, + "field_59732": null, + "field_59741": null, + "field_59728": null, + "field_59709": null, + "field_59710": null, + "field_59744": null, + "field_59711": [], + "field_59737": null, + "field_59712": [ + 2 + ], + "field_59713": 21030, + "field_59729": null + }, + { + "id": 3, + "order": "3.00000000000000000000", + "created_on": "2025-02-05T07:48:00.081236+00:00", + "updated_on": "2025-02-05T10:39:19.387237+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59726": null, + "field_59700": 21024, + "field_59701": "Write, design, and schedule three social media posts promoting the company\u2019s latest product update, ensuring alignment with brand guidelines and marketing strategy.", + "field_59702": "Social Media Posts", + "field_59703": null, + "field_59704": null, + "field_59705": 21028, + "field_59706": "2025-02-06", + "field_59727": null, + "field_59730": null, + "field_59740": null, + "field_59707": "53", + "field_59708": [ + 1 + ], + "field_59731": null, + "field_59732": null, + "field_59741": null, + "field_59728": null, + "field_59709": null, + "field_59710": null, + "field_59744": null, + "field_59711": [ + 5, + 6, + 7, + 8, + 9 + ], + "field_59737": null, + "field_59712": [ + 3 + ], + "field_59713": 21032, + "field_59729": null + }, + { + "id": 4, + "order": "4.00000000000000000000", + "created_on": "2025-02-05T07:48:00.081262+00:00", + "updated_on": "2025-02-05T10:39:22.743200+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59726": null, + "field_59700": 21022, + "field_59701": "Resolve 15 customer support tickets by diagnosing issues, providing solutions, updating ticket statuses, and following up to ensure customer satisfaction.", + "field_59702": "Customer Ticketing", + "field_59703": null, + "field_59704": null, + "field_59705": 21029, + "field_59706": "2025-02-06", + "field_59727": null, + "field_59730": null, + "field_59740": null, + "field_59707": "6", + "field_59708": [], + "field_59731": null, + "field_59732": null, + "field_59741": null, + "field_59728": null, + "field_59709": null, + "field_59710": null, + "field_59744": null, + "field_59711": [], + "field_59737": null, + "field_59712": [ + 3 + ], + "field_59713": 21032, + "field_59729": null + }, + { + "id": 5, + "order": "5.00000000000000000000", + "created_on": "2025-02-05T07:48:00.081289+00:00", + "updated_on": "2025-02-05T10:39:32.932913+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59726": null, + "field_59700": 21023, + "field_59701": "Break down an upcoming project into five key tasks, assign them to team members, set deadlines in the project management system, and communicate expectations to stakeholders.", + "field_59702": "Task Assignment", + "field_59703": null, + "field_59704": null, + "field_59705": 21028, + "field_59706": "2025-02-27", + "field_59727": null, + "field_59730": null, + "field_59740": null, + "field_59707": "11", + "field_59708": [], + "field_59731": null, + "field_59732": null, + "field_59741": null, + "field_59728": null, + "field_59709": null, + "field_59710": null, + "field_59744": null, + "field_59711": [], + "field_59737": null, + "field_59712": [ + 4 + ], + "field_59713": 21031, + "field_59729": null + }, + { + "id": 6, + "order": "6.00000000000000000000", + "created_on": "2025-02-05T07:48:00.081315+00:00", + "updated_on": "2025-02-05T13:27:19.005898+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59726": null, + "field_59700": 21022, + "field_59701": "Install security patches and update software on all employee workstations, ensuring compatibility, testing functionality, and documenting changes for compliance.", + "field_59702": "System Updates", + "field_59703": null, + "field_59704": null, + "field_59705": 21027, + "field_59706": "2025-02-11", + "field_59727": null, + "field_59730": null, + "field_59740": null, + "field_59707": "9", + "field_59708": [ + 2 + ], + "field_59731": null, + "field_59732": null, + "field_59741": null, + "field_59728": null, + "field_59709": null, + "field_59710": null, + "field_59744": null, + "field_59711": [ + 1 + ], + "field_59737": null, + "field_59712": [ + 3 + ], + "field_59713": 21031, + "field_59729": null + }, + { + "id": 7, + "order": "7.00000000000000000000", + "created_on": "2025-02-05T07:48:00.081340+00:00", + "updated_on": "2025-02-05T10:39:24.070108+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59726": null, + "field_59700": 21022, + "field_59701": "Conduct a physical inventory count of all high-value products, compare results with digital records, report discrepancies, and update the inventory management system.", + "field_59702": "Inventory Check", + "field_59703": null, + "field_59704": null, + "field_59705": 21028, + "field_59706": "2025-02-08", + "field_59727": null, + "field_59730": null, + "field_59740": null, + "field_59707": "23", + "field_59708": [ + 3 + ], + "field_59731": null, + "field_59732": null, + "field_59741": null, + "field_59728": null, + "field_59709": null, + "field_59710": null, + "field_59744": null, + "field_59711": [ + 2, + 3, + 4 + ], + "field_59737": null, + "field_59712": [ + 3 + ], + "field_59713": 21032, + "field_59729": null + }, + { + "id": 8, + "order": "8.00000000000000000000", + "created_on": "2025-02-05T07:48:00.081365+00:00", + "updated_on": "2025-02-05T10:39:35.378363+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59726": null, + "field_59700": 21024, + "field_59701": "Follow up with five potential clients via email or phone, answer questions, provide additional information, and schedule meetings to move them through the sales pipeline.", + "field_59702": "Client Follow-Up", + "field_59703": null, + "field_59704": null, + "field_59705": 21029, + "field_59706": "2025-02-07", + "field_59727": null, + "field_59730": null, + "field_59740": null, + "field_59707": "45", + "field_59708": [], + "field_59731": null, + "field_59732": null, + "field_59741": null, + "field_59728": null, + "field_59709": null, + "field_59710": null, + "field_59744": null, + "field_59711": [], + "field_59737": null, + "field_59712": [ + 3 + ], + "field_59713": 21031, + "field_59729": null + }, + { + "id": 9, + "order": "9.00000000000000000000", + "created_on": "2025-02-05T07:48:00.081389+00:00", + "updated_on": "2025-02-05T10:39:35.770470+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59726": null, + "field_59700": 21023, + "field_59701": "Review and update one company policy by assessing current regulations, identifying gaps, revising wording, obtaining approval, and publishing the final version.", + "field_59702": "Policy Review", + "field_59703": null, + "field_59704": null, + "field_59705": 21029, + "field_59706": "2025-02-11", + "field_59727": null, + "field_59730": null, + "field_59740": null, + "field_59707": "16", + "field_59708": [ + 4 + ], + "field_59731": null, + "field_59732": null, + "field_59741": null, + "field_59728": null, + "field_59709": null, + "field_59710": null, + "field_59744": null, + "field_59711": [], + "field_59737": null, + "field_59712": [ + 4 + ], + "field_59713": 21031, + "field_59729": null + }, + { + "id": 10, + "order": "10.00000000000000000000", + "created_on": "2025-02-05T07:48:00.081413+00:00", + "updated_on": "2025-02-05T10:39:36.077388+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59726": null, + "field_59700": 21023, + "field_59701": "Conduct one-on-one performance reviews with three employees, discuss achievements and challenges, document feedback, and outline action steps for improvement.", + "field_59702": "Performance Reviews", + "field_59703": null, + "field_59704": null, + "field_59705": 21029, + "field_59706": "2025-02-28", + "field_59727": null, + "field_59730": null, + "field_59740": null, + "field_59707": "30", + "field_59708": [], + "field_59731": null, + "field_59732": null, + "field_59741": null, + "field_59728": null, + "field_59709": null, + "field_59710": null, + "field_59744": null, + "field_59711": [], + "field_59737": null, + "field_59712": [ + 4 + ], + "field_59713": 21031, + "field_59729": null + } + ], + "data_sync": null + }, + { + "id": 5692, + "name": "Contractors", + "order": 3, + "fields": [ + { + "id": 59714, + "type": "text", + "name": "Company Name", + "description": null, + "order": 0, + "primary": true, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "text_default": "" + }, + { + "id": 59715, + "type": "text", + "name": "Address", + "description": null, + "order": 1, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "text_default": "" + }, + { + "id": 59716, + "type": "email", + "name": "Email", + "description": null, + "order": 2, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false + }, + { + "id": 59717, + "type": "phone_number", + "name": "Phone", + "description": null, + "order": 3, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false + }, + { + "id": 59718, + "type": "text", + "name": "VAT Number", + "description": null, + "order": 4, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "text_default": "" + }, + { + "id": 59733, + "type": "formula", + "name": "Formula", + "description": null, + "order": 5, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "duration_format": null, + "date_include_time": null, + "date_show_tzinfo": null, + "number_prefix": "", + "array_formula_type": null, + "nullable": false, + "date_format": null, + "date_time_format": null, + "date_force_timezone": null, + "number_suffix": "", + "number_separator": "", + "error": null, + "number_decimal_places": null, + "formula": "regex_replace(field('VAT Number'),'(GB)?([0-9]{9})','')", + "formula_type": "text" + }, + { + "id": 59719, + "type": "link_row", + "name": "Tasks", + "description": null, + "order": 6, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "link_row_table_id": 5691, + "link_row_related_field_id": 59708, + "link_row_limit_selection_view_id": null, + "has_related_field": true + } + ], + "views": [ + { + "id": 26448, + "type": "grid", + "name": "Grid", + "order": 1, + "ownership_type": "collaborative", + "owned_by": "frederik@baserow.io", + "filter_type": "AND", + "filters_disabled": false, + "filters": [], + "filter_groups": [], + "sortings": [], + "group_bys": [], + "decorations": [], + "public": false, + "row_identifier_type": "id", + "row_height_size": "small", + "field_options": [ + { + "id": 261230, + "field_id": 59714, + "width": 200, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261231, + "field_id": 59715, + "width": 200, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261232, + "field_id": 59716, + "width": 200, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261233, + "field_id": 59717, + "width": 158, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261234, + "field_id": 59718, + "width": 200, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261235, + "field_id": 59719, + "width": 200, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261236, + "field_id": 59733, + "width": 200, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + } + ] + } + ], + "rows": [ + { + "id": 1, + "order": "1.00000000000000000000", + "created_on": "2025-02-05T08:42:47.025930+00:00", + "updated_on": "2025-02-05T08:50:20.819069+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59714": "BrightBuild Ltd", + "field_59715": "12 Greenway Street, London, SW1A 1AA", + "field_59716": "info@brightbuild.co.uk", + "field_59717": "+44 20 7946 0123", + "field_59718": "GB123456789", + "field_59733": null, + "field_59719": [ + 3 + ] + }, + { + "id": 2, + "order": "2.00000000000000000000", + "created_on": "2025-02-05T08:42:47.025996+00:00", + "updated_on": "2025-02-05T08:42:47.025996+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59714": "ProTech Solutions", + "field_59715": "45 Kings Road, Manchester, M1 3LD", + "field_59716": "contact@protechsolutions.co.uk", + "field_59717": "+44 161 555 6789", + "field_59718": "GB987654321", + "field_59733": null, + "field_59719": [ + 6 + ] + }, + { + "id": 3, + "order": "3.00000000000000000000", + "created_on": "2025-02-05T08:42:47.026022+00:00", + "updated_on": "2025-02-05T08:42:47.026022+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59714": "EcoElectrics UK", + "field_59715": "78 Solar Avenue, Birmingham, B2 4QA", + "field_59716": "support@ecoelectrics.co.uk", + "field_59717": "+44 121 432 8765", + "field_59718": "GB456123789", + "field_59733": null, + "field_59719": [ + 7 + ] + }, + { + "id": 4, + "order": "4.00000000000000000000", + "created_on": "2025-02-05T08:42:47.026045+00:00", + "updated_on": "2025-02-05T08:42:47.026045+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59714": "SwiftLogistics", + "field_59715": "22 Dockside Lane, Liverpool, L3 1AB", + "field_59716": "admin@swiftlogistics.co.uk", + "field_59717": "+44 151 789 6543", + "field_59718": "GB321654987", + "field_59733": null, + "field_59719": [ + 9 + ] + }, + { + "id": 5, + "order": "5.00000000000000000000", + "created_on": "2025-02-05T08:42:47.026069+00:00", + "updated_on": "2025-02-05T08:42:47.026069+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59714": "Regal Interiors", + "field_59715": "89 High Street, Edinburgh, EH2 4PH", + "field_59716": "sales@regalinteriors.co.uk", + "field_59717": "+44 131 246 9870", + "field_59718": "GB654987321", + "field_59733": null, + "field_59719": [] + } + ], + "data_sync": null + }, + { + "id": 5693, + "name": "Asset repository", + "order": 4, + "fields": [ + { + "id": 59734, + "type": "formula", + "name": "Name", + "description": null, + "order": 0, + "primary": true, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "duration_format": null, + "date_include_time": null, + "date_show_tzinfo": null, + "number_prefix": "", + "array_formula_type": null, + "nullable": true, + "date_format": null, + "date_time_format": null, + "date_force_timezone": null, + "number_suffix": "", + "number_separator": "", + "error": null, + "number_decimal_places": null, + "formula": "get_file_visible_name(index(field('File'),0))", + "formula_type": "text" + }, + { + "id": 59720, + "type": "file", + "name": "File", + "description": null, + "order": 1, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false + }, + { + "id": 59735, + "type": "formula", + "name": "is Image", + "description": null, + "order": 2, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "duration_format": null, + "date_include_time": null, + "date_show_tzinfo": null, + "number_prefix": "", + "array_formula_type": null, + "nullable": true, + "date_format": null, + "date_time_format": null, + "date_force_timezone": null, + "number_suffix": "", + "number_separator": "", + "error": null, + "number_decimal_places": null, + "formula": "is_image(index(field('File'),0))", + "formula_type": "boolean" + }, + { + "id": 59721, + "type": "link_row", + "name": "Task", + "description": null, + "order": 3, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "link_row_table_id": 5691, + "link_row_related_field_id": 59711, + "link_row_limit_selection_view_id": null, + "has_related_field": true + } + ], + "views": [ + { + "id": 26449, + "type": "grid", + "name": "All assets", + "order": 1, + "ownership_type": "collaborative", + "owned_by": "frederik@baserow.io", + "filter_type": "AND", + "filters_disabled": false, + "filters": [], + "filter_groups": [], + "sortings": [], + "group_bys": [], + "decorations": [], + "public": false, + "row_identifier_type": "id", + "row_height_size": "small", + "field_options": [ + { + "id": 261237, + "field_id": 59734, + "width": 200, + "hidden": false, + "order": 0, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261238, + "field_id": 59721, + "width": 200, + "hidden": false, + "order": 1, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261239, + "field_id": 59720, + "width": 192, + "hidden": false, + "order": 2, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261240, + "field_id": 59735, + "width": 185, + "hidden": false, + "order": 3, + "aggregation_type": "", + "aggregation_raw_type": "" + } + ] + }, + { + "id": 26450, + "type": "grid", + "name": "Image assets", + "order": 2, + "ownership_type": "collaborative", + "owned_by": "frederik@baserow.io", + "filter_type": "AND", + "filters_disabled": false, + "filters": [ + { + "id": 13965, + "field_id": 59735, + "type": "boolean", + "value": "1", + "group": null + } + ], + "filter_groups": [], + "sortings": [], + "group_bys": [], + "decorations": [], + "public": false, + "row_identifier_type": "id", + "row_height_size": "small", + "field_options": [ + { + "id": 261241, + "field_id": 59734, + "width": 200, + "hidden": false, + "order": 0, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261242, + "field_id": 59721, + "width": 200, + "hidden": false, + "order": 1, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261243, + "field_id": 59720, + "width": 192, + "hidden": false, + "order": 2, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261244, + "field_id": 59735, + "width": 185, + "hidden": false, + "order": 3, + "aggregation_type": "", + "aggregation_raw_type": "" + } + ] + }, + { + "id": 26451, + "type": "grid", + "name": "Other assets", + "order": 3, + "ownership_type": "collaborative", + "owned_by": "frederik@baserow.io", + "filter_type": "AND", + "filters_disabled": false, + "filters": [ + { + "id": 13966, + "field_id": 59735, + "type": "boolean", + "value": "0", + "group": null + } + ], + "filter_groups": [], + "sortings": [], + "group_bys": [], + "decorations": [], + "public": false, + "row_identifier_type": "id", + "row_height_size": "small", + "field_options": [ + { + "id": 261245, + "field_id": 59734, + "width": 200, + "hidden": false, + "order": 0, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261246, + "field_id": 59721, + "width": 200, + "hidden": false, + "order": 1, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261247, + "field_id": 59720, + "width": 192, + "hidden": false, + "order": 2, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261248, + "field_id": 59735, + "width": 185, + "hidden": false, + "order": 3, + "aggregation_type": "", + "aggregation_raw_type": "" + } + ] + }, + { + "id": 26452, + "type": "form", + "name": "Add new asset", + "order": 4, + "ownership_type": "collaborative", + "owned_by": "frederik@baserow.io", + "public": true, + "title": "", + "description": "", + "cover_image": null, + "logo_image": null, + "submit_text": "Submit", + "submit_action": "MESSAGE", + "submit_action_message": "The asset has been added", + "submit_action_redirect_url": "", + "field_options": [ + { + "id": 25250, + "field_id": 59721, + "name": "", + "description": "The task related to the asset", + "enabled": true, + "required": true, + "order": 0, + "show_when_matching_conditions": false, + "condition_type": "AND", + "conditions": [], + "condition_groups": [], + "field_component": "default", + "include_all_select_options": true, + "allowed_select_options": [] + }, + { + "id": 25251, + "field_id": 59720, + "name": "", + "description": "Select a single file to be attached to the task", + "enabled": true, + "required": true, + "order": 1, + "show_when_matching_conditions": false, + "condition_type": "AND", + "conditions": [], + "condition_groups": [], + "field_component": "default", + "include_all_select_options": true, + "allowed_select_options": [] + }, + { + "id": 25252, + "field_id": 59734, + "name": "", + "description": "", + "enabled": false, + "required": true, + "order": 2, + "show_when_matching_conditions": false, + "condition_type": "AND", + "conditions": [], + "condition_groups": [], + "field_component": "default", + "include_all_select_options": true, + "allowed_select_options": [] + }, + { + "id": 25253, + "field_id": 59735, + "name": "", + "description": "", + "enabled": false, + "required": true, + "order": 3, + "show_when_matching_conditions": false, + "condition_type": "AND", + "conditions": [], + "condition_groups": [], + "field_component": "default", + "include_all_select_options": true, + "allowed_select_options": [] + } + ] + } + ], + "rows": [ + { + "id": 1, + "order": "1.00000000000000000000", + "created_on": "2025-02-05T10:02:37.395368+00:00", + "updated_on": "2025-02-05T10:13:44.901137+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59734": null, + "field_59720": [ + { + "name": "WnJgHQmzjyeKVF2EWnOw3JAp0fPIEgfB_e7fa567aac5fdffb5569ad7301a186889981b3f504d39250a6aebbce0ac452d6.pdf", + "visible_name": "contract.pdf", + "original_name": "WnJgHQmzjyeKVF2EWnOw3JAp0fPIEgfB_e7fa567aac5fdffb5569ad7301a186889981b3f504d39250a6aebbce0ac452d6.pdf" + } + ], + "field_59735": null, + "field_59721": [ + 6 + ] + }, + { + "id": 2, + "order": "2.00000000000000000000", + "created_on": "2025-02-05T10:02:37.395435+00:00", + "updated_on": "2025-02-05T10:13:59.627865+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59734": null, + "field_59720": [ + { + "name": "WnJgHQmzjyeKVF2EWnOw3JAp0fPIEgfB_e7fa567aac5fdffb5569ad7301a186889981b3f504d39250a6aebbce0ac452d6.pdf", + "visible_name": "contract.pdf", + "original_name": "WnJgHQmzjyeKVF2EWnOw3JAp0fPIEgfB_e7fa567aac5fdffb5569ad7301a186889981b3f504d39250a6aebbce0ac452d6.pdf" + } + ], + "field_59735": null, + "field_59721": [ + 7 + ] + }, + { + "id": 3, + "order": "3.00000000000000000000", + "created_on": "2025-02-05T10:14:06.969361+00:00", + "updated_on": "2025-02-05T10:14:19.248714+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59734": null, + "field_59720": [ + { + "name": "sv5sVjuuU4vka45DtxdrVEgB41z41kcF_d15e48a86f901b103b995ee1aa8611a5676f234dbec030d7f20a40956610ab55.jpeg", + "visible_name": "pallets.jpeg", + "original_name": "sv5sVjuuU4vka45DtxdrVEgB41z41kcF_d15e48a86f901b103b995ee1aa8611a5676f234dbec030d7f20a40956610ab55.jpeg" + } + ], + "field_59735": null, + "field_59721": [ + 7 + ] + }, + { + "id": 4, + "order": "4.00000000000000000000", + "created_on": "2025-02-05T10:14:21.840714+00:00", + "updated_on": "2025-02-05T10:14:35.405845+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59734": null, + "field_59720": [ + { + "name": "EkOQ883tzFvi17Sg02ARsvmz3kreg5K7_cd993b3a02bdd9f086b6496b2dfd4ad22f245b78458a9aa28c90ba3493188334.jpeg", + "visible_name": "tools.jpeg", + "original_name": "EkOQ883tzFvi17Sg02ARsvmz3kreg5K7_cd993b3a02bdd9f086b6496b2dfd4ad22f245b78458a9aa28c90ba3493188334.jpeg" + } + ], + "field_59735": null, + "field_59721": [ + 7 + ] + }, + { + "id": 5, + "order": "5.00000000000000000000", + "created_on": "2025-02-05T10:14:58.718123+00:00", + "updated_on": "2025-02-05T10:15:11.710567+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59734": null, + "field_59720": [ + { + "name": "WnJgHQmzjyeKVF2EWnOw3JAp0fPIEgfB_e7fa567aac5fdffb5569ad7301a186889981b3f504d39250a6aebbce0ac452d6.pdf", + "visible_name": "contract.pdf", + "original_name": "WnJgHQmzjyeKVF2EWnOw3JAp0fPIEgfB_e7fa567aac5fdffb5569ad7301a186889981b3f504d39250a6aebbce0ac452d6.pdf" + } + ], + "field_59735": null, + "field_59721": [ + 3 + ] + }, + { + "id": 6, + "order": "6.00000000000000000000", + "created_on": "2025-02-05T10:15:06.267566+00:00", + "updated_on": "2025-02-05T10:18:37.530230+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59734": null, + "field_59720": [ + { + "name": "mQO3bvgYePOu0rWoAz7kocRAO2QKN75M_38f6c19434e047b7681f6ef89cd68ba62779308825f039f30d0afa2ef4521b80.webp", + "visible_name": "A 3D render of a rainbow colore...g above a reflective lake.webp", + "original_name": "mQO3bvgYePOu0rWoAz7kocRAO2QKN75M_38f6c19434e047b7681f6ef89cd68ba62779308825f039f30d0afa2ef4521b80.webp" + } + ], + "field_59735": null, + "field_59721": [ + 3 + ] + }, + { + "id": 7, + "order": "7.00000000000000000000", + "created_on": "2025-02-05T10:15:07.735556+00:00", + "updated_on": "2025-02-05T10:18:52.363224+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59734": null, + "field_59720": [ + { + "name": "9wEN1j8G8FM2OvsLeIKejqBZtXXi2wDh_78fd39be87f430673055eb29c12640404a2536ea416a1691672db111e0216d93.webp", + "visible_name": "A blue orange sliced in half la...r in front of a blue wall.webp", + "original_name": "9wEN1j8G8FM2OvsLeIKejqBZtXXi2wDh_78fd39be87f430673055eb29c12640404a2536ea416a1691672db111e0216d93.webp" + } + ], + "field_59735": null, + "field_59721": [ + 3 + ] + }, + { + "id": 8, + "order": "8.00000000000000000000", + "created_on": "2025-02-05T10:15:13.177066+00:00", + "updated_on": "2025-02-05T10:19:03.067117+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59734": null, + "field_59720": [ + { + "name": "y1P9ulM5rL4cQFRcy18vl7lrmF9fa9eX_d6f44caa1e0c26cf4fa6140e6205220b601387af004a2d74cf175746226cfa8a.webp", + "visible_name": "A centered explosion of colorfu...der on a black background.webp", + "original_name": "y1P9ulM5rL4cQFRcy18vl7lrmF9fa9eX_d6f44caa1e0c26cf4fa6140e6205220b601387af004a2d74cf175746226cfa8a.webp" + } + ], + "field_59735": null, + "field_59721": [ + 3 + ] + }, + { + "id": 9, + "order": "9.00000000000000000000", + "created_on": "2025-02-05T10:19:11.863993+00:00", + "updated_on": "2025-02-05T10:19:48.303568+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59734": null, + "field_59720": [ + { + "name": "fPeEzUORQ9ZvGiatPk76YGW2SuSoKRqW_e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855.pdf", + "visible_name": "template.pdf", + "original_name": "fPeEzUORQ9ZvGiatPk76YGW2SuSoKRqW_e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855.pdf" + } + ], + "field_59735": null, + "field_59721": [ + 3 + ] + } + ], + "data_sync": null + }, + { + "id": 5694, + "name": "Team members", + "order": 5, + "fields": [ + { + "id": 59722, + "type": "text", + "name": "Name", + "description": null, + "order": 0, + "primary": true, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "text_default": "" + }, + { + "id": 59723, + "type": "email", + "name": "Email", + "description": null, + "order": 1, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false + }, + { + "id": 59724, + "type": "phone_number", + "name": "Phone", + "description": null, + "order": 2, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false + }, + { + "id": 59725, + "type": "link_row", + "name": "Tasks", + "description": null, + "order": 3, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "link_row_table_id": 5691, + "link_row_related_field_id": 59712, + "link_row_limit_selection_view_id": null, + "has_related_field": true + }, + { + "id": 59736, + "type": "formula", + "name": "Open workload", + "description": null, + "order": 4, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "duration_format": null, + "date_include_time": null, + "date_show_tzinfo": null, + "number_prefix": "", + "array_formula_type": null, + "nullable": false, + "date_format": null, + "date_time_format": null, + "date_force_timezone": null, + "number_suffix": "hours", + "number_separator": "", + "error": null, + "number_decimal_places": 0, + "formula": "sum(filter(lookup('Tasks','Expected workload'),lookup('Tasks','Status') != 'Completed'))", + "formula_type": "number" + }, + { + "id": 59738, + "type": "formula", + "name": "This week", + "description": null, + "order": 6, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "duration_format": null, + "date_include_time": null, + "date_show_tzinfo": null, + "number_prefix": "", + "array_formula_type": null, + "nullable": false, + "date_format": null, + "date_time_format": null, + "date_force_timezone": null, + "number_suffix": "hours", + "number_separator": "", + "error": null, + "number_decimal_places": 0, + "formula": "sum(filter(lookup('Tasks','Expected workload'),and(lookup('Tasks','Status') != 'Completed',lookup('Tasks','Week') = tonumber(datetime_format(today(),'IW')))))", + "formula_type": "number" + }, + { + "id": 59739, + "type": "formula", + "name": "Next week", + "description": null, + "order": 7, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "duration_format": null, + "date_include_time": null, + "date_show_tzinfo": null, + "number_prefix": "", + "array_formula_type": null, + "nullable": false, + "date_format": null, + "date_time_format": null, + "date_force_timezone": null, + "number_suffix": "hours", + "number_separator": "", + "error": null, + "number_decimal_places": 0, + "formula": "sum(filter(lookup('Tasks','Expected workload'),and(lookup('Tasks','Status') != 'Completed',lookup('Tasks','Week') = tonumber(datetime_format(today(),'IW')) + 1)))", + "formula_type": "number" + }, + { + "id": 59742, + "type": "formula", + "name": "This week occupation", + "description": null, + "order": 8, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "duration_format": null, + "date_include_time": null, + "date_show_tzinfo": null, + "number_prefix": "", + "array_formula_type": null, + "nullable": false, + "date_format": null, + "date_time_format": null, + "date_force_timezone": null, + "number_suffix": "%", + "number_separator": "", + "error": null, + "number_decimal_places": 0, + "formula": "round((field('This week') / 40) * 100,0)", + "formula_type": "number" + }, + { + "id": 59743, + "type": "formula", + "name": "Next week occupation", + "description": null, + "order": 9, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "duration_format": null, + "date_include_time": null, + "date_show_tzinfo": null, + "number_prefix": "", + "array_formula_type": null, + "nullable": false, + "date_format": null, + "date_time_format": null, + "date_force_timezone": null, + "number_suffix": "%", + "number_separator": "", + "error": null, + "number_decimal_places": 0, + "formula": "round((field('Next week') / 40) * 100,0)", + "formula_type": "number" + } + ], + "views": [ + { + "id": 26453, + "type": "grid", + "name": "All team members", + "order": 1, + "ownership_type": "collaborative", + "owned_by": "frederik@baserow.io", + "filter_type": "AND", + "filters_disabled": false, + "filters": [], + "filter_groups": [], + "sortings": [], + "group_bys": [], + "decorations": [ + { + "id": 8727, + "type": "background_color", + "value_provider_type": "conditional_color", + "value_provider_conf": { + "colors": [ + { + "id": "8de5d866-560f-4b3d-97b1-349c78e4a101", + "color": "light-yellow", + "filters": [ + { + "id": "55e47b98-4c1a-442f-8367-953c94b58efc", + "type": "higher_than", + "field": 59742, + "group": null, + "value": "100" + }, + { + "id": "7e5edaf7-8a4e-4a1a-80d7-10995d222bbb", + "type": "higher_than", + "field": 59743, + "group": null, + "value": "100" + } + ], + "operator": "OR" + } + ] + }, + "order": 1 + } + ], + "public": false, + "row_identifier_type": "id", + "row_height_size": "small", + "field_options": [ + { + "id": 261249, + "field_id": 59722, + "width": 131, + "hidden": false, + "order": 0, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261250, + "field_id": 59723, + "width": 197, + "hidden": false, + "order": 1, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261251, + "field_id": 59724, + "width": 126, + "hidden": false, + "order": 2, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261252, + "field_id": 59725, + "width": 200, + "hidden": true, + "order": 3, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261253, + "field_id": 59736, + "width": 162, + "hidden": false, + "order": 4, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261254, + "field_id": 59738, + "width": 134, + "hidden": false, + "order": 5, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261255, + "field_id": 59742, + "width": 204, + "hidden": false, + "order": 6, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261256, + "field_id": 59739, + "width": 139, + "hidden": false, + "order": 7, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 261257, + "field_id": 59743, + "width": 209, + "hidden": false, + "order": 8, + "aggregation_type": "", + "aggregation_raw_type": "" + } + ] + } + ], + "rows": [ + { + "id": 1, + "order": "1.00000000000000000000", + "created_on": "2025-02-05T10:35:51.289680+00:00", + "updated_on": "2025-02-05T10:36:38.792224+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59722": "Allie Ecker", + "field_59723": "allie.ecker@example.com", + "field_59724": "(949) 873-7292", + "field_59725": [ + 1 + ], + "field_59736": null, + "field_59738": null, + "field_59739": null, + "field_59742": null, + "field_59743": null + }, + { + "id": 2, + "order": "2.00000000000000000000", + "created_on": "2025-02-05T10:35:51.289766+00:00", + "updated_on": "2025-02-05T10:36:38.792329+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59722": "Bran Lopez", + "field_59723": "bran.lopez@example.com", + "field_59724": "(650) 869-3623", + "field_59725": [ + 2 + ], + "field_59736": null, + "field_59738": null, + "field_59739": null, + "field_59742": null, + "field_59743": null + }, + { + "id": 3, + "order": "3.00000000000000000000", + "created_on": "2025-02-05T10:36:38.575119+00:00", + "updated_on": "2025-02-05T10:36:38.792357+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59722": "Cinda Pullen", + "field_59723": "cinda.pullen@example.com", + "field_59724": "(213) 743-1636", + "field_59725": [ + 3, + 4, + 6, + 7, + 8 + ], + "field_59736": null, + "field_59738": null, + "field_59739": null, + "field_59742": null, + "field_59743": null + }, + { + "id": 4, + "order": "4.00000000000000000000", + "created_on": "2025-02-05T10:36:38.575189+00:00", + "updated_on": "2025-02-05T10:36:38.792399+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_59722": "Clayton Best", + "field_59723": "clayton.best@example.com", + "field_59724": "(916) 478-0153", + "field_59725": [ + 5, + 9, + 10 + ], + "field_59736": null, + "field_59738": null, + "field_59739": null, + "field_59742": null, + "field_59743": null + } + ], + "data_sync": null + } + ] + }, + { + "pages": [ + { + "id": 6663, + "name": "__shared__", + "order": 1, + "path": "__shared__", + "path_params": [], + "query_params": [], + "shared": true, + "elements": [], + "data_sources": [], + "workflow_actions": [], + "visibility": "all", + "role_type": "allow_all", + "roles": [] + }, + { + "id": 6664, + "name": "Task details", + "order": 1, + "path": "/task-details/:task_id", + "path_params": [ + { + "name": "task_id", + "type": "numeric" + } + ], + "query_params": [], + "shared": false, + "elements": [ + { + "id": 106651, + "order": "1.00000000000000000000", + "type": "heading", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "concat('\ud83d\udccb ',get('data_source.12144.field_59570'),' (',get('data_source.12144.field_59585'),')')", + "level": 1 + }, + { + "id": 106652, + "order": "1.00000000000000000000", + "type": "heading", + "parent_element_id": 106650, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'\u2139\ufe0f Details'", + "level": 2 + }, + { + "id": 106653, + "order": "1.00000000000000000000", + "type": "heading", + "parent_element_id": 106650, + "place_in_container": "1", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'\ud83d\udcf8 Images'", + "level": 2 + }, + { + "id": 106654, + "order": "1.00000000000000000000", + "type": "heading", + "parent_element_id": 106650, + "place_in_container": "2", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'\ud83d\udcc4 Documents'", + "level": 2 + }, + { + "id": 106655, + "order": "2.00000000000000000000", + "type": "text", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "get('data_source.12144.field_59569')", + "format": "plain" + }, + { + "id": 106656, + "order": "2.00000000000000000000", + "type": "text", + "parent_element_id": 106650, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_color": "border" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'CATEGORY'", + "format": "plain" + }, + { + "id": 106650, + "order": "3.00000000000000000000", + "type": "column", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "column_amount": 3, + "column_gap": 20, + "alignment": "top" + }, + { + "id": 106657, + "order": "3.00000000000000000000", + "type": "text", + "parent_element_id": 106650, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "get('data_source.12144.field_59568.value')", + "format": "plain" + }, + { + "id": 106658, + "order": "4.00000000000000000000", + "type": "text", + "parent_element_id": 106650, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_color": "border" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'IMPORTANCE'", + "format": "plain" + }, + { + "id": 106659, + "order": "5.00000000000000000000", + "type": "text", + "parent_element_id": 106650, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "get('data_source.12144.field_59573.value')", + "format": "plain" + }, + { + "id": 106660, + "order": "6.00000000000000000000", + "type": "text", + "parent_element_id": 106650, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_color": "border" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'DEADLINE'", + "format": "plain" + }, + { + "id": 106661, + "order": "7.00000000000000000000", + "type": "text", + "parent_element_id": 106650, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "get('data_source.12144.field_59574')", + "format": "plain" + }, + { + "id": 106662, + "order": "8.00000000000000000000", + "type": "text", + "parent_element_id": 106650, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_color": "border" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'EXPECTED WORKLOAD'", + "format": "plain" + }, + { + "id": 106663, + "order": "9.00000000000000000000", + "type": "text", + "parent_element_id": 106650, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "concat(get('data_source.12144.field_59575'),' hours')", + "format": "plain" + }, + { + "id": 106664, + "order": "10.00000000000000000000", + "type": "text", + "parent_element_id": 106650, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_color": "border" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'DESIRED START DATE'", + "format": "plain" + }, + { + "id": 106665, + "order": "11.00000000000000000000", + "type": "text", + "parent_element_id": 106650, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "concat(get('data_source.12144.field_59592'),' ')", + "format": "plain" + }, + { + "id": 106666, + "order": "12.00000000000000000000", + "type": "text", + "parent_element_id": 106650, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_color": "border" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'FINAL START DATE'", + "format": "plain" + }, + { + "id": 106667, + "order": "13.00000000000000000000", + "type": "text", + "parent_element_id": 106650, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "concat(get('data_source.12144.field_59587'),' ')", + "format": "plain" + } + ], + "data_sources": [ + { + "id": 12144, + "name": "Task details", + "order": "1.00000000000000000000", + "service": { + "id": 15000, + "integration_id": 898, + "type": "local_baserow_get_row", + "table_id": 5679, + "view_id": null, + "search_query": "", + "filter_type": "AND", + "filters": [], + "row_id": "get('page_parameter.task_id')" + } + } + ], + "workflow_actions": [], + "visibility": "all", + "role_type": "allow_all", + "roles": [] + } + ], + "integrations": [ + { + "id": 898, + "name": "Local Baserow", + "order": "1.00000000000000000000", + "type": "local_baserow", + "authorized_user": null + } + ], + "theme": { + "primary_color": "#014aac", + "secondary_color": "#0090da", + "border_color": "#a0a0a0", + "main_success_color": "#12D452", + "main_warning_color": "#FCC74A", + "main_error_color": "#FF5A4A", + "custom_colors": [], + "body_font_family": "inter", + "body_font_size": 14, + "body_font_weight": "regular", + "body_text_color": "#070810ff", + "body_text_alignment": "left", + "heading_1_font_family": "tahoma", + "heading_1_font_size": 24, + "heading_1_font_weight": "bold", + "heading_1_text_color": "primary", + "heading_1_text_alignment": "left", + "heading_2_font_family": "tahoma", + "heading_2_font_size": 20, + "heading_2_font_weight": "semi-bold", + "heading_2_text_color": "primary", + "heading_2_text_alignment": "left", + "heading_3_font_family": "tahoma", + "heading_3_font_size": 16, + "heading_3_font_weight": "medium", + "heading_3_text_color": "#070810ff", + "heading_3_text_alignment": "left", + "heading_4_font_family": "tahoma", + "heading_4_font_size": 16, + "heading_4_font_weight": "medium", + "heading_4_text_color": "#070810ff", + "heading_4_text_alignment": "left", + "heading_5_font_family": "tahoma", + "heading_5_font_size": 14, + "heading_5_font_weight": "regular", + "heading_5_text_color": "#070810ff", + "heading_5_text_alignment": "left", + "heading_6_font_family": "tahoma", + "heading_6_font_size": 14, + "heading_6_font_weight": "regular", + "heading_6_text_color": "#202128", + "heading_6_text_alignment": "left", + "button_font_family": "inter", + "button_font_size": 13, + "button_font_weight": "regular", + "button_alignment": "left", + "button_text_alignment": "center", + "button_width": "auto", + "button_background_color": "primary", + "button_text_color": "#ffffffff", + "button_border_color": "border", + "button_border_size": 0, + "button_border_radius": 4, + "button_vertical_padding": 12, + "button_horizontal_padding": 12, + "button_hover_background_color": "#96baf6ff", + "button_hover_text_color": "#ffffffff", + "button_hover_border_color": "border", + "link_font_family": "inter", + "link_font_size": 13, + "link_font_weight": "regular", + "link_text_alignment": "left", + "link_text_color": "primary", + "link_hover_text_color": "#96baf6ff", + "image_alignment": "left", + "image_max_width": 100, + "image_max_height": null, + "image_border_radius": 0, + "image_constraint": "contain", + "page_background_color": "#ffffffff", + "page_background_file_id": null, + "page_background_mode": "tile", + "label_font_family": "inter", + "label_text_color": "#070810FF", + "label_font_size": 13, + "label_font_weight": "medium", + "input_font_family": "inter", + "input_font_size": 13, + "input_font_weight": "regular", + "input_text_color": "#070810FF", + "input_background_color": "#FFFFFFFF", + "input_border_color": "border", + "input_border_size": 1, + "input_border_radius": 4, + "input_vertical_padding": 8, + "input_horizontal_padding": 12, + "table_border_color": "border", + "table_border_size": 0, + "table_border_radius": 0, + "table_header_background_color": "#014aac4d", + "table_header_text_color": "#000000ff", + "table_header_font_size": 13, + "table_header_font_weight": "semi-bold", + "table_header_font_family": "inter", + "table_header_text_alignment": "left", + "table_cell_background_color": "transparent", + "table_cell_alternate_background_color": "transparent", + "table_cell_alignment": "left", + "table_cell_vertical_padding": 10, + "table_cell_horizontal_padding": 20, + "table_vertical_separator_color": "#000000FF", + "table_vertical_separator_size": 0, + "table_horizontal_separator_color": "#000000FF", + "table_horizontal_separator_size": 1 + }, + "user_sources": [], + "favicon_file": null, + "login_page": null, + "id": 2167, + "name": "Case 6 - Task Management", + "order": 11, + "type": "builder" + }, + { + "pages": [ + { + "id": 6665, + "name": "__shared__", + "order": 1, + "path": "__shared__", + "path_params": [], + "query_params": [], + "shared": true, + "elements": [], + "data_sources": [], + "workflow_actions": [], + "visibility": "all", + "role_type": "allow_all", + "roles": [] + }, + { + "id": 6666, + "name": "Task details", + "order": 1, + "path": "/task-details/:task_id", + "path_params": [ + { + "name": "task_id", + "type": "numeric" + } + ], + "query_params": [], + "shared": false, + "elements": [ + { + "id": 106669, + "order": "1.00000000000000000000", + "type": "heading", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "concat('\ud83d\udccb ',get('data_source.12145.field_59597'),' (',get('data_source.12145.field_59615'),')')", + "level": 1 + }, + { + "id": 106670, + "order": "1.00000000000000000000", + "type": "heading", + "parent_element_id": 106668, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'\u2139\ufe0f Details'", + "level": 2 + }, + { + "id": 106671, + "order": "1.00000000000000000000", + "type": "heading", + "parent_element_id": 106668, + "place_in_container": "1", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'\ud83d\udcf8 Images'", + "level": 2 + }, + { + "id": 106672, + "order": "1.00000000000000000000", + "type": "heading", + "parent_element_id": 106668, + "place_in_container": "2", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'\ud83d\udcc4 Documents'", + "level": 2 + }, + { + "id": 106688, + "order": "1.00000000000000000000", + "type": "link", + "parent_element_id": 106686, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "navigation_type": "custom", + "navigate_to_page_id": null, + "page_parameters": [], + "query_parameters": [], + "navigate_to_url": "get('current_record.field_59613.0.url')", + "target": "blank", + "value": "get('current_record.field_59622')", + "variant": "link" + }, + { + "id": 106689, + "order": "1.00000000000000000000", + "type": "image", + "parent_element_id": 106687, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "image_source_type": "url", + "image_file_id": null, + "image_url": "get('current_record.field_59613.0.url')", + "alt_text": "" + }, + { + "id": 106673, + "order": "2.00000000000000000000", + "type": "text", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "concat(get('data_source.12145.field_59569'),get('data_source.12145.field_59596'))", + "format": "plain" + }, + { + "id": 106674, + "order": "2.00000000000000000000", + "type": "text", + "parent_element_id": 106668, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_color": "border" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'CATEGORY'", + "format": "plain" + }, + { + "id": 106686, + "order": "2.00000000000000000000", + "type": "repeat", + "parent_element_id": 106668, + "place_in_container": "2", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "data_source_id": 12147, + "items_per_page": 20, + "button_load_more_label": "", + "schema_property": null, + "property_options": [], + "orientation": "vertical", + "items_per_row": { + "tablet": 2, + "desktop": 2, + "smartphone": 2 + }, + "horizontal_gap": 0, + "vertical_gap": 0 + }, + { + "id": 106687, + "order": "2.00000000000000000000", + "type": "repeat", + "parent_element_id": 106668, + "place_in_container": "1", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "data_source_id": 12146, + "items_per_page": 20, + "button_load_more_label": "", + "schema_property": null, + "property_options": [], + "orientation": "vertical", + "items_per_row": { + "tablet": 2, + "desktop": 2, + "smartphone": 2 + }, + "horizontal_gap": 0, + "vertical_gap": 0 + }, + { + "id": 106668, + "order": "3.00000000000000000000", + "type": "column", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "column_amount": 3, + "column_gap": 20, + "alignment": "top" + }, + { + "id": 106675, + "order": "3.00000000000000000000", + "type": "text", + "parent_element_id": 106668, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "get('data_source.12145.field_59595.value')", + "format": "plain" + }, + { + "id": 106676, + "order": "4.00000000000000000000", + "type": "text", + "parent_element_id": 106668, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_color": "border" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'IMPORTANCE'", + "format": "plain" + }, + { + "id": 106677, + "order": "5.00000000000000000000", + "type": "text", + "parent_element_id": 106668, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "get('data_source.12145.field_59600.value')", + "format": "plain" + }, + { + "id": 106678, + "order": "6.00000000000000000000", + "type": "text", + "parent_element_id": 106668, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_color": "border" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'DEADLINE'", + "format": "plain" + }, + { + "id": 106679, + "order": "7.00000000000000000000", + "type": "text", + "parent_element_id": 106668, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "get('data_source.12145.field_59601')", + "format": "plain" + }, + { + "id": 106680, + "order": "8.00000000000000000000", + "type": "text", + "parent_element_id": 106668, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_color": "border" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'EXPECTED WORKLOAD'", + "format": "plain" + }, + { + "id": 106681, + "order": "9.00000000000000000000", + "type": "text", + "parent_element_id": 106668, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "concat(get('data_source.12145.field_59602'),' hours')", + "format": "plain" + }, + { + "id": 106682, + "order": "10.00000000000000000000", + "type": "text", + "parent_element_id": 106668, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_color": "border" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'DESIRED START DATE'", + "format": "plain" + }, + { + "id": 106683, + "order": "11.00000000000000000000", + "type": "text", + "parent_element_id": 106668, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "concat(get('data_source.12145.field_59624'),' ')", + "format": "plain" + }, + { + "id": 106684, + "order": "12.00000000000000000000", + "type": "text", + "parent_element_id": 106668, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_color": "border" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'FINAL START DATE'", + "format": "plain" + }, + { + "id": 106685, + "order": "13.00000000000000000000", + "type": "text", + "parent_element_id": 106668, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "concat(get('data_source.12145.field_59617'),' ')", + "format": "plain" + } + ], + "data_sources": [ + { + "id": 12145, + "name": "Task details", + "order": "1.00000000000000000000", + "service": { + "id": 15001, + "integration_id": 899, + "type": "local_baserow_get_row", + "table_id": 5681, + "view_id": null, + "search_query": "", + "filter_type": "AND", + "filters": [], + "row_id": "get('page_parameter.task_id')" + } + }, + { + "id": 12146, + "name": "Image assets", + "order": "2.00000000000000000000", + "service": { + "id": 15002, + "integration_id": 899, + "type": "local_baserow_list_rows", + "table_id": 5683, + "view_id": 26424, + "sortings": [], + "search_query": "", + "filter_type": "AND", + "filters": [ + { + "field_id": 59614, + "type": "link_row_has", + "value": "get('page_parameter.task_id')", + "value_is_formula": true + } + ] + } + }, + { + "id": 12147, + "name": "Other assets", + "order": "3.00000000000000000000", + "service": { + "id": 15003, + "integration_id": 899, + "type": "local_baserow_list_rows", + "table_id": 5683, + "view_id": 26425, + "sortings": [], + "search_query": "", + "filter_type": "AND", + "filters": [ + { + "field_id": 59614, + "type": "link_row_has", + "value": "get('page_parameter.task_id')", + "value_is_formula": true + } + ] + } + } + ], + "workflow_actions": [], + "visibility": "all", + "role_type": "allow_all", + "roles": [] + } + ], + "integrations": [ + { + "id": 899, + "name": "Local Baserow", + "order": "1.00000000000000000000", + "type": "local_baserow", + "authorized_user": null + } + ], + "theme": { + "primary_color": "#014aac", + "secondary_color": "#0090da", + "border_color": "#a0a0a0", + "main_success_color": "#12D452", + "main_warning_color": "#FCC74A", + "main_error_color": "#FF5A4A", + "custom_colors": [], + "body_font_family": "inter", + "body_font_size": 14, + "body_font_weight": "regular", + "body_text_color": "#070810ff", + "body_text_alignment": "left", + "heading_1_font_family": "tahoma", + "heading_1_font_size": 24, + "heading_1_font_weight": "bold", + "heading_1_text_color": "primary", + "heading_1_text_alignment": "left", + "heading_2_font_family": "tahoma", + "heading_2_font_size": 20, + "heading_2_font_weight": "semi-bold", + "heading_2_text_color": "primary", + "heading_2_text_alignment": "left", + "heading_3_font_family": "tahoma", + "heading_3_font_size": 16, + "heading_3_font_weight": "medium", + "heading_3_text_color": "#070810ff", + "heading_3_text_alignment": "left", + "heading_4_font_family": "tahoma", + "heading_4_font_size": 16, + "heading_4_font_weight": "medium", + "heading_4_text_color": "#070810ff", + "heading_4_text_alignment": "left", + "heading_5_font_family": "tahoma", + "heading_5_font_size": 14, + "heading_5_font_weight": "regular", + "heading_5_text_color": "#070810ff", + "heading_5_text_alignment": "left", + "heading_6_font_family": "tahoma", + "heading_6_font_size": 14, + "heading_6_font_weight": "regular", + "heading_6_text_color": "#202128", + "heading_6_text_alignment": "left", + "button_font_family": "inter", + "button_font_size": 13, + "button_font_weight": "regular", + "button_alignment": "left", + "button_text_alignment": "center", + "button_width": "auto", + "button_background_color": "primary", + "button_text_color": "#ffffffff", + "button_border_color": "border", + "button_border_size": 0, + "button_border_radius": 4, + "button_vertical_padding": 12, + "button_horizontal_padding": 12, + "button_hover_background_color": "#96baf6ff", + "button_hover_text_color": "#ffffffff", + "button_hover_border_color": "border", + "link_font_family": "inter", + "link_font_size": 13, + "link_font_weight": "regular", + "link_text_alignment": "left", + "link_text_color": "primary", + "link_hover_text_color": "#96baf6ff", + "image_alignment": "left", + "image_max_width": 100, + "image_max_height": null, + "image_border_radius": 0, + "image_constraint": "contain", + "page_background_color": "#ffffffff", + "page_background_file_id": null, + "page_background_mode": "tile", + "label_font_family": "inter", + "label_text_color": "#070810FF", + "label_font_size": 13, + "label_font_weight": "medium", + "input_font_family": "inter", + "input_font_size": 13, + "input_font_weight": "regular", + "input_text_color": "#070810FF", + "input_background_color": "#FFFFFFFF", + "input_border_color": "border", + "input_border_size": 1, + "input_border_radius": 4, + "input_vertical_padding": 8, + "input_horizontal_padding": 12, + "table_border_color": "border", + "table_border_size": 0, + "table_border_radius": 0, + "table_header_background_color": "#014aac4d", + "table_header_text_color": "#000000ff", + "table_header_font_size": 13, + "table_header_font_weight": "semi-bold", + "table_header_font_family": "inter", + "table_header_text_alignment": "left", + "table_cell_background_color": "transparent", + "table_cell_alternate_background_color": "transparent", + "table_cell_alignment": "left", + "table_cell_vertical_padding": 10, + "table_cell_horizontal_padding": 20, + "table_vertical_separator_color": "#000000FF", + "table_vertical_separator_size": 0, + "table_horizontal_separator_color": "#000000FF", + "table_horizontal_separator_size": 1 + }, + "user_sources": [], + "favicon_file": null, + "login_page": null, + "id": 2168, + "name": "Case 7 - Task Management", + "order": 12, + "type": "builder" + } + ] +} diff --git a/backend/templates/formulas.zip b/backend/templates/formulas.zip new file mode 100644 index 000000000..25e456a3a Binary files /dev/null and b/backend/templates/formulas.zip differ diff --git a/backend/templates/purchase-order-management.json b/backend/templates/purchase-order-management.json new file mode 100644 index 000000000..6153f5237 --- /dev/null +++ b/backend/templates/purchase-order-management.json @@ -0,0 +1,15528 @@ +{ + "baserow_template_version": 1, + "name": "Purchase Order Management", + "icon": "iconoir-cart", + "keywords": [ + "purchase order", + "order approval", + "supplier", + "purchases", + "purchase requests", + "products", + "inventory", + "part numbers" + ], + "categories": [ + "Finance and Accounting", + "Business Operations" + ], + "export":[ + { + "id": 2181, + "name": "Purchase Order Management", + "order": 2, + "type": "database", + "tables": [ + { + "id": 5756, + "name": "Staff members", + "order": 1, + "fields": [ + { + "id": 60407, + "type": "text", + "name": "Name", + "description": null, + "order": 0, + "primary": true, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "text_default": "" + }, + { + "id": 60408, + "type": "email", + "name": "Email", + "description": null, + "order": 1, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false + }, + { + "id": 60409, + "type": "phone_number", + "name": "Phone", + "description": null, + "order": 2, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false + }, + { + "id": 60410, + "type": "single_select", + "name": "Job role", + "description": null, + "order": 3, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "select_options": [ + { + "id": 21186, + "value": "Purchase department", + "color": "light-gray", + "order": 0 + }, + { + "id": 21187, + "value": "Other", + "color": "brown", + "order": 1 + } + ] + }, + { + "id": 60413, + "type": "link_row", + "name": "Requests", + "description": null, + "order": 4, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "link_row_table_id": 5754, + "link_row_related_field_id": 60412, + "link_row_limit_selection_view_id": null, + "has_related_field": true + }, + { + "id": 60414, + "type": "password", + "name": "Password", + "description": null, + "order": 5, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false + }, + { + "id": 60415, + "type": "rollup", + "name": "Total requested", + "description": null, + "order": 6, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "number_suffix": "", + "date_time_format": null, + "date_force_timezone": null, + "number_decimal_places": 2, + "date_include_time": null, + "number_prefix": "\u20ac", + "duration_format": null, + "number_separator": "SPACE_PERIOD", + "nullable": false, + "date_format": null, + "array_formula_type": null, + "error": null, + "date_show_tzinfo": null, + "through_field_id": 60413, + "target_field_id": 60405, + "rollup_function": "sum" + }, + { + "id": 60416, + "type": "rollup", + "name": "Total approved", + "description": null, + "order": 7, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "number_suffix": "", + "date_time_format": null, + "date_force_timezone": null, + "number_decimal_places": 2, + "date_include_time": null, + "number_prefix": "\u20ac", + "duration_format": null, + "number_separator": "SPACE_PERIOD", + "nullable": false, + "date_format": null, + "array_formula_type": null, + "error": null, + "date_show_tzinfo": null, + "through_field_id": 60413, + "target_field_id": 60406, + "rollup_function": "sum" + }, + { + "id": 60421, + "type": "formula", + "name": "Approval ratio", + "description": null, + "order": 8, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "number_suffix": "", + "date_time_format": null, + "date_force_timezone": null, + "number_decimal_places": 0, + "date_include_time": null, + "number_prefix": "", + "duration_format": null, + "number_separator": "", + "nullable": false, + "date_format": null, + "array_formula_type": null, + "error": null, + "date_show_tzinfo": null, + "formula": "round((field('Total approved') / field('Total requested')) * 100,0)", + "formula_type": "number" + } + ], + "views": [ + { + "id": 26720, + "type": "grid", + "name": "All staff members", + "order": 1, + "ownership_type": "collaborative", + "owned_by": "frederik@baserow.io", + "filter_type": "AND", + "filters_disabled": false, + "filters": [], + "filter_groups": [], + "sortings": [ + { + "id": 20615, + "field_id": 60407, + "order": "ASC" + } + ], + "group_bys": [], + "decorations": [], + "public": false, + "row_identifier_type": "id", + "row_height_size": "small", + "field_options": [ + { + "id": 265021, + "field_id": 60407, + "width": 180, + "hidden": false, + "order": 0, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 265019, + "field_id": 60408, + "width": 267, + "hidden": false, + "order": 1, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 265026, + "field_id": 60414, + "width": 120, + "hidden": false, + "order": 2, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 265020, + "field_id": 60409, + "width": 164, + "hidden": false, + "order": 3, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 265022, + "field_id": 60410, + "width": 200, + "hidden": false, + "order": 4, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 265025, + "field_id": 60413, + "width": 200, + "hidden": false, + "order": 5, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 265034, + "field_id": 60415, + "width": 200, + "hidden": false, + "order": 6, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 265035, + "field_id": 60416, + "width": 200, + "hidden": false, + "order": 7, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 265042, + "field_id": 60421, + "width": 151, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + } + ] + }, + { + "id": 26721, + "type": "grid", + "name": "Purchase department staff members", + "order": 2, + "ownership_type": "collaborative", + "owned_by": "frederik@baserow.io", + "filter_type": "AND", + "filters_disabled": false, + "filters": [ + { + "id": 14074, + "field_id": 60410, + "type": "single_select_equal", + "value": "21186", + "group": null + } + ], + "filter_groups": [], + "sortings": [ + { + "id": 20616, + "field_id": 60407, + "order": "ASC" + } + ], + "group_bys": [], + "decorations": [], + "public": false, + "row_identifier_type": "id", + "row_height_size": "small", + "field_options": [ + { + "id": 265028, + "field_id": 60407, + "width": 180, + "hidden": false, + "order": 0, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 265029, + "field_id": 60408, + "width": 267, + "hidden": false, + "order": 1, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 265030, + "field_id": 60414, + "width": 120, + "hidden": false, + "order": 2, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 265031, + "field_id": 60409, + "width": 164, + "hidden": false, + "order": 3, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 265032, + "field_id": 60410, + "width": 200, + "hidden": false, + "order": 4, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 265033, + "field_id": 60413, + "width": 200, + "hidden": true, + "order": 5, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 265036, + "field_id": 60415, + "width": 200, + "hidden": true, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 265037, + "field_id": 60416, + "width": 200, + "hidden": true, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 265043, + "field_id": 60421, + "width": 200, + "hidden": true, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + } + ] + } + ], + "rows": [ + { + "id": 1, + "order": "1.00000000000000000000", + "created_on": "2025-03-06T10:15:02.938899+00:00", + "updated_on": "2025-03-06T12:40:54.716822+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60407": "Allie Ecker", + "field_60408": "allie.ecker@example.com", + "field_60409": "(949) 873-7292", + "field_60410": 21187, + "field_60413": [ + 47, + 50, + 53, + 56, + 60, + 64, + 65, + 67 + ], + "field_60414": "pbkdf2_sha256$720000$ziawXAIXB5JUhEzqw65AcE$llm26L5Gy/xLRHhq5m1UpW5TyYGypCZy6w97cXMtzkk=", + "field_60415": null, + "field_60416": null, + "field_60421": null + }, + { + "id": 2, + "order": "2.00000000000000000000", + "created_on": "2025-03-06T10:15:02.938994+00:00", + "updated_on": "2025-03-06T12:40:56.237850+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60407": "Bran Lopez", + "field_60408": "bran.lopez@example.com", + "field_60409": "(650) 869-3623", + "field_60410": 21187, + "field_60413": [ + 48, + 58, + 61 + ], + "field_60414": "pbkdf2_sha256$720000$XRXfe3rKg9g04Fpu1P7p2T$F2b+8R+NXyoolrteEEIUhwaUh9ZYjYjKPR5ZI9P/3RQ=", + "field_60415": null, + "field_60416": null, + "field_60421": null + }, + { + "id": 3, + "order": "3.00000000000000000000", + "created_on": "2025-03-06T10:16:39.188853+00:00", + "updated_on": "2025-03-06T12:40:56.653164+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60407": "Cinda Pullen", + "field_60408": "cinda.pullen@example.com", + "field_60409": "(213) 743-1636", + "field_60410": 21187, + "field_60413": [ + 49, + 51, + 52, + 55, + 59 + ], + "field_60414": "pbkdf2_sha256$720000$1FnL5w067VtK7dn6IXhFg3$PXmPY1zYLiTKnXttgjaVzmunLcpbJAwAT70Q8v/U6jM=", + "field_60415": null, + "field_60416": null, + "field_60421": null + }, + { + "id": 4, + "order": "4.00000000000000000000", + "created_on": "2025-03-06T10:16:39.188940+00:00", + "updated_on": "2025-03-06T12:40:56.943859+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60407": "Clayton Best", + "field_60408": "clayton.best@example.com", + "field_60409": "(916) 478-0153", + "field_60410": 21187, + "field_60413": [ + 54, + 57, + 62, + 63, + 66, + 68 + ], + "field_60414": "pbkdf2_sha256$720000$xqsnIiQTkBo5AIJ5rH4dQ6$thIm/iMAh2ScPUhmPmbTLTrMmZgoi3kKFmRqPbO+9tA=", + "field_60415": null, + "field_60416": null, + "field_60421": null + }, + { + "id": 12, + "order": "12.00000000000000000000", + "created_on": "2025-03-06T10:16:39.189236+00:00", + "updated_on": "2025-03-06T12:41:08.888924+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60407": "Lane Mahon", + "field_60408": "lane.mahon@example.com", + "field_60409": "(925) 250-4627", + "field_60410": 21186, + "field_60413": [], + "field_60414": "pbkdf2_sha256$720000$tbU6DYrjCANCHlKu9mPvNm$8Fh1BPLP7FwYYiGL75rbW2EcSDaMUZ/N06SJk8yvwiI=", + "field_60415": null, + "field_60416": null, + "field_60421": null + }, + { + "id": 16, + "order": "16.00000000000000000000", + "created_on": "2025-03-06T10:16:39.189381+00:00", + "updated_on": "2025-03-06T12:41:10.834739+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60407": "Nora Mott", + "field_60408": "nora.mott@example.com", + "field_60409": "(818) 240-6675", + "field_60410": 21186, + "field_60413": [], + "field_60414": "pbkdf2_sha256$720000$s9Dzaj9Ux8sRlhiu1ATL6K$PmIh/PUXS3hdpapR3Ke0RKiSK/w+smwfKILTInPWldQ=", + "field_60415": null, + "field_60416": null, + "field_60421": null + } + ], + "data_sync": null + }, + { + "id": 5751, + "name": "Suppliers", + "order": 2, + "fields": [ + { + "id": 60357, + "type": "text", + "name": "ID", + "description": null, + "order": 0, + "primary": true, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "text_default": "" + }, + { + "id": 60358, + "type": "text", + "name": "Name", + "description": null, + "order": 1, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "text_default": "" + }, + { + "id": 60359, + "type": "text", + "name": "Address", + "description": null, + "order": 2, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "text_default": "" + }, + { + "id": 60360, + "type": "text", + "name": "Contact", + "description": null, + "order": 3, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "text_default": "" + }, + { + "id": 60361, + "type": "phone_number", + "name": "Phone", + "description": null, + "order": 4, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false + }, + { + "id": 60362, + "type": "email", + "name": "Email", + "description": null, + "order": 5, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false + }, + { + "id": 60365, + "type": "link_row", + "name": "Requests", + "description": null, + "order": 8, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "link_row_table_id": 5754, + "link_row_related_field_id": 60375, + "link_row_limit_selection_view_id": null, + "has_related_field": true + }, + { + "id": 60417, + "type": "count", + "name": "Count requests", + "description": null, + "order": 9, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "number_suffix": "", + "date_time_format": null, + "date_force_timezone": null, + "number_decimal_places": 0, + "date_include_time": null, + "number_prefix": "", + "duration_format": null, + "number_separator": "", + "nullable": false, + "date_format": null, + "array_formula_type": null, + "error": null, + "date_show_tzinfo": null, + "through_field_id": 60365 + }, + { + "id": 60418, + "type": "rollup", + "name": "Total requested", + "description": null, + "order": 10, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "number_suffix": "", + "date_time_format": null, + "date_force_timezone": null, + "number_decimal_places": 2, + "date_include_time": null, + "number_prefix": "\u20ac", + "duration_format": null, + "number_separator": "SPACE_PERIOD", + "nullable": false, + "date_format": null, + "array_formula_type": null, + "error": null, + "date_show_tzinfo": null, + "through_field_id": 60365, + "target_field_id": 60405, + "rollup_function": "sum" + }, + { + "id": 60419, + "type": "rollup", + "name": "Total approved", + "description": null, + "order": 11, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "number_suffix": "", + "date_time_format": null, + "date_force_timezone": null, + "number_decimal_places": 2, + "date_include_time": null, + "number_prefix": "\u20ac", + "duration_format": null, + "number_separator": "SPACE_PERIOD", + "nullable": false, + "date_format": null, + "array_formula_type": null, + "error": null, + "date_show_tzinfo": null, + "through_field_id": 60365, + "target_field_id": 60406, + "rollup_function": "sum" + }, + { + "id": 60420, + "type": "formula", + "name": "Approval ratio", + "description": null, + "order": 12, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "number_suffix": "%", + "date_time_format": null, + "date_force_timezone": null, + "number_decimal_places": 0, + "date_include_time": null, + "number_prefix": "", + "duration_format": null, + "number_separator": "", + "nullable": false, + "date_format": null, + "array_formula_type": null, + "error": null, + "date_show_tzinfo": null, + "formula": "round((field('Total approved') / field('Total requested')) * 100,0)", + "formula_type": "number" + } + ], + "views": [ + { + "id": 26708, + "type": "grid", + "name": "All suppliers", + "order": 1, + "ownership_type": "collaborative", + "owned_by": "frederik@baserow.io", + "filter_type": "AND", + "filters_disabled": false, + "filters": [], + "filter_groups": [], + "sortings": [ + { + "id": 20605, + "field_id": 60365, + "order": "ASC" + } + ], + "group_bys": [], + "decorations": [], + "public": false, + "row_identifier_type": "id", + "row_height_size": "small", + "field_options": [ + { + "id": 264898, + "field_id": 60357, + "width": 114, + "hidden": false, + "order": 0, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264899, + "field_id": 60358, + "width": 145, + "hidden": false, + "order": 1, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264900, + "field_id": 60359, + "width": 200, + "hidden": false, + "order": 2, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264901, + "field_id": 60360, + "width": 163, + "hidden": false, + "order": 3, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264902, + "field_id": 60361, + "width": 200, + "hidden": false, + "order": 4, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264903, + "field_id": 60362, + "width": 200, + "hidden": false, + "order": 5, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264906, + "field_id": 60365, + "width": 200, + "hidden": false, + "order": 6, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 265038, + "field_id": 60417, + "width": 200, + "hidden": false, + "order": 7, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 265039, + "field_id": 60418, + "width": 200, + "hidden": false, + "order": 8, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 265040, + "field_id": 60419, + "width": 200, + "hidden": false, + "order": 9, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 265041, + "field_id": 60420, + "width": 165, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + } + ] + } + ], + "rows": [ + { + "id": 1, + "order": "1.00000000000000000000", + "created_on": "2025-03-04T05:25:53.161255+00:00", + "updated_on": "2025-03-06T10:19:58.288106+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60357": "SUPP-001", + "field_60358": "TechnoParts", + "field_60359": "123 Rue de l'A\u00e9ronautique, Paris, 75001", + "field_60360": "Jean Dupont", + "field_60361": "+33 1 23 45 67 89", + "field_60362": "jean.dupont@example.com", + "field_60365": [ + 47, + 49, + 50, + 53, + 67 + ], + "field_60417": null, + "field_60418": null, + "field_60419": null, + "field_60420": null + }, + { + "id": 6, + "order": "6.00000000000000000000", + "created_on": "2025-03-04T05:25:53.161456+00:00", + "updated_on": "2025-03-06T10:19:58.288294+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60357": "SUPP-006", + "field_60358": "FusionFabricators", + "field_60359": "987 Avenue du Transport, Nantes, 44000", + "field_60360": "Clara Lef\u00e8vre", + "field_60361": "+33 2 40 12 34 56", + "field_60362": "clara.lef\u00e8vre@example.com", + "field_60365": [ + 48, + 52, + 59, + 60, + 56 + ], + "field_60417": null, + "field_60418": null, + "field_60419": null, + "field_60420": null + }, + { + "id": 12, + "order": "12.00000000000000000000", + "created_on": "2025-03-04T05:25:53.161679+00:00", + "updated_on": "2025-03-06T10:19:58.288460+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60357": "SUPP-012", + "field_60358": "PinnacleProductions", + "field_60359": "680 Boulevard des Avions, Toulon, 83000", + "field_60360": "C\u00e9cile Gauthier", + "field_60361": "+33 4 94 12 34 56", + "field_60362": "c\u00e9cile.gauthier@example.com", + "field_60365": [ + 62, + 65, + 61, + 58, + 55 + ], + "field_60417": null, + "field_60418": null, + "field_60419": null, + "field_60420": null + }, + { + "id": 14, + "order": "14.00000000000000000000", + "created_on": "2025-03-04T05:25:53.161741+00:00", + "updated_on": "2025-03-06T10:19:58.288507+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60357": "SUPP-014", + "field_60358": "CrestManufacturing", + "field_60359": "802 Avenue des Avions, Dijon, 21000", + "field_60360": "Isabelle Richard", + "field_60361": "+33 3 80 12 34 56", + "field_60362": "isabelle.richard@example.com", + "field_60365": [ + 64, + 68 + ], + "field_60417": null, + "field_60418": null, + "field_60419": null, + "field_60420": null + }, + { + "id": 18, + "order": "18.00000000000000000000", + "created_on": "2025-03-04T05:25:53.161862+00:00", + "updated_on": "2025-03-06T10:19:58.288599+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60357": "SUPP-018", + "field_60358": "AlphaParts", + "field_60359": "246 Boulevard de la M\u00e9canique, Nantes, 44000", + "field_60360": "C\u00e9line Dupuis", + "field_60361": "+33 2 40 12 34 78", + "field_60362": "c\u00e9line.dupuis@example.com", + "field_60365": [ + 54, + 57, + 63, + 66, + 51 + ], + "field_60417": null, + "field_60418": null, + "field_60419": null, + "field_60420": null + } + ], + "data_sync": null + }, + { + "id": 5752, + "name": "Parts", + "order": 3, + "fields": [ + { + "id": 60366, + "type": "text", + "name": "Part Number", + "description": null, + "order": 0, + "primary": true, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "text_default": "" + }, + { + "id": 60367, + "type": "text", + "name": "Name", + "description": null, + "order": 1, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "text_default": "" + }, + { + "id": 60368, + "type": "text", + "name": "Description", + "description": null, + "order": 2, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "text_default": "" + }, + { + "id": 60369, + "type": "link_row", + "name": "Part categories", + "description": null, + "order": 4, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "link_row_table_id": 5753, + "link_row_related_field_id": 60373, + "link_row_limit_selection_view_id": null, + "has_related_field": true + }, + { + "id": 60371, + "type": "link_row", + "name": "Request details", + "description": null, + "order": 7, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "link_row_table_id": 5755, + "link_row_related_field_id": 60387, + "link_row_limit_selection_view_id": null, + "has_related_field": true + } + ], + "views": [ + { + "id": 26711, + "type": "grid", + "name": "All parts", + "order": 1, + "ownership_type": "collaborative", + "owned_by": "frederik@baserow.io", + "filter_type": "AND", + "filters_disabled": false, + "filters": [], + "filter_groups": [], + "sortings": [ + { + "id": 20608, + "field_id": 60366, + "order": "ASC" + } + ], + "group_bys": [], + "decorations": [], + "public": false, + "row_identifier_type": "id", + "row_height_size": "small", + "field_options": [ + { + "id": 264921, + "field_id": 60366, + "width": 140, + "hidden": false, + "order": 0, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264922, + "field_id": 60367, + "width": 263, + "hidden": false, + "order": 1, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264923, + "field_id": 60368, + "width": 349, + "hidden": false, + "order": 2, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264924, + "field_id": 60369, + "width": 185, + "hidden": false, + "order": 3, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264926, + "field_id": 60371, + "width": 200, + "hidden": false, + "order": 6, + "aggregation_type": "", + "aggregation_raw_type": "" + } + ] + }, + { + "id": 26722, + "type": "grid", + "name": "All parts grouped by category", + "order": 2, + "ownership_type": "collaborative", + "owned_by": "frederik@baserow.io", + "filter_type": "AND", + "filters_disabled": false, + "filters": [], + "filter_groups": [], + "sortings": [ + { + "id": 20617, + "field_id": 60366, + "order": "ASC" + } + ], + "group_bys": [ + { + "id": 3696, + "field_id": 60369, + "order": "ASC" + } + ], + "decorations": [], + "public": false, + "row_identifier_type": "id", + "row_height_size": "small", + "field_options": [ + { + "id": 265044, + "field_id": 60366, + "width": 140, + "hidden": false, + "order": 0, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 265045, + "field_id": 60367, + "width": 263, + "hidden": false, + "order": 1, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 265046, + "field_id": 60368, + "width": 349, + "hidden": false, + "order": 2, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 265047, + "field_id": 60369, + "width": 185, + "hidden": false, + "order": 3, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 265048, + "field_id": 60371, + "width": 200, + "hidden": false, + "order": 6, + "aggregation_type": "", + "aggregation_raw_type": "" + } + ] + } + ], + "rows": [ + { + "id": 1, + "order": "1.00000000000000000000", + "created_on": "2025-03-04T05:28:56.799177+00:00", + "updated_on": "2025-03-04T05:39:41.459620+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60366": "AERO-31201", + "field_60367": "ARM Cortex A76 Processor", + "field_60368": "High-efficiency CPU for avionics computing", + "field_60369": [ + 2 + ], + "field_60371": [ + 1, + 31 + ] + }, + { + "id": 2, + "order": "2.00000000000000000000", + "created_on": "2025-03-04T05:28:56.799259+00:00", + "updated_on": "2025-03-04T05:37:38.312582+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60366": "STOR-40582", + "field_60367": "512GB Aerospace SSD", + "field_60368": "High-speed solid-state storage for aircraft systems", + "field_60369": [ + 3 + ], + "field_60371": [ + 30, + 68 + ] + }, + { + "id": 3, + "order": "3.00000000000000000000", + "created_on": "2025-03-04T05:28:56.799293+00:00", + "updated_on": "2025-03-04T05:37:43.136816+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60366": "ELEC-28913", + "field_60367": "4.7k\u03a9 Precision Resistor", + "field_60368": "Tight tolerance resistor for aerospace circuits", + "field_60369": [ + 4 + ], + "field_60371": [ + 9, + 16 + ] + }, + { + "id": 4, + "order": "4.00000000000000000000", + "created_on": "2025-03-04T05:28:56.799325+00:00", + "updated_on": "2025-03-04T05:41:07.095780+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60366": "CTRL-67824", + "field_60367": "Aircraft Cockpit Control Panel", + "field_60368": "Central interface for pilot operations", + "field_60369": [ + 5 + ], + "field_60371": [ + 12 + ] + }, + { + "id": 5, + "order": "5.00000000000000000000", + "created_on": "2025-03-04T05:28:56.799356+00:00", + "updated_on": "2025-03-04T05:41:25.276948+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60366": "DISP-50233", + "field_60367": "10-Inch High-Brightness Display", + "field_60368": "Ruggedized touchscreen for flight decks", + "field_60369": [ + 1 + ], + "field_60371": [ + 33 + ] + }, + { + "id": 6, + "order": "6.00000000000000000000", + "created_on": "2025-03-04T05:28:56.799386+00:00", + "updated_on": "2025-03-04T05:37:01.787409+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60366": "AERO-32984", + "field_60367": "FPGA for Real-Time Processing", + "field_60368": "Optimized for avionics data computation", + "field_60369": [ + 2 + ], + "field_60371": [ + 36, + 37 + ] + }, + { + "id": 7, + "order": "7.00000000000000000000", + "created_on": "2025-03-04T05:28:56.799417+00:00", + "updated_on": "2025-03-04T05:37:37.069780+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60366": "STOR-49231", + "field_60367": "1TB NVMe Aerospace SSD", + "field_60368": "High-speed storage for navigation and logging", + "field_60369": [ + 3 + ], + "field_60371": [] + }, + { + "id": 8, + "order": "8.00000000000000000000", + "created_on": "2025-03-04T05:28:56.799446+00:00", + "updated_on": "2025-03-04T05:40:00.407527+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60366": "ELEC-21567", + "field_60367": "100\u03bcF Tantalum Capacitor", + "field_60368": "Stable capacitor for avionics power supplies", + "field_60369": [ + 4 + ], + "field_60371": [ + 2, + 29 + ] + }, + { + "id": 9, + "order": "9.00000000000000000000", + "created_on": "2025-03-04T05:28:56.799476+00:00", + "updated_on": "2025-03-04T05:40:58.933837+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60366": "CTRL-71234", + "field_60367": "Autopilot Control Module", + "field_60368": "Manages automated flight functions", + "field_60369": [ + 5 + ], + "field_60371": [ + 17 + ] + }, + { + "id": 10, + "order": "10.00000000000000000000", + "created_on": "2025-03-04T05:28:56.799515+00:00", + "updated_on": "2025-03-04T05:39:58.562952+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60366": "DISP-59876", + "field_60367": "7-Inch OLED Flight Display", + "field_60368": "High-contrast screen for cockpit use", + "field_60369": [ + 1 + ], + "field_60371": [ + 22 + ] + }, + { + "id": 11, + "order": "11.00000000000000000000", + "created_on": "2025-03-04T05:28:56.799554+00:00", + "updated_on": "2025-03-04T05:39:42.268183+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60366": "AERO-64152", + "field_60367": "Multi-Core RISC Processor", + "field_60368": "Low-power CPU for aerospace embedded systems", + "field_60369": [ + 2 + ], + "field_60371": [] + }, + { + "id": 12, + "order": "12.00000000000000000000", + "created_on": "2025-03-04T05:28:56.799613+00:00", + "updated_on": "2025-03-04T05:39:22.560734+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60366": "STOR-58342", + "field_60367": "256GB Secure Flash Memory", + "field_60368": "Encrypted storage for flight data", + "field_60369": [ + 3 + ], + "field_60371": [ + 54 + ] + }, + { + "id": 13, + "order": "13.00000000000000000000", + "created_on": "2025-03-04T05:28:56.799657+00:00", + "updated_on": "2025-03-04T05:40:01.313834+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60366": "ELEC-31984", + "field_60367": "50\u03a9 RF Termination Resistor", + "field_60368": "Essential for signal integrity in avionics", + "field_60369": [ + 4 + ], + "field_60371": [ + 34 + ] + }, + { + "id": 14, + "order": "14.00000000000000000000", + "created_on": "2025-03-04T05:28:56.799698+00:00", + "updated_on": "2025-03-04T05:41:09.927999+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60366": "CTRL-84573", + "field_60367": "Hydraulic System Control Board", + "field_60368": "Regulates aircraft hydraulic operations", + "field_60369": [ + 5 + ], + "field_60371": [] + }, + { + "id": 15, + "order": "15.00000000000000000000", + "created_on": "2025-03-04T05:28:56.799739+00:00", + "updated_on": "2025-03-04T05:41:16.513325+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60366": "DISP-21457", + "field_60367": "Ultra-Wide Avionics Display", + "field_60368": "Expanded field-of-view screen for navigation", + "field_60369": [ + 1 + ], + "field_60371": [] + }, + { + "id": 16, + "order": "16.00000000000000000000", + "created_on": "2025-03-04T05:28:56.799779+00:00", + "updated_on": "2025-03-04T05:39:42.846857+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60366": "AERO-75934", + "field_60367": "Neural Network Co-Processor", + "field_60368": "AI-driven chip for predictive maintenance", + "field_60369": [ + 2 + ], + "field_60371": [] + }, + { + "id": 17, + "order": "17.00000000000000000000", + "created_on": "2025-03-04T05:28:56.799820+00:00", + "updated_on": "2025-03-04T05:40:31.592444+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60366": "STOR-69382", + "field_60367": "2TB Flight Data Recorder SSD", + "field_60368": "Crash-resistant aerospace storage", + "field_60369": [ + 3 + ], + "field_60371": [ + 20, + 46 + ] + }, + { + "id": 18, + "order": "18.00000000000000000000", + "created_on": "2025-03-04T05:28:56.799862+00:00", + "updated_on": "2025-03-04T05:37:21.589259+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60366": "ELEC-47832", + "field_60367": "1mH Shielded Inductor", + "field_60368": "For avionics power and signal filtering", + "field_60369": [ + 4 + ], + "field_60371": [] + }, + { + "id": 19, + "order": "19.00000000000000000000", + "created_on": "2025-03-04T05:28:56.799903+00:00", + "updated_on": "2025-03-04T05:38:07.902216+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60366": "CTRL-98123", + "field_60367": "Landing Gear Control Unit", + "field_60368": "Automates aircraft landing gear deployment", + "field_60369": [ + 5 + ], + "field_60371": [] + }, + { + "id": 20, + "order": "20.00000000000000000000", + "created_on": "2025-03-04T05:28:56.799944+00:00", + "updated_on": "2025-03-04T05:41:20.918124+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60366": "DISP-41753", + "field_60367": "HUD Projection Display", + "field_60368": "Head-up display for augmented flight data", + "field_60369": [ + 1 + ], + "field_60371": [ + 13 + ] + }, + { + "id": 21, + "order": "21.00000000000000000000", + "created_on": "2025-03-04T05:28:56.799986+00:00", + "updated_on": "2025-03-04T05:38:12.779936+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60366": "AERO-56248", + "field_60367": "GPU for Advanced Graphics", + "field_60368": "Optimized for real-time cockpit visuals", + "field_60369": [ + 2 + ], + "field_60371": [] + }, + { + "id": 22, + "order": "22.00000000000000000000", + "created_on": "2025-03-04T05:28:56.800027+00:00", + "updated_on": "2025-03-04T05:40:26.700039+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60366": "STOR-31592", + "field_60367": "5TB Enterprise-Class SSD", + "field_60368": "Designed for aerospace server storage", + "field_60369": [ + 3 + ], + "field_60371": [ + 50 + ] + }, + { + "id": 23, + "order": "23.00000000000000000000", + "created_on": "2025-03-04T05:28:56.800070+00:00", + "updated_on": "2025-03-04T05:40:46.522448+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60366": "ELEC-71283", + "field_60367": "Surface Mount Ceramic Capacitor", + "field_60368": "Low-profile component for aerospace electronics", + "field_60369": [ + 4 + ], + "field_60371": [] + }, + { + "id": 24, + "order": "24.00000000000000000000", + "created_on": "2025-03-04T05:28:56.800112+00:00", + "updated_on": "2025-03-04T05:39:55.172381+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60366": "CTRL-67452", + "field_60367": "Pressurization System Interface", + "field_60368": "Monitors and adjusts cabin pressure", + "field_60369": [ + 5 + ], + "field_60371": [ + 23 + ] + }, + { + "id": 25, + "order": "25.00000000000000000000", + "created_on": "2025-03-04T05:28:56.800153+00:00", + "updated_on": "2025-03-04T05:37:20.392429+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60366": "DISP-35612", + "field_60367": "Multi-Touch Mission Display", + "field_60368": "Interactive panel for flight operations", + "field_60369": [ + 1 + ], + "field_60371": [ + 18 + ] + }, + { + "id": 26, + "order": "26.00000000000000000000", + "created_on": "2025-03-04T05:28:56.800194+00:00", + "updated_on": "2025-03-04T05:38:24.606283+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60366": "AERO-41567", + "field_60367": "Rad-Hardened Microprocessor", + "field_60368": "Designed for spaceborne applications", + "field_60369": [ + 2 + ], + "field_60371": [ + 51 + ] + }, + { + "id": 27, + "order": "27.00000000000000000000", + "created_on": "2025-03-04T05:28:56.800224+00:00", + "updated_on": "2025-03-04T05:40:35.124093+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60366": "STOR-81273", + "field_60367": "512GB Flight Recorder Storage", + "field_60368": "Secure, tamper-proof data storage", + "field_60369": [ + 3 + ], + "field_60371": [] + }, + { + "id": 28, + "order": "28.00000000000000000000", + "created_on": "2025-03-04T05:28:56.800254+00:00", + "updated_on": "2025-03-04T05:39:25.767221+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60366": "ELEC-92345", + "field_60367": "100pF RF Capacitor", + "field_60368": "Optimized for aerospace communications", + "field_60369": [ + 4 + ], + "field_60371": [ + 35 + ] + }, + { + "id": 29, + "order": "29.00000000000000000000", + "created_on": "2025-03-04T05:28:56.800283+00:00", + "updated_on": "2025-03-04T05:39:55.709223+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60366": "CTRL-56312", + "field_60367": "Flight Management System Panel", + "field_60368": "Controls aircraft navigation functions", + "field_60369": [ + 5 + ], + "field_60371": [ + 40 + ] + }, + { + "id": 30, + "order": "30.00000000000000000000", + "created_on": "2025-03-04T05:28:56.800312+00:00", + "updated_on": "2025-03-04T05:39:38.788039+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60366": "DISP-62453", + "field_60367": "8-Inch E-Ink Display", + "field_60368": "Power-efficient screen for aircraft manuals", + "field_60369": [ + 1 + ], + "field_60371": [ + 10 + ] + }, + { + "id": 31, + "order": "31.00000000000000000000", + "created_on": "2025-03-04T05:28:56.800341+00:00", + "updated_on": "2025-03-04T05:38:13.763021+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60366": "AERO-87432", + "field_60367": "AI-Enhanced DSP Processor", + "field_60368": "Real-time processing for avionics systems", + "field_60369": [ + 2 + ], + "field_60371": [] + }, + { + "id": 32, + "order": "32.00000000000000000000", + "created_on": "2025-03-04T05:28:56.800371+00:00", + "updated_on": "2025-03-04T05:39:18.052819+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60366": "STOR-95123", + "field_60367": "Low-Power NAND Flash", + "field_60368": "Energy-efficient storage for aerospace devices", + "field_60369": [ + 3 + ], + "field_60371": [ + 55 + ] + }, + { + "id": 33, + "order": "33.00000000000000000000", + "created_on": "2025-03-04T05:28:56.800399+00:00", + "updated_on": "2025-03-04T05:40:49.074762+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60366": "ELEC-64732", + "field_60367": "High-Frequency Crystal Oscillator", + "field_60368": "Provides precise clock signals", + "field_60369": [ + 4 + ], + "field_60371": [] + }, + { + "id": 34, + "order": "34.00000000000000000000", + "created_on": "2025-03-04T05:28:56.800429+00:00", + "updated_on": "2025-03-04T05:37:04.896489+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60366": "CTRL-57483", + "field_60367": "Aircraft Fuel Monitoring Board", + "field_60368": "Measures and regulates fuel levels", + "field_60369": [ + 5 + ], + "field_60371": [ + 14 + ] + }, + { + "id": 35, + "order": "35.00000000000000000000", + "created_on": "2025-03-04T05:28:56.800457+00:00", + "updated_on": "2025-03-04T05:39:39.202812+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60366": "DISP-23945", + "field_60367": "Color e-Paper Display", + "field_60368": "Sunlight-readable aerospace screen", + "field_60369": [ + 1 + ], + "field_60371": [ + 32 + ] + }, + { + "id": 36, + "order": "36.00000000000000000000", + "created_on": "2025-03-04T05:28:56.800490+00:00", + "updated_on": "2025-03-04T05:37:17.396309+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60366": "AERO-91247", + "field_60367": "Low-Power Embedded Chip", + "field_60368": "Optimized for aerospace battery-powered systems", + "field_60369": [ + 2 + ], + "field_60371": [ + 38 + ] + }, + { + "id": 37, + "order": "37.00000000000000000000", + "created_on": "2025-03-04T05:28:56.800529+00:00", + "updated_on": "2025-03-04T05:39:20.870840+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60366": "STOR-34682", + "field_60367": "128GB Industrial-Grade Memory Card", + "field_60368": "Durable storage for aerospace environments", + "field_60369": [ + 3 + ], + "field_60371": [ + 21, + 53, + 67 + ] + }, + { + "id": 38, + "order": "38.00000000000000000000", + "created_on": "2025-03-04T05:28:56.800570+00:00", + "updated_on": "2025-03-04T05:37:42.237581+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60366": "ELEC-89234", + "field_60367": "Microstrip RF Filter", + "field_60368": "For high-precision signal filtering", + "field_60369": [ + 4 + ], + "field_60371": [] + }, + { + "id": 39, + "order": "39.00000000000000000000", + "created_on": "2025-03-04T05:28:56.800610+00:00", + "updated_on": "2025-03-04T05:41:40.374396+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60366": "CTRL-98124", + "field_60367": "Environmental Control System Board", + "field_60368": "Regulates cabin air conditioning", + "field_60369": [ + 5 + ], + "field_60371": [] + }, + { + "id": 40, + "order": "40.00000000000000000000", + "created_on": "2025-03-04T05:28:56.800639+00:00", + "updated_on": "2025-03-04T05:38:28.078196+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60366": "DISP-43251", + "field_60367": "Flexible OLED Instrument Panel", + "field_60368": "Curved display for cockpit enhancements", + "field_60369": [ + 1 + ], + "field_60371": [ + 47 + ] + }, + { + "id": 41, + "order": "41.00000000000000000000", + "created_on": "2025-03-04T05:28:56.800668+00:00", + "updated_on": "2025-03-04T05:37:23.538835+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60366": "PWR-89324", + "field_60367": "48V Aircraft Power Converter", + "field_60368": "Converts high-voltage DC for avionics", + "field_60369": [ + 14 + ], + "field_60371": [ + 39, + 44, + 64 + ] + }, + { + "id": 42, + "order": "42.00000000000000000000", + "created_on": "2025-03-04T05:28:56.800697+00:00", + "updated_on": "2025-03-04T05:40:23.432147+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60366": "PWR-62438", + "field_60367": "High-Efficiency Fuel Cell", + "field_60368": "Provides auxiliary power to aircraft", + "field_60369": [ + 14 + ], + "field_60371": [ + 60 + ] + }, + { + "id": 43, + "order": "43.00000000000000000000", + "created_on": "2025-03-04T05:28:56.800735+00:00", + "updated_on": "2025-03-04T05:39:05.666425+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60366": "SENS-57238", + "field_60367": "Airflow Pressure Sensor", + "field_60368": "Monitors real-time aerodynamic pressure", + "field_60369": [ + 15 + ], + "field_60371": [ + 26 + ] + }, + { + "id": 44, + "order": "44.00000000000000000000", + "created_on": "2025-03-04T05:28:56.800774+00:00", + "updated_on": "2025-03-04T05:39:23.833505+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60366": "SENS-98234", + "field_60367": "Optical Navigation Sensor", + "field_60368": "Tracks aircraft position with high precision", + "field_60369": [ + 15 + ], + "field_60371": [ + 27 + ] + }, + { + "id": 45, + "order": "45.00000000000000000000", + "created_on": "2025-03-04T05:28:56.800813+00:00", + "updated_on": "2025-03-04T05:40:12.626269+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60366": "NET-21498", + "field_60367": "Aerospace Gigabit Router", + "field_60368": "Provides high-speed onboard connectivity", + "field_60369": [ + 9 + ], + "field_60371": [ + 19 + ] + }, + { + "id": 46, + "order": "46.00000000000000000000", + "created_on": "2025-03-04T05:28:56.800852+00:00", + "updated_on": "2025-03-04T05:40:12.365837+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60366": "NET-48923", + "field_60367": "Flight Data Synchronization Hub", + "field_60368": "Manages secure avionics data transfer", + "field_60369": [ + 9 + ], + "field_60371": [] + }, + { + "id": 47, + "order": "47.00000000000000000000", + "created_on": "2025-03-04T05:28:56.800892+00:00", + "updated_on": "2025-03-04T05:36:58.174836+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60366": "ANT-67234", + "field_60367": "Satellite Communication Antenna", + "field_60368": "Ensures reliable link to ground stations", + "field_60369": [ + 6 + ], + "field_60371": [] + }, + { + "id": 48, + "order": "48.00000000000000000000", + "created_on": "2025-03-04T05:28:56.800933+00:00", + "updated_on": "2025-03-04T05:37:13.538351+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60366": "ANT-82456", + "field_60367": "Phased Array Radar Antenna", + "field_60368": "Provides high-resolution weather tracking", + "field_60369": [ + 6 + ], + "field_60371": [] + }, + { + "id": 49, + "order": "49.00000000000000000000", + "created_on": "2025-03-04T05:28:56.800973+00:00", + "updated_on": "2025-03-04T05:40:03.406947+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60366": "ENG-48912", + "field_60367": "High-Efficiency Turbofan Engine", + "field_60368": "Optimized for fuel efficiency and thrust", + "field_60369": [ + 10 + ], + "field_60371": [] + }, + { + "id": 50, + "order": "50.00000000000000000000", + "created_on": "2025-03-04T05:28:56.801031+00:00", + "updated_on": "2025-03-04T05:39:03.327544+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60366": "ENG-67123", + "field_60367": "Electric Propulsion Unit", + "field_60368": "Advanced system for hybrid-electric aircraft", + "field_60369": [ + 10 + ], + "field_60371": [ + 65 + ] + }, + { + "id": 51, + "order": "51.00000000000000000000", + "created_on": "2025-03-04T05:28:56.801075+00:00", + "updated_on": "2025-03-04T05:37:55.003707+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60366": "HYD-57382", + "field_60367": "Aircraft Hydraulic Pump", + "field_60368": "Provides hydraulic power for control surfaces", + "field_60369": [ + 11 + ], + "field_60371": [] + }, + { + "id": 52, + "order": "52.00000000000000000000", + "created_on": "2025-03-04T05:28:56.801116+00:00", + "updated_on": "2025-03-04T05:37:55.326475+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60366": "HYD-92467", + "field_60367": "Landing Gear Actuator", + "field_60368": "Controls retraction and extension of gear", + "field_60369": [ + 11 + ], + "field_60371": [ + 43 + ] + }, + { + "id": 53, + "order": "53.00000000000000000000", + "created_on": "2025-03-04T05:28:56.801156+00:00", + "updated_on": "2025-03-04T05:40:14.621605+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60366": "MECH-67341", + "field_60367": "Carbon Fiber Structural Panel", + "field_60368": "Lightweight composite for aircraft fuselage", + "field_60369": [ + 12 + ], + "field_60371": [ + 25 + ] + }, + { + "id": 54, + "order": "54.00000000000000000000", + "created_on": "2025-03-04T05:28:56.801197+00:00", + "updated_on": "2025-03-04T05:37:41.163365+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60366": "MECH-89123", + "field_60367": "Titanium Fastener Set", + "field_60368": "Corrosion-resistant bolts for aerospace use", + "field_60369": [ + 12 + ], + "field_60371": [ + 15, + 45, + 62 + ] + }, + { + "id": 55, + "order": "55.00000000000000000000", + "created_on": "2025-03-04T05:28:56.801236+00:00", + "updated_on": "2025-03-04T05:41:27.998537+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60366": "COOL-62398", + "field_60367": "Avionics Liquid Cooling System", + "field_60368": "Removes excess heat from onboard electronics", + "field_60369": [ + 8 + ], + "field_60371": [] + }, + { + "id": 56, + "order": "56.00000000000000000000", + "created_on": "2025-03-04T05:28:56.801274+00:00", + "updated_on": "2025-03-04T05:37:19.157048+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60366": "COOL-89172", + "field_60367": "Phase Change Heat Sink", + "field_60368": "Passive cooling for extreme temperatures", + "field_60369": [ + 8 + ], + "field_60371": [] + }, + { + "id": 57, + "order": "57.00000000000000000000", + "created_on": "2025-03-04T05:28:56.801330+00:00", + "updated_on": "2025-03-04T05:40:19.298030+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60366": "OPT-57234", + "field_60367": "Aerospace Optical Fiber", + "field_60368": "Used for high-speed data transmission", + "field_60369": [ + 13 + ], + "field_60371": [ + 24 + ] + }, + { + "id": 58, + "order": "58.00000000000000000000", + "created_on": "2025-03-04T05:28:56.801373+00:00", + "updated_on": "2025-03-04T05:40:22.327235+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60366": "OPT-92834", + "field_60367": "Laser Gyroscope", + "field_60368": "Enhances inertial navigation accuracy", + "field_60369": [ + 13 + ], + "field_60371": [] + }, + { + "id": 59, + "order": "59.00000000000000000000", + "created_on": "2025-03-04T05:28:56.801416+00:00", + "updated_on": "2025-03-04T05:38:16.069814+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60366": "CHEM-67123", + "field_60367": "High-Performance Aircraft Grease", + "field_60368": "Reduces wear in extreme conditions", + "field_60369": [ + 7 + ], + "field_60371": [] + }, + { + "id": 60, + "order": "60.00000000000000000000", + "created_on": "2025-03-04T05:28:56.801458+00:00", + "updated_on": "2025-03-04T05:38:20.500842+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60366": "CHEM-78451", + "field_60367": "De-Icing Fluid", + "field_60368": "Prevents ice buildup on wings and surfaces", + "field_60369": [ + 7 + ], + "field_60371": [] + }, + { + "id": 61, + "order": "61.00000000000000000000", + "created_on": "2025-03-04T05:28:56.801500+00:00", + "updated_on": "2025-03-04T05:40:24.034052+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60366": "SEAL-78123", + "field_60367": "Fireproof Sealing Tape", + "field_60368": "Protects wiring from extreme heat", + "field_60369": [ + 16 + ], + "field_60371": [ + 59 + ] + }, + { + "id": 62, + "order": "62.00000000000000000000", + "created_on": "2025-03-04T05:28:56.801541+00:00", + "updated_on": "2025-03-04T05:39:06.798681+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60366": "SEAL-45238", + "field_60367": "Cockpit Soundproofing Foam", + "field_60368": "Reduces noise levels in the flight deck", + "field_60369": [ + 16 + ], + "field_60371": [] + }, + { + "id": 63, + "order": "63.00000000000000000000", + "created_on": "2025-03-04T05:28:56.801607+00:00", + "updated_on": "2025-03-04T05:42:01.282782+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60366": "ELEC-48392", + "field_60367": "Flight Control Relay Module", + "field_60368": "Manages electrical signals for control surfaces", + "field_60369": [ + 4 + ], + "field_60371": [] + }, + { + "id": 64, + "order": "64.00000000000000000000", + "created_on": "2025-03-04T05:28:56.801649+00:00", + "updated_on": "2025-03-04T05:42:01.282841+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60366": "ELEC-97321", + "field_60367": "High-Voltage MOSFET", + "field_60368": "Handles power switching in aerospace circuits", + "field_60369": [ + 4 + ], + "field_60371": [] + }, + { + "id": 65, + "order": "65.00000000000000000000", + "created_on": "2025-03-04T05:28:56.801690+00:00", + "updated_on": "2025-03-04T05:41:14.443370+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60366": "CTRL-91384", + "field_60367": "Digital Throttle Control Unit", + "field_60368": "Regulates engine thrust for efficiency", + "field_60369": [ + 5 + ], + "field_60371": [] + }, + { + "id": 66, + "order": "66.00000000000000000000", + "created_on": "2025-03-04T05:28:56.801732+00:00", + "updated_on": "2025-03-04T05:41:13.678958+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60366": "CTRL-78124", + "field_60367": "Automated Brake Control System", + "field_60368": "Enhances landing safety", + "field_60369": [ + 5 + ], + "field_60371": [] + }, + { + "id": 67, + "order": "67.00000000000000000000", + "created_on": "2025-03-04T05:28:56.801787+00:00", + "updated_on": "2025-03-04T05:37:00.796502+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60366": "ANT-72834", + "field_60367": "Multiband GPS Antenna", + "field_60368": "Supports multiple positioning frequencies", + "field_60369": [ + 6 + ], + "field_60371": [] + }, + { + "id": 68, + "order": "68.00000000000000000000", + "created_on": "2025-03-04T05:28:56.801838+00:00", + "updated_on": "2025-03-04T05:40:09.095485+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60366": "NET-34192", + "field_60367": "Avionics Ethernet Switch", + "field_60368": "Routes critical data within aircraft", + "field_60369": [ + 9 + ], + "field_60371": [] + }, + { + "id": 69, + "order": "69.00000000000000000000", + "created_on": "2025-03-04T05:28:56.801878+00:00", + "updated_on": "2025-03-04T05:39:08.795302+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60366": "PWR-67234", + "field_60367": "Aircraft Battery Management System", + "field_60368": "Monitors and optimizes battery performance", + "field_60369": [ + 14 + ], + "field_60371": [] + }, + { + "id": 70, + "order": "70.00000000000000000000", + "created_on": "2025-03-04T05:28:56.801937+00:00", + "updated_on": "2025-03-04T05:37:55.626675+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60366": "HYD-67123", + "field_60367": "Rudder Actuator System", + "field_60368": "Controls aircraft yaw movement", + "field_60369": [ + 11 + ], + "field_60371": [ + 41 + ] + }, + { + "id": 71, + "order": "71.00000000000000000000", + "created_on": "2025-03-04T05:28:56.801981+00:00", + "updated_on": "2025-03-04T05:38:53.749926+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60366": "ENG-62384", + "field_60367": "Variable Pitch Propeller Assembly", + "field_60368": "Adjusts blade angle for efficiency", + "field_60369": [ + 10 + ], + "field_60371": [] + }, + { + "id": 72, + "order": "72.00000000000000000000", + "created_on": "2025-03-04T05:28:56.802032+00:00", + "updated_on": "2025-03-04T05:41:27.313829+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60366": "COOL-92384", + "field_60367": "Aerospace Refrigeration Module", + "field_60368": "Keeps sensitive avionics at optimal temperature", + "field_60369": [ + 8 + ], + "field_60371": [] + }, + { + "id": 73, + "order": "73.00000000000000000000", + "created_on": "2025-03-04T05:28:56.802075+00:00", + "updated_on": "2025-03-04T05:37:05.980390+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60366": "DISP-98432", + "field_60367": "Heads-Up Display for Pilots", + "field_60368": "Projects flight data onto windshield", + "field_60369": [ + 1 + ], + "field_60371": [ + 58 + ] + }, + { + "id": 74, + "order": "74.00000000000000000000", + "created_on": "2025-03-04T05:28:56.802117+00:00", + "updated_on": "2025-03-04T05:38:25.575896+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60366": "AERO-70125", + "field_60367": "Quad-Core DSP Processor", + "field_60368": "Digital signal processor for radar and avionics", + "field_60369": [ + 2 + ], + "field_60371": [ + 52 + ] + }, + { + "id": 75, + "order": "75.00000000000000000000", + "created_on": "2025-03-04T05:28:56.802160+00:00", + "updated_on": "2025-03-04T05:37:24.893533+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60366": "STOR-95847", + "field_60367": "256GB Radiation-Hardened SSD", + "field_60368": "High-durability solid-state drive for aerospace applications", + "field_60369": [ + 3 + ], + "field_60371": [] + }, + { + "id": 76, + "order": "76.00000000000000000000", + "created_on": "2025-03-04T05:28:56.802204+00:00", + "updated_on": "2025-03-04T05:42:01.282856+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60366": "ELEC-37482", + "field_60367": "2.2\u03a9 High-Power Resistor", + "field_60368": "Used in power regulation circuits for avionics", + "field_60369": [ + 4 + ], + "field_60371": [ + 63 + ] + }, + { + "id": 77, + "order": "77.00000000000000000000", + "created_on": "2025-03-04T05:28:56.802246+00:00", + "updated_on": "2025-03-04T05:41:46.966392+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60366": "CTRL-83920", + "field_60367": "Flight Management System Panel", + "field_60368": "User interface for aircraft navigation and monitoring", + "field_60369": [ + 5 + ], + "field_60371": [] + }, + { + "id": 78, + "order": "78.00000000000000000000", + "created_on": "2025-03-04T05:28:56.802289+00:00", + "updated_on": "2025-03-04T05:39:27.387549+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60366": "DISP-67239", + "field_60367": "12-Inch Anti-Glare LCD Display", + "field_60368": "Optimized for cockpit use in bright conditions", + "field_60369": [ + 1 + ], + "field_60371": [] + }, + { + "id": 79, + "order": "79.00000000000000000000", + "created_on": "2025-03-04T05:28:56.802330+00:00", + "updated_on": "2025-03-04T05:38:09.491478+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60366": "AERO-82394", + "field_60367": "Multi-Core AI Accelerator", + "field_60368": "Optimized for in-flight AI data processing", + "field_60369": [ + 2 + ], + "field_60371": [] + }, + { + "id": 80, + "order": "80.00000000000000000000", + "created_on": "2025-03-04T05:28:56.802372+00:00", + "updated_on": "2025-03-04T05:39:12.179368+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60366": "STOR-27349", + "field_60367": "2TB Encrypted Aerospace HDD", + "field_60368": "Secure data storage for black box applications", + "field_60369": [ + 3 + ], + "field_60371": [] + }, + { + "id": 81, + "order": "81.00000000000000000000", + "created_on": "2025-03-04T05:28:56.802414+00:00", + "updated_on": "2025-03-04T05:38:29.465154+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60366": "ELEC-51283", + "field_60367": "470\u03bcF Electrolytic Capacitor", + "field_60368": "High-reliability capacitor for aerospace power systems", + "field_60369": [ + 4 + ], + "field_60371": [] + }, + { + "id": 82, + "order": "82.00000000000000000000", + "created_on": "2025-03-04T05:28:56.802457+00:00", + "updated_on": "2025-03-04T05:41:46.966419+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60366": "CTRL-90341", + "field_60367": "Engine Throttle Control Unit", + "field_60368": "Manages thrust adjustments in jet engines", + "field_60369": [ + 5 + ], + "field_60371": [] + }, + { + "id": 83, + "order": "83.00000000000000000000", + "created_on": "2025-03-04T05:28:56.802500+00:00", + "updated_on": "2025-03-04T05:38:06.400474+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60366": "DISP-31285", + "field_60367": "15-Inch Heads-Up Display (HUD)", + "field_60368": "Transparent screen for pilot navigation data", + "field_60369": [ + 1 + ], + "field_60371": [] + }, + { + "id": 84, + "order": "84.00000000000000000000", + "created_on": "2025-03-04T05:28:56.802543+00:00", + "updated_on": "2025-03-04T05:39:49.209021+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60366": "AERO-45237", + "field_60367": "RISC-V Avionics Processor", + "field_60368": "Low-power CPU for embedded flight systems", + "field_60369": [ + 2 + ], + "field_60371": [] + }, + { + "id": 85, + "order": "85.00000000000000000000", + "created_on": "2025-03-04T05:28:56.802587+00:00", + "updated_on": "2025-03-04T05:40:36.364990+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60366": "STOR-18374", + "field_60367": "512GB Industrial SD Card", + "field_60368": "High-endurance flash storage for aerospace systems", + "field_60369": [ + 3 + ], + "field_60371": [] + }, + { + "id": 86, + "order": "86.00000000000000000000", + "created_on": "2025-03-04T05:28:56.802630+00:00", + "updated_on": "2025-03-04T05:40:51.351492+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60366": "ELEC-76321", + "field_60367": "Inductive Proximity Sensor", + "field_60368": "Non-contact sensor for landing gear position detection", + "field_60369": [ + 4 + ], + "field_60371": [ + 11, + 28 + ] + }, + { + "id": 87, + "order": "87.00000000000000000000", + "created_on": "2025-03-04T05:28:56.802676+00:00", + "updated_on": "2025-03-04T05:39:57.220471+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60366": "CTRL-68452", + "field_60367": "Hydraulic Actuation Controller", + "field_60368": "Regulates hydraulic systems in aircraft", + "field_60369": [ + 5 + ], + "field_60371": [] + }, + { + "id": 88, + "order": "88.00000000000000000000", + "created_on": "2025-03-04T05:28:56.802719+00:00", + "updated_on": "2025-03-04T05:39:28.980874+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60366": "DISP-58134", + "field_60367": "8-Inch Flexible OLED Display", + "field_60368": "Curved screen for compact avionics panels", + "field_60369": [ + 1 + ], + "field_60371": [ + 48 + ] + }, + { + "id": 89, + "order": "89.00000000000000000000", + "created_on": "2025-03-04T05:28:56.802762+00:00", + "updated_on": "2025-03-04T05:39:52.585474+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60366": "AERO-23984", + "field_60367": "AI-Based Fault Detection Chip", + "field_60368": "Real-time anomaly detection in aircraft systems", + "field_60369": [ + 2 + ], + "field_60371": [] + }, + { + "id": 90, + "order": "90.00000000000000000000", + "created_on": "2025-03-04T05:28:56.802804+00:00", + "updated_on": "2025-03-04T05:40:25.624647+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60366": "STOR-98245", + "field_60367": "128GB Aerospace RAM Module", + "field_60368": "High-speed memory for mission-critical computing", + "field_60369": [ + 3 + ], + "field_60371": [] + }, + { + "id": 91, + "order": "91.00000000000000000000", + "created_on": "2025-03-04T05:28:56.802845+00:00", + "updated_on": "2025-03-04T05:42:05.807953+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60366": "ELEC-51237", + "field_60367": "150A Power MOSFET", + "field_60368": "High-efficiency transistor for aerospace power supplies", + "field_60369": [ + 4 + ], + "field_60371": [] + }, + { + "id": 92, + "order": "92.00000000000000000000", + "created_on": "2025-03-04T05:28:56.802888+00:00", + "updated_on": "2025-03-04T05:41:12.999625+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60366": "CTRL-34129", + "field_60367": "Autonomous Navigation Computer", + "field_60368": "Processes real-time flight path adjustments", + "field_60369": [ + 5 + ], + "field_60371": [ + 57 + ] + }, + { + "id": 93, + "order": "93.00000000000000000000", + "created_on": "2025-03-04T05:28:56.802930+00:00", + "updated_on": "2025-03-04T05:39:33.214619+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60366": "DISP-79134", + "field_60367": "Ultra-Wide Multi-Touch Display", + "field_60368": "Designed for advanced cockpit interface", + "field_60369": [ + 1 + ], + "field_60371": [ + 49 + ] + }, + { + "id": 94, + "order": "94.00000000000000000000", + "created_on": "2025-03-04T05:28:56.802975+00:00", + "updated_on": "2025-03-04T05:37:03.200321+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60366": "AERO-64829", + "field_60367": "Embedded Neural Processing Unit", + "field_60368": "AI acceleration for avionics data analysis", + "field_60369": [ + 2 + ], + "field_60371": [] + }, + { + "id": 95, + "order": "95.00000000000000000000", + "created_on": "2025-03-04T05:28:56.803017+00:00", + "updated_on": "2025-03-04T05:38:38.106708+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60366": "STOR-41723", + "field_60367": "4TB Solid-State Flight Recorder", + "field_60368": "Long-term storage for black box data", + "field_60369": [ + 3 + ], + "field_60371": [] + }, + { + "id": 96, + "order": "96.00000000000000000000", + "created_on": "2025-03-04T05:28:56.803057+00:00", + "updated_on": "2025-03-04T05:40:52.100634+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60366": "ELEC-91283", + "field_60367": "3.3V Voltage Regulator", + "field_60368": "Precision power supply component for avionics", + "field_60369": [ + 4 + ], + "field_60371": [] + }, + { + "id": 97, + "order": "97.00000000000000000000", + "created_on": "2025-03-04T05:28:56.803100+00:00", + "updated_on": "2025-03-04T05:41:28.711209+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60366": "CTRL-71283", + "field_60367": "Flap Position Control System", + "field_60368": "Manages wing flap positioning for optimal aerodynamics", + "field_60369": [ + 5 + ], + "field_60371": [] + }, + { + "id": 98, + "order": "98.00000000000000000000", + "created_on": "2025-03-04T05:28:56.803140+00:00", + "updated_on": "2025-03-04T05:39:28.277551+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60366": "DISP-82347", + "field_60367": "Panoramic Flight Deck Display", + "field_60368": "Enhanced situational awareness for pilots", + "field_60369": [ + 1 + ], + "field_60371": [ + 56 + ] + }, + { + "id": 99, + "order": "99.00000000000000000000", + "created_on": "2025-03-04T05:28:56.803182+00:00", + "updated_on": "2025-03-04T05:40:59.593822+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60366": "AERO-57493", + "field_60367": "Secure Boot Microcontroller", + "field_60368": "Provides cybersecurity for avionics firmware", + "field_60369": [ + 2 + ], + "field_60371": [] + }, + { + "id": 100, + "order": "100.00000000000000000000", + "created_on": "2025-03-04T05:28:56.803225+00:00", + "updated_on": "2025-03-04T05:37:29.366130+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60366": "STOR-13248", + "field_60367": "64GB Error-Correcting Memory", + "field_60368": "Ensures data integrity in flight computers", + "field_60369": [ + 3 + ], + "field_60371": [] + }, + { + "id": 101, + "order": "101.00000000000000000000", + "created_on": "2025-03-04T05:28:56.803264+00:00", + "updated_on": "2025-03-04T05:37:40.461932+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60366": "ELEC-64237", + "field_60367": "EMI Shielded Inductor", + "field_60368": "Reduces electromagnetic interference in avionics", + "field_60369": [ + 4 + ], + "field_60371": [] + }, + { + "id": 102, + "order": "102.00000000000000000000", + "created_on": "2025-03-04T05:28:56.803303+00:00", + "updated_on": "2025-03-04T05:41:12.118107+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60366": "CTRL-72384", + "field_60367": "Aircraft Autothrottle System", + "field_60368": "Controls engine power settings automatically", + "field_60369": [ + 5 + ], + "field_60371": [ + 42 + ] + }, + { + "id": 103, + "order": "103.00000000000000000000", + "created_on": "2025-03-04T05:28:56.803357+00:00", + "updated_on": "2025-03-04T05:38:03.453562+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60366": "DISP-42398", + "field_60367": "10.1-Inch Touchscreen Cockpit Display", + "field_60368": "Responsive and ruggedized for in-flight use", + "field_60369": [ + 1 + ], + "field_60371": [] + } + ], + "data_sync": null + }, + { + "id": 5753, + "name": "Part categories", + "order": 4, + "fields": [ + { + "id": 60372, + "type": "text", + "name": "Name", + "description": null, + "order": 0, + "primary": true, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "text_default": "" + }, + { + "id": 60373, + "type": "link_row", + "name": "Parts", + "description": null, + "order": 3, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "link_row_table_id": 5752, + "link_row_related_field_id": 60369, + "link_row_limit_selection_view_id": null, + "has_related_field": true + }, + { + "id": 60395, + "type": "count", + "name": "Count", + "description": null, + "order": 4, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "number_suffix": "", + "date_time_format": null, + "date_force_timezone": null, + "number_decimal_places": 0, + "date_include_time": null, + "number_prefix": "", + "duration_format": null, + "number_separator": "", + "nullable": false, + "date_format": null, + "array_formula_type": null, + "error": null, + "date_show_tzinfo": null, + "through_field_id": 60373 + } + ], + "views": [ + { + "id": 26712, + "type": "grid", + "name": "All categories", + "order": 1, + "ownership_type": "collaborative", + "owned_by": "frederik@baserow.io", + "filter_type": "AND", + "filters_disabled": false, + "filters": [], + "filter_groups": [], + "sortings": [ + { + "id": 20609, + "field_id": 60372, + "order": "ASC" + } + ], + "group_bys": [], + "decorations": [], + "public": false, + "row_identifier_type": "id", + "row_height_size": "small", + "field_options": [ + { + "id": 264928, + "field_id": 60372, + "width": 200, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264929, + "field_id": 60373, + "width": 200, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264930, + "field_id": 60395, + "width": 200, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + } + ] + } + ], + "rows": [ + { + "id": 1, + "order": "1.00000000000000000000", + "created_on": "2025-03-04T05:29:58.339600+00:00", + "updated_on": "2025-03-04T05:30:03.533924+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60372": "Displays", + "field_60373": [ + 5, + 10, + 15, + 20, + 25, + 30, + 35, + 40, + 73, + 78, + 83, + 88, + 93, + 98, + 103 + ], + "field_60395": null + }, + { + "id": 2, + "order": "2.00000000000000000000", + "created_on": "2025-03-04T05:29:58.339667+00:00", + "updated_on": "2025-03-04T05:30:14.485662+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60372": "Computer Chips", + "field_60373": [ + 1, + 6, + 11, + 16, + 21, + 26, + 31, + 36, + 74, + 79, + 84, + 89, + 94, + 99 + ], + "field_60395": null + }, + { + "id": 3, + "order": "3.00000000000000000000", + "created_on": "2025-03-04T05:30:14.268574+00:00", + "updated_on": "2025-03-04T05:30:14.485743+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60372": "Storage", + "field_60373": [ + 2, + 7, + 12, + 17, + 22, + 27, + 32, + 37, + 75, + 80, + 85, + 90, + 95, + 100 + ], + "field_60395": null + }, + { + "id": 4, + "order": "4.00000000000000000000", + "created_on": "2025-03-04T05:30:14.268664+00:00", + "updated_on": "2025-03-04T05:30:14.485770+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60372": "Electronic Components", + "field_60373": [ + 3, + 8, + 13, + 18, + 23, + 28, + 33, + 38, + 63, + 64, + 76, + 81, + 86, + 91, + 96, + 101 + ], + "field_60395": null + }, + { + "id": 5, + "order": "5.00000000000000000000", + "created_on": "2025-03-04T05:30:14.268700+00:00", + "updated_on": "2025-03-04T05:30:14.485793+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60372": "Control Panels", + "field_60373": [ + 4, + 9, + 14, + 19, + 24, + 29, + 34, + 39, + 65, + 66, + 77, + 82, + 87, + 92, + 97, + 102 + ], + "field_60395": null + }, + { + "id": 6, + "order": "6.00000000000000000000", + "created_on": "2025-03-04T05:30:29.497712+00:00", + "updated_on": "2025-03-04T05:30:31.001053+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60372": "Antennas", + "field_60373": [ + 47, + 48, + 67 + ], + "field_60395": null + }, + { + "id": 7, + "order": "7.00000000000000000000", + "created_on": "2025-03-04T05:30:30.737759+00:00", + "updated_on": "2025-03-04T05:30:31.001182+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60372": "Chemicals & Lubricants", + "field_60373": [ + 59, + 60 + ], + "field_60395": null + }, + { + "id": 8, + "order": "8.00000000000000000000", + "created_on": "2025-03-04T05:30:44.799114+00:00", + "updated_on": "2025-03-04T05:30:45.792384+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60372": "Cooling Systems", + "field_60373": [ + 55, + 56, + 72 + ], + "field_60395": null + }, + { + "id": 9, + "order": "9.00000000000000000000", + "created_on": "2025-03-04T05:30:59.632233+00:00", + "updated_on": "2025-03-04T05:31:59.843605+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60372": "Networking", + "field_60373": [ + 45, + 46, + 68 + ], + "field_60395": null + }, + { + "id": 10, + "order": "10.00000000000000000000", + "created_on": "2025-03-04T05:31:00.688882+00:00", + "updated_on": "2025-03-04T05:31:00.898758+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60372": "Engines", + "field_60373": [ + 49, + 50, + 71 + ], + "field_60395": null + }, + { + "id": 11, + "order": "11.00000000000000000000", + "created_on": "2025-03-04T05:31:11.087610+00:00", + "updated_on": "2025-03-04T05:31:13.024325+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60372": "Hydraulics", + "field_60373": [ + 51, + 52, + 70 + ], + "field_60395": null + }, + { + "id": 12, + "order": "12.00000000000000000000", + "created_on": "2025-03-04T05:31:12.856171+00:00", + "updated_on": "2025-03-04T05:31:13.024394+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60372": "Mechanical Components", + "field_60373": [ + 53, + 54 + ], + "field_60395": null + }, + { + "id": 13, + "order": "13.00000000000000000000", + "created_on": "2025-03-04T05:32:00.984238+00:00", + "updated_on": "2025-03-04T05:32:02.283729+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60372": "Optical Components", + "field_60373": [ + 57, + 58 + ], + "field_60395": null + }, + { + "id": 14, + "order": "14.00000000000000000000", + "created_on": "2025-03-04T05:32:02.054028+00:00", + "updated_on": "2025-03-04T05:32:02.283819+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60372": "Power Systems", + "field_60373": [ + 41, + 42, + 69 + ], + "field_60395": null + }, + { + "id": 15, + "order": "15.00000000000000000000", + "created_on": "2025-03-04T05:33:02.057241+00:00", + "updated_on": "2025-03-04T05:35:09.339270+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60372": "Sensors", + "field_60373": [ + 43, + 44 + ], + "field_60395": null + }, + { + "id": 16, + "order": "16.00000000000000000000", + "created_on": "2025-03-04T05:33:03.434460+00:00", + "updated_on": "2025-03-04T05:33:44.490979+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60372": "Seals & Insulation", + "field_60373": [ + 61, + 62 + ], + "field_60395": null + } + ], + "data_sync": null + }, + { + "id": 5754, + "name": "Requests", + "order": 5, + "fields": [ + { + "id": 60374, + "type": "formula", + "name": "ID", + "description": null, + "order": 0, + "primary": true, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "number_suffix": "", + "date_time_format": null, + "date_force_timezone": null, + "number_decimal_places": null, + "date_include_time": null, + "number_prefix": "", + "duration_format": null, + "number_separator": "", + "nullable": false, + "date_format": null, + "array_formula_type": null, + "error": null, + "date_show_tzinfo": null, + "formula": "if(row_id() < 10,concat('PRQ-0000',row_id()),if(row_id() < 100,concat('PRQ-000',row_id()),if(row_id() < 1000,concat('PRQ-00',row_id()),if(row_id() < 10000,concat('PRQ-0',row_id()),row_id()))))", + "formula_type": "text" + }, + { + "id": 60375, + "type": "link_row", + "name": "Global supplier", + "description": null, + "order": 1, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "link_row_table_id": 5751, + "link_row_related_field_id": 60365, + "link_row_limit_selection_view_id": null, + "has_related_field": true + }, + { + "id": 60394, + "type": "rollup", + "name": "Global supplier name", + "description": null, + "order": 2, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "number_suffix": "", + "date_time_format": null, + "date_force_timezone": null, + "number_decimal_places": null, + "date_include_time": null, + "number_prefix": "", + "duration_format": null, + "number_separator": "", + "nullable": true, + "date_format": null, + "array_formula_type": null, + "error": null, + "date_show_tzinfo": null, + "through_field_id": 60375, + "target_field_id": 60358, + "rollup_function": "min" + }, + { + "id": 60376, + "type": "long_text", + "name": "Comments", + "description": null, + "order": 3, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "long_text_enable_rich_text": false + }, + { + "id": 60377, + "type": "single_select", + "name": "Status", + "description": null, + "order": 4, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "select_options": [ + { + "id": 21176, + "value": "Request", + "color": "light-gray", + "order": 0 + }, + { + "id": 21177, + "value": "Quote", + "color": "light-pink", + "order": 1 + }, + { + "id": 21178, + "value": "Order", + "color": "light-brown", + "order": 2 + }, + { + "id": 21179, + "value": "Processing order", + "color": "light-yellow", + "order": 3 + }, + { + "id": 21180, + "value": "Delivery in progress", + "color": "light-cyan", + "order": 4 + }, + { + "id": 21181, + "value": "Closed", + "color": "light-green", + "order": 5 + } + ] + }, + { + "id": 60378, + "type": "link_row", + "name": "Request details", + "description": null, + "order": 5, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "link_row_table_id": 5755, + "link_row_related_field_id": 60386, + "link_row_limit_selection_view_id": null, + "has_related_field": true + }, + { + "id": 60379, + "type": "date", + "name": "Date request", + "description": null, + "order": 6, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "date_format": "ISO", + "date_include_time": false, + "date_time_format": "24", + "date_show_tzinfo": false, + "date_force_timezone": null + }, + { + "id": 60396, + "type": "rollup", + "name": "Requested", + "description": null, + "order": 7, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "number_suffix": "", + "date_time_format": null, + "date_force_timezone": null, + "number_decimal_places": 0, + "date_include_time": null, + "number_prefix": "", + "duration_format": null, + "number_separator": "", + "nullable": false, + "date_format": null, + "array_formula_type": null, + "error": null, + "date_show_tzinfo": null, + "through_field_id": 60378, + "target_field_id": 60389, + "rollup_function": "sum" + }, + { + "id": 60397, + "type": "rollup", + "name": "Approved", + "description": null, + "order": 8, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "number_suffix": "", + "date_time_format": null, + "date_force_timezone": null, + "number_decimal_places": 0, + "date_include_time": null, + "number_prefix": "", + "duration_format": null, + "number_separator": "", + "nullable": false, + "date_format": null, + "array_formula_type": null, + "error": null, + "date_show_tzinfo": null, + "through_field_id": 60378, + "target_field_id": 60390, + "rollup_function": "sum" + }, + { + "id": 60398, + "type": "rollup", + "name": "Delivered", + "description": null, + "order": 9, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "number_suffix": "", + "date_time_format": null, + "date_force_timezone": null, + "number_decimal_places": 0, + "date_include_time": null, + "number_prefix": "", + "duration_format": null, + "number_separator": "", + "nullable": false, + "date_format": null, + "array_formula_type": null, + "error": null, + "date_show_tzinfo": null, + "through_field_id": 60378, + "target_field_id": 60391, + "rollup_function": "sum" + }, + { + "id": 60405, + "type": "rollup", + "name": "Total requested", + "description": null, + "order": 10, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "number_suffix": "", + "date_time_format": null, + "date_force_timezone": null, + "number_decimal_places": 2, + "date_include_time": null, + "number_prefix": "\u20ac", + "duration_format": null, + "number_separator": "SPACE_PERIOD", + "nullable": false, + "date_format": null, + "array_formula_type": null, + "error": null, + "date_show_tzinfo": null, + "through_field_id": 60378, + "target_field_id": 60402, + "rollup_function": "sum" + }, + { + "id": 60406, + "type": "rollup", + "name": "Total approved", + "description": null, + "order": 11, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "number_suffix": "", + "date_time_format": null, + "date_force_timezone": null, + "number_decimal_places": 2, + "date_include_time": null, + "number_prefix": "\u20ac", + "duration_format": null, + "number_separator": "SPACE_PERIOD", + "nullable": false, + "date_format": null, + "array_formula_type": null, + "error": null, + "date_show_tzinfo": null, + "through_field_id": 60378, + "target_field_id": 60403, + "rollup_function": "sum" + }, + { + "id": 60381, + "type": "text", + "name": "Name", + "description": null, + "order": 14, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "text_default": "" + }, + { + "id": 60382, + "type": "date", + "name": "Date quote", + "description": null, + "order": 15, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "date_format": "ISO", + "date_include_time": false, + "date_time_format": "24", + "date_show_tzinfo": false, + "date_force_timezone": null + }, + { + "id": 60383, + "type": "date", + "name": "Date order", + "description": null, + "order": 16, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "date_format": "ISO", + "date_include_time": false, + "date_time_format": "24", + "date_show_tzinfo": false, + "date_force_timezone": null + }, + { + "id": 60384, + "type": "date", + "name": "Date delivery", + "description": null, + "order": 17, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "date_format": "ISO", + "date_include_time": false, + "date_time_format": "24", + "date_show_tzinfo": false, + "date_force_timezone": null + }, + { + "id": 60385, + "type": "formula", + "name": "Today", + "description": null, + "order": 18, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "number_suffix": "", + "date_time_format": "24", + "date_force_timezone": "UTC", + "number_decimal_places": null, + "date_include_time": false, + "number_prefix": "", + "duration_format": null, + "number_separator": "", + "nullable": true, + "date_format": "ISO", + "array_formula_type": null, + "error": null, + "date_show_tzinfo": false, + "formula": "today()", + "formula_type": "date" + }, + { + "id": 60412, + "type": "link_row", + "name": "Initiated by", + "description": null, + "order": 19, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "link_row_table_id": 5756, + "link_row_related_field_id": 60413, + "link_row_limit_selection_view_id": null, + "has_related_field": true + }, + { + "id": 60422, + "type": "formula", + "name": "Full approval", + "description": null, + "order": 20, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "number_suffix": "", + "date_time_format": null, + "date_force_timezone": null, + "number_decimal_places": null, + "date_include_time": null, + "number_prefix": "", + "duration_format": null, + "number_separator": "", + "nullable": false, + "date_format": null, + "array_formula_type": null, + "error": null, + "date_show_tzinfo": null, + "formula": "field('Requested') = field('Approved')", + "formula_type": "boolean" + }, + { + "id": 60423, + "type": "formula", + "name": "Full delivery", + "description": null, + "order": 21, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "number_suffix": "", + "date_time_format": null, + "date_force_timezone": null, + "number_decimal_places": null, + "date_include_time": null, + "number_prefix": "", + "duration_format": null, + "number_separator": "", + "nullable": false, + "date_format": null, + "array_formula_type": null, + "error": null, + "date_show_tzinfo": null, + "formula": "field('Delivered') = field('Approved')", + "formula_type": "boolean" + } + ], + "views": [ + { + "id": 26713, + "type": "grid", + "name": "All requests", + "order": 1, + "ownership_type": "collaborative", + "owned_by": "frederik@baserow.io", + "filter_type": "AND", + "filters_disabled": false, + "filters": [], + "filter_groups": [], + "sortings": [ + { + "id": 20618, + "field_id": 60379, + "order": "DESC" + } + ], + "group_bys": [], + "decorations": [], + "public": false, + "row_identifier_type": "id", + "row_height_size": "small", + "field_options": [ + { + "id": 264931, + "field_id": 60374, + "width": 143, + "hidden": false, + "order": 0, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264932, + "field_id": 60381, + "width": 200, + "hidden": false, + "order": 1, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264933, + "field_id": 60375, + "width": 155, + "hidden": false, + "order": 2, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264934, + "field_id": 60394, + "width": 207, + "hidden": false, + "order": 3, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264935, + "field_id": 60379, + "width": 151, + "hidden": false, + "order": 4, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264936, + "field_id": 60382, + "width": 145, + "hidden": false, + "order": 5, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264937, + "field_id": 60383, + "width": 137, + "hidden": false, + "order": 6, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264938, + "field_id": 60384, + "width": 147, + "hidden": false, + "order": 7, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264939, + "field_id": 60377, + "width": 167, + "hidden": false, + "order": 8, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264940, + "field_id": 60376, + "width": 200, + "hidden": false, + "order": 9, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264941, + "field_id": 60378, + "width": 200, + "hidden": false, + "order": 10, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264942, + "field_id": 60396, + "width": 136, + "hidden": false, + "order": 11, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264943, + "field_id": 60397, + "width": 128, + "hidden": false, + "order": 12, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 265049, + "field_id": 60422, + "width": 200, + "hidden": false, + "order": 13, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264944, + "field_id": 60398, + "width": 120, + "hidden": false, + "order": 14, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 265050, + "field_id": 60423, + "width": 200, + "hidden": false, + "order": 15, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264945, + "field_id": 60405, + "width": 161, + "hidden": false, + "order": 16, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264946, + "field_id": 60406, + "width": 167, + "hidden": false, + "order": 17, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264948, + "field_id": 60385, + "width": 200, + "hidden": true, + "order": 18, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 265024, + "field_id": 60412, + "width": 200, + "hidden": false, + "order": 19, + "aggregation_type": "", + "aggregation_raw_type": "" + } + ] + }, + { + "id": 26724, + "type": "grid", + "name": "All requests grouped by supplier", + "order": 2, + "ownership_type": "collaborative", + "owned_by": "frederik@baserow.io", + "filter_type": "AND", + "filters_disabled": false, + "filters": [], + "filter_groups": [], + "sortings": [ + { + "id": 20619, + "field_id": 60379, + "order": "DESC" + } + ], + "group_bys": [ + { + "id": 3697, + "field_id": 60394, + "order": "ASC" + } + ], + "decorations": [], + "public": false, + "row_identifier_type": "id", + "row_height_size": "small", + "field_options": [ + { + "id": 265053, + "field_id": 60374, + "width": 143, + "hidden": false, + "order": 0, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 265054, + "field_id": 60381, + "width": 200, + "hidden": false, + "order": 1, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 265055, + "field_id": 60375, + "width": 155, + "hidden": true, + "order": 2, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 265056, + "field_id": 60394, + "width": 207, + "hidden": true, + "order": 3, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 265057, + "field_id": 60379, + "width": 151, + "hidden": false, + "order": 4, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 265058, + "field_id": 60382, + "width": 145, + "hidden": false, + "order": 5, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 265059, + "field_id": 60383, + "width": 137, + "hidden": false, + "order": 6, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 265060, + "field_id": 60384, + "width": 147, + "hidden": false, + "order": 7, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 265061, + "field_id": 60377, + "width": 167, + "hidden": false, + "order": 8, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 265062, + "field_id": 60376, + "width": 200, + "hidden": false, + "order": 9, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 265063, + "field_id": 60378, + "width": 200, + "hidden": false, + "order": 10, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 265064, + "field_id": 60396, + "width": 136, + "hidden": false, + "order": 11, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 265065, + "field_id": 60397, + "width": 128, + "hidden": false, + "order": 12, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 265066, + "field_id": 60422, + "width": 200, + "hidden": false, + "order": 13, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 265067, + "field_id": 60398, + "width": 120, + "hidden": false, + "order": 14, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 265068, + "field_id": 60423, + "width": 200, + "hidden": false, + "order": 15, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 265069, + "field_id": 60405, + "width": 161, + "hidden": false, + "order": 16, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 265070, + "field_id": 60406, + "width": 167, + "hidden": false, + "order": 17, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 265071, + "field_id": 60385, + "width": 200, + "hidden": true, + "order": 18, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 265072, + "field_id": 60412, + "width": 200, + "hidden": false, + "order": 19, + "aggregation_type": "", + "aggregation_raw_type": "" + } + ] + }, + { + "id": 26725, + "type": "grid", + "name": "All requests grouped by initiator", + "order": 3, + "ownership_type": "collaborative", + "owned_by": "frederik@baserow.io", + "filter_type": "AND", + "filters_disabled": false, + "filters": [], + "filter_groups": [], + "sortings": [ + { + "id": 20620, + "field_id": 60379, + "order": "DESC" + } + ], + "group_bys": [ + { + "id": 3698, + "field_id": 60412, + "order": "ASC" + } + ], + "decorations": [], + "public": false, + "row_identifier_type": "id", + "row_height_size": "small", + "field_options": [ + { + "id": 265073, + "field_id": 60374, + "width": 143, + "hidden": false, + "order": 0, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 265074, + "field_id": 60381, + "width": 200, + "hidden": false, + "order": 1, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 265075, + "field_id": 60375, + "width": 155, + "hidden": false, + "order": 2, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 265076, + "field_id": 60394, + "width": 207, + "hidden": false, + "order": 3, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 265077, + "field_id": 60379, + "width": 151, + "hidden": false, + "order": 4, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 265078, + "field_id": 60382, + "width": 145, + "hidden": false, + "order": 5, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 265079, + "field_id": 60383, + "width": 137, + "hidden": false, + "order": 6, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 265080, + "field_id": 60384, + "width": 147, + "hidden": false, + "order": 7, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 265081, + "field_id": 60377, + "width": 167, + "hidden": false, + "order": 8, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 265082, + "field_id": 60376, + "width": 200, + "hidden": false, + "order": 9, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 265083, + "field_id": 60378, + "width": 200, + "hidden": false, + "order": 10, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 265084, + "field_id": 60396, + "width": 136, + "hidden": false, + "order": 11, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 265085, + "field_id": 60397, + "width": 128, + "hidden": false, + "order": 12, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 265086, + "field_id": 60422, + "width": 200, + "hidden": false, + "order": 13, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 265087, + "field_id": 60398, + "width": 120, + "hidden": false, + "order": 14, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 265088, + "field_id": 60423, + "width": 200, + "hidden": false, + "order": 15, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 265089, + "field_id": 60405, + "width": 161, + "hidden": false, + "order": 16, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 265090, + "field_id": 60406, + "width": 167, + "hidden": false, + "order": 17, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 265091, + "field_id": 60385, + "width": 200, + "hidden": true, + "order": 18, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 265092, + "field_id": 60412, + "width": 200, + "hidden": true, + "order": 19, + "aggregation_type": "", + "aggregation_raw_type": "" + } + ] + }, + { + "id": 26726, + "type": "grid", + "name": "Full approval requests", + "order": 4, + "ownership_type": "collaborative", + "owned_by": "frederik@baserow.io", + "filter_type": "AND", + "filters_disabled": false, + "filters": [ + { + "id": 14075, + "field_id": 60422, + "type": "boolean", + "value": "1", + "group": null + } + ], + "filter_groups": [], + "sortings": [ + { + "id": 20621, + "field_id": 60379, + "order": "DESC" + } + ], + "group_bys": [], + "decorations": [], + "public": false, + "row_identifier_type": "id", + "row_height_size": "small", + "field_options": [ + { + "id": 265093, + "field_id": 60374, + "width": 143, + "hidden": false, + "order": 0, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 265094, + "field_id": 60381, + "width": 200, + "hidden": false, + "order": 1, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 265095, + "field_id": 60375, + "width": 155, + "hidden": false, + "order": 2, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 265096, + "field_id": 60394, + "width": 207, + "hidden": false, + "order": 3, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 265097, + "field_id": 60379, + "width": 151, + "hidden": false, + "order": 4, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 265098, + "field_id": 60382, + "width": 145, + "hidden": false, + "order": 5, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 265099, + "field_id": 60383, + "width": 137, + "hidden": false, + "order": 6, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 265100, + "field_id": 60384, + "width": 147, + "hidden": false, + "order": 7, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 265101, + "field_id": 60377, + "width": 167, + "hidden": false, + "order": 8, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 265102, + "field_id": 60376, + "width": 200, + "hidden": false, + "order": 9, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 265103, + "field_id": 60378, + "width": 200, + "hidden": false, + "order": 10, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 265104, + "field_id": 60396, + "width": 136, + "hidden": false, + "order": 11, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 265105, + "field_id": 60397, + "width": 128, + "hidden": false, + "order": 12, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 265106, + "field_id": 60422, + "width": 200, + "hidden": false, + "order": 13, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 265107, + "field_id": 60398, + "width": 120, + "hidden": false, + "order": 14, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 265108, + "field_id": 60423, + "width": 200, + "hidden": false, + "order": 15, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 265109, + "field_id": 60405, + "width": 161, + "hidden": false, + "order": 16, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 265110, + "field_id": 60406, + "width": 167, + "hidden": false, + "order": 17, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 265111, + "field_id": 60385, + "width": 200, + "hidden": true, + "order": 18, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 265112, + "field_id": 60412, + "width": 200, + "hidden": false, + "order": 19, + "aggregation_type": "", + "aggregation_raw_type": "" + } + ] + }, + { + "id": 26727, + "type": "grid", + "name": "Full delivered requests", + "order": 5, + "ownership_type": "collaborative", + "owned_by": "frederik@baserow.io", + "filter_type": "AND", + "filters_disabled": false, + "filters": [ + { + "id": 14076, + "field_id": 60422, + "type": "boolean", + "value": "1", + "group": null + } + ], + "filter_groups": [], + "sortings": [ + { + "id": 20622, + "field_id": 60379, + "order": "DESC" + } + ], + "group_bys": [], + "decorations": [], + "public": false, + "row_identifier_type": "id", + "row_height_size": "small", + "field_options": [ + { + "id": 265113, + "field_id": 60374, + "width": 143, + "hidden": false, + "order": 0, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 265114, + "field_id": 60381, + "width": 200, + "hidden": false, + "order": 1, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 265115, + "field_id": 60375, + "width": 155, + "hidden": false, + "order": 2, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 265116, + "field_id": 60394, + "width": 207, + "hidden": false, + "order": 3, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 265117, + "field_id": 60379, + "width": 151, + "hidden": false, + "order": 4, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 265118, + "field_id": 60382, + "width": 145, + "hidden": false, + "order": 5, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 265119, + "field_id": 60383, + "width": 137, + "hidden": false, + "order": 6, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 265120, + "field_id": 60384, + "width": 147, + "hidden": false, + "order": 7, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 265121, + "field_id": 60377, + "width": 167, + "hidden": false, + "order": 8, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 265122, + "field_id": 60376, + "width": 200, + "hidden": false, + "order": 9, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 265123, + "field_id": 60378, + "width": 200, + "hidden": false, + "order": 10, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 265124, + "field_id": 60396, + "width": 136, + "hidden": false, + "order": 11, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 265125, + "field_id": 60397, + "width": 128, + "hidden": false, + "order": 12, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 265126, + "field_id": 60422, + "width": 200, + "hidden": false, + "order": 13, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 265127, + "field_id": 60398, + "width": 120, + "hidden": false, + "order": 14, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 265128, + "field_id": 60423, + "width": 200, + "hidden": false, + "order": 15, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 265129, + "field_id": 60405, + "width": 161, + "hidden": false, + "order": 16, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 265130, + "field_id": 60406, + "width": 167, + "hidden": false, + "order": 17, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 265131, + "field_id": 60385, + "width": 200, + "hidden": true, + "order": 18, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 265132, + "field_id": 60412, + "width": 200, + "hidden": false, + "order": 19, + "aggregation_type": "", + "aggregation_raw_type": "" + } + ] + }, + { + "id": 26714, + "type": "grid", + "name": "All open requests", + "order": 6, + "ownership_type": "collaborative", + "owned_by": "frederik@baserow.io", + "filter_type": "AND", + "filters_disabled": false, + "filters": [ + { + "id": 14073, + "field_id": 60377, + "type": "single_select_not_equal", + "value": "21181", + "group": null + } + ], + "filter_groups": [], + "sortings": [ + { + "id": 20610, + "field_id": 60379, + "order": "ASC" + } + ], + "group_bys": [], + "decorations": [], + "public": false, + "row_identifier_type": "id", + "row_height_size": "small", + "field_options": [ + { + "id": 264949, + "field_id": 60374, + "width": 143, + "hidden": false, + "order": 0, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264950, + "field_id": 60381, + "width": 200, + "hidden": false, + "order": 1, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264951, + "field_id": 60375, + "width": 172, + "hidden": false, + "order": 2, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264952, + "field_id": 60394, + "width": 208, + "hidden": false, + "order": 3, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264953, + "field_id": 60379, + "width": 150, + "hidden": false, + "order": 4, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264954, + "field_id": 60382, + "width": 200, + "hidden": false, + "order": 5, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264955, + "field_id": 60383, + "width": 200, + "hidden": false, + "order": 6, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264956, + "field_id": 60384, + "width": 200, + "hidden": false, + "order": 7, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264957, + "field_id": 60377, + "width": 128, + "hidden": false, + "order": 8, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264958, + "field_id": 60376, + "width": 200, + "hidden": false, + "order": 9, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264959, + "field_id": 60378, + "width": 200, + "hidden": false, + "order": 10, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264960, + "field_id": 60396, + "width": 135, + "hidden": false, + "order": 11, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264961, + "field_id": 60397, + "width": 133, + "hidden": false, + "order": 12, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 265051, + "field_id": 60422, + "width": 200, + "hidden": false, + "order": 13, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264962, + "field_id": 60398, + "width": 100, + "hidden": false, + "order": 14, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 265052, + "field_id": 60423, + "width": 200, + "hidden": false, + "order": 15, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264963, + "field_id": 60405, + "width": 143, + "hidden": false, + "order": 16, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264964, + "field_id": 60406, + "width": 145, + "hidden": false, + "order": 17, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264966, + "field_id": 60385, + "width": 200, + "hidden": true, + "order": 18, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 265027, + "field_id": 60412, + "width": 200, + "hidden": false, + "order": 19, + "aggregation_type": "", + "aggregation_raw_type": "" + } + ] + }, + { + "id": 26723, + "type": "kanban", + "name": "All requests stacked by status", + "order": 7, + "ownership_type": "collaborative", + "owned_by": "frederik@baserow.io", + "filter_type": "AND", + "filters_disabled": false, + "filters": [], + "filter_groups": [], + "sortings": [], + "decorations": [], + "public": false, + "single_select_field_id": 60377, + "field_options": [ + { + "id": 35380, + "field_id": 60374, + "hidden": false, + "order": 32767 + }, + { + "id": 35381, + "field_id": 60375, + "hidden": false, + "order": 32767 + }, + { + "id": 35383, + "field_id": 60376, + "hidden": false, + "order": 32767 + }, + { + "id": 35384, + "field_id": 60377, + "hidden": true, + "order": 32767 + }, + { + "id": 35385, + "field_id": 60378, + "hidden": true, + "order": 32767 + }, + { + "id": 35386, + "field_id": 60379, + "hidden": true, + "order": 32767 + }, + { + "id": 35392, + "field_id": 60381, + "hidden": true, + "order": 32767 + }, + { + "id": 35393, + "field_id": 60382, + "hidden": true, + "order": 32767 + }, + { + "id": 35394, + "field_id": 60383, + "hidden": true, + "order": 32767 + }, + { + "id": 35395, + "field_id": 60384, + "hidden": true, + "order": 32767 + }, + { + "id": 35396, + "field_id": 60385, + "hidden": true, + "order": 32767 + }, + { + "id": 35382, + "field_id": 60394, + "hidden": true, + "order": 32767 + }, + { + "id": 35387, + "field_id": 60396, + "hidden": true, + "order": 32767 + }, + { + "id": 35388, + "field_id": 60397, + "hidden": true, + "order": 32767 + }, + { + "id": 35389, + "field_id": 60398, + "hidden": true, + "order": 32767 + }, + { + "id": 35390, + "field_id": 60405, + "hidden": true, + "order": 32767 + }, + { + "id": 35391, + "field_id": 60406, + "hidden": true, + "order": 32767 + }, + { + "id": 35397, + "field_id": 60412, + "hidden": true, + "order": 32767 + }, + { + "id": 35398, + "field_id": 60422, + "hidden": true, + "order": 32767 + }, + { + "id": 35399, + "field_id": 60423, + "hidden": true, + "order": 32767 + } + ] + }, + { + "id": 26728, + "type": "calendar", + "name": "Calendar: all request", + "order": 8, + "ownership_type": "collaborative", + "owned_by": "frederik@baserow.io", + "filter_type": "AND", + "filters_disabled": false, + "filters": [], + "filter_groups": [], + "sortings": [], + "decorations": [ + { + "id": 8803, + "type": "left_border_color", + "value_provider_type": "single_select_color", + "value_provider_conf": { + "field_id": 60377 + }, + "order": 1 + } + ], + "public": false, + "date_field_id": 60379, + "field_options": [ + { + "id": 12607, + "field_id": 60374, + "hidden": false, + "order": 32767 + }, + { + "id": 12608, + "field_id": 60375, + "hidden": true, + "order": 32767 + }, + { + "id": 12610, + "field_id": 60376, + "hidden": true, + "order": 32767 + }, + { + "id": 12611, + "field_id": 60377, + "hidden": true, + "order": 32767 + }, + { + "id": 12612, + "field_id": 60378, + "hidden": true, + "order": 32767 + }, + { + "id": 12613, + "field_id": 60379, + "hidden": true, + "order": 32767 + }, + { + "id": 12619, + "field_id": 60381, + "hidden": true, + "order": 32767 + }, + { + "id": 12620, + "field_id": 60382, + "hidden": true, + "order": 32767 + }, + { + "id": 12621, + "field_id": 60383, + "hidden": true, + "order": 32767 + }, + { + "id": 12622, + "field_id": 60384, + "hidden": true, + "order": 32767 + }, + { + "id": 12623, + "field_id": 60385, + "hidden": true, + "order": 32767 + }, + { + "id": 12609, + "field_id": 60394, + "hidden": true, + "order": 32767 + }, + { + "id": 12614, + "field_id": 60396, + "hidden": true, + "order": 32767 + }, + { + "id": 12615, + "field_id": 60397, + "hidden": true, + "order": 32767 + }, + { + "id": 12616, + "field_id": 60398, + "hidden": true, + "order": 32767 + }, + { + "id": 12617, + "field_id": 60405, + "hidden": true, + "order": 32767 + }, + { + "id": 12618, + "field_id": 60406, + "hidden": true, + "order": 32767 + }, + { + "id": 12624, + "field_id": 60412, + "hidden": true, + "order": 32767 + }, + { + "id": 12625, + "field_id": 60422, + "hidden": true, + "order": 32767 + }, + { + "id": 12626, + "field_id": 60423, + "hidden": true, + "order": 32767 + } + ] + }, + { + "id": 26729, + "type": "timeline", + "name": "Timeline: request processing", + "order": 9, + "ownership_type": "collaborative", + "owned_by": "frederik@baserow.io", + "filter_type": "AND", + "filters_disabled": false, + "filters": [], + "filter_groups": [], + "sortings": [], + "decorations": [ + { + "id": 8804, + "type": "left_border_color", + "value_provider_type": "single_select_color", + "value_provider_conf": { + "field_id": 60377 + }, + "order": 1 + } + ], + "public": false, + "start_date_field_id": 60379, + "end_date_field_id": 60384, + "field_options": [ + { + "id": 1538, + "field_id": 60374, + "hidden": false, + "order": 32767 + }, + { + "id": 1539, + "field_id": 60375, + "hidden": true, + "order": 32767 + }, + { + "id": 1541, + "field_id": 60376, + "hidden": true, + "order": 32767 + }, + { + "id": 1542, + "field_id": 60377, + "hidden": true, + "order": 32767 + }, + { + "id": 1543, + "field_id": 60378, + "hidden": true, + "order": 32767 + }, + { + "id": 1544, + "field_id": 60379, + "hidden": true, + "order": 32767 + }, + { + "id": 1550, + "field_id": 60381, + "hidden": false, + "order": 32767 + }, + { + "id": 1551, + "field_id": 60382, + "hidden": true, + "order": 32767 + }, + { + "id": 1552, + "field_id": 60383, + "hidden": true, + "order": 32767 + }, + { + "id": 1553, + "field_id": 60384, + "hidden": true, + "order": 32767 + }, + { + "id": 1554, + "field_id": 60385, + "hidden": true, + "order": 32767 + }, + { + "id": 1540, + "field_id": 60394, + "hidden": false, + "order": 32767 + }, + { + "id": 1545, + "field_id": 60396, + "hidden": true, + "order": 32767 + }, + { + "id": 1546, + "field_id": 60397, + "hidden": true, + "order": 32767 + }, + { + "id": 1547, + "field_id": 60398, + "hidden": true, + "order": 32767 + }, + { + "id": 1548, + "field_id": 60405, + "hidden": true, + "order": 32767 + }, + { + "id": 1549, + "field_id": 60406, + "hidden": true, + "order": 32767 + }, + { + "id": 1555, + "field_id": 60412, + "hidden": true, + "order": 32767 + }, + { + "id": 1556, + "field_id": 60422, + "hidden": true, + "order": 32767 + }, + { + "id": 1557, + "field_id": 60423, + "hidden": true, + "order": 32767 + } + ] + } + ], + "rows": [ + { + "id": 47, + "order": "1.00000000000000000000", + "created_on": "2025-03-04T12:46:29.756518+00:00", + "updated_on": "2025-03-06T10:23:45.197116+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60374": null, + "field_60375": [ + 1 + ], + "field_60394": null, + "field_60376": "", + "field_60377": 21181, + "field_60378": [ + 1, + 2, + 9, + 10 + ], + "field_60379": "2025-02-05", + "field_60396": null, + "field_60397": null, + "field_60398": null, + "field_60405": null, + "field_60406": null, + "field_60381": "Aerospace Components Order", + "field_60382": "2025-02-07", + "field_60383": "2025-02-10", + "field_60384": "2025-02-19", + "field_60385": null, + "field_60412": [ + 1 + ], + "field_60422": null, + "field_60423": null + }, + { + "id": 48, + "order": "2.00000000000000000000", + "created_on": "2025-03-04T12:46:31.774041+00:00", + "updated_on": "2025-03-06T10:23:45.197222+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60374": null, + "field_60375": [ + 6 + ], + "field_60394": null, + "field_60376": "", + "field_60377": 21181, + "field_60378": [ + 11, + 12, + 13 + ], + "field_60379": "2025-02-06", + "field_60396": null, + "field_60397": null, + "field_60398": null, + "field_60405": null, + "field_60406": null, + "field_60381": "Defense Equipment Purchase", + "field_60382": "2025-02-10", + "field_60383": "2025-02-12", + "field_60384": "2025-02-21", + "field_60385": null, + "field_60412": [ + 2 + ], + "field_60422": null, + "field_60423": null + }, + { + "id": 49, + "order": "3.00000000000000000000", + "created_on": "2025-03-04T12:46:31.774139+00:00", + "updated_on": "2025-03-06T10:23:45.197278+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60374": null, + "field_60375": [ + 1 + ], + "field_60394": null, + "field_60376": "Please expedite delivery; this is urgent for project completion.", + "field_60377": 21181, + "field_60378": [ + 14 + ], + "field_60379": "2025-02-06", + "field_60396": null, + "field_60397": null, + "field_60398": null, + "field_60405": null, + "field_60406": null, + "field_60381": "Security Systems Order", + "field_60382": "2025-02-10", + "field_60383": "2025-02-12", + "field_60384": "2025-03-21", + "field_60385": null, + "field_60412": [ + 3 + ], + "field_60422": null, + "field_60423": null + }, + { + "id": 50, + "order": "4.00000000000000000000", + "created_on": "2025-03-04T12:46:31.774191+00:00", + "updated_on": "2025-03-06T10:23:45.197322+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60374": null, + "field_60375": [ + 1 + ], + "field_60394": null, + "field_60376": "", + "field_60377": 21180, + "field_60378": [ + 15 + ], + "field_60379": "2025-02-07", + "field_60396": null, + "field_60397": null, + "field_60398": null, + "field_60405": null, + "field_60406": null, + "field_60381": "Ground Transportation Order", + "field_60382": "2025-02-10", + "field_60383": "2025-02-12", + "field_60384": null, + "field_60385": null, + "field_60412": [ + 1 + ], + "field_60422": null, + "field_60423": null + }, + { + "id": 51, + "order": "5.00000000000000000000", + "created_on": "2025-03-04T12:46:31.774238+00:00", + "updated_on": "2025-03-06T10:23:45.197367+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60374": null, + "field_60375": [ + 18 + ], + "field_60394": null, + "field_60376": "Verify that all items meet the specified technical requirements.", + "field_60377": 21180, + "field_60378": [ + 16, + 17, + 18, + 19 + ], + "field_60379": "2025-02-10", + "field_60396": null, + "field_60397": null, + "field_60398": null, + "field_60405": null, + "field_60406": null, + "field_60381": "Digital Identity Solutions Purchase", + "field_60382": "2025-02-12", + "field_60383": "2025-02-14", + "field_60384": null, + "field_60385": null, + "field_60412": [ + 3 + ], + "field_60422": null, + "field_60423": null + }, + { + "id": 52, + "order": "6.00000000000000000000", + "created_on": "2025-03-04T12:46:31.774288+00:00", + "updated_on": "2025-03-06T10:23:45.197422+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60374": null, + "field_60375": [ + 6 + ], + "field_60394": null, + "field_60376": "", + "field_60377": 21181, + "field_60378": [ + 20 + ], + "field_60379": "2025-02-10", + "field_60396": null, + "field_60397": null, + "field_60398": null, + "field_60405": null, + "field_60406": null, + "field_60381": "Air Traffic Management Order", + "field_60382": "2025-02-12", + "field_60383": "2025-02-14", + "field_60384": "2025-03-19", + "field_60385": null, + "field_60412": [ + 3 + ], + "field_60422": null, + "field_60423": null + }, + { + "id": 53, + "order": "7.00000000000000000000", + "created_on": "2025-03-04T12:46:31.774337+00:00", + "updated_on": "2025-03-06T10:23:45.197466+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60374": null, + "field_60375": [ + 1 + ], + "field_60394": null, + "field_60376": "", + "field_60377": 21180, + "field_60378": [ + 21, + 22, + 23 + ], + "field_60379": "2025-02-11", + "field_60396": null, + "field_60397": null, + "field_60398": null, + "field_60405": null, + "field_60406": null, + "field_60381": "Satellite Components Purchase", + "field_60382": "2025-02-13", + "field_60383": "2025-02-17", + "field_60384": null, + "field_60385": null, + "field_60412": [ + 1 + ], + "field_60422": null, + "field_60423": null + }, + { + "id": 54, + "order": "8.00000000000000000000", + "created_on": "2025-03-04T12:46:31.774389+00:00", + "updated_on": "2025-03-06T10:23:45.197508+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60374": null, + "field_60375": [ + 18 + ], + "field_60394": null, + "field_60376": "", + "field_60377": 21181, + "field_60378": [ + 24, + 25 + ], + "field_60379": "2025-02-11", + "field_60396": null, + "field_60397": null, + "field_60398": null, + "field_60405": null, + "field_60406": null, + "field_60381": "Cybersecurity Equipment Order", + "field_60382": "2025-02-13", + "field_60383": "2025-02-17", + "field_60384": "2025-03-27", + "field_60385": null, + "field_60412": [ + 4 + ], + "field_60422": null, + "field_60423": null + }, + { + "id": 55, + "order": "9.00000000000000000000", + "created_on": "2025-03-04T12:46:31.774436+00:00", + "updated_on": "2025-03-06T10:23:45.197550+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60374": null, + "field_60375": [ + 12 + ], + "field_60394": null, + "field_60376": "", + "field_60377": 21179, + "field_60378": [ + 26, + 27, + 28, + 29 + ], + "field_60379": "2025-02-11", + "field_60396": null, + "field_60397": null, + "field_60398": null, + "field_60405": null, + "field_60406": null, + "field_60381": "Radar Systems Purchase", + "field_60382": "2025-02-13", + "field_60383": "2025-02-17", + "field_60384": null, + "field_60385": null, + "field_60412": [ + 3 + ], + "field_60422": null, + "field_60423": null + }, + { + "id": 56, + "order": "10.00000000000000000000", + "created_on": "2025-03-04T12:46:31.774497+00:00", + "updated_on": "2025-03-06T10:23:45.197594+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60374": null, + "field_60375": [ + 6 + ], + "field_60394": null, + "field_60376": "", + "field_60377": 21179, + "field_60378": [ + 30, + 31 + ], + "field_60379": "2025-02-13", + "field_60396": null, + "field_60397": null, + "field_60398": null, + "field_60405": null, + "field_60406": null, + "field_60381": "Naval Equipment Order", + "field_60382": "2025-02-17", + "field_60383": "2025-02-19", + "field_60384": null, + "field_60385": null, + "field_60412": [ + 1 + ], + "field_60422": null, + "field_60423": null + }, + { + "id": 57, + "order": "11.00000000000000000000", + "created_on": "2025-03-04T12:46:31.774545+00:00", + "updated_on": "2025-03-06T10:23:45.197638+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60374": null, + "field_60375": [ + 18 + ], + "field_60394": null, + "field_60376": "", + "field_60377": 21179, + "field_60378": [ + 32, + 33, + 34 + ], + "field_60379": "2025-02-14", + "field_60396": null, + "field_60397": null, + "field_60398": null, + "field_60405": null, + "field_60406": null, + "field_60381": "Space Systems Order", + "field_60382": "2025-02-17", + "field_60383": "2025-02-19", + "field_60384": null, + "field_60385": null, + "field_60412": [ + 4 + ], + "field_60422": null, + "field_60423": null + }, + { + "id": 58, + "order": "12.00000000000000000000", + "created_on": "2025-03-04T12:46:31.774591+00:00", + "updated_on": "2025-03-06T10:23:45.197679+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60374": null, + "field_60375": [ + 12 + ], + "field_60394": null, + "field_60376": "Coordinate with the logistics team for special handling instructions", + "field_60377": 21178, + "field_60378": [ + 35, + 36 + ], + "field_60379": "2025-02-17", + "field_60396": null, + "field_60397": null, + "field_60398": null, + "field_60405": null, + "field_60406": null, + "field_60381": "Communication Equipment Purchase", + "field_60382": "2025-02-19", + "field_60383": "2025-02-21", + "field_60384": null, + "field_60385": null, + "field_60412": [ + 2 + ], + "field_60422": null, + "field_60423": null + }, + { + "id": 59, + "order": "13.00000000000000000000", + "created_on": "2025-03-04T12:46:31.774636+00:00", + "updated_on": "2025-03-06T10:23:45.197785+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60374": null, + "field_60375": [ + 6 + ], + "field_60394": null, + "field_60376": "Ensure that the order includes a detailed packing list for customs clearance.", + "field_60377": 21178, + "field_60378": [ + 37 + ], + "field_60379": "2025-02-17", + "field_60396": null, + "field_60397": null, + "field_60398": null, + "field_60405": null, + "field_60406": null, + "field_60381": "Training Simulation Order", + "field_60382": "2025-02-19", + "field_60383": "2025-02-21", + "field_60384": null, + "field_60385": null, + "field_60412": [ + 3 + ], + "field_60422": null, + "field_60423": null + }, + { + "id": 60, + "order": "14.00000000000000000000", + "created_on": "2025-03-04T12:46:31.774683+00:00", + "updated_on": "2025-03-06T10:23:45.197842+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60374": null, + "field_60375": [ + 6 + ], + "field_60394": null, + "field_60376": "", + "field_60377": 21178, + "field_60378": [ + 38 + ], + "field_60379": "2025-02-18", + "field_60396": null, + "field_60397": null, + "field_60398": null, + "field_60405": null, + "field_60406": null, + "field_60381": "Electronic Warfare Systems Purchase", + "field_60382": "2025-02-20", + "field_60383": "2025-02-24", + "field_60384": null, + "field_60385": null, + "field_60412": [ + 1 + ], + "field_60422": null, + "field_60423": null + }, + { + "id": 61, + "order": "15.00000000000000000000", + "created_on": "2025-03-04T12:46:31.774802+00:00", + "updated_on": "2025-03-06T10:23:45.197917+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60374": null, + "field_60375": [ + 12 + ], + "field_60394": null, + "field_60376": "Confirm that the supplier provides a warranty and after-sales support.", + "field_60377": 21177, + "field_60378": [ + 39, + 40, + 41, + 42, + 43 + ], + "field_60379": "2025-03-18", + "field_60396": null, + "field_60397": null, + "field_60398": null, + "field_60405": null, + "field_60406": null, + "field_60381": "Air Defense Systems Order", + "field_60382": "2025-03-20", + "field_60383": null, + "field_60384": null, + "field_60385": null, + "field_60412": [ + 2 + ], + "field_60422": null, + "field_60423": null + }, + { + "id": 62, + "order": "16.00000000000000000000", + "created_on": "2025-03-04T12:46:31.774849+00:00", + "updated_on": "2025-03-06T10:23:45.198089+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60374": null, + "field_60375": [ + 12 + ], + "field_60394": null, + "field_60376": "Request a certificate of compliance with industry standards.", + "field_60377": 21177, + "field_60378": [ + 44, + 45, + 46, + 47 + ], + "field_60379": "2025-03-19", + "field_60396": null, + "field_60397": null, + "field_60398": null, + "field_60405": null, + "field_60406": null, + "field_60381": "Border Control Solutions Purchase", + "field_60382": "2025-03-21", + "field_60383": null, + "field_60384": null, + "field_60385": null, + "field_60412": [ + 4 + ], + "field_60422": null, + "field_60423": null + }, + { + "id": 63, + "order": "17.00000000000000000000", + "created_on": "2025-03-04T12:46:31.774918+00:00", + "updated_on": "2025-03-06T10:23:45.198143+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60374": null, + "field_60375": [ + 18 + ], + "field_60394": null, + "field_60376": "", + "field_60377": 21177, + "field_60378": [ + 48, + 49, + 50, + 51, + 52 + ], + "field_60379": "2025-03-21", + "field_60396": null, + "field_60397": null, + "field_60398": null, + "field_60405": null, + "field_60406": null, + "field_60381": "Critical Infrastructure Protection Order", + "field_60382": "2025-03-24", + "field_60383": null, + "field_60384": null, + "field_60385": null, + "field_60412": [ + 4 + ], + "field_60422": null, + "field_60423": null + }, + { + "id": 64, + "order": "18.00000000000000000000", + "created_on": "2025-03-04T12:46:31.774967+00:00", + "updated_on": "2025-03-06T10:23:45.198186+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60374": null, + "field_60375": [ + 14 + ], + "field_60394": null, + "field_60376": "Schedule a quality inspection upon receipt of the order.", + "field_60377": 21178, + "field_60378": [ + 53 + ], + "field_60379": "2025-03-03", + "field_60396": null, + "field_60397": null, + "field_60398": null, + "field_60405": null, + "field_60406": null, + "field_60381": "Unmanned Aerial Vehicles Purchase", + "field_60382": "2025-03-05", + "field_60383": "2025-03-07", + "field_60384": null, + "field_60385": null, + "field_60412": [ + 1 + ], + "field_60422": null, + "field_60423": null + }, + { + "id": 65, + "order": "19.00000000000000000000", + "created_on": "2025-03-04T12:46:31.775015+00:00", + "updated_on": "2025-03-06T10:23:45.198228+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60374": null, + "field_60375": [ + 12 + ], + "field_60394": null, + "field_60376": "", + "field_60377": 21176, + "field_60378": [ + 54, + 55, + 56 + ], + "field_60379": "2025-03-03", + "field_60396": null, + "field_60397": null, + "field_60398": null, + "field_60405": null, + "field_60406": null, + "field_60381": "Maritime Surveillance Systems Order", + "field_60382": null, + "field_60383": null, + "field_60384": null, + "field_60385": null, + "field_60412": [ + 1 + ], + "field_60422": null, + "field_60423": null + }, + { + "id": 66, + "order": "20.00000000000000000000", + "created_on": "2025-03-04T12:46:31.775063+00:00", + "updated_on": "2025-03-06T10:23:45.198270+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60374": null, + "field_60375": [ + 18 + ], + "field_60394": null, + "field_60376": "Notify the finance department to prepare for payment upon delivery.", + "field_60377": 21176, + "field_60378": [ + 57, + 58, + 59, + 60 + ], + "field_60379": "2025-03-04", + "field_60396": null, + "field_60397": null, + "field_60398": null, + "field_60405": null, + "field_60406": null, + "field_60381": "Advanced Weapon Systems Purchase", + "field_60382": null, + "field_60383": null, + "field_60384": null, + "field_60385": null, + "field_60412": [ + 4 + ], + "field_60422": null, + "field_60423": null + }, + { + "id": 67, + "order": "21.00000000000000000000", + "created_on": "2025-03-04T13:24:07.056783+00:00", + "updated_on": "2025-03-06T10:23:45.198312+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60374": null, + "field_60375": [ + 1 + ], + "field_60394": null, + "field_60376": "Parts for new R&D project", + "field_60377": 21178, + "field_60378": [ + 62, + 63, + 64 + ], + "field_60379": "2025-03-03", + "field_60396": null, + "field_60397": null, + "field_60398": null, + "field_60405": null, + "field_60406": null, + "field_60381": "Parts for new R&D project", + "field_60382": "2025-03-04", + "field_60383": "2025-03-04", + "field_60384": null, + "field_60385": null, + "field_60412": [ + 1 + ], + "field_60422": null, + "field_60423": null + }, + { + "id": 68, + "order": "22.00000000000000000000", + "created_on": "2025-03-06T14:27:01.219608+00:00", + "updated_on": "2025-03-06T14:57:14.814031+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60374": null, + "field_60375": [ + 14 + ], + "field_60394": null, + "field_60376": "no comments", + "field_60377": 21177, + "field_60378": [ + 65, + 67, + 68 + ], + "field_60379": "2025-03-06", + "field_60396": null, + "field_60397": null, + "field_60398": null, + "field_60405": null, + "field_60406": null, + "field_60381": "test", + "field_60382": "2025-03-06", + "field_60383": "2025-03-06", + "field_60384": "2025-03-06", + "field_60385": null, + "field_60412": [ + 4 + ], + "field_60422": null, + "field_60423": null + } + ], + "data_sync": null + }, + { + "id": 5755, + "name": "Request details", + "order": 6, + "fields": [ + { + "id": 60399, + "type": "formula", + "name": "ID", + "description": null, + "order": 0, + "primary": true, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "number_suffix": "", + "date_time_format": null, + "date_force_timezone": null, + "number_decimal_places": null, + "date_include_time": null, + "number_prefix": "", + "duration_format": null, + "number_separator": "", + "nullable": false, + "date_format": null, + "array_formula_type": null, + "error": null, + "date_show_tzinfo": null, + "formula": "concat(join(lookup('Request','ID'),''),'--',join(lookup('Part','Part Number'),''))", + "formula_type": "text" + }, + { + "id": 60386, + "type": "link_row", + "name": "Request", + "description": null, + "order": 1, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "link_row_table_id": 5754, + "link_row_related_field_id": 60378, + "link_row_limit_selection_view_id": null, + "has_related_field": true + }, + { + "id": 60387, + "type": "link_row", + "name": "Part", + "description": null, + "order": 2, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "link_row_table_id": 5752, + "link_row_related_field_id": 60371, + "link_row_limit_selection_view_id": null, + "has_related_field": true + }, + { + "id": 60401, + "type": "rollup", + "name": "Part name", + "description": null, + "order": 4, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "number_suffix": "", + "date_time_format": null, + "date_force_timezone": null, + "number_decimal_places": null, + "date_include_time": null, + "number_prefix": "", + "duration_format": null, + "number_separator": "", + "nullable": true, + "date_format": null, + "array_formula_type": null, + "error": null, + "date_show_tzinfo": null, + "through_field_id": 60387, + "target_field_id": 60367, + "rollup_function": "min" + }, + { + "id": 60388, + "type": "number", + "name": "Unit price", + "description": null, + "order": 5, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "number_decimal_places": 2, + "number_negative": false, + "number_prefix": "\u20ac", + "number_suffix": "", + "number_separator": "SPACE_PERIOD" + }, + { + "id": 60389, + "type": "number", + "name": "Quantity requested", + "description": "Number of items requested in the purchase request", + "order": 6, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "number_decimal_places": 0, + "number_negative": false, + "number_prefix": "", + "number_suffix": "", + "number_separator": "" + }, + { + "id": 60390, + "type": "number", + "name": "Quantity approved", + "description": "Number of items validated in the quote", + "order": 7, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "number_decimal_places": 0, + "number_negative": false, + "number_prefix": "", + "number_suffix": "", + "number_separator": "" + }, + { + "id": 60391, + "type": "number", + "name": "Quantity Delivered", + "description": "Number of items delivered to the customer", + "order": 8, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "number_decimal_places": 0, + "number_negative": false, + "number_prefix": "", + "number_suffix": "", + "number_separator": "" + }, + { + "id": 60392, + "type": "single_select", + "name": "Status", + "description": null, + "order": 9, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "select_options": [ + { + "id": 21182, + "value": "Approved", + "color": "dark-green", + "order": 0 + }, + { + "id": 21183, + "value": "PN is replaced", + "color": "dark-cyan", + "order": 1 + }, + { + "id": 21184, + "value": "Quantity is adjusted", + "color": "dark-orange", + "order": 2 + }, + { + "id": 21185, + "value": "Rejected", + "color": "dark-red", + "order": 3 + } + ] + }, + { + "id": 60402, + "type": "formula", + "name": "Subtotal requested", + "description": null, + "order": 10, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "number_suffix": "", + "date_time_format": null, + "date_force_timezone": null, + "number_decimal_places": 2, + "date_include_time": null, + "number_prefix": "\u20ac", + "duration_format": null, + "number_separator": "SPACE_PERIOD", + "nullable": false, + "date_format": null, + "array_formula_type": null, + "error": null, + "date_show_tzinfo": null, + "formula": "field('Unit price') * field('Quantity requested')", + "formula_type": "number" + }, + { + "id": 60403, + "type": "formula", + "name": "Subtotal approved", + "description": null, + "order": 11, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "number_suffix": "", + "date_time_format": null, + "date_force_timezone": null, + "number_decimal_places": 2, + "date_include_time": null, + "number_prefix": "\u20ac", + "duration_format": null, + "number_separator": "SPACE_PERIOD", + "nullable": false, + "date_format": null, + "array_formula_type": null, + "error": null, + "date_show_tzinfo": null, + "formula": "field('Unit price') * field('Quantity approved')", + "formula_type": "number" + }, + { + "id": 60400, + "type": "formula", + "name": "Request NO", + "description": null, + "order": 12, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "number_suffix": "", + "date_time_format": null, + "date_force_timezone": null, + "number_decimal_places": null, + "date_include_time": null, + "number_prefix": "", + "duration_format": null, + "number_separator": "", + "nullable": false, + "date_format": null, + "array_formula_type": null, + "error": null, + "date_show_tzinfo": null, + "formula": "join(lookup('Request','ID'),'')", + "formula_type": "text" + }, + { + "id": 60404, + "type": "formula", + "name": "Request status", + "description": null, + "order": 13, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "number_suffix": "", + "date_time_format": null, + "date_force_timezone": null, + "number_decimal_places": null, + "date_include_time": null, + "number_prefix": "", + "duration_format": null, + "number_separator": "", + "nullable": false, + "date_format": null, + "array_formula_type": null, + "error": null, + "date_show_tzinfo": null, + "formula": "join(totext(lookup('Request','Status')),'')", + "formula_type": "text" + } + ], + "views": [ + { + "id": 26715, + "type": "grid", + "name": "All request details", + "order": 1, + "ownership_type": "collaborative", + "owned_by": "frederik@baserow.io", + "filter_type": "AND", + "filters_disabled": false, + "filters": [ + { + "id": 14068, + "field_id": 60386, + "type": "not_empty", + "value": "", + "group": null + } + ], + "filter_groups": [], + "sortings": [ + { + "id": 20611, + "field_id": 60386, + "order": "ASC" + } + ], + "group_bys": [], + "decorations": [], + "public": false, + "row_identifier_type": "id", + "row_height_size": "small", + "field_options": [ + { + "id": 264967, + "field_id": 60399, + "width": 146, + "hidden": false, + "order": 0, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264968, + "field_id": 60386, + "width": 168, + "hidden": false, + "order": 1, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264969, + "field_id": 60400, + "width": 200, + "hidden": true, + "order": 2, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264970, + "field_id": 60387, + "width": 126, + "hidden": false, + "order": 3, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264971, + "field_id": 60401, + "width": 325, + "hidden": false, + "order": 4, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264972, + "field_id": 60388, + "width": 138, + "hidden": false, + "order": 5, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264973, + "field_id": 60389, + "width": 162, + "hidden": false, + "order": 6, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264974, + "field_id": 60402, + "width": 145, + "hidden": false, + "order": 7, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264975, + "field_id": 60390, + "width": 163, + "hidden": false, + "order": 8, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264976, + "field_id": 60403, + "width": 141, + "hidden": false, + "order": 9, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264977, + "field_id": 60391, + "width": 159, + "hidden": false, + "order": 10, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264978, + "field_id": 60392, + "width": 200, + "hidden": false, + "order": 11, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264979, + "field_id": 60404, + "width": 200, + "hidden": true, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + } + ] + }, + { + "id": 26716, + "type": "grid", + "name": "All request details grouped by request", + "order": 2, + "ownership_type": "collaborative", + "owned_by": "frederik@baserow.io", + "filter_type": "AND", + "filters_disabled": false, + "filters": [ + { + "id": 14069, + "field_id": 60386, + "type": "not_empty", + "value": "", + "group": null + } + ], + "filter_groups": [], + "sortings": [ + { + "id": 20612, + "field_id": 60386, + "order": "ASC" + } + ], + "group_bys": [ + { + "id": 3694, + "field_id": 60386, + "order": "ASC" + } + ], + "decorations": [], + "public": false, + "row_identifier_type": "id", + "row_height_size": "small", + "field_options": [ + { + "id": 264980, + "field_id": 60399, + "width": 146, + "hidden": false, + "order": 0, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264981, + "field_id": 60386, + "width": 168, + "hidden": false, + "order": 1, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264982, + "field_id": 60400, + "width": 200, + "hidden": true, + "order": 2, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264983, + "field_id": 60387, + "width": 126, + "hidden": false, + "order": 3, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264984, + "field_id": 60401, + "width": 325, + "hidden": false, + "order": 4, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264985, + "field_id": 60388, + "width": 138, + "hidden": false, + "order": 5, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264986, + "field_id": 60389, + "width": 162, + "hidden": false, + "order": 6, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264987, + "field_id": 60402, + "width": 139, + "hidden": false, + "order": 7, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264988, + "field_id": 60390, + "width": 163, + "hidden": false, + "order": 8, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264989, + "field_id": 60403, + "width": 141, + "hidden": false, + "order": 9, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264990, + "field_id": 60391, + "width": 159, + "hidden": false, + "order": 10, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264991, + "field_id": 60392, + "width": 200, + "hidden": false, + "order": 11, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264992, + "field_id": 60404, + "width": 200, + "hidden": true, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + } + ] + }, + { + "id": 26730, + "type": "grid", + "name": "All request details grouped by part", + "order": 3, + "ownership_type": "collaborative", + "owned_by": "frederik@baserow.io", + "filter_type": "AND", + "filters_disabled": false, + "filters": [ + { + "id": 14077, + "field_id": 60386, + "type": "not_empty", + "value": "", + "group": null + } + ], + "filter_groups": [], + "sortings": [ + { + "id": 20623, + "field_id": 60386, + "order": "ASC" + } + ], + "group_bys": [ + { + "id": 3699, + "field_id": 60387, + "order": "ASC" + } + ], + "decorations": [], + "public": false, + "row_identifier_type": "id", + "row_height_size": "small", + "field_options": [ + { + "id": 265133, + "field_id": 60399, + "width": 146, + "hidden": false, + "order": 0, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 265134, + "field_id": 60386, + "width": 168, + "hidden": false, + "order": 1, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 265135, + "field_id": 60400, + "width": 200, + "hidden": true, + "order": 2, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 265136, + "field_id": 60387, + "width": 126, + "hidden": true, + "order": 3, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 265137, + "field_id": 60401, + "width": 325, + "hidden": false, + "order": 4, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 265138, + "field_id": 60388, + "width": 138, + "hidden": false, + "order": 5, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 265139, + "field_id": 60389, + "width": 162, + "hidden": false, + "order": 6, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 265140, + "field_id": 60402, + "width": 139, + "hidden": false, + "order": 7, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 265141, + "field_id": 60390, + "width": 163, + "hidden": false, + "order": 8, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 265142, + "field_id": 60403, + "width": 141, + "hidden": false, + "order": 9, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 265143, + "field_id": 60391, + "width": 159, + "hidden": false, + "order": 10, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 265144, + "field_id": 60392, + "width": 200, + "hidden": false, + "order": 11, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 265145, + "field_id": 60404, + "width": 200, + "hidden": true, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + } + ] + }, + { + "id": 26717, + "type": "grid", + "name": "All request details with status Request", + "order": 4, + "ownership_type": "collaborative", + "owned_by": "frederik@baserow.io", + "filter_type": "AND", + "filters_disabled": false, + "filters": [ + { + "id": 14070, + "field_id": 60386, + "type": "not_empty", + "value": "", + "group": null + }, + { + "id": 14071, + "field_id": 60404, + "type": "equal", + "value": "Request", + "group": null + } + ], + "filter_groups": [], + "sortings": [ + { + "id": 20613, + "field_id": 60400, + "order": "ASC" + } + ], + "group_bys": [ + { + "id": 3695, + "field_id": 60400, + "order": "ASC" + } + ], + "decorations": [], + "public": false, + "row_identifier_type": "id", + "row_height_size": "small", + "field_options": [ + { + "id": 264993, + "field_id": 60399, + "width": 146, + "hidden": false, + "order": 0, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264994, + "field_id": 60386, + "width": 168, + "hidden": false, + "order": 1, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264995, + "field_id": 60400, + "width": 200, + "hidden": true, + "order": 2, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264996, + "field_id": 60387, + "width": 126, + "hidden": false, + "order": 3, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264997, + "field_id": 60401, + "width": 325, + "hidden": false, + "order": 4, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264998, + "field_id": 60388, + "width": 138, + "hidden": false, + "order": 5, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264999, + "field_id": 60389, + "width": 162, + "hidden": false, + "order": 6, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 265000, + "field_id": 60402, + "width": 139, + "hidden": false, + "order": 7, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 265001, + "field_id": 60390, + "width": 163, + "hidden": false, + "order": 8, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 265002, + "field_id": 60403, + "width": 141, + "hidden": false, + "order": 9, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 265003, + "field_id": 60391, + "width": 159, + "hidden": false, + "order": 10, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 265004, + "field_id": 60392, + "width": 200, + "hidden": false, + "order": 11, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 265005, + "field_id": 60404, + "width": 200, + "hidden": true, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + } + ] + }, + { + "id": 26718, + "type": "grid", + "name": "Empty request details", + "order": 5, + "ownership_type": "collaborative", + "owned_by": "frederik@baserow.io", + "filter_type": "AND", + "filters_disabled": false, + "filters": [ + { + "id": 14072, + "field_id": 60386, + "type": "empty", + "value": "", + "group": null + } + ], + "filter_groups": [], + "sortings": [ + { + "id": 20614, + "field_id": 60386, + "order": "ASC" + } + ], + "group_bys": [], + "decorations": [], + "public": false, + "row_identifier_type": "id", + "row_height_size": "small", + "field_options": [ + { + "id": 265006, + "field_id": 60399, + "width": 146, + "hidden": false, + "order": 0, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 265007, + "field_id": 60386, + "width": 168, + "hidden": false, + "order": 1, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 265008, + "field_id": 60400, + "width": 200, + "hidden": true, + "order": 2, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 265009, + "field_id": 60387, + "width": 126, + "hidden": false, + "order": 3, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 265010, + "field_id": 60401, + "width": 325, + "hidden": false, + "order": 4, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 265011, + "field_id": 60388, + "width": 138, + "hidden": false, + "order": 5, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 265012, + "field_id": 60389, + "width": 162, + "hidden": false, + "order": 6, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 265013, + "field_id": 60402, + "width": 139, + "hidden": false, + "order": 7, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 265014, + "field_id": 60390, + "width": 163, + "hidden": false, + "order": 8, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 265015, + "field_id": 60403, + "width": 141, + "hidden": false, + "order": 9, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 265016, + "field_id": 60391, + "width": 159, + "hidden": false, + "order": 10, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 265017, + "field_id": 60392, + "width": 200, + "hidden": false, + "order": 11, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 265018, + "field_id": 60404, + "width": 200, + "hidden": true, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + } + ] + }, + { + "id": 26719, + "type": "kanban", + "name": "All request details stacked by status", + "order": 6, + "ownership_type": "collaborative", + "owned_by": "frederik@baserow.io", + "filter_type": "AND", + "filters_disabled": false, + "filters": [], + "filter_groups": [], + "sortings": [], + "decorations": [], + "public": false, + "single_select_field_id": 60392, + "field_options": [ + { + "id": 35367, + "field_id": 60386, + "hidden": false, + "order": 32767 + }, + { + "id": 35368, + "field_id": 60387, + "hidden": false, + "order": 32767 + }, + { + "id": 35369, + "field_id": 60388, + "hidden": true, + "order": 32767 + }, + { + "id": 35370, + "field_id": 60389, + "hidden": true, + "order": 32767 + }, + { + "id": 35371, + "field_id": 60390, + "hidden": true, + "order": 32767 + }, + { + "id": 35372, + "field_id": 60391, + "hidden": true, + "order": 32767 + }, + { + "id": 35373, + "field_id": 60392, + "hidden": true, + "order": 32767 + }, + { + "id": 35374, + "field_id": 60399, + "hidden": false, + "order": 32767 + }, + { + "id": 35375, + "field_id": 60400, + "hidden": true, + "order": 32767 + }, + { + "id": 35376, + "field_id": 60401, + "hidden": true, + "order": 32767 + }, + { + "id": 35377, + "field_id": 60402, + "hidden": true, + "order": 32767 + }, + { + "id": 35378, + "field_id": 60403, + "hidden": true, + "order": 32767 + }, + { + "id": 35379, + "field_id": 60404, + "hidden": true, + "order": 32767 + } + ] + } + ], + "rows": [ + { + "id": 1, + "order": "1.00000000000000000000", + "created_on": "2025-03-04T06:19:05.318350+00:00", + "updated_on": "2025-03-04T13:15:56.135512+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60399": null, + "field_60386": [ + 47 + ], + "field_60387": [ + 1 + ], + "field_60401": null, + "field_60388": "235.00", + "field_60389": "1", + "field_60390": "1", + "field_60391": "1", + "field_60392": 21182, + "field_60402": null, + "field_60403": null, + "field_60400": null, + "field_60404": null + }, + { + "id": 2, + "order": "2.00000000000000000000", + "created_on": "2025-03-04T06:19:05.318394+00:00", + "updated_on": "2025-03-04T13:15:56.135553+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60399": null, + "field_60386": [ + 47 + ], + "field_60387": [ + 8 + ], + "field_60401": null, + "field_60388": "17.00", + "field_60389": "4", + "field_60390": "4", + "field_60391": "4", + "field_60392": 21182, + "field_60402": null, + "field_60403": null, + "field_60400": null, + "field_60404": null + }, + { + "id": 9, + "order": "7.00000000000000000000", + "created_on": "2025-03-04T09:46:39.722518+00:00", + "updated_on": "2025-03-04T13:15:56.135568+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60399": null, + "field_60386": [ + 47 + ], + "field_60387": [ + 3 + ], + "field_60401": null, + "field_60388": "34.00", + "field_60389": "1", + "field_60390": "1", + "field_60391": "1", + "field_60392": 21182, + "field_60402": null, + "field_60403": null, + "field_60400": null, + "field_60404": null + }, + { + "id": 10, + "order": "8.00000000000000000000", + "created_on": "2025-03-04T09:47:02.181125+00:00", + "updated_on": "2025-03-04T13:15:56.135581+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60399": null, + "field_60386": [ + 47 + ], + "field_60387": [ + 30 + ], + "field_60401": null, + "field_60388": "2.34", + "field_60389": "1", + "field_60390": "1", + "field_60391": "1", + "field_60392": 21182, + "field_60402": null, + "field_60403": null, + "field_60400": null, + "field_60404": null + }, + { + "id": 11, + "order": "9.00000000000000000000", + "created_on": "2025-03-04T09:47:14.058267+00:00", + "updated_on": "2025-03-04T12:59:49.532765+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60399": null, + "field_60386": [ + 48 + ], + "field_60387": [ + 86 + ], + "field_60401": null, + "field_60388": "3.21", + "field_60389": "8", + "field_60390": "6", + "field_60391": null, + "field_60392": 21184, + "field_60402": null, + "field_60403": null, + "field_60400": null, + "field_60404": null + }, + { + "id": 12, + "order": "10.00000000000000000000", + "created_on": "2025-03-04T12:04:26.628240+00:00", + "updated_on": "2025-03-04T13:16:26.748315+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60399": null, + "field_60386": [ + 48 + ], + "field_60387": [ + 4 + ], + "field_60401": null, + "field_60388": "1800.00", + "field_60389": "1", + "field_60390": "1", + "field_60391": null, + "field_60392": 21183, + "field_60402": null, + "field_60403": null, + "field_60400": null, + "field_60404": null + }, + { + "id": 13, + "order": "11.00000000000000000000", + "created_on": "2025-03-04T12:04:30.299894+00:00", + "updated_on": "2025-03-04T13:15:28.843486+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60399": null, + "field_60386": [ + 48 + ], + "field_60387": [ + 20 + ], + "field_60401": null, + "field_60388": "999.00", + "field_60389": "1", + "field_60390": "0", + "field_60391": "0", + "field_60392": 21185, + "field_60402": null, + "field_60403": null, + "field_60400": null, + "field_60404": null + }, + { + "id": 14, + "order": "12.00000000000000000000", + "created_on": "2025-03-04T12:04:34.530606+00:00", + "updated_on": "2025-03-04T13:15:56.135593+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60399": null, + "field_60386": [ + 49 + ], + "field_60387": [ + 34 + ], + "field_60401": null, + "field_60388": "7500.00", + "field_60389": "1", + "field_60390": "1", + "field_60391": "1", + "field_60392": 21182, + "field_60402": null, + "field_60403": null, + "field_60400": null, + "field_60404": null + }, + { + "id": 15, + "order": "13.00000000000000000000", + "created_on": "2025-03-04T12:04:44.307524+00:00", + "updated_on": "2025-03-04T13:15:59.071618+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60399": null, + "field_60386": [ + 50 + ], + "field_60387": [ + 54 + ], + "field_60401": null, + "field_60388": "400.00", + "field_60389": "3", + "field_60390": "3", + "field_60391": null, + "field_60392": 21182, + "field_60402": null, + "field_60403": null, + "field_60400": null, + "field_60404": null + }, + { + "id": 16, + "order": "14.00000000000000000000", + "created_on": "2025-03-04T12:33:47.372094+00:00", + "updated_on": "2025-03-04T13:15:59.442018+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60399": null, + "field_60386": [ + 51 + ], + "field_60387": [ + 3 + ], + "field_60401": null, + "field_60388": "1.60", + "field_60389": "1", + "field_60390": "1", + "field_60391": null, + "field_60392": 21182, + "field_60402": null, + "field_60403": null, + "field_60400": null, + "field_60404": null + }, + { + "id": 17, + "order": "15.00000000000000000000", + "created_on": "2025-03-04T12:33:51.633201+00:00", + "updated_on": "2025-03-04T13:15:59.922239+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60399": null, + "field_60386": [ + 51 + ], + "field_60387": [ + 9 + ], + "field_60401": null, + "field_60388": "456.00", + "field_60389": "1", + "field_60390": "1", + "field_60391": null, + "field_60392": 21182, + "field_60402": null, + "field_60403": null, + "field_60400": null, + "field_60404": null + }, + { + "id": 18, + "order": "16.00000000000000000000", + "created_on": "2025-03-04T12:33:56.036765+00:00", + "updated_on": "2025-03-04T13:16:28.868860+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60399": null, + "field_60386": [ + 51 + ], + "field_60387": [ + 25 + ], + "field_60401": null, + "field_60388": "699.00", + "field_60389": "1", + "field_60390": "1", + "field_60391": null, + "field_60392": 21183, + "field_60402": null, + "field_60403": null, + "field_60400": null, + "field_60404": null + }, + { + "id": 19, + "order": "17.00000000000000000000", + "created_on": "2025-03-04T12:34:01.812846+00:00", + "updated_on": "2025-03-04T13:16:32.621627+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60399": null, + "field_60386": [ + 51 + ], + "field_60387": [ + 45 + ], + "field_60401": null, + "field_60388": "132.00", + "field_60389": "10", + "field_60390": "6", + "field_60391": null, + "field_60392": 21184, + "field_60402": null, + "field_60403": null, + "field_60400": null, + "field_60404": null + }, + { + "id": 20, + "order": "18.00000000000000000000", + "created_on": "2025-03-04T13:00:15.742244+00:00", + "updated_on": "2025-03-04T13:15:56.135636+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60399": null, + "field_60386": [ + 52 + ], + "field_60387": [ + 17 + ], + "field_60401": null, + "field_60388": "200.00", + "field_60389": "3", + "field_60390": "3", + "field_60391": "3", + "field_60392": 21182, + "field_60402": null, + "field_60403": null, + "field_60400": null, + "field_60404": null + }, + { + "id": 21, + "order": "19.00000000000000000000", + "created_on": "2025-03-04T13:00:21.727590+00:00", + "updated_on": "2025-03-04T13:15:25.929104+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60399": null, + "field_60386": [ + 53 + ], + "field_60387": [ + 37 + ], + "field_60401": null, + "field_60388": "85.00", + "field_60389": "5", + "field_60390": "0", + "field_60391": "0", + "field_60392": 21185, + "field_60402": null, + "field_60403": null, + "field_60400": null, + "field_60404": null + }, + { + "id": 22, + "order": "20.00000000000000000000", + "created_on": "2025-03-04T13:00:22.761852+00:00", + "updated_on": "2025-03-04T13:16:01.003856+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60399": null, + "field_60386": [ + 53 + ], + "field_60387": [ + 10 + ], + "field_60401": null, + "field_60388": "299.00", + "field_60389": "1", + "field_60390": "1", + "field_60391": null, + "field_60392": 21182, + "field_60402": null, + "field_60403": null, + "field_60400": null, + "field_60404": null + }, + { + "id": 23, + "order": "21.00000000000000000000", + "created_on": "2025-03-04T13:00:23.277972+00:00", + "updated_on": "2025-03-04T13:16:01.343049+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60399": null, + "field_60386": [ + 53 + ], + "field_60387": [ + 24 + ], + "field_60401": null, + "field_60388": "500.00", + "field_60389": "1", + "field_60390": "1", + "field_60391": null, + "field_60392": 21182, + "field_60402": null, + "field_60403": null, + "field_60400": null, + "field_60404": null + }, + { + "id": 24, + "order": "22.00000000000000000000", + "created_on": "2025-03-04T13:00:23.816698+00:00", + "updated_on": "2025-03-04T13:15:56.135670+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60399": null, + "field_60386": [ + 54 + ], + "field_60387": [ + 57 + ], + "field_60401": null, + "field_60388": "180.00", + "field_60389": "9", + "field_60390": "9", + "field_60391": "9", + "field_60392": 21182, + "field_60402": null, + "field_60403": null, + "field_60400": null, + "field_60404": null + }, + { + "id": 25, + "order": "23.00000000000000000000", + "created_on": "2025-03-04T13:00:24.283919+00:00", + "updated_on": "2025-03-04T13:16:26.748396+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60399": null, + "field_60386": [ + 54 + ], + "field_60387": [ + 53 + ], + "field_60401": null, + "field_60388": "400.00", + "field_60389": "1", + "field_60390": "1", + "field_60391": null, + "field_60392": 21183, + "field_60402": null, + "field_60403": null, + "field_60400": null, + "field_60404": null + }, + { + "id": 26, + "order": "24.00000000000000000000", + "created_on": "2025-03-04T13:00:24.773620+00:00", + "updated_on": "2025-03-04T13:16:02.629436+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60399": null, + "field_60386": [ + 55 + ], + "field_60387": [ + 43 + ], + "field_60401": null, + "field_60388": "1.05", + "field_60389": "100", + "field_60390": "100", + "field_60391": null, + "field_60392": 21182, + "field_60402": null, + "field_60403": null, + "field_60400": null, + "field_60404": null + }, + { + "id": 27, + "order": "25.00000000000000000000", + "created_on": "2025-03-04T13:00:25.286353+00:00", + "updated_on": "2025-03-04T13:16:41.961154+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60399": null, + "field_60386": [ + 55 + ], + "field_60387": [ + 44 + ], + "field_60401": null, + "field_60388": "0.89", + "field_60389": "100", + "field_60390": "75", + "field_60391": null, + "field_60392": 21184, + "field_60402": null, + "field_60403": null, + "field_60400": null, + "field_60404": null + }, + { + "id": 28, + "order": "26.00000000000000000000", + "created_on": "2025-03-04T13:00:25.725012+00:00", + "updated_on": "2025-03-04T13:16:03.188536+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60399": null, + "field_60386": [ + 55 + ], + "field_60387": [ + 86 + ], + "field_60401": null, + "field_60388": "0.67", + "field_60389": "100", + "field_60390": "100", + "field_60391": null, + "field_60392": 21182, + "field_60402": null, + "field_60403": null, + "field_60400": null, + "field_60404": null + }, + { + "id": 29, + "order": "27.00000000000000000000", + "created_on": "2025-03-04T13:00:26.257835+00:00", + "updated_on": "2025-03-04T13:16:26.748414+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60399": null, + "field_60386": [ + 55 + ], + "field_60387": [ + 8 + ], + "field_60401": null, + "field_60388": "1.34", + "field_60389": "1000", + "field_60390": "1000", + "field_60391": null, + "field_60392": 21183, + "field_60402": null, + "field_60403": null, + "field_60400": null, + "field_60404": null + }, + { + "id": 30, + "order": "28.00000000000000000000", + "created_on": "2025-03-04T13:00:26.939887+00:00", + "updated_on": "2025-03-04T13:16:03.273188+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60399": null, + "field_60386": [ + 56 + ], + "field_60387": [ + 2 + ], + "field_60401": null, + "field_60388": "245.00", + "field_60389": "3", + "field_60390": "3", + "field_60391": null, + "field_60392": 21182, + "field_60402": null, + "field_60403": null, + "field_60400": null, + "field_60404": null + }, + { + "id": 31, + "order": "29.00000000000000000000", + "created_on": "2025-03-04T13:00:27.286886+00:00", + "updated_on": "2025-03-04T13:15:23.173344+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60399": null, + "field_60386": [ + 56 + ], + "field_60387": [ + 1 + ], + "field_60401": null, + "field_60388": "266.00", + "field_60389": "1", + "field_60390": "0", + "field_60391": "0", + "field_60392": 21185, + "field_60402": null, + "field_60403": null, + "field_60400": null, + "field_60404": null + }, + { + "id": 32, + "order": "30.00000000000000000000", + "created_on": "2025-03-04T13:00:27.764042+00:00", + "updated_on": "2025-03-04T13:16:03.715070+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60399": null, + "field_60386": [ + 57 + ], + "field_60387": [ + 35 + ], + "field_60401": null, + "field_60388": "700.00", + "field_60389": "1", + "field_60390": "1", + "field_60391": null, + "field_60392": 21182, + "field_60402": null, + "field_60403": null, + "field_60400": null, + "field_60404": null + }, + { + "id": 33, + "order": "31.00000000000000000000", + "created_on": "2025-03-04T13:00:52.065396+00:00", + "updated_on": "2025-03-04T13:16:04.228707+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60399": null, + "field_60386": [ + 57 + ], + "field_60387": [ + 5 + ], + "field_60401": null, + "field_60388": "699.00", + "field_60389": "1", + "field_60390": "1", + "field_60391": null, + "field_60392": 21182, + "field_60402": null, + "field_60403": null, + "field_60400": null, + "field_60404": null + }, + { + "id": 34, + "order": "32.00000000000000000000", + "created_on": "2025-03-04T13:00:52.676509+00:00", + "updated_on": "2025-03-04T13:16:44.641285+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60399": null, + "field_60386": [ + 57 + ], + "field_60387": [ + 13 + ], + "field_60401": null, + "field_60388": "1.07", + "field_60389": "200", + "field_60390": "150", + "field_60391": null, + "field_60392": 21184, + "field_60402": null, + "field_60403": null, + "field_60400": null, + "field_60404": null + }, + { + "id": 35, + "order": "33.00000000000000000000", + "created_on": "2025-03-04T13:00:53.597330+00:00", + "updated_on": "2025-03-04T13:16:05.350791+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60399": null, + "field_60386": [ + 58 + ], + "field_60387": [ + 28 + ], + "field_60401": null, + "field_60388": "1.12", + "field_60389": "500", + "field_60390": "500", + "field_60391": null, + "field_60392": 21182, + "field_60402": null, + "field_60403": null, + "field_60400": null, + "field_60404": null + }, + { + "id": 36, + "order": "34.00000000000000000000", + "created_on": "2025-03-04T13:00:54.867545+00:00", + "updated_on": "2025-03-04T13:16:05.732475+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60399": null, + "field_60386": [ + 58 + ], + "field_60387": [ + 6 + ], + "field_60401": null, + "field_60388": "620.00", + "field_60389": "1", + "field_60390": "1", + "field_60391": null, + "field_60392": 21182, + "field_60402": null, + "field_60403": null, + "field_60400": null, + "field_60404": null + }, + { + "id": 37, + "order": "35.00000000000000000000", + "created_on": "2025-03-04T13:00:58.257829+00:00", + "updated_on": "2025-03-04T13:16:26.748426+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60399": null, + "field_60386": [ + 59 + ], + "field_60387": [ + 6 + ], + "field_60401": null, + "field_60388": "600.00", + "field_60389": "1", + "field_60390": "1", + "field_60391": null, + "field_60392": 21183, + "field_60402": null, + "field_60403": null, + "field_60400": null, + "field_60404": null + }, + { + "id": 38, + "order": "36.00000000000000000000", + "created_on": "2025-03-04T13:01:15.163486+00:00", + "updated_on": "2025-03-04T13:16:46.700416+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60399": null, + "field_60386": [ + 60 + ], + "field_60387": [ + 36 + ], + "field_60401": null, + "field_60388": "230.00", + "field_60389": "15", + "field_60390": "10", + "field_60391": null, + "field_60392": 21184, + "field_60402": null, + "field_60403": null, + "field_60400": null, + "field_60404": null + }, + { + "id": 39, + "order": "37.00000000000000000000", + "created_on": "2025-03-04T13:01:21.225248+00:00", + "updated_on": "2025-03-04T13:16:06.154354+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60399": null, + "field_60386": [ + 61 + ], + "field_60387": [ + 41 + ], + "field_60401": null, + "field_60388": "18.00", + "field_60389": "6", + "field_60390": "6", + "field_60391": null, + "field_60392": 21182, + "field_60402": null, + "field_60403": null, + "field_60400": null, + "field_60404": null + }, + { + "id": 40, + "order": "38.00000000000000000000", + "created_on": "2025-03-04T13:01:31.871807+00:00", + "updated_on": "2025-03-04T13:16:26.748437+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60399": null, + "field_60386": [ + 61 + ], + "field_60387": [ + 29 + ], + "field_60401": null, + "field_60388": "10200.00", + "field_60389": "1", + "field_60390": "1", + "field_60391": null, + "field_60392": 21183, + "field_60402": null, + "field_60403": null, + "field_60400": null, + "field_60404": null + }, + { + "id": 41, + "order": "39.00000000000000000000", + "created_on": "2025-03-04T13:01:32.925411+00:00", + "updated_on": "2025-03-04T13:16:06.503505+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60399": null, + "field_60386": [ + 61 + ], + "field_60387": [ + 70 + ], + "field_60401": null, + "field_60388": "7600.00", + "field_60389": "1", + "field_60390": "1", + "field_60391": null, + "field_60392": 21182, + "field_60402": null, + "field_60403": null, + "field_60400": null, + "field_60404": null + }, + { + "id": 42, + "order": "40.00000000000000000000", + "created_on": "2025-03-04T13:01:34.468507+00:00", + "updated_on": "2025-03-04T13:16:06.848976+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60399": null, + "field_60386": [ + 61 + ], + "field_60387": [ + 102 + ], + "field_60401": null, + "field_60388": "3500.00", + "field_60389": "1", + "field_60390": "1", + "field_60391": null, + "field_60392": 21182, + "field_60402": null, + "field_60403": null, + "field_60400": null, + "field_60404": null + }, + { + "id": 43, + "order": "41.00000000000000000000", + "created_on": "2025-03-04T13:01:35.609325+00:00", + "updated_on": "2025-03-04T13:16:49.634184+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60399": null, + "field_60386": [ + 61 + ], + "field_60387": [ + 52 + ], + "field_60401": null, + "field_60388": "1800.00", + "field_60389": "10", + "field_60390": "6", + "field_60391": null, + "field_60392": 21184, + "field_60402": null, + "field_60403": null, + "field_60400": null, + "field_60404": null + }, + { + "id": 44, + "order": "42.00000000000000000000", + "created_on": "2025-03-04T13:01:36.784361+00:00", + "updated_on": "2025-03-04T13:16:07.232590+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60399": null, + "field_60386": [ + 62 + ], + "field_60387": [ + 41 + ], + "field_60401": null, + "field_60388": "38.00", + "field_60389": "10", + "field_60390": "10", + "field_60391": null, + "field_60392": 21182, + "field_60402": null, + "field_60403": null, + "field_60400": null, + "field_60404": null + }, + { + "id": 45, + "order": "43.00000000000000000000", + "created_on": "2025-03-04T13:01:44.696612+00:00", + "updated_on": "2025-03-04T13:16:07.561986+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60399": null, + "field_60386": [ + 62 + ], + "field_60387": [ + 54 + ], + "field_60401": null, + "field_60388": "550.00", + "field_60389": "1", + "field_60390": "1", + "field_60391": null, + "field_60392": 21182, + "field_60402": null, + "field_60403": null, + "field_60400": null, + "field_60404": null + }, + { + "id": 46, + "order": "44.00000000000000000000", + "created_on": "2025-03-04T13:01:45.190749+00:00", + "updated_on": "2025-03-04T13:16:09.688409+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60399": null, + "field_60386": [ + 62 + ], + "field_60387": [ + 17 + ], + "field_60401": null, + "field_60388": "218.00", + "field_60389": "5", + "field_60390": "5", + "field_60391": null, + "field_60392": 21182, + "field_60402": null, + "field_60403": null, + "field_60400": null, + "field_60404": null + }, + { + "id": 47, + "order": "45.00000000000000000000", + "created_on": "2025-03-04T13:01:45.682952+00:00", + "updated_on": "2025-03-04T13:15:19.541122+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60399": null, + "field_60386": [ + 62 + ], + "field_60387": [ + 40 + ], + "field_60401": null, + "field_60388": "399.00", + "field_60389": "1", + "field_60390": "0", + "field_60391": "0", + "field_60392": 21185, + "field_60402": null, + "field_60403": null, + "field_60400": null, + "field_60404": null + }, + { + "id": 48, + "order": "46.00000000000000000000", + "created_on": "2025-03-04T13:01:48.028579+00:00", + "updated_on": "2025-03-04T13:16:10.003199+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60399": null, + "field_60386": [ + 63 + ], + "field_60387": [ + 88 + ], + "field_60401": null, + "field_60388": "400.00", + "field_60389": "1", + "field_60390": "1", + "field_60391": null, + "field_60392": 21182, + "field_60402": null, + "field_60403": null, + "field_60400": null, + "field_60404": null + }, + { + "id": 49, + "order": "47.00000000000000000000", + "created_on": "2025-03-04T13:01:54.850172+00:00", + "updated_on": "2025-03-04T13:16:10.316059+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60399": null, + "field_60386": [ + 63 + ], + "field_60387": [ + 93 + ], + "field_60401": null, + "field_60388": "699.00", + "field_60389": "1", + "field_60390": "1", + "field_60391": null, + "field_60392": 21182, + "field_60402": null, + "field_60403": null, + "field_60400": null, + "field_60404": null + }, + { + "id": 50, + "order": "48.00000000000000000000", + "created_on": "2025-03-04T13:01:56.205528+00:00", + "updated_on": "2025-03-04T13:16:51.399850+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60399": null, + "field_60386": [ + 63 + ], + "field_60387": [ + 22 + ], + "field_60401": null, + "field_60388": "205.00", + "field_60389": "7", + "field_60390": "4", + "field_60391": null, + "field_60392": 21184, + "field_60402": null, + "field_60403": null, + "field_60400": null, + "field_60404": null + }, + { + "id": 51, + "order": "49.00000000000000000000", + "created_on": "2025-03-04T13:01:56.958905+00:00", + "updated_on": "2025-03-04T13:16:10.689075+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60399": null, + "field_60386": [ + 63 + ], + "field_60387": [ + 26 + ], + "field_60401": null, + "field_60388": "109.00", + "field_60389": "1", + "field_60390": "1", + "field_60391": null, + "field_60392": 21182, + "field_60402": null, + "field_60403": null, + "field_60400": null, + "field_60404": null + }, + { + "id": 52, + "order": "50.00000000000000000000", + "created_on": "2025-03-04T13:01:58.048036+00:00", + "updated_on": "2025-03-04T13:16:11.430536+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60399": null, + "field_60386": [ + 63 + ], + "field_60387": [ + 74 + ], + "field_60401": null, + "field_60388": "120.00", + "field_60389": "1", + "field_60390": "1", + "field_60391": null, + "field_60392": 21182, + "field_60402": null, + "field_60403": null, + "field_60400": null, + "field_60404": null + }, + { + "id": 53, + "order": "51.00000000000000000000", + "created_on": "2025-03-04T13:02:00.128564+00:00", + "updated_on": "2025-03-04T13:16:55.847349+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60399": null, + "field_60386": [ + 64 + ], + "field_60387": [ + 37 + ], + "field_60401": null, + "field_60388": "67.00", + "field_60389": "4", + "field_60390": "3", + "field_60391": null, + "field_60392": 21184, + "field_60402": null, + "field_60403": null, + "field_60400": null, + "field_60404": null + }, + { + "id": 54, + "order": "52.00000000000000000000", + "created_on": "2025-03-04T13:02:08.867955+00:00", + "updated_on": "2025-03-04T13:10:35.817410+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60399": null, + "field_60386": [ + 65 + ], + "field_60387": [ + 12 + ], + "field_60401": null, + "field_60388": null, + "field_60389": "9", + "field_60390": null, + "field_60391": null, + "field_60392": null, + "field_60402": null, + "field_60403": null, + "field_60400": null, + "field_60404": null + }, + { + "id": 55, + "order": "53.00000000000000000000", + "created_on": "2025-03-04T13:02:09.402871+00:00", + "updated_on": "2025-03-04T13:10:38.456360+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60399": null, + "field_60386": [ + 65 + ], + "field_60387": [ + 32 + ], + "field_60401": null, + "field_60388": null, + "field_60389": "12", + "field_60390": null, + "field_60391": null, + "field_60392": null, + "field_60402": null, + "field_60403": null, + "field_60400": null, + "field_60404": null + }, + { + "id": 56, + "order": "54.00000000000000000000", + "created_on": "2025-03-04T13:02:10.341873+00:00", + "updated_on": "2025-03-04T13:10:39.302129+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60399": null, + "field_60386": [ + 65 + ], + "field_60387": [ + 98 + ], + "field_60401": null, + "field_60388": null, + "field_60389": "1", + "field_60390": null, + "field_60391": null, + "field_60392": null, + "field_60402": null, + "field_60403": null, + "field_60400": null, + "field_60404": null + }, + { + "id": 57, + "order": "55.00000000000000000000", + "created_on": "2025-03-04T13:02:19.409320+00:00", + "updated_on": "2025-03-04T13:10:40.061160+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60399": null, + "field_60386": [ + 66 + ], + "field_60387": [ + 92 + ], + "field_60401": null, + "field_60388": null, + "field_60389": "1", + "field_60390": null, + "field_60391": null, + "field_60392": null, + "field_60402": null, + "field_60403": null, + "field_60400": null, + "field_60404": null + }, + { + "id": 58, + "order": "56.00000000000000000000", + "created_on": "2025-03-04T13:02:20.158999+00:00", + "updated_on": "2025-03-04T13:10:42.814118+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60399": null, + "field_60386": [ + 66 + ], + "field_60387": [ + 73 + ], + "field_60401": null, + "field_60388": null, + "field_60389": "2", + "field_60390": null, + "field_60391": null, + "field_60392": null, + "field_60402": null, + "field_60403": null, + "field_60400": null, + "field_60404": null + }, + { + "id": 59, + "order": "57.00000000000000000000", + "created_on": "2025-03-04T13:02:28.004403+00:00", + "updated_on": "2025-03-04T13:10:45.546151+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60399": null, + "field_60386": [ + 66 + ], + "field_60387": [ + 61 + ], + "field_60401": null, + "field_60388": null, + "field_60389": "10", + "field_60390": null, + "field_60391": null, + "field_60392": null, + "field_60402": null, + "field_60403": null, + "field_60400": null, + "field_60404": null + }, + { + "id": 60, + "order": "58.00000000000000000000", + "created_on": "2025-03-04T13:02:29.011021+00:00", + "updated_on": "2025-03-04T13:10:48.650816+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60399": null, + "field_60386": [ + 66 + ], + "field_60387": [ + 42 + ], + "field_60401": null, + "field_60388": null, + "field_60389": "80", + "field_60390": null, + "field_60391": null, + "field_60392": null, + "field_60402": null, + "field_60403": null, + "field_60400": null, + "field_60404": null + }, + { + "id": 62, + "order": "60.00000000000000000000", + "created_on": "2025-03-04T13:24:30.048717+00:00", + "updated_on": "2025-03-04T13:26:40.933187+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60399": null, + "field_60386": [ + 67 + ], + "field_60387": [ + 54 + ], + "field_60401": null, + "field_60388": "400.00", + "field_60389": "4", + "field_60390": "3", + "field_60391": null, + "field_60392": 21184, + "field_60402": null, + "field_60403": null, + "field_60400": null, + "field_60404": null + }, + { + "id": 63, + "order": "61.00000000000000000000", + "created_on": "2025-03-04T13:24:36.921052+00:00", + "updated_on": "2025-03-04T13:26:59.014303+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60399": null, + "field_60386": [ + 67 + ], + "field_60387": [ + 76 + ], + "field_60401": null, + "field_60388": "1.02", + "field_60389": "100", + "field_60390": "100", + "field_60391": null, + "field_60392": 21183, + "field_60402": null, + "field_60403": null, + "field_60400": null, + "field_60404": null + }, + { + "id": 64, + "order": "62.00000000000000000000", + "created_on": "2025-03-04T13:24:48.929942+00:00", + "updated_on": "2025-03-04T13:26:48.395853+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60399": null, + "field_60386": [ + 67 + ], + "field_60387": [ + 41 + ], + "field_60401": null, + "field_60388": "200.00", + "field_60389": "1", + "field_60390": "1", + "field_60391": null, + "field_60392": 21182, + "field_60402": null, + "field_60403": null, + "field_60400": null, + "field_60404": null + }, + { + "id": 65, + "order": "63.00000000000000000000", + "created_on": "2025-03-06T14:27:08.626129+00:00", + "updated_on": "2025-03-06T14:56:17.979783+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60399": null, + "field_60386": [ + 68 + ], + "field_60387": [ + 50 + ], + "field_60401": null, + "field_60388": "0.00", + "field_60389": "1", + "field_60390": "0", + "field_60391": "0", + "field_60392": 21185, + "field_60402": null, + "field_60403": null, + "field_60400": null, + "field_60404": null + }, + { + "id": 67, + "order": "65.00000000000000000000", + "created_on": "2025-03-06T14:27:24.781780+00:00", + "updated_on": "2025-03-06T14:56:44.402400+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60399": null, + "field_60386": [ + 68 + ], + "field_60387": [ + 37 + ], + "field_60401": null, + "field_60388": "213.00", + "field_60389": "10", + "field_60390": "10", + "field_60391": "0", + "field_60392": 21182, + "field_60402": null, + "field_60403": null, + "field_60400": null, + "field_60404": null + }, + { + "id": 68, + "order": "66.00000000000000000000", + "created_on": "2025-03-06T14:27:40.631034+00:00", + "updated_on": "2025-03-06T14:57:10.528900+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60399": null, + "field_60386": [ + 68 + ], + "field_60387": [ + 2 + ], + "field_60401": null, + "field_60388": "564.00", + "field_60389": "4", + "field_60390": "4", + "field_60391": "0", + "field_60392": 21183, + "field_60402": null, + "field_60403": null, + "field_60400": null, + "field_60404": null + } + ], + "data_sync": null + } + ] + }, + { + "pages": [ + { + "id": 6722, + "name": "__shared__", + "order": 1, + "path": "__shared__", + "path_params": [], + "query_params": [], + "shared": true, + "elements": [ + { + "id": 107738, + "order": "0.50000000000000000000", + "type": "image", + "parent_element_id": 107667, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "image_source_type": "upload", + "image_file_id": { + "name": "ozYnvncZObH3qO03UgdCIAQ2Y4MHWJ4w_d570910b4de568550dc3e4548e3233094024b77f3ddab2102aaddce3023fd13f.png", + "original_name": "template-header.png" + }, + "image_url": "", + "alt_text": "" + }, + { + "id": 107739, + "order": "0.66666666666666662966", + "type": "column", + "parent_element_id": 107667, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "column_amount": 2, + "column_gap": 20, + "alignment": "center" + }, + { + "id": 107667, + "order": "1.00000000000000000000", + "type": "header", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 10, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "share_type": "all", + "pages": [] + }, + { + "id": 107740, + "order": "1.00000000000000000000", + "type": "text", + "parent_element_id": 107739, + "place_in_container": "0", + "visibility": "logged-in", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "concat('\ud83d\udd11 Logged in as **', get('user.username'), '** (', get('user.role'), ')')", + "format": "markdown" + }, + { + "id": 107741, + "order": "1.00000000000000000000", + "type": "button", + "parent_element_id": 107739, + "place_in_container": "1", + "visibility": "logged-in", + "role_type": "allow_all", + "roles": [], + "styles": { + "button": { + "button_alignment": "right" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'LOGOUT'" + } + ], + "data_sources": [], + "workflow_actions": [ + { + "id": 14035, + "type": "logout", + "order": 1, + "page_id": 6722, + "element_id": 107741, + "event": "click" + } + ], + "visibility": "all", + "role_type": "allow_all", + "roles": [] + }, + { + "id": 6723, + "name": "Login", + "order": 1, + "path": "/login", + "path_params": [], + "query_params": [], + "shared": false, + "elements": [ + { + "id": 107672, + "order": "0.50000000000000000000", + "type": "heading", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Purchase Order Managment'", + "level": 1 + }, + { + "id": 107673, + "order": "1.00000000000000000000", + "type": "auth_form", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "login_button": { + "button_alignment": "center", + "button_horizontal_padding": 48 + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 50, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 50, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 50, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 50, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "color", + "style_background_color": "#b5b5b51a", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "small", + "style_width_child": "normal", + "user_source_id": 677, + "login_button_label": "'Sign in'" + } + ], + "data_sources": [], + "workflow_actions": [ + { + "id": 14021, + "type": "open_page", + "order": 1, + "page_id": 6723, + "element_id": 107673, + "event": "after_login", + "navigation_type": "page", + "navigate_to_page_id": 6724, + "page_parameters": [], + "query_parameters": [], + "navigate_to_url": "", + "target": "self" + } + ], + "visibility": "all", + "role_type": "allow_all", + "roles": [] + }, + { + "id": 6724, + "name": "Homepage", + "order": 2, + "path": "/", + "path_params": [], + "query_params": [], + "shared": false, + "elements": [ + { + "id": 107674, + "order": "1.00000000000000000000", + "type": "heading", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Purchase request overview'", + "level": 1 + }, + { + "id": 107675, + "order": "1.50000000000000000000", + "type": "link", + "parent_element_id": null, + "place_in_container": null, + "visibility": "logged-in", + "role_type": "disallow_all_except", + "roles": [ + "Other" + ], + "styles": { + "button": { + "button_alignment": "right" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "navigation_type": "page", + "navigate_to_page_id": 6725, + "page_parameters": [], + "query_parameters": [], + "navigate_to_url": "", + "target": "self", + "value": "'+ Add a new request'", + "variant": "button" + }, + { + "id": 107676, + "order": "1.66666666666666674068", + "type": "heading", + "parent_element_id": null, + "place_in_container": null, + "visibility": "logged-in", + "role_type": "disallow_all_except", + "roles": [ + "Other" + ], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'My requests'", + "level": 2 + }, + { + "id": 107677, + "order": "1.71428571428571419055", + "type": "table", + "parent_element_id": null, + "place_in_container": null, + "visibility": "logged-in", + "role_type": "disallow_all_except", + "roles": [ + "Other" + ], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "data_source_id": 12252, + "items_per_page": 20, + "button_load_more_label": "", + "schema_property": null, + "property_options": [], + "fields": [ + { + "uid": "04a376ba-7bcb-404f-8b70-315dd2f7f870", + "name": "Request", + "type": "link", + "styles": {}, + "config": { + "navigation_type": "page", + "navigate_to_page_id": 6727, + "page_parameters": [ + { + "name": "request_id", + "value": "get('current_record.id')" + } + ], + "query_parameters": [], + "navigate_to_url": "", + "target": "self", + "link_name": "get('current_record.field_60374')", + "variant": "link" + } + }, + { + "uid": "f50dc56e-acd8-4fe1-98cb-1c95373d44e0", + "name": "Name", + "type": "text", + "styles": {}, + "config": { + "value": "get('current_record.field_60381')" + } + }, + { + "uid": "015e018b-87c9-4cb7-9c58-a1847dc8b7b8", + "name": "Date", + "type": "text", + "styles": {}, + "config": { + "value": "get('current_record.field_60379')" + } + }, + { + "uid": "e931550c-ab0b-4ead-b761-174ce27c2adc", + "name": "Supplier", + "type": "text", + "styles": {}, + "config": { + "value": "concat(get('current_record.field_60394'),' (',get('current_record.field_60375.*.value'),')')" + } + }, + { + "uid": "aefca5d3-fa5d-4277-9157-1aaa1c75c25a", + "name": "Status", + "type": "tags", + "styles": {}, + "config": { + "values": "get('current_record.field_60377.value')", + "colors_is_formula": true, + "colors": "get('current_record.field_60377.color')" + } + }, + { + "uid": "63ce30ff-7c8c-41a4-8de6-b74df8b4035a", + "name": "Art. R/A/D", + "type": "text", + "styles": {}, + "config": { + "value": "concat(get('current_record.field_60396'),'/',get('current_record.field_60397'),'/',get('current_record.field_60398'))" + } + }, + { + "uid": "fd6cfee5-1038-4b4b-a83d-0df247cc7073", + "name": "Total R.", + "type": "text", + "styles": {}, + "config": { + "value": "concat('\u20ac ',get('current_record.field_60405'))" + } + }, + { + "uid": "1266b9c5-08c3-4da5-a32f-9cc74a6da3f7", + "name": "Total D", + "type": "text", + "styles": {}, + "config": { + "value": "concat('\u20ac ',get('current_record.field_60406'))" + } + } + ], + "orientation": { + "tablet": "vertical", + "desktop": "horizontal", + "smartphone": "vertical" + } + }, + { + "id": 107678, + "order": "1.75000000000000000000", + "type": "heading", + "parent_element_id": null, + "place_in_container": null, + "visibility": "logged-in", + "role_type": "disallow_all_except", + "roles": [ + "Purchase department" + ], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 50, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'All open requests'", + "level": 2 + }, + { + "id": 107679, + "order": "2.00000000000000000000", + "type": "table", + "parent_element_id": null, + "place_in_container": null, + "visibility": "logged-in", + "role_type": "disallow_all_except", + "roles": [ + "Purchase department" + ], + "styles": { + "header_button": { + "button_text_color": "primary", + "button_border_color": "transparent", + "button_hover_text_color": "secondary", + "button_hover_border_color": "transparent", + "button_hover_background_color": "transparent" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "data_source_id": 12251, + "items_per_page": 20, + "button_load_more_label": "", + "schema_property": null, + "property_options": [ + { + "schema_property": "field_60374", + "filterable": false, + "sortable": true, + "searchable": true + }, + { + "schema_property": "field_60394", + "filterable": false, + "sortable": true, + "searchable": true + }, + { + "schema_property": "field_60375", + "filterable": false, + "sortable": false, + "searchable": true + }, + { + "schema_property": "field_60377", + "filterable": true, + "sortable": true, + "searchable": false + }, + { + "schema_property": "field_60379", + "filterable": true, + "sortable": true, + "searchable": false + }, + { + "schema_property": "field_60380", + "filterable": false, + "sortable": true, + "searchable": true + }, + { + "schema_property": "field_60376", + "filterable": false, + "sortable": false, + "searchable": true + } + ], + "fields": [ + { + "uid": "9ec9ce53-93d2-46fd-bb4e-de00562c34dc", + "name": "Request", + "type": "link", + "styles": {}, + "config": { + "navigation_type": "page", + "navigate_to_page_id": 6727, + "page_parameters": [ + { + "name": "request_id", + "value": "get('current_record.id')" + } + ], + "query_parameters": [], + "navigate_to_url": "", + "target": "self", + "link_name": "get('current_record.field_60374')", + "variant": "link" + } + }, + { + "uid": "ad8afe8d-4de3-4f22-b3bf-cf2f9f305efd", + "name": "Name", + "type": "text", + "styles": {}, + "config": { + "value": "get('current_record.field_60381')" + } + }, + { + "uid": "9b66872e-11bf-476b-8188-63dd0f59f9d7", + "name": "Date", + "type": "text", + "styles": {}, + "config": { + "value": "get('current_record.field_60379')" + } + }, + { + "uid": "35df1dc7-bc9d-4c13-b469-6ca071e98491", + "name": "Supplier", + "type": "text", + "styles": {}, + "config": { + "value": "concat(get('current_record.field_60394'),' (',get('current_record.field_60375.*.value'),')')" + } + }, + { + "uid": "4c9d08a5-dc84-4386-9848-bdef25872bef", + "name": "Status", + "type": "tags", + "styles": {}, + "config": { + "values": "get('current_record.field_60377.value')", + "colors_is_formula": true, + "colors": "get('current_record.field_60377.color')" + } + }, + { + "uid": "25675570-6cc8-4706-af47-3409c375cb4c", + "name": "Art. R/A/D", + "type": "text", + "styles": {}, + "config": { + "value": "concat(get('current_record.field_60396'),' / ',get('current_record.field_60397'),' / ',get('current_record.field_60398'))" + } + }, + { + "uid": "a81c98ba-58b1-4e2c-a905-a2e53c984154", + "name": "Total R.", + "type": "text", + "styles": {}, + "config": { + "value": "concat('\u20ac ',get('current_record.field_60405'))" + } + }, + { + "uid": "def9e150-4235-4f60-854d-3505e559ef9f", + "name": "Total A.", + "type": "text", + "styles": {}, + "config": { + "value": "concat('\u20ac ',get('current_record.field_60406'))" + } + }, + { + "uid": "aa4b8386-0a36-43eb-a92e-f46a9e6bbb98", + "name": "Initi\u00e9 par", + "type": "text", + "styles": {}, + "config": { + "value": "get('current_record.field_60412.*.value')" + } + } + ], + "orientation": { + "tablet": "vertical", + "desktop": "horizontal", + "smartphone": "vertical" + } + } + ], + "data_sources": [ + { + "id": 12251, + "name": "All open requests", + "order": "1.00000000000000000000", + "service": { + "id": 15132, + "integration_id": 904, + "type": "local_baserow_list_rows", + "table_id": 5754, + "view_id": 26714, + "sortings": [], + "search_query": "", + "filter_type": "AND", + "filters": [] + } + }, + { + "id": 12252, + "name": "My requests", + "order": "2.00000000000000000000", + "service": { + "id": 15133, + "integration_id": 904, + "type": "local_baserow_list_rows", + "table_id": 5754, + "view_id": 26713, + "sortings": [ + { + "field_id": 60379, + "order_by": "DESC" + } + ], + "search_query": "", + "filter_type": "AND", + "filters": [ + { + "field_id": 60412, + "type": "link_row_has", + "value": "get('user.id')", + "value_is_formula": true + } + ] + } + } + ], + "workflow_actions": [], + "visibility": "logged-in", + "role_type": "allow_all", + "roles": [] + }, + { + "id": 6725, + "name": "Add request", + "order": 3, + "path": "/add-request", + "path_params": [], + "query_params": [], + "shared": false, + "elements": [ + { + "id": 108343, + "order": "0.50000000000000000000", + "type": "link", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "navigation_type": "page", + "navigate_to_page_id": 6724, + "page_parameters": [], + "query_parameters": [], + "navigate_to_url": "", + "target": "self", + "value": "'<- Back to overview'", + "variant": "link" + }, + { + "id": 107681, + "order": "1.00000000000000000000", + "type": "input_text", + "parent_element_id": 107680, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "label": "'SHORT NAME OF THE REQUEST'", + "required": true, + "validation_type": "any", + "placeholder": "", + "default_value": "", + "is_multiline": false, + "rows": 3, + "input_type": "text" + }, + { + "id": 107685, + "order": "1.00000000000000000000", + "type": "heading", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Add a new request'", + "level": 1 + }, + { + "id": 107686, + "order": "1.50000000000000000000", + "type": "heading", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'General information'", + "level": 2 + }, + { + "id": 107680, + "order": "2.00000000000000000000", + "type": "form_container", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "button": { + "button_alignment": "center", + "button_horizontal_padding": 48 + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "color", + "style_background_color": "ev6JA", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "small", + "style_width_child": "normal", + "submit_button_label": "'Register new request'", + "reset_initial_values_post_submission": false + }, + { + "id": 107682, + "order": "2.00000000000000000000", + "type": "datetime_picker", + "parent_element_id": 107680, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "label": "'DATE OF THE REQUEST'", + "required": true, + "default_value": "", + "date_format": "ISO", + "include_time": false, + "time_format": "24" + }, + { + "id": 107683, + "order": "3.00000000000000000000", + "type": "record_selector", + "parent_element_id": 107680, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "data_source_id": 12253, + "items_per_page": 20, + "button_load_more_label": "", + "schema_property": null, + "property_options": [ + { + "schema_property": "field_60358", + "filterable": false, + "sortable": false, + "searchable": true + }, + { + "schema_property": "field_60359", + "filterable": false, + "sortable": false, + "searchable": true + } + ], + "required": true, + "label": "'SELECT SUPPLIER'", + "default_value": "", + "placeholder": "", + "multiple": false, + "option_name_suffix": "concat(get('current_record.field_60358'),' - ',get('current_record.field_60359'))" + }, + { + "id": 107684, + "order": "5.00000000000000000000", + "type": "input_text", + "parent_element_id": 107680, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "label": "'COMMENTS'", + "required": false, + "validation_type": "any", + "placeholder": "", + "default_value": "", + "is_multiline": false, + "rows": 3, + "input_type": "text" + } + ], + "data_sources": [ + { + "id": 12253, + "name": "All global suppliers", + "order": "1.00000000000000000000", + "service": { + "id": 15134, + "integration_id": 904, + "type": "local_baserow_list_rows", + "table_id": 5751, + "view_id": 26709, + "sortings": [], + "search_query": "", + "filter_type": "AND", + "filters": [] + } + } + ], + "workflow_actions": [ + { + "id": 14037, + "type": "create_row", + "order": 3, + "page_id": 6725, + "element_id": 107680, + "event": "submit", + "service": { + "id": 15145, + "integration_id": 904, + "type": "local_baserow_upsert_row", + "table_id": 5754, + "row_id": "", + "field_mappings": [ + { + "field_id": 60375, + "value": "get('form_data.107683')", + "enabled": true + }, + { + "field_id": 60376, + "value": "get('form_data.107684')", + "enabled": true + }, + { + "field_id": 60377, + "value": "'Request'", + "enabled": true + }, + { + "field_id": 60378, + "value": "", + "enabled": false + }, + { + "field_id": 60379, + "value": "get('form_data.107682')", + "enabled": true + }, + { + "field_id": 60381, + "value": "get('form_data.107681')", + "enabled": true + }, + { + "field_id": 60382, + "value": "", + "enabled": false + }, + { + "field_id": 60383, + "value": "", + "enabled": false + }, + { + "field_id": 60384, + "value": "", + "enabled": false + }, + { + "field_id": 60412, + "value": "get('user.id')", + "enabled": true + } + ] + } + }, + { + "id": 14039, + "type": "open_page", + "order": 4, + "page_id": 6725, + "element_id": 107680, + "event": "submit", + "navigation_type": "page", + "navigate_to_page_id": 6726, + "page_parameters": [ + { + "name": "request_id", + "value": "get('previous_action.14037.id')" + } + ], + "query_parameters": [], + "navigate_to_url": "", + "target": "self" + } + ], + "visibility": "logged-in", + "role_type": "disallow_all_except", + "roles": [ + "Other" + ] + }, + { + "id": 6726, + "name": "Add request details", + "order": 4, + "path": "/add-request/:request_id", + "path_params": [ + { + "name": "request_id", + "type": "numeric" + } + ], + "query_params": [], + "shared": false, + "elements": [ + { + "id": 107690, + "order": "0.50000000000000000000", + "type": "text", + "parent_element_id": 107688, + "place_in_container": "1", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_color": "primary", + "body_font_weight": "semi-bold" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'SHORT NAME'", + "format": "plain" + }, + { + "id": 107691, + "order": "1.00000000000000000000", + "type": "heading", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Ajouter une nouvelle demande'", + "level": 1 + }, + { + "id": 107692, + "order": "1.00000000000000000000", + "type": "text", + "parent_element_id": 107688, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_color": "primary", + "body_font_weight": "semi-bold" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'ID'", + "format": "plain" + }, + { + "id": 107693, + "order": "1.00000000000000000000", + "type": "text", + "parent_element_id": 107688, + "place_in_container": "1", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "get('data_source.12254.field_60381')", + "format": "plain" + }, + { + "id": 107694, + "order": "1.00000000000000000000", + "type": "text", + "parent_element_id": 107688, + "place_in_container": "3", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_color": "primary", + "body_font_weight": "semi-bold" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'SUPPLIER'", + "format": "plain" + }, + { + "id": 107695, + "order": "1.00000000000000000000", + "type": "heading", + "parent_element_id": 107689, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Add an article'", + "level": 3 + }, + { + "id": 107696, + "order": "1.00000000000000000000", + "type": "heading", + "parent_element_id": 107689, + "place_in_container": "1", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Overview'", + "level": 3 + }, + { + "id": 107697, + "order": "1.00000000000000000000", + "type": "button", + "parent_element_id": 107687, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "button": { + "button_width": "full", + "button_alignment": "center", + "button_text_color": "primary", + "button_font_weight": "bold", + "button_border_color": "primary", + "button_hover_border_color": "primary", + "button_hover_background_color": "primary" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'\ud83d\udce8 SEND REQUEST'" + }, + { + "id": 107698, + "order": "1.00000000000000000000", + "type": "button", + "parent_element_id": 107687, + "place_in_container": "1", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "button": { + "button_width": "full", + "button_alignment": "center", + "button_text_color": "primary", + "button_font_weight": "bold", + "button_border_color": "primary", + "button_hover_border_color": "primary", + "button_hover_background_color": "primary" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'\u274c CANCEL'" + }, + { + "id": 107709, + "order": "1.00000000000000000000", + "type": "record_selector", + "parent_element_id": 107708, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "data_source_id": 12256, + "items_per_page": 20, + "button_load_more_label": "", + "schema_property": null, + "property_options": [ + { + "schema_property": "field_60366", + "filterable": false, + "sortable": false, + "searchable": true + }, + { + "schema_property": "field_60367", + "filterable": false, + "sortable": false, + "searchable": true + }, + { + "schema_property": "field_60368", + "filterable": false, + "sortable": false, + "searchable": true + }, + { + "schema_property": "field_60369", + "filterable": false, + "sortable": false, + "searchable": true + }, + { + "schema_property": "field_60370", + "filterable": false, + "sortable": false, + "searchable": true + }, + { + "schema_property": "field_60393", + "filterable": false, + "sortable": false, + "searchable": true + } + ], + "required": true, + "label": "'PART'", + "default_value": "", + "placeholder": "", + "multiple": false, + "option_name_suffix": "get('current_record.field_60367')" + }, + { + "id": 107687, + "order": "1.33333333333333325932", + "type": "column", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 2, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 2, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "column_amount": 6, + "column_gap": 20, + "alignment": "center" + }, + { + "id": 107699, + "order": "1.50000000000000000000", + "type": "heading", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'General information'", + "level": 2 + }, + { + "id": 107700, + "order": "1.50000000000000000000", + "type": "text", + "parent_element_id": 107688, + "place_in_container": "2", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_color": "primary", + "body_font_weight": "semi-bold" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'DATE'", + "format": "plain" + }, + { + "id": 107701, + "order": "1.50000000000000000000", + "type": "text", + "parent_element_id": 107688, + "place_in_container": "4", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_color": "primary", + "body_font_weight": "semi-bold" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'COMMENTS'", + "format": "plain" + }, + { + "id": 107688, + "order": "1.66666666666666674068", + "type": "column", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 1, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 1, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "column_amount": 5, + "column_gap": 20, + "alignment": "top" + }, + { + "id": 107702, + "order": "2.00000000000000000000", + "type": "text", + "parent_element_id": 107688, + "place_in_container": "3", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "concat(get('data_source.12254.field_60394'),' (',get('data_source.12254.field_60375.*.value'),')')", + "format": "plain" + }, + { + "id": 107703, + "order": "2.00000000000000000000", + "type": "text", + "parent_element_id": 107688, + "place_in_container": "2", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "get('data_source.12254.field_60379')", + "format": "plain" + }, + { + "id": 107704, + "order": "2.00000000000000000000", + "type": "text", + "parent_element_id": 107688, + "place_in_container": "4", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "get('data_source.12254.field_60376')", + "format": "plain" + }, + { + "id": 107705, + "order": "2.00000000000000000000", + "type": "table", + "parent_element_id": 107689, + "place_in_container": "1", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "data_source_id": 12255, + "items_per_page": 20, + "button_load_more_label": "", + "schema_property": null, + "property_options": [], + "fields": [ + { + "uid": "f94c2990-0bd3-42a3-9103-9a3a71cb1ab5", + "name": "PN", + "type": "text", + "styles": {}, + "config": { + "value": "get('current_record.field_60387.*.value')" + } + }, + { + "uid": "1dc132fa-4ac9-4d68-9389-91657d1678af", + "name": "Name", + "type": "text", + "styles": {}, + "config": { + "value": "get('current_record.field_60401')" + } + }, + { + "uid": "bdc5c9ec-ed3d-415a-95fd-42600dad0e8d", + "name": "#", + "type": "text", + "styles": {}, + "config": { + "value": "get('current_record.field_60389')" + } + }, + { + "uid": "8056b449-f2fc-48d9-a755-d395b048386b", + "name": "-", + "type": "button", + "styles": { + "cell": { + "button_text_color": "#000000ff", + "button_border_color": "transparent", + "button_hover_border_color": "error", + "button_hover_background_color": "transparent" + } + }, + "config": { + "label": "'\u274c'" + } + } + ], + "orientation": { + "tablet": "vertical", + "desktop": "horizontal", + "smartphone": "vertical" + } + }, + { + "id": 107708, + "order": "2.00000000000000000000", + "type": "form_container", + "parent_element_id": 107689, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "button": { + "button_alignment": "center", + "button_horizontal_padding": 48 + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 20, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 20, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 50, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 50, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "color", + "style_background_color": "ev6JA", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "submit_button_label": "'Add article'", + "reset_initial_values_post_submission": true + }, + { + "id": 107710, + "order": "2.00000000000000000000", + "type": "input_text", + "parent_element_id": 107708, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "input": {} + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "label": "'Quantity'", + "required": true, + "validation_type": "integer", + "placeholder": "", + "default_value": "'1'", + "is_multiline": false, + "rows": 3, + "input_type": "text" + }, + { + "id": 107706, + "order": "3.00000000000000000000", + "type": "text", + "parent_element_id": 107688, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "get('data_source.12254.field_60374')", + "format": "plain" + }, + { + "id": 107707, + "order": "3.00000000000000000000", + "type": "heading", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 50, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "concat('Articles', '\n', '')", + "level": 2 + }, + { + "id": 107689, + "order": "4.00000000000000000000", + "type": "column", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "column_amount": 2, + "column_gap": 50, + "alignment": "top" + } + ], + "data_sources": [ + { + "id": 12254, + "name": "Get request", + "order": "1.00000000000000000000", + "service": { + "id": 15135, + "integration_id": 904, + "type": "local_baserow_get_row", + "table_id": 5754, + "view_id": 26713, + "search_query": "", + "filter_type": "AND", + "filters": [], + "row_id": "get('page_parameter.request_id')" + } + }, + { + "id": 12255, + "name": "Get request details", + "order": "2.00000000000000000000", + "service": { + "id": 15136, + "integration_id": 904, + "type": "local_baserow_list_rows", + "table_id": 5755, + "view_id": 26715, + "sortings": [], + "search_query": "", + "filter_type": "AND", + "filters": [ + { + "field_id": 60386, + "type": "link_row_has", + "value": "get('page_parameter.request_id')", + "value_is_formula": true + } + ] + } + }, + { + "id": 12256, + "name": "Get all parts", + "order": "3.00000000000000000000", + "service": { + "id": 15137, + "integration_id": 904, + "type": "local_baserow_list_rows", + "table_id": 5752, + "view_id": 26711, + "sortings": [], + "search_query": "", + "filter_type": "AND", + "filters": [] + } + } + ], + "workflow_actions": [ + { + "id": 14024, + "type": "create_row", + "order": 1, + "page_id": 6726, + "element_id": 107708, + "event": "submit", + "service": { + "id": 15141, + "integration_id": 904, + "type": "local_baserow_upsert_row", + "table_id": 5755, + "row_id": "", + "field_mappings": [ + { + "field_id": 60386, + "value": "get('data_source.12254.id')", + "enabled": true + }, + { + "field_id": 60387, + "value": "get('form_data.107709')", + "enabled": true + }, + { + "field_id": 60389, + "value": "get('form_data.107710')", + "enabled": true + }, + { + "field_id": 60388, + "value": "", + "enabled": false + }, + { + "field_id": 60390, + "value": "", + "enabled": false + }, + { + "field_id": 60391, + "value": "", + "enabled": false + }, + { + "field_id": 60392, + "value": "", + "enabled": false + } + ] + } + }, + { + "id": 14025, + "type": "delete_row", + "order": 1, + "page_id": 6726, + "element_id": 107705, + "event": "8056b449-f2fc-48d9-a755-d395b048386b_click", + "service": { + "id": 15142, + "integration_id": 904, + "type": "local_baserow_delete_row", + "table_id": 5755, + "row_id": "get('current_record.id')" + } + }, + { + "id": 14026, + "type": "delete_row", + "order": 1, + "page_id": 6726, + "element_id": 107698, + "event": "click", + "service": { + "id": 15143, + "integration_id": 904, + "type": "local_baserow_delete_row", + "table_id": 5754, + "row_id": "get('data_source.12254.id')" + } + }, + { + "id": 14027, + "type": "open_page", + "order": 1, + "page_id": 6726, + "element_id": 107697, + "event": "click", + "navigation_type": "page", + "navigate_to_page_id": 6724, + "page_parameters": [], + "query_parameters": [], + "navigate_to_url": "", + "target": "self" + }, + { + "id": 14028, + "type": "refresh_data_source", + "order": 2, + "page_id": 6726, + "element_id": 107708, + "event": "submit", + "data_source_id": 12255 + }, + { + "id": 14029, + "type": "refresh_data_source", + "order": 2, + "page_id": 6726, + "element_id": 107705, + "event": "8056b449-f2fc-48d9-a755-d395b048386b_click", + "data_source_id": 12255 + }, + { + "id": 14030, + "type": "open_page", + "order": 2, + "page_id": 6726, + "element_id": 107698, + "event": "click", + "navigation_type": "page", + "navigate_to_page_id": 6724, + "page_parameters": [], + "query_parameters": [], + "navigate_to_url": "", + "target": "self" + } + ], + "visibility": "logged-in", + "role_type": "disallow_all_except", + "roles": [ + "Other" + ] + }, + { + "id": 6727, + "name": "Request details", + "order": 6, + "path": "/request-details/:request_id", + "path_params": [ + { + "name": "request_id", + "type": "numeric" + } + ], + "query_params": [], + "shared": false, + "elements": [ + { + "id": 107714, + "order": "0.50000000000000000000", + "type": "text", + "parent_element_id": 107712, + "place_in_container": "1", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_color": "primary", + "body_font_weight": "semi-bold" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'SHORT NAME'", + "format": "plain" + }, + { + "id": 107715, + "order": "0.50000000000000000000", + "type": "text", + "parent_element_id": 107713, + "place_in_container": "1", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_color": "primary", + "body_font_weight": "semi-bold" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'QUOTE DATE'", + "format": "plain" + }, + { + "id": 108342, + "order": "0.50000000000000000000", + "type": "link", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "navigation_type": "page", + "navigate_to_page_id": 6724, + "page_parameters": [], + "query_parameters": [], + "navigate_to_url": "", + "target": "self", + "value": "'<- Back to overview'", + "variant": "link" + }, + { + "id": 107716, + "order": "1.00000000000000000000", + "type": "heading", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "concat('Request details ', get('data_source.12257.field_60374'), ' (', get('data_source.12257.field_60394'), ')')", + "level": 1 + }, + { + "id": 107717, + "order": "1.00000000000000000000", + "type": "text", + "parent_element_id": 107712, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_color": "primary", + "body_font_weight": "semi-bold" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'ID'", + "format": "plain" + }, + { + "id": 107718, + "order": "1.00000000000000000000", + "type": "text", + "parent_element_id": 107712, + "place_in_container": "1", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "get('data_source.12257.field_60381')", + "format": "plain" + }, + { + "id": 107719, + "order": "1.00000000000000000000", + "type": "text", + "parent_element_id": 107712, + "place_in_container": "2", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_color": "primary", + "body_font_weight": "semi-bold" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'SUPPLIER'", + "format": "plain" + }, + { + "id": 107720, + "order": "1.00000000000000000000", + "type": "text", + "parent_element_id": 107712, + "place_in_container": "3", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_color": "primary", + "body_font_weight": "semi-bold" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'COMMENTS'", + "format": "plain" + }, + { + "id": 107721, + "order": "1.00000000000000000000", + "type": "text", + "parent_element_id": 107712, + "place_in_container": "4", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_color": "primary", + "body_font_weight": "semi-bold" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'INITIATED BY'", + "format": "plain" + }, + { + "id": 107744, + "order": "1.00000000000000000000", + "type": "button", + "parent_element_id": 107742, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "button": { + "button_width": "full", + "button_text_color": "NGqct", + "button_border_color": "NGqct", + "button_background_color": "#f5f5f5", + "button_hover_text_color": "NGqct", + "button_hover_border_color": "NGqct", + "button_hover_background_color": "#f5f5f5" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#683838", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'REQUEST'" + }, + { + "id": 107745, + "order": "1.00000000000000000000", + "type": "button", + "parent_element_id": 107742, + "place_in_container": "1", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "button": { + "button_width": "full", + "button_text_color": "NGqct", + "button_border_color": "NGqct", + "button_background_color": "#f7e1f2", + "button_hover_text_color": "NGqct", + "button_hover_border_color": "NGqct", + "button_hover_background_color": "#f7e1f2" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#683838", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'QUOTE'" + }, + { + "id": 107746, + "order": "1.00000000000000000000", + "type": "button", + "parent_element_id": 107742, + "place_in_container": "2", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "button": { + "button_width": "full", + "button_text_color": "NGqct", + "button_border_color": "NGqct", + "button_background_color": "#f5e6dc", + "button_hover_text_color": "NGqct", + "button_hover_border_color": "NGqct", + "button_hover_background_color": "#f5e6dc" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#683838", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'ORDER'" + }, + { + "id": 107747, + "order": "1.00000000000000000000", + "type": "button", + "parent_element_id": 107742, + "place_in_container": "3", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "button": { + "button_width": "full", + "button_text_color": "NGqct", + "button_border_color": "NGqct", + "button_background_color": "#fffbf0", + "button_hover_text_color": "NGqct", + "button_hover_border_color": "NGqct", + "button_hover_background_color": "#fffbf0" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#683838", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'IN PROGRESS'" + }, + { + "id": 107748, + "order": "1.00000000000000000000", + "type": "button", + "parent_element_id": 107742, + "place_in_container": "4", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "button": { + "button_width": "full", + "button_text_color": "NGqct", + "button_border_color": "NGqct", + "button_background_color": "#cff5fa", + "button_hover_text_color": "NGqct", + "button_hover_border_color": "NGqct", + "button_hover_background_color": "#cff5fa" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#683838", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'IN DELIVERY'" + }, + { + "id": 107749, + "order": "1.00000000000000000000", + "type": "button", + "parent_element_id": 107742, + "place_in_container": "5", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "button": { + "button_width": "full", + "button_text_color": "NGqct", + "button_border_color": "NGqct", + "button_background_color": "#ecfcf1", + "button_hover_text_color": "NGqct", + "button_hover_border_color": "NGqct", + "button_hover_background_color": "#ecfcf1" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#683838", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'CLOSED'" + }, + { + "id": 107724, + "order": "1.33333333333333325932", + "type": "text", + "parent_element_id": 107713, + "place_in_container": "2", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_color": "primary", + "body_font_weight": "semi-bold" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'ORDER DATE'", + "format": "plain" + }, + { + "id": 107725, + "order": "1.33333333333333325932", + "type": "text", + "parent_element_id": 107713, + "place_in_container": "3", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_color": "primary", + "body_font_weight": "semi-bold" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'DELIVERY DATE'", + "format": "plain" + }, + { + "id": 107726, + "order": "1.50000000000000000000", + "type": "heading", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'General information'", + "level": 2 + }, + { + "id": 107712, + "order": "1.66666666666666674068", + "type": "column", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 1, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "column_amount": 5, + "column_gap": 20, + "alignment": "top" + }, + { + "id": 107713, + "order": "2.00000000000000000000", + "type": "column", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 1, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "column_amount": 5, + "column_gap": 20, + "alignment": "top" + }, + { + "id": 107727, + "order": "2.00000000000000000000", + "type": "text", + "parent_element_id": 107712, + "place_in_container": "2", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "concat(get('data_source.12257.field_60394'),' (',get('data_source.12257.field_60375.*.value'),')')", + "format": "plain" + }, + { + "id": 107728, + "order": "2.00000000000000000000", + "type": "text", + "parent_element_id": 107712, + "place_in_container": "3", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "get('data_source.12257.field_60376')", + "format": "plain" + }, + { + "id": 107729, + "order": "2.00000000000000000000", + "type": "text", + "parent_element_id": 107713, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_color": "primary", + "body_font_weight": "semi-bold" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'REQUEST DATE'", + "format": "plain" + }, + { + "id": 107730, + "order": "2.00000000000000000000", + "type": "text", + "parent_element_id": 107713, + "place_in_container": "1", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "get('data_source.12257.field_60382')", + "format": "plain" + }, + { + "id": 107750, + "order": "2.33333333333333348136", + "type": "heading", + "parent_element_id": null, + "place_in_container": null, + "visibility": "logged-in", + "role_type": "disallow_all_except", + "roles": [ + "Purchase department" + ], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 50, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "concat('Current status: ', get('data_source.12257.field_60377.value'))", + "level": 2 + }, + { + "id": 107742, + "order": "2.50000000000000000000", + "type": "column", + "parent_element_id": null, + "place_in_container": null, + "visibility": "logged-in", + "role_type": "disallow_all_except", + "roles": [ + "Purchase department" + ], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "column_amount": 6, + "column_gap": 20, + "alignment": "top" + }, + { + "id": 107731, + "order": "3.00000000000000000000", + "type": "text", + "parent_element_id": 107712, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "get('data_source.12257.field_60374')", + "format": "plain" + }, + { + "id": 107732, + "order": "3.00000000000000000000", + "type": "heading", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 50, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Articles'", + "level": 2 + }, + { + "id": 107733, + "order": "3.00000000000000000000", + "type": "text", + "parent_element_id": 107712, + "place_in_container": "4", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "get('data_source.12257.field_60412.*.value')", + "format": "plain" + }, + { + "id": 107734, + "order": "3.00000000000000000000", + "type": "text", + "parent_element_id": 107713, + "place_in_container": "2", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "get('data_source.12257.field_60383')", + "format": "plain" + }, + { + "id": 107735, + "order": "3.00000000000000000000", + "type": "text", + "parent_element_id": 107713, + "place_in_container": "3", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "get('data_source.12257.field_60384')", + "format": "plain" + }, + { + "id": 107736, + "order": "4.00000000000000000000", + "type": "text", + "parent_element_id": 107713, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "get('data_source.12257.field_60379')", + "format": "plain" + }, + { + "id": 107737, + "order": "4.00000000000000000000", + "type": "table", + "parent_element_id": null, + "place_in_container": null, + "visibility": "logged-in", + "role_type": "disallow_all_except", + "roles": [ + "Other" + ], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "data_source_id": 12258, + "items_per_page": 20, + "button_load_more_label": "", + "schema_property": null, + "property_options": [], + "fields": [ + { + "uid": "1862ad4e-8572-4e30-b892-0cafeaffd1dd", + "name": "Part", + "type": "text", + "styles": {}, + "config": { + "value": "get('current_record.field_60387.*.value')" + } + }, + { + "uid": "f8c427cd-c04e-453c-81b4-5d7f9811cb09", + "name": "Part name", + "type": "text", + "styles": {}, + "config": { + "value": "get('current_record.field_60401')" + } + }, + { + "uid": "fa2b4c83-592f-4ef1-9aba-92f4dfeeea1a", + "name": "Unit price", + "type": "text", + "styles": {}, + "config": { + "value": "concat('\u20ac ',get('current_record.field_60388'))" + } + }, + { + "uid": "cde487a9-7e2e-4381-b6ef-e31c2b114464", + "name": "Q. R.", + "type": "text", + "styles": {}, + "config": { + "value": "get('current_record.field_60389')" + } + }, + { + "uid": "096b1b16-aa99-47da-8a38-02c8b74ef11f", + "name": "Q. A.", + "type": "text", + "styles": {}, + "config": { + "value": "get('current_record.field_60390')" + } + }, + { + "uid": "9bc7e6ef-7d88-4a84-8ffc-6869a4762aa2", + "name": "Q. D.", + "type": "text", + "styles": {}, + "config": { + "value": "get('current_record.field_60391')" + } + }, + { + "uid": "89984dca-cd6a-4133-af35-9e911cbec05f", + "name": "Total R.", + "type": "text", + "styles": {}, + "config": { + "value": "concat('\u20ac ',get('current_record.field_60402'))" + } + }, + { + "uid": "9e5f9ceb-5486-4931-a46e-f077f9acbb17", + "name": "Total A.", + "type": "text", + "styles": {}, + "config": { + "value": "concat('\u20ac ',get('current_record.field_60403'))" + } + }, + { + "uid": "31b5f4f4-fc73-45a2-98cc-8120607a9284", + "name": "Status", + "type": "tags", + "styles": {}, + "config": { + "values": "get('current_record.field_60392.value')", + "colors_is_formula": true, + "colors": "get('current_record.field_60392.color')" + } + } + ], + "orientation": { + "tablet": "vertical", + "desktop": "horizontal", + "smartphone": "vertical" + } + }, + { + "id": 107901, + "order": "5.00000000000000000000", + "type": "table", + "parent_element_id": null, + "place_in_container": null, + "visibility": "logged-in", + "role_type": "disallow_all_except", + "roles": [ + "Purchase department" + ], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "data_source_id": 12258, + "items_per_page": 20, + "button_load_more_label": "", + "schema_property": null, + "property_options": [], + "fields": [ + { + "uid": "b66d33f4-7a01-42e1-ba8b-22c38c593b9a", + "name": "Part", + "type": "link", + "styles": {}, + "config": { + "navigation_type": "page", + "navigate_to_page_id": 6728, + "page_parameters": [ + { + "name": "request_id", + "value": "get('current_record.field_60386.0.id')" + }, + { + "name": "request_details_id", + "value": "get('current_record.id')" + } + ], + "query_parameters": [], + "navigate_to_url": "", + "target": "self", + "link_name": "get('current_record.field_60387.0.value')", + "variant": "link" + } + }, + { + "uid": "f8c427cd-c04e-453c-81b4-5d7f9811cb09", + "name": "Part name", + "type": "text", + "styles": {}, + "config": { + "value": "get('current_record.field_60401')" + } + }, + { + "uid": "fa2b4c83-592f-4ef1-9aba-92f4dfeeea1a", + "name": "Unit price", + "type": "text", + "styles": {}, + "config": { + "value": "concat('\u20ac ',get('current_record.field_60388'))" + } + }, + { + "uid": "cde487a9-7e2e-4381-b6ef-e31c2b114464", + "name": "Q. R.", + "type": "text", + "styles": {}, + "config": { + "value": "get('current_record.field_60389')" + } + }, + { + "uid": "096b1b16-aa99-47da-8a38-02c8b74ef11f", + "name": "Q. A.", + "type": "text", + "styles": {}, + "config": { + "value": "get('current_record.field_60390')" + } + }, + { + "uid": "9bc7e6ef-7d88-4a84-8ffc-6869a4762aa2", + "name": "Q. D.", + "type": "text", + "styles": {}, + "config": { + "value": "get('current_record.field_60391')" + } + }, + { + "uid": "89984dca-cd6a-4133-af35-9e911cbec05f", + "name": "Total R.", + "type": "text", + "styles": {}, + "config": { + "value": "concat('\u20ac ',get('current_record.field_60402'))" + } + }, + { + "uid": "9e5f9ceb-5486-4931-a46e-f077f9acbb17", + "name": "Total A.", + "type": "text", + "styles": {}, + "config": { + "value": "concat('\u20ac ',get('current_record.field_60403'))" + } + }, + { + "uid": "31b5f4f4-fc73-45a2-98cc-8120607a9284", + "name": "Status", + "type": "tags", + "styles": {}, + "config": { + "values": "get('current_record.field_60392.value')", + "colors_is_formula": true, + "colors": "get('current_record.field_60392.color')" + } + } + ], + "orientation": { + "tablet": "vertical", + "desktop": "horizontal", + "smartphone": "vertical" + } + } + ], + "data_sources": [ + { + "id": 12257, + "name": "Get request", + "order": "1.00000000000000000000", + "service": { + "id": 15138, + "integration_id": 904, + "type": "local_baserow_get_row", + "table_id": 5754, + "view_id": 26713, + "search_query": "", + "filter_type": "AND", + "filters": [], + "row_id": "get('page_parameter.request_id')" + } + }, + { + "id": 12258, + "name": "Get request details", + "order": "2.00000000000000000000", + "service": { + "id": 15139, + "integration_id": 904, + "type": "local_baserow_list_rows", + "table_id": 5755, + "view_id": 26715, + "sortings": [], + "search_query": "", + "filter_type": "AND", + "filters": [ + { + "field_id": 60386, + "type": "link_row_has", + "value": "get('page_parameter.request_id')", + "value_is_formula": true + } + ] + } + } + ], + "workflow_actions": [ + { + "id": 14041, + "type": "update_row", + "order": 1, + "page_id": 6727, + "element_id": 107744, + "event": "click", + "service": { + "id": 15146, + "integration_id": 904, + "type": "local_baserow_upsert_row", + "table_id": 5754, + "row_id": "get('data_source.12257.id')", + "field_mappings": [ + { + "field_id": 60375, + "value": "", + "enabled": false + }, + { + "field_id": 60376, + "value": "", + "enabled": false + }, + { + "field_id": 60377, + "value": "'Request'", + "enabled": true + }, + { + "field_id": 60378, + "value": "", + "enabled": false + }, + { + "field_id": 60379, + "value": "", + "enabled": false + }, + { + "field_id": 60381, + "value": "", + "enabled": false + }, + { + "field_id": 60382, + "value": "", + "enabled": false + }, + { + "field_id": 60383, + "value": "", + "enabled": false + }, + { + "field_id": 60384, + "value": "", + "enabled": false + }, + { + "field_id": 60412, + "value": "", + "enabled": false + } + ] + } + }, + { + "id": 14045, + "type": "update_row", + "order": 1, + "page_id": 6727, + "element_id": 107745, + "event": "click", + "service": { + "id": 15147, + "integration_id": 904, + "type": "local_baserow_upsert_row", + "table_id": 5754, + "row_id": "get('data_source.12257.id')", + "field_mappings": [ + { + "field_id": 60375, + "value": "", + "enabled": false + }, + { + "field_id": 60376, + "value": "", + "enabled": false + }, + { + "field_id": 60377, + "value": "'Quote'", + "enabled": true + }, + { + "field_id": 60378, + "value": "", + "enabled": false + }, + { + "field_id": 60379, + "value": "", + "enabled": false + }, + { + "field_id": 60381, + "value": "", + "enabled": false + }, + { + "field_id": 60382, + "value": "get('data_source.12257.field_60385')", + "enabled": true + }, + { + "field_id": 60383, + "value": "", + "enabled": false + }, + { + "field_id": 60384, + "value": "", + "enabled": false + }, + { + "field_id": 60412, + "value": "", + "enabled": false + } + ] + } + }, + { + "id": 14049, + "type": "update_row", + "order": 1, + "page_id": 6727, + "element_id": 107746, + "event": "click", + "service": { + "id": 15148, + "integration_id": 904, + "type": "local_baserow_upsert_row", + "table_id": 5754, + "row_id": "get('data_source.12257.id')", + "field_mappings": [ + { + "field_id": 60375, + "value": "", + "enabled": false + }, + { + "field_id": 60376, + "value": "", + "enabled": false + }, + { + "field_id": 60377, + "value": "'Order'", + "enabled": true + }, + { + "field_id": 60378, + "value": "", + "enabled": false + }, + { + "field_id": 60379, + "value": "", + "enabled": false + }, + { + "field_id": 60381, + "value": "", + "enabled": false + }, + { + "field_id": 60382, + "value": "", + "enabled": false + }, + { + "field_id": 60383, + "value": "get('data_source.12257.field_60385')", + "enabled": true + }, + { + "field_id": 60384, + "value": "", + "enabled": false + }, + { + "field_id": 60412, + "value": "", + "enabled": false + } + ] + } + }, + { + "id": 14053, + "type": "update_row", + "order": 1, + "page_id": 6727, + "element_id": 107747, + "event": "click", + "service": { + "id": 15149, + "integration_id": 904, + "type": "local_baserow_upsert_row", + "table_id": 5754, + "row_id": "get('data_source.12257.id')", + "field_mappings": [ + { + "field_id": 60375, + "value": "", + "enabled": false + }, + { + "field_id": 60376, + "value": "", + "enabled": false + }, + { + "field_id": 60377, + "value": "'Processing order'", + "enabled": true + }, + { + "field_id": 60378, + "value": "", + "enabled": false + }, + { + "field_id": 60379, + "value": "", + "enabled": false + }, + { + "field_id": 60381, + "value": "", + "enabled": false + }, + { + "field_id": 60382, + "value": "", + "enabled": false + }, + { + "field_id": 60383, + "value": "", + "enabled": false + }, + { + "field_id": 60384, + "value": "", + "enabled": false + }, + { + "field_id": 60412, + "value": "", + "enabled": false + } + ] + } + }, + { + "id": 14057, + "type": "update_row", + "order": 1, + "page_id": 6727, + "element_id": 107748, + "event": "click", + "service": { + "id": 15150, + "integration_id": 904, + "type": "local_baserow_upsert_row", + "table_id": 5754, + "row_id": "get('data_source.12257.id')", + "field_mappings": [ + { + "field_id": 60375, + "value": "", + "enabled": false + }, + { + "field_id": 60376, + "value": "", + "enabled": false + }, + { + "field_id": 60377, + "value": "'Delivery in progress'", + "enabled": true + }, + { + "field_id": 60378, + "value": "", + "enabled": false + }, + { + "field_id": 60379, + "value": "", + "enabled": false + }, + { + "field_id": 60382, + "value": "", + "enabled": false + }, + { + "field_id": 60381, + "value": "", + "enabled": false + }, + { + "field_id": 60383, + "value": "", + "enabled": false + }, + { + "field_id": 60384, + "value": "get('data_source.12257.field_60385')", + "enabled": true + }, + { + "field_id": 60412, + "value": "", + "enabled": false + } + ] + } + }, + { + "id": 14061, + "type": "update_row", + "order": 1, + "page_id": 6727, + "element_id": 107749, + "event": "click", + "service": { + "id": 15151, + "integration_id": 904, + "type": "local_baserow_upsert_row", + "table_id": 5754, + "row_id": "get('data_source.12257.id')", + "field_mappings": [ + { + "field_id": 60375, + "value": "", + "enabled": false + }, + { + "field_id": 60376, + "value": "", + "enabled": false + }, + { + "field_id": 60377, + "value": "'Closed'", + "enabled": true + }, + { + "field_id": 60378, + "value": "", + "enabled": false + }, + { + "field_id": 60379, + "value": "", + "enabled": false + }, + { + "field_id": 60381, + "value": "", + "enabled": false + }, + { + "field_id": 60382, + "value": "", + "enabled": false + }, + { + "field_id": 60383, + "value": "", + "enabled": false + }, + { + "field_id": 60384, + "value": "get('data_source.12257.field_60385')", + "enabled": true + }, + { + "field_id": 60412, + "value": "", + "enabled": false + } + ] + } + }, + { + "id": 14043, + "type": "refresh_data_source", + "order": 2, + "page_id": 6727, + "element_id": 107744, + "event": "click", + "data_source_id": 12257 + }, + { + "id": 14047, + "type": "refresh_data_source", + "order": 2, + "page_id": 6727, + "element_id": 107745, + "event": "click", + "data_source_id": 12257 + }, + { + "id": 14051, + "type": "refresh_data_source", + "order": 2, + "page_id": 6727, + "element_id": 107746, + "event": "click", + "data_source_id": 12257 + }, + { + "id": 14055, + "type": "refresh_data_source", + "order": 2, + "page_id": 6727, + "element_id": 107747, + "event": "click", + "data_source_id": 12257 + }, + { + "id": 14059, + "type": "refresh_data_source", + "order": 2, + "page_id": 6727, + "element_id": 107748, + "event": "click", + "data_source_id": 12257 + }, + { + "id": 14063, + "type": "refresh_data_source", + "order": 2, + "page_id": 6727, + "element_id": 107749, + "event": "click", + "data_source_id": 12257 + } + ], + "visibility": "logged-in", + "role_type": "allow_all", + "roles": [] + }, + { + "id": 6728, + "name": "Request details update", + "order": 7, + "path": "/request-details-update/:request_id/:request_details_id", + "path_params": [ + { + "name": "request_id", + "type": "numeric" + }, + { + "name": "request_details_id", + "type": "numeric" + } + ], + "query_params": [], + "shared": false, + "elements": [ + { + "id": 107754, + "order": "0.50000000000000000000", + "type": "text", + "parent_element_id": 107751, + "place_in_container": "1", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_color": "primary", + "body_font_weight": "semi-bold" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'SHORT NAME'", + "format": "plain" + }, + { + "id": 107755, + "order": "0.50000000000000000000", + "type": "text", + "parent_element_id": 107752, + "place_in_container": "1", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_color": "primary", + "body_font_weight": "semi-bold" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'QUOTE DATE'", + "format": "plain" + }, + { + "id": 107756, + "order": "1.00000000000000000000", + "type": "heading", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "concat('Request details ',get('data_source.12259.field_60374'),' (',get('data_source.12259.field_60394'),')')", + "level": 1 + }, + { + "id": 107757, + "order": "1.00000000000000000000", + "type": "text", + "parent_element_id": 107751, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_color": "primary", + "body_font_weight": "semi-bold" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'ID'", + "format": "plain" + }, + { + "id": 107758, + "order": "1.00000000000000000000", + "type": "text", + "parent_element_id": 107751, + "place_in_container": "1", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "get('data_source.12259.field_60381')", + "format": "plain" + }, + { + "id": 107759, + "order": "1.00000000000000000000", + "type": "text", + "parent_element_id": 107751, + "place_in_container": "2", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_color": "primary", + "body_font_weight": "semi-bold" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'SUPPLIER'", + "format": "plain" + }, + { + "id": 107760, + "order": "1.00000000000000000000", + "type": "text", + "parent_element_id": 107751, + "place_in_container": "3", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_color": "primary", + "body_font_weight": "semi-bold" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'COMMENTS'", + "format": "plain" + }, + { + "id": 107761, + "order": "1.00000000000000000000", + "type": "text", + "parent_element_id": 107751, + "place_in_container": "4", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_color": "primary", + "body_font_weight": "semi-bold" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'INITIATED BY'", + "format": "plain" + }, + { + "id": 107785, + "order": "1.00000000000000000000", + "type": "record_selector", + "parent_element_id": 107783, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "data_source_id": 12262, + "items_per_page": 20, + "button_load_more_label": "", + "schema_property": null, + "property_options": [ + { + "schema_property": "field_60367", + "filterable": false, + "sortable": false, + "searchable": true + }, + { + "schema_property": "field_60368", + "filterable": false, + "sortable": false, + "searchable": true + }, + { + "schema_property": "field_60369", + "filterable": false, + "sortable": false, + "searchable": true + }, + { + "schema_property": "field_60366", + "filterable": false, + "sortable": false, + "searchable": true + } + ], + "required": true, + "label": "'PART'", + "default_value": "get('data_source.12261.field_60387.0.id')", + "placeholder": "", + "multiple": false, + "option_name_suffix": "concat(get('current_record.field_60367'), ' - ', get('current_record.field_60369.*.value'))" + }, + { + "id": 107768, + "order": "1.33333333333333325932", + "type": "text", + "parent_element_id": 107752, + "place_in_container": "2", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_color": "primary", + "body_font_weight": "semi-bold" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'ORDER DATE'", + "format": "plain" + }, + { + "id": 107769, + "order": "1.33333333333333325932", + "type": "text", + "parent_element_id": 107752, + "place_in_container": "3", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_color": "primary", + "body_font_weight": "semi-bold" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'DELIVERY DATE'", + "format": "plain" + }, + { + "id": 107770, + "order": "1.50000000000000000000", + "type": "heading", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'General information'", + "level": 2 + }, + { + "id": 107790, + "order": "1.50000000000000000000", + "type": "choice", + "parent_element_id": 107783, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "label": "'STATUS'", + "required": true, + "placeholder": "", + "default_value": "get('data_source.12261.field_60392.id')", + "options": [], + "multiple": false, + "show_as_dropdown": true, + "option_type": "formulas", + "formula_value": "get('data_source_context.12261.field_60392.*.id')", + "formula_name": "get('data_source_context.12261.field_60392.*.value')" + }, + { + "id": 107751, + "order": "1.66666666666666674068", + "type": "column", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 1, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "column_amount": 5, + "column_gap": 20, + "alignment": "top" + }, + { + "id": 107752, + "order": "2.00000000000000000000", + "type": "column", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 1, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "column_amount": 5, + "column_gap": 20, + "alignment": "top" + }, + { + "id": 107771, + "order": "2.00000000000000000000", + "type": "text", + "parent_element_id": 107751, + "place_in_container": "2", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "concat(get('data_source.12259.field_60394'),' (',get('data_source.12259.field_60375.*.value'),')')", + "format": "plain" + }, + { + "id": 107772, + "order": "2.00000000000000000000", + "type": "text", + "parent_element_id": 107751, + "place_in_container": "3", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "get('data_source.12259.field_60376')", + "format": "plain" + }, + { + "id": 107773, + "order": "2.00000000000000000000", + "type": "text", + "parent_element_id": 107752, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_color": "primary", + "body_font_weight": "semi-bold" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'REQUEST DATE'", + "format": "plain" + }, + { + "id": 107774, + "order": "2.00000000000000000000", + "type": "text", + "parent_element_id": 107752, + "place_in_container": "1", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "get('data_source.12259.field_60382')", + "format": "plain" + }, + { + "id": 107786, + "order": "2.00000000000000000000", + "type": "input_text", + "parent_element_id": 107783, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "label": "'UNIT PRICE'", + "required": true, + "validation_type": "integer", + "placeholder": "", + "default_value": "get('data_source.12261.field_60388')", + "is_multiline": false, + "rows": 3, + "input_type": "text" + }, + { + "id": 107775, + "order": "2.33333333333333348136", + "type": "heading", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 50, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "concat('Current article: ', get('data_source.12261.field_60401'), ' ( ', get('data_source.12261.field_60387.*.value'), ') ')", + "level": 2 + }, + { + "id": 107791, + "order": "2.39999999999999991118", + "type": "link", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "navigation_type": "page", + "navigate_to_page_id": 6727, + "page_parameters": [ + { + "name": "request_id", + "value": "get('data_source.12259.id')" + } + ], + "query_parameters": [], + "navigate_to_url": "", + "target": "self", + "value": "'<- Back to articles overview'", + "variant": "link" + }, + { + "id": 107783, + "order": "2.50000000000000000000", + "type": "form_container", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "button": { + "button_alignment": "center", + "button_horizontal_padding": 48 + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 50, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 50, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "color", + "style_background_color": "#a0a0a01a", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "small", + "style_width_child": "normal", + "submit_button_label": "'UPDATE ARTICLE DETAILS'", + "reset_initial_values_post_submission": false + }, + { + "id": 107776, + "order": "3.00000000000000000000", + "type": "text", + "parent_element_id": 107751, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "get('data_source.12259.field_60374')", + "format": "plain" + }, + { + "id": 107777, + "order": "3.00000000000000000000", + "type": "heading", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 50, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Articles'", + "level": 2 + }, + { + "id": 107778, + "order": "3.00000000000000000000", + "type": "text", + "parent_element_id": 107751, + "place_in_container": "4", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "concat(get('data_source.12259.field_60380.*.value'), get('data_source.12259.field_60412.*.value'))", + "format": "plain" + }, + { + "id": 107779, + "order": "3.00000000000000000000", + "type": "text", + "parent_element_id": 107752, + "place_in_container": "2", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "get('data_source.12259.field_60383')", + "format": "plain" + }, + { + "id": 107780, + "order": "3.00000000000000000000", + "type": "text", + "parent_element_id": 107752, + "place_in_container": "3", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "get('data_source.12259.field_60384')", + "format": "plain" + }, + { + "id": 107787, + "order": "3.00000000000000000000", + "type": "input_text", + "parent_element_id": 107783, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "label": "'QUANTITY REQUESTED'", + "required": true, + "validation_type": "integer", + "placeholder": "", + "default_value": "get('data_source.12261.field_60389')", + "is_multiline": false, + "rows": 3, + "input_type": "text" + }, + { + "id": 107781, + "order": "4.00000000000000000000", + "type": "text", + "parent_element_id": 107752, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "get('data_source.12259.field_60379')", + "format": "plain" + }, + { + "id": 107782, + "order": "4.00000000000000000000", + "type": "table", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "data_source_id": 12260, + "items_per_page": 20, + "button_load_more_label": "", + "schema_property": null, + "property_options": [], + "fields": [ + { + "uid": "1862ad4e-8572-4e30-b892-0cafeaffd1dd", + "name": "Part", + "type": "text", + "styles": {}, + "config": { + "value": "get('current_record.field_60387.*.value')" + } + }, + { + "uid": "f8c427cd-c04e-453c-81b4-5d7f9811cb09", + "name": "Part name", + "type": "text", + "styles": {}, + "config": { + "value": "get('current_record.field_60401')" + } + }, + { + "uid": "fa2b4c83-592f-4ef1-9aba-92f4dfeeea1a", + "name": "Unit price", + "type": "text", + "styles": {}, + "config": { + "value": "concat('\u20ac ',get('current_record.field_60388'))" + } + }, + { + "uid": "cde487a9-7e2e-4381-b6ef-e31c2b114464", + "name": "Q. R.", + "type": "text", + "styles": {}, + "config": { + "value": "get('current_record.field_60389')" + } + }, + { + "uid": "096b1b16-aa99-47da-8a38-02c8b74ef11f", + "name": "Q. A.", + "type": "text", + "styles": {}, + "config": { + "value": "get('current_record.field_60390')" + } + }, + { + "uid": "9bc7e6ef-7d88-4a84-8ffc-6869a4762aa2", + "name": "Q. D.", + "type": "text", + "styles": {}, + "config": { + "value": "get('current_record.field_60391')" + } + }, + { + "uid": "89984dca-cd6a-4133-af35-9e911cbec05f", + "name": "Total R.", + "type": "text", + "styles": {}, + "config": { + "value": "concat('\u20ac ',get('current_record.field_60402'))" + } + }, + { + "uid": "9e5f9ceb-5486-4931-a46e-f077f9acbb17", + "name": "Total A.", + "type": "text", + "styles": {}, + "config": { + "value": "concat('\u20ac ',get('current_record.field_60403'))" + } + }, + { + "uid": "31b5f4f4-fc73-45a2-98cc-8120607a9284", + "name": "Status", + "type": "tags", + "styles": {}, + "config": { + "values": "get('current_record.field_60392.value')", + "colors_is_formula": true, + "colors": "get('current_record.field_60392.color')" + } + } + ], + "orientation": { + "tablet": "vertical", + "desktop": "horizontal", + "smartphone": "vertical" + } + }, + { + "id": 107788, + "order": "4.00000000000000000000", + "type": "input_text", + "parent_element_id": 107783, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "label": "'QUANTITY APPROVED'", + "required": true, + "validation_type": "integer", + "placeholder": "", + "default_value": "get('data_source.12261.field_60390')", + "is_multiline": false, + "rows": 3, + "input_type": "text" + }, + { + "id": 107789, + "order": "5.00000000000000000000", + "type": "input_text", + "parent_element_id": 107783, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "label": "'QUANTITY DELIVERED'", + "required": true, + "validation_type": "integer", + "placeholder": "", + "default_value": "get('data_source.12261.field_60391')", + "is_multiline": false, + "rows": 3, + "input_type": "text" + } + ], + "data_sources": [ + { + "id": 12259, + "name": "Get request", + "order": "1.00000000000000000000", + "service": { + "id": 15152, + "integration_id": 904, + "type": "local_baserow_get_row", + "table_id": 5754, + "view_id": 26713, + "search_query": "", + "filter_type": "AND", + "filters": [], + "row_id": "get('page_parameter.request_id')" + } + }, + { + "id": 12260, + "name": "Get request details", + "order": "2.00000000000000000000", + "service": { + "id": 15153, + "integration_id": 904, + "type": "local_baserow_list_rows", + "table_id": 5755, + "view_id": 26715, + "sortings": [], + "search_query": "", + "filter_type": "AND", + "filters": [ + { + "field_id": 60386, + "type": "link_row_has", + "value": "get('page_parameter.request_id')", + "value_is_formula": true + } + ] + } + }, + { + "id": 12261, + "name": "Get request detail", + "order": "3.00000000000000000000", + "service": { + "id": 15160, + "integration_id": 904, + "type": "local_baserow_get_row", + "table_id": 5755, + "view_id": 26715, + "search_query": "", + "filter_type": "AND", + "filters": [], + "row_id": "get('page_parameter.request_details_id')" + } + }, + { + "id": 12262, + "name": "Get parts", + "order": "4.00000000000000000000", + "service": { + "id": 15161, + "integration_id": 904, + "type": "local_baserow_list_rows", + "table_id": 5752, + "view_id": 26711, + "sortings": [], + "search_query": "", + "filter_type": "AND", + "filters": [] + } + } + ], + "workflow_actions": [ + { + "id": 14077, + "type": "update_row", + "order": 1, + "page_id": 6728, + "element_id": 107783, + "event": "submit", + "service": { + "id": 15162, + "integration_id": 904, + "type": "local_baserow_upsert_row", + "table_id": 5755, + "row_id": "get('data_source.12261.id')", + "field_mappings": [ + { + "field_id": 60386, + "value": "", + "enabled": false + }, + { + "field_id": 60387, + "value": "get('form_data.107785')", + "enabled": true + }, + { + "field_id": 60388, + "value": "get('form_data.107786')", + "enabled": true + }, + { + "field_id": 60389, + "value": "get('form_data.107787')", + "enabled": true + }, + { + "field_id": 60390, + "value": "get('form_data.107788')", + "enabled": true + }, + { + "field_id": 60391, + "value": "get('form_data.107789')", + "enabled": true + }, + { + "field_id": 60392, + "value": "get('form_data.107790')", + "enabled": true + } + ] + } + }, + { + "id": 14079, + "type": "open_page", + "order": 2, + "page_id": 6728, + "element_id": 107783, + "event": "submit", + "navigation_type": "page", + "navigate_to_page_id": 6727, + "page_parameters": [ + { + "name": "request_id", + "value": "get('data_source.12259.id')" + } + ], + "query_parameters": [], + "navigate_to_url": "", + "target": "self" + } + ], + "visibility": "logged-in", + "role_type": "disallow_all_except", + "roles": [ + "Purchase department" + ] + } + ], + "integrations": [ + { + "id": 904, + "name": "Local Baserow", + "order": "1.00000000000000000000", + "type": "local_baserow", + "authorized_user": null + } + ], + "theme": { + "primary_color": "#014aac", + "secondary_color": "#0090da", + "border_color": "#a0a0a0", + "main_success_color": "#12D452", + "main_warning_color": "#FCC74A", + "main_error_color": "#FF5A4A", + "custom_colors": [ + { + "name": "Text color", + "color": "#5b5b5b", + "value": "NGqct" + }, + { + "name": "Light background", + "color": "#b5b5b51a", + "value": "ev6JA" + } + ], + "body_font_family": "inter", + "body_font_size": 14, + "body_font_weight": "regular", + "body_text_color": "NGqct", + "body_text_alignment": "left", + "heading_1_font_family": "inter", + "heading_1_font_size": 24, + "heading_1_font_weight": "bold", + "heading_1_text_color": "primary", + "heading_1_text_alignment": "center", + "heading_2_font_family": "inter", + "heading_2_font_size": 20, + "heading_2_font_weight": "semi-bold", + "heading_2_text_color": "NGqct", + "heading_2_text_alignment": "left", + "heading_3_font_family": "inter", + "heading_3_font_size": 16, + "heading_3_font_weight": "medium", + "heading_3_text_color": "NGqct", + "heading_3_text_alignment": "left", + "heading_4_font_family": "inter", + "heading_4_font_size": 16, + "heading_4_font_weight": "medium", + "heading_4_text_color": "NGqct", + "heading_4_text_alignment": "left", + "heading_5_font_family": "inter", + "heading_5_font_size": 14, + "heading_5_font_weight": "regular", + "heading_5_text_color": "NGqct", + "heading_5_text_alignment": "left", + "heading_6_font_family": "inter", + "heading_6_font_size": 14, + "heading_6_font_weight": "regular", + "heading_6_text_color": "NGqct", + "heading_6_text_alignment": "left", + "button_font_family": "inter", + "button_font_size": 13, + "button_font_weight": "regular", + "button_alignment": "left", + "button_text_alignment": "center", + "button_width": "auto", + "button_background_color": "transparent", + "button_text_color": "secondary", + "button_border_color": "secondary", + "button_border_size": 2, + "button_border_radius": 4, + "button_vertical_padding": 12, + "button_horizontal_padding": 12, + "button_hover_background_color": "secondary", + "button_hover_text_color": "#ffffffff", + "button_hover_border_color": "secondary", + "link_font_family": "inter", + "link_font_size": 13, + "link_font_weight": "regular", + "link_text_alignment": "left", + "link_text_color": "primary", + "link_hover_text_color": "#697fc9", + "image_alignment": "left", + "image_max_width": 100, + "image_max_height": null, + "image_border_radius": 0, + "image_constraint": "contain", + "page_background_color": "#ffffffff", + "page_background_file_id": null, + "page_background_mode": "tile", + "label_font_family": "inter", + "label_text_color": "NGqct", + "label_font_size": 12, + "label_font_weight": "semi-bold", + "input_font_family": "inter", + "input_font_size": 13, + "input_font_weight": "regular", + "input_text_color": "NGqct", + "input_background_color": "#FFFFFFFF", + "input_border_color": "border", + "input_border_size": 1, + "input_border_radius": 4, + "input_vertical_padding": 8, + "input_horizontal_padding": 12, + "table_border_color": "border", + "table_border_size": 0, + "table_border_radius": 0, + "table_header_background_color": "primary", + "table_header_text_color": "#ffffff", + "table_header_font_size": 13, + "table_header_font_weight": "semi-bold", + "table_header_font_family": "inter", + "table_header_text_alignment": "left", + "table_cell_background_color": "transparent", + "table_cell_alternate_background_color": "transparent", + "table_cell_alignment": "left", + "table_cell_vertical_padding": 10, + "table_cell_horizontal_padding": 20, + "table_vertical_separator_color": "border", + "table_vertical_separator_size": 0, + "table_horizontal_separator_color": "border", + "table_horizontal_separator_size": 1 + }, + "user_sources": [ + { + "id": 677, + "name": "Staff members", + "order": "1.00000000000000000000", + "type": "local_baserow", + "uid": "677_5756_60408_60410", + "integration_id": 904, + "auth_providers": [ + { + "id": 680, + "type": "local_baserow_password", + "domain": null, + "enabled": true, + "password_field_id": 60414 + } + ], + "table_id": 5756, + "email_field_id": 60408, + "name_field_id": 60407, + "role_field_id": 60410 + } + ], + "favicon_file": null, + "login_page": { + "id": 6723, + "name": "Login", + "order": 1, + "path": "/login", + "path_params": [], + "query_params": [], + "shared": false, + "elements": [ + { + "id": 107672, + "order": "0.50000000000000000000", + "type": "heading", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Purchase Order Managment'", + "level": 1 + }, + { + "id": 107673, + "order": "1.00000000000000000000", + "type": "auth_form", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "login_button": { + "button_alignment": "center", + "button_horizontal_padding": 48 + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 50, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 50, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 50, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 50, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "color", + "style_background_color": "#b5b5b51a", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "small", + "style_width_child": "normal", + "user_source_id": 677, + "login_button_label": "'Sign in'" + } + ], + "data_sources": [], + "workflow_actions": [ + { + "id": 14021, + "type": "open_page", + "order": 1, + "page_id": 6723, + "element_id": 107673, + "event": "after_login", + "navigation_type": "page", + "navigate_to_page_id": 6724, + "page_parameters": [], + "query_parameters": [], + "navigate_to_url": "", + "target": "self" + } + ], + "visibility": "all", + "role_type": "allow_all", + "roles": [] + }, + "id": 2182, + "name": "Purchase Order Manager", + "order": 3, + "type": "builder" + } + ] +} \ No newline at end of file diff --git a/backend/templates/purchase-order-management.zip b/backend/templates/purchase-order-management.zip new file mode 100644 index 000000000..10972144f Binary files /dev/null and b/backend/templates/purchase-order-management.zip differ diff --git a/backend/templates/skill-discovery-management.json b/backend/templates/skill-discovery-management.json new file mode 100644 index 000000000..1ebee9ce4 --- /dev/null +++ b/backend/templates/skill-discovery-management.json @@ -0,0 +1,26986 @@ +{ + "baserow_template_version": 1, + "name": "Skill Discovery Management", + "icon": "iconoir-people-tag", + "keywords": [ + "assessments", + "performance reviews", + "skills", + "skill detection", + "skill discovery", + "skill management", + "potential assessment", + "skills assessment", + "talent detection", + "talent" + ], + "categories": [ + "HR and Recruiting" + ], + "export":[ + { + "id": 2176, + "name": "Skill Discovery Management", + "order": 1, + "type": "database", + "tables": [ + { + "id": 5730, + "name": "Employees", + "order": 4, + "fields": [ + { + "id": 60111, + "type": "text", + "name": "Name", + "description": null, + "order": 0, + "primary": true, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "text_default": "" + }, + { + "id": 60112, + "type": "email", + "name": "Email", + "description": null, + "order": 1, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false + }, + { + "id": 60113, + "type": "phone_number", + "name": "Phone", + "description": null, + "order": 2, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false + }, + { + "id": 60114, + "type": "file", + "name": "Picture", + "description": null, + "order": 3, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false + }, + { + "id": 60116, + "type": "text", + "name": "Job role", + "description": null, + "order": 8, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "text_default": "" + }, + { + "id": 60117, + "type": "text", + "name": "Home address", + "description": null, + "order": 10, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "text_default": "" + }, + { + "id": 60118, + "type": "text", + "name": "ZIP code", + "description": null, + "order": 11, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "text_default": "" + }, + { + "id": 60119, + "type": "date", + "name": "Date of birth", + "description": null, + "order": 12, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "date_format": "ISO", + "date_include_time": false, + "date_time_format": "24", + "date_show_tzinfo": false, + "date_force_timezone": null + }, + { + "id": 60120, + "type": "date", + "name": "Start date", + "description": null, + "order": 14, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "date_format": "ISO", + "date_include_time": false, + "date_time_format": "24", + "date_show_tzinfo": false, + "date_force_timezone": null + }, + { + "id": 60121, + "type": "date", + "name": "End date", + "description": null, + "order": 15, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "date_format": "ISO", + "date_include_time": false, + "date_time_format": "24", + "date_show_tzinfo": false, + "date_force_timezone": null + }, + { + "id": 60181, + "type": "formula", + "name": "Is active", + "description": null, + "order": 16, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "date_show_tzinfo": null, + "nullable": false, + "number_decimal_places": null, + "number_separator": "", + "date_format": null, + "number_prefix": "", + "number_suffix": "", + "duration_format": null, + "array_formula_type": null, + "date_time_format": null, + "error": null, + "date_force_timezone": null, + "date_include_time": null, + "formula": "isblank(field('End date'))", + "formula_type": "boolean" + }, + { + "id": 60122, + "type": "single_select", + "name": "Status", + "description": null, + "order": 17, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "select_options": [ + { + "id": 21146, + "value": "Full-time", + "color": "darker-blue", + "order": 0 + }, + { + "id": 21147, + "value": "4/5 part-time", + "color": "dark-blue", + "order": 1 + }, + { + "id": 21148, + "value": "3/5 part-time", + "color": "blue", + "order": 2 + }, + { + "id": 21149, + "value": "1/2 part-time", + "color": "light-blue", + "order": 3 + } + ] + }, + { + "id": 60182, + "type": "formula", + "name": "Birthday this year", + "description": null, + "order": 18, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "date_show_tzinfo": false, + "nullable": true, + "number_decimal_places": null, + "number_separator": "", + "date_format": "ISO", + "number_prefix": "", + "number_suffix": "", + "duration_format": null, + "array_formula_type": null, + "date_time_format": "24", + "error": null, + "date_force_timezone": null, + "date_include_time": false, + "formula": "todate(concat(year(today()),'-',month(field('Date of birth')),'-',day(field('Date of birth'))),'YYYY-MM-DD')", + "formula_type": "date" + }, + { + "id": 60123, + "type": "link_row", + "name": "Manager", + "description": null, + "order": 19, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "link_row_table_id": 5730, + "link_row_related_field_id": null, + "link_row_limit_selection_view_id": null, + "has_related_field": false + }, + { + "id": 60125, + "type": "link_row", + "name": "Performance rewiews", + "description": null, + "order": 21, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "link_row_table_id": 5731, + "link_row_related_field_id": 60130, + "link_row_limit_selection_view_id": null, + "has_related_field": true + }, + { + "id": 60203, + "type": "count", + "name": "Count reviews", + "description": null, + "order": 22, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "date_show_tzinfo": null, + "nullable": false, + "number_decimal_places": 0, + "number_separator": "", + "date_format": null, + "number_prefix": "", + "number_suffix": "", + "duration_format": null, + "array_formula_type": null, + "date_time_format": null, + "error": null, + "date_force_timezone": null, + "date_include_time": null, + "through_field_id": 60125 + }, + { + "id": 60195, + "type": "formula", + "name": "Total last 3 years", + "description": null, + "order": 23, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "date_show_tzinfo": null, + "nullable": false, + "number_decimal_places": 1, + "number_separator": "", + "date_format": null, + "number_prefix": "", + "number_suffix": "", + "duration_format": null, + "array_formula_type": null, + "date_time_format": null, + "error": null, + "date_force_timezone": null, + "date_include_time": null, + "formula": "sum(filter(lookup('Performance rewiews','Overall performance rating'),lookup('Performance rewiews','Year') > (field('Last review') - 3)))", + "formula_type": "number" + }, + { + "id": 60207, + "type": "formula", + "name": "Average last 3 years", + "description": null, + "order": 24, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "date_show_tzinfo": null, + "nullable": false, + "number_decimal_places": 1, + "number_separator": "", + "date_format": null, + "number_prefix": "", + "number_suffix": "", + "duration_format": null, + "array_formula_type": null, + "date_time_format": null, + "error": null, + "date_force_timezone": null, + "date_include_time": null, + "formula": "if(field('Count reviews') = 0,0,sum(filter(lookup('Performance rewiews','Overall performance rating'),lookup('Performance rewiews','Year') > (field('Last review') - 3))) / count(filter(lookup('Performance rewiews','Overall performance rating'),lookup('Performance rewiews','Year') > (field('Last review') - 3))))", + "formula_type": "number" + }, + { + "id": 60211, + "type": "formula", + "name": "Sustained performance", + "description": null, + "order": 25, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "date_show_tzinfo": null, + "nullable": false, + "number_decimal_places": null, + "number_separator": "", + "date_format": null, + "number_prefix": "", + "number_suffix": "", + "duration_format": null, + "array_formula_type": null, + "date_time_format": null, + "error": null, + "date_force_timezone": null, + "date_include_time": null, + "formula": "if(field('Average last 3 years') = 0,'N/A',if(field('Average last 3 years') < 2.5,'Low',if(field('Average last 3 years') < 3.5,'Medium','High')))", + "formula_type": "text" + }, + { + "id": 60183, + "type": "rollup", + "name": "Last review", + "description": null, + "order": 26, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "date_show_tzinfo": null, + "nullable": true, + "number_decimal_places": 0, + "number_separator": "", + "date_format": null, + "number_prefix": "", + "number_suffix": "", + "duration_format": null, + "array_formula_type": null, + "date_time_format": null, + "error": null, + "date_force_timezone": null, + "date_include_time": null, + "through_field_id": 60125, + "target_field_id": 60132, + "rollup_function": "max" + }, + { + "id": 60126, + "type": "link_row", + "name": "Potential assessments", + "description": null, + "order": 27, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "link_row_table_id": 5733, + "link_row_related_field_id": 60138, + "link_row_limit_selection_view_id": null, + "has_related_field": true + }, + { + "id": 60208, + "type": "formula", + "name": "Has potential", + "description": null, + "order": 28, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "date_show_tzinfo": null, + "nullable": false, + "number_decimal_places": null, + "number_separator": "", + "date_format": null, + "number_prefix": "", + "number_suffix": "", + "duration_format": null, + "array_formula_type": null, + "date_time_format": null, + "error": null, + "date_force_timezone": null, + "date_include_time": null, + "formula": "every(filter(lookup('Potential assessments','Has potential'),lookup('Potential assessments','Year') = field('Last review')))", + "formula_type": "boolean" + }, + { + "id": 60127, + "type": "link_row", + "name": "Ability assessments", + "description": null, + "order": 29, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "link_row_table_id": 5735, + "link_row_related_field_id": 60155, + "link_row_limit_selection_view_id": null, + "has_related_field": true + }, + { + "id": 60199, + "type": "formula", + "name": "Has ability", + "description": null, + "order": 30, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "date_show_tzinfo": null, + "nullable": false, + "number_decimal_places": null, + "number_separator": "", + "date_format": null, + "number_prefix": "", + "number_suffix": "", + "duration_format": null, + "array_formula_type": null, + "date_time_format": null, + "error": null, + "date_force_timezone": null, + "date_include_time": null, + "formula": "every(filter(lookup('Ability assessments','Has ability'),lookup('Ability assessments','Year') = field('Last review')))", + "formula_type": "boolean" + }, + { + "id": 60214, + "type": "formula", + "name": "Category", + "description": null, + "order": 31, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "date_show_tzinfo": null, + "nullable": false, + "number_decimal_places": null, + "number_separator": "", + "date_format": null, + "number_prefix": "", + "number_suffix": "", + "duration_format": null, + "array_formula_type": null, + "date_time_format": null, + "error": null, + "date_force_timezone": null, + "date_include_time": null, + "formula": "if(field('Sustained performance') = 'N/A','Too Soon to Rate',if(field('Sustained performance') = 'Low','Improve',if(field('Has ability'),'Accelerate','Grow')))", + "formula_type": "text" + }, + { + "id": 60128, + "type": "password", + "name": "Password", + "description": null, + "order": 32, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false + }, + { + "id": 60212, + "type": "formula", + "name": "Has potential symbol", + "description": null, + "order": 33, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "date_show_tzinfo": null, + "nullable": false, + "number_decimal_places": null, + "number_separator": "", + "date_format": null, + "number_prefix": "", + "number_suffix": "", + "duration_format": null, + "array_formula_type": null, + "date_time_format": null, + "error": null, + "date_force_timezone": null, + "date_include_time": null, + "formula": "if(field('Has potential'),'\u2714\ufe0f ','\u274c')", + "formula_type": "text" + }, + { + "id": 60205, + "type": "formula", + "name": "Has ability symbol", + "description": null, + "order": 34, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "date_show_tzinfo": null, + "nullable": false, + "number_decimal_places": null, + "number_separator": "", + "date_format": null, + "number_prefix": "", + "number_suffix": "", + "duration_format": null, + "array_formula_type": null, + "date_time_format": null, + "error": null, + "date_force_timezone": null, + "date_include_time": null, + "formula": "if(field('Has ability'),'\u2714\ufe0f ','\u274c')", + "formula_type": "text" + }, + { + "id": 60194, + "type": "formula", + "name": "Next review", + "description": null, + "order": 35, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "date_show_tzinfo": null, + "nullable": false, + "number_decimal_places": 0, + "number_separator": "", + "date_format": null, + "number_prefix": "", + "number_suffix": "", + "duration_format": null, + "array_formula_type": null, + "date_time_format": null, + "error": null, + "date_force_timezone": null, + "date_include_time": null, + "formula": "if(field('Last review') = 0,year(today()),field('Last review') + 1)", + "formula_type": "number" + }, + { + "id": 60206, + "type": "formula", + "name": "Needs review link", + "description": null, + "order": 36, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "date_show_tzinfo": null, + "nullable": false, + "number_decimal_places": null, + "number_separator": "", + "date_format": null, + "number_prefix": "", + "number_suffix": "", + "duration_format": null, + "array_formula_type": null, + "date_time_format": null, + "error": null, + "date_force_timezone": null, + "date_include_time": null, + "formula": "if(field('Needs review'),concat('+ Add performance review for ',field('Next review')),'')", + "formula_type": "text" + }, + { + "id": 60215, + "type": "formula", + "name": "Meets potential requirements", + "description": null, + "order": 37, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "date_show_tzinfo": null, + "nullable": false, + "number_decimal_places": null, + "number_separator": "", + "date_format": null, + "number_prefix": "", + "number_suffix": "", + "duration_format": null, + "array_formula_type": null, + "date_time_format": null, + "error": null, + "date_force_timezone": null, + "date_include_time": null, + "formula": "or(field('Sustained performance') = 'High',field('Sustained performance') = 'Medium')", + "formula_type": "boolean" + }, + { + "id": 60202, + "type": "formula", + "name": "Needs review", + "description": null, + "order": 38, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "date_show_tzinfo": null, + "nullable": false, + "number_decimal_places": null, + "number_separator": "", + "date_format": null, + "number_prefix": "", + "number_suffix": "", + "duration_format": null, + "array_formula_type": null, + "date_time_format": null, + "error": null, + "date_force_timezone": null, + "date_include_time": null, + "formula": "field('Next review') = year(today())", + "formula_type": "boolean" + }, + { + "id": 60218, + "type": "formula", + "name": "Needs potential assessment", + "description": null, + "order": 39, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "date_show_tzinfo": null, + "nullable": false, + "number_decimal_places": null, + "number_separator": "", + "date_format": null, + "number_prefix": "", + "number_suffix": "", + "duration_format": null, + "array_formula_type": null, + "date_time_format": null, + "error": null, + "date_force_timezone": null, + "date_include_time": null, + "formula": "and(count(filter(field('Potential assessments'),lookup('Potential assessments','Year') = field('Last review'))) = 0,field('Meets potential requirements'))", + "formula_type": "boolean" + }, + { + "id": 60221, + "type": "formula", + "name": "Needs potential assessment link", + "description": null, + "order": 40, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "date_show_tzinfo": null, + "nullable": false, + "number_decimal_places": null, + "number_separator": "", + "date_format": null, + "number_prefix": "", + "number_suffix": "", + "duration_format": null, + "array_formula_type": null, + "date_time_format": null, + "error": null, + "date_force_timezone": null, + "date_include_time": null, + "formula": "if(field('Needs potential assessment'),concat('+ Add potential assessment for ',field('Last review')),'')", + "formula_type": "text" + }, + { + "id": 60213, + "type": "formula", + "name": "Meets ability requirements", + "description": null, + "order": 41, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "date_show_tzinfo": null, + "nullable": false, + "number_decimal_places": null, + "number_separator": "", + "date_format": null, + "number_prefix": "", + "number_suffix": "", + "duration_format": null, + "array_formula_type": null, + "date_time_format": null, + "error": null, + "date_force_timezone": null, + "date_include_time": null, + "formula": "field('Has potential')", + "formula_type": "boolean" + }, + { + "id": 60216, + "type": "formula", + "name": "Needs ability assessment", + "description": null, + "order": 42, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "date_show_tzinfo": null, + "nullable": false, + "number_decimal_places": null, + "number_separator": "", + "date_format": null, + "number_prefix": "", + "number_suffix": "", + "duration_format": null, + "array_formula_type": null, + "date_time_format": null, + "error": null, + "date_force_timezone": null, + "date_include_time": null, + "formula": "and(count(filter(field('Ability assessments'),lookup('Ability assessments','Year') = field('Last review'))) = 0,field('Meets ability requirements'))", + "formula_type": "boolean" + }, + { + "id": 60219, + "type": "formula", + "name": "Needs ability assessment link", + "description": null, + "order": 43, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "date_show_tzinfo": null, + "nullable": false, + "number_decimal_places": null, + "number_separator": "", + "date_format": null, + "number_prefix": "", + "number_suffix": "", + "duration_format": null, + "array_formula_type": null, + "date_time_format": null, + "error": null, + "date_force_timezone": null, + "date_include_time": null, + "formula": "if(field('Needs ability assessment'),concat('+ Add ability assessment for ',field('Last review')),'')", + "formula_type": "text" + }, + { + "id": 60129, + "type": "link_row", + "name": "Accelerated assessments", + "description": null, + "order": 44, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "link_row_table_id": 5736, + "link_row_related_field_id": 60161, + "link_row_limit_selection_view_id": null, + "has_related_field": true + }, + { + "id": 60217, + "type": "formula", + "name": "Meets accelerated requirements", + "description": null, + "order": 45, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "date_show_tzinfo": null, + "nullable": false, + "number_decimal_places": null, + "number_separator": "", + "date_format": null, + "number_prefix": "", + "number_suffix": "", + "duration_format": null, + "array_formula_type": null, + "date_time_format": null, + "error": null, + "date_force_timezone": null, + "date_include_time": null, + "formula": "field('Category') = 'Accelerate'", + "formula_type": "boolean" + }, + { + "id": 60220, + "type": "formula", + "name": "Needs accelerated assessment", + "description": null, + "order": 46, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "date_show_tzinfo": null, + "nullable": false, + "number_decimal_places": null, + "number_separator": "", + "date_format": null, + "number_prefix": "", + "number_suffix": "", + "duration_format": null, + "array_formula_type": null, + "date_time_format": null, + "error": null, + "date_force_timezone": null, + "date_include_time": null, + "formula": "and(count(filter(field('Accelerated assessments'),lookup('Accelerated assessments','Year') = field('Last review'))) = 0,field('Meets accelerated requirements'))", + "formula_type": "boolean" + }, + { + "id": 60222, + "type": "formula", + "name": "Needs accelerated assessment link", + "description": null, + "order": 47, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "date_show_tzinfo": null, + "nullable": false, + "number_decimal_places": null, + "number_separator": "", + "date_format": null, + "number_prefix": "", + "number_suffix": "", + "duration_format": null, + "array_formula_type": null, + "date_time_format": null, + "error": null, + "date_force_timezone": null, + "date_include_time": null, + "formula": "if(field('Needs accelerated assessment'),concat('+ Add accelerated assessment for ',field('Last review')),'')", + "formula_type": "text" + } + ], + "views": [ + { + "id": 26631, + "type": "grid", + "name": "All employees", + "order": 1, + "ownership_type": "collaborative", + "owned_by": "frederik@baserow.io", + "filter_type": "AND", + "filters_disabled": false, + "filters": [], + "filter_groups": [], + "sortings": [ + { + "id": 20518, + "field_id": 60111, + "order": "ASC" + } + ], + "group_bys": [], + "decorations": [], + "public": false, + "row_identifier_type": "id", + "row_height_size": "small", + "field_options": [ + { + "id": 263683, + "field_id": 60111, + "width": 166, + "hidden": false, + "order": 0, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263684, + "field_id": 60112, + "width": 250, + "hidden": false, + "order": 1, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263685, + "field_id": 60113, + "width": 132, + "hidden": false, + "order": 2, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263686, + "field_id": 60114, + "width": 115, + "hidden": false, + "order": 3, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263687, + "field_id": 60116, + "width": 200, + "hidden": false, + "order": 4, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263688, + "field_id": 60128, + "width": 200, + "hidden": false, + "order": 5, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263689, + "field_id": 60123, + "width": 129, + "hidden": false, + "order": 6, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263691, + "field_id": 60117, + "width": 200, + "hidden": false, + "order": 8, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263692, + "field_id": 60118, + "width": 130, + "hidden": false, + "order": 9, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263693, + "field_id": 60119, + "width": 150, + "hidden": false, + "order": 10, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263694, + "field_id": 60182, + "width": 181, + "hidden": false, + "order": 11, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263695, + "field_id": 60122, + "width": 134, + "hidden": false, + "order": 12, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263696, + "field_id": 60120, + "width": 157, + "hidden": false, + "order": 13, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263697, + "field_id": 60121, + "width": 130, + "hidden": false, + "order": 14, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263698, + "field_id": 60181, + "width": 128, + "hidden": false, + "order": 15, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263699, + "field_id": 60125, + "width": 249, + "hidden": false, + "order": 16, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263700, + "field_id": 60203, + "width": 150, + "hidden": false, + "order": 17, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263704, + "field_id": 60183, + "width": 134, + "hidden": false, + "order": 18, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263711, + "field_id": 60194, + "width": 138, + "hidden": false, + "order": 19, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263712, + "field_id": 60202, + "width": 146, + "hidden": false, + "order": 20, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263701, + "field_id": 60195, + "width": 173, + "hidden": false, + "order": 21, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263702, + "field_id": 60207, + "width": 193, + "hidden": false, + "order": 22, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263703, + "field_id": 60211, + "width": 208, + "hidden": false, + "order": 23, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263705, + "field_id": 60126, + "width": 200, + "hidden": false, + "order": 24, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263717, + "field_id": 60215, + "width": 251, + "hidden": false, + "order": 25, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263720, + "field_id": 60218, + "width": 242, + "hidden": false, + "order": 26, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263706, + "field_id": 60208, + "width": 152, + "hidden": false, + "order": 27, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263707, + "field_id": 60127, + "width": 188, + "hidden": false, + "order": 28, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263716, + "field_id": 60213, + "width": 228, + "hidden": false, + "order": 29, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263718, + "field_id": 60216, + "width": 227, + "hidden": false, + "order": 30, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263708, + "field_id": 60199, + "width": 133, + "hidden": false, + "order": 31, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263709, + "field_id": 60214, + "width": 149, + "hidden": false, + "order": 32, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263710, + "field_id": 60129, + "width": 222, + "hidden": false, + "order": 33, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263713, + "field_id": 60205, + "width": 200, + "hidden": true, + "order": 34, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263714, + "field_id": 60206, + "width": 200, + "hidden": true, + "order": 35, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263715, + "field_id": 60212, + "width": 200, + "hidden": true, + "order": 36, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263719, + "field_id": 60217, + "width": 263, + "hidden": false, + "order": 37, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263721, + "field_id": 60219, + "width": 200, + "hidden": true, + "order": 38, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263722, + "field_id": 60220, + "width": 258, + "hidden": false, + "order": 39, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263723, + "field_id": 60221, + "width": 200, + "hidden": true, + "order": 40, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263724, + "field_id": 60222, + "width": 200, + "hidden": true, + "order": 41, + "aggregation_type": "", + "aggregation_raw_type": "" + } + ] + }, + { + "id": 26632, + "type": "grid", + "name": "All employees: basic information", + "order": 2, + "ownership_type": "collaborative", + "owned_by": "frederik@baserow.io", + "filter_type": "AND", + "filters_disabled": false, + "filters": [], + "filter_groups": [], + "sortings": [ + { + "id": 20519, + "field_id": 60111, + "order": "ASC" + } + ], + "group_bys": [], + "decorations": [], + "public": false, + "row_identifier_type": "id", + "row_height_size": "small", + "field_options": [ + { + "id": 263725, + "field_id": 60111, + "width": 166, + "hidden": false, + "order": 0, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263726, + "field_id": 60112, + "width": 250, + "hidden": false, + "order": 1, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263727, + "field_id": 60113, + "width": 132, + "hidden": false, + "order": 2, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263728, + "field_id": 60114, + "width": 115, + "hidden": false, + "order": 3, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263729, + "field_id": 60116, + "width": 200, + "hidden": false, + "order": 4, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263730, + "field_id": 60128, + "width": 200, + "hidden": true, + "order": 5, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263731, + "field_id": 60123, + "width": 129, + "hidden": false, + "order": 6, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263733, + "field_id": 60117, + "width": 200, + "hidden": false, + "order": 8, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263734, + "field_id": 60118, + "width": 130, + "hidden": false, + "order": 9, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263735, + "field_id": 60119, + "width": 150, + "hidden": false, + "order": 10, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263736, + "field_id": 60182, + "width": 181, + "hidden": false, + "order": 11, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263737, + "field_id": 60122, + "width": 134, + "hidden": false, + "order": 12, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263738, + "field_id": 60120, + "width": 157, + "hidden": false, + "order": 13, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263739, + "field_id": 60121, + "width": 130, + "hidden": false, + "order": 14, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263740, + "field_id": 60181, + "width": 128, + "hidden": false, + "order": 15, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263741, + "field_id": 60125, + "width": 249, + "hidden": true, + "order": 16, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263742, + "field_id": 60203, + "width": 150, + "hidden": true, + "order": 17, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263743, + "field_id": 60183, + "width": 134, + "hidden": true, + "order": 18, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263744, + "field_id": 60194, + "width": 138, + "hidden": true, + "order": 19, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263745, + "field_id": 60202, + "width": 146, + "hidden": true, + "order": 20, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263746, + "field_id": 60195, + "width": 173, + "hidden": true, + "order": 21, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263747, + "field_id": 60207, + "width": 193, + "hidden": true, + "order": 22, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263748, + "field_id": 60211, + "width": 208, + "hidden": true, + "order": 23, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263749, + "field_id": 60126, + "width": 200, + "hidden": true, + "order": 24, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263750, + "field_id": 60215, + "width": 251, + "hidden": true, + "order": 25, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263751, + "field_id": 60218, + "width": 242, + "hidden": true, + "order": 26, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263752, + "field_id": 60208, + "width": 152, + "hidden": true, + "order": 27, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263753, + "field_id": 60127, + "width": 188, + "hidden": true, + "order": 28, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263754, + "field_id": 60213, + "width": 228, + "hidden": true, + "order": 29, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263755, + "field_id": 60216, + "width": 227, + "hidden": true, + "order": 30, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263756, + "field_id": 60199, + "width": 133, + "hidden": true, + "order": 31, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263757, + "field_id": 60214, + "width": 149, + "hidden": true, + "order": 32, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263758, + "field_id": 60129, + "width": 222, + "hidden": true, + "order": 33, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263759, + "field_id": 60205, + "width": 200, + "hidden": true, + "order": 34, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263760, + "field_id": 60206, + "width": 200, + "hidden": true, + "order": 35, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263761, + "field_id": 60212, + "width": 200, + "hidden": true, + "order": 36, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263762, + "field_id": 60217, + "width": 263, + "hidden": true, + "order": 37, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263763, + "field_id": 60219, + "width": 200, + "hidden": true, + "order": 38, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263764, + "field_id": 60220, + "width": 258, + "hidden": true, + "order": 39, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263765, + "field_id": 60221, + "width": 200, + "hidden": true, + "order": 40, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263766, + "field_id": 60222, + "width": 200, + "hidden": true, + "order": 41, + "aggregation_type": "", + "aggregation_raw_type": "" + } + ] + }, + { + "id": 26633, + "type": "grid", + "name": "All employees: reviews and performance", + "order": 3, + "ownership_type": "collaborative", + "owned_by": "frederik@baserow.io", + "filter_type": "AND", + "filters_disabled": false, + "filters": [], + "filter_groups": [], + "sortings": [ + { + "id": 20520, + "field_id": 60111, + "order": "ASC" + } + ], + "group_bys": [], + "decorations": [], + "public": false, + "row_identifier_type": "id", + "row_height_size": "small", + "field_options": [ + { + "id": 263767, + "field_id": 60111, + "width": 166, + "hidden": false, + "order": 0, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263768, + "field_id": 60112, + "width": 250, + "hidden": true, + "order": 1, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263769, + "field_id": 60113, + "width": 132, + "hidden": true, + "order": 2, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263770, + "field_id": 60114, + "width": 115, + "hidden": true, + "order": 3, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263771, + "field_id": 60116, + "width": 200, + "hidden": false, + "order": 4, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263772, + "field_id": 60128, + "width": 200, + "hidden": true, + "order": 5, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263773, + "field_id": 60123, + "width": 129, + "hidden": true, + "order": 6, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263774, + "field_id": 60117, + "width": 200, + "hidden": true, + "order": 8, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263775, + "field_id": 60118, + "width": 130, + "hidden": true, + "order": 9, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263776, + "field_id": 60119, + "width": 150, + "hidden": true, + "order": 10, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263777, + "field_id": 60182, + "width": 181, + "hidden": true, + "order": 11, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263778, + "field_id": 60122, + "width": 134, + "hidden": true, + "order": 12, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263779, + "field_id": 60120, + "width": 157, + "hidden": true, + "order": 13, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263780, + "field_id": 60121, + "width": 130, + "hidden": true, + "order": 14, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263781, + "field_id": 60181, + "width": 128, + "hidden": false, + "order": 15, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263782, + "field_id": 60125, + "width": 249, + "hidden": false, + "order": 16, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263783, + "field_id": 60203, + "width": 150, + "hidden": false, + "order": 17, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263784, + "field_id": 60183, + "width": 134, + "hidden": false, + "order": 18, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263785, + "field_id": 60194, + "width": 138, + "hidden": false, + "order": 19, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263786, + "field_id": 60202, + "width": 146, + "hidden": false, + "order": 20, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263787, + "field_id": 60195, + "width": 173, + "hidden": false, + "order": 21, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263788, + "field_id": 60207, + "width": 193, + "hidden": false, + "order": 22, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263789, + "field_id": 60211, + "width": 208, + "hidden": false, + "order": 23, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263790, + "field_id": 60126, + "width": 200, + "hidden": false, + "order": 24, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263791, + "field_id": 60215, + "width": 251, + "hidden": false, + "order": 25, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263792, + "field_id": 60218, + "width": 242, + "hidden": false, + "order": 26, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263793, + "field_id": 60208, + "width": 152, + "hidden": false, + "order": 27, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263794, + "field_id": 60127, + "width": 188, + "hidden": false, + "order": 28, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263795, + "field_id": 60213, + "width": 228, + "hidden": false, + "order": 29, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263796, + "field_id": 60216, + "width": 227, + "hidden": false, + "order": 30, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263797, + "field_id": 60199, + "width": 133, + "hidden": false, + "order": 31, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263798, + "field_id": 60214, + "width": 149, + "hidden": false, + "order": 32, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263799, + "field_id": 60129, + "width": 222, + "hidden": false, + "order": 33, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263800, + "field_id": 60205, + "width": 200, + "hidden": true, + "order": 34, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263801, + "field_id": 60206, + "width": 200, + "hidden": true, + "order": 35, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263802, + "field_id": 60212, + "width": 200, + "hidden": true, + "order": 36, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263803, + "field_id": 60217, + "width": 263, + "hidden": false, + "order": 37, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263804, + "field_id": 60219, + "width": 200, + "hidden": true, + "order": 38, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263805, + "field_id": 60220, + "width": 258, + "hidden": false, + "order": 39, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263806, + "field_id": 60221, + "width": 200, + "hidden": true, + "order": 40, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263807, + "field_id": 60222, + "width": 200, + "hidden": true, + "order": 41, + "aggregation_type": "", + "aggregation_raw_type": "" + } + ] + }, + { + "id": 26634, + "type": "grid", + "name": "Needs performance review this year", + "order": 4, + "ownership_type": "collaborative", + "owned_by": "frederik@baserow.io", + "filter_type": "AND", + "filters_disabled": false, + "filters": [ + { + "id": 14032, + "field_id": 60202, + "type": "boolean", + "value": "1", + "group": null + } + ], + "filter_groups": [], + "sortings": [ + { + "id": 20521, + "field_id": 60111, + "order": "ASC" + } + ], + "group_bys": [], + "decorations": [], + "public": false, + "row_identifier_type": "id", + "row_height_size": "small", + "field_options": [ + { + "id": 263808, + "field_id": 60111, + "width": 166, + "hidden": false, + "order": 0, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263809, + "field_id": 60112, + "width": 250, + "hidden": false, + "order": 1, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263810, + "field_id": 60113, + "width": 132, + "hidden": false, + "order": 2, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263811, + "field_id": 60114, + "width": 115, + "hidden": false, + "order": 3, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263812, + "field_id": 60116, + "width": 200, + "hidden": false, + "order": 4, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263813, + "field_id": 60128, + "width": 200, + "hidden": false, + "order": 5, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263814, + "field_id": 60123, + "width": 129, + "hidden": false, + "order": 6, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263815, + "field_id": 60117, + "width": 200, + "hidden": false, + "order": 8, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263816, + "field_id": 60118, + "width": 130, + "hidden": false, + "order": 9, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263817, + "field_id": 60119, + "width": 150, + "hidden": false, + "order": 10, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263818, + "field_id": 60182, + "width": 181, + "hidden": false, + "order": 11, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263819, + "field_id": 60122, + "width": 134, + "hidden": false, + "order": 12, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263820, + "field_id": 60120, + "width": 157, + "hidden": false, + "order": 13, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263821, + "field_id": 60121, + "width": 130, + "hidden": false, + "order": 14, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263822, + "field_id": 60181, + "width": 128, + "hidden": false, + "order": 15, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263823, + "field_id": 60125, + "width": 249, + "hidden": false, + "order": 16, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263824, + "field_id": 60203, + "width": 150, + "hidden": false, + "order": 17, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263825, + "field_id": 60183, + "width": 134, + "hidden": false, + "order": 18, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263826, + "field_id": 60194, + "width": 138, + "hidden": false, + "order": 19, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263827, + "field_id": 60202, + "width": 146, + "hidden": false, + "order": 20, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263828, + "field_id": 60195, + "width": 173, + "hidden": false, + "order": 21, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263829, + "field_id": 60207, + "width": 193, + "hidden": false, + "order": 22, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263830, + "field_id": 60211, + "width": 208, + "hidden": false, + "order": 23, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263831, + "field_id": 60126, + "width": 200, + "hidden": false, + "order": 24, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263832, + "field_id": 60215, + "width": 251, + "hidden": false, + "order": 25, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263833, + "field_id": 60218, + "width": 242, + "hidden": false, + "order": 26, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263834, + "field_id": 60208, + "width": 152, + "hidden": false, + "order": 27, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263835, + "field_id": 60127, + "width": 188, + "hidden": false, + "order": 28, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263836, + "field_id": 60213, + "width": 228, + "hidden": false, + "order": 29, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263837, + "field_id": 60216, + "width": 227, + "hidden": false, + "order": 30, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263838, + "field_id": 60199, + "width": 133, + "hidden": false, + "order": 31, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263839, + "field_id": 60214, + "width": 149, + "hidden": false, + "order": 32, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263840, + "field_id": 60129, + "width": 222, + "hidden": false, + "order": 33, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263841, + "field_id": 60205, + "width": 200, + "hidden": true, + "order": 34, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263842, + "field_id": 60206, + "width": 200, + "hidden": true, + "order": 35, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263843, + "field_id": 60212, + "width": 200, + "hidden": true, + "order": 36, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263844, + "field_id": 60217, + "width": 263, + "hidden": false, + "order": 37, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263845, + "field_id": 60219, + "width": 200, + "hidden": true, + "order": 38, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263846, + "field_id": 60220, + "width": 258, + "hidden": false, + "order": 39, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263847, + "field_id": 60221, + "width": 200, + "hidden": true, + "order": 40, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263848, + "field_id": 60222, + "width": 200, + "hidden": true, + "order": 41, + "aggregation_type": "", + "aggregation_raw_type": "" + } + ] + }, + { + "id": 26635, + "type": "grid", + "name": "Needs potential assessment this year", + "order": 5, + "ownership_type": "collaborative", + "owned_by": "frederik@baserow.io", + "filter_type": "AND", + "filters_disabled": false, + "filters": [ + { + "id": 14033, + "field_id": 60218, + "type": "boolean", + "value": "1", + "group": null + } + ], + "filter_groups": [], + "sortings": [ + { + "id": 20522, + "field_id": 60111, + "order": "ASC" + } + ], + "group_bys": [], + "decorations": [], + "public": false, + "row_identifier_type": "id", + "row_height_size": "small", + "field_options": [ + { + "id": 263849, + "field_id": 60111, + "width": 166, + "hidden": false, + "order": 0, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263850, + "field_id": 60112, + "width": 250, + "hidden": false, + "order": 1, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263851, + "field_id": 60113, + "width": 132, + "hidden": false, + "order": 2, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263852, + "field_id": 60114, + "width": 115, + "hidden": false, + "order": 3, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263853, + "field_id": 60116, + "width": 200, + "hidden": false, + "order": 4, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263854, + "field_id": 60128, + "width": 200, + "hidden": false, + "order": 5, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263855, + "field_id": 60123, + "width": 129, + "hidden": false, + "order": 6, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263856, + "field_id": 60117, + "width": 200, + "hidden": false, + "order": 8, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263857, + "field_id": 60118, + "width": 130, + "hidden": false, + "order": 9, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263858, + "field_id": 60119, + "width": 150, + "hidden": false, + "order": 10, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263859, + "field_id": 60182, + "width": 181, + "hidden": false, + "order": 11, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263860, + "field_id": 60122, + "width": 134, + "hidden": false, + "order": 12, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263861, + "field_id": 60120, + "width": 157, + "hidden": false, + "order": 13, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263862, + "field_id": 60121, + "width": 130, + "hidden": false, + "order": 14, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263863, + "field_id": 60181, + "width": 128, + "hidden": false, + "order": 15, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263864, + "field_id": 60125, + "width": 249, + "hidden": false, + "order": 16, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263865, + "field_id": 60203, + "width": 150, + "hidden": false, + "order": 17, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263866, + "field_id": 60183, + "width": 134, + "hidden": false, + "order": 18, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263867, + "field_id": 60194, + "width": 138, + "hidden": false, + "order": 19, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263868, + "field_id": 60202, + "width": 146, + "hidden": false, + "order": 20, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263869, + "field_id": 60195, + "width": 173, + "hidden": false, + "order": 21, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263870, + "field_id": 60207, + "width": 193, + "hidden": false, + "order": 22, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263871, + "field_id": 60211, + "width": 208, + "hidden": false, + "order": 23, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263872, + "field_id": 60126, + "width": 200, + "hidden": false, + "order": 24, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263873, + "field_id": 60215, + "width": 251, + "hidden": false, + "order": 25, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263874, + "field_id": 60218, + "width": 242, + "hidden": false, + "order": 26, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263875, + "field_id": 60208, + "width": 152, + "hidden": false, + "order": 27, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263876, + "field_id": 60127, + "width": 188, + "hidden": false, + "order": 28, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263877, + "field_id": 60213, + "width": 228, + "hidden": false, + "order": 29, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263878, + "field_id": 60216, + "width": 227, + "hidden": false, + "order": 30, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263879, + "field_id": 60199, + "width": 133, + "hidden": false, + "order": 31, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263880, + "field_id": 60214, + "width": 149, + "hidden": false, + "order": 32, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263881, + "field_id": 60129, + "width": 222, + "hidden": false, + "order": 33, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263882, + "field_id": 60205, + "width": 200, + "hidden": true, + "order": 34, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263883, + "field_id": 60206, + "width": 200, + "hidden": true, + "order": 35, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263884, + "field_id": 60212, + "width": 200, + "hidden": true, + "order": 36, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263885, + "field_id": 60217, + "width": 263, + "hidden": false, + "order": 37, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263886, + "field_id": 60219, + "width": 200, + "hidden": true, + "order": 38, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263887, + "field_id": 60220, + "width": 258, + "hidden": false, + "order": 39, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263888, + "field_id": 60221, + "width": 200, + "hidden": true, + "order": 40, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263889, + "field_id": 60222, + "width": 200, + "hidden": true, + "order": 41, + "aggregation_type": "", + "aggregation_raw_type": "" + } + ] + }, + { + "id": 26638, + "type": "grid", + "name": "Has potential", + "order": 6, + "ownership_type": "collaborative", + "owned_by": "frederik@baserow.io", + "filter_type": "AND", + "filters_disabled": false, + "filters": [ + { + "id": 14036, + "field_id": 60208, + "type": "boolean", + "value": "1", + "group": null + } + ], + "filter_groups": [], + "sortings": [ + { + "id": 20525, + "field_id": 60111, + "order": "ASC" + } + ], + "group_bys": [], + "decorations": [], + "public": false, + "row_identifier_type": "id", + "row_height_size": "small", + "field_options": [ + { + "id": 263972, + "field_id": 60111, + "width": 166, + "hidden": false, + "order": 0, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263973, + "field_id": 60112, + "width": 250, + "hidden": false, + "order": 1, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263974, + "field_id": 60113, + "width": 132, + "hidden": false, + "order": 2, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263975, + "field_id": 60114, + "width": 115, + "hidden": false, + "order": 3, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263976, + "field_id": 60116, + "width": 200, + "hidden": false, + "order": 4, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263977, + "field_id": 60128, + "width": 200, + "hidden": false, + "order": 5, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263978, + "field_id": 60123, + "width": 129, + "hidden": false, + "order": 6, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263979, + "field_id": 60117, + "width": 200, + "hidden": false, + "order": 8, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263980, + "field_id": 60118, + "width": 130, + "hidden": false, + "order": 9, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263981, + "field_id": 60119, + "width": 150, + "hidden": false, + "order": 10, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263982, + "field_id": 60182, + "width": 181, + "hidden": false, + "order": 11, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263983, + "field_id": 60122, + "width": 134, + "hidden": false, + "order": 12, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263984, + "field_id": 60120, + "width": 157, + "hidden": false, + "order": 13, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263985, + "field_id": 60121, + "width": 130, + "hidden": false, + "order": 14, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263986, + "field_id": 60181, + "width": 128, + "hidden": false, + "order": 15, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263987, + "field_id": 60125, + "width": 249, + "hidden": false, + "order": 16, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263988, + "field_id": 60203, + "width": 150, + "hidden": false, + "order": 17, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263989, + "field_id": 60183, + "width": 134, + "hidden": false, + "order": 18, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263990, + "field_id": 60194, + "width": 138, + "hidden": false, + "order": 19, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263991, + "field_id": 60202, + "width": 146, + "hidden": false, + "order": 20, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263992, + "field_id": 60195, + "width": 173, + "hidden": false, + "order": 21, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263993, + "field_id": 60207, + "width": 193, + "hidden": false, + "order": 22, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263994, + "field_id": 60211, + "width": 208, + "hidden": false, + "order": 23, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263995, + "field_id": 60126, + "width": 200, + "hidden": false, + "order": 24, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263996, + "field_id": 60215, + "width": 251, + "hidden": false, + "order": 25, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263997, + "field_id": 60218, + "width": 242, + "hidden": false, + "order": 26, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263998, + "field_id": 60208, + "width": 152, + "hidden": false, + "order": 27, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263999, + "field_id": 60127, + "width": 188, + "hidden": false, + "order": 28, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264000, + "field_id": 60213, + "width": 228, + "hidden": false, + "order": 29, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264001, + "field_id": 60216, + "width": 227, + "hidden": false, + "order": 30, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264002, + "field_id": 60199, + "width": 133, + "hidden": false, + "order": 31, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264003, + "field_id": 60214, + "width": 149, + "hidden": false, + "order": 32, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264004, + "field_id": 60129, + "width": 222, + "hidden": false, + "order": 33, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264005, + "field_id": 60205, + "width": 200, + "hidden": true, + "order": 34, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264006, + "field_id": 60206, + "width": 200, + "hidden": true, + "order": 35, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264007, + "field_id": 60212, + "width": 200, + "hidden": true, + "order": 36, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264008, + "field_id": 60217, + "width": 263, + "hidden": false, + "order": 37, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264009, + "field_id": 60219, + "width": 200, + "hidden": true, + "order": 38, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264010, + "field_id": 60220, + "width": 258, + "hidden": false, + "order": 39, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264011, + "field_id": 60221, + "width": 200, + "hidden": true, + "order": 40, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264012, + "field_id": 60222, + "width": 200, + "hidden": true, + "order": 41, + "aggregation_type": "", + "aggregation_raw_type": "" + } + ] + }, + { + "id": 26636, + "type": "grid", + "name": "Needs ability assessment this year", + "order": 7, + "ownership_type": "collaborative", + "owned_by": "frederik@baserow.io", + "filter_type": "AND", + "filters_disabled": false, + "filters": [ + { + "id": 14034, + "field_id": 60216, + "type": "boolean", + "value": "1", + "group": null + } + ], + "filter_groups": [], + "sortings": [ + { + "id": 20523, + "field_id": 60111, + "order": "ASC" + } + ], + "group_bys": [], + "decorations": [], + "public": false, + "row_identifier_type": "id", + "row_height_size": "small", + "field_options": [ + { + "id": 263890, + "field_id": 60111, + "width": 166, + "hidden": false, + "order": 0, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263891, + "field_id": 60112, + "width": 250, + "hidden": false, + "order": 1, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263892, + "field_id": 60113, + "width": 132, + "hidden": false, + "order": 2, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263893, + "field_id": 60114, + "width": 115, + "hidden": false, + "order": 3, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263894, + "field_id": 60116, + "width": 200, + "hidden": false, + "order": 4, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263895, + "field_id": 60128, + "width": 200, + "hidden": false, + "order": 5, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263896, + "field_id": 60123, + "width": 129, + "hidden": false, + "order": 6, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263897, + "field_id": 60117, + "width": 200, + "hidden": false, + "order": 8, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263898, + "field_id": 60118, + "width": 130, + "hidden": false, + "order": 9, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263899, + "field_id": 60119, + "width": 150, + "hidden": false, + "order": 10, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263900, + "field_id": 60182, + "width": 181, + "hidden": false, + "order": 11, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263901, + "field_id": 60122, + "width": 134, + "hidden": false, + "order": 12, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263902, + "field_id": 60120, + "width": 157, + "hidden": false, + "order": 13, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263903, + "field_id": 60121, + "width": 130, + "hidden": false, + "order": 14, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263904, + "field_id": 60181, + "width": 128, + "hidden": false, + "order": 15, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263905, + "field_id": 60125, + "width": 249, + "hidden": false, + "order": 16, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263906, + "field_id": 60203, + "width": 150, + "hidden": false, + "order": 17, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263907, + "field_id": 60183, + "width": 134, + "hidden": false, + "order": 18, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263908, + "field_id": 60194, + "width": 138, + "hidden": false, + "order": 19, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263909, + "field_id": 60202, + "width": 146, + "hidden": false, + "order": 20, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263910, + "field_id": 60195, + "width": 173, + "hidden": false, + "order": 21, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263911, + "field_id": 60207, + "width": 193, + "hidden": false, + "order": 22, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263912, + "field_id": 60211, + "width": 208, + "hidden": false, + "order": 23, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263913, + "field_id": 60126, + "width": 200, + "hidden": false, + "order": 24, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263914, + "field_id": 60215, + "width": 251, + "hidden": false, + "order": 25, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263915, + "field_id": 60218, + "width": 242, + "hidden": false, + "order": 26, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263916, + "field_id": 60208, + "width": 152, + "hidden": false, + "order": 27, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263917, + "field_id": 60127, + "width": 188, + "hidden": false, + "order": 28, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263918, + "field_id": 60213, + "width": 228, + "hidden": false, + "order": 29, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263919, + "field_id": 60216, + "width": 227, + "hidden": false, + "order": 30, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263920, + "field_id": 60199, + "width": 133, + "hidden": false, + "order": 31, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263921, + "field_id": 60214, + "width": 149, + "hidden": false, + "order": 32, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263922, + "field_id": 60129, + "width": 222, + "hidden": false, + "order": 33, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263923, + "field_id": 60205, + "width": 200, + "hidden": true, + "order": 34, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263924, + "field_id": 60206, + "width": 200, + "hidden": true, + "order": 35, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263925, + "field_id": 60212, + "width": 200, + "hidden": true, + "order": 36, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263926, + "field_id": 60217, + "width": 263, + "hidden": false, + "order": 37, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263927, + "field_id": 60219, + "width": 200, + "hidden": true, + "order": 38, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263928, + "field_id": 60220, + "width": 258, + "hidden": false, + "order": 39, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263929, + "field_id": 60221, + "width": 200, + "hidden": true, + "order": 40, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263930, + "field_id": 60222, + "width": 200, + "hidden": true, + "order": 41, + "aggregation_type": "", + "aggregation_raw_type": "" + } + ] + }, + { + "id": 26637, + "type": "grid", + "name": "Has ability", + "order": 8, + "ownership_type": "collaborative", + "owned_by": "frederik@baserow.io", + "filter_type": "AND", + "filters_disabled": false, + "filters": [ + { + "id": 14035, + "field_id": 60199, + "type": "boolean", + "value": "1", + "group": null + } + ], + "filter_groups": [], + "sortings": [ + { + "id": 20524, + "field_id": 60111, + "order": "ASC" + } + ], + "group_bys": [], + "decorations": [], + "public": false, + "row_identifier_type": "id", + "row_height_size": "small", + "field_options": [ + { + "id": 263931, + "field_id": 60111, + "width": 166, + "hidden": false, + "order": 0, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263932, + "field_id": 60112, + "width": 250, + "hidden": false, + "order": 1, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263933, + "field_id": 60113, + "width": 132, + "hidden": false, + "order": 2, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263934, + "field_id": 60114, + "width": 115, + "hidden": false, + "order": 3, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263935, + "field_id": 60116, + "width": 200, + "hidden": false, + "order": 4, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263936, + "field_id": 60128, + "width": 200, + "hidden": false, + "order": 5, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263937, + "field_id": 60123, + "width": 129, + "hidden": false, + "order": 6, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263938, + "field_id": 60117, + "width": 200, + "hidden": false, + "order": 8, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263939, + "field_id": 60118, + "width": 130, + "hidden": false, + "order": 9, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263940, + "field_id": 60119, + "width": 150, + "hidden": false, + "order": 10, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263941, + "field_id": 60182, + "width": 181, + "hidden": false, + "order": 11, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263942, + "field_id": 60122, + "width": 134, + "hidden": false, + "order": 12, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263943, + "field_id": 60120, + "width": 157, + "hidden": false, + "order": 13, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263944, + "field_id": 60121, + "width": 130, + "hidden": false, + "order": 14, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263945, + "field_id": 60181, + "width": 128, + "hidden": false, + "order": 15, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263946, + "field_id": 60125, + "width": 249, + "hidden": false, + "order": 16, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263947, + "field_id": 60203, + "width": 150, + "hidden": false, + "order": 17, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263948, + "field_id": 60183, + "width": 134, + "hidden": false, + "order": 18, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263949, + "field_id": 60194, + "width": 138, + "hidden": false, + "order": 19, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263950, + "field_id": 60202, + "width": 146, + "hidden": false, + "order": 20, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263951, + "field_id": 60195, + "width": 173, + "hidden": false, + "order": 21, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263952, + "field_id": 60207, + "width": 193, + "hidden": false, + "order": 22, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263953, + "field_id": 60211, + "width": 208, + "hidden": false, + "order": 23, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263954, + "field_id": 60126, + "width": 200, + "hidden": false, + "order": 24, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263955, + "field_id": 60215, + "width": 251, + "hidden": false, + "order": 25, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263956, + "field_id": 60218, + "width": 242, + "hidden": false, + "order": 26, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263957, + "field_id": 60208, + "width": 152, + "hidden": false, + "order": 27, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263958, + "field_id": 60127, + "width": 188, + "hidden": false, + "order": 28, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263959, + "field_id": 60213, + "width": 228, + "hidden": false, + "order": 29, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263960, + "field_id": 60216, + "width": 227, + "hidden": false, + "order": 30, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263961, + "field_id": 60199, + "width": 133, + "hidden": false, + "order": 31, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263962, + "field_id": 60214, + "width": 149, + "hidden": false, + "order": 32, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263963, + "field_id": 60129, + "width": 222, + "hidden": false, + "order": 33, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263964, + "field_id": 60205, + "width": 200, + "hidden": true, + "order": 34, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263965, + "field_id": 60206, + "width": 200, + "hidden": true, + "order": 35, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263966, + "field_id": 60212, + "width": 200, + "hidden": true, + "order": 36, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263967, + "field_id": 60217, + "width": 263, + "hidden": false, + "order": 37, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263968, + "field_id": 60219, + "width": 200, + "hidden": true, + "order": 38, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263969, + "field_id": 60220, + "width": 258, + "hidden": false, + "order": 39, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263970, + "field_id": 60221, + "width": 200, + "hidden": true, + "order": 40, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263971, + "field_id": 60222, + "width": 200, + "hidden": true, + "order": 41, + "aggregation_type": "", + "aggregation_raw_type": "" + } + ] + }, + { + "id": 26639, + "type": "grid", + "name": "Category: Too Soon to Rate", + "order": 9, + "ownership_type": "collaborative", + "owned_by": "frederik@baserow.io", + "filter_type": "AND", + "filters_disabled": false, + "filters": [ + { + "id": 14037, + "field_id": 60214, + "type": "equal", + "value": "Too Soon to Rate", + "group": null + } + ], + "filter_groups": [], + "sortings": [ + { + "id": 20526, + "field_id": 60111, + "order": "ASC" + } + ], + "group_bys": [], + "decorations": [], + "public": false, + "row_identifier_type": "id", + "row_height_size": "small", + "field_options": [ + { + "id": 264013, + "field_id": 60111, + "width": 166, + "hidden": false, + "order": 0, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264014, + "field_id": 60112, + "width": 250, + "hidden": false, + "order": 1, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264015, + "field_id": 60113, + "width": 132, + "hidden": false, + "order": 2, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264016, + "field_id": 60114, + "width": 115, + "hidden": false, + "order": 3, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264017, + "field_id": 60116, + "width": 200, + "hidden": false, + "order": 4, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264018, + "field_id": 60128, + "width": 200, + "hidden": false, + "order": 5, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264019, + "field_id": 60123, + "width": 129, + "hidden": false, + "order": 6, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264020, + "field_id": 60117, + "width": 200, + "hidden": false, + "order": 8, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264021, + "field_id": 60118, + "width": 130, + "hidden": false, + "order": 9, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264022, + "field_id": 60119, + "width": 150, + "hidden": false, + "order": 10, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264023, + "field_id": 60182, + "width": 181, + "hidden": false, + "order": 11, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264024, + "field_id": 60122, + "width": 134, + "hidden": false, + "order": 12, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264025, + "field_id": 60120, + "width": 157, + "hidden": false, + "order": 13, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264026, + "field_id": 60121, + "width": 130, + "hidden": false, + "order": 14, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264027, + "field_id": 60181, + "width": 128, + "hidden": false, + "order": 15, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264028, + "field_id": 60125, + "width": 249, + "hidden": false, + "order": 16, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264029, + "field_id": 60203, + "width": 150, + "hidden": false, + "order": 17, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264030, + "field_id": 60183, + "width": 134, + "hidden": false, + "order": 18, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264031, + "field_id": 60194, + "width": 138, + "hidden": false, + "order": 19, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264032, + "field_id": 60202, + "width": 146, + "hidden": false, + "order": 20, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264033, + "field_id": 60195, + "width": 173, + "hidden": false, + "order": 21, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264034, + "field_id": 60207, + "width": 193, + "hidden": false, + "order": 22, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264035, + "field_id": 60211, + "width": 208, + "hidden": false, + "order": 23, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264036, + "field_id": 60126, + "width": 200, + "hidden": false, + "order": 24, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264037, + "field_id": 60215, + "width": 251, + "hidden": false, + "order": 25, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264038, + "field_id": 60218, + "width": 242, + "hidden": false, + "order": 26, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264039, + "field_id": 60208, + "width": 152, + "hidden": false, + "order": 27, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264040, + "field_id": 60127, + "width": 188, + "hidden": false, + "order": 28, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264041, + "field_id": 60213, + "width": 228, + "hidden": false, + "order": 29, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264042, + "field_id": 60216, + "width": 227, + "hidden": false, + "order": 30, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264043, + "field_id": 60199, + "width": 133, + "hidden": false, + "order": 31, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264044, + "field_id": 60214, + "width": 149, + "hidden": false, + "order": 32, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264045, + "field_id": 60129, + "width": 222, + "hidden": false, + "order": 33, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264046, + "field_id": 60205, + "width": 200, + "hidden": true, + "order": 34, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264047, + "field_id": 60206, + "width": 200, + "hidden": true, + "order": 35, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264048, + "field_id": 60212, + "width": 200, + "hidden": true, + "order": 36, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264049, + "field_id": 60217, + "width": 263, + "hidden": false, + "order": 37, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264050, + "field_id": 60219, + "width": 200, + "hidden": true, + "order": 38, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264051, + "field_id": 60220, + "width": 258, + "hidden": false, + "order": 39, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264052, + "field_id": 60221, + "width": 200, + "hidden": true, + "order": 40, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264053, + "field_id": 60222, + "width": 200, + "hidden": true, + "order": 41, + "aggregation_type": "", + "aggregation_raw_type": "" + } + ] + }, + { + "id": 26640, + "type": "grid", + "name": "Category: Improve", + "order": 10, + "ownership_type": "collaborative", + "owned_by": "frederik@baserow.io", + "filter_type": "AND", + "filters_disabled": false, + "filters": [ + { + "id": 14038, + "field_id": 60214, + "type": "equal", + "value": "Improve", + "group": null + } + ], + "filter_groups": [], + "sortings": [ + { + "id": 20527, + "field_id": 60111, + "order": "ASC" + } + ], + "group_bys": [], + "decorations": [], + "public": false, + "row_identifier_type": "id", + "row_height_size": "small", + "field_options": [ + { + "id": 264054, + "field_id": 60111, + "width": 166, + "hidden": false, + "order": 0, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264055, + "field_id": 60112, + "width": 250, + "hidden": false, + "order": 1, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264056, + "field_id": 60113, + "width": 132, + "hidden": false, + "order": 2, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264057, + "field_id": 60114, + "width": 115, + "hidden": false, + "order": 3, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264058, + "field_id": 60116, + "width": 200, + "hidden": false, + "order": 4, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264059, + "field_id": 60128, + "width": 200, + "hidden": false, + "order": 5, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264060, + "field_id": 60123, + "width": 129, + "hidden": false, + "order": 6, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264061, + "field_id": 60117, + "width": 200, + "hidden": false, + "order": 8, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264062, + "field_id": 60118, + "width": 130, + "hidden": false, + "order": 9, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264063, + "field_id": 60119, + "width": 150, + "hidden": false, + "order": 10, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264064, + "field_id": 60182, + "width": 181, + "hidden": false, + "order": 11, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264065, + "field_id": 60122, + "width": 134, + "hidden": false, + "order": 12, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264066, + "field_id": 60120, + "width": 157, + "hidden": false, + "order": 13, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264067, + "field_id": 60121, + "width": 130, + "hidden": false, + "order": 14, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264068, + "field_id": 60181, + "width": 128, + "hidden": false, + "order": 15, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264069, + "field_id": 60125, + "width": 249, + "hidden": false, + "order": 16, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264070, + "field_id": 60203, + "width": 150, + "hidden": false, + "order": 17, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264071, + "field_id": 60183, + "width": 134, + "hidden": false, + "order": 18, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264072, + "field_id": 60194, + "width": 138, + "hidden": false, + "order": 19, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264073, + "field_id": 60202, + "width": 146, + "hidden": false, + "order": 20, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264074, + "field_id": 60195, + "width": 173, + "hidden": false, + "order": 21, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264075, + "field_id": 60207, + "width": 193, + "hidden": false, + "order": 22, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264076, + "field_id": 60211, + "width": 208, + "hidden": false, + "order": 23, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264077, + "field_id": 60126, + "width": 200, + "hidden": false, + "order": 24, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264078, + "field_id": 60215, + "width": 251, + "hidden": false, + "order": 25, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264079, + "field_id": 60218, + "width": 242, + "hidden": false, + "order": 26, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264080, + "field_id": 60208, + "width": 152, + "hidden": false, + "order": 27, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264081, + "field_id": 60127, + "width": 188, + "hidden": false, + "order": 28, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264082, + "field_id": 60213, + "width": 228, + "hidden": false, + "order": 29, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264083, + "field_id": 60216, + "width": 227, + "hidden": false, + "order": 30, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264084, + "field_id": 60199, + "width": 133, + "hidden": false, + "order": 31, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264085, + "field_id": 60214, + "width": 149, + "hidden": false, + "order": 32, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264086, + "field_id": 60129, + "width": 222, + "hidden": false, + "order": 33, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264087, + "field_id": 60205, + "width": 200, + "hidden": true, + "order": 34, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264088, + "field_id": 60206, + "width": 200, + "hidden": true, + "order": 35, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264089, + "field_id": 60212, + "width": 200, + "hidden": true, + "order": 36, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264090, + "field_id": 60217, + "width": 263, + "hidden": false, + "order": 37, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264091, + "field_id": 60219, + "width": 200, + "hidden": true, + "order": 38, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264092, + "field_id": 60220, + "width": 258, + "hidden": false, + "order": 39, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264093, + "field_id": 60221, + "width": 200, + "hidden": true, + "order": 40, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264094, + "field_id": 60222, + "width": 200, + "hidden": true, + "order": 41, + "aggregation_type": "", + "aggregation_raw_type": "" + } + ] + }, + { + "id": 26641, + "type": "grid", + "name": "Category: Grow", + "order": 11, + "ownership_type": "collaborative", + "owned_by": "frederik@baserow.io", + "filter_type": "AND", + "filters_disabled": false, + "filters": [ + { + "id": 14039, + "field_id": 60214, + "type": "equal", + "value": "Grow", + "group": null + } + ], + "filter_groups": [], + "sortings": [ + { + "id": 20528, + "field_id": 60111, + "order": "ASC" + } + ], + "group_bys": [], + "decorations": [], + "public": false, + "row_identifier_type": "id", + "row_height_size": "small", + "field_options": [ + { + "id": 264095, + "field_id": 60111, + "width": 166, + "hidden": false, + "order": 0, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264096, + "field_id": 60112, + "width": 250, + "hidden": false, + "order": 1, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264097, + "field_id": 60113, + "width": 132, + "hidden": false, + "order": 2, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264098, + "field_id": 60114, + "width": 115, + "hidden": false, + "order": 3, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264099, + "field_id": 60116, + "width": 200, + "hidden": false, + "order": 4, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264100, + "field_id": 60128, + "width": 200, + "hidden": false, + "order": 5, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264101, + "field_id": 60123, + "width": 129, + "hidden": false, + "order": 6, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264102, + "field_id": 60117, + "width": 200, + "hidden": false, + "order": 8, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264103, + "field_id": 60118, + "width": 130, + "hidden": false, + "order": 9, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264104, + "field_id": 60119, + "width": 150, + "hidden": false, + "order": 10, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264105, + "field_id": 60182, + "width": 181, + "hidden": false, + "order": 11, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264106, + "field_id": 60122, + "width": 134, + "hidden": false, + "order": 12, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264107, + "field_id": 60120, + "width": 157, + "hidden": false, + "order": 13, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264108, + "field_id": 60121, + "width": 130, + "hidden": false, + "order": 14, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264109, + "field_id": 60181, + "width": 128, + "hidden": false, + "order": 15, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264110, + "field_id": 60125, + "width": 249, + "hidden": false, + "order": 16, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264111, + "field_id": 60203, + "width": 150, + "hidden": false, + "order": 17, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264112, + "field_id": 60183, + "width": 134, + "hidden": false, + "order": 18, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264113, + "field_id": 60194, + "width": 138, + "hidden": false, + "order": 19, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264114, + "field_id": 60202, + "width": 146, + "hidden": false, + "order": 20, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264115, + "field_id": 60195, + "width": 173, + "hidden": false, + "order": 21, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264116, + "field_id": 60207, + "width": 193, + "hidden": false, + "order": 22, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264117, + "field_id": 60211, + "width": 208, + "hidden": false, + "order": 23, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264118, + "field_id": 60126, + "width": 200, + "hidden": false, + "order": 24, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264119, + "field_id": 60215, + "width": 251, + "hidden": false, + "order": 25, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264120, + "field_id": 60218, + "width": 242, + "hidden": false, + "order": 26, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264121, + "field_id": 60208, + "width": 152, + "hidden": false, + "order": 27, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264122, + "field_id": 60127, + "width": 188, + "hidden": false, + "order": 28, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264123, + "field_id": 60213, + "width": 228, + "hidden": false, + "order": 29, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264124, + "field_id": 60216, + "width": 227, + "hidden": false, + "order": 30, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264125, + "field_id": 60199, + "width": 133, + "hidden": false, + "order": 31, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264126, + "field_id": 60214, + "width": 149, + "hidden": false, + "order": 32, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264127, + "field_id": 60129, + "width": 222, + "hidden": false, + "order": 33, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264128, + "field_id": 60205, + "width": 200, + "hidden": true, + "order": 34, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264129, + "field_id": 60206, + "width": 200, + "hidden": true, + "order": 35, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264130, + "field_id": 60212, + "width": 200, + "hidden": true, + "order": 36, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264131, + "field_id": 60217, + "width": 263, + "hidden": false, + "order": 37, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264132, + "field_id": 60219, + "width": 200, + "hidden": true, + "order": 38, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264133, + "field_id": 60220, + "width": 258, + "hidden": false, + "order": 39, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264134, + "field_id": 60221, + "width": 200, + "hidden": true, + "order": 40, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264135, + "field_id": 60222, + "width": 200, + "hidden": true, + "order": 41, + "aggregation_type": "", + "aggregation_raw_type": "" + } + ] + }, + { + "id": 26642, + "type": "grid", + "name": "Category: Accelerate", + "order": 12, + "ownership_type": "collaborative", + "owned_by": "frederik@baserow.io", + "filter_type": "AND", + "filters_disabled": false, + "filters": [ + { + "id": 14040, + "field_id": 60214, + "type": "equal", + "value": "Accelerate", + "group": null + } + ], + "filter_groups": [], + "sortings": [ + { + "id": 20529, + "field_id": 60111, + "order": "ASC" + } + ], + "group_bys": [], + "decorations": [], + "public": false, + "row_identifier_type": "id", + "row_height_size": "small", + "field_options": [ + { + "id": 264136, + "field_id": 60111, + "width": 166, + "hidden": false, + "order": 0, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264137, + "field_id": 60112, + "width": 250, + "hidden": false, + "order": 1, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264138, + "field_id": 60113, + "width": 132, + "hidden": false, + "order": 2, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264139, + "field_id": 60114, + "width": 115, + "hidden": false, + "order": 3, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264140, + "field_id": 60116, + "width": 200, + "hidden": false, + "order": 4, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264141, + "field_id": 60128, + "width": 200, + "hidden": false, + "order": 5, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264142, + "field_id": 60123, + "width": 129, + "hidden": false, + "order": 6, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264143, + "field_id": 60117, + "width": 200, + "hidden": false, + "order": 8, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264144, + "field_id": 60118, + "width": 130, + "hidden": false, + "order": 9, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264145, + "field_id": 60119, + "width": 150, + "hidden": false, + "order": 10, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264146, + "field_id": 60182, + "width": 181, + "hidden": false, + "order": 11, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264147, + "field_id": 60122, + "width": 134, + "hidden": false, + "order": 12, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264148, + "field_id": 60120, + "width": 157, + "hidden": false, + "order": 13, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264149, + "field_id": 60121, + "width": 130, + "hidden": false, + "order": 14, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264150, + "field_id": 60181, + "width": 128, + "hidden": false, + "order": 15, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264151, + "field_id": 60125, + "width": 249, + "hidden": false, + "order": 16, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264152, + "field_id": 60203, + "width": 150, + "hidden": false, + "order": 17, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264153, + "field_id": 60183, + "width": 134, + "hidden": false, + "order": 18, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264154, + "field_id": 60194, + "width": 138, + "hidden": false, + "order": 19, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264155, + "field_id": 60202, + "width": 146, + "hidden": false, + "order": 20, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264156, + "field_id": 60195, + "width": 173, + "hidden": false, + "order": 21, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264157, + "field_id": 60207, + "width": 193, + "hidden": false, + "order": 22, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264158, + "field_id": 60211, + "width": 208, + "hidden": false, + "order": 23, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264159, + "field_id": 60126, + "width": 200, + "hidden": false, + "order": 24, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264160, + "field_id": 60215, + "width": 251, + "hidden": false, + "order": 25, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264161, + "field_id": 60218, + "width": 242, + "hidden": false, + "order": 26, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264162, + "field_id": 60208, + "width": 152, + "hidden": false, + "order": 27, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264163, + "field_id": 60127, + "width": 188, + "hidden": false, + "order": 28, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264164, + "field_id": 60213, + "width": 228, + "hidden": false, + "order": 29, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264165, + "field_id": 60216, + "width": 227, + "hidden": false, + "order": 30, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264166, + "field_id": 60199, + "width": 133, + "hidden": false, + "order": 31, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264167, + "field_id": 60214, + "width": 149, + "hidden": false, + "order": 32, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264168, + "field_id": 60129, + "width": 222, + "hidden": false, + "order": 33, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264169, + "field_id": 60205, + "width": 200, + "hidden": true, + "order": 34, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264170, + "field_id": 60206, + "width": 200, + "hidden": true, + "order": 35, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264171, + "field_id": 60212, + "width": 200, + "hidden": true, + "order": 36, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264172, + "field_id": 60217, + "width": 263, + "hidden": false, + "order": 37, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264173, + "field_id": 60219, + "width": 200, + "hidden": true, + "order": 38, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264174, + "field_id": 60220, + "width": 258, + "hidden": false, + "order": 39, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264175, + "field_id": 60221, + "width": 200, + "hidden": true, + "order": 40, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264176, + "field_id": 60222, + "width": 200, + "hidden": true, + "order": 41, + "aggregation_type": "", + "aggregation_raw_type": "" + } + ] + }, + { + "id": 26622, + "type": "gallery", + "name": "Gallery: all employees", + "order": 13, + "ownership_type": "collaborative", + "owned_by": "frederik@baserow.io", + "filter_type": "AND", + "filters_disabled": false, + "filters": [], + "filter_groups": [], + "sortings": [], + "decorations": [], + "public": false, + "card_cover_image_field_id": 60114, + "field_options": [ + { + "id": 25603, + "field_id": 60111, + "hidden": false, + "order": 32767 + }, + { + "id": 25604, + "field_id": 60112, + "hidden": false, + "order": 32767 + }, + { + "id": 25605, + "field_id": 60113, + "hidden": false, + "order": 32767 + }, + { + "id": 25606, + "field_id": 60114, + "hidden": true, + "order": 32767 + }, + { + "id": 25608, + "field_id": 60116, + "hidden": false, + "order": 32767 + }, + { + "id": 25609, + "field_id": 60117, + "hidden": true, + "order": 32767 + }, + { + "id": 25610, + "field_id": 60118, + "hidden": true, + "order": 32767 + }, + { + "id": 25611, + "field_id": 60119, + "hidden": true, + "order": 32767 + }, + { + "id": 25612, + "field_id": 60120, + "hidden": true, + "order": 32767 + }, + { + "id": 25613, + "field_id": 60121, + "hidden": true, + "order": 32767 + }, + { + "id": 25614, + "field_id": 60122, + "hidden": true, + "order": 32767 + }, + { + "id": 25615, + "field_id": 60123, + "hidden": true, + "order": 32767 + }, + { + "id": 25619, + "field_id": 60181, + "hidden": true, + "order": 32767 + }, + { + "id": 25620, + "field_id": 60182, + "hidden": true, + "order": 32767 + } + ] + }, + { + "id": 26623, + "type": "calendar", + "name": "Birthday calendar", + "order": 14, + "ownership_type": "collaborative", + "owned_by": "frederik@baserow.io", + "filter_type": "AND", + "filters_disabled": false, + "filters": [], + "filter_groups": [], + "sortings": [], + "decorations": [], + "public": false, + "date_field_id": 60182, + "field_options": [ + { + "id": 12571, + "field_id": 60111, + "hidden": false, + "order": 32767 + }, + { + "id": 12572, + "field_id": 60112, + "hidden": true, + "order": 32767 + }, + { + "id": 12573, + "field_id": 60113, + "hidden": true, + "order": 32767 + }, + { + "id": 12574, + "field_id": 60114, + "hidden": true, + "order": 32767 + }, + { + "id": 12576, + "field_id": 60116, + "hidden": true, + "order": 32767 + }, + { + "id": 12577, + "field_id": 60117, + "hidden": true, + "order": 32767 + }, + { + "id": 12578, + "field_id": 60118, + "hidden": true, + "order": 32767 + }, + { + "id": 12579, + "field_id": 60119, + "hidden": true, + "order": 32767 + }, + { + "id": 12580, + "field_id": 60120, + "hidden": true, + "order": 32767 + }, + { + "id": 12581, + "field_id": 60121, + "hidden": true, + "order": 32767 + }, + { + "id": 12582, + "field_id": 60122, + "hidden": true, + "order": 32767 + }, + { + "id": 12583, + "field_id": 60123, + "hidden": true, + "order": 32767 + }, + { + "id": 12586, + "field_id": 60181, + "hidden": true, + "order": 32767 + }, + { + "id": 12587, + "field_id": 60182, + "hidden": true, + "order": 32767 + } + ] + }, + { + "id": 26624, + "type": "kanban", + "name": "All employees stacked by status", + "order": 15, + "ownership_type": "collaborative", + "owned_by": "frederik@baserow.io", + "filter_type": "AND", + "filters_disabled": false, + "filters": [], + "filter_groups": [], + "sortings": [], + "decorations": [], + "public": false, + "single_select_field_id": 60122, + "field_options": [ + { + "id": 35274, + "field_id": 60111, + "hidden": false, + "order": 1 + }, + { + "id": 35275, + "field_id": 60112, + "hidden": false, + "order": 2 + }, + { + "id": 35276, + "field_id": 60113, + "hidden": false, + "order": 3 + }, + { + "id": 35277, + "field_id": 60114, + "hidden": true, + "order": 4 + }, + { + "id": 35279, + "field_id": 60116, + "hidden": false, + "order": 7 + }, + { + "id": 35282, + "field_id": 60117, + "hidden": true, + "order": 10 + }, + { + "id": 35283, + "field_id": 60118, + "hidden": true, + "order": 11 + }, + { + "id": 35284, + "field_id": 60119, + "hidden": true, + "order": 12 + }, + { + "id": 35285, + "field_id": 60120, + "hidden": true, + "order": 14 + }, + { + "id": 35286, + "field_id": 60121, + "hidden": true, + "order": 15 + }, + { + "id": 35287, + "field_id": 60181, + "hidden": true, + "order": 16 + }, + { + "id": 35288, + "field_id": 60122, + "hidden": true, + "order": 17 + }, + { + "id": 35289, + "field_id": 60182, + "hidden": true, + "order": 18 + }, + { + "id": 35290, + "field_id": 60123, + "hidden": true, + "order": 19 + }, + { + "id": 35291, + "field_id": 60125, + "hidden": true, + "order": 32767 + }, + { + "id": 35297, + "field_id": 60126, + "hidden": true, + "order": 32767 + }, + { + "id": 35299, + "field_id": 60127, + "hidden": true, + "order": 32767 + }, + { + "id": 35302, + "field_id": 60128, + "hidden": true, + "order": 32767 + }, + { + "id": 35314, + "field_id": 60129, + "hidden": true, + "order": 32767 + }, + { + "id": 35296, + "field_id": 60183, + "hidden": true, + "order": 32767 + }, + { + "id": 35305, + "field_id": 60194, + "hidden": true, + "order": 32767 + }, + { + "id": 35293, + "field_id": 60195, + "hidden": true, + "order": 32767 + }, + { + "id": 35300, + "field_id": 60199, + "hidden": true, + "order": 32767 + }, + { + "id": 35308, + "field_id": 60202, + "hidden": true, + "order": 32767 + }, + { + "id": 35292, + "field_id": 60203, + "hidden": true, + "order": 32767 + }, + { + "id": 35304, + "field_id": 60205, + "hidden": true, + "order": 32767 + }, + { + "id": 35306, + "field_id": 60206, + "hidden": true, + "order": 32767 + }, + { + "id": 35294, + "field_id": 60207, + "hidden": true, + "order": 32767 + }, + { + "id": 35298, + "field_id": 60208, + "hidden": true, + "order": 32767 + }, + { + "id": 35295, + "field_id": 60211, + "hidden": true, + "order": 32767 + }, + { + "id": 35303, + "field_id": 60212, + "hidden": true, + "order": 32767 + }, + { + "id": 35311, + "field_id": 60213, + "hidden": true, + "order": 32767 + }, + { + "id": 35301, + "field_id": 60214, + "hidden": true, + "order": 32767 + }, + { + "id": 35307, + "field_id": 60215, + "hidden": true, + "order": 32767 + }, + { + "id": 35312, + "field_id": 60216, + "hidden": true, + "order": 32767 + }, + { + "id": 35315, + "field_id": 60217, + "hidden": true, + "order": 32767 + }, + { + "id": 35309, + "field_id": 60218, + "hidden": true, + "order": 32767 + }, + { + "id": 35313, + "field_id": 60219, + "hidden": true, + "order": 32767 + }, + { + "id": 35316, + "field_id": 60220, + "hidden": true, + "order": 32767 + }, + { + "id": 35310, + "field_id": 60221, + "hidden": true, + "order": 32767 + }, + { + "id": 35317, + "field_id": 60222, + "hidden": true, + "order": 32767 + } + ] + } + ], + "rows": [ + { + "id": 1, + "order": "1.00000000000000000000", + "created_on": "2024-10-21T11:20:15.182140+00:00", + "updated_on": "2025-02-18T10:47:45.251189+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60111": "Allie Ecker", + "field_60112": "allie.ecker@example.com", + "field_60113": "(949) 873-7292", + "field_60114": [ + { + "name": "kxKGRTtKA1xgLFDzn6eKKtwZH2zsExh2_87342f8e2a009873f0cf6cbf8b480d495c898a19238d60b3d6fb81efa41c9883.jpg", + "visible_name": "Woman.12.jpg", + "original_name": "kxKGRTtKA1xgLFDzn6eKKtwZH2zsExh2_87342f8e2a009873f0cf6cbf8b480d495c898a19238d60b3d6fb81efa41c9883.jpg" + } + ], + "field_60116": "People manager", + "field_60117": "3380 Park Avenue, Elk Grove, California", + "field_60118": "95624", + "field_60119": "1975-05-26", + "field_60120": "2012-01-08", + "field_60121": null, + "field_60181": null, + "field_60122": 21146, + "field_60182": null, + "field_60123": [], + "field_60125": [], + "field_60203": null, + "field_60195": null, + "field_60207": null, + "field_60211": null, + "field_60183": null, + "field_60126": [], + "field_60208": null, + "field_60127": [], + "field_60199": null, + "field_60214": null, + "field_60128": "pbkdf2_sha256$720000$USySlmgHbkWuUUYJaDbChR$G3Sjg7vYkvMor0Ya0QxNREINXWCFSgo2wkaAibrl8is=", + "field_60212": null, + "field_60205": null, + "field_60194": null, + "field_60206": null, + "field_60215": null, + "field_60202": null, + "field_60218": null, + "field_60221": null, + "field_60213": null, + "field_60216": null, + "field_60219": null, + "field_60129": [], + "field_60217": null, + "field_60220": null, + "field_60222": null + }, + { + "id": 2, + "order": "2.00000000000000000000", + "created_on": "2024-10-21T11:20:15.182196+00:00", + "updated_on": "2025-02-18T10:47:46.810010+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60111": "Bran Lopez", + "field_60112": "bran.lopez@example.com", + "field_60113": "(650) 869-3623", + "field_60114": [ + { + "name": "hwWiVjQfxJ3rcQtPlCjaiTszydWJSZbR_d022b4d76cc31161673cb1f62b4d1984dc8db57d5d7b62b46ff73de4fde45cfd.jpg", + "visible_name": "Man.20.jpg", + "original_name": "hwWiVjQfxJ3rcQtPlCjaiTszydWJSZbR_d022b4d76cc31161673cb1f62b4d1984dc8db57d5d7b62b46ff73de4fde45cfd.jpg" + } + ], + "field_60116": "People manager", + "field_60117": "2014 Alpaca Way, Brea, California", + "field_60118": "92621", + "field_60119": "1989-09-23", + "field_60120": "2012-01-31", + "field_60121": null, + "field_60181": null, + "field_60122": 21146, + "field_60182": null, + "field_60123": [], + "field_60125": [], + "field_60203": null, + "field_60195": null, + "field_60207": null, + "field_60211": null, + "field_60183": null, + "field_60126": [], + "field_60208": null, + "field_60127": [], + "field_60199": null, + "field_60214": null, + "field_60128": "pbkdf2_sha256$720000$XrI0Ky3lmUSVUoMTZ1GBMS$1ULP95PU8JYumsYvOKyOrZ4azEwp2AktLe3mPzgJ2mY=", + "field_60212": null, + "field_60205": null, + "field_60194": null, + "field_60206": null, + "field_60215": null, + "field_60202": null, + "field_60218": null, + "field_60221": null, + "field_60213": null, + "field_60216": null, + "field_60219": null, + "field_60129": [], + "field_60217": null, + "field_60220": null, + "field_60222": null + }, + { + "id": 3, + "order": "3.00000000000000000000", + "created_on": "2024-10-21T11:21:39.820984+00:00", + "updated_on": "2025-02-18T10:47:48.329698+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60111": "Cinda Pullen", + "field_60112": "cinda.pullen@example.com", + "field_60113": "(213) 743-1636", + "field_60114": [ + { + "name": "s9JEDin0ovWKdly0AErA1ewEmoWUU2G2_32a0bb1e8cd43f9a27f05e95039ad44b606915d94c3f6ac8aa9359a5d66d0e40.jpg", + "visible_name": "Woman.36.jpg", + "original_name": "s9JEDin0ovWKdly0AErA1ewEmoWUU2G2_32a0bb1e8cd43f9a27f05e95039ad44b606915d94c3f6ac8aa9359a5d66d0e40.jpg" + } + ], + "field_60116": "People manager", + "field_60117": "1609 Hillhaven Drive, Los Angeles, California", + "field_60118": "90036", + "field_60119": "1999-10-17", + "field_60120": "2019-07-30", + "field_60121": null, + "field_60181": null, + "field_60122": 21146, + "field_60182": null, + "field_60123": [], + "field_60125": [], + "field_60203": null, + "field_60195": null, + "field_60207": null, + "field_60211": null, + "field_60183": null, + "field_60126": [], + "field_60208": null, + "field_60127": [], + "field_60199": null, + "field_60214": null, + "field_60128": "pbkdf2_sha256$720000$6LdwnSx8C1EMAs1x0vFwL8$kna0mZm/5pIKo/WLg6WpmqP9siD9RclGhoE2uvqGiQQ=", + "field_60212": null, + "field_60205": null, + "field_60194": null, + "field_60206": null, + "field_60215": null, + "field_60202": null, + "field_60218": null, + "field_60221": null, + "field_60213": null, + "field_60216": null, + "field_60219": null, + "field_60129": [], + "field_60217": null, + "field_60220": null, + "field_60222": null + }, + { + "id": 4, + "order": "4.00000000000000000000", + "created_on": "2024-10-21T11:21:39.821058+00:00", + "updated_on": "2025-02-18T10:47:50.064869+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60111": "Clayton Best", + "field_60112": "clayton.best@example.com", + "field_60113": "(916) 478-0153", + "field_60114": [ + { + "name": "EQGS7ZdOrEU1WNv3HXhdNeby3oZsvKJM_636d58571a3d01fad628780775449b7c9fe67e40a5d2154ffeed3cccec5bd2f0.jpg", + "visible_name": "Man.33.jpg", + "original_name": "EQGS7ZdOrEU1WNv3HXhdNeby3oZsvKJM_636d58571a3d01fad628780775449b7c9fe67e40a5d2154ffeed3cccec5bd2f0.jpg" + } + ], + "field_60116": "People manager", + "field_60117": "902 Park Street, San Francisco, California", + "field_60118": "94108", + "field_60119": "1998-09-10", + "field_60120": "2020-01-30", + "field_60121": null, + "field_60181": null, + "field_60122": 21146, + "field_60182": null, + "field_60123": [], + "field_60125": [], + "field_60203": null, + "field_60195": null, + "field_60207": null, + "field_60211": null, + "field_60183": null, + "field_60126": [], + "field_60208": null, + "field_60127": [], + "field_60199": null, + "field_60214": null, + "field_60128": "pbkdf2_sha256$720000$Uaj3L10rlxkTB0pmJhFezU$6lEaa7XNn4bh2GzOIJIGS6I/zWTikrzaOm+ls3/KN/w=", + "field_60212": null, + "field_60205": null, + "field_60194": null, + "field_60206": null, + "field_60215": null, + "field_60202": null, + "field_60218": null, + "field_60221": null, + "field_60213": null, + "field_60216": null, + "field_60219": null, + "field_60129": [], + "field_60217": null, + "field_60220": null, + "field_60222": null + }, + { + "id": 5, + "order": "5.00000000000000000000", + "created_on": "2024-10-21T11:21:39.821106+00:00", + "updated_on": "2025-02-18T10:47:51.918191+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60111": "Donald Johns", + "field_60112": "donald.johns@example.com", + "field_60113": "(805) 367-1199", + "field_60114": [ + { + "name": "3jnfFatES4EztJzjjAApSxbW8JliNuD3_8bf30a876d0d0082aac1b41058c42c8ff2ab323e25afc56b9f5b9bab76cf3ea9.jpg", + "visible_name": "Man.48.jpg", + "original_name": "3jnfFatES4EztJzjjAApSxbW8JliNuD3_8bf30a876d0d0082aac1b41058c42c8ff2ab323e25afc56b9f5b9bab76cf3ea9.jpg" + } + ], + "field_60116": "People manager", + "field_60117": "1522 Hillcrest Lane, Los Angeles, California", + "field_60118": "90017", + "field_60119": "2001-01-03", + "field_60120": "2012-01-08", + "field_60121": null, + "field_60181": null, + "field_60122": 21146, + "field_60182": null, + "field_60123": [], + "field_60125": [], + "field_60203": null, + "field_60195": null, + "field_60207": null, + "field_60211": null, + "field_60183": null, + "field_60126": [], + "field_60208": null, + "field_60127": [], + "field_60199": null, + "field_60214": null, + "field_60128": "pbkdf2_sha256$720000$xxN9ou7LSLL7CicKk006AO$aY8JlVpwvFJJKIXXMbQY8Hk2awrb2bL42rRyHgMCkjQ=", + "field_60212": null, + "field_60205": null, + "field_60194": null, + "field_60206": null, + "field_60215": null, + "field_60202": null, + "field_60218": null, + "field_60221": null, + "field_60213": null, + "field_60216": null, + "field_60219": null, + "field_60129": [], + "field_60217": null, + "field_60220": null, + "field_60222": null + }, + { + "id": 6, + "order": "6.00000000000000000000", + "created_on": "2024-10-21T11:21:39.821150+00:00", + "updated_on": "2024-11-05T12:23:54.682065+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60111": "Donald Wright", + "field_60112": "donald.wright@example.com", + "field_60113": "(925) 413-4033", + "field_60114": [ + { + "name": "BlysszbZR5iZlRaae6HYtlOB26xTQBme_706cb9712f46ff3654d0a1b873f9d20934da457ae1545f1bfdcfcc4f75c4f0fa.jpg", + "visible_name": "Man.09.jpg", + "original_name": "BlysszbZR5iZlRaae6HYtlOB26xTQBme_706cb9712f46ff3654d0a1b873f9d20934da457ae1545f1bfdcfcc4f75c4f0fa.jpg" + } + ], + "field_60116": "Recruitment Specialist", + "field_60117": "1053 Thompson Drive, Union City, California", + "field_60118": "94587", + "field_60119": "1970-01-07", + "field_60120": "2012-01-08", + "field_60121": null, + "field_60181": null, + "field_60122": 21146, + "field_60182": null, + "field_60123": [ + 1 + ], + "field_60125": [ + 22 + ], + "field_60203": null, + "field_60195": null, + "field_60207": null, + "field_60211": null, + "field_60183": null, + "field_60126": [ + 8 + ], + "field_60208": null, + "field_60127": [], + "field_60199": null, + "field_60214": null, + "field_60128": null, + "field_60212": null, + "field_60205": null, + "field_60194": null, + "field_60206": null, + "field_60215": null, + "field_60202": null, + "field_60218": null, + "field_60221": null, + "field_60213": null, + "field_60216": null, + "field_60219": null, + "field_60129": [], + "field_60217": null, + "field_60220": null, + "field_60222": null + }, + { + "id": 7, + "order": "7.00000000000000000000", + "created_on": "2024-10-21T11:21:39.821194+00:00", + "updated_on": "2024-11-05T12:23:56.643943+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60111": "Elizabeth Cunningham", + "field_60112": "elizabeth.cunningham@example.com", + "field_60113": "(323) 930-9329", + "field_60114": [ + { + "name": "L2YN0dAB7Ibkz45TUSuhuUjA25UNHqMY_6ad39d6d65565870ad02632ebc8f3103ef36c0004f787bc43df882383912bcf1.jpg", + "visible_name": "Woman.27.jpg", + "original_name": "L2YN0dAB7Ibkz45TUSuhuUjA25UNHqMY_6ad39d6d65565870ad02632ebc8f3103ef36c0004f787bc43df882383912bcf1.jpg" + } + ], + "field_60116": "Talent Acquisition Manager", + "field_60117": "4695 Woodland Terrace, Sacramento, California", + "field_60118": "95814", + "field_60119": "1977-07-05", + "field_60120": "2012-01-08", + "field_60121": null, + "field_60181": null, + "field_60122": 21147, + "field_60182": null, + "field_60123": [ + 1 + ], + "field_60125": [ + 19 + ], + "field_60203": null, + "field_60195": null, + "field_60207": null, + "field_60211": null, + "field_60183": null, + "field_60126": [ + 5 + ], + "field_60208": null, + "field_60127": [ + 3 + ], + "field_60199": null, + "field_60214": null, + "field_60128": null, + "field_60212": null, + "field_60205": null, + "field_60194": null, + "field_60206": null, + "field_60215": null, + "field_60202": null, + "field_60218": null, + "field_60221": null, + "field_60213": null, + "field_60216": null, + "field_60219": null, + "field_60129": [ + 2 + ], + "field_60217": null, + "field_60220": null, + "field_60222": null + }, + { + "id": 8, + "order": "8.00000000000000000000", + "created_on": "2024-10-21T11:21:39.821237+00:00", + "updated_on": "2024-11-05T12:23:58.226774+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60111": "Eric Rothman", + "field_60112": "eric.rothman@example.com", + "field_60113": "(619) 525-2361", + "field_60114": [ + { + "name": "vIBYnrW1Rj6qHQRkmNnIzdixixPP8Xbq_e2ad95f8dcb90def82b6c29a01416e1eafe86b21f119b8539a4fad35ee05b676.jpg", + "visible_name": "Man.15.jpg", + "original_name": "vIBYnrW1Rj6qHQRkmNnIzdixixPP8Xbq_e2ad95f8dcb90def82b6c29a01416e1eafe86b21f119b8539a4fad35ee05b676.jpg" + } + ], + "field_60116": "Training Coordinator", + "field_60117": "2400 Half and Half Drive, Alpaugh, California", + "field_60118": "93219", + "field_60119": "1998-06-20", + "field_60120": "2019-07-30", + "field_60121": null, + "field_60181": null, + "field_60122": 21148, + "field_60182": null, + "field_60123": [ + 1 + ], + "field_60125": [], + "field_60203": null, + "field_60195": null, + "field_60207": null, + "field_60211": null, + "field_60183": null, + "field_60126": [], + "field_60208": null, + "field_60127": [], + "field_60199": null, + "field_60214": null, + "field_60128": null, + "field_60212": null, + "field_60205": null, + "field_60194": null, + "field_60206": null, + "field_60215": null, + "field_60202": null, + "field_60218": null, + "field_60221": null, + "field_60213": null, + "field_60216": null, + "field_60219": null, + "field_60129": [], + "field_60217": null, + "field_60220": null, + "field_60222": null + }, + { + "id": 9, + "order": "9.00000000000000000000", + "created_on": "2024-10-21T11:21:39.821280+00:00", + "updated_on": "2025-02-18T11:53:11.837011+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60111": "Jane Dradder", + "field_60112": "jane.rudder@example.com", + "field_60113": "(720) 555-2389", + "field_60114": [ + { + "name": "0VXv789rzdpCsIyOibvarn6MsOdLpxXi_4be2f64cec3e3d83bcf84510216161f08e6181441413cfbdbdb69c11168e5434.jpg", + "visible_name": "Woman.02.jpg", + "original_name": "0VXv789rzdpCsIyOibvarn6MsOdLpxXi_4be2f64cec3e3d83bcf84510216161f08e6181441413cfbdbdb69c11168e5434.jpg" + } + ], + "field_60116": "Learning & Development Manager", + "field_60117": "414 Euclid Avenue, Oxnard, California", + "field_60118": "93030", + "field_60119": "1962-10-15", + "field_60120": "2021-01-31", + "field_60121": null, + "field_60181": null, + "field_60122": 21148, + "field_60182": null, + "field_60123": [ + 1 + ], + "field_60125": [ + 1, + 2, + 3, + 4, + 21 + ], + "field_60203": null, + "field_60195": null, + "field_60207": null, + "field_60211": null, + "field_60183": null, + "field_60126": [ + 1, + 7 + ], + "field_60208": null, + "field_60127": [ + 1, + 5 + ], + "field_60199": null, + "field_60214": null, + "field_60128": null, + "field_60212": null, + "field_60205": null, + "field_60194": null, + "field_60206": null, + "field_60215": null, + "field_60202": null, + "field_60218": null, + "field_60221": null, + "field_60213": null, + "field_60216": null, + "field_60219": null, + "field_60129": [ + 1, + 4 + ], + "field_60217": null, + "field_60220": null, + "field_60222": null + }, + { + "id": 10, + "order": "10.00000000000000000000", + "created_on": "2024-10-21T11:21:39.821337+00:00", + "updated_on": "2025-02-18T11:53:10.539101+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60111": "Janice Fitzpatrick", + "field_60112": "janice.fitzpatrick@example.com", + "field_60113": "(510) 476-1189", + "field_60114": [ + { + "name": "MIMtJhmzR6k5A6IGNG3AkBzu45ZVSKuu_6033c389c7b9a28b3f4d1ad791cd071bb18d341fb50ca862338d0688129b1d93.jpg", + "visible_name": "Woman.16.jpg", + "original_name": "MIMtJhmzR6k5A6IGNG3AkBzu45ZVSKuu_6033c389c7b9a28b3f4d1ad791cd071bb18d341fb50ca862338d0688129b1d93.jpg" + } + ], + "field_60116": "Accounts Payable Clerk", + "field_60117": "3637 Duck Creek Road, San Bruno, California", + "field_60118": "94066", + "field_60119": "1986-07-21", + "field_60120": "2019-07-30", + "field_60121": "2022-07-31", + "field_60181": null, + "field_60122": 21147, + "field_60182": null, + "field_60123": [ + 2 + ], + "field_60125": [ + 23 + ], + "field_60203": null, + "field_60195": null, + "field_60207": null, + "field_60211": null, + "field_60183": null, + "field_60126": [ + 9 + ], + "field_60208": null, + "field_60127": [ + 6 + ], + "field_60199": null, + "field_60214": null, + "field_60128": null, + "field_60212": null, + "field_60205": null, + "field_60194": null, + "field_60206": null, + "field_60215": null, + "field_60202": null, + "field_60218": null, + "field_60221": null, + "field_60213": null, + "field_60216": null, + "field_60219": null, + "field_60129": [ + 5 + ], + "field_60217": null, + "field_60220": null, + "field_60222": null + }, + { + "id": 11, + "order": "11.00000000000000000000", + "created_on": "2024-10-21T11:21:39.821385+00:00", + "updated_on": "2024-11-05T12:24:02.986526+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60111": "John Marshall", + "field_60112": "john.marshall@example.com", + "field_60113": "(323) 207-7576", + "field_60114": [ + { + "name": "PlYcEYbeXxFZzAt36QJiJstKmbJWmTRt_5b771a1ce64c7ccb1b909d679a9a9cab06d2563777570d6990b609608a526283.jpg", + "visible_name": "Man.03.jpg", + "original_name": "PlYcEYbeXxFZzAt36QJiJstKmbJWmTRt_5b771a1ce64c7ccb1b909d679a9a9cab06d2563777570d6990b609608a526283.jpg" + } + ], + "field_60116": "Senior Accountant", + "field_60117": "3294 Chicago Avenue, Exeter, California", + "field_60118": "93221", + "field_60119": "2001-06-12", + "field_60120": "2019-07-30", + "field_60121": null, + "field_60181": null, + "field_60122": 21149, + "field_60182": null, + "field_60123": [ + 2 + ], + "field_60125": [ + 20 + ], + "field_60203": null, + "field_60195": null, + "field_60207": null, + "field_60211": null, + "field_60183": null, + "field_60126": [ + 6 + ], + "field_60208": null, + "field_60127": [ + 4 + ], + "field_60199": null, + "field_60214": null, + "field_60128": null, + "field_60212": null, + "field_60205": null, + "field_60194": null, + "field_60206": null, + "field_60215": null, + "field_60202": null, + "field_60218": null, + "field_60221": null, + "field_60213": null, + "field_60216": null, + "field_60219": null, + "field_60129": [ + 3 + ], + "field_60217": null, + "field_60220": null, + "field_60222": null + }, + { + "id": 12, + "order": "12.00000000000000000000", + "created_on": "2024-10-21T11:21:39.821429+00:00", + "updated_on": "2024-11-05T12:24:04.520273+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60111": "Jonathan Castillo", + "field_60112": "jonathan.castillo@example.com", + "field_60113": "(714) 674-5259", + "field_60114": [ + { + "name": "P5kvW6AMB0sD5mPulsMqcX7rjqXvNct1_3e4ea491bc171831d98bd16209e167056256efec656b03792cc985f56c52d625.jpg", + "visible_name": "Man.27.jpg", + "original_name": "P5kvW6AMB0sD5mPulsMqcX7rjqXvNct1_3e4ea491bc171831d98bd16209e167056256efec656b03792cc985f56c52d625.jpg" + } + ], + "field_60116": "Treasury Analyst", + "field_60117": "1669 Water Street, Dublin, California", + "field_60118": "94568", + "field_60119": "1970-09-14", + "field_60120": "2012-01-08", + "field_60121": null, + "field_60181": null, + "field_60122": 21146, + "field_60182": null, + "field_60123": [ + 2 + ], + "field_60125": [ + 5, + 8, + 11, + 14 + ], + "field_60203": null, + "field_60195": null, + "field_60207": null, + "field_60211": null, + "field_60183": null, + "field_60126": [], + "field_60208": null, + "field_60127": [], + "field_60199": null, + "field_60214": null, + "field_60128": null, + "field_60212": null, + "field_60205": null, + "field_60194": null, + "field_60206": null, + "field_60215": null, + "field_60202": null, + "field_60218": null, + "field_60221": null, + "field_60213": null, + "field_60216": null, + "field_60219": null, + "field_60129": [], + "field_60217": null, + "field_60220": null, + "field_60222": null + }, + { + "id": 13, + "order": "13.00000000000000000000", + "created_on": "2024-10-21T11:21:39.821473+00:00", + "updated_on": "2024-11-05T12:24:06.156206+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60111": "Judith Triplett", + "field_60112": "judith.triplett@example.com", + "field_60113": "(323) 762-0628", + "field_60114": [ + { + "name": "QEOXBNmUlWB6c3dTyxdvudsvmYiw3nik_84455edcdf85e5bbcf4ea2c2e53253a70d2dc5003170a2bcb7adb2e06d319885.jpg", + "visible_name": "Woman.38.jpg", + "original_name": "QEOXBNmUlWB6c3dTyxdvudsvmYiw3nik_84455edcdf85e5bbcf4ea2c2e53253a70d2dc5003170a2bcb7adb2e06d319885.jpg" + } + ], + "field_60116": "Systems Administrator", + "field_60117": "1028 Rosemont Avenue, Anaheim, California", + "field_60118": "92801", + "field_60119": "1974-07-16", + "field_60120": "2012-01-31", + "field_60121": "2016-10-06", + "field_60181": null, + "field_60122": 21149, + "field_60182": null, + "field_60123": [ + 3 + ], + "field_60125": [ + 17 + ], + "field_60203": null, + "field_60195": null, + "field_60207": null, + "field_60211": null, + "field_60183": null, + "field_60126": [], + "field_60208": null, + "field_60127": [], + "field_60199": null, + "field_60214": null, + "field_60128": null, + "field_60212": null, + "field_60205": null, + "field_60194": null, + "field_60206": null, + "field_60215": null, + "field_60202": null, + "field_60218": null, + "field_60221": null, + "field_60213": null, + "field_60216": null, + "field_60219": null, + "field_60129": [], + "field_60217": null, + "field_60220": null, + "field_60222": null + }, + { + "id": 14, + "order": "14.00000000000000000000", + "created_on": "2024-10-21T11:21:39.821516+00:00", + "updated_on": "2025-02-18T16:09:46.299474+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60111": "Lane Mahon", + "field_60112": "lane.mahon@example.com", + "field_60113": "(925) 250-4627", + "field_60114": [ + { + "name": "h1ZodzpTOeI86idsJnItM1yN5Mwsg8nc_7d55a7f32efd179a5dd35d905c33a80528c84e057c8c6ad07a6f190fd8a135b8.jpg", + "visible_name": "Man.18.jpg", + "original_name": "h1ZodzpTOeI86idsJnItM1yN5Mwsg8nc_7d55a7f32efd179a5dd35d905c33a80528c84e057c8c6ad07a6f190fd8a135b8.jpg" + } + ], + "field_60116": "IT Security Analyst", + "field_60117": "4381 Hill Croft Farm Road, Chico, California", + "field_60118": "95926", + "field_60119": "1997-05-10", + "field_60120": "2019-07-30", + "field_60121": null, + "field_60181": null, + "field_60122": 21146, + "field_60182": null, + "field_60123": [ + 3 + ], + "field_60125": [ + 6, + 9, + 12, + 15 + ], + "field_60203": null, + "field_60195": null, + "field_60207": null, + "field_60211": null, + "field_60183": null, + "field_60126": [ + 2 + ], + "field_60208": null, + "field_60127": [ + 2 + ], + "field_60199": null, + "field_60214": null, + "field_60128": null, + "field_60212": null, + "field_60205": null, + "field_60194": null, + "field_60206": null, + "field_60215": null, + "field_60202": null, + "field_60218": null, + "field_60221": null, + "field_60213": null, + "field_60216": null, + "field_60219": null, + "field_60129": [], + "field_60217": null, + "field_60220": null, + "field_60222": null + }, + { + "id": 15, + "order": "15.00000000000000000000", + "created_on": "2024-10-21T11:21:39.821560+00:00", + "updated_on": "2024-11-05T12:24:09.071989+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60111": "Latisha Mazon", + "field_60112": "latisha.mazon@example.com", + "field_60113": "(530) 540-8012", + "field_60114": [ + { + "name": "uBMM8mm9cD2l5p1B1N1B2HlMylaKbXq6_64038313f395241c5d4d6615d9ba2d4d680777b263a811177230dbb5e391bd6c.jpg", + "visible_name": "Woman.46.jpg", + "original_name": "uBMM8mm9cD2l5p1B1N1B2HlMylaKbXq6_64038313f395241c5d4d6615d9ba2d4d680777b263a811177230dbb5e391bd6c.jpg" + } + ], + "field_60116": "Security Architect", + "field_60117": "2105 New York Avenue, Glendale, California", + "field_60118": "91204", + "field_60119": "1992-05-19", + "field_60120": "2019-07-30", + "field_60121": null, + "field_60181": null, + "field_60122": 21147, + "field_60182": null, + "field_60123": [ + 3 + ], + "field_60125": [ + 18 + ], + "field_60203": null, + "field_60195": null, + "field_60207": null, + "field_60211": null, + "field_60183": null, + "field_60126": [ + 4 + ], + "field_60208": null, + "field_60127": [], + "field_60199": null, + "field_60214": null, + "field_60128": null, + "field_60212": null, + "field_60205": null, + "field_60194": null, + "field_60206": null, + "field_60215": null, + "field_60202": null, + "field_60218": null, + "field_60221": null, + "field_60213": null, + "field_60216": null, + "field_60219": null, + "field_60129": [], + "field_60217": null, + "field_60220": null, + "field_60222": null + }, + { + "id": 16, + "order": "16.00000000000000000000", + "created_on": "2024-10-21T11:21:39.821617+00:00", + "updated_on": "2024-11-05T12:24:10.632724+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60111": "Lena Hogan", + "field_60112": "lena.hogan@example.com", + "field_60113": "(559) 949-6790", + "field_60114": [ + { + "name": "R1Ftm3oXercyem2nJseEVMnPu8KJCmFs_623cf9aca2c33d047b0c4312716412c1265e6269631846fff2dfb1147070c8fd.jpg", + "visible_name": "Woman.17.jpg", + "original_name": "R1Ftm3oXercyem2nJseEVMnPu8KJCmFs_623cf9aca2c33d047b0c4312716412c1265e6269631846fff2dfb1147070c8fd.jpg" + } + ], + "field_60116": "Cybersecurity Manager", + "field_60117": "898 Pearl Street, Sacramento, California", + "field_60118": "95814", + "field_60119": "1985-01-22", + "field_60120": "2012-01-08", + "field_60121": null, + "field_60181": null, + "field_60122": 21146, + "field_60182": null, + "field_60123": [ + 3 + ], + "field_60125": [ + 13, + 16 + ], + "field_60203": null, + "field_60195": null, + "field_60207": null, + "field_60211": null, + "field_60183": null, + "field_60126": [ + 3 + ], + "field_60208": null, + "field_60127": [], + "field_60199": null, + "field_60214": null, + "field_60128": null, + "field_60212": null, + "field_60205": null, + "field_60194": null, + "field_60206": null, + "field_60215": null, + "field_60202": null, + "field_60218": null, + "field_60221": null, + "field_60213": null, + "field_60216": null, + "field_60219": null, + "field_60129": [], + "field_60217": null, + "field_60220": null, + "field_60222": null + }, + { + "id": 17, + "order": "17.00000000000000000000", + "created_on": "2024-10-21T11:21:39.821666+00:00", + "updated_on": "2024-11-05T12:24:11.881135+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60111": "Leroy Tye", + "field_60112": "leroy.tye@example.com", + "field_60113": "(510) 808-7208", + "field_60114": [ + { + "name": "tAseSp9aRpY0SJCt5YQ3ZYZa1W62w80N_9254445c723333fd7687daff449887a52d0178ff24e24af1c076144a7ba80b32.jpg", + "visible_name": "Man.02.jpg", + "original_name": "tAseSp9aRpY0SJCt5YQ3ZYZa1W62w80N_9254445c723333fd7687daff449887a52d0178ff24e24af1c076144a7ba80b32.jpg" + } + ], + "field_60116": "Brand Manager", + "field_60117": "3486 Canis Heights Drive, Los Angeles, California", + "field_60118": "90007", + "field_60119": "1967-06-02", + "field_60120": "2012-01-08", + "field_60121": "2017-02-01", + "field_60181": null, + "field_60122": 21148, + "field_60182": null, + "field_60123": [ + 4 + ], + "field_60125": [], + "field_60203": null, + "field_60195": null, + "field_60207": null, + "field_60211": null, + "field_60183": null, + "field_60126": [], + "field_60208": null, + "field_60127": [], + "field_60199": null, + "field_60214": null, + "field_60128": null, + "field_60212": null, + "field_60205": null, + "field_60194": null, + "field_60206": null, + "field_60215": null, + "field_60202": null, + "field_60218": null, + "field_60221": null, + "field_60213": null, + "field_60216": null, + "field_60219": null, + "field_60129": [], + "field_60217": null, + "field_60220": null, + "field_60222": null + }, + { + "id": 18, + "order": "18.00000000000000000000", + "created_on": "2024-10-21T11:21:39.821721+00:00", + "updated_on": "2024-11-05T12:24:13.619300+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60111": "Michael Robicheaux", + "field_60112": "michael.robicheaux@example.com", + "field_60113": "(707) 840-5210", + "field_60114": [ + { + "name": "hL3mKMPbFZ9BeJEB5c6r5UgDtAeWsaRz_0afdb3017ed6ceb4d23b69ab3e44ef5efacb60ad98ddbd49c3138d3059b798c5.jpg", + "visible_name": "Man.28.jpg", + "original_name": "hL3mKMPbFZ9BeJEB5c6r5UgDtAeWsaRz_0afdb3017ed6ceb4d23b69ab3e44ef5efacb60ad98ddbd49c3138d3059b798c5.jpg" + } + ], + "field_60116": "Brand Strategist", + "field_60117": "3633 Nickel Road, Pasadena, California", + "field_60118": "91101", + "field_60119": "1975-11-04", + "field_60120": "2012-01-31", + "field_60121": null, + "field_60181": null, + "field_60122": 21147, + "field_60182": null, + "field_60123": [ + 4 + ], + "field_60125": [], + "field_60203": null, + "field_60195": null, + "field_60207": null, + "field_60211": null, + "field_60183": null, + "field_60126": [], + "field_60208": null, + "field_60127": [], + "field_60199": null, + "field_60214": null, + "field_60128": null, + "field_60212": null, + "field_60205": null, + "field_60194": null, + "field_60206": null, + "field_60215": null, + "field_60202": null, + "field_60218": null, + "field_60221": null, + "field_60213": null, + "field_60216": null, + "field_60219": null, + "field_60129": [], + "field_60217": null, + "field_60220": null, + "field_60222": null + }, + { + "id": 19, + "order": "19.00000000000000000000", + "created_on": "2024-10-21T11:21:39.821764+00:00", + "updated_on": "2024-11-05T12:24:14.997138+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60111": "Nora Mott", + "field_60112": "nora.mott@example.com", + "field_60113": "(818) 240-6675", + "field_60114": [ + { + "name": "33ljkMHV9qiWyi7CHrBIe4NHAIvYYThi_deae73b64502c13fe8f9ba9af624570071be79e62956e1492cd6686186824cc2.jpg", + "visible_name": "Woman.55.jpg", + "original_name": "33ljkMHV9qiWyi7CHrBIe4NHAIvYYThi_deae73b64502c13fe8f9ba9af624570071be79e62956e1492cd6686186824cc2.jpg" + } + ], + "field_60116": "Digital Marketing Specialist", + "field_60117": "792 Pretty View Lane, Mckinleyville, California", + "field_60118": "95519", + "field_60119": "1977-08-14", + "field_60120": "2023-07-30", + "field_60121": null, + "field_60181": null, + "field_60122": 21149, + "field_60182": null, + "field_60123": [ + 4 + ], + "field_60125": [], + "field_60203": null, + "field_60195": null, + "field_60207": null, + "field_60211": null, + "field_60183": null, + "field_60126": [], + "field_60208": null, + "field_60127": [], + "field_60199": null, + "field_60214": null, + "field_60128": null, + "field_60212": null, + "field_60205": null, + "field_60194": null, + "field_60206": null, + "field_60215": null, + "field_60202": null, + "field_60218": null, + "field_60221": null, + "field_60213": null, + "field_60216": null, + "field_60219": null, + "field_60129": [], + "field_60217": null, + "field_60220": null, + "field_60222": null + }, + { + "id": 20, + "order": "20.00000000000000000000", + "created_on": "2024-10-21T11:21:39.821808+00:00", + "updated_on": "2024-11-05T12:24:16.382038+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60111": "Paul Garcia", + "field_60112": "paul.garcia@example.com", + "field_60113": "(916) 910-4721", + "field_60114": [ + { + "name": "5zLgBF157sGf8dTYBGpTnQdnwTlCenmX_8ef24a4e04ccceb7d1f9199b20922abbc08069902fef9a0c17ac3cbb822679e5.jpg", + "visible_name": "Man.13.jpg", + "original_name": "5zLgBF157sGf8dTYBGpTnQdnwTlCenmX_8ef24a4e04ccceb7d1f9199b20922abbc08069902fef9a0c17ac3cbb822679e5.jpg" + } + ], + "field_60116": "SEO Specialist", + "field_60117": "678 Poplar Avenue, San Diego, California", + "field_60118": "92101", + "field_60119": "1983-05-18", + "field_60120": "2012-01-31", + "field_60121": "2019-10-12", + "field_60181": null, + "field_60122": 21149, + "field_60182": null, + "field_60123": [ + 4 + ], + "field_60125": [], + "field_60203": null, + "field_60195": null, + "field_60207": null, + "field_60211": null, + "field_60183": null, + "field_60126": [], + "field_60208": null, + "field_60127": [], + "field_60199": null, + "field_60214": null, + "field_60128": null, + "field_60212": null, + "field_60205": null, + "field_60194": null, + "field_60206": null, + "field_60215": null, + "field_60202": null, + "field_60218": null, + "field_60221": null, + "field_60213": null, + "field_60216": null, + "field_60219": null, + "field_60129": [], + "field_60217": null, + "field_60220": null, + "field_60222": null + }, + { + "id": 21, + "order": "21.00000000000000000000", + "created_on": "2024-10-21T11:21:39.821851+00:00", + "updated_on": "2024-11-05T12:24:17.769480+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60111": "Richard Rethman", + "field_60112": "richard.rethman@example.com", + "field_60113": "(626) 585-3240", + "field_60114": [ + { + "name": "md3VgyTEzkP8njQ43rimk5E5SzzIfyWd_860fc8f7a7c919681aa15783aebf52d282bf73edcba69fd03516ca5aba743f14.jpg", + "visible_name": "Man.31.jpg", + "original_name": "md3VgyTEzkP8njQ43rimk5E5SzzIfyWd_860fc8f7a7c919681aa15783aebf52d282bf73edcba69fd03516ca5aba743f14.jpg" + } + ], + "field_60116": "Supply Chain Analyst", + "field_60117": "567 Ford Street, San Jose, California", + "field_60118": "95131", + "field_60119": "1995-02-28", + "field_60120": "2019-07-30", + "field_60121": null, + "field_60181": null, + "field_60122": 21147, + "field_60182": null, + "field_60123": [ + 5 + ], + "field_60125": [], + "field_60203": null, + "field_60195": null, + "field_60207": null, + "field_60211": null, + "field_60183": null, + "field_60126": [], + "field_60208": null, + "field_60127": [], + "field_60199": null, + "field_60214": null, + "field_60128": null, + "field_60212": null, + "field_60205": null, + "field_60194": null, + "field_60206": null, + "field_60215": null, + "field_60202": null, + "field_60218": null, + "field_60221": null, + "field_60213": null, + "field_60216": null, + "field_60219": null, + "field_60129": [], + "field_60217": null, + "field_60220": null, + "field_60222": null + }, + { + "id": 22, + "order": "22.00000000000000000000", + "created_on": "2024-10-21T11:21:39.821895+00:00", + "updated_on": "2024-11-05T12:24:19.573940+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60111": "Rodney Tran", + "field_60112": "rodney.tran@example.com", + "field_60113": "(408) 451-1453", + "field_60114": [ + { + "name": "xBgeCT1WWcpZKGake5YhApbuQQywOfgb_a7820b4c5db7e94b1b25ad0a13f25a0474045e279a3b39691cbef744862bc538.jpg", + "visible_name": "Man.35.jpg", + "original_name": "xBgeCT1WWcpZKGake5YhApbuQQywOfgb_a7820b4c5db7e94b1b25ad0a13f25a0474045e279a3b39691cbef744862bc538.jpg" + } + ], + "field_60116": "Procurement Officer", + "field_60117": "3358 Southside Lane, Los Angeles, California", + "field_60118": "90017", + "field_60119": "1987-05-30", + "field_60120": "2012-01-31", + "field_60121": null, + "field_60181": null, + "field_60122": 21146, + "field_60182": null, + "field_60123": [ + 5 + ], + "field_60125": [], + "field_60203": null, + "field_60195": null, + "field_60207": null, + "field_60211": null, + "field_60183": null, + "field_60126": [], + "field_60208": null, + "field_60127": [], + "field_60199": null, + "field_60214": null, + "field_60128": null, + "field_60212": null, + "field_60205": null, + "field_60194": null, + "field_60206": null, + "field_60215": null, + "field_60202": null, + "field_60218": null, + "field_60221": null, + "field_60213": null, + "field_60216": null, + "field_60219": null, + "field_60129": [], + "field_60217": null, + "field_60220": null, + "field_60222": null + }, + { + "id": 23, + "order": "23.00000000000000000000", + "created_on": "2024-10-21T11:21:39.821938+00:00", + "updated_on": "2024-11-05T12:24:20.842460+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60111": "Sandra Love", + "field_60112": "sandra.love@example.com", + "field_60113": "(559) 592-9157", + "field_60114": [ + { + "name": "nS5Ctm0iRr9qaQKzMHefbpbj0iD3OETb_cfb289c2f728ba9774ce052190c0b13f3fbf18b004ca50103eb57c5e5c1345e8.jpg", + "visible_name": "Woman.23.jpg", + "original_name": "nS5Ctm0iRr9qaQKzMHefbpbj0iD3OETb_cfb289c2f728ba9774ce052190c0b13f3fbf18b004ca50103eb57c5e5c1345e8.jpg" + } + ], + "field_60116": "Quality Assurance Specialist", + "field_60117": "4647 Green Avenue, Oakland, California", + "field_60118": "94612", + "field_60119": "1979-12-04", + "field_60120": "2012-01-31", + "field_60121": null, + "field_60181": null, + "field_60122": 21147, + "field_60182": null, + "field_60123": [ + 5 + ], + "field_60125": [], + "field_60203": null, + "field_60195": null, + "field_60207": null, + "field_60211": null, + "field_60183": null, + "field_60126": [], + "field_60208": null, + "field_60127": [], + "field_60199": null, + "field_60214": null, + "field_60128": null, + "field_60212": null, + "field_60205": null, + "field_60194": null, + "field_60206": null, + "field_60215": null, + "field_60202": null, + "field_60218": null, + "field_60221": null, + "field_60213": null, + "field_60216": null, + "field_60219": null, + "field_60129": [], + "field_60217": null, + "field_60220": null, + "field_60222": null + }, + { + "id": 24, + "order": "24.00000000000000000000", + "created_on": "2024-10-21T11:21:39.821983+00:00", + "updated_on": "2024-11-05T12:24:22.666370+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60111": "Thomas Nickson", + "field_60112": "thomas.nickson@example.com", + "field_60113": "(916) 336-7017", + "field_60114": [ + { + "name": "gFkBdvgksMnYjASCkJrZoKIN1mO4SOkI_a61a8f87e0ad660120ad5476f8f3181239a96b1386dc8f0c5586bd2c9e736705.jpg", + "visible_name": "Man.11.jpg", + "original_name": "gFkBdvgksMnYjASCkJrZoKIN1mO4SOkI_a61a8f87e0ad660120ad5476f8f3181239a96b1386dc8f0c5586bd2c9e736705.jpg" + } + ], + "field_60116": "Quality Control Manager", + "field_60117": "858 Park Street, San Francisco, California", + "field_60118": "94108", + "field_60119": "1987-04-15", + "field_60120": "2024-07-30", + "field_60121": null, + "field_60181": null, + "field_60122": 21147, + "field_60182": null, + "field_60123": [ + 5 + ], + "field_60125": [], + "field_60203": null, + "field_60195": null, + "field_60207": null, + "field_60211": null, + "field_60183": null, + "field_60126": [], + "field_60208": null, + "field_60127": [], + "field_60199": null, + "field_60214": null, + "field_60128": null, + "field_60212": null, + "field_60205": null, + "field_60194": null, + "field_60206": null, + "field_60215": null, + "field_60202": null, + "field_60218": null, + "field_60221": null, + "field_60213": null, + "field_60216": null, + "field_60219": null, + "field_60129": [], + "field_60217": null, + "field_60220": null, + "field_60222": null + } + ], + "data_sync": null + }, + { + "id": 5731, + "name": "Performance reviews", + "order": 5, + "fields": [ + { + "id": 60196, + "type": "formula", + "name": "Name", + "description": null, + "order": 0, + "primary": true, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "date_show_tzinfo": null, + "nullable": false, + "number_decimal_places": null, + "number_separator": "", + "date_format": null, + "number_prefix": "", + "number_suffix": "", + "duration_format": null, + "array_formula_type": null, + "date_time_format": null, + "error": null, + "date_force_timezone": null, + "date_include_time": null, + "formula": "concat(min(lookup('Employee','Name')),' - ',field('Year'),' -',field('Overall performance rating'))", + "formula_type": "text" + }, + { + "id": 60130, + "type": "link_row", + "name": "Employee", + "description": null, + "order": 1, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "link_row_table_id": 5730, + "link_row_related_field_id": 60125, + "link_row_limit_selection_view_id": null, + "has_related_field": true + }, + { + "id": 60131, + "type": "link_row", + "name": "People Manager", + "description": null, + "order": 2, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "link_row_table_id": 5730, + "link_row_related_field_id": null, + "link_row_limit_selection_view_id": null, + "has_related_field": false + }, + { + "id": 60132, + "type": "number", + "name": "Year", + "description": null, + "order": 3, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "number_decimal_places": 0, + "number_negative": false, + "number_prefix": "", + "number_suffix": "", + "number_separator": "" + }, + { + "id": 60133, + "type": "link_row", + "name": "Overall what rating", + "description": null, + "order": 4, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "link_row_table_id": 5732, + "link_row_related_field_id": null, + "link_row_limit_selection_view_id": null, + "has_related_field": false + }, + { + "id": 60185, + "type": "rollup", + "name": "Overall what description", + "description": null, + "order": 5, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "date_show_tzinfo": null, + "nullable": true, + "number_decimal_places": null, + "number_separator": "", + "date_format": null, + "number_prefix": "", + "number_suffix": "", + "duration_format": null, + "array_formula_type": null, + "date_time_format": null, + "error": null, + "date_force_timezone": null, + "date_include_time": null, + "through_field_id": 60133, + "target_field_id": 60137, + "rollup_function": "min" + }, + { + "id": 60134, + "type": "link_row", + "name": "Overall how rating", + "description": null, + "order": 6, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "link_row_table_id": 5732, + "link_row_related_field_id": null, + "link_row_limit_selection_view_id": null, + "has_related_field": false + }, + { + "id": 60186, + "type": "rollup", + "name": "Overall how description", + "description": null, + "order": 7, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "date_show_tzinfo": null, + "nullable": true, + "number_decimal_places": null, + "number_separator": "", + "date_format": null, + "number_prefix": "", + "number_suffix": "", + "duration_format": null, + "array_formula_type": null, + "date_time_format": null, + "error": null, + "date_force_timezone": null, + "date_include_time": null, + "through_field_id": 60134, + "target_field_id": 60137, + "rollup_function": "min" + }, + { + "id": 60187, + "type": "formula", + "name": "Overall performance rating", + "description": null, + "order": 8, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "date_show_tzinfo": null, + "nullable": false, + "number_decimal_places": 1, + "number_separator": "", + "date_format": null, + "number_prefix": "", + "number_suffix": "", + "duration_format": null, + "array_formula_type": null, + "date_time_format": null, + "error": null, + "date_force_timezone": null, + "date_include_time": null, + "formula": "(min(lookup('Overall what rating','Score')) + min(lookup('Overall how rating','Score'))) / 2", + "formula_type": "number" + } + ], + "views": [ + { + "id": 26625, + "type": "grid", + "name": "All performance reviews", + "order": 1, + "ownership_type": "collaborative", + "owned_by": "frederik@baserow.io", + "filter_type": "AND", + "filters_disabled": false, + "filters": [], + "filter_groups": [], + "sortings": [ + { + "id": 20530, + "field_id": 60132, + "order": "DESC" + }, + { + "id": 20531, + "field_id": 60187, + "order": "DESC" + } + ], + "group_bys": [], + "decorations": [], + "public": false, + "row_identifier_type": "id", + "row_height_size": "small", + "field_options": [ + { + "id": 263620, + "field_id": 60196, + "width": 200, + "hidden": false, + "order": 0, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263621, + "field_id": 60130, + "width": 157, + "hidden": false, + "order": 1, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263622, + "field_id": 60131, + "width": 170, + "hidden": false, + "order": 2, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263623, + "field_id": 60132, + "width": 100, + "hidden": false, + "order": 3, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263624, + "field_id": 60187, + "width": 240, + "hidden": false, + "order": 4, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263625, + "field_id": 60133, + "width": 189, + "hidden": false, + "order": 5, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263626, + "field_id": 60185, + "width": 220, + "hidden": false, + "order": 6, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263627, + "field_id": 60134, + "width": 200, + "hidden": false, + "order": 7, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263628, + "field_id": 60186, + "width": 222, + "hidden": false, + "order": 8, + "aggregation_type": "", + "aggregation_raw_type": "" + } + ] + }, + { + "id": 26643, + "type": "grid", + "name": "All performance reviews grouped by employee", + "order": 2, + "ownership_type": "collaborative", + "owned_by": "frederik@baserow.io", + "filter_type": "AND", + "filters_disabled": false, + "filters": [], + "filter_groups": [], + "sortings": [ + { + "id": 20532, + "field_id": 60132, + "order": "DESC" + }, + { + "id": 20533, + "field_id": 60187, + "order": "DESC" + } + ], + "group_bys": [ + { + "id": 3670, + "field_id": 60130, + "order": "ASC" + } + ], + "decorations": [], + "public": false, + "row_identifier_type": "id", + "row_height_size": "small", + "field_options": [ + { + "id": 264177, + "field_id": 60196, + "width": 200, + "hidden": false, + "order": 0, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264178, + "field_id": 60130, + "width": 157, + "hidden": true, + "order": 1, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264179, + "field_id": 60131, + "width": 170, + "hidden": false, + "order": 2, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264180, + "field_id": 60132, + "width": 100, + "hidden": false, + "order": 3, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264181, + "field_id": 60187, + "width": 240, + "hidden": false, + "order": 4, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264182, + "field_id": 60133, + "width": 189, + "hidden": false, + "order": 5, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264183, + "field_id": 60185, + "width": 220, + "hidden": false, + "order": 6, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264184, + "field_id": 60134, + "width": 200, + "hidden": false, + "order": 7, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264185, + "field_id": 60186, + "width": 222, + "hidden": false, + "order": 8, + "aggregation_type": "", + "aggregation_raw_type": "" + } + ] + }, + { + "id": 26644, + "type": "grid", + "name": "All performance reviews grouped by manager", + "order": 3, + "ownership_type": "collaborative", + "owned_by": "frederik@baserow.io", + "filter_type": "AND", + "filters_disabled": false, + "filters": [], + "filter_groups": [], + "sortings": [ + { + "id": 20534, + "field_id": 60132, + "order": "DESC" + }, + { + "id": 20535, + "field_id": 60187, + "order": "DESC" + } + ], + "group_bys": [ + { + "id": 3671, + "field_id": 60131, + "order": "ASC" + } + ], + "decorations": [], + "public": false, + "row_identifier_type": "id", + "row_height_size": "small", + "field_options": [ + { + "id": 264186, + "field_id": 60196, + "width": 200, + "hidden": false, + "order": 0, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264187, + "field_id": 60130, + "width": 157, + "hidden": false, + "order": 1, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264188, + "field_id": 60131, + "width": 170, + "hidden": true, + "order": 2, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264189, + "field_id": 60132, + "width": 100, + "hidden": false, + "order": 3, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264190, + "field_id": 60187, + "width": 240, + "hidden": false, + "order": 4, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264191, + "field_id": 60133, + "width": 189, + "hidden": false, + "order": 5, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264192, + "field_id": 60185, + "width": 220, + "hidden": false, + "order": 6, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264193, + "field_id": 60134, + "width": 200, + "hidden": false, + "order": 7, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264194, + "field_id": 60186, + "width": 222, + "hidden": false, + "order": 8, + "aggregation_type": "", + "aggregation_raw_type": "" + } + ] + }, + { + "id": 26645, + "type": "grid", + "name": "All performance reviews grouped by year", + "order": 4, + "ownership_type": "collaborative", + "owned_by": "frederik@baserow.io", + "filter_type": "AND", + "filters_disabled": false, + "filters": [], + "filter_groups": [], + "sortings": [ + { + "id": 20536, + "field_id": 60132, + "order": "DESC" + }, + { + "id": 20537, + "field_id": 60187, + "order": "DESC" + } + ], + "group_bys": [ + { + "id": 3672, + "field_id": 60132, + "order": "DESC" + } + ], + "decorations": [], + "public": false, + "row_identifier_type": "id", + "row_height_size": "small", + "field_options": [ + { + "id": 264195, + "field_id": 60196, + "width": 200, + "hidden": false, + "order": 0, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264196, + "field_id": 60130, + "width": 157, + "hidden": false, + "order": 1, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264197, + "field_id": 60131, + "width": 170, + "hidden": false, + "order": 2, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264198, + "field_id": 60132, + "width": 100, + "hidden": true, + "order": 3, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264199, + "field_id": 60187, + "width": 240, + "hidden": false, + "order": 4, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264200, + "field_id": 60133, + "width": 189, + "hidden": false, + "order": 5, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264201, + "field_id": 60185, + "width": 220, + "hidden": false, + "order": 6, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264202, + "field_id": 60134, + "width": 200, + "hidden": false, + "order": 7, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264203, + "field_id": 60186, + "width": 222, + "hidden": false, + "order": 8, + "aggregation_type": "", + "aggregation_raw_type": "" + } + ] + }, + { + "id": 26646, + "type": "grid", + "name": "High performance ratings > 3.5", + "order": 5, + "ownership_type": "collaborative", + "owned_by": "frederik@baserow.io", + "filter_type": "AND", + "filters_disabled": false, + "filters": [ + { + "id": 14041, + "field_id": 60187, + "type": "higher_than", + "value": "3.5", + "group": null + } + ], + "filter_groups": [], + "sortings": [ + { + "id": 20538, + "field_id": 60132, + "order": "DESC" + }, + { + "id": 20539, + "field_id": 60187, + "order": "DESC" + } + ], + "group_bys": [], + "decorations": [], + "public": false, + "row_identifier_type": "id", + "row_height_size": "small", + "field_options": [ + { + "id": 264204, + "field_id": 60196, + "width": 200, + "hidden": false, + "order": 0, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264205, + "field_id": 60130, + "width": 157, + "hidden": false, + "order": 1, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264206, + "field_id": 60131, + "width": 170, + "hidden": false, + "order": 2, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264207, + "field_id": 60132, + "width": 100, + "hidden": false, + "order": 3, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264208, + "field_id": 60187, + "width": 240, + "hidden": false, + "order": 4, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264209, + "field_id": 60133, + "width": 189, + "hidden": false, + "order": 5, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264210, + "field_id": 60185, + "width": 220, + "hidden": false, + "order": 6, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264211, + "field_id": 60134, + "width": 200, + "hidden": false, + "order": 7, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264212, + "field_id": 60186, + "width": 222, + "hidden": false, + "order": 8, + "aggregation_type": "", + "aggregation_raw_type": "" + } + ] + }, + { + "id": 26647, + "type": "grid", + "name": "Low performance ratings < 2.5", + "order": 6, + "ownership_type": "collaborative", + "owned_by": "frederik@baserow.io", + "filter_type": "AND", + "filters_disabled": false, + "filters": [ + { + "id": 14042, + "field_id": 60187, + "type": "lower_than", + "value": "2.5", + "group": null + } + ], + "filter_groups": [], + "sortings": [ + { + "id": 20540, + "field_id": 60132, + "order": "DESC" + }, + { + "id": 20541, + "field_id": 60187, + "order": "DESC" + } + ], + "group_bys": [], + "decorations": [], + "public": false, + "row_identifier_type": "id", + "row_height_size": "small", + "field_options": [ + { + "id": 264213, + "field_id": 60196, + "width": 200, + "hidden": false, + "order": 0, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264214, + "field_id": 60130, + "width": 157, + "hidden": false, + "order": 1, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264215, + "field_id": 60131, + "width": 170, + "hidden": false, + "order": 2, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264216, + "field_id": 60132, + "width": 100, + "hidden": false, + "order": 3, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264217, + "field_id": 60187, + "width": 240, + "hidden": false, + "order": 4, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264218, + "field_id": 60133, + "width": 189, + "hidden": false, + "order": 5, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264219, + "field_id": 60185, + "width": 220, + "hidden": false, + "order": 6, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264220, + "field_id": 60134, + "width": 200, + "hidden": false, + "order": 7, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264221, + "field_id": 60186, + "width": 222, + "hidden": false, + "order": 8, + "aggregation_type": "", + "aggregation_raw_type": "" + } + ] + } + ], + "rows": [ + { + "id": 1, + "order": "1.00000000000000000000", + "created_on": "2025-02-18T09:03:19.182597+00:00", + "updated_on": "2025-02-18T09:11:28.395983+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60196": null, + "field_60130": [ + 9 + ], + "field_60131": [ + 1 + ], + "field_60132": "2021", + "field_60133": [ + 3 + ], + "field_60185": null, + "field_60134": [ + 3 + ], + "field_60186": null, + "field_60187": null + }, + { + "id": 2, + "order": "2.00000000000000000000", + "created_on": "2025-02-18T09:03:19.182615+00:00", + "updated_on": "2025-02-18T09:14:04.266570+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60196": null, + "field_60130": [ + 9 + ], + "field_60131": [ + 1 + ], + "field_60132": "2022", + "field_60133": [ + 4 + ], + "field_60185": null, + "field_60134": [ + 3 + ], + "field_60186": null, + "field_60187": null + }, + { + "id": 3, + "order": "3.00000000000000000000", + "created_on": "2025-02-18T09:14:11.859678+00:00", + "updated_on": "2025-02-18T09:40:49.816039+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60196": null, + "field_60130": [ + 9 + ], + "field_60131": [ + 1 + ], + "field_60132": "2023", + "field_60133": [ + 4 + ], + "field_60185": null, + "field_60134": [ + 4 + ], + "field_60186": null, + "field_60187": null + }, + { + "id": 4, + "order": "4.00000000000000000000", + "created_on": "2025-02-18T09:14:38.914105+00:00", + "updated_on": "2025-02-18T09:40:50.153126+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60196": null, + "field_60130": [ + 9 + ], + "field_60131": [ + 1 + ], + "field_60132": "2024", + "field_60133": [ + 4 + ], + "field_60185": null, + "field_60134": [ + 4 + ], + "field_60186": null, + "field_60187": null + }, + { + "id": 5, + "order": "5.00000000000000000000", + "created_on": "2025-02-18T09:14:53.006914+00:00", + "updated_on": "2025-02-18T09:39:42.135070+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60196": null, + "field_60130": [ + 12 + ], + "field_60131": [ + 2 + ], + "field_60132": "2021", + "field_60133": [ + 2 + ], + "field_60185": null, + "field_60134": [ + 3 + ], + "field_60186": null, + "field_60187": null + }, + { + "id": 6, + "order": "6.00000000000000000000", + "created_on": "2025-02-18T09:15:27.277549+00:00", + "updated_on": "2025-02-18T09:17:39.623831+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60196": null, + "field_60130": [ + 14 + ], + "field_60131": [ + 3 + ], + "field_60132": "2021", + "field_60133": [ + 2 + ], + "field_60185": null, + "field_60134": [ + 3 + ], + "field_60186": null, + "field_60187": null + }, + { + "id": 8, + "order": "8.00000000000000000000", + "created_on": "2025-02-18T09:16:16.627379+00:00", + "updated_on": "2025-02-18T09:40:17.025905+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60196": null, + "field_60130": [ + 12 + ], + "field_60131": [ + 2 + ], + "field_60132": "2022", + "field_60133": [ + 1 + ], + "field_60185": null, + "field_60134": [ + 1 + ], + "field_60186": null, + "field_60187": null + }, + { + "id": 9, + "order": "9.00000000000000000000", + "created_on": "2025-02-18T09:16:17.943433+00:00", + "updated_on": "2025-02-18T09:17:36.919648+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60196": null, + "field_60130": [ + 14 + ], + "field_60131": [ + 3 + ], + "field_60132": "2022", + "field_60133": [ + 3 + ], + "field_60185": null, + "field_60134": [ + 2 + ], + "field_60186": null, + "field_60187": null + }, + { + "id": 11, + "order": "11.00000000000000000000", + "created_on": "2025-02-18T09:16:18.847785+00:00", + "updated_on": "2025-02-18T09:17:36.515469+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60196": null, + "field_60130": [ + 12 + ], + "field_60131": [ + 2 + ], + "field_60132": "2023", + "field_60133": [ + 2 + ], + "field_60185": null, + "field_60134": [ + 2 + ], + "field_60186": null, + "field_60187": null + }, + { + "id": 12, + "order": "12.00000000000000000000", + "created_on": "2025-02-18T09:16:19.929728+00:00", + "updated_on": "2025-02-18T09:17:30.326078+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60196": null, + "field_60130": [ + 14 + ], + "field_60131": [ + 3 + ], + "field_60132": "2023", + "field_60133": [ + 3 + ], + "field_60185": null, + "field_60134": [ + 4 + ], + "field_60186": null, + "field_60187": null + }, + { + "id": 13, + "order": "13.00000000000000000000", + "created_on": "2025-02-18T09:16:19.929783+00:00", + "updated_on": "2025-02-18T09:17:41.051528+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60196": null, + "field_60130": [ + 16 + ], + "field_60131": [ + 3 + ], + "field_60132": "2023", + "field_60133": [ + 2 + ], + "field_60185": null, + "field_60134": [ + 3 + ], + "field_60186": null, + "field_60187": null + }, + { + "id": 14, + "order": "14.00000000000000000000", + "created_on": "2025-02-18T09:16:21.027902+00:00", + "updated_on": "2025-02-18T09:17:35.883096+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60196": null, + "field_60130": [ + 12 + ], + "field_60131": [ + 2 + ], + "field_60132": "2024", + "field_60133": [ + 2 + ], + "field_60185": null, + "field_60134": [ + 2 + ], + "field_60186": null, + "field_60187": null + }, + { + "id": 15, + "order": "15.00000000000000000000", + "created_on": "2025-02-18T09:16:21.809717+00:00", + "updated_on": "2025-02-18T09:17:41.530580+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60196": null, + "field_60130": [ + 14 + ], + "field_60131": [ + 3 + ], + "field_60132": "2024", + "field_60133": [ + 3 + ], + "field_60185": null, + "field_60134": [ + 3 + ], + "field_60186": null, + "field_60187": null + }, + { + "id": 16, + "order": "16.00000000000000000000", + "created_on": "2025-02-18T09:16:21.809772+00:00", + "updated_on": "2025-02-18T09:17:31.765848+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60196": null, + "field_60130": [ + 16 + ], + "field_60131": [ + 3 + ], + "field_60132": "2024", + "field_60133": [ + 1 + ], + "field_60185": null, + "field_60134": [ + 4 + ], + "field_60186": null, + "field_60187": null + }, + { + "id": 17, + "order": "17.00000000000000000000", + "created_on": "2025-02-18T12:30:10.875280+00:00", + "updated_on": "2025-02-18T12:31:45.375526+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60196": null, + "field_60130": [ + 13 + ], + "field_60131": [ + 3 + ], + "field_60132": "2025", + "field_60133": [ + 4 + ], + "field_60185": null, + "field_60134": [ + 3 + ], + "field_60186": null, + "field_60187": null + }, + { + "id": 18, + "order": "18.00000000000000000000", + "created_on": "2025-02-18T18:38:32.169547+00:00", + "updated_on": "2025-02-18T18:42:38.623916+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60196": null, + "field_60130": [ + 15 + ], + "field_60131": [ + 3 + ], + "field_60132": "2025", + "field_60133": [ + 2 + ], + "field_60185": null, + "field_60134": [ + 4 + ], + "field_60186": null, + "field_60187": null + }, + { + "id": 19, + "order": "19.00000000000000000000", + "created_on": "2025-02-18T19:17:49.555711+00:00", + "updated_on": "2025-02-18T19:17:49.555711+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60196": null, + "field_60130": [ + 7 + ], + "field_60131": [ + 1 + ], + "field_60132": "2025", + "field_60133": [ + 3 + ], + "field_60185": null, + "field_60134": [ + 3 + ], + "field_60186": null, + "field_60187": null + }, + { + "id": 20, + "order": "20.00000000000000000000", + "created_on": "2025-02-19T12:25:30.446938+00:00", + "updated_on": "2025-02-19T12:25:48.597794+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60196": null, + "field_60130": [ + 11 + ], + "field_60131": [ + 2 + ], + "field_60132": "2025", + "field_60133": [ + 3 + ], + "field_60185": null, + "field_60134": [ + 3 + ], + "field_60186": null, + "field_60187": null + }, + { + "id": 21, + "order": "21.00000000000000000000", + "created_on": "2025-02-19T12:28:08.232869+00:00", + "updated_on": "2025-02-19T12:28:08.232869+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60196": null, + "field_60130": [ + 9 + ], + "field_60131": [ + 1 + ], + "field_60132": "2025", + "field_60133": [ + 4 + ], + "field_60185": null, + "field_60134": [ + 4 + ], + "field_60186": null, + "field_60187": null + }, + { + "id": 22, + "order": "22.00000000000000000000", + "created_on": "2025-02-19T12:29:11.985496+00:00", + "updated_on": "2025-02-19T12:29:11.985496+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60196": null, + "field_60130": [ + 6 + ], + "field_60131": [ + 1 + ], + "field_60132": "2025", + "field_60133": [ + 3 + ], + "field_60185": null, + "field_60134": [ + 2 + ], + "field_60186": null, + "field_60187": null + }, + { + "id": 23, + "order": "23.00000000000000000000", + "created_on": "2025-02-19T12:30:57.696377+00:00", + "updated_on": "2025-02-19T12:30:57.696377+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60196": null, + "field_60130": [ + 10 + ], + "field_60131": [ + 2 + ], + "field_60132": "2025", + "field_60133": [ + 3 + ], + "field_60185": null, + "field_60134": [ + 4 + ], + "field_60186": null, + "field_60187": null + } + ], + "data_sync": null + }, + { + "id": 5732, + "name": "Performance ratings", + "order": 6, + "fields": [ + { + "id": 60135, + "type": "text", + "name": "Name", + "description": null, + "order": 0, + "primary": true, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "text_default": "" + }, + { + "id": 60136, + "type": "number", + "name": "Score", + "description": null, + "order": 1, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "number_decimal_places": 0, + "number_negative": false, + "number_prefix": "", + "number_suffix": "", + "number_separator": "" + }, + { + "id": 60137, + "type": "text", + "name": "Description", + "description": null, + "order": 2, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "text_default": "" + } + ], + "views": [ + { + "id": 26626, + "type": "grid", + "name": "All performance ratings", + "order": 1, + "ownership_type": "collaborative", + "owned_by": "frederik@baserow.io", + "filter_type": "AND", + "filters_disabled": false, + "filters": [], + "filter_groups": [], + "sortings": [ + { + "id": 20542, + "field_id": 60136, + "order": "ASC" + } + ], + "group_bys": [], + "decorations": [], + "public": false, + "row_identifier_type": "id", + "row_height_size": "small", + "field_options": [ + { + "id": 263629, + "field_id": 60135, + "width": 200, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263630, + "field_id": 60136, + "width": 118, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263631, + "field_id": 60137, + "width": 200, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + } + ] + } + ], + "rows": [ + { + "id": 1, + "order": "1.00000000000000000000", + "created_on": "2025-02-18T09:06:31.930770+00:00", + "updated_on": "2025-02-18T09:09:12.621232+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60135": "\u2b50", + "field_60136": "1", + "field_60137": "Low" + }, + { + "id": 2, + "order": "2.00000000000000000000", + "created_on": "2025-02-18T09:06:31.930797+00:00", + "updated_on": "2025-02-18T09:09:16.786477+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60135": "\u2b50\u2b50", + "field_60136": "2", + "field_60137": "Moderate" + }, + { + "id": 3, + "order": "3.00000000000000000000", + "created_on": "2025-02-18T09:06:41.292015+00:00", + "updated_on": "2025-02-18T09:09:19.127740+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60135": "\u2b50\u2b50\u2b50", + "field_60136": "3", + "field_60137": "Well" + }, + { + "id": 4, + "order": "4.00000000000000000000", + "created_on": "2025-02-18T09:06:43.768426+00:00", + "updated_on": "2025-02-18T09:09:22.478528+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60135": "\u2b50\u2b50\u2b50\u2b50", + "field_60136": "4", + "field_60137": "Superior" + } + ], + "data_sync": null + }, + { + "id": 5733, + "name": "Potential assessments", + "order": 7, + "fields": [ + { + "id": 60209, + "type": "formula", + "name": "Name", + "description": null, + "order": 0, + "primary": true, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "date_show_tzinfo": null, + "nullable": false, + "number_decimal_places": null, + "number_separator": "", + "date_format": null, + "number_prefix": "", + "number_suffix": "", + "duration_format": null, + "array_formula_type": null, + "date_time_format": null, + "error": null, + "date_force_timezone": null, + "date_include_time": null, + "formula": "concat(min(lookup('Employee','Name')),' - ', field('Year'),' - ',field('Has potential'))", + "formula_type": "text" + }, + { + "id": 60138, + "type": "link_row", + "name": "Employee", + "description": null, + "order": 1, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "link_row_table_id": 5730, + "link_row_related_field_id": 60126, + "link_row_limit_selection_view_id": null, + "has_related_field": true + }, + { + "id": 60139, + "type": "link_row", + "name": "Manager", + "description": null, + "order": 2, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "link_row_table_id": 5730, + "link_row_related_field_id": null, + "link_row_limit_selection_view_id": null, + "has_related_field": false + }, + { + "id": 60140, + "type": "link_row", + "name": "01", + "description": null, + "order": 3, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "link_row_table_id": 5734, + "link_row_related_field_id": null, + "link_row_limit_selection_view_id": null, + "has_related_field": false + }, + { + "id": 60141, + "type": "link_row", + "name": "02", + "description": null, + "order": 4, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "link_row_table_id": 5734, + "link_row_related_field_id": null, + "link_row_limit_selection_view_id": null, + "has_related_field": false + }, + { + "id": 60142, + "type": "link_row", + "name": "03", + "description": null, + "order": 5, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "link_row_table_id": 5734, + "link_row_related_field_id": null, + "link_row_limit_selection_view_id": null, + "has_related_field": false + }, + { + "id": 60143, + "type": "link_row", + "name": "04", + "description": null, + "order": 6, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "link_row_table_id": 5734, + "link_row_related_field_id": null, + "link_row_limit_selection_view_id": null, + "has_related_field": false + }, + { + "id": 60144, + "type": "link_row", + "name": "05", + "description": null, + "order": 7, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "link_row_table_id": 5734, + "link_row_related_field_id": null, + "link_row_limit_selection_view_id": null, + "has_related_field": false + }, + { + "id": 60145, + "type": "link_row", + "name": "06", + "description": null, + "order": 8, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "link_row_table_id": 5734, + "link_row_related_field_id": null, + "link_row_limit_selection_view_id": null, + "has_related_field": false + }, + { + "id": 60146, + "type": "link_row", + "name": "07", + "description": null, + "order": 9, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "link_row_table_id": 5734, + "link_row_related_field_id": null, + "link_row_limit_selection_view_id": null, + "has_related_field": false + }, + { + "id": 60147, + "type": "link_row", + "name": "08", + "description": null, + "order": 10, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "link_row_table_id": 5734, + "link_row_related_field_id": null, + "link_row_limit_selection_view_id": null, + "has_related_field": false + }, + { + "id": 60148, + "type": "link_row", + "name": "09", + "description": null, + "order": 11, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "link_row_table_id": 5734, + "link_row_related_field_id": null, + "link_row_limit_selection_view_id": null, + "has_related_field": false + }, + { + "id": 60149, + "type": "link_row", + "name": "10", + "description": null, + "order": 12, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "link_row_table_id": 5734, + "link_row_related_field_id": null, + "link_row_limit_selection_view_id": null, + "has_related_field": false + }, + { + "id": 60150, + "type": "link_row", + "name": "11", + "description": null, + "order": 13, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "link_row_table_id": 5734, + "link_row_related_field_id": null, + "link_row_limit_selection_view_id": null, + "has_related_field": false + }, + { + "id": 60151, + "type": "link_row", + "name": "12", + "description": null, + "order": 14, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "link_row_table_id": 5734, + "link_row_related_field_id": null, + "link_row_limit_selection_view_id": null, + "has_related_field": false + }, + { + "id": 60188, + "type": "formula", + "name": "Communication total", + "description": null, + "order": 15, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "date_show_tzinfo": null, + "nullable": false, + "number_decimal_places": 0, + "number_separator": "", + "date_format": null, + "number_prefix": "", + "number_suffix": "", + "duration_format": null, + "array_formula_type": null, + "date_time_format": null, + "error": null, + "date_force_timezone": null, + "date_include_time": null, + "formula": "sum(lookup('01','Score') + lookup('02','Score') + lookup('03','Score'))", + "formula_type": "number" + }, + { + "id": 60189, + "type": "formula", + "name": "Problem solving total", + "description": null, + "order": 16, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "date_show_tzinfo": null, + "nullable": false, + "number_decimal_places": 0, + "number_separator": "", + "date_format": null, + "number_prefix": "", + "number_suffix": "", + "duration_format": null, + "array_formula_type": null, + "date_time_format": null, + "error": null, + "date_force_timezone": null, + "date_include_time": null, + "formula": "sum(lookup('04','Score') + lookup('05','Score') + lookup('06','Score'))", + "formula_type": "number" + }, + { + "id": 60190, + "type": "formula", + "name": "Leadership total", + "description": null, + "order": 17, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "date_show_tzinfo": null, + "nullable": false, + "number_decimal_places": 0, + "number_separator": "", + "date_format": null, + "number_prefix": "", + "number_suffix": "", + "duration_format": null, + "array_formula_type": null, + "date_time_format": null, + "error": null, + "date_force_timezone": null, + "date_include_time": null, + "formula": "sum(lookup('07','Score') + lookup('08','Score') + lookup('09','Score'))", + "formula_type": "number" + }, + { + "id": 60191, + "type": "formula", + "name": "Technical total", + "description": null, + "order": 18, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "date_show_tzinfo": null, + "nullable": false, + "number_decimal_places": 0, + "number_separator": "", + "date_format": null, + "number_prefix": "", + "number_suffix": "", + "duration_format": null, + "array_formula_type": null, + "date_time_format": null, + "error": null, + "date_force_timezone": null, + "date_include_time": null, + "formula": "sum(lookup('10','Score') + lookup('11','Score') + lookup('12','Score'))", + "formula_type": "number" + }, + { + "id": 60197, + "type": "formula", + "name": "Total score", + "description": null, + "order": 19, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "date_show_tzinfo": null, + "nullable": false, + "number_decimal_places": 0, + "number_separator": "", + "date_format": null, + "number_prefix": "", + "number_suffix": "", + "duration_format": null, + "array_formula_type": null, + "date_time_format": null, + "error": null, + "date_force_timezone": null, + "date_include_time": null, + "formula": "field('Communication total') + field('Problem solving total') + field('Leadership total') + field('Technical total')", + "formula_type": "number" + }, + { + "id": 60198, + "type": "formula", + "name": "Score in every category", + "description": null, + "order": 20, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "date_show_tzinfo": null, + "nullable": false, + "number_decimal_places": null, + "number_separator": "", + "date_format": null, + "number_prefix": "", + "number_suffix": "", + "duration_format": null, + "array_formula_type": null, + "date_time_format": null, + "error": null, + "date_force_timezone": null, + "date_include_time": null, + "formula": "and(and(field('Communication total') > 0,field('Problem solving total') > 0),and(field('Leadership total') > 0,field('Technical total') > 0))", + "formula_type": "boolean" + }, + { + "id": 60204, + "type": "formula", + "name": "Has potential", + "description": null, + "order": 21, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "date_show_tzinfo": null, + "nullable": false, + "number_decimal_places": null, + "number_separator": "", + "date_format": null, + "number_prefix": "", + "number_suffix": "", + "duration_format": null, + "array_formula_type": null, + "date_time_format": null, + "error": null, + "date_force_timezone": null, + "date_include_time": null, + "formula": "and(field('Score in every category'),field('Total score') >= 7)", + "formula_type": "boolean" + }, + { + "id": 60152, + "type": "number", + "name": "Year", + "description": null, + "order": 22, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "number_decimal_places": 0, + "number_negative": false, + "number_prefix": "", + "number_suffix": "", + "number_separator": "" + }, + { + "id": 60210, + "type": "formula", + "name": "Has potential symbol", + "description": null, + "order": 23, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "date_show_tzinfo": null, + "nullable": false, + "number_decimal_places": null, + "number_separator": "", + "date_format": null, + "number_prefix": "", + "number_suffix": "", + "duration_format": null, + "array_formula_type": null, + "date_time_format": null, + "error": null, + "date_force_timezone": null, + "date_include_time": null, + "formula": "if(field('Has potential'),'\u2714\ufe0f ','\u274c')", + "formula_type": "text" + } + ], + "views": [ + { + "id": 26627, + "type": "grid", + "name": "All potential assessments", + "order": 1, + "ownership_type": "collaborative", + "owned_by": "frederik@baserow.io", + "filter_type": "AND", + "filters_disabled": false, + "filters": [], + "filter_groups": [], + "sortings": [ + { + "id": 20543, + "field_id": 60152, + "order": "DESC" + }, + { + "id": 20544, + "field_id": 60197, + "order": "DESC" + } + ], + "group_bys": [], + "decorations": [], + "public": false, + "row_identifier_type": "id", + "row_height_size": "small", + "field_options": [ + { + "id": 263632, + "field_id": 60209, + "width": 200, + "hidden": false, + "order": 0, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263633, + "field_id": 60138, + "width": 180, + "hidden": false, + "order": 1, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263634, + "field_id": 60139, + "width": 138, + "hidden": false, + "order": 2, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263635, + "field_id": 60152, + "width": 113, + "hidden": false, + "order": 3, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263636, + "field_id": 60140, + "width": 115, + "hidden": false, + "order": 4, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263637, + "field_id": 60141, + "width": 121, + "hidden": false, + "order": 5, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263638, + "field_id": 60142, + "width": 117, + "hidden": false, + "order": 6, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263639, + "field_id": 60143, + "width": 122, + "hidden": false, + "order": 7, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263640, + "field_id": 60144, + "width": 134, + "hidden": false, + "order": 8, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263641, + "field_id": 60145, + "width": 125, + "hidden": false, + "order": 9, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263642, + "field_id": 60146, + "width": 124, + "hidden": false, + "order": 10, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263643, + "field_id": 60147, + "width": 126, + "hidden": false, + "order": 11, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263644, + "field_id": 60148, + "width": 100, + "hidden": false, + "order": 12, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263645, + "field_id": 60149, + "width": 115, + "hidden": false, + "order": 13, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263646, + "field_id": 60150, + "width": 116, + "hidden": false, + "order": 14, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263647, + "field_id": 60151, + "width": 147, + "hidden": false, + "order": 15, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263648, + "field_id": 60188, + "width": 156, + "hidden": false, + "order": 16, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263649, + "field_id": 60189, + "width": 200, + "hidden": false, + "order": 17, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263650, + "field_id": 60190, + "width": 200, + "hidden": false, + "order": 18, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263651, + "field_id": 60191, + "width": 200, + "hidden": false, + "order": 19, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263652, + "field_id": 60197, + "width": 200, + "hidden": false, + "order": 20, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263653, + "field_id": 60198, + "width": 226, + "hidden": false, + "order": 21, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263654, + "field_id": 60204, + "width": 226, + "hidden": false, + "order": 22, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263655, + "field_id": 60210, + "width": 200, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + } + ] + }, + { + "id": 26648, + "type": "grid", + "name": "All potential assessments grouped by employee", + "order": 2, + "ownership_type": "collaborative", + "owned_by": "frederik@baserow.io", + "filter_type": "AND", + "filters_disabled": false, + "filters": [], + "filter_groups": [], + "sortings": [ + { + "id": 20545, + "field_id": 60152, + "order": "DESC" + }, + { + "id": 20546, + "field_id": 60197, + "order": "DESC" + } + ], + "group_bys": [ + { + "id": 3673, + "field_id": 60138, + "order": "ASC" + } + ], + "decorations": [], + "public": false, + "row_identifier_type": "id", + "row_height_size": "small", + "field_options": [ + { + "id": 264222, + "field_id": 60209, + "width": 200, + "hidden": false, + "order": 0, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264223, + "field_id": 60138, + "width": 180, + "hidden": true, + "order": 1, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264224, + "field_id": 60139, + "width": 138, + "hidden": false, + "order": 2, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264225, + "field_id": 60152, + "width": 113, + "hidden": false, + "order": 3, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264226, + "field_id": 60140, + "width": 115, + "hidden": false, + "order": 4, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264227, + "field_id": 60141, + "width": 121, + "hidden": false, + "order": 5, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264228, + "field_id": 60142, + "width": 117, + "hidden": false, + "order": 6, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264229, + "field_id": 60143, + "width": 122, + "hidden": false, + "order": 7, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264230, + "field_id": 60144, + "width": 134, + "hidden": false, + "order": 8, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264231, + "field_id": 60145, + "width": 125, + "hidden": false, + "order": 9, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264232, + "field_id": 60146, + "width": 124, + "hidden": false, + "order": 10, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264233, + "field_id": 60147, + "width": 126, + "hidden": false, + "order": 11, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264234, + "field_id": 60148, + "width": 100, + "hidden": false, + "order": 12, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264235, + "field_id": 60149, + "width": 115, + "hidden": false, + "order": 13, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264236, + "field_id": 60150, + "width": 116, + "hidden": false, + "order": 14, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264237, + "field_id": 60151, + "width": 147, + "hidden": false, + "order": 15, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264238, + "field_id": 60188, + "width": 156, + "hidden": false, + "order": 16, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264239, + "field_id": 60189, + "width": 200, + "hidden": false, + "order": 17, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264240, + "field_id": 60190, + "width": 200, + "hidden": false, + "order": 18, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264241, + "field_id": 60191, + "width": 200, + "hidden": false, + "order": 19, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264242, + "field_id": 60197, + "width": 200, + "hidden": false, + "order": 20, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264243, + "field_id": 60198, + "width": 226, + "hidden": false, + "order": 21, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264244, + "field_id": 60204, + "width": 226, + "hidden": false, + "order": 22, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264245, + "field_id": 60210, + "width": 200, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + } + ] + }, + { + "id": 26649, + "type": "grid", + "name": "All potential assessments grouped by manager", + "order": 3, + "ownership_type": "collaborative", + "owned_by": "frederik@baserow.io", + "filter_type": "AND", + "filters_disabled": false, + "filters": [], + "filter_groups": [], + "sortings": [ + { + "id": 20547, + "field_id": 60152, + "order": "DESC" + }, + { + "id": 20548, + "field_id": 60197, + "order": "DESC" + } + ], + "group_bys": [ + { + "id": 3674, + "field_id": 60139, + "order": "ASC" + } + ], + "decorations": [], + "public": false, + "row_identifier_type": "id", + "row_height_size": "small", + "field_options": [ + { + "id": 264246, + "field_id": 60209, + "width": 200, + "hidden": false, + "order": 0, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264247, + "field_id": 60138, + "width": 180, + "hidden": false, + "order": 1, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264248, + "field_id": 60139, + "width": 138, + "hidden": true, + "order": 2, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264249, + "field_id": 60152, + "width": 113, + "hidden": false, + "order": 3, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264250, + "field_id": 60140, + "width": 115, + "hidden": false, + "order": 4, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264251, + "field_id": 60141, + "width": 121, + "hidden": false, + "order": 5, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264252, + "field_id": 60142, + "width": 117, + "hidden": false, + "order": 6, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264253, + "field_id": 60143, + "width": 122, + "hidden": false, + "order": 7, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264254, + "field_id": 60144, + "width": 134, + "hidden": false, + "order": 8, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264255, + "field_id": 60145, + "width": 125, + "hidden": false, + "order": 9, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264256, + "field_id": 60146, + "width": 124, + "hidden": false, + "order": 10, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264257, + "field_id": 60147, + "width": 126, + "hidden": false, + "order": 11, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264258, + "field_id": 60148, + "width": 100, + "hidden": false, + "order": 12, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264259, + "field_id": 60149, + "width": 115, + "hidden": false, + "order": 13, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264260, + "field_id": 60150, + "width": 116, + "hidden": false, + "order": 14, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264261, + "field_id": 60151, + "width": 147, + "hidden": false, + "order": 15, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264262, + "field_id": 60188, + "width": 156, + "hidden": false, + "order": 16, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264263, + "field_id": 60189, + "width": 200, + "hidden": false, + "order": 17, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264264, + "field_id": 60190, + "width": 200, + "hidden": false, + "order": 18, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264265, + "field_id": 60191, + "width": 200, + "hidden": false, + "order": 19, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264266, + "field_id": 60197, + "width": 200, + "hidden": false, + "order": 20, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264267, + "field_id": 60198, + "width": 226, + "hidden": false, + "order": 21, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264268, + "field_id": 60204, + "width": 226, + "hidden": false, + "order": 22, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264269, + "field_id": 60210, + "width": 200, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + } + ] + }, + { + "id": 26650, + "type": "grid", + "name": "All potential assessments grouped by year", + "order": 4, + "ownership_type": "collaborative", + "owned_by": "frederik@baserow.io", + "filter_type": "AND", + "filters_disabled": false, + "filters": [], + "filter_groups": [], + "sortings": [ + { + "id": 20549, + "field_id": 60152, + "order": "DESC" + }, + { + "id": 20550, + "field_id": 60197, + "order": "DESC" + } + ], + "group_bys": [ + { + "id": 3675, + "field_id": 60152, + "order": "DESC" + } + ], + "decorations": [], + "public": false, + "row_identifier_type": "id", + "row_height_size": "small", + "field_options": [ + { + "id": 264270, + "field_id": 60209, + "width": 200, + "hidden": false, + "order": 0, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264271, + "field_id": 60138, + "width": 180, + "hidden": false, + "order": 1, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264272, + "field_id": 60139, + "width": 138, + "hidden": false, + "order": 2, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264273, + "field_id": 60152, + "width": 113, + "hidden": false, + "order": 3, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264274, + "field_id": 60140, + "width": 115, + "hidden": false, + "order": 4, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264275, + "field_id": 60141, + "width": 121, + "hidden": false, + "order": 5, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264276, + "field_id": 60142, + "width": 117, + "hidden": false, + "order": 6, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264277, + "field_id": 60143, + "width": 122, + "hidden": false, + "order": 7, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264278, + "field_id": 60144, + "width": 134, + "hidden": false, + "order": 8, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264279, + "field_id": 60145, + "width": 125, + "hidden": false, + "order": 9, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264280, + "field_id": 60146, + "width": 124, + "hidden": false, + "order": 10, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264281, + "field_id": 60147, + "width": 126, + "hidden": false, + "order": 11, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264282, + "field_id": 60148, + "width": 100, + "hidden": false, + "order": 12, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264283, + "field_id": 60149, + "width": 115, + "hidden": false, + "order": 13, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264284, + "field_id": 60150, + "width": 116, + "hidden": false, + "order": 14, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264285, + "field_id": 60151, + "width": 147, + "hidden": false, + "order": 15, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264286, + "field_id": 60188, + "width": 156, + "hidden": false, + "order": 16, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264287, + "field_id": 60189, + "width": 200, + "hidden": false, + "order": 17, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264288, + "field_id": 60190, + "width": 200, + "hidden": false, + "order": 18, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264289, + "field_id": 60191, + "width": 200, + "hidden": false, + "order": 19, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264290, + "field_id": 60197, + "width": 200, + "hidden": false, + "order": 20, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264291, + "field_id": 60198, + "width": 226, + "hidden": false, + "order": 21, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264292, + "field_id": 60204, + "width": 226, + "hidden": false, + "order": 22, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264293, + "field_id": 60210, + "width": 200, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + } + ] + }, + { + "id": 26651, + "type": "grid", + "name": "Passed assessments", + "order": 5, + "ownership_type": "collaborative", + "owned_by": "frederik@baserow.io", + "filter_type": "AND", + "filters_disabled": false, + "filters": [ + { + "id": 14043, + "field_id": 60204, + "type": "boolean", + "value": "1", + "group": null + } + ], + "filter_groups": [], + "sortings": [ + { + "id": 20551, + "field_id": 60152, + "order": "DESC" + }, + { + "id": 20552, + "field_id": 60197, + "order": "DESC" + } + ], + "group_bys": [], + "decorations": [], + "public": false, + "row_identifier_type": "id", + "row_height_size": "small", + "field_options": [ + { + "id": 264294, + "field_id": 60209, + "width": 200, + "hidden": false, + "order": 0, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264295, + "field_id": 60138, + "width": 180, + "hidden": false, + "order": 1, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264296, + "field_id": 60139, + "width": 138, + "hidden": false, + "order": 2, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264297, + "field_id": 60152, + "width": 113, + "hidden": false, + "order": 3, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264298, + "field_id": 60140, + "width": 115, + "hidden": false, + "order": 4, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264299, + "field_id": 60141, + "width": 121, + "hidden": false, + "order": 5, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264300, + "field_id": 60142, + "width": 117, + "hidden": false, + "order": 6, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264301, + "field_id": 60143, + "width": 122, + "hidden": false, + "order": 7, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264302, + "field_id": 60144, + "width": 134, + "hidden": false, + "order": 8, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264303, + "field_id": 60145, + "width": 125, + "hidden": false, + "order": 9, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264304, + "field_id": 60146, + "width": 124, + "hidden": false, + "order": 10, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264305, + "field_id": 60147, + "width": 126, + "hidden": false, + "order": 11, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264306, + "field_id": 60148, + "width": 100, + "hidden": false, + "order": 12, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264307, + "field_id": 60149, + "width": 115, + "hidden": false, + "order": 13, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264308, + "field_id": 60150, + "width": 116, + "hidden": false, + "order": 14, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264309, + "field_id": 60151, + "width": 147, + "hidden": false, + "order": 15, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264310, + "field_id": 60188, + "width": 156, + "hidden": false, + "order": 16, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264311, + "field_id": 60189, + "width": 200, + "hidden": false, + "order": 17, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264312, + "field_id": 60190, + "width": 200, + "hidden": false, + "order": 18, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264313, + "field_id": 60191, + "width": 200, + "hidden": false, + "order": 19, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264314, + "field_id": 60197, + "width": 200, + "hidden": false, + "order": 20, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264315, + "field_id": 60198, + "width": 226, + "hidden": false, + "order": 21, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264316, + "field_id": 60204, + "width": 226, + "hidden": false, + "order": 22, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264317, + "field_id": 60210, + "width": 200, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + } + ] + }, + { + "id": 26652, + "type": "grid", + "name": "Failed assessments", + "order": 6, + "ownership_type": "collaborative", + "owned_by": "frederik@baserow.io", + "filter_type": "AND", + "filters_disabled": false, + "filters": [ + { + "id": 14044, + "field_id": 60204, + "type": "boolean", + "value": "0", + "group": null + } + ], + "filter_groups": [], + "sortings": [ + { + "id": 20553, + "field_id": 60152, + "order": "DESC" + }, + { + "id": 20554, + "field_id": 60197, + "order": "DESC" + } + ], + "group_bys": [], + "decorations": [], + "public": false, + "row_identifier_type": "id", + "row_height_size": "small", + "field_options": [ + { + "id": 264318, + "field_id": 60209, + "width": 200, + "hidden": false, + "order": 0, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264319, + "field_id": 60138, + "width": 180, + "hidden": false, + "order": 1, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264320, + "field_id": 60139, + "width": 138, + "hidden": false, + "order": 2, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264321, + "field_id": 60152, + "width": 113, + "hidden": false, + "order": 3, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264322, + "field_id": 60140, + "width": 115, + "hidden": false, + "order": 4, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264323, + "field_id": 60141, + "width": 121, + "hidden": false, + "order": 5, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264324, + "field_id": 60142, + "width": 117, + "hidden": false, + "order": 6, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264325, + "field_id": 60143, + "width": 122, + "hidden": false, + "order": 7, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264326, + "field_id": 60144, + "width": 134, + "hidden": false, + "order": 8, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264327, + "field_id": 60145, + "width": 125, + "hidden": false, + "order": 9, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264328, + "field_id": 60146, + "width": 124, + "hidden": false, + "order": 10, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264329, + "field_id": 60147, + "width": 126, + "hidden": false, + "order": 11, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264330, + "field_id": 60148, + "width": 100, + "hidden": false, + "order": 12, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264331, + "field_id": 60149, + "width": 115, + "hidden": false, + "order": 13, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264332, + "field_id": 60150, + "width": 116, + "hidden": false, + "order": 14, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264333, + "field_id": 60151, + "width": 147, + "hidden": false, + "order": 15, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264334, + "field_id": 60188, + "width": 156, + "hidden": false, + "order": 16, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264335, + "field_id": 60189, + "width": 200, + "hidden": false, + "order": 17, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264336, + "field_id": 60190, + "width": 200, + "hidden": false, + "order": 18, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264337, + "field_id": 60191, + "width": 200, + "hidden": false, + "order": 19, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264338, + "field_id": 60197, + "width": 200, + "hidden": false, + "order": 20, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264339, + "field_id": 60198, + "width": 226, + "hidden": false, + "order": 21, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264340, + "field_id": 60204, + "width": 226, + "hidden": false, + "order": 22, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264341, + "field_id": 60210, + "width": 200, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + } + ] + } + ], + "rows": [ + { + "id": 1, + "order": "1.00000000000000000000", + "created_on": "2025-02-18T09:52:27.834035+00:00", + "updated_on": "2025-02-18T10:19:05.474879+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60209": null, + "field_60138": [ + 9 + ], + "field_60139": [ + 1 + ], + "field_60140": [ + 1 + ], + "field_60141": [ + 1 + ], + "field_60142": [ + 1 + ], + "field_60143": [ + 2 + ], + "field_60144": [ + 1 + ], + "field_60145": [ + 2 + ], + "field_60146": [ + 1 + ], + "field_60147": [ + 1 + ], + "field_60148": [ + 1 + ], + "field_60149": [ + 1 + ], + "field_60150": [ + 1 + ], + "field_60151": [ + 1 + ], + "field_60188": null, + "field_60189": null, + "field_60190": null, + "field_60191": null, + "field_60197": null, + "field_60198": null, + "field_60204": null, + "field_60152": "2024", + "field_60210": null + }, + { + "id": 2, + "order": "2.00000000000000000000", + "created_on": "2025-02-18T09:52:27.834062+00:00", + "updated_on": "2025-02-18T10:19:06.811013+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60209": null, + "field_60138": [ + 14 + ], + "field_60139": [ + 3 + ], + "field_60140": [ + 2 + ], + "field_60141": [ + 2 + ], + "field_60142": [ + 1 + ], + "field_60143": [ + 1 + ], + "field_60144": [ + 2 + ], + "field_60145": [ + 1 + ], + "field_60146": [ + 1 + ], + "field_60147": [ + 2 + ], + "field_60148": [ + 1 + ], + "field_60149": [ + 1 + ], + "field_60150": [ + 1 + ], + "field_60151": [ + 1 + ], + "field_60188": null, + "field_60189": null, + "field_60190": null, + "field_60191": null, + "field_60197": null, + "field_60198": null, + "field_60204": null, + "field_60152": "2024", + "field_60210": null + }, + { + "id": 3, + "order": "3.00000000000000000000", + "created_on": "2025-02-18T09:53:31.892872+00:00", + "updated_on": "2025-02-18T10:19:08.859672+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60209": null, + "field_60138": [ + 16 + ], + "field_60139": [ + 3 + ], + "field_60140": [ + 2 + ], + "field_60141": [ + 2 + ], + "field_60142": [ + 2 + ], + "field_60143": [ + 2 + ], + "field_60144": [ + 2 + ], + "field_60145": [ + 2 + ], + "field_60146": [ + 1 + ], + "field_60147": [ + 1 + ], + "field_60148": [ + 1 + ], + "field_60149": [ + 2 + ], + "field_60150": [ + 2 + ], + "field_60151": [ + 2 + ], + "field_60188": null, + "field_60189": null, + "field_60190": null, + "field_60191": null, + "field_60197": null, + "field_60198": null, + "field_60204": null, + "field_60152": "2024", + "field_60210": null + }, + { + "id": 4, + "order": "4.00000000000000000000", + "created_on": "2025-02-18T18:59:34.748176+00:00", + "updated_on": "2025-02-18T19:15:58.094517+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60209": null, + "field_60138": [ + 15 + ], + "field_60139": [ + 3 + ], + "field_60140": [ + 1 + ], + "field_60141": [ + 1 + ], + "field_60142": [ + 1 + ], + "field_60143": [ + 1 + ], + "field_60144": [ + 1 + ], + "field_60145": [ + 2 + ], + "field_60146": [ + 2 + ], + "field_60147": [ + 1 + ], + "field_60148": [ + 1 + ], + "field_60149": [ + 1 + ], + "field_60150": [ + 2 + ], + "field_60151": [ + 2 + ], + "field_60188": null, + "field_60189": null, + "field_60190": null, + "field_60191": null, + "field_60197": null, + "field_60198": null, + "field_60204": null, + "field_60152": "2025", + "field_60210": null + }, + { + "id": 5, + "order": "5.00000000000000000000", + "created_on": "2025-02-19T08:29:01.063819+00:00", + "updated_on": "2025-02-19T08:29:26.410589+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60209": null, + "field_60138": [ + 7 + ], + "field_60139": [ + 1 + ], + "field_60140": [ + 1 + ], + "field_60141": [ + 1 + ], + "field_60142": [ + 2 + ], + "field_60143": [ + 1 + ], + "field_60144": [ + 1 + ], + "field_60145": [ + 1 + ], + "field_60146": [ + 2 + ], + "field_60147": [ + 1 + ], + "field_60148": [ + 1 + ], + "field_60149": [ + 1 + ], + "field_60150": [ + 1 + ], + "field_60151": [ + 2 + ], + "field_60188": null, + "field_60189": null, + "field_60190": null, + "field_60191": null, + "field_60197": null, + "field_60198": null, + "field_60204": null, + "field_60152": "2025", + "field_60210": null + }, + { + "id": 6, + "order": "6.00000000000000000000", + "created_on": "2025-02-19T12:26:19.574862+00:00", + "updated_on": "2025-02-19T12:26:32.818213+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60209": null, + "field_60138": [ + 11 + ], + "field_60139": [ + 2 + ], + "field_60140": [ + 1 + ], + "field_60141": [ + 2 + ], + "field_60142": [ + 2 + ], + "field_60143": [ + 1 + ], + "field_60144": [ + 1 + ], + "field_60145": [ + 2 + ], + "field_60146": [ + 1 + ], + "field_60147": [ + 1 + ], + "field_60148": [ + 2 + ], + "field_60149": [ + 1 + ], + "field_60150": [ + 1 + ], + "field_60151": [ + 1 + ], + "field_60188": null, + "field_60189": null, + "field_60190": null, + "field_60191": null, + "field_60197": null, + "field_60198": null, + "field_60204": null, + "field_60152": "2025", + "field_60210": null + }, + { + "id": 7, + "order": "7.00000000000000000000", + "created_on": "2025-02-19T12:28:36.325224+00:00", + "updated_on": "2025-02-19T12:28:36.325224+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60209": null, + "field_60138": [ + 9 + ], + "field_60139": [ + 1 + ], + "field_60140": [ + 1 + ], + "field_60141": [ + 1 + ], + "field_60142": [ + 2 + ], + "field_60143": [ + 1 + ], + "field_60144": [ + 1 + ], + "field_60145": [ + 1 + ], + "field_60146": [ + 1 + ], + "field_60147": [ + 2 + ], + "field_60148": [ + 1 + ], + "field_60149": [ + 2 + ], + "field_60150": [ + 1 + ], + "field_60151": [ + 1 + ], + "field_60188": null, + "field_60189": null, + "field_60190": null, + "field_60191": null, + "field_60197": null, + "field_60198": null, + "field_60204": null, + "field_60152": "2025", + "field_60210": null + }, + { + "id": 8, + "order": "8.00000000000000000000", + "created_on": "2025-02-19T12:29:33.888975+00:00", + "updated_on": "2025-02-19T12:29:41.901802+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60209": null, + "field_60138": [ + 6 + ], + "field_60139": [ + 1 + ], + "field_60140": [ + 2 + ], + "field_60141": [ + 1 + ], + "field_60142": [ + 1 + ], + "field_60143": [ + 2 + ], + "field_60144": [ + 2 + ], + "field_60145": [ + 2 + ], + "field_60146": [ + 1 + ], + "field_60147": [ + 1 + ], + "field_60148": [ + 1 + ], + "field_60149": [ + 2 + ], + "field_60150": [ + 2 + ], + "field_60151": [ + 1 + ], + "field_60188": null, + "field_60189": null, + "field_60190": null, + "field_60191": null, + "field_60197": null, + "field_60198": null, + "field_60204": null, + "field_60152": "2025", + "field_60210": null + }, + { + "id": 9, + "order": "9.00000000000000000000", + "created_on": "2025-02-19T12:31:20.030391+00:00", + "updated_on": "2025-02-19T12:31:20.030391+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60209": null, + "field_60138": [ + 10 + ], + "field_60139": [ + 2 + ], + "field_60140": [ + 1 + ], + "field_60141": [ + 1 + ], + "field_60142": [ + 1 + ], + "field_60143": [ + 2 + ], + "field_60144": [ + 2 + ], + "field_60145": [ + 1 + ], + "field_60146": [ + 2 + ], + "field_60147": [ + 1 + ], + "field_60148": [ + 2 + ], + "field_60149": [ + 1 + ], + "field_60150": [ + 1 + ], + "field_60151": [ + 1 + ], + "field_60188": null, + "field_60189": null, + "field_60190": null, + "field_60191": null, + "field_60197": null, + "field_60198": null, + "field_60204": null, + "field_60152": "2025", + "field_60210": null + } + ], + "data_sync": null + }, + { + "id": 5734, + "name": "Potential assessment scales", + "order": 8, + "fields": [ + { + "id": 60153, + "type": "text", + "name": "Name", + "description": null, + "order": 0, + "primary": true, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "text_default": "" + }, + { + "id": 60154, + "type": "number", + "name": "Score", + "description": null, + "order": 1, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "number_decimal_places": 0, + "number_negative": false, + "number_prefix": "", + "number_suffix": "", + "number_separator": "" + } + ], + "views": [ + { + "id": 26628, + "type": "grid", + "name": "All scales", + "order": 1, + "ownership_type": "collaborative", + "owned_by": "frederik@baserow.io", + "filter_type": "AND", + "filters_disabled": false, + "filters": [], + "filter_groups": [], + "sortings": [], + "group_bys": [], + "decorations": [], + "public": false, + "row_identifier_type": "id", + "row_height_size": "small", + "field_options": [ + { + "id": 263656, + "field_id": 60153, + "width": 134, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263657, + "field_id": 60154, + "width": 106, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + } + ] + } + ], + "rows": [ + { + "id": 1, + "order": "1.00000000000000000000", + "created_on": "2025-02-18T09:56:25.760470+00:00", + "updated_on": "2025-02-18T09:56:47.721370+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60153": "Always", + "field_60154": "1" + }, + { + "id": 2, + "order": "2.00000000000000000000", + "created_on": "2025-02-18T09:56:25.760491+00:00", + "updated_on": "2025-02-18T09:56:55.832264+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60153": "Occasionally", + "field_60154": "0" + } + ], + "data_sync": null + }, + { + "id": 5735, + "name": "Ability assessments", + "order": 9, + "fields": [ + { + "id": 60200, + "type": "formula", + "name": "Name", + "description": null, + "order": 0, + "primary": true, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "date_show_tzinfo": null, + "nullable": false, + "number_decimal_places": null, + "number_separator": "", + "date_format": null, + "number_prefix": "", + "number_suffix": "", + "duration_format": null, + "array_formula_type": null, + "date_time_format": null, + "error": null, + "date_force_timezone": null, + "date_include_time": null, + "formula": "concat(min(lookup('Employee','Name')),' - ', field('Year'),' - ',field('Has ability'))", + "formula_type": "text" + }, + { + "id": 60155, + "type": "link_row", + "name": "Employee", + "description": null, + "order": 1, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "link_row_table_id": 5730, + "link_row_related_field_id": 60127, + "link_row_limit_selection_view_id": null, + "has_related_field": true + }, + { + "id": 60156, + "type": "link_row", + "name": "Manager", + "description": null, + "order": 2, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "link_row_table_id": 5730, + "link_row_related_field_id": null, + "link_row_limit_selection_view_id": null, + "has_related_field": false + }, + { + "id": 60157, + "type": "number", + "name": "Year", + "description": null, + "order": 3, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "number_decimal_places": 0, + "number_negative": false, + "number_prefix": "", + "number_suffix": "", + "number_separator": "" + }, + { + "id": 60158, + "type": "boolean", + "name": "Question 1", + "description": null, + "order": 4, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false + }, + { + "id": 60159, + "type": "boolean", + "name": "Question 2", + "description": null, + "order": 5, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false + }, + { + "id": 60160, + "type": "boolean", + "name": "Question 3", + "description": null, + "order": 6, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false + }, + { + "id": 60192, + "type": "formula", + "name": "Has ability", + "description": null, + "order": 7, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "date_show_tzinfo": null, + "nullable": false, + "number_decimal_places": null, + "number_separator": "", + "date_format": null, + "number_prefix": "", + "number_suffix": "", + "duration_format": null, + "array_formula_type": null, + "date_time_format": null, + "error": null, + "date_force_timezone": null, + "date_include_time": null, + "formula": "and(and(field('Question 1'),field('Question 2')),field('Question 3'))", + "formula_type": "boolean" + }, + { + "id": 60201, + "type": "formula", + "name": "Has ability symbol", + "description": null, + "order": 8, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "date_show_tzinfo": null, + "nullable": false, + "number_decimal_places": null, + "number_separator": "", + "date_format": null, + "number_prefix": "", + "number_suffix": "", + "duration_format": null, + "array_formula_type": null, + "date_time_format": null, + "error": null, + "date_force_timezone": null, + "date_include_time": null, + "formula": "if(field('Has ability'),'\u2714\ufe0f ','\u274c')", + "formula_type": "text" + } + ], + "views": [ + { + "id": 26629, + "type": "grid", + "name": "All ability assessments", + "order": 1, + "ownership_type": "collaborative", + "owned_by": "frederik@baserow.io", + "filter_type": "AND", + "filters_disabled": false, + "filters": [], + "filter_groups": [], + "sortings": [ + { + "id": 20555, + "field_id": 60157, + "order": "DESC" + }, + { + "id": 20556, + "field_id": 60192, + "order": "DESC" + } + ], + "group_bys": [], + "decorations": [], + "public": false, + "row_identifier_type": "id", + "row_height_size": "small", + "field_options": [ + { + "id": 263658, + "field_id": 60200, + "width": 200, + "hidden": false, + "order": 0, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263659, + "field_id": 60155, + "width": 135, + "hidden": false, + "order": 1, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263660, + "field_id": 60156, + "width": 141, + "hidden": false, + "order": 2, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263661, + "field_id": 60157, + "width": 102, + "hidden": false, + "order": 3, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263662, + "field_id": 60158, + "width": 138, + "hidden": false, + "order": 4, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263663, + "field_id": 60159, + "width": 139, + "hidden": false, + "order": 5, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263664, + "field_id": 60160, + "width": 148, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263665, + "field_id": 60192, + "width": 200, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263666, + "field_id": 60201, + "width": 200, + "hidden": true, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + } + ] + }, + { + "id": 26653, + "type": "grid", + "name": "All ability assessments grouped by employee", + "order": 2, + "ownership_type": "collaborative", + "owned_by": "frederik@baserow.io", + "filter_type": "AND", + "filters_disabled": false, + "filters": [], + "filter_groups": [], + "sortings": [ + { + "id": 20557, + "field_id": 60157, + "order": "DESC" + }, + { + "id": 20558, + "field_id": 60192, + "order": "DESC" + } + ], + "group_bys": [ + { + "id": 3678, + "field_id": 60155, + "order": "ASC" + } + ], + "decorations": [], + "public": false, + "row_identifier_type": "id", + "row_height_size": "small", + "field_options": [ + { + "id": 264342, + "field_id": 60200, + "width": 200, + "hidden": false, + "order": 0, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264343, + "field_id": 60155, + "width": 135, + "hidden": true, + "order": 1, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264344, + "field_id": 60156, + "width": 141, + "hidden": false, + "order": 2, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264345, + "field_id": 60157, + "width": 102, + "hidden": false, + "order": 3, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264346, + "field_id": 60158, + "width": 138, + "hidden": false, + "order": 4, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264347, + "field_id": 60159, + "width": 139, + "hidden": false, + "order": 5, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264348, + "field_id": 60160, + "width": 148, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264349, + "field_id": 60192, + "width": 200, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264350, + "field_id": 60201, + "width": 200, + "hidden": true, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + } + ] + }, + { + "id": 26654, + "type": "grid", + "name": "All ability assessments grouped by manager", + "order": 3, + "ownership_type": "collaborative", + "owned_by": "frederik@baserow.io", + "filter_type": "AND", + "filters_disabled": false, + "filters": [], + "filter_groups": [], + "sortings": [ + { + "id": 20559, + "field_id": 60157, + "order": "DESC" + }, + { + "id": 20560, + "field_id": 60192, + "order": "DESC" + } + ], + "group_bys": [ + { + "id": 3679, + "field_id": 60156, + "order": "ASC" + } + ], + "decorations": [], + "public": false, + "row_identifier_type": "id", + "row_height_size": "small", + "field_options": [ + { + "id": 264351, + "field_id": 60200, + "width": 200, + "hidden": false, + "order": 0, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264352, + "field_id": 60155, + "width": 135, + "hidden": false, + "order": 1, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264353, + "field_id": 60156, + "width": 141, + "hidden": true, + "order": 2, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264354, + "field_id": 60157, + "width": 102, + "hidden": false, + "order": 3, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264355, + "field_id": 60158, + "width": 138, + "hidden": false, + "order": 4, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264356, + "field_id": 60159, + "width": 139, + "hidden": false, + "order": 5, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264357, + "field_id": 60160, + "width": 148, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264358, + "field_id": 60192, + "width": 200, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264359, + "field_id": 60201, + "width": 200, + "hidden": true, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + } + ] + }, + { + "id": 26655, + "type": "grid", + "name": "All ability assessments grouped by year", + "order": 4, + "ownership_type": "collaborative", + "owned_by": "frederik@baserow.io", + "filter_type": "AND", + "filters_disabled": false, + "filters": [], + "filter_groups": [], + "sortings": [ + { + "id": 20561, + "field_id": 60157, + "order": "DESC" + }, + { + "id": 20562, + "field_id": 60192, + "order": "DESC" + } + ], + "group_bys": [ + { + "id": 3680, + "field_id": 60157, + "order": "DESC" + } + ], + "decorations": [], + "public": false, + "row_identifier_type": "id", + "row_height_size": "small", + "field_options": [ + { + "id": 264360, + "field_id": 60200, + "width": 200, + "hidden": false, + "order": 0, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264361, + "field_id": 60155, + "width": 135, + "hidden": false, + "order": 1, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264362, + "field_id": 60156, + "width": 141, + "hidden": false, + "order": 2, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264363, + "field_id": 60157, + "width": 102, + "hidden": true, + "order": 3, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264364, + "field_id": 60158, + "width": 138, + "hidden": false, + "order": 4, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264365, + "field_id": 60159, + "width": 139, + "hidden": false, + "order": 5, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264366, + "field_id": 60160, + "width": 148, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264367, + "field_id": 60192, + "width": 200, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264368, + "field_id": 60201, + "width": 200, + "hidden": true, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + } + ] + }, + { + "id": 26656, + "type": "grid", + "name": "Passed tests", + "order": 5, + "ownership_type": "collaborative", + "owned_by": "frederik@baserow.io", + "filter_type": "AND", + "filters_disabled": false, + "filters": [ + { + "id": 14045, + "field_id": 60192, + "type": "boolean", + "value": "1", + "group": null + } + ], + "filter_groups": [], + "sortings": [ + { + "id": 20563, + "field_id": 60157, + "order": "DESC" + }, + { + "id": 20564, + "field_id": 60192, + "order": "DESC" + } + ], + "group_bys": [], + "decorations": [], + "public": false, + "row_identifier_type": "id", + "row_height_size": "small", + "field_options": [ + { + "id": 264369, + "field_id": 60200, + "width": 200, + "hidden": false, + "order": 0, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264370, + "field_id": 60155, + "width": 135, + "hidden": false, + "order": 1, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264371, + "field_id": 60156, + "width": 141, + "hidden": false, + "order": 2, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264372, + "field_id": 60157, + "width": 102, + "hidden": false, + "order": 3, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264373, + "field_id": 60158, + "width": 138, + "hidden": false, + "order": 4, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264374, + "field_id": 60159, + "width": 139, + "hidden": false, + "order": 5, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264375, + "field_id": 60160, + "width": 148, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264376, + "field_id": 60192, + "width": 200, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264377, + "field_id": 60201, + "width": 200, + "hidden": true, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + } + ] + }, + { + "id": 26657, + "type": "grid", + "name": "Failed tests", + "order": 6, + "ownership_type": "collaborative", + "owned_by": "frederik@baserow.io", + "filter_type": "AND", + "filters_disabled": false, + "filters": [ + { + "id": 14046, + "field_id": 60192, + "type": "boolean", + "value": "0", + "group": null + } + ], + "filter_groups": [], + "sortings": [ + { + "id": 20565, + "field_id": 60157, + "order": "DESC" + }, + { + "id": 20566, + "field_id": 60192, + "order": "DESC" + } + ], + "group_bys": [], + "decorations": [], + "public": false, + "row_identifier_type": "id", + "row_height_size": "small", + "field_options": [ + { + "id": 264378, + "field_id": 60200, + "width": 200, + "hidden": false, + "order": 0, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264379, + "field_id": 60155, + "width": 135, + "hidden": false, + "order": 1, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264380, + "field_id": 60156, + "width": 141, + "hidden": false, + "order": 2, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264381, + "field_id": 60157, + "width": 102, + "hidden": false, + "order": 3, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264382, + "field_id": 60158, + "width": 138, + "hidden": false, + "order": 4, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264383, + "field_id": 60159, + "width": 139, + "hidden": false, + "order": 5, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264384, + "field_id": 60160, + "width": 148, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264385, + "field_id": 60192, + "width": 200, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264386, + "field_id": 60201, + "width": 200, + "hidden": true, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + } + ] + } + ], + "rows": [ + { + "id": 1, + "order": "1.00000000000000000000", + "created_on": "2025-02-18T10:14:20.975347+00:00", + "updated_on": "2025-02-18T10:27:14.229303+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60200": null, + "field_60155": [ + 9 + ], + "field_60156": [ + 1 + ], + "field_60157": "2024", + "field_60158": "true", + "field_60159": "true", + "field_60160": "true", + "field_60192": null, + "field_60201": null + }, + { + "id": 2, + "order": "2.00000000000000000000", + "created_on": "2025-02-18T10:14:20.975382+00:00", + "updated_on": "2025-02-18T10:25:33.064415+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60200": null, + "field_60155": [ + 14 + ], + "field_60156": [ + 3 + ], + "field_60157": "2024", + "field_60158": "true", + "field_60159": "false", + "field_60160": "true", + "field_60192": null, + "field_60201": null + }, + { + "id": 3, + "order": "3.00000000000000000000", + "created_on": "2025-02-19T08:30:43.233315+00:00", + "updated_on": "2025-02-19T10:09:41.459968+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60200": null, + "field_60155": [ + 7 + ], + "field_60156": [ + 1 + ], + "field_60157": "2025", + "field_60158": "true", + "field_60159": "true", + "field_60160": "true", + "field_60192": null, + "field_60201": null + }, + { + "id": 4, + "order": "4.00000000000000000000", + "created_on": "2025-02-19T12:26:41.961990+00:00", + "updated_on": "2025-02-19T12:26:41.961990+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60200": null, + "field_60155": [ + 11 + ], + "field_60156": [ + 2 + ], + "field_60157": "2025", + "field_60158": "true", + "field_60159": "true", + "field_60160": "true", + "field_60192": null, + "field_60201": null + }, + { + "id": 5, + "order": "5.00000000000000000000", + "created_on": "2025-02-19T12:28:47.204913+00:00", + "updated_on": "2025-02-19T12:28:47.204913+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60200": null, + "field_60155": [ + 9 + ], + "field_60156": [ + 1 + ], + "field_60157": "2025", + "field_60158": "true", + "field_60159": "true", + "field_60160": "true", + "field_60192": null, + "field_60201": null + }, + { + "id": 6, + "order": "6.00000000000000000000", + "created_on": "2025-02-19T12:31:50.929376+00:00", + "updated_on": "2025-02-19T12:31:50.929376+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60200": null, + "field_60155": [ + 10 + ], + "field_60156": [ + 2 + ], + "field_60157": "2025", + "field_60158": "true", + "field_60159": "true", + "field_60160": "true", + "field_60192": null, + "field_60201": null + } + ], + "data_sync": null + }, + { + "id": 5736, + "name": "Accelerated assessment", + "order": 10, + "fields": [ + { + "id": 60184, + "type": "formula", + "name": "Name", + "description": null, + "order": 0, + "primary": true, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "date_show_tzinfo": null, + "nullable": false, + "number_decimal_places": null, + "number_separator": "", + "date_format": null, + "number_prefix": "", + "number_suffix": "", + "duration_format": null, + "array_formula_type": null, + "date_time_format": null, + "error": null, + "date_force_timezone": null, + "date_include_time": null, + "formula": "concat(min(lookup('Employee','Name')),' - ', field('Year'))", + "formula_type": "text" + }, + { + "id": 60161, + "type": "link_row", + "name": "Employee", + "description": null, + "order": 1, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "link_row_table_id": 5730, + "link_row_related_field_id": 60129, + "link_row_limit_selection_view_id": null, + "has_related_field": true + }, + { + "id": 60162, + "type": "link_row", + "name": "Manager", + "description": null, + "order": 2, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "link_row_table_id": 5730, + "link_row_related_field_id": null, + "link_row_limit_selection_view_id": null, + "has_related_field": false + }, + { + "id": 60163, + "type": "number", + "name": "Year", + "description": null, + "order": 3, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "number_decimal_places": 0, + "number_negative": false, + "number_prefix": "", + "number_suffix": "", + "number_separator": "" + }, + { + "id": 60164, + "type": "long_text", + "name": "Strength 1", + "description": null, + "order": 4, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "long_text_enable_rich_text": false + }, + { + "id": 60165, + "type": "long_text", + "name": "Strength 2", + "description": null, + "order": 5, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "long_text_enable_rich_text": false + }, + { + "id": 60166, + "type": "long_text", + "name": "Strength 3", + "description": null, + "order": 6, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "long_text_enable_rich_text": false + }, + { + "id": 60167, + "type": "long_text", + "name": "Development 1", + "description": null, + "order": 7, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "long_text_enable_rich_text": false + }, + { + "id": 60168, + "type": "long_text", + "name": "Development 2", + "description": null, + "order": 8, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "long_text_enable_rich_text": false + }, + { + "id": 60169, + "type": "long_text", + "name": "Development 3", + "description": null, + "order": 9, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "long_text_enable_rich_text": false + }, + { + "id": 60170, + "type": "long_text", + "name": "Retention risk", + "description": null, + "order": 10, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "long_text_enable_rich_text": false + }, + { + "id": 60171, + "type": "long_text", + "name": "Impact of loss", + "description": null, + "order": 11, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "long_text_enable_rich_text": false + }, + { + "id": 60172, + "type": "long_text", + "name": "New to position", + "description": null, + "order": 12, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "long_text_enable_rich_text": false + }, + { + "id": 60173, + "type": "long_text", + "name": "Willingness to relocate", + "description": null, + "order": 13, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "long_text_enable_rich_text": false + }, + { + "id": 60174, + "type": "long_text", + "name": "Desired locations", + "description": null, + "order": 14, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "long_text_enable_rich_text": false + }, + { + "id": 60175, + "type": "long_text", + "name": "Comments", + "description": null, + "order": 15, + "primary": false, + "read_only": false, + "immutable_type": false, + "immutable_properties": false, + "long_text_enable_rich_text": false + } + ], + "views": [ + { + "id": 26630, + "type": "grid", + "name": "All accelerated assessments", + "order": 1, + "ownership_type": "collaborative", + "owned_by": "frederik@baserow.io", + "filter_type": "AND", + "filters_disabled": false, + "filters": [], + "filter_groups": [], + "sortings": [ + { + "id": 20567, + "field_id": 60163, + "order": "DESC" + } + ], + "group_bys": [], + "decorations": [], + "public": false, + "row_identifier_type": "id", + "row_height_size": "small", + "field_options": [ + { + "id": 263667, + "field_id": 60184, + "width": 200, + "hidden": false, + "order": 0, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263668, + "field_id": 60161, + "width": 142, + "hidden": false, + "order": 1, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263669, + "field_id": 60162, + "width": 138, + "hidden": false, + "order": 2, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263670, + "field_id": 60163, + "width": 135, + "hidden": false, + "order": 3, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263671, + "field_id": 60164, + "width": 200, + "hidden": false, + "order": 4, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263672, + "field_id": 60165, + "width": 200, + "hidden": false, + "order": 5, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263673, + "field_id": 60166, + "width": 200, + "hidden": false, + "order": 6, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263674, + "field_id": 60167, + "width": 200, + "hidden": false, + "order": 7, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263675, + "field_id": 60168, + "width": 200, + "hidden": false, + "order": 8, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263676, + "field_id": 60169, + "width": 200, + "hidden": false, + "order": 9, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263677, + "field_id": 60170, + "width": 200, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263678, + "field_id": 60171, + "width": 200, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263679, + "field_id": 60172, + "width": 200, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263680, + "field_id": 60173, + "width": 200, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263681, + "field_id": 60174, + "width": 200, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 263682, + "field_id": 60175, + "width": 200, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + } + ] + }, + { + "id": 26658, + "type": "grid", + "name": "All accelerated assessments grouped by employee", + "order": 2, + "ownership_type": "collaborative", + "owned_by": "frederik@baserow.io", + "filter_type": "AND", + "filters_disabled": false, + "filters": [], + "filter_groups": [], + "sortings": [ + { + "id": 20568, + "field_id": 60163, + "order": "DESC" + } + ], + "group_bys": [ + { + "id": 3681, + "field_id": 60161, + "order": "ASC" + } + ], + "decorations": [], + "public": false, + "row_identifier_type": "id", + "row_height_size": "small", + "field_options": [ + { + "id": 264387, + "field_id": 60184, + "width": 200, + "hidden": false, + "order": 0, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264388, + "field_id": 60161, + "width": 142, + "hidden": true, + "order": 1, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264389, + "field_id": 60162, + "width": 138, + "hidden": false, + "order": 2, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264390, + "field_id": 60163, + "width": 135, + "hidden": false, + "order": 3, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264391, + "field_id": 60164, + "width": 200, + "hidden": false, + "order": 4, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264392, + "field_id": 60165, + "width": 200, + "hidden": false, + "order": 5, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264393, + "field_id": 60166, + "width": 200, + "hidden": false, + "order": 6, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264394, + "field_id": 60167, + "width": 200, + "hidden": false, + "order": 7, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264395, + "field_id": 60168, + "width": 200, + "hidden": false, + "order": 8, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264396, + "field_id": 60169, + "width": 200, + "hidden": false, + "order": 9, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264397, + "field_id": 60170, + "width": 200, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264398, + "field_id": 60171, + "width": 200, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264399, + "field_id": 60172, + "width": 200, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264400, + "field_id": 60173, + "width": 200, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264401, + "field_id": 60174, + "width": 200, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264402, + "field_id": 60175, + "width": 200, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + } + ] + }, + { + "id": 26659, + "type": "grid", + "name": "All accelerated assessments grouped by manager", + "order": 3, + "ownership_type": "collaborative", + "owned_by": "frederik@baserow.io", + "filter_type": "AND", + "filters_disabled": false, + "filters": [], + "filter_groups": [], + "sortings": [ + { + "id": 20569, + "field_id": 60163, + "order": "DESC" + } + ], + "group_bys": [ + { + "id": 3682, + "field_id": 60162, + "order": "ASC" + } + ], + "decorations": [], + "public": false, + "row_identifier_type": "id", + "row_height_size": "small", + "field_options": [ + { + "id": 264403, + "field_id": 60184, + "width": 200, + "hidden": false, + "order": 0, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264404, + "field_id": 60161, + "width": 142, + "hidden": false, + "order": 1, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264405, + "field_id": 60162, + "width": 138, + "hidden": true, + "order": 2, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264406, + "field_id": 60163, + "width": 135, + "hidden": false, + "order": 3, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264407, + "field_id": 60164, + "width": 200, + "hidden": false, + "order": 4, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264408, + "field_id": 60165, + "width": 200, + "hidden": false, + "order": 5, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264409, + "field_id": 60166, + "width": 200, + "hidden": false, + "order": 6, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264410, + "field_id": 60167, + "width": 200, + "hidden": false, + "order": 7, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264411, + "field_id": 60168, + "width": 200, + "hidden": false, + "order": 8, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264412, + "field_id": 60169, + "width": 200, + "hidden": false, + "order": 9, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264413, + "field_id": 60170, + "width": 200, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264414, + "field_id": 60171, + "width": 200, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264415, + "field_id": 60172, + "width": 200, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264416, + "field_id": 60173, + "width": 200, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264417, + "field_id": 60174, + "width": 200, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264418, + "field_id": 60175, + "width": 200, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + } + ] + }, + { + "id": 26660, + "type": "grid", + "name": "All accelerated assessments grouped by year", + "order": 4, + "ownership_type": "collaborative", + "owned_by": "frederik@baserow.io", + "filter_type": "AND", + "filters_disabled": false, + "filters": [], + "filter_groups": [], + "sortings": [ + { + "id": 20570, + "field_id": 60163, + "order": "DESC" + } + ], + "group_bys": [ + { + "id": 3683, + "field_id": 60163, + "order": "ASC" + } + ], + "decorations": [], + "public": false, + "row_identifier_type": "id", + "row_height_size": "small", + "field_options": [ + { + "id": 264419, + "field_id": 60184, + "width": 200, + "hidden": false, + "order": 0, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264420, + "field_id": 60161, + "width": 142, + "hidden": false, + "order": 1, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264421, + "field_id": 60162, + "width": 138, + "hidden": false, + "order": 2, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264422, + "field_id": 60163, + "width": 135, + "hidden": true, + "order": 3, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264423, + "field_id": 60164, + "width": 200, + "hidden": false, + "order": 4, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264424, + "field_id": 60165, + "width": 200, + "hidden": false, + "order": 5, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264425, + "field_id": 60166, + "width": 200, + "hidden": false, + "order": 6, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264426, + "field_id": 60167, + "width": 200, + "hidden": false, + "order": 7, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264427, + "field_id": 60168, + "width": 200, + "hidden": false, + "order": 8, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264428, + "field_id": 60169, + "width": 200, + "hidden": false, + "order": 9, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264429, + "field_id": 60170, + "width": 200, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264430, + "field_id": 60171, + "width": 200, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264431, + "field_id": 60172, + "width": 200, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264432, + "field_id": 60173, + "width": 200, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264433, + "field_id": 60174, + "width": 200, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + }, + { + "id": 264434, + "field_id": 60175, + "width": 200, + "hidden": false, + "order": 32767, + "aggregation_type": "", + "aggregation_raw_type": "" + } + ] + } + ], + "rows": [ + { + "id": 1, + "order": "1.00000000000000000000", + "created_on": "2025-02-19T08:38:49.436747+00:00", + "updated_on": "2025-02-19T08:49:31.612177+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60184": null, + "field_60161": [ + 9 + ], + "field_60162": [ + 1 + ], + "field_60163": "2024", + "field_60164": "Leadership", + "field_60165": "Strategic thinking", + "field_60166": "Empathy", + "field_60167": "Public speaking", + "field_60168": "Time management", + "field_60169": "Project management", + "field_60170": "Low", + "field_60171": "High", + "field_60172": "Yes", + "field_60173": "Yes", + "field_60174": "New York", + "field_60175": "Excellent leadership potential." + }, + { + "id": 2, + "order": "2.00000000000000000000", + "created_on": "2025-02-19T08:38:49.436781+00:00", + "updated_on": "2025-02-19T10:10:52.892506+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60184": null, + "field_60161": [ + 7 + ], + "field_60162": [ + 1 + ], + "field_60163": "2025", + "field_60164": "Problem-solving", + "field_60165": "Creativity", + "field_60166": "Attention to detail", + "field_60167": "Delegation", + "field_60168": "Technical skills", + "field_60169": "Adaptability", + "field_60170": "Medium", + "field_60171": "Medium", + "field_60172": "No", + "field_60173": "No", + "field_60174": "San Francisco", + "field_60175": "Needs improvement in technical skills." + }, + { + "id": 3, + "order": "3.00000000000000000000", + "created_on": "2025-02-19T08:49:09.679145+00:00", + "updated_on": "2025-02-19T12:27:21.731140+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60184": null, + "field_60161": [ + 11 + ], + "field_60162": [ + 2 + ], + "field_60163": "2025", + "field_60164": "Communication", + "field_60165": "Time management", + "field_60166": "Innovation", + "field_60167": "Conflict resolution", + "field_60168": "Leadership", + "field_60169": "Problem-solving", + "field_60170": "High", + "field_60171": "Low", + "field_60172": "Yes", + "field_60173": "Maybe", + "field_60174": "Remote", + "field_60175": "Highly adaptable to new environments." + }, + { + "id": 4, + "order": "4.00000000000000000000", + "created_on": "2025-02-19T08:49:09.679170+00:00", + "updated_on": "2025-02-19T12:27:37.309938+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60184": null, + "field_60161": [ + 9 + ], + "field_60162": [ + 1 + ], + "field_60163": "2025", + "field_60164": "Teamwork", + "field_60165": "Analytical skills", + "field_60166": "Negotiation", + "field_60167": "Networking", + "field_60168": "Stress management", + "field_60169": "Teamwork", + "field_60170": "Low", + "field_60171": "High", + "field_60172": "No", + "field_60173": "Yes", + "field_60174": "London", + "field_60175": "Strong team player with excellent communication skills." + }, + { + "id": 5, + "order": "5.00000000000000000000", + "created_on": "2025-02-19T08:49:09.679183+00:00", + "updated_on": "2025-02-19T12:32:14.127785+00:00", + "created_by": "frederik@baserow.io", + "last_modified_by": "frederik@baserow.io", + "field_60184": null, + "field_60161": [ + 10 + ], + "field_60162": [ + 2 + ], + "field_60163": "2025", + "field_60164": "Adaptability", + "field_60165": "Project management", + "field_60166": "Technical expertise", + "field_60167": "Decision-making", + "field_60168": "Communication", + "field_60169": "Strategic thinking", + "field_60170": "Medium", + "field_60171": "Medium", + "field_60172": "Yes", + "field_60173": "No", + "field_60174": "Berlin", + "field_60175": "Innovative thinker with a strong project management background." + } + ], + "data_sync": null + } + ] + }, + { + "pages": [ + { + "id": 6693, + "name": "__shared__", + "order": 1, + "path": "__shared__", + "path_params": [], + "query_params": [], + "shared": true, + "elements": [ + { + "id": 107247, + "order": "1.00000000000000000000", + "type": "header", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "share_type": "except", + "pages": [ + 6694 + ] + }, + { + "id": 107250, + "order": "1.00000000000000000000", + "type": "image", + "parent_element_id": 107247, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "image_source_type": "upload", + "image_file_id": { + "name": "ozYnvncZObH3qO03UgdCIAQ2Y4MHWJ4w_d570910b4de568550dc3e4548e3233094024b77f3ddab2102aaddce3023fd13f.png", + "original_name": "template-header.png" + }, + "image_url": "", + "alt_text": "" + }, + { + "id": 107251, + "order": "1.00000000000000000000", + "type": "text", + "parent_element_id": 107248, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "concat('\ud83d\udd11 Logged in as **',get('user.username'),'** (',get('user.role'),')')", + "format": "markdown" + }, + { + "id": 107252, + "order": "1.00000000000000000000", + "type": "button", + "parent_element_id": 107248, + "place_in_container": "1", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "button": { + "button_alignment": "right", + "button_font_size": 12 + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'LOGOUT'" + }, + { + "id": 107253, + "order": "1.00000000000000000000", + "type": "link", + "parent_element_id": 107249, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "button": { + "button_width": "full", + "button_font_size": 14 + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "navigation_type": "page", + "navigate_to_page_id": 6695, + "page_parameters": [], + "query_parameters": [], + "navigate_to_url": "", + "target": "self", + "value": "'All employees'", + "variant": "button" + }, + { + "id": 107254, + "order": "1.00000000000000000000", + "type": "link", + "parent_element_id": 107249, + "place_in_container": "1", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "button": { + "button_width": "full", + "button_font_size": 14 + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "navigation_type": "page", + "navigate_to_page_id": 6696, + "page_parameters": [], + "query_parameters": [], + "navigate_to_url": "", + "target": "self", + "value": "'TODO: Performance review'", + "variant": "button" + }, + { + "id": 107255, + "order": "1.00000000000000000000", + "type": "link", + "parent_element_id": 107249, + "place_in_container": "2", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "button": { + "button_width": "full", + "button_font_size": 14 + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "navigation_type": "page", + "navigate_to_page_id": 6697, + "page_parameters": [], + "query_parameters": [], + "navigate_to_url": "", + "target": "self", + "value": "'TODO: Potential assessment'", + "variant": "button" + }, + { + "id": 107256, + "order": "1.00000000000000000000", + "type": "link", + "parent_element_id": 107249, + "place_in_container": "3", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "button": { + "button_width": "full", + "button_font_size": 14 + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "navigation_type": "page", + "navigate_to_page_id": 6698, + "page_parameters": [], + "query_parameters": [], + "navigate_to_url": "", + "target": "self", + "value": "'TODO: Ability assessment'", + "variant": "button" + }, + { + "id": 107248, + "order": "2.00000000000000000000", + "type": "column", + "parent_element_id": 107247, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 10, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "column_amount": 2, + "column_gap": 20, + "alignment": "center" + }, + { + "id": 107249, + "order": "3.00000000000000000000", + "type": "column", + "parent_element_id": 107247, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "column_amount": 4, + "column_gap": 20, + "alignment": "top" + } + ], + "data_sources": [], + "workflow_actions": [ + { + "id": 13978, + "type": "logout", + "order": 1, + "page_id": 6693, + "element_id": 107252, + "event": "click" + } + ], + "visibility": "all", + "role_type": "allow_all", + "roles": [] + }, + { + "id": 6694, + "name": "Login", + "order": 1, + "path": "/", + "path_params": [], + "query_params": [], + "shared": false, + "elements": [ + { + "id": 107257, + "order": "1.00000000000000000000", + "type": "image", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "image_source_type": "upload", + "image_file_id": { + "name": "F4nBAS96bygGuPzyB0WvApJG8I8CIMwJ_d570910b4de568550dc3e4548e3233094024b77f3ddab2102aaddce3023fd13f.png", + "original_name": "marketing-header.png" + }, + "image_url": "", + "alt_text": "" + }, + { + "id": 107258, + "order": "1.50000000000000000000", + "type": "heading", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "heading_1_text_alignment": "center" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 10, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Skill Discovery Application'", + "level": 1 + }, + { + "id": 107259, + "order": "2.00000000000000000000", + "type": "auth_form", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "input": {}, + "login_button": { + "button_alignment": "center", + "button_horizontal_padding": 36 + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 100, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 100, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 50, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 50, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "color", + "style_background_color": "#eeeeee4d", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "small", + "style_width_child": "normal", + "user_source_id": 674, + "login_button_label": "'Sign in'" + } + ], + "data_sources": [], + "workflow_actions": [ + { + "id": 13979, + "type": "open_page", + "order": 1, + "page_id": 6694, + "element_id": 107259, + "event": "after_login", + "navigation_type": "page", + "navigate_to_page_id": 6695, + "page_parameters": [], + "query_parameters": [], + "navigate_to_url": "", + "target": "self" + } + ], + "visibility": "all", + "role_type": "allow_all", + "roles": [] + }, + { + "id": 6695, + "name": "All employees", + "order": 2, + "path": "/all-employees", + "path_params": [], + "query_params": [], + "shared": false, + "elements": [ + { + "id": 107261, + "order": "0.50000000000000000000", + "type": "link", + "parent_element_id": 107260, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "button": { + "button_width": "full", + "button_font_size": 18, + "button_border_radius": 0, + "button_vertical_padding": 18 + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "navigation_type": "page", + "navigate_to_page_id": 6699, + "page_parameters": [ + { + "name": "employee_id", + "value": "get('current_record.id')" + } + ], + "query_parameters": [], + "navigate_to_url": "", + "target": "self", + "value": "get('current_record.field_60111')", + "variant": "button" + }, + { + "id": 107262, + "order": "1.00000000000000000000", + "type": "image", + "parent_element_id": 107260, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "image": {} + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "image_source_type": "url", + "image_file_id": null, + "image_url": "get('current_record.field_60114.0.url')", + "alt_text": "" + }, + { + "id": 107263, + "order": "1.50000000000000000000", + "type": "heading", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "heading_1_text_alignment": "center" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 10, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'All employees'", + "level": 1 + }, + { + "id": 107264, + "order": "2.00000000000000000000", + "type": "text", + "parent_element_id": 107260, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "concat('\ud83d\udcde ',get('current_record.field_60113'))", + "format": "plain" + }, + { + "id": 107260, + "order": "3.00000000000000000000", + "type": "repeat", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "data_source_id": 12196, + "items_per_page": 20, + "button_load_more_label": "", + "schema_property": null, + "property_options": [ + { + "schema_property": "field_60111", + "filterable": false, + "sortable": false, + "searchable": true + }, + { + "schema_property": "field_60116", + "filterable": true, + "sortable": false, + "searchable": false + }, + { + "schema_property": "field_60214", + "filterable": false, + "sortable": false, + "searchable": true + } + ], + "orientation": "horizontal", + "items_per_row": { + "tablet": 2, + "desktop": 4, + "smartphone": 1 + }, + "horizontal_gap": 20, + "vertical_gap": 20 + }, + { + "id": 107265, + "order": "3.00000000000000000000", + "type": "text", + "parent_element_id": 107260, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "concat('\u2709\ufe0f ',get('current_record.field_60112'))", + "format": "plain" + }, + { + "id": 107266, + "order": "3.50000000000000000000", + "type": "text", + "parent_element_id": 107260, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_color": "secondary" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'CATEGORY'", + "format": "plain" + }, + { + "id": 107267, + "order": "3.66666666666666651864", + "type": "text", + "parent_element_id": 107260, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "get('current_record.field_60214')", + "format": "plain" + }, + { + "id": 107268, + "order": "4.00000000000000000000", + "type": "text", + "parent_element_id": 107260, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_color": "secondary" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'LAST REVIEW'", + "format": "plain" + }, + { + "id": 107269, + "order": "4.50000000000000000000", + "type": "text", + "parent_element_id": 107260, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "get('current_record.field_60183')", + "format": "plain" + }, + { + "id": 107270, + "order": "5.00000000000000000000", + "type": "text", + "parent_element_id": 107260, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_color": "secondary" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'HAS POTENTIAL'", + "format": "plain" + }, + { + "id": 107271, + "order": "5.50000000000000000000", + "type": "text", + "parent_element_id": 107260, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "get('current_record.field_60212')", + "format": "plain" + }, + { + "id": 107272, + "order": "6.00000000000000000000", + "type": "text", + "parent_element_id": 107260, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_color": "secondary" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'HAS ABILITY'", + "format": "plain" + }, + { + "id": 107273, + "order": "6.50000000000000000000", + "type": "text", + "parent_element_id": 107260, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "get('current_record.field_60205')", + "format": "plain" + } + ], + "data_sources": [ + { + "id": 12196, + "name": "My employees", + "order": "1.00000000000000000000", + "service": { + "id": 15062, + "integration_id": 902, + "type": "local_baserow_list_rows", + "table_id": 5730, + "view_id": 26609, + "sortings": [], + "search_query": "", + "filter_type": "AND", + "filters": [ + { + "field_id": 60123, + "type": "link_row_has", + "value": "get('user.id')", + "value_is_formula": true + } + ] + } + } + ], + "workflow_actions": [], + "visibility": "logged-in", + "role_type": "disallow_all_except", + "roles": [ + "People manager" + ] + }, + { + "id": 6696, + "name": "TOOD: Performance review", + "order": 3, + "path": "/employees-performance-review", + "path_params": [], + "query_params": [], + "shared": false, + "elements": [ + { + "id": 107275, + "order": "0.50000000000000000000", + "type": "link", + "parent_element_id": 107274, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "button": { + "button_width": "full", + "button_font_size": 18, + "button_border_radius": 0, + "button_vertical_padding": 18 + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "navigation_type": "page", + "navigate_to_page_id": 6699, + "page_parameters": [ + { + "name": "employee_id", + "value": "get('current_record.id')" + } + ], + "query_parameters": [], + "navigate_to_url": "", + "target": "self", + "value": "get('current_record.field_60111')", + "variant": "button" + }, + { + "id": 107276, + "order": "1.00000000000000000000", + "type": "image", + "parent_element_id": 107274, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "image": {} + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "image_source_type": "url", + "image_file_id": null, + "image_url": "get('current_record.field_60114.0.url')", + "alt_text": "" + }, + { + "id": 107277, + "order": "1.50000000000000000000", + "type": "heading", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "heading_1_text_alignment": "center" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 10, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Employees that require a performance review'", + "level": 1 + }, + { + "id": 107278, + "order": "2.00000000000000000000", + "type": "text", + "parent_element_id": 107274, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "concat('\ud83d\udcde ',get('current_record.field_60113'))", + "format": "plain" + }, + { + "id": 107274, + "order": "3.00000000000000000000", + "type": "repeat", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "data_source_id": 12197, + "items_per_page": 20, + "button_load_more_label": "", + "schema_property": null, + "property_options": [ + { + "schema_property": "field_60111", + "filterable": false, + "sortable": false, + "searchable": true + }, + { + "schema_property": "field_60116", + "filterable": true, + "sortable": false, + "searchable": false + }, + { + "schema_property": "field_60214", + "filterable": false, + "sortable": false, + "searchable": true + } + ], + "orientation": "horizontal", + "items_per_row": { + "tablet": 2, + "desktop": 4, + "smartphone": 1 + }, + "horizontal_gap": 20, + "vertical_gap": 20 + }, + { + "id": 107279, + "order": "3.00000000000000000000", + "type": "text", + "parent_element_id": 107274, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "concat('\u2709\ufe0f ',get('current_record.field_60112'))", + "format": "plain" + }, + { + "id": 107280, + "order": "3.50000000000000000000", + "type": "text", + "parent_element_id": 107274, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_color": "secondary" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'CATEGORY'", + "format": "plain" + }, + { + "id": 107281, + "order": "3.66666666666666651864", + "type": "text", + "parent_element_id": 107274, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "get('current_record.field_60214')", + "format": "plain" + }, + { + "id": 107282, + "order": "4.00000000000000000000", + "type": "text", + "parent_element_id": 107274, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_color": "secondary" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'LAST REVIEW'", + "format": "plain" + }, + { + "id": 107283, + "order": "4.50000000000000000000", + "type": "text", + "parent_element_id": 107274, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "get('current_record.field_60183')", + "format": "plain" + }, + { + "id": 107284, + "order": "5.00000000000000000000", + "type": "text", + "parent_element_id": 107274, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_color": "secondary" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'HAS POTENTIAL'", + "format": "plain" + }, + { + "id": 107285, + "order": "5.50000000000000000000", + "type": "text", + "parent_element_id": 107274, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "get('current_record.field_60212')", + "format": "plain" + }, + { + "id": 107286, + "order": "6.00000000000000000000", + "type": "text", + "parent_element_id": 107274, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_color": "secondary" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'HAS ABILITY'", + "format": "plain" + }, + { + "id": 107287, + "order": "6.50000000000000000000", + "type": "text", + "parent_element_id": 107274, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "get('current_record.field_60205')", + "format": "plain" + } + ], + "data_sources": [ + { + "id": 12197, + "name": "My employees", + "order": "1.00000000000000000000", + "service": { + "id": 15063, + "integration_id": 902, + "type": "local_baserow_list_rows", + "table_id": 5730, + "view_id": 26611, + "sortings": [], + "search_query": "", + "filter_type": "AND", + "filters": [ + { + "field_id": 60123, + "type": "link_row_has", + "value": "get('user.id')", + "value_is_formula": true + } + ] + } + } + ], + "workflow_actions": [], + "visibility": "logged-in", + "role_type": "disallow_all_except", + "roles": [ + "People manager" + ] + }, + { + "id": 6697, + "name": "TOOD: Potential assessment", + "order": 4, + "path": "/employees-potential-assessment", + "path_params": [], + "query_params": [], + "shared": false, + "elements": [ + { + "id": 107289, + "order": "0.50000000000000000000", + "type": "link", + "parent_element_id": 107288, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "button": { + "button_width": "full", + "button_font_size": 18, + "button_border_radius": 0, + "button_vertical_padding": 18 + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "navigation_type": "page", + "navigate_to_page_id": 6699, + "page_parameters": [ + { + "name": "employee_id", + "value": "get('current_record.id')" + } + ], + "query_parameters": [], + "navigate_to_url": "", + "target": "self", + "value": "get('current_record.field_60111')", + "variant": "button" + }, + { + "id": 107290, + "order": "1.00000000000000000000", + "type": "image", + "parent_element_id": 107288, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "image": {} + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "image_source_type": "url", + "image_file_id": null, + "image_url": "get('current_record.field_60114.0.url')", + "alt_text": "" + }, + { + "id": 107291, + "order": "1.50000000000000000000", + "type": "heading", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "heading_1_text_alignment": "center" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 10, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Employees that require a potential assessment'", + "level": 1 + }, + { + "id": 107292, + "order": "2.00000000000000000000", + "type": "text", + "parent_element_id": 107288, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "concat('\ud83d\udcde ',get('current_record.field_60113'))", + "format": "plain" + }, + { + "id": 107288, + "order": "3.00000000000000000000", + "type": "repeat", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "data_source_id": 12198, + "items_per_page": 20, + "button_load_more_label": "", + "schema_property": null, + "property_options": [ + { + "schema_property": "field_60111", + "filterable": false, + "sortable": false, + "searchable": true + }, + { + "schema_property": "field_60116", + "filterable": true, + "sortable": false, + "searchable": false + }, + { + "schema_property": "field_60214", + "filterable": false, + "sortable": false, + "searchable": true + } + ], + "orientation": "horizontal", + "items_per_row": { + "tablet": 2, + "desktop": 4, + "smartphone": 1 + }, + "horizontal_gap": 20, + "vertical_gap": 20 + }, + { + "id": 107293, + "order": "3.00000000000000000000", + "type": "text", + "parent_element_id": 107288, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "concat('\u2709\ufe0f ',get('current_record.field_60112'))", + "format": "plain" + }, + { + "id": 107294, + "order": "3.50000000000000000000", + "type": "text", + "parent_element_id": 107288, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_color": "secondary" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'CATEGORY'", + "format": "plain" + }, + { + "id": 107295, + "order": "3.66666666666666651864", + "type": "text", + "parent_element_id": 107288, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "get('current_record.field_60214')", + "format": "plain" + }, + { + "id": 107296, + "order": "4.00000000000000000000", + "type": "text", + "parent_element_id": 107288, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_color": "secondary" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'LAST REVIEW'", + "format": "plain" + }, + { + "id": 107297, + "order": "4.50000000000000000000", + "type": "text", + "parent_element_id": 107288, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "get('current_record.field_60183')", + "format": "plain" + }, + { + "id": 107298, + "order": "5.00000000000000000000", + "type": "text", + "parent_element_id": 107288, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_color": "secondary" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'HAS POTENTIAL'", + "format": "plain" + }, + { + "id": 107299, + "order": "5.50000000000000000000", + "type": "text", + "parent_element_id": 107288, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "get('current_record.field_60212')", + "format": "plain" + }, + { + "id": 107300, + "order": "6.00000000000000000000", + "type": "text", + "parent_element_id": 107288, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_color": "secondary" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'HAS ABILITY'", + "format": "plain" + }, + { + "id": 107301, + "order": "6.50000000000000000000", + "type": "text", + "parent_element_id": 107288, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "get('current_record.field_60205')", + "format": "plain" + } + ], + "data_sources": [ + { + "id": 12198, + "name": "My employees", + "order": "1.00000000000000000000", + "service": { + "id": 15064, + "integration_id": 902, + "type": "local_baserow_list_rows", + "table_id": 5730, + "view_id": 26612, + "sortings": [], + "search_query": "", + "filter_type": "AND", + "filters": [ + { + "field_id": 60123, + "type": "link_row_has", + "value": "get('user.id')", + "value_is_formula": true + } + ] + } + } + ], + "workflow_actions": [], + "visibility": "logged-in", + "role_type": "disallow_all_except", + "roles": [ + "People manager" + ] + }, + { + "id": 6698, + "name": "TOOD: Ability assessment", + "order": 5, + "path": "/employees-ability-assessment", + "path_params": [], + "query_params": [], + "shared": false, + "elements": [ + { + "id": 107303, + "order": "0.50000000000000000000", + "type": "link", + "parent_element_id": 107302, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "button": { + "button_width": "full", + "button_font_size": 18, + "button_border_radius": 0, + "button_vertical_padding": 18 + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "navigation_type": "page", + "navigate_to_page_id": 6699, + "page_parameters": [ + { + "name": "employee_id", + "value": "get('current_record.id')" + } + ], + "query_parameters": [], + "navigate_to_url": "", + "target": "self", + "value": "get('current_record.field_60111')", + "variant": "button" + }, + { + "id": 107304, + "order": "1.00000000000000000000", + "type": "image", + "parent_element_id": 107302, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "image": {} + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "image_source_type": "url", + "image_file_id": null, + "image_url": "get('current_record.field_60114.0.url')", + "alt_text": "" + }, + { + "id": 107305, + "order": "1.50000000000000000000", + "type": "heading", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "heading_1_text_alignment": "center" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 10, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Employees that require an ability assessment'", + "level": 1 + }, + { + "id": 107306, + "order": "2.00000000000000000000", + "type": "text", + "parent_element_id": 107302, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "concat('\ud83d\udcde ',get('current_record.field_60113'))", + "format": "plain" + }, + { + "id": 107302, + "order": "3.00000000000000000000", + "type": "repeat", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "data_source_id": 12199, + "items_per_page": 20, + "button_load_more_label": "", + "schema_property": null, + "property_options": [ + { + "schema_property": "field_60111", + "filterable": false, + "sortable": false, + "searchable": true + }, + { + "schema_property": "field_60116", + "filterable": true, + "sortable": false, + "searchable": false + }, + { + "schema_property": "field_60214", + "filterable": false, + "sortable": false, + "searchable": true + } + ], + "orientation": "horizontal", + "items_per_row": { + "tablet": 2, + "desktop": 4, + "smartphone": 1 + }, + "horizontal_gap": 20, + "vertical_gap": 20 + }, + { + "id": 107307, + "order": "3.00000000000000000000", + "type": "text", + "parent_element_id": 107302, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "concat('\u2709\ufe0f ',get('current_record.field_60112'))", + "format": "plain" + }, + { + "id": 107308, + "order": "3.50000000000000000000", + "type": "text", + "parent_element_id": 107302, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_color": "secondary" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'CATEGORY'", + "format": "plain" + }, + { + "id": 107309, + "order": "3.66666666666666651864", + "type": "text", + "parent_element_id": 107302, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "get('current_record.field_60214')", + "format": "plain" + }, + { + "id": 107310, + "order": "4.00000000000000000000", + "type": "text", + "parent_element_id": 107302, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_color": "secondary" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'LAST REVIEW'", + "format": "plain" + }, + { + "id": 107311, + "order": "4.50000000000000000000", + "type": "text", + "parent_element_id": 107302, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "get('current_record.field_60183')", + "format": "plain" + }, + { + "id": 107312, + "order": "5.00000000000000000000", + "type": "text", + "parent_element_id": 107302, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_color": "secondary" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'HAS POTENTIAL'", + "format": "plain" + }, + { + "id": 107313, + "order": "5.50000000000000000000", + "type": "text", + "parent_element_id": 107302, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "get('current_record.field_60212')", + "format": "plain" + }, + { + "id": 107314, + "order": "6.00000000000000000000", + "type": "text", + "parent_element_id": 107302, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_color": "secondary" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'HAS ABILITY'", + "format": "plain" + }, + { + "id": 107315, + "order": "6.50000000000000000000", + "type": "text", + "parent_element_id": 107302, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "get('current_record.field_60205')", + "format": "plain" + } + ], + "data_sources": [ + { + "id": 12199, + "name": "My employees", + "order": "1.00000000000000000000", + "service": { + "id": 15065, + "integration_id": 902, + "type": "local_baserow_list_rows", + "table_id": 5730, + "view_id": 26613, + "sortings": [], + "search_query": "", + "filter_type": "AND", + "filters": [ + { + "field_id": 60123, + "type": "link_row_has", + "value": "get('user.id')", + "value_is_formula": true + } + ] + } + } + ], + "workflow_actions": [], + "visibility": "logged-in", + "role_type": "disallow_all_except", + "roles": [ + "People manager" + ] + }, + { + "id": 6699, + "name": "Employee Details", + "order": 6, + "path": "/employee-details/:employee_id", + "path_params": [ + { + "name": "employee_id", + "type": "numeric" + } + ], + "query_params": [], + "shared": false, + "elements": [ + { + "id": 107354, + "order": "0.33333333333333331483", + "type": "text", + "parent_element_id": 107353, + "place_in_container": "2", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_color": "secondary" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'RETENTION RISK'", + "format": "plain" + }, + { + "id": 107355, + "order": "0.40000000000000002220", + "type": "text", + "parent_element_id": 107353, + "place_in_container": "2", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "get('current_record.field_60170')", + "format": "plain" + }, + { + "id": 107356, + "order": "0.50000000000000000000", + "type": "text", + "parent_element_id": 107353, + "place_in_container": "2", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_color": "secondary" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'IMPACT OF LOSS'", + "format": "plain" + }, + { + "id": 107357, + "order": "0.66666666666666662966", + "type": "text", + "parent_element_id": 107353, + "place_in_container": "2", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "get('current_record.field_60171')", + "format": "plain" + }, + { + "id": 107318, + "order": "1.00000000000000000000", + "type": "heading", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "concat(get('data_source.12200.field_60111'),' (',get('data_source.12200.field_60214'),')')", + "level": 1 + }, + { + "id": 107319, + "order": "1.00000000000000000000", + "type": "image", + "parent_element_id": 107316, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "image_source_type": "url", + "image_file_id": null, + "image_url": "get('data_source.12200.field_60114.0.url')", + "alt_text": "" + }, + { + "id": 107320, + "order": "1.00000000000000000000", + "type": "text", + "parent_element_id": 107316, + "place_in_container": "1", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_color": "secondary" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'JOB ROLE'", + "format": "plain" + }, + { + "id": 107352, + "order": "1.00000000000000000000", + "type": "column", + "parent_element_id": 107317, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "color", + "style_background_color": "#1e5f974d", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "column_amount": 2, + "column_gap": 20, + "alignment": "center" + }, + { + "id": 107358, + "order": "1.00000000000000000000", + "type": "text", + "parent_element_id": 107353, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_color": "secondary" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'STRENGTH 1'", + "format": "plain" + }, + { + "id": 107359, + "order": "1.00000000000000000000", + "type": "text", + "parent_element_id": 107353, + "place_in_container": "2", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_color": "secondary" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'NEW TO POSITION'", + "format": "plain" + }, + { + "id": 107360, + "order": "1.00000000000000000000", + "type": "heading", + "parent_element_id": 107352, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "heading_3_font_weight": "semi-bold" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "concat('YEAR: ',get('current_record.field_60163'))", + "level": 3 + }, + { + "id": 107361, + "order": "1.00000000000000000000", + "type": "link", + "parent_element_id": 107352, + "place_in_container": "1", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "link": { + "link_font_size": 16, + "link_font_weight": "medium", + "link_text_alignment": "right" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 10, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "navigation_type": "page", + "navigate_to_page_id": 6707, + "page_parameters": [ + { + "name": "accelerate", + "value": "get('current_record.id')" + } + ], + "query_parameters": [], + "navigate_to_url": "", + "target": "self", + "value": "'Edit'", + "variant": "link" + }, + { + "id": 107321, + "order": "1.33333333333333325932", + "type": "text", + "parent_element_id": 107316, + "place_in_container": "1", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "get('data_source.12200.field_60116')", + "format": "plain" + }, + { + "id": 107322, + "order": "1.50000000000000000000", + "type": "text", + "parent_element_id": 107316, + "place_in_container": "1", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_color": "secondary" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'E-MAIL'", + "format": "plain" + }, + { + "id": 107323, + "order": "1.50000000000000000000", + "type": "heading", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 1, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Personal information'", + "level": 2 + }, + { + "id": 107324, + "order": "1.50000000000000000000", + "type": "text", + "parent_element_id": 107317, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_color": "secondary" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'MANAGER'", + "format": "plain" + }, + { + "id": 107362, + "order": "1.50000000000000000000", + "type": "text", + "parent_element_id": 107353, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "get('current_record.field_60164')", + "format": "plain" + }, + { + "id": 107325, + "order": "1.57142857142857139685", + "type": "link", + "parent_element_id": 107316, + "place_in_container": "1", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "navigation_type": "custom", + "navigate_to_page_id": null, + "page_parameters": [], + "query_parameters": [], + "navigate_to_url": "concat('mailto:',get('data_source.12200.field_60112'))", + "target": "self", + "value": "get('data_source.12200.field_60112')", + "variant": "link" + }, + { + "id": 107326, + "order": "1.60000000000000008882", + "type": "text", + "parent_element_id": 107317, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "get('current_record.field_60162.0.value')", + "format": "plain" + }, + { + "id": 107327, + "order": "1.66666666666666674068", + "type": "text", + "parent_element_id": 107316, + "place_in_container": "1", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_color": "secondary" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'PHONE'", + "format": "plain" + }, + { + "id": 107328, + "order": "1.66666666666666674068", + "type": "text", + "parent_element_id": 107317, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_color": "secondary" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'COMMENTS'", + "format": "plain" + }, + { + "id": 107329, + "order": "1.71428571428571419055", + "type": "text", + "parent_element_id": 107316, + "place_in_container": "1", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "get('data_source.12200.field_60113')", + "format": "plain" + }, + { + "id": 107330, + "order": "1.75000000000000000000", + "type": "text", + "parent_element_id": 107316, + "place_in_container": "1", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_color": "secondary" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'DEPARTMENT'", + "format": "plain" + }, + { + "id": 107331, + "order": "1.75000000000000000000", + "type": "text", + "parent_element_id": 107317, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "get('current_record.field_60175')", + "format": "plain" + }, + { + "id": 107316, + "order": "2.00000000000000000000", + "type": "column", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "column_amount": 2, + "column_gap": 20, + "alignment": "center" + }, + { + "id": 107353, + "order": "2.00000000000000000000", + "type": "column", + "parent_element_id": 107317, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 10, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "color", + "style_background_color": "#8c8c8c0d", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "column_amount": 4, + "column_gap": 20, + "alignment": "top" + }, + { + "id": 107363, + "order": "2.00000000000000000000", + "type": "text", + "parent_element_id": 107353, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_color": "secondary" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'STRENGTH 2'", + "format": "plain" + }, + { + "id": 107364, + "order": "2.00000000000000000000", + "type": "text", + "parent_element_id": 107353, + "place_in_container": "1", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_color": "secondary" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'DEVELOPMENT 1'", + "format": "plain" + }, + { + "id": 107365, + "order": "2.00000000000000000000", + "type": "text", + "parent_element_id": 107353, + "place_in_container": "3", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_color": "secondary" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'WILLINGNESS TO RELOCATE'", + "format": "plain" + }, + { + "id": 107366, + "order": "2.00000000000000000000", + "type": "text", + "parent_element_id": 107353, + "place_in_container": "2", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "get('current_record.field_60172')", + "format": "plain" + }, + { + "id": 107367, + "order": "2.50000000000000000000", + "type": "text", + "parent_element_id": 107353, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "get('current_record.field_60165')", + "format": "plain" + }, + { + "id": 107368, + "order": "2.50000000000000000000", + "type": "text", + "parent_element_id": 107353, + "place_in_container": "1", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "get('current_record.field_60167')", + "format": "plain" + }, + { + "id": 107369, + "order": "2.50000000000000000000", + "type": "text", + "parent_element_id": 107353, + "place_in_container": "3", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "get('current_record.field_60173')", + "format": "plain" + }, + { + "id": 107332, + "order": "2.75000000000000000000", + "type": "text", + "parent_element_id": 107316, + "place_in_container": "1", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "get('data_source.12200.field_60179')", + "format": "plain" + }, + { + "id": 107333, + "order": "3.00000000000000000000", + "type": "text", + "parent_element_id": 107316, + "place_in_container": "1", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_color": "secondary" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'UNIT'", + "format": "plain" + }, + { + "id": 107334, + "order": "3.00000000000000000000", + "type": "heading", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 1, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Performance reviews'", + "level": 2 + }, + { + "id": 107370, + "order": "3.00000000000000000000", + "type": "text", + "parent_element_id": 107353, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_color": "secondary" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'STRENGTH 3'", + "format": "plain" + }, + { + "id": 107371, + "order": "3.00000000000000000000", + "type": "text", + "parent_element_id": 107353, + "place_in_container": "1", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_color": "secondary" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'DEVELOPMENT 2'", + "format": "plain" + }, + { + "id": 107372, + "order": "3.00000000000000000000", + "type": "text", + "parent_element_id": 107353, + "place_in_container": "3", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_color": "secondary" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'DESIRED LOCATION(S)'", + "format": "plain" + }, + { + "id": 107335, + "order": "3.50000000000000000000", + "type": "link", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "navigation_type": "page", + "navigate_to_page_id": 6700, + "page_parameters": [ + { + "name": "employee_id", + "value": "get('data_source.12200.id')" + } + ], + "query_parameters": [], + "navigate_to_url": "", + "target": "self", + "value": "get('data_source.12200.field_60206')", + "variant": "link" + }, + { + "id": 107373, + "order": "3.50000000000000000000", + "type": "text", + "parent_element_id": 107353, + "place_in_container": "1", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "get('current_record.field_60168')", + "format": "plain" + }, + { + "id": 107336, + "order": "4.00000000000000000000", + "type": "text", + "parent_element_id": 107316, + "place_in_container": "1", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "get('data_source.12200.field_60180')", + "format": "plain" + }, + { + "id": 107337, + "order": "4.00000000000000000000", + "type": "table", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "data_source_id": 12201, + "items_per_page": 5, + "button_load_more_label": "", + "schema_property": null, + "property_options": [], + "fields": [ + { + "uid": "539b05db-24f9-441f-89b9-58f98efd0d72", + "name": "Year", + "type": "text", + "styles": {}, + "config": { + "value": "get('current_record.field_60132')" + } + }, + { + "uid": "a283dd02-4f7f-46f0-9e7f-867909098e68", + "name": "People Manager", + "type": "text", + "styles": {}, + "config": { + "value": "get('current_record.field_60131.*.value')" + } + }, + { + "uid": "a2fb396f-a645-4ae4-802e-5d619b75ece4", + "name": "Overall performance", + "type": "text", + "styles": { + "cell": { + "body_font_weight": "bold" + } + }, + "config": { + "value": "get('current_record.field_60187')" + } + }, + { + "uid": "96134175-cc9a-477b-8fa2-072344f88c0c", + "name": "What rating", + "type": "text", + "styles": {}, + "config": { + "value": "get('current_record.field_60133.*.value')" + } + }, + { + "uid": "4b079916-1ac6-4d02-b857-e0d0eb9a8a0b", + "name": "What description", + "type": "text", + "styles": {}, + "config": { + "value": "get('current_record.field_60185')" + } + }, + { + "uid": "39e6b822-9f61-4976-997e-2fd6cd398ed4", + "name": "How rating", + "type": "text", + "styles": {}, + "config": { + "value": "get('current_record.field_60134.*.value')" + } + }, + { + "uid": "a8e6c911-d37c-4c5e-aa1d-370b00d87a45", + "name": "How description", + "type": "text", + "styles": {}, + "config": { + "value": "get('current_record.field_60186')" + } + }, + { + "uid": "37579674-0fb4-41cc-8d54-d53d2923b817", + "name": "Edit", + "type": "link", + "styles": {}, + "config": { + "navigation_type": "page", + "navigate_to_page_id": 6701, + "page_parameters": [ + { + "name": "performance_id", + "value": "get('current_record.id')" + } + ], + "query_parameters": [], + "navigate_to_url": "", + "target": "self", + "link_name": "'Edit'", + "variant": "link" + } + } + ], + "orientation": { + "tablet": "vertical", + "desktop": "horizontal", + "smartphone": "vertical" + } + }, + { + "id": 107374, + "order": "4.00000000000000000000", + "type": "text", + "parent_element_id": 107353, + "place_in_container": "0", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "get('current_record.field_60166')", + "format": "plain" + }, + { + "id": 107375, + "order": "4.00000000000000000000", + "type": "text", + "parent_element_id": 107353, + "place_in_container": "1", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_color": "secondary" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'DEVELOPMENT 3'", + "format": "plain" + }, + { + "id": 107376, + "order": "4.00000000000000000000", + "type": "text", + "parent_element_id": 107353, + "place_in_container": "3", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "get('current_record.field_60174')", + "format": "plain" + }, + { + "id": 107338, + "order": "5.00000000000000000000", + "type": "text", + "parent_element_id": 107316, + "place_in_container": "1", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_color": "secondary" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'OFFICE LOCATION'", + "format": "plain" + }, + { + "id": 107339, + "order": "5.00000000000000000000", + "type": "text", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_text_color": "primary" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "concat('AVERAGE SCORE LAST 3 YEARS: **',get('data_source.12200.field_60207'),'**')", + "format": "markdown" + }, + { + "id": 107377, + "order": "5.00000000000000000000", + "type": "text", + "parent_element_id": 107353, + "place_in_container": "1", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "get('current_record.field_60169')", + "format": "plain" + }, + { + "id": 107340, + "order": "6.00000000000000000000", + "type": "text", + "parent_element_id": 107316, + "place_in_container": "1", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "get('data_source.12200.field_60124.*.value')", + "format": "plain" + }, + { + "id": 107341, + "order": "6.00000000000000000000", + "type": "text", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_text_color": "primary" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 20, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "concat('SUSTAINED PERFORMANCE: **',get('data_source.12200.field_60211'),'**')", + "format": "markdown" + }, + { + "id": 107342, + "order": "7.00000000000000000000", + "type": "text", + "parent_element_id": 107316, + "place_in_container": "1", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 12, + "body_text_color": "secondary" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'ACTIVE FROM | UNTIL'", + "format": "plain" + }, + { + "id": 107343, + "order": "7.00000000000000000000", + "type": "heading", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 1, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Potential assessments'", + "level": 2 + }, + { + "id": 107344, + "order": "8.00000000000000000000", + "type": "text", + "parent_element_id": 107316, + "place_in_container": "1", + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 0, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "concat(get('data_source.12200.field_60120'),' | ',get('data_source.12200.field_60121'))", + "format": "plain" + }, + { + "id": 107345, + "order": "8.00000000000000000000", + "type": "link", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "navigation_type": "page", + "navigate_to_page_id": 6702, + "page_parameters": [ + { + "name": "employee_id", + "value": "get('data_source.12200.id')" + } + ], + "query_parameters": [], + "navigate_to_url": "'/my-employees'", + "target": "self", + "value": "get('data_source.12200.field_60221')", + "variant": "link" + }, + { + "id": 107346, + "order": "9.00000000000000000000", + "type": "table", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "data_source_id": 12202, + "items_per_page": 20, + "button_load_more_label": "", + "schema_property": null, + "property_options": [], + "fields": [ + { + "uid": "e6b50be8-0f89-4961-a4b5-5be12ea64e4b", + "name": "Year", + "type": "text", + "styles": {}, + "config": { + "value": "get('current_record.field_60152')" + } + }, + { + "uid": "4b7c2b7c-4c23-4ee3-b80d-dfb0112facdc", + "name": "People Manager", + "type": "text", + "styles": {}, + "config": { + "value": "get('current_record.field_60139.*.value')" + } + }, + { + "uid": "4cc743be-028a-4d03-96df-db26d8518483", + "name": "Total score", + "type": "text", + "styles": { + "cell": { + "body_font_weight": "bold" + } + }, + "config": { + "value": "get('current_record.field_60197')" + } + }, + { + "uid": "21f0436c-90b9-4bf8-ae9f-777a926f89cd", + "name": "Communication", + "type": "text", + "styles": {}, + "config": { + "value": "get('current_record.field_60188')" + } + }, + { + "uid": "1a787601-84e9-477f-b315-e1db96328504", + "name": "Problem solving", + "type": "text", + "styles": {}, + "config": { + "value": "get('current_record.field_60189')" + } + }, + { + "uid": "61a5b036-32f8-4fec-a358-c02aff0637eb", + "name": "Leadership", + "type": "text", + "styles": {}, + "config": { + "value": "get('current_record.field_60190')" + } + }, + { + "uid": "8cc5ff18-2ec6-4d46-a8d0-5e762bb44584", + "name": "Technical", + "type": "text", + "styles": {}, + "config": { + "value": "get('current_record.field_60191')" + } + }, + { + "uid": "cf496f7c-8b45-412d-afda-24cbf35b7d47", + "name": "Has potential", + "type": "text", + "styles": {}, + "config": { + "value": "get('current_record.field_60210')" + } + }, + { + "uid": "e38c6d61-53dc-4f9b-9742-eb70279ad934", + "name": "Edit", + "type": "link", + "styles": {}, + "config": { + "navigation_type": "page", + "navigate_to_page_id": 6703, + "page_parameters": [ + { + "name": "potential_id", + "value": "get('current_record.id')" + } + ], + "query_parameters": [], + "navigate_to_url": "", + "target": "self", + "link_name": "'Edit'", + "variant": "link" + } + } + ], + "orientation": { + "tablet": "vertical", + "desktop": "horizontal", + "smartphone": "vertical" + } + }, + { + "id": 107347, + "order": "10.00000000000000000000", + "type": "heading", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 1, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Ability assessments'", + "level": 2 + }, + { + "id": 107348, + "order": "11.00000000000000000000", + "type": "link", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "navigation_type": "page", + "navigate_to_page_id": 6704, + "page_parameters": [ + { + "name": "employee_id", + "value": "get('data_source.12200.id')" + } + ], + "query_parameters": [], + "navigate_to_url": "'/my-employees'", + "target": "self", + "value": "get('data_source.12200.field_60219')", + "variant": "link" + }, + { + "id": 107349, + "order": "12.00000000000000000000", + "type": "table", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "data_source_id": 12203, + "items_per_page": 20, + "button_load_more_label": "", + "schema_property": null, + "property_options": [], + "fields": [ + { + "uid": "a4393467-e344-4d27-b3b5-d7d3315ac377", + "name": "Year", + "type": "text", + "styles": {}, + "config": { + "value": "get('current_record.field_60157')" + } + }, + { + "uid": "cdafe5ed-0479-4f35-be13-3a50b11cd7bf", + "name": "People Manager", + "type": "text", + "styles": {}, + "config": { + "value": "get('current_record.field_60156.*.value')" + } + }, + { + "uid": "46605322-4cb2-4683-86ff-00d9bc80ae95", + "name": "Technical", + "type": "boolean", + "styles": {}, + "config": { + "value": "get('current_record.field_60158')" + } + }, + { + "uid": "ad320caf-ca55-409c-825d-3909be736f9c", + "name": "Time", + "type": "boolean", + "styles": {}, + "config": { + "value": "get('current_record.field_60159')" + } + }, + { + "uid": "1c6c8c8a-d3c2-4fa3-afe9-bd84d783cd30", + "name": "Adaptability", + "type": "boolean", + "styles": {}, + "config": { + "value": "get('current_record.field_60160')" + } + }, + { + "uid": "43872db3-d52d-4e04-97fd-9fe7665577ab", + "name": "Has ability", + "type": "text", + "styles": {}, + "config": { + "value": "get('current_record.field_60201')" + } + }, + { + "uid": "3b1bf652-f84c-4d99-b970-c8deee2e6a6e", + "name": "Edit", + "type": "link", + "styles": {}, + "config": { + "navigation_type": "page", + "navigate_to_page_id": 6705, + "page_parameters": [ + { + "name": "ability", + "value": "get('current_record.id')" + } + ], + "query_parameters": [], + "navigate_to_url": "", + "target": "self", + "link_name": "'Edit'", + "variant": "link" + } + } + ], + "orientation": { + "tablet": "vertical", + "desktop": "horizontal", + "smartphone": "vertical" + } + }, + { + "id": 107350, + "order": "13.00000000000000000000", + "type": "heading", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 1, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Accelerated assessments'", + "level": 2 + }, + { + "id": 107351, + "order": "14.00000000000000000000", + "type": "link", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "navigation_type": "page", + "navigate_to_page_id": 6706, + "page_parameters": [ + { + "name": "employee_id", + "value": "get('data_source.12200.id')" + } + ], + "query_parameters": [], + "navigate_to_url": "'/my-employees'", + "target": "self", + "value": "get('data_source.12200.field_60222')", + "variant": "link" + }, + { + "id": 107317, + "order": "15.00000000000000000000", + "type": "repeat", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "data_source_id": 12204, + "items_per_page": 20, + "button_load_more_label": "", + "schema_property": null, + "property_options": [], + "orientation": "vertical", + "items_per_row": { + "tablet": 2, + "desktop": 2, + "smartphone": 2 + }, + "horizontal_gap": 0, + "vertical_gap": 50 + } + ], + "data_sources": [ + { + "id": 12200, + "name": "Employee details", + "order": "1.00000000000000000000", + "service": { + "id": 15066, + "integration_id": 902, + "type": "local_baserow_get_row", + "table_id": 5730, + "view_id": 26609, + "search_query": "", + "filter_type": "AND", + "filters": [], + "row_id": "get('page_parameter.employee_id')" + } + }, + { + "id": 12201, + "name": "Performance reviews", + "order": "2.00000000000000000000", + "service": { + "id": 15067, + "integration_id": 902, + "type": "local_baserow_list_rows", + "table_id": 5731, + "view_id": 26625, + "sortings": [ + { + "field_id": 60132, + "order_by": "DESC" + } + ], + "search_query": "", + "filter_type": "AND", + "filters": [ + { + "field_id": 60130, + "type": "link_row_has", + "value": "get('page_parameter.employee_id')", + "value_is_formula": true + } + ] + } + }, + { + "id": 12202, + "name": "Potential assessments", + "order": "3.00000000000000000000", + "service": { + "id": 15068, + "integration_id": 902, + "type": "local_baserow_list_rows", + "table_id": 5733, + "view_id": 26627, + "sortings": [ + { + "field_id": 60152, + "order_by": "DESC" + } + ], + "search_query": "", + "filter_type": "AND", + "filters": [ + { + "field_id": 60138, + "type": "link_row_has", + "value": "get('page_parameter.employee_id')", + "value_is_formula": true + } + ] + } + }, + { + "id": 12203, + "name": "Ability assessments", + "order": "4.00000000000000000000", + "service": { + "id": 15069, + "integration_id": 902, + "type": "local_baserow_list_rows", + "table_id": 5735, + "view_id": 26629, + "sortings": [ + { + "field_id": 60157, + "order_by": "DESC" + } + ], + "search_query": "", + "filter_type": "AND", + "filters": [ + { + "field_id": 60155, + "type": "link_row_has", + "value": "get('page_parameter.employee_id')", + "value_is_formula": true + } + ] + } + }, + { + "id": 12204, + "name": "Accelerated assessments", + "order": "5.00000000000000000000", + "service": { + "id": 15070, + "integration_id": 902, + "type": "local_baserow_list_rows", + "table_id": 5736, + "view_id": 26630, + "sortings": [ + { + "field_id": 60163, + "order_by": "DESC" + } + ], + "search_query": "", + "filter_type": "AND", + "filters": [ + { + "field_id": 60161, + "type": "link_row_has", + "value": "get('page_parameter.employee_id')", + "value_is_formula": true + } + ] + } + } + ], + "workflow_actions": [], + "visibility": "logged-in", + "role_type": "disallow_all_except", + "roles": [ + "People manager" + ] + }, + { + "id": 6700, + "name": "Add performance review", + "order": 7, + "path": "/add-performance-review/:employee_id", + "path_params": [ + { + "name": "employee_id", + "type": "numeric" + } + ], + "query_params": [], + "shared": false, + "elements": [ + { + "id": 107382, + "order": "0.50000000000000000000", + "type": "text", + "parent_element_id": 107378, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 13, + "body_font_weight": "medium" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'EMPLOYEE:'", + "format": "plain" + }, + { + "id": 107383, + "order": "0.66666666666666662966", + "type": "link", + "parent_element_id": 107378, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 5, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "navigation_type": "page", + "navigate_to_page_id": 6699, + "page_parameters": [ + { + "name": "employee_id", + "value": "get('page_parameter.employee_id')" + } + ], + "query_parameters": [], + "navigate_to_url": "", + "target": "self", + "value": "get('data_source.12205.field_60111')", + "variant": "link" + }, + { + "id": 107379, + "order": "1.00000000000000000000", + "type": "input_text", + "parent_element_id": 107378, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "label": "'YEAR'", + "required": true, + "validation_type": "integer", + "placeholder": "", + "default_value": "get('data_source.12205.field_60194')", + "is_multiline": false, + "rows": 3, + "input_type": "text" + }, + { + "id": 107384, + "order": "1.00000000000000000000", + "type": "heading", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Add performance review'", + "level": 1 + }, + { + "id": 107378, + "order": "3.00000000000000000000", + "type": "form_container", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "button": { + "button_width": "full" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 50, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 50, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 50, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 50, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "color", + "style_background_color": "#eeeeee4d", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "small", + "style_width_child": "normal", + "submit_button_label": "'+ Add performance review'", + "reset_initial_values_post_submission": false + }, + { + "id": 107380, + "order": "3.50000000000000000000", + "type": "record_selector", + "parent_element_id": 107378, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "data_source_id": 12206, + "items_per_page": 5, + "button_load_more_label": "", + "schema_property": null, + "property_options": [], + "required": true, + "label": "'OVERALL WHAT RATING'", + "default_value": "", + "placeholder": "", + "multiple": false, + "option_name_suffix": "" + }, + { + "id": 107381, + "order": "3.66666666666666651864", + "type": "record_selector", + "parent_element_id": 107378, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "data_source_id": 12206, + "items_per_page": 5, + "button_load_more_label": "", + "schema_property": null, + "property_options": [], + "required": true, + "label": "'OVERALL HOW RATING'", + "default_value": "", + "placeholder": "", + "multiple": false, + "option_name_suffix": "" + } + ], + "data_sources": [ + { + "id": 12205, + "name": "Employee details", + "order": "1.00000000000000000000", + "service": { + "id": 15071, + "integration_id": 902, + "type": "local_baserow_get_row", + "table_id": 5730, + "view_id": 26609, + "search_query": "", + "filter_type": "AND", + "filters": [], + "row_id": "get('page_parameter.employee_id')" + } + }, + { + "id": 12206, + "name": "Performance ratings", + "order": "2.00000000000000000000", + "service": { + "id": 15072, + "integration_id": 902, + "type": "local_baserow_list_rows", + "table_id": 5732, + "view_id": 26626, + "sortings": [], + "search_query": "", + "filter_type": "AND", + "filters": [] + } + } + ], + "workflow_actions": [ + { + "id": 13980, + "type": "create_row", + "order": 1, + "page_id": 6700, + "element_id": 107378, + "event": "submit", + "service": { + "id": 15083, + "integration_id": 902, + "type": "local_baserow_upsert_row", + "table_id": 5731, + "row_id": "", + "field_mappings": [ + { + "field_id": 60130, + "value": "get('data_source.12205.id')", + "enabled": true + }, + { + "field_id": 60131, + "value": "get('user.id')", + "enabled": true + }, + { + "field_id": 60132, + "value": "get('form_data.107379')", + "enabled": true + }, + { + "field_id": 60133, + "value": "get('form_data.107380')", + "enabled": true + }, + { + "field_id": 60134, + "value": "get('form_data.107381')", + "enabled": true + } + ] + } + }, + { + "id": 13981, + "type": "notification", + "order": 2, + "page_id": 6700, + "element_id": 107378, + "event": "submit", + "title": "'\u2705 Success '", + "description": "concat('The performance review ',get('previous_action.13980.field_60196'),' is added ')" + }, + { + "id": 13982, + "type": "open_page", + "order": 3, + "page_id": 6700, + "element_id": 107378, + "event": "submit", + "navigation_type": "page", + "navigate_to_page_id": 6699, + "page_parameters": [ + { + "name": "employee_id", + "value": "get('data_source.12205.id')" + } + ], + "query_parameters": [], + "navigate_to_url": "", + "target": "self" + } + ], + "visibility": "logged-in", + "role_type": "disallow_all_except", + "roles": [ + "People manager" + ] + }, + { + "id": 6701, + "name": "Edit performance review", + "order": 8, + "path": "/edit-performance-review/:performance_id", + "path_params": [ + { + "name": "performance_id", + "type": "numeric" + } + ], + "query_params": [], + "shared": false, + "elements": [ + { + "id": 107388, + "order": "0.50000000000000000000", + "type": "text", + "parent_element_id": 107385, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 13, + "body_font_weight": "medium" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'EMPLOYEE:'", + "format": "plain" + }, + { + "id": 107389, + "order": "0.66666666666666662966", + "type": "link", + "parent_element_id": 107385, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 5, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "navigation_type": "page", + "navigate_to_page_id": 6699, + "page_parameters": [ + { + "name": "employee_id", + "value": "get('data_source.12207.field_60130.0.id')" + } + ], + "query_parameters": [], + "navigate_to_url": "", + "target": "self", + "value": "get('data_source.12207.field_60130.0.value')", + "variant": "link" + }, + { + "id": 107390, + "order": "1.00000000000000000000", + "type": "heading", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Edit performance review '", + "level": 1 + }, + { + "id": 107391, + "order": "1.00000000000000000000", + "type": "text", + "parent_element_id": 107385, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 13, + "body_font_weight": "medium" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'YEAR:'", + "format": "plain" + }, + { + "id": 107392, + "order": "2.00000000000000000000", + "type": "text", + "parent_element_id": 107385, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": {} + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 5, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "get('data_source.12207.field_60132')", + "format": "plain" + }, + { + "id": 107385, + "order": "3.00000000000000000000", + "type": "form_container", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "button": { + "button_width": "full" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 50, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 50, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 50, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 50, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "color", + "style_background_color": "#eeeeee4d", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "small", + "style_width_child": "normal", + "submit_button_label": "'+ Update performance review'", + "reset_initial_values_post_submission": false + }, + { + "id": 107386, + "order": "3.50000000000000000000", + "type": "record_selector", + "parent_element_id": 107385, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "data_source_id": 12208, + "items_per_page": 5, + "button_load_more_label": "", + "schema_property": null, + "property_options": [], + "required": true, + "label": "'OVERALL WHAT RATING'", + "default_value": "get('data_source.12207.field_60133.0.id')", + "placeholder": "", + "multiple": false, + "option_name_suffix": "" + }, + { + "id": 107387, + "order": "3.66666666666666651864", + "type": "record_selector", + "parent_element_id": 107385, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "data_source_id": 12208, + "items_per_page": 5, + "button_load_more_label": "", + "schema_property": null, + "property_options": [], + "required": true, + "label": "'OVERALL HOW RATING'", + "default_value": "get('data_source.12207.field_60134.0.id')", + "placeholder": "", + "multiple": false, + "option_name_suffix": "" + } + ], + "data_sources": [ + { + "id": 12207, + "name": "Performance review", + "order": "2.00000000000000000000", + "service": { + "id": 15073, + "integration_id": 902, + "type": "local_baserow_get_row", + "table_id": 5731, + "view_id": null, + "search_query": "", + "filter_type": "AND", + "filters": [], + "row_id": "get('page_parameter.performance_id')" + } + }, + { + "id": 12208, + "name": "Performance ratings", + "order": "3.00000000000000000000", + "service": { + "id": 15074, + "integration_id": 902, + "type": "local_baserow_list_rows", + "table_id": 5732, + "view_id": 26626, + "sortings": [], + "search_query": "", + "filter_type": "AND", + "filters": [] + } + } + ], + "workflow_actions": [ + { + "id": 13983, + "type": "update_row", + "order": 1, + "page_id": 6701, + "element_id": 107385, + "event": "submit", + "service": { + "id": 15084, + "integration_id": 902, + "type": "local_baserow_upsert_row", + "table_id": 5731, + "row_id": "get('data_source.12207.id')", + "field_mappings": [ + { + "field_id": 60130, + "value": "", + "enabled": false + }, + { + "field_id": 60131, + "value": "get('user.id')", + "enabled": true + }, + { + "field_id": 60132, + "value": "get('data_source.12207.field_60132')", + "enabled": true + }, + { + "field_id": 60133, + "value": "get('form_data.107386')", + "enabled": true + }, + { + "field_id": 60134, + "value": "get('form_data.107387')", + "enabled": true + } + ] + } + }, + { + "id": 13984, + "type": "notification", + "order": 2, + "page_id": 6701, + "element_id": 107385, + "event": "submit", + "title": "'\u2705 Success '", + "description": "concat('The performance review ',get('previous_action.13983.field_60196'),' is updated ')" + }, + { + "id": 13985, + "type": "open_page", + "order": 3, + "page_id": 6701, + "element_id": 107385, + "event": "submit", + "navigation_type": "page", + "navigate_to_page_id": 6699, + "page_parameters": [ + { + "name": "employee_id", + "value": "get('data_source.12207.field_60130.0.id')" + } + ], + "query_parameters": [], + "navigate_to_url": "", + "target": "self" + } + ], + "visibility": "logged-in", + "role_type": "disallow_all_except", + "roles": [ + "People manager" + ] + }, + { + "id": 6702, + "name": "Add potential assessment", + "order": 9, + "path": "/add-potential-assessment/:employee_id", + "path_params": [ + { + "name": "employee_id", + "type": "numeric" + } + ], + "query_params": [], + "shared": false, + "elements": [ + { + "id": 107407, + "order": "0.33333333333333331483", + "type": "heading", + "parent_element_id": 107393, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "heading_2_text_color": "#ffffff" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "color", + "style_background_color": "primary", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'General info'", + "level": 2 + }, + { + "id": 107408, + "order": "0.50000000000000000000", + "type": "text", + "parent_element_id": 107393, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 13, + "body_font_weight": "medium" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'EMPLOYEE:'", + "format": "plain" + }, + { + "id": 107409, + "order": "0.66666666666666662966", + "type": "link", + "parent_element_id": 107393, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 5, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "navigation_type": "page", + "navigate_to_page_id": 6699, + "page_parameters": [ + { + "name": "employee_id", + "value": "get('page_parameter.employee_id')" + } + ], + "query_parameters": [], + "navigate_to_url": "", + "target": "self", + "value": "get('data_source.12209.field_60111')", + "variant": "link" + }, + { + "id": 107394, + "order": "1.00000000000000000000", + "type": "input_text", + "parent_element_id": 107393, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "label": "'YEAR'", + "required": true, + "validation_type": "integer", + "placeholder": "", + "default_value": "get('data_source.12209.field_60183')", + "is_multiline": false, + "rows": 3, + "input_type": "text" + }, + { + "id": 107410, + "order": "1.00000000000000000000", + "type": "heading", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Add potential assessment'", + "level": 1 + }, + { + "id": 107411, + "order": "1.50000000000000000000", + "type": "heading", + "parent_element_id": 107393, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "heading_2_text_color": "#ffffff" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "color", + "style_background_color": "primary", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Communication'", + "level": 2 + }, + { + "id": 107393, + "order": "3.00000000000000000000", + "type": "form_container", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "button": { + "button_width": "full" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 50, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 50, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 50, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 50, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "color", + "style_background_color": "#eeeeee4d", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "medium", + "style_width_child": "normal", + "submit_button_label": "'+ Add potential assessment'", + "reset_initial_values_post_submission": false + }, + { + "id": 107395, + "order": "3.50000000000000000000", + "type": "record_selector", + "parent_element_id": 107393, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "data_source_id": 12210, + "items_per_page": 5, + "button_load_more_label": "", + "schema_property": null, + "property_options": [], + "required": true, + "label": "'01. Explains complex ideas to non-technical audiences in a clear and understandable way.'", + "default_value": "", + "placeholder": "", + "multiple": false, + "option_name_suffix": "" + }, + { + "id": 107396, + "order": "5.00000000000000000000", + "type": "record_selector", + "parent_element_id": 107393, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "data_source_id": 12210, + "items_per_page": 5, + "button_load_more_label": "", + "schema_property": null, + "property_options": [], + "required": true, + "label": "'02. Handles critical feedback from colleagues or superiors constructively.'", + "default_value": "", + "placeholder": "", + "multiple": false, + "option_name_suffix": "" + }, + { + "id": 107397, + "order": "6.00000000000000000000", + "type": "record_selector", + "parent_element_id": 107393, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "data_source_id": 12210, + "items_per_page": 5, + "button_load_more_label": "", + "schema_property": null, + "property_options": [], + "required": true, + "label": "'03. Communicates project delays to the team promptly and effectively.'", + "default_value": "", + "placeholder": "", + "multiple": false, + "option_name_suffix": "" + }, + { + "id": 107412, + "order": "7.00000000000000000000", + "type": "heading", + "parent_element_id": 107393, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "heading_2_text_color": "#ffffff" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "color", + "style_background_color": "primary", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Problem solving'", + "level": 2 + }, + { + "id": 107398, + "order": "7.50000000000000000000", + "type": "record_selector", + "parent_element_id": 107393, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "data_source_id": 12210, + "items_per_page": 5, + "button_load_more_label": "", + "schema_property": null, + "property_options": [], + "required": true, + "label": "'04. Approaches challenging problems with a systematic and logical method.'", + "default_value": "", + "placeholder": "", + "multiple": false, + "option_name_suffix": "" + }, + { + "id": 107399, + "order": "7.66666666666666696273", + "type": "record_selector", + "parent_element_id": 107393, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "data_source_id": 12210, + "items_per_page": 5, + "button_load_more_label": "", + "schema_property": null, + "property_options": [], + "required": true, + "label": "'05. Thinks outside the box to solve issues creatively.'", + "default_value": "", + "placeholder": "", + "multiple": false, + "option_name_suffix": "" + }, + { + "id": 107400, + "order": "7.75000000000000000000", + "type": "record_selector", + "parent_element_id": 107393, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "data_source_id": 12210, + "items_per_page": 5, + "button_load_more_label": "", + "schema_property": null, + "property_options": [], + "required": true, + "label": "'06. Addresses significant errors in projects proactively before deadlines.'", + "default_value": "", + "placeholder": "", + "multiple": false, + "option_name_suffix": "" + }, + { + "id": 107413, + "order": "8.00000000000000000000", + "type": "heading", + "parent_element_id": 107393, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "heading_2_text_color": "#ffffff" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "color", + "style_background_color": "primary", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Leadership'", + "level": 2 + }, + { + "id": 107401, + "order": "8.50000000000000000000", + "type": "record_selector", + "parent_element_id": 107393, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "data_source_id": 12210, + "items_per_page": 5, + "button_load_more_label": "", + "schema_property": null, + "property_options": [], + "required": true, + "label": "'07. Motivates and supports team members through difficult projects.'", + "default_value": "", + "placeholder": "", + "multiple": false, + "option_name_suffix": "" + }, + { + "id": 107402, + "order": "8.66666666666666607455", + "type": "record_selector", + "parent_element_id": 107393, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "data_source_id": 12210, + "items_per_page": 5, + "button_load_more_label": "", + "schema_property": null, + "property_options": [], + "required": true, + "label": "'08. Delegates tasks efficiently to ensure both team productivity and growth.'", + "default_value": "", + "placeholder": "", + "multiple": false, + "option_name_suffix": "" + }, + { + "id": 107403, + "order": "8.75000000000000000000", + "type": "record_selector", + "parent_element_id": 107393, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "data_source_id": 12210, + "items_per_page": 5, + "button_load_more_label": "", + "schema_property": null, + "property_options": [], + "required": true, + "label": "'09. Addresses underperformance in team members with constructive feedback and support.'", + "default_value": "", + "placeholder": "", + "multiple": false, + "option_name_suffix": "" + }, + { + "id": 107414, + "order": "9.00000000000000000000", + "type": "heading", + "parent_element_id": 107393, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "heading_2_text_color": "#ffffff" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "color", + "style_background_color": "primary", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Technical skills'", + "level": 2 + }, + { + "id": 107404, + "order": "10.00000000000000000000", + "type": "record_selector", + "parent_element_id": 107393, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "data_source_id": 12210, + "items_per_page": 5, + "button_load_more_label": "", + "schema_property": null, + "property_options": [], + "required": true, + "label": "'10. Overcomes technical challenges using skills and knowledge effectively.\u00a0'", + "default_value": "", + "placeholder": "", + "multiple": false, + "option_name_suffix": "" + }, + { + "id": 107405, + "order": "11.00000000000000000000", + "type": "record_selector", + "parent_element_id": 107393, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "data_source_id": 12210, + "items_per_page": 5, + "button_load_more_label": "", + "schema_property": null, + "property_options": [], + "required": true, + "label": "'11. Stays updated with the latest technologies and trends in the field regularly.'", + "default_value": "", + "placeholder": "", + "multiple": false, + "option_name_suffix": "" + }, + { + "id": 107406, + "order": "12.00000000000000000000", + "type": "record_selector", + "parent_element_id": 107393, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "data_source_id": 12210, + "items_per_page": 5, + "button_load_more_label": "", + "schema_property": null, + "property_options": [], + "required": true, + "label": "'12.\u00a0Learns and implements new tools or software efficiently for projects.'", + "default_value": "", + "placeholder": "", + "multiple": false, + "option_name_suffix": "" + } + ], + "data_sources": [ + { + "id": 12209, + "name": "Employee details", + "order": "1.00000000000000000000", + "service": { + "id": 15075, + "integration_id": 902, + "type": "local_baserow_get_row", + "table_id": 5730, + "view_id": 26609, + "search_query": "", + "filter_type": "AND", + "filters": [], + "row_id": "get('page_parameter.employee_id')" + } + }, + { + "id": 12210, + "name": "Potential assessment scales", + "order": "2.00000000000000000000", + "service": { + "id": 15076, + "integration_id": 902, + "type": "local_baserow_list_rows", + "table_id": 5734, + "view_id": 26628, + "sortings": [], + "search_query": "", + "filter_type": "AND", + "filters": [] + } + } + ], + "workflow_actions": [ + { + "id": 13986, + "type": "create_row", + "order": 1, + "page_id": 6702, + "element_id": 107393, + "event": "submit", + "service": { + "id": 15085, + "integration_id": 902, + "type": "local_baserow_upsert_row", + "table_id": 5733, + "row_id": "", + "field_mappings": [ + { + "field_id": 60138, + "value": "get('data_source.12209.id')", + "enabled": true + }, + { + "field_id": 60139, + "value": "get('user.id')", + "enabled": true + }, + { + "field_id": 60140, + "value": "get('form_data.107395')", + "enabled": true + }, + { + "field_id": 60152, + "value": "get('form_data.107394')", + "enabled": true + }, + { + "field_id": 60141, + "value": "get('form_data.107396')", + "enabled": true + }, + { + "field_id": 60142, + "value": "get('form_data.107397')", + "enabled": true + }, + { + "field_id": 60143, + "value": "get('form_data.107398')", + "enabled": true + }, + { + "field_id": 60144, + "value": "get('form_data.107399')", + "enabled": true + }, + { + "field_id": 60145, + "value": "get('form_data.107400')", + "enabled": true + }, + { + "field_id": 60146, + "value": "get('form_data.107401')", + "enabled": true + }, + { + "field_id": 60147, + "value": "get('form_data.107402')", + "enabled": true + }, + { + "field_id": 60148, + "value": "get('form_data.107403')", + "enabled": true + }, + { + "field_id": 60149, + "value": "get('form_data.107404')", + "enabled": true + }, + { + "field_id": 60150, + "value": "get('form_data.107405')", + "enabled": true + }, + { + "field_id": 60151, + "value": "get('form_data.107406')", + "enabled": true + } + ] + } + }, + { + "id": 13987, + "type": "notification", + "order": 2, + "page_id": 6702, + "element_id": 107393, + "event": "submit", + "title": "'\u2705 Success '", + "description": "concat('The potential assessment ',get('previous_action.13986.field_60209'),' is added')" + }, + { + "id": 13988, + "type": "open_page", + "order": 3, + "page_id": 6702, + "element_id": 107393, + "event": "submit", + "navigation_type": "page", + "navigate_to_page_id": 6699, + "page_parameters": [ + { + "name": "employee_id", + "value": "get('data_source.12209.id')" + } + ], + "query_parameters": [], + "navigate_to_url": "", + "target": "self" + } + ], + "visibility": "logged-in", + "role_type": "disallow_all_except", + "roles": [ + "People manager" + ] + }, + { + "id": 6703, + "name": "Edit potential assessment", + "order": 10, + "path": "/edit-potential-assessment/:potential_id", + "path_params": [ + { + "name": "potential_id", + "type": "numeric" + } + ], + "query_params": [], + "shared": false, + "elements": [ + { + "id": 107428, + "order": "0.33333333333333331483", + "type": "heading", + "parent_element_id": 107415, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "heading_2_text_color": "#ffffff" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "color", + "style_background_color": "primary", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'General info'", + "level": 2 + }, + { + "id": 107429, + "order": "0.50000000000000000000", + "type": "text", + "parent_element_id": 107415, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 13, + "body_font_weight": "medium" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'EMPLOYEE:'", + "format": "plain" + }, + { + "id": 107430, + "order": "0.66666666666666662966", + "type": "link", + "parent_element_id": 107415, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 5, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "navigation_type": "page", + "navigate_to_page_id": 6699, + "page_parameters": [ + { + "name": "employee_id", + "value": "get('data_source.12211.field_60138.0.id')" + } + ], + "query_parameters": [], + "navigate_to_url": "", + "target": "self", + "value": "get('data_source.12211.field_60138.0.value')", + "variant": "link" + }, + { + "id": 107431, + "order": "1.00000000000000000000", + "type": "heading", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Edit potential assessment'", + "level": 1 + }, + { + "id": 107432, + "order": "1.00000000000000000000", + "type": "text", + "parent_element_id": 107415, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 13, + "body_font_weight": "medium" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'YEAR:'", + "format": "plain" + }, + { + "id": 107433, + "order": "1.33333333333333325932", + "type": "text", + "parent_element_id": 107415, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": {} + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 5, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "get('data_source.12211.field_60152')", + "format": "plain" + }, + { + "id": 107434, + "order": "1.50000000000000000000", + "type": "heading", + "parent_element_id": 107415, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "heading_2_text_color": "#ffffff" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "color", + "style_background_color": "primary", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Communication'", + "level": 2 + }, + { + "id": 107415, + "order": "3.00000000000000000000", + "type": "form_container", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "button": { + "button_width": "full" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 50, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 50, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 50, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 50, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "color", + "style_background_color": "#eeeeee4d", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "medium", + "style_width_child": "normal", + "submit_button_label": "'+ Update potential assessment'", + "reset_initial_values_post_submission": false + }, + { + "id": 107416, + "order": "3.50000000000000000000", + "type": "record_selector", + "parent_element_id": 107415, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "data_source_id": 12212, + "items_per_page": 5, + "button_load_more_label": "", + "schema_property": null, + "property_options": [], + "required": true, + "label": "'01. Explains complex ideas to non-technical audiences in a clear and understandable way.'", + "default_value": "get('data_source.12211.field_60140.0.id')", + "placeholder": "", + "multiple": false, + "option_name_suffix": "" + }, + { + "id": 107417, + "order": "5.00000000000000000000", + "type": "record_selector", + "parent_element_id": 107415, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "data_source_id": 12212, + "items_per_page": 5, + "button_load_more_label": "", + "schema_property": null, + "property_options": [], + "required": true, + "label": "'02. Handles critical feedback from colleagues or superiors constructively.'", + "default_value": "get('data_source.12211.field_60141.0.id')", + "placeholder": "", + "multiple": false, + "option_name_suffix": "" + }, + { + "id": 107418, + "order": "6.00000000000000000000", + "type": "record_selector", + "parent_element_id": 107415, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "data_source_id": 12212, + "items_per_page": 5, + "button_load_more_label": "", + "schema_property": null, + "property_options": [], + "required": true, + "label": "'03. Communicates project delays to the team promptly and effectively.'", + "default_value": "get('data_source.12211.field_60142.0.id')", + "placeholder": "", + "multiple": false, + "option_name_suffix": "" + }, + { + "id": 107435, + "order": "7.00000000000000000000", + "type": "heading", + "parent_element_id": 107415, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "heading_2_text_color": "#ffffff" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "color", + "style_background_color": "primary", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Problem solving'", + "level": 2 + }, + { + "id": 107419, + "order": "7.50000000000000000000", + "type": "record_selector", + "parent_element_id": 107415, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "data_source_id": 12212, + "items_per_page": 5, + "button_load_more_label": "", + "schema_property": null, + "property_options": [], + "required": true, + "label": "'04. Approaches challenging problems with a systematic and logical method.'", + "default_value": "get('data_source.12211.field_60143.0.id')", + "placeholder": "", + "multiple": false, + "option_name_suffix": "" + }, + { + "id": 107420, + "order": "7.66666666666666696273", + "type": "record_selector", + "parent_element_id": 107415, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "data_source_id": 12212, + "items_per_page": 5, + "button_load_more_label": "", + "schema_property": null, + "property_options": [], + "required": true, + "label": "'05. Thinks outside the box to solve issues creatively.'", + "default_value": "get('data_source.12211.field_60144.0.id')", + "placeholder": "", + "multiple": false, + "option_name_suffix": "" + }, + { + "id": 107421, + "order": "7.75000000000000000000", + "type": "record_selector", + "parent_element_id": 107415, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "data_source_id": 12212, + "items_per_page": 5, + "button_load_more_label": "", + "schema_property": null, + "property_options": [], + "required": true, + "label": "'06. Addresses significant errors in projects proactively before deadlines.'", + "default_value": "get('data_source.12211.field_60145.0.id')", + "placeholder": "", + "multiple": false, + "option_name_suffix": "" + }, + { + "id": 107436, + "order": "8.00000000000000000000", + "type": "heading", + "parent_element_id": 107415, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "heading_2_text_color": "#ffffff" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "color", + "style_background_color": "primary", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Leadership'", + "level": 2 + }, + { + "id": 107422, + "order": "8.50000000000000000000", + "type": "record_selector", + "parent_element_id": 107415, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "data_source_id": 12212, + "items_per_page": 5, + "button_load_more_label": "", + "schema_property": null, + "property_options": [], + "required": true, + "label": "'07. Motivates and supports team members through difficult projects.'", + "default_value": "get('data_source.12211.field_60146.0.id')", + "placeholder": "", + "multiple": false, + "option_name_suffix": "" + }, + { + "id": 107423, + "order": "8.66666666666666607455", + "type": "record_selector", + "parent_element_id": 107415, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "data_source_id": 12212, + "items_per_page": 5, + "button_load_more_label": "", + "schema_property": null, + "property_options": [], + "required": true, + "label": "'08. Delegates tasks efficiently to ensure both team productivity and growth.'", + "default_value": "get('data_source.12211.field_60147.0.id')", + "placeholder": "", + "multiple": false, + "option_name_suffix": "" + }, + { + "id": 107424, + "order": "8.75000000000000000000", + "type": "record_selector", + "parent_element_id": 107415, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "data_source_id": 12212, + "items_per_page": 5, + "button_load_more_label": "", + "schema_property": null, + "property_options": [], + "required": true, + "label": "'09. Addresses underperformance in team members with constructive feedback and support.'", + "default_value": "get('data_source.12211.field_60148.0.id')", + "placeholder": "", + "multiple": false, + "option_name_suffix": "" + }, + { + "id": 107437, + "order": "9.00000000000000000000", + "type": "heading", + "parent_element_id": 107415, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "heading_2_text_color": "#ffffff" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "color", + "style_background_color": "primary", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Technical skills'", + "level": 2 + }, + { + "id": 107425, + "order": "10.00000000000000000000", + "type": "record_selector", + "parent_element_id": 107415, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "data_source_id": 12212, + "items_per_page": 5, + "button_load_more_label": "", + "schema_property": null, + "property_options": [], + "required": true, + "label": "'10. Overcomes technical challenges using skills and knowledge effectively.'", + "default_value": "get('data_source.12211.field_60149.0.id')", + "placeholder": "", + "multiple": false, + "option_name_suffix": "" + }, + { + "id": 107426, + "order": "11.00000000000000000000", + "type": "record_selector", + "parent_element_id": 107415, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "data_source_id": 12212, + "items_per_page": 5, + "button_load_more_label": "", + "schema_property": null, + "property_options": [], + "required": true, + "label": "'11. Stays updated with the latest technologies and trends in the field regularly.'", + "default_value": "get('data_source.12211.field_60150.0.id')", + "placeholder": "", + "multiple": false, + "option_name_suffix": "" + }, + { + "id": 107427, + "order": "12.00000000000000000000", + "type": "record_selector", + "parent_element_id": 107415, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "data_source_id": 12212, + "items_per_page": 5, + "button_load_more_label": "", + "schema_property": null, + "property_options": [], + "required": true, + "label": "'12.\u00a0Learns and implements new tools or software efficiently for projects.'", + "default_value": "get('data_source.12211.field_60151.0.id')", + "placeholder": "", + "multiple": false, + "option_name_suffix": "" + } + ], + "data_sources": [ + { + "id": 12211, + "name": "Assessment details", + "order": "1.00000000000000000000", + "service": { + "id": 15077, + "integration_id": 902, + "type": "local_baserow_get_row", + "table_id": 5733, + "view_id": 26627, + "search_query": "", + "filter_type": "AND", + "filters": [], + "row_id": "get('page_parameter.potential_id')" + } + }, + { + "id": 12212, + "name": "Potential assessment scales", + "order": "2.00000000000000000000", + "service": { + "id": 15078, + "integration_id": 902, + "type": "local_baserow_list_rows", + "table_id": 5734, + "view_id": 26628, + "sortings": [], + "search_query": "", + "filter_type": "AND", + "filters": [] + } + } + ], + "workflow_actions": [ + { + "id": 13989, + "type": "update_row", + "order": 1, + "page_id": 6703, + "element_id": 107415, + "event": "submit", + "service": { + "id": 15086, + "integration_id": 902, + "type": "local_baserow_upsert_row", + "table_id": 5733, + "row_id": "get('data_source.12211.id')", + "field_mappings": [ + { + "field_id": 60139, + "value": "get('user.id')", + "enabled": true + }, + { + "field_id": 60144, + "value": "get('form_data.107420')", + "enabled": true + }, + { + "field_id": 60145, + "value": "get('form_data.107421')", + "enabled": true + }, + { + "field_id": 60146, + "value": "get('form_data.107422')", + "enabled": true + }, + { + "field_id": 60147, + "value": "get('form_data.107423')", + "enabled": true + }, + { + "field_id": 60148, + "value": "get('form_data.107424')", + "enabled": true + }, + { + "field_id": 60149, + "value": "get('form_data.107425')", + "enabled": true + }, + { + "field_id": 60150, + "value": "get('form_data.107426')", + "enabled": true + }, + { + "field_id": 60151, + "value": "get('form_data.107427')", + "enabled": true + }, + { + "field_id": 60152, + "value": "get('data_source.12211.field_60152')", + "enabled": true + }, + { + "field_id": 60138, + "value": "get('data_source.12211.field_60138.0.id')", + "enabled": true + }, + { + "field_id": 60140, + "value": "get('form_data.107416')", + "enabled": true + }, + { + "field_id": 60141, + "value": "get('form_data.107417')", + "enabled": true + }, + { + "field_id": 60142, + "value": "get('form_data.107418')", + "enabled": true + }, + { + "field_id": 60143, + "value": "get('form_data.107419')", + "enabled": true + } + ] + } + }, + { + "id": 13990, + "type": "notification", + "order": 2, + "page_id": 6703, + "element_id": 107415, + "event": "submit", + "title": "'\u2705 Success '", + "description": "concat('The performance review ',get('previous_action.13989.field_60209'),' is updated')" + }, + { + "id": 13991, + "type": "open_page", + "order": 3, + "page_id": 6703, + "element_id": 107415, + "event": "submit", + "navigation_type": "page", + "navigate_to_page_id": 6699, + "page_parameters": [ + { + "name": "employee_id", + "value": "get('data_source.12211.field_60138.0.id')" + } + ], + "query_parameters": [], + "navigate_to_url": "", + "target": "self" + } + ], + "visibility": "logged-in", + "role_type": "disallow_all_except", + "roles": [ + "People manager" + ] + }, + { + "id": 6704, + "name": "Add ability assessment", + "order": 11, + "path": "/add-ability-assessment/:employee_id", + "path_params": [ + { + "name": "employee_id", + "type": "numeric" + } + ], + "query_params": [], + "shared": false, + "elements": [ + { + "id": 107443, + "order": "0.33333333333333331483", + "type": "heading", + "parent_element_id": 107438, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "heading_2_text_color": "#ffffff" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "color", + "style_background_color": "primary", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'General info'", + "level": 2 + }, + { + "id": 107444, + "order": "0.50000000000000000000", + "type": "text", + "parent_element_id": 107438, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 13, + "body_font_weight": "medium" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'EMPLOYEE:'", + "format": "plain" + }, + { + "id": 107445, + "order": "0.66666666666666662966", + "type": "link", + "parent_element_id": 107438, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 5, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "navigation_type": "page", + "navigate_to_page_id": 6699, + "page_parameters": [ + { + "name": "employee_id", + "value": "get('page_parameter.employee_id')" + } + ], + "query_parameters": [], + "navigate_to_url": "", + "target": "self", + "value": "get('data_source.12213.field_60111')", + "variant": "link" + }, + { + "id": 107439, + "order": "1.00000000000000000000", + "type": "input_text", + "parent_element_id": 107438, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "label": "'YEAR'", + "required": true, + "validation_type": "integer", + "placeholder": "", + "default_value": "get('data_source.12213.field_60183')", + "is_multiline": false, + "rows": 3, + "input_type": "text" + }, + { + "id": 107446, + "order": "1.00000000000000000000", + "type": "heading", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Add ability assessment'", + "level": 1 + }, + { + "id": 107447, + "order": "1.50000000000000000000", + "type": "heading", + "parent_element_id": 107438, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "heading_2_text_color": "#ffffff" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "color", + "style_background_color": "primary", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Technical proficiency'", + "level": 2 + }, + { + "id": 107440, + "order": "2.00000000000000000000", + "type": "checkbox", + "parent_element_id": 107438, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 30, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "label": "'Can the staff member proficiently use the required software tools for their role?'", + "required": false, + "default_value": "" + }, + { + "id": 107438, + "order": "3.00000000000000000000", + "type": "form_container", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "button": { + "button_width": "full" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 50, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 50, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 50, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 50, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "color", + "style_background_color": "#eeeeee4d", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "medium", + "style_width_child": "normal", + "submit_button_label": "'+ Add ability assessment'", + "reset_initial_values_post_submission": false + }, + { + "id": 107448, + "order": "7.00000000000000000000", + "type": "heading", + "parent_element_id": 107438, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "heading_2_text_color": "#ffffff" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "color", + "style_background_color": "primary", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Time management'", + "level": 2 + }, + { + "id": 107441, + "order": "7.50000000000000000000", + "type": "checkbox", + "parent_element_id": 107438, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 30, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "label": "'Does the staff member consistently meet project deadlines without compromising quality?'", + "required": false, + "default_value": "" + }, + { + "id": 107449, + "order": "8.00000000000000000000", + "type": "heading", + "parent_element_id": 107438, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "heading_2_text_color": "#ffffff" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "color", + "style_background_color": "primary", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Adaptability'", + "level": 2 + }, + { + "id": 107442, + "order": "9.00000000000000000000", + "type": "checkbox", + "parent_element_id": 107438, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 30, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "label": "'Can the staff member quickly adapt to changes in project requirements or priorities?'", + "required": false, + "default_value": "" + } + ], + "data_sources": [ + { + "id": 12213, + "name": "Employee details", + "order": "1.00000000000000000000", + "service": { + "id": 15079, + "integration_id": 902, + "type": "local_baserow_get_row", + "table_id": 5730, + "view_id": 26609, + "search_query": "", + "filter_type": "AND", + "filters": [], + "row_id": "get('page_parameter.employee_id')" + } + } + ], + "workflow_actions": [ + { + "id": 13992, + "type": "create_row", + "order": 1, + "page_id": 6704, + "element_id": 107438, + "event": "submit", + "service": { + "id": 15087, + "integration_id": 902, + "type": "local_baserow_upsert_row", + "table_id": 5735, + "row_id": "", + "field_mappings": [ + { + "field_id": 60155, + "value": "get('data_source.12213.id')", + "enabled": true + }, + { + "field_id": 60156, + "value": "get('user.id')", + "enabled": true + }, + { + "field_id": 60157, + "value": "get('form_data.107439')", + "enabled": true + }, + { + "field_id": 60158, + "value": "get('form_data.107440')", + "enabled": true + }, + { + "field_id": 60159, + "value": "get('form_data.107441')", + "enabled": true + }, + { + "field_id": 60160, + "value": "get('form_data.107442')", + "enabled": true + } + ] + } + }, + { + "id": 13993, + "type": "notification", + "order": 2, + "page_id": 6704, + "element_id": 107438, + "event": "submit", + "title": "'\u2705 Success '", + "description": "concat('The ability assessment',get('previous_action.13992.field_60200'),' is added')" + }, + { + "id": 13994, + "type": "open_page", + "order": 3, + "page_id": 6704, + "element_id": 107438, + "event": "submit", + "navigation_type": "page", + "navigate_to_page_id": 6699, + "page_parameters": [ + { + "name": "employee_id", + "value": "get('data_source.12213.id')" + } + ], + "query_parameters": [], + "navigate_to_url": "", + "target": "self" + } + ], + "visibility": "logged-in", + "role_type": "disallow_all_except", + "roles": [ + "People manager" + ] + }, + { + "id": 6705, + "name": "Edit ability assessment", + "order": 12, + "path": "/edit-ability-assessment/:ability", + "path_params": [ + { + "name": "ability", + "type": "numeric" + } + ], + "query_params": [], + "shared": false, + "elements": [ + { + "id": 107454, + "order": "0.33333333333333331483", + "type": "heading", + "parent_element_id": 107450, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "heading_2_text_color": "#ffffff" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "color", + "style_background_color": "primary", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'General info'", + "level": 2 + }, + { + "id": 107455, + "order": "0.50000000000000000000", + "type": "text", + "parent_element_id": 107450, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 13, + "body_font_weight": "medium" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'EMPLOYEE:'", + "format": "plain" + }, + { + "id": 107456, + "order": "0.66666666666666662966", + "type": "link", + "parent_element_id": 107450, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 5, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "navigation_type": "page", + "navigate_to_page_id": 6699, + "page_parameters": [ + { + "name": "employee_id", + "value": "get('data_source.12214.field_60155.0.id')" + } + ], + "query_parameters": [], + "navigate_to_url": "", + "target": "self", + "value": "get('data_source.12214.field_60155.0.value')", + "variant": "link" + }, + { + "id": 107457, + "order": "1.00000000000000000000", + "type": "heading", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Edit ability assessment'", + "level": 1 + }, + { + "id": 107458, + "order": "1.00000000000000000000", + "type": "text", + "parent_element_id": 107450, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 13, + "body_font_weight": "medium" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'YEAR:'", + "format": "plain" + }, + { + "id": 107459, + "order": "1.33333333333333325932", + "type": "text", + "parent_element_id": 107450, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 13, + "body_font_weight": "medium" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 5, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "get('data_source.12214.field_60157')", + "format": "plain" + }, + { + "id": 107460, + "order": "1.50000000000000000000", + "type": "heading", + "parent_element_id": 107450, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "heading_2_text_color": "#ffffff" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "color", + "style_background_color": "primary", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Technical Proficiency'", + "level": 2 + }, + { + "id": 107451, + "order": "2.00000000000000000000", + "type": "checkbox", + "parent_element_id": 107450, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 30, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "label": "'Can the staff member proficiently use the required software tools for their role?'", + "required": false, + "default_value": "get('data_source.12214.field_60158')" + }, + { + "id": 107450, + "order": "3.00000000000000000000", + "type": "form_container", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "button": { + "button_width": "full" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 50, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 50, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 50, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 50, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "color", + "style_background_color": "#eeeeee4d", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "medium", + "style_width_child": "normal", + "submit_button_label": "'+ Update ability assessment'", + "reset_initial_values_post_submission": false + }, + { + "id": 107461, + "order": "7.00000000000000000000", + "type": "heading", + "parent_element_id": 107450, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "heading_2_text_color": "#ffffff" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "color", + "style_background_color": "primary", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Time management'", + "level": 2 + }, + { + "id": 107452, + "order": "7.50000000000000000000", + "type": "checkbox", + "parent_element_id": 107450, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 30, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "label": "'Does the staff member consistently meet project deadlines without compromising quality?'", + "required": false, + "default_value": "get('data_source.12214.field_60159')" + }, + { + "id": 107462, + "order": "8.00000000000000000000", + "type": "heading", + "parent_element_id": 107450, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "heading_2_text_color": "#ffffff" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "color", + "style_background_color": "primary", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Adaptability'", + "level": 2 + }, + { + "id": 107453, + "order": "9.00000000000000000000", + "type": "checkbox", + "parent_element_id": 107450, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 30, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "label": "'Can the staff member quickly adapt to changes in project requirements or priorities?'", + "required": false, + "default_value": "get('data_source.12214.field_60160')" + } + ], + "data_sources": [ + { + "id": 12214, + "name": "Assessment details", + "order": "1.00000000000000000000", + "service": { + "id": 15080, + "integration_id": 902, + "type": "local_baserow_get_row", + "table_id": 5735, + "view_id": null, + "search_query": "", + "filter_type": "AND", + "filters": [], + "row_id": "get('page_parameter.ability')" + } + } + ], + "workflow_actions": [ + { + "id": 13995, + "type": "update_row", + "order": 1, + "page_id": 6705, + "element_id": 107450, + "event": "submit", + "service": { + "id": 15088, + "integration_id": 902, + "type": "local_baserow_upsert_row", + "table_id": 5735, + "row_id": "get('data_source.12214.id')", + "field_mappings": [ + { + "field_id": 60155, + "value": "get('data_source.12214.field_60155.0.id')", + "enabled": true + }, + { + "field_id": 60156, + "value": "get('user.id')", + "enabled": true + }, + { + "field_id": 60157, + "value": "get('data_source.12214.field_60157')", + "enabled": true + }, + { + "field_id": 60158, + "value": "get('form_data.107451')", + "enabled": true + }, + { + "field_id": 60159, + "value": "get('form_data.107452')", + "enabled": true + }, + { + "field_id": 60160, + "value": "get('form_data.107453')", + "enabled": true + } + ] + } + }, + { + "id": 13996, + "type": "notification", + "order": 2, + "page_id": 6705, + "element_id": 107450, + "event": "submit", + "title": "'\u2705 Success '", + "description": "concat('The ability assessment',get('previous_action.13995.field_60200'),' is updated')" + }, + { + "id": 13997, + "type": "open_page", + "order": 3, + "page_id": 6705, + "element_id": 107450, + "event": "submit", + "navigation_type": "page", + "navigate_to_page_id": 6699, + "page_parameters": [ + { + "name": "employee_id", + "value": "get('data_source.12214.field_60155.0.id')" + } + ], + "query_parameters": [], + "navigate_to_url": "", + "target": "self" + } + ], + "visibility": "logged-in", + "role_type": "disallow_all_except", + "roles": [ + "People manager" + ] + }, + { + "id": 6706, + "name": "Add accelerate assessment", + "order": 13, + "path": "/add-accelerate-assessment/:employee_id", + "path_params": [ + { + "name": "employee_id", + "type": "numeric" + } + ], + "query_params": [], + "shared": false, + "elements": [ + { + "id": 107477, + "order": "0.33333333333333331483", + "type": "heading", + "parent_element_id": 107463, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "heading_2_text_color": "#ffffff" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "color", + "style_background_color": "primary", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'General info'", + "level": 2 + }, + { + "id": 107478, + "order": "0.50000000000000000000", + "type": "text", + "parent_element_id": 107463, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 13, + "body_font_weight": "medium" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'EMPLOYEE:'", + "format": "plain" + }, + { + "id": 107479, + "order": "0.66666666666666662966", + "type": "link", + "parent_element_id": 107463, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 5, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "navigation_type": "page", + "navigate_to_page_id": 6699, + "page_parameters": [ + { + "name": "employee_id", + "value": "get('page_parameter.employee_id')" + } + ], + "query_parameters": [], + "navigate_to_url": "", + "target": "self", + "value": "get('data_source.12215.field_60111')", + "variant": "link" + }, + { + "id": 107464, + "order": "1.00000000000000000000", + "type": "input_text", + "parent_element_id": 107463, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "label": "'YEAR'", + "required": true, + "validation_type": "integer", + "placeholder": "", + "default_value": "get('data_source.12215.field_60183')", + "is_multiline": false, + "rows": 3, + "input_type": "text" + }, + { + "id": 107480, + "order": "1.00000000000000000000", + "type": "heading", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Add accelerated assessment'", + "level": 1 + }, + { + "id": 107481, + "order": "1.50000000000000000000", + "type": "heading", + "parent_element_id": 107463, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "heading_2_text_color": "#ffffff" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "color", + "style_background_color": "primary", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Strengths '", + "level": 2 + }, + { + "id": 107465, + "order": "2.00000000000000000000", + "type": "input_text", + "parent_element_id": 107463, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "label": "'Strength 1'", + "required": true, + "validation_type": "any", + "placeholder": "", + "default_value": "", + "is_multiline": true, + "rows": 3, + "input_type": "text" + }, + { + "id": 107463, + "order": "3.00000000000000000000", + "type": "form_container", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "button": { + "button_width": "full" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 50, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 50, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 50, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 50, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "color", + "style_background_color": "#eeeeee4d", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "medium", + "style_width_child": "normal", + "submit_button_label": "'+ Add accelerated assessment'", + "reset_initial_values_post_submission": false + }, + { + "id": 107466, + "order": "3.00000000000000000000", + "type": "input_text", + "parent_element_id": 107463, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "label": "'Strength 2'", + "required": true, + "validation_type": "any", + "placeholder": "", + "default_value": "", + "is_multiline": true, + "rows": 3, + "input_type": "text" + }, + { + "id": 107467, + "order": "4.00000000000000000000", + "type": "input_text", + "parent_element_id": 107463, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "label": "'Strength 3'", + "required": true, + "validation_type": "any", + "placeholder": "", + "default_value": "", + "is_multiline": true, + "rows": 3, + "input_type": "text" + }, + { + "id": 107482, + "order": "7.00000000000000000000", + "type": "heading", + "parent_element_id": 107463, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "heading_2_text_color": "#ffffff" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "color", + "style_background_color": "primary", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Developments'", + "level": 2 + }, + { + "id": 107468, + "order": "7.50000000000000000000", + "type": "input_text", + "parent_element_id": 107463, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "label": "'Development 1'", + "required": true, + "validation_type": "any", + "placeholder": "", + "default_value": "", + "is_multiline": true, + "rows": 3, + "input_type": "text" + }, + { + "id": 107469, + "order": "7.66666666666666696273", + "type": "input_text", + "parent_element_id": 107463, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "label": "'Development 2'", + "required": true, + "validation_type": "any", + "placeholder": "", + "default_value": "", + "is_multiline": true, + "rows": 3, + "input_type": "text" + }, + { + "id": 107470, + "order": "7.75000000000000000000", + "type": "input_text", + "parent_element_id": 107463, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "label": "'Development 3'", + "required": true, + "validation_type": "any", + "placeholder": "", + "default_value": "", + "is_multiline": true, + "rows": 3, + "input_type": "text" + }, + { + "id": 107483, + "order": "8.00000000000000000000", + "type": "heading", + "parent_element_id": 107463, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "heading_2_text_color": "#ffffff" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "color", + "style_background_color": "primary", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Miscellaneous'", + "level": 2 + }, + { + "id": 107471, + "order": "9.00000000000000000000", + "type": "input_text", + "parent_element_id": 107463, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "label": "'Retention risk'", + "required": true, + "validation_type": "any", + "placeholder": "", + "default_value": "", + "is_multiline": true, + "rows": 3, + "input_type": "text" + }, + { + "id": 107472, + "order": "10.00000000000000000000", + "type": "input_text", + "parent_element_id": 107463, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "label": "'Impact of loss'", + "required": true, + "validation_type": "any", + "placeholder": "", + "default_value": "", + "is_multiline": true, + "rows": 3, + "input_type": "text" + }, + { + "id": 107473, + "order": "11.00000000000000000000", + "type": "input_text", + "parent_element_id": 107463, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "label": "'New to position'", + "required": true, + "validation_type": "any", + "placeholder": "", + "default_value": "", + "is_multiline": true, + "rows": 3, + "input_type": "text" + }, + { + "id": 107474, + "order": "12.00000000000000000000", + "type": "input_text", + "parent_element_id": 107463, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "label": "'Willingness to relocate'", + "required": true, + "validation_type": "any", + "placeholder": "", + "default_value": "", + "is_multiline": true, + "rows": 3, + "input_type": "text" + }, + { + "id": 107475, + "order": "13.00000000000000000000", + "type": "input_text", + "parent_element_id": 107463, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "label": "'Desired location(s)'", + "required": true, + "validation_type": "any", + "placeholder": "", + "default_value": "", + "is_multiline": true, + "rows": 3, + "input_type": "text" + }, + { + "id": 107484, + "order": "14.00000000000000000000", + "type": "heading", + "parent_element_id": 107463, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "heading_2_text_color": "#ffffff" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "color", + "style_background_color": "primary", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Comments'", + "level": 2 + }, + { + "id": 107476, + "order": "15.00000000000000000000", + "type": "input_text", + "parent_element_id": 107463, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "label": "'Additional comments'", + "required": false, + "validation_type": "any", + "placeholder": "", + "default_value": "", + "is_multiline": true, + "rows": 3, + "input_type": "text" + } + ], + "data_sources": [ + { + "id": 12215, + "name": "Employee details", + "order": "1.00000000000000000000", + "service": { + "id": 15081, + "integration_id": 902, + "type": "local_baserow_get_row", + "table_id": 5730, + "view_id": 26609, + "search_query": "", + "filter_type": "AND", + "filters": [], + "row_id": "get('page_parameter.employee_id')" + } + } + ], + "workflow_actions": [ + { + "id": 13998, + "type": "create_row", + "order": 1, + "page_id": 6706, + "element_id": 107463, + "event": "submit", + "service": { + "id": 15089, + "integration_id": 902, + "type": "local_baserow_upsert_row", + "table_id": 5736, + "row_id": "", + "field_mappings": [ + { + "field_id": 60162, + "value": "get('user.id')", + "enabled": true + }, + { + "field_id": 60174, + "value": "get('form_data.107475')", + "enabled": true + }, + { + "field_id": 60175, + "value": "get('form_data.107476')", + "enabled": true + }, + { + "field_id": 60168, + "value": "get('form_data.107469')", + "enabled": true + }, + { + "field_id": 60169, + "value": "get('form_data.107470')", + "enabled": true + }, + { + "field_id": 60170, + "value": "get('form_data.107471')", + "enabled": true + }, + { + "field_id": 60171, + "value": "get('form_data.107472')", + "enabled": true + }, + { + "field_id": 60172, + "value": "get('form_data.107473')", + "enabled": true + }, + { + "field_id": 60173, + "value": "get('form_data.107474')", + "enabled": true + }, + { + "field_id": 60161, + "value": "get('data_source.12215.id')", + "enabled": true + }, + { + "field_id": 60163, + "value": "get('form_data.107464')", + "enabled": true + }, + { + "field_id": 60164, + "value": "get('form_data.107465')", + "enabled": true + }, + { + "field_id": 60165, + "value": "get('form_data.107466')", + "enabled": true + }, + { + "field_id": 60166, + "value": "get('form_data.107467')", + "enabled": true + }, + { + "field_id": 60167, + "value": "get('form_data.107468')", + "enabled": true + } + ] + } + }, + { + "id": 13999, + "type": "notification", + "order": 2, + "page_id": 6706, + "element_id": 107463, + "event": "submit", + "title": "'\u2705 Success '", + "description": "concat('The accelerated assessment',get('previous_action.13998.field_60184'),' is added')" + }, + { + "id": 14000, + "type": "open_page", + "order": 3, + "page_id": 6706, + "element_id": 107463, + "event": "submit", + "navigation_type": "page", + "navigate_to_page_id": 6699, + "page_parameters": [ + { + "name": "employee_id", + "value": "get('data_source.12215.id')" + } + ], + "query_parameters": [], + "navigate_to_url": "", + "target": "self" + } + ], + "visibility": "logged-in", + "role_type": "disallow_all_except", + "roles": [ + "People manager" + ] + }, + { + "id": 6707, + "name": "Edit accelerate assessment", + "order": 14, + "path": "/edit-accelerate-assessment/:accelerate", + "path_params": [ + { + "name": "accelerate", + "type": "numeric" + } + ], + "query_params": [], + "shared": false, + "elements": [ + { + "id": 107498, + "order": "0.33333333333333331483", + "type": "heading", + "parent_element_id": 107485, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "heading_2_text_color": "#ffffff" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "color", + "style_background_color": "primary", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'General info'", + "level": 2 + }, + { + "id": 107499, + "order": "0.50000000000000000000", + "type": "text", + "parent_element_id": 107485, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 13, + "body_font_weight": "medium" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'EMPLOYEE:'", + "format": "plain" + }, + { + "id": 107500, + "order": "0.66666666666666662966", + "type": "link", + "parent_element_id": 107485, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 5, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "navigation_type": "page", + "navigate_to_page_id": 6699, + "page_parameters": [ + { + "name": "employee_id", + "value": "get('data_source.12216.field_60161.0.id')" + } + ], + "query_parameters": [], + "navigate_to_url": "", + "target": "self", + "value": "get('data_source.12216.field_60161.0.value')", + "variant": "link" + }, + { + "id": 107501, + "order": "1.00000000000000000000", + "type": "heading", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Edit accelerated assessment'", + "level": 1 + }, + { + "id": 107502, + "order": "1.00000000000000000000", + "type": "text", + "parent_element_id": 107485, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "body_font_size": 13, + "body_font_weight": "medium" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 0, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'YEAR:'", + "format": "plain" + }, + { + "id": 107503, + "order": "1.33333333333333325932", + "type": "text", + "parent_element_id": 107485, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 5, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "get('data_source.12216.field_60163')", + "format": "plain" + }, + { + "id": 107504, + "order": "1.50000000000000000000", + "type": "heading", + "parent_element_id": 107485, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "heading_2_text_color": "#ffffff" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "color", + "style_background_color": "primary", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Strengths '", + "level": 2 + }, + { + "id": 107486, + "order": "2.00000000000000000000", + "type": "input_text", + "parent_element_id": 107485, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "label": "'Strength 1'", + "required": true, + "validation_type": "any", + "placeholder": "", + "default_value": "get('data_source.12216.field_60164')", + "is_multiline": true, + "rows": 3, + "input_type": "text" + }, + { + "id": 107485, + "order": "3.00000000000000000000", + "type": "form_container", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "button": { + "button_width": "full" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 50, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 50, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 50, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 50, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "color", + "style_background_color": "#eeeeee4d", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "medium", + "style_width_child": "normal", + "submit_button_label": "'+ Update accelerated assessment'", + "reset_initial_values_post_submission": false + }, + { + "id": 107487, + "order": "3.00000000000000000000", + "type": "input_text", + "parent_element_id": 107485, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "label": "'Strength 2'", + "required": true, + "validation_type": "any", + "placeholder": "", + "default_value": "get('data_source.12216.field_60165')", + "is_multiline": true, + "rows": 3, + "input_type": "text" + }, + { + "id": 107488, + "order": "4.00000000000000000000", + "type": "input_text", + "parent_element_id": 107485, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "label": "'Strength 3'", + "required": true, + "validation_type": "any", + "placeholder": "", + "default_value": "get('data_source.12216.field_60166')", + "is_multiline": true, + "rows": 3, + "input_type": "text" + }, + { + "id": 107505, + "order": "7.00000000000000000000", + "type": "heading", + "parent_element_id": 107485, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "heading_2_text_color": "#ffffff" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "color", + "style_background_color": "primary", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Developments'", + "level": 2 + }, + { + "id": 107489, + "order": "7.50000000000000000000", + "type": "input_text", + "parent_element_id": 107485, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "label": "'Development 1'", + "required": true, + "validation_type": "any", + "placeholder": "", + "default_value": "get('data_source.12216.field_60167')", + "is_multiline": true, + "rows": 3, + "input_type": "text" + }, + { + "id": 107490, + "order": "7.66666666666666696273", + "type": "input_text", + "parent_element_id": 107485, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "label": "'Development 2'", + "required": true, + "validation_type": "any", + "placeholder": "", + "default_value": "get('data_source.12216.field_60168')", + "is_multiline": true, + "rows": 3, + "input_type": "text" + }, + { + "id": 107491, + "order": "7.75000000000000000000", + "type": "input_text", + "parent_element_id": 107485, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "label": "'Development 3'", + "required": true, + "validation_type": "any", + "placeholder": "", + "default_value": "get('data_source.12216.field_60169')", + "is_multiline": true, + "rows": 3, + "input_type": "text" + }, + { + "id": 107506, + "order": "8.00000000000000000000", + "type": "heading", + "parent_element_id": 107485, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "heading_2_text_color": "#ffffff" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "color", + "style_background_color": "primary", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Miscellaneous'", + "level": 2 + }, + { + "id": 107492, + "order": "9.00000000000000000000", + "type": "input_text", + "parent_element_id": 107485, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "label": "'Retention risk'", + "required": true, + "validation_type": "any", + "placeholder": "", + "default_value": "get('data_source.12216.field_60170')", + "is_multiline": true, + "rows": 3, + "input_type": "text" + }, + { + "id": 107493, + "order": "10.00000000000000000000", + "type": "input_text", + "parent_element_id": 107485, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "label": "'Impact of loss'", + "required": true, + "validation_type": "any", + "placeholder": "", + "default_value": "get('data_source.12216.field_60171')", + "is_multiline": true, + "rows": 3, + "input_type": "text" + }, + { + "id": 107494, + "order": "11.00000000000000000000", + "type": "input_text", + "parent_element_id": 107485, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "label": "'New to position'", + "required": true, + "validation_type": "any", + "placeholder": "", + "default_value": "get('data_source.12216.field_60172')", + "is_multiline": true, + "rows": 3, + "input_type": "text" + }, + { + "id": 107495, + "order": "12.00000000000000000000", + "type": "input_text", + "parent_element_id": 107485, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "label": "'Willingness to relocate'", + "required": true, + "validation_type": "any", + "placeholder": "", + "default_value": "get('data_source.12216.field_60173')", + "is_multiline": true, + "rows": 3, + "input_type": "text" + }, + { + "id": 107496, + "order": "13.00000000000000000000", + "type": "input_text", + "parent_element_id": 107485, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "label": "'Desired location(s)'", + "required": true, + "validation_type": "any", + "placeholder": "", + "default_value": "get('data_source.12216.field_60174')", + "is_multiline": true, + "rows": 3, + "input_type": "text" + }, + { + "id": 107507, + "order": "14.00000000000000000000", + "type": "heading", + "parent_element_id": 107485, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "heading_2_text_color": "#ffffff" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 10, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "color", + "style_background_color": "primary", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Comments'", + "level": 2 + }, + { + "id": 107497, + "order": "15.00000000000000000000", + "type": "input_text", + "parent_element_id": 107485, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 0, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 0, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "label": "'Additional comments'", + "required": false, + "validation_type": "any", + "placeholder": "", + "default_value": "get('data_source.12216.field_60175')", + "is_multiline": true, + "rows": 3, + "input_type": "text" + } + ], + "data_sources": [ + { + "id": 12216, + "name": "Assessment details", + "order": "1.00000000000000000000", + "service": { + "id": 15082, + "integration_id": 902, + "type": "local_baserow_get_row", + "table_id": 5736, + "view_id": null, + "search_query": "", + "filter_type": "AND", + "filters": [], + "row_id": "get('page_parameter.accelerate')" + } + } + ], + "workflow_actions": [ + { + "id": 14001, + "type": "update_row", + "order": 1, + "page_id": 6707, + "element_id": 107485, + "event": "submit", + "service": { + "id": 15090, + "integration_id": 902, + "type": "local_baserow_upsert_row", + "table_id": 5736, + "row_id": "get('data_source.12216.id')", + "field_mappings": [ + { + "field_id": 60161, + "value": "get('data_source.12216.field_60161.0.id')", + "enabled": true + }, + { + "field_id": 60162, + "value": "get('user.id')", + "enabled": true + }, + { + "field_id": 60163, + "value": "get('data_source.12216.field_60163')", + "enabled": true + }, + { + "field_id": 60164, + "value": "get('form_data.107486')", + "enabled": true + }, + { + "field_id": 60165, + "value": "get('form_data.107487')", + "enabled": true + }, + { + "field_id": 60166, + "value": "get('form_data.107488')", + "enabled": true + }, + { + "field_id": 60167, + "value": "get('form_data.107489')", + "enabled": true + }, + { + "field_id": 60168, + "value": "get('form_data.107490')", + "enabled": true + }, + { + "field_id": 60169, + "value": "get('form_data.107491')", + "enabled": true + }, + { + "field_id": 60170, + "value": "get('form_data.107492')", + "enabled": true + }, + { + "field_id": 60171, + "value": "get('form_data.107493')", + "enabled": true + }, + { + "field_id": 60172, + "value": "get('form_data.107494')", + "enabled": true + }, + { + "field_id": 60173, + "value": "get('form_data.107495')", + "enabled": true + }, + { + "field_id": 60174, + "value": "get('form_data.107496')", + "enabled": true + }, + { + "field_id": 60175, + "value": "get('form_data.107497')", + "enabled": true + } + ] + } + }, + { + "id": 14002, + "type": "notification", + "order": 2, + "page_id": 6707, + "element_id": 107485, + "event": "submit", + "title": "'\u2705 Success '", + "description": "concat('The accelerated assessment',get('previous_action.14001.field_60184'),' is added')" + }, + { + "id": 14003, + "type": "open_page", + "order": 3, + "page_id": 6707, + "element_id": 107485, + "event": "submit", + "navigation_type": "page", + "navigate_to_page_id": 6699, + "page_parameters": [ + { + "name": "employee_id", + "value": "get('data_source.12216.field_60161.0.id')" + } + ], + "query_parameters": [], + "navigate_to_url": "", + "target": "self" + } + ], + "visibility": "logged-in", + "role_type": "disallow_all_except", + "roles": [ + "People manager" + ] + } + ], + "integrations": [ + { + "id": 902, + "name": "Local Baserow", + "order": "1.00000000000000000000", + "type": "local_baserow", + "authorized_user": null + } + ], + "theme": { + "primary_color": "#1e5f97", + "secondary_color": "#5ebcb9", + "border_color": "#8c8c8c", + "main_success_color": "#12D452", + "main_warning_color": "#FCC74A", + "main_error_color": "#FF5A4A", + "custom_colors": [], + "body_font_family": "inter", + "body_font_size": 14, + "body_font_weight": "regular", + "body_text_color": "#444444", + "body_text_alignment": "left", + "heading_1_font_family": "inter", + "heading_1_font_size": 24, + "heading_1_font_weight": "semi-bold", + "heading_1_text_color": "primary", + "heading_1_text_alignment": "center", + "heading_2_font_family": "inter", + "heading_2_font_size": 20, + "heading_2_font_weight": "regular", + "heading_2_text_color": "primary", + "heading_2_text_alignment": "left", + "heading_3_font_family": "inter", + "heading_3_font_size": 16, + "heading_3_font_weight": "regular", + "heading_3_text_color": "#444444", + "heading_3_text_alignment": "left", + "heading_4_font_family": "tahoma", + "heading_4_font_size": 16, + "heading_4_font_weight": "regular", + "heading_4_text_color": "#444444", + "heading_4_text_alignment": "left", + "heading_5_font_family": "inter", + "heading_5_font_size": 14, + "heading_5_font_weight": "regular", + "heading_5_text_color": "#444444", + "heading_5_text_alignment": "left", + "heading_6_font_family": "inter", + "heading_6_font_size": 14, + "heading_6_font_weight": "regular", + "heading_6_text_color": "#444444", + "heading_6_text_alignment": "left", + "button_font_family": "inter", + "button_font_size": 13, + "button_font_weight": "regular", + "button_alignment": "left", + "button_text_alignment": "center", + "button_width": "auto", + "button_background_color": "transparent", + "button_text_color": "primary", + "button_border_color": "primary", + "button_border_size": 1, + "button_border_radius": 4, + "button_vertical_padding": 12, + "button_horizontal_padding": 12, + "button_hover_background_color": "primary", + "button_hover_text_color": "#ffffffff", + "button_hover_border_color": "primary", + "link_font_family": "inter", + "link_font_size": 13, + "link_font_weight": "regular", + "link_text_alignment": "left", + "link_text_color": "secondary", + "link_hover_text_color": "primary", + "image_alignment": "left", + "image_max_width": 100, + "image_max_height": null, + "image_border_radius": 0, + "image_constraint": "contain", + "page_background_color": "#ffffffff", + "page_background_file_id": null, + "page_background_mode": "tile", + "label_font_family": "inter", + "label_text_color": "#444444", + "label_font_size": 13, + "label_font_weight": "medium", + "input_font_family": "inter", + "input_font_size": 13, + "input_font_weight": "regular", + "input_text_color": "#444444", + "input_background_color": "#FFFFFFFF", + "input_border_color": "border", + "input_border_size": 1, + "input_border_radius": 4, + "input_vertical_padding": 8, + "input_horizontal_padding": 12, + "table_border_color": "border", + "table_border_size": 0, + "table_border_radius": 4, + "table_header_background_color": "secondary", + "table_header_text_color": "#ffffff", + "table_header_font_size": 13, + "table_header_font_weight": "semi-bold", + "table_header_font_family": "inter", + "table_header_text_alignment": "left", + "table_cell_background_color": "transparent", + "table_cell_alternate_background_color": "transparent", + "table_cell_alignment": "left", + "table_cell_vertical_padding": 10, + "table_cell_horizontal_padding": 20, + "table_vertical_separator_color": "border", + "table_vertical_separator_size": 0, + "table_horizontal_separator_color": "border", + "table_horizontal_separator_size": 1 + }, + "user_sources": [ + { + "id": 674, + "name": "Talent Managers", + "order": "1.00000000000000000000", + "type": "local_baserow", + "uid": "90ce6639eb334dbf86e1a078813acb1c", + "integration_id": 902, + "auth_providers": [ + { + "id": 677, + "type": "local_baserow_password", + "domain": null, + "enabled": true, + "password_field_id": 60128 + } + ], + "table_id": 5730, + "email_field_id": 60112, + "name_field_id": 60111, + "role_field_id": 60116 + } + ], + "favicon_file": null, + "login_page": { + "id": 6694, + "name": "Login", + "order": 1, + "path": "/", + "path_params": [], + "query_params": [], + "shared": false, + "elements": [ + { + "id": 107257, + "order": "1.00000000000000000000", + "type": "image", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": {}, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "image_source_type": "upload", + "image_file_id": { + "name": "F4nBAS96bygGuPzyB0WvApJG8I8CIMwJ_d570910b4de568550dc3e4548e3233094024b77f3ddab2102aaddce3023fd13f.png", + "original_name": "marketing-header.png" + }, + "image_url": "", + "alt_text": "" + }, + { + "id": 107258, + "order": "1.50000000000000000000", + "type": "heading", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "typography": { + "heading_1_text_alignment": "center" + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 10, + "style_margin_top": 10, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 10, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 0, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 0, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "none", + "style_background_color": "#ffffffff", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "normal", + "style_width_child": "normal", + "value": "'Skill Discovery Application'", + "level": 1 + }, + { + "id": 107259, + "order": "2.00000000000000000000", + "type": "auth_form", + "parent_element_id": null, + "place_in_container": null, + "visibility": "all", + "role_type": "allow_all", + "roles": [], + "styles": { + "input": {}, + "login_button": { + "button_alignment": "center", + "button_horizontal_padding": 36 + } + }, + "style_border_top_color": "border", + "style_border_top_size": 0, + "style_padding_top": 100, + "style_margin_top": 0, + "style_border_bottom_color": "border", + "style_border_bottom_size": 0, + "style_padding_bottom": 100, + "style_margin_bottom": 0, + "style_border_left_color": "border", + "style_border_left_size": 0, + "style_padding_left": 20, + "style_margin_left": 50, + "style_border_right_color": "border", + "style_border_right_size": 0, + "style_padding_right": 20, + "style_margin_right": 50, + "style_background_radius": 0, + "style_border_radius": 0, + "style_background": "color", + "style_background_color": "#eeeeee4d", + "style_background_file_id": null, + "style_background_mode": "fill", + "style_width": "small", + "style_width_child": "normal", + "user_source_id": 674, + "login_button_label": "'Sign in'" + } + ], + "data_sources": [], + "workflow_actions": [ + { + "id": 13979, + "type": "open_page", + "order": 1, + "page_id": 6694, + "element_id": 107259, + "event": "after_login", + "navigation_type": "page", + "navigate_to_page_id": 6695, + "page_parameters": [], + "query_parameters": [], + "navigate_to_url": "", + "target": "self" + } + ], + "visibility": "all", + "role_type": "allow_all", + "roles": [] + }, + "id": 2177, + "name": "Skill Discovery Application", + "order": 2, + "type": "builder" + } + ] +} \ No newline at end of file diff --git a/backend/templates/skill-discovery-management.zip b/backend/templates/skill-discovery-management.zip new file mode 100644 index 000000000..ea54aab0d Binary files /dev/null and b/backend/templates/skill-discovery-management.zip differ diff --git a/backend/tests/airtable_responses/basic/airtable_application.json b/backend/tests/airtable_responses/basic/airtable_application.json index c50192ef4..68bcaf415 100644 --- a/backend/tests/airtable_responses/basic/airtable_application.json +++ b/backend/tests/airtable_responses/basic/airtable_application.json @@ -54,12 +54,14 @@ { "id":"fldG9y88Zw7q7u4Z7i4", "name":"Name", - "type":"text" + "type":"text", + "description": "" }, { "id":"fldB7wkyR0buF1sRF9O", "name":"Email", "type":"text", + "description": "This is an email", "typeOptions":{ "validatorName":"email" } @@ -681,13 +683,6 @@ "personalForUserId":null, "createdByUserId":"usrdGm7k7NIVWhK7W7L" }, - { - "id":"viwsFAwnvkr98dfv8nm", - "name":"With hidden fields", - "type":"grid", - "personalForUserId":null, - "createdByUserId":"usrdGm7k7NIVWhK7W7L" - }, { "id":"viwBAGnUgZ6X5Eyg5Wf", "name":"Gallery view", @@ -699,7 +694,6 @@ "viewOrder":[ "viwcpYeEpAs6kZspktV", "viwDgBCKTEdCQoHTQKH", - "viwsFAwnvkr98dfv8nm", "viwBAGnUgZ6X5Eyg5Wf" ], "viewsById":{ @@ -718,13 +712,6 @@ "personalForUserId":null, "createdByUserId":"usrdGm7k7NIVWhK7W7L" }, - "viwsFAwnvkr98dfv8nm":{ - "id":"viwsFAwnvkr98dfv8nm", - "name":"With hidden fields", - "type":"grid", - "personalForUserId":null, - "createdByUserId":"usrdGm7k7NIVWhK7W7L" - }, "viwBAGnUgZ6X5Eyg5Wf":{ "id":"viwBAGnUgZ6X5Eyg5Wf", "name":"Gallery view", diff --git a/backend/tests/airtable_responses/basic/airtable_view_viwBAGnUgZ6X5Eyg5Wf.json b/backend/tests/airtable_responses/basic/airtable_view_viwBAGnUgZ6X5Eyg5Wf.json new file mode 100644 index 000000000..6b8d86474 --- /dev/null +++ b/backend/tests/airtable_responses/basic/airtable_view_viwBAGnUgZ6X5Eyg5Wf.json @@ -0,0 +1,174 @@ +{ + "msg":"SUCCESS", + "data":{ + "id":"viwBAGnUgZ6X5Eyg5Wf", + "frozenColumnCount":1, + "columnOrder":[ + { + "columnId":"fldwSc9PqedIhTSqhi5", + "visibility":true + }, + { + "columnId":"fldQcEaGEe7xuhUEuPL", + "visibility":true + }, + { + "columnId":"fldcOCTbMILJBgAMBxv", + "visibility":true + }, + { + "columnId":"fldKZpzOnQ7On9VnnGN", + "visibility":false + }, + { + "columnId":"fldjIa0urbGdkdSrkGv", + "visibility":false + }, + { + "columnId":"fldwdy4qWUvC5PmW5yd", + "visibility":false + }, + { + "columnId":"fldTn59fpliSFcwpFA9", + "visibility":false + }, + { + "columnId":"fldURNo0cvi6YWYcYj1", + "visibility":false + }, + { + "columnId":"fldRd2Vkzgsf6X4z6B4", + "visibility":false + }, + { + "columnId":"fldEB5dp0mNjVZu0VJI", + "visibility":false + }, + { + "columnId":"fldyAXIzheHfugGhuFD", + "visibility":false + }, + { + "columnId":"fldVLeVbnkAvUCnnUTW", + "visibility":false + }, + { + "columnId":"fldkrPuYJTqq7vSJ7Oh", + "visibility":false + }, + { + "columnId":"fldNdoAZRim39AxR9Eg", + "visibility":false + }, + { + "columnId":"fldREVrTBZhbNZrBNlV", + "visibility":false + }, + { + "columnId":"fldcg9ASeZABV9leVIy", + "visibility":false + }, + { + "columnId":"fldODF8Kujn3xjzuxTR", + "visibility":false + }, + { + "columnId":"fldLCn2jQ22UXCEQXv4", + "visibility":false + }, + { + "columnId":"fldzC3b6BhynEJUBEgT", + "visibility":false + }, + { + "columnId":"fldp1IFu0zdgRy70RoX", + "visibility":false + }, + { + "columnId":"fld69hqFzBP4ml0zmLH", + "visibility":false + }, + { + "columnId":"fldmQQxqgzCuQ36gQgL", + "visibility":false + }, + { + "columnId":"fldKhufJJ5a1HYrJHtj", + "visibility":false + }, + { + "columnId":"fldcTpJuoUVpsDNoszO", + "visibility":false + }, + { + "columnId":"fldws6n8xdrEJrMxJFJ", + "visibility":false + }, + { + "columnId":"fldMth4ShN7mJiphJpF", + "visibility":false + }, + { + "columnId":"fldFldbZPRtXiMyPi8E", + "visibility":false + }, + { + "columnId":"fldTd8oPvJFORlGvRWl", + "visibility":false + }, + { + "columnId":"fldi4UoOqlIGYfmqY1o", + "visibility":false + }, + { + "columnId":"fldBWcrozQbeCwyzCZQ", + "visibility":false + }, + { + "columnId":"fldJu33NLzR82odL2wU", + "visibility":false + }, + { + "columnId":"fldgq60cnkxHBALnBeY", + "visibility":false + } + ], + "filters":null, + "lastSortsApplied":null, + "groupLevels":null, + "colorConfig":null, + "sharesById":{ + + }, + "metadata":{ + "gallery":{ + "coverColumnId":"fldwdy4qWUvC5PmW5yd", + "coverFitType":"crop" + } + }, + "description":null, + "createdByUserId":"usrdGm7k7NIVWhK7W7L", + "applicationTransactionNumber":439, + "rowOrder":[ + { + "rowId":"recyANUudYjDqIXdq9Z", + "visibility":true + }, + { + "rowId":"recAAA5JwFXBk4swkfB", + "visibility":true + }, + { + "rowId":"rec2O9BdjKJO6dgj6QF", + "visibility":true + }, + { + "rowId":"rec9Imz1INvNXgRIXn1", + "visibility":true + } + ], + "signedUserContentUrls":{ + + } + } +} diff --git a/backend/tests/airtable_responses/basic/airtable_view_viwDgBCKTEdCQoHTQKH.json b/backend/tests/airtable_responses/basic/airtable_view_viwDgBCKTEdCQoHTQKH.json new file mode 100644 index 000000000..468de804e --- /dev/null +++ b/backend/tests/airtable_responses/basic/airtable_view_viwDgBCKTEdCQoHTQKH.json @@ -0,0 +1,229 @@ +{ + "msg":"SUCCESS", + "data":{ + "id":"viwDgBCKTEdCQoHTQKH", + "frozenColumnCount":1, + "columnOrder":[ + { + "columnId":"fldwSc9PqedIhTSqhi5", + "visibility":true, + "width":172 + }, + { + "columnId":"fldQcEaGEe7xuhUEuPL", + "visibility":false, + "width":134 + }, + { + "columnId":"fldcOCTbMILJBgAMBxv", + "visibility":false + }, + { + "columnId":"fldKZpzOnQ7On9VnnGN", + "visibility":false + }, + { + "columnId":"fldjIa0urbGdkdSrkGv", + "visibility":true + }, + { + "columnId":"fldwdy4qWUvC5PmW5yd", + "visibility":true, + "width":134 + }, + { + "columnId":"fldTn59fpliSFcwpFA9", + "visibility":true, + "width":200 + }, + { + "columnId":"fldURNo0cvi6YWYcYj1", + "visibility":true, + "width":250 + }, + { + "columnId":"fldRd2Vkzgsf6X4z6B4", + "visibility":false + }, + { + "columnId":"fldEB5dp0mNjVZu0VJI", + "visibility":true + }, + { + "columnId":"fldyAXIzheHfugGhuFD", + "visibility":true + }, + { + "columnId":"fldVLeVbnkAvUCnnUTW", + "visibility":true + }, + { + "columnId":"fldkrPuYJTqq7vSJ7Oh", + "visibility":true, + "width":210 + }, + { + "columnId":"fldNdoAZRim39AxR9Eg", + "visibility":true + }, + { + "columnId":"fldREVrTBZhbNZrBNlV", + "visibility":true + }, + { + "columnId":"fldcg9ASeZABV9leVIy", + "visibility":true + }, + { + "columnId":"fldODF8Kujn3xjzuxTR", + "visibility":true + }, + { + "columnId":"fldLCn2jQ22UXCEQXv4", + "visibility":true + }, + { + "columnId":"fldzC3b6BhynEJUBEgT", + "visibility":true, + "width":290 + }, + { + "columnId":"fldp1IFu0zdgRy70RoX", + "visibility":true + }, + { + "columnId":"fld69hqFzBP4ml0zmLH", + "visibility":true + }, + { + "columnId":"fldmQQxqgzCuQ36gQgL", + "visibility":true, + "width":180 + }, + { + "columnId":"fldKhufJJ5a1HYrJHtj", + "visibility":false + }, + { + "columnId":"fldcTpJuoUVpsDNoszO", + "visibility":true + }, + { + "columnId":"fldws6n8xdrEJrMxJFJ", + "visibility":true + }, + { + "columnId":"fldMth4ShN7mJiphJpF", + "visibility":true + }, + { + "columnId":"fldFldbZPRtXiMyPi8E", + "visibility":true + }, + { + "columnId":"fldTd8oPvJFORlGvRWl", + "visibility":true + }, + { + "columnId":"fldi4UoOqlIGYfmqY1o", + "visibility":true + }, + { + "columnId":"fldBWcrozQbeCwyzCZQ", + "visibility":false + }, + { + "columnId":"fldJu33NLzR82odL2wU", + "visibility":true + }, + { + "columnId":"fldgq60cnkxHBALnBeY", + "visibility":true + } + ], + "filters":{ + "filterSet":[ + { + "id":"fltp2gabc8P91234f", + "columnId":"fldwSc9PqedIhTSqhi5", + "operator":"isNotEmpty", + "value":null + }, + { + "id":"flthuYL0uubbDF2Xy", + "type":"nested", + "conjunction":"or", + "filterSet":[ + { + "id":"flt70g1l245672xRi", + "columnId":"fldwSc9PqedIhTSqhi5", + "operator":"!=", + "value":"test" + }, + { + "id":"fltVg238719fbIKqC", + "columnId":"fldcg9ASeZABV9leVIy", + "operator":"<", + "value":10 + } + ] + } + ], + "conjunction":"and" + }, + "lastSortsApplied":{ + "sortSet":[ + { + "id":"srtglUy98ghs5ou8D", + "columnId":"fldwSc9PqedIhTSqhi5", + "ascending":true + }, + { + "id":"srtglUy98ghs5ou8D", + "columnId":"fldQcEaGEe7xuhUEuPL", + "ascending":true + } + ], + "shouldAutoSort":true, + "appliedTime":"2025-02-18T19:16:10.999Z" + }, + "groupLevels":[ + { + "id":"glvvqP2okySUA2345", + "columnId":"fldRd2Vkzgsf6X4z6B4", + "order":"ascending", + "emptyGroupState":"hidden" + } + ], + "colorConfig":null, + "sharesById":{ + + }, + "metadata":{ + "grid":{ + "rowHeight": "medium" + } + }, + "description":null, + "createdByUserId":"usrdGm7k7NIVWhK7W7L", + "applicationTransactionNumber":284, + "rowOrder":[ + { + "rowId":"recyANUudYjDqIXdq9Z", + "visibility":true + }, + { + "rowId":"recAAA5JwFXBk4swkfB", + "visibility":true + }, + { + "rowId":"rec2O9BdjKJO6dgj6QF", + "visibility":true + }, + { + "rowId":"rec9Imz1INvNXgRIXn1", + "visibility":true + } + ] + } +} diff --git a/backend/tests/baserow/api/templates/test_templates_views.py b/backend/tests/baserow/api/templates/test_templates_views.py index 16e7335d6..61067e1ef 100644 --- a/backend/tests/baserow/api/templates/test_templates_views.py +++ b/backend/tests/baserow/api/templates/test_templates_views.py @@ -33,11 +33,13 @@ def test_list_templates(api_client, data_fixture): category=category_1, keywords="test1,test2", slug="project-tracker", + open_application=None, ) template_2 = data_fixture.create_template( name="Template 2", icon="document", category=category_2, + open_application=1, ) template_3 = data_fixture.create_template( name="Template 3", icon="document", categories=[category_2, category_3] @@ -46,25 +48,67 @@ def test_list_templates(api_client, data_fixture): response = api_client.get(reverse("api:templates:list")) assert response.status_code == HTTP_200_OK response_json = response.json() - assert len(response_json) == 3 - assert response_json[0]["id"] == category_1.id - assert response_json[0]["name"] == "Cat 1" - assert len(response_json[0]["templates"]) == 1 - assert response_json[0]["templates"][0]["id"] == template_1.id - assert response_json[0]["templates"][0]["name"] == template_1.name - assert response_json[0]["templates"][0]["slug"] == template_1.slug - assert response_json[0]["templates"][0]["icon"] == template_1.icon - assert response_json[0]["templates"][0]["keywords"] == "test1,test2" - assert response_json[0]["templates"][0]["workspace_id"] == template_1.workspace_id - assert response_json[0]["templates"][0]["is_default"] is True - assert len(response_json[1]["templates"]) == 2 - assert response_json[1]["templates"][0]["id"] == template_2.id - assert response_json[1]["templates"][0]["is_default"] is False - assert response_json[1]["templates"][1]["id"] == template_3.id - assert response_json[1]["templates"][1]["is_default"] is False - assert len(response_json[2]["templates"]) == 1 - assert response_json[2]["templates"][0]["id"] == template_3.id - assert response_json[2]["templates"][0]["is_default"] is False + + assert response_json == [ + { + "id": category_1.id, + "name": "Cat 1", + "templates": [ + { + "id": template_1.id, + "name": "Template 1", + "slug": template_1.slug, + "icon": "document", + "keywords": "test1,test2", + "workspace_id": template_1.workspace_id, + "is_default": True, + "open_application": None, + } + ], + }, + { + "id": category_2.id, + "name": "Cat 2", + "templates": [ + { + "id": template_2.id, + "name": "Template 2", + "slug": template_2.slug, + "icon": "document", + "keywords": "", + "workspace_id": template_2.workspace_id, + "is_default": False, + "open_application": 1, + }, + { + "id": template_3.id, + "name": "Template 3", + "slug": template_3.slug, + "icon": "document", + "keywords": "", + "workspace_id": template_3.workspace_id, + "is_default": False, + "open_application": None, + }, + ], + }, + { + "id": category_3.id, + "name": "Cat 3", + "templates": [ + { + "id": template_3.id, + "name": "Template 3", + "slug": template_3.slug, + "icon": "document", + "keywords": "", + "workspace_id": template_3.workspace_id, + "is_default": False, + "open_application": None, + } + ], + }, + ] @pytest.mark.django_db diff --git a/backend/tests/baserow/contrib/builder/api/domains/test_domain_public_views.py b/backend/tests/baserow/contrib/builder/api/domains/test_domain_public_views.py index 07d6b7e2e..dd8441d87 100644 --- a/backend/tests/baserow/contrib/builder/api/domains/test_domain_public_views.py +++ b/backend/tests/baserow/contrib/builder/api/domains/test_domain_public_views.py @@ -107,12 +107,12 @@ def test_get_public_builder_by_domain_name(api_client, data_fixture): page2 = data_fixture.create_builder_page(user=user, builder=builder_to) domain = data_fixture.create_builder_custom_domain( - domain_name="test.getbaserow.io", published_to=builder_to + domain_name="xyztest.getbaserow.io", published_to=builder_to ) url = reverse( "api:builder:domains:get_builder_by_domain_name", - kwargs={"domain_name": "test.getbaserow.io"}, + kwargs={"domain_name": "xyztest.getbaserow.io"}, ) # Anonymous request @@ -128,10 +128,7 @@ def test_get_public_builder_by_domain_name(api_client, data_fixture): del response_json["theme"] # We are not testing the theme response here. - assert ( - builder_to.page_set(manager="objects_with_shared").filter(shared=True).count() - == 1 - ) + assert builder_to.page_set.filter(shared=True).count() == 1 shared_page = builder_to.shared_page @@ -215,14 +212,14 @@ def test_get_builder_missing_domain_name(api_client, data_fixture): def test_get_non_public_builder(api_client, data_fixture): user, token = data_fixture.create_user_and_token() page = data_fixture.create_builder_page(user=user) - page2 = data_fixture.create_builder_page(builder=page.builder, user=user) - domain = data_fixture.create_builder_custom_domain( - domain_name="test.getbaserow.io", builder=page.builder + data_fixture.create_builder_page(builder=page.builder, user=user) + data_fixture.create_builder_custom_domain( + domain_name="notpublic.getbaserow.io", builder=page.builder ) url = reverse( "api:builder:domains:get_builder_by_domain_name", - kwargs={"domain_name": "test.getbaserow.io"}, + kwargs={"domain_name": "notpublic.getbaserow.io"}, ) response = api_client.get( url, @@ -260,10 +257,7 @@ def test_get_public_builder_by_id(api_client, data_fixture): del response_json["theme"] # We are not testing the theme response here. - assert ( - page.builder.page_set(manager="objects_with_shared").filter(shared=True).count() - == 1 - ) + assert page.builder.page_set.filter(shared=True).count() == 1 shared_page = page.builder.shared_page diff --git a/backend/tests/baserow/contrib/builder/api/elements/test_menu_element.py b/backend/tests/baserow/contrib/builder/api/elements/test_menu_element.py new file mode 100644 index 000000000..9f42b6836 --- /dev/null +++ b/backend/tests/baserow/contrib/builder/api/elements/test_menu_element.py @@ -0,0 +1,167 @@ +import uuid + +from django.urls import reverse + +import pytest +from rest_framework.status import HTTP_200_OK + +from baserow.contrib.builder.elements.handler import ElementHandler +from baserow.contrib.builder.elements.models import MenuItemElement +from baserow.test_utils.helpers import AnyInt, AnyStr + + +@pytest.fixture +def menu_element_fixture(data_fixture): + """Fixture to help test the Menu element.""" + + user, token = data_fixture.create_user_and_token() + builder = data_fixture.create_builder_application(user=user) + page_a = data_fixture.create_builder_page(builder=builder, path="/page_a/:foo/") + page_b = data_fixture.create_builder_page(builder=builder, path="/page_b/") + + menu_element = data_fixture.create_builder_menu_element(user=user, page=page_a) + + return { + "token": token, + "page_a": page_a, + "page_b": page_b, + "menu_element": menu_element, + } + + +def create_menu_item(**kwargs): + menu_item = { + "name": "Link", + "type": MenuItemElement.TYPES.LINK, + "variant": MenuItemElement.VARIANTS.LINK, + "menu_item_order": 0, + "uid": uuid.uuid4(), + "navigation_type": "", + "navigate_to_page_id": None, + "navigate_to_url": "", + "page_parameters": [], + "query_parameters": [], + "parent_menu_item": None, + "target": "self", + "children": [], + } + menu_item.update(kwargs) + return menu_item + + +@pytest.mark.django_db +def test_get_menu_element(api_client, menu_element_fixture): + menu_element = menu_element_fixture["menu_element"] + + # Add a Menu item + menu_item = create_menu_item() + data = {"menu_items": [menu_item]} + ElementHandler().update_element(menu_element, **data) + + page = menu_element_fixture["page_a"] + token = menu_element_fixture["token"] + + url = reverse("api:builder:element:list", kwargs={"page_id": page.id}) + response = api_client.get( + url, + format="json", + HTTP_AUTHORIZATION=f"JWT {token}", + ) + + assert response.status_code == HTTP_200_OK + [menu] = response.json() + + assert menu["id"] == menu_element.id + assert menu["type"] == "menu" + assert menu["orientation"] == "horizontal" + assert menu["menu_items"] == [ + { + "children": [], + "id": menu_element.menu_items.all()[0].id, + "menu_item_order": AnyInt(), + "name": "Link", + "navigate_to_page_id": None, + "navigate_to_url": "", + "navigation_type": "", + "page_parameters": [], + "parent_menu_item": None, + "query_parameters": [], + "target": "self", + "type": "link", + "uid": AnyStr(), + "variant": "link", + }, + ] + + +@pytest.mark.django_db +def test_create_menu_element(api_client, data_fixture): + user, token = data_fixture.create_user_and_token() + page = data_fixture.create_builder_page(user=user) + + url = reverse("api:builder:element:list", kwargs={"page_id": page.id}) + + response = api_client.post( + url, + { + "type": "menu", + }, + format="json", + HTTP_AUTHORIZATION=f"JWT {token}", + ) + + assert response.status_code == HTTP_200_OK + assert response.json()["type"] == "menu" + + +@pytest.mark.django_db +def test_can_update_menu_element_items(api_client, menu_element_fixture): + menu_element = menu_element_fixture["menu_element"] + token = menu_element_fixture["token"] + + url = reverse("api:builder:element:item", kwargs={"element_id": menu_element.id}) + response = api_client.patch( + url, + { + "menu_items": [ + { + "name": "Foo Bar", + "variant": "link", + "value": "", + "type": "link", + "uid": uuid.uuid4(), + "children": [], + "navigation_type": "page", + "navigate_to_page_id": None, + "navigate_to_url": "", + "page_parameters": [], + "query_parameters": [], + "target": "self", + } + ] + }, + format="json", + HTTP_AUTHORIZATION=f"JWT {token}", + ) + + assert response.status_code == HTTP_200_OK + data = response.json() + assert data["id"] == menu_element.id + assert data["menu_items"] == [ + { + "id": menu_element.menu_items.all()[0].id, + "menu_item_order": AnyInt(), + "name": "Foo Bar", + "variant": "link", + "type": "link", + "uid": AnyStr(), + "navigate_to_page_id": None, + "navigate_to_url": "", + "navigation_type": "page", + "page_parameters": [], + "parent_menu_item": None, + "query_parameters": [], + "target": "self", + "children": [], + }, + ] diff --git a/backend/tests/baserow/contrib/builder/api/test_builder_serializer.py b/backend/tests/baserow/contrib/builder/api/test_builder_serializer.py index 4e34d4888..3230400a8 100644 --- a/backend/tests/baserow/contrib/builder/api/test_builder_serializer.py +++ b/backend/tests/baserow/contrib/builder/api/test_builder_serializer.py @@ -48,7 +48,7 @@ def test_validate_login_page_id_raises_error_if_shared_page( builder = builder_fixture["builder"] # Set the builder's page to be the shared page - shared_page = builder.page_set(manager="objects_with_shared").get(shared=True) + shared_page = builder.page_set.get(shared=True) response = api_client.patch( reverse("api:applications:item", kwargs={"application_id": builder.id}), {"login_page_id": shared_page.id}, diff --git a/backend/tests/baserow/contrib/builder/api/workflow_actions/test_workflow_actions_views.py b/backend/tests/baserow/contrib/builder/api/workflow_actions/test_workflow_actions_views.py index 862e78110..195ac5163 100644 --- a/backend/tests/baserow/contrib/builder/api/workflow_actions/test_workflow_actions_views.py +++ b/backend/tests/baserow/contrib/builder/api/workflow_actions/test_workflow_actions_views.py @@ -180,32 +180,25 @@ class PublicTestWorkflowActionType(NotificationWorkflowActionType): @pytest.mark.django_db -def test_public_workflow_actions_view( - api_client, data_fixture, mutable_builder_workflow_action_registry -): +def test_public_workflow_actions_view(api_client, data_fixture): user, token = data_fixture.create_user_and_token() - page = data_fixture.create_builder_page(user=user) + workspace = data_fixture.create_workspace(user=user) - mutable_builder_workflow_action_registry.unregister( - NotificationWorkflowActionType().type - ) - mutable_builder_workflow_action_registry.register(PublicTestWorkflowActionType()) - - workflow_action = BuilderWorkflowActionHandler().create_workflow_action( - PublicTestWorkflowActionType(), test="hello", page=page + builder = data_fixture.create_builder_application(workspace=workspace) + page = data_fixture.create_builder_page(builder=builder) + BuilderWorkflowActionHandler().create_workflow_action( + NotificationWorkflowActionType(), page=page ) - url = reverse( - "api:builder:workflow_action:item", - kwargs={"workflow_action_id": workflow_action.id}, - ) - response = api_client.get( - url, - format="json", - HTTP_AUTHORIZATION=f"JWT {token}", + published_builder = data_fixture.create_builder_application(workspace=None) + published_page = data_fixture.create_builder_page(builder=published_builder) + BuilderWorkflowActionHandler().create_workflow_action( + NotificationWorkflowActionType(), page=published_page ) - assert "test" not in response.json() + data_fixture.create_builder_custom_domain( + builder=builder, published_to=published_builder + ) url = reverse( "api:builder:domains:list_workflow_actions", @@ -217,8 +210,23 @@ def test_public_workflow_actions_view( HTTP_AUTHORIZATION=f"JWT {token}", ) - [workflow_action_in_response] = response.json() - assert "test" in workflow_action_in_response + response_json = response.json() + assert len(response_json) == 1 + assert response_json[0]["type"] == NotificationWorkflowActionType.type + + url = reverse( + "api:builder:domains:list_workflow_actions", + kwargs={"page_id": published_page.id}, + ) + response = api_client.get( + url, + format="json", + HTTP_AUTHORIZATION=f"JWT {token}", + ) + + response_json = response.json() + assert len(response_json) == 1 + assert response_json[0]["type"] == NotificationWorkflowActionType.type @pytest.mark.django_db @@ -704,17 +712,21 @@ def test_dispatch_local_baserow_upsert_row_workflow_action_with_unmatching_index ], ) field = table.field_set.get() - rows = RowHandler().create_rows( - user, - table, - rows_values=[ - {f"field_{field.id}": "Community Engagement"}, - {f"field_{field.id}": "Construction"}, - {f"field_{field.id}": "Complex Construction Design"}, - {f"field_{field.id}": "Simple Construction Design"}, - {f"field_{field.id}": "Landscape Design"}, - {f"field_{field.id}": "Infrastructure Design"}, - ], + rows = ( + RowHandler() + .create_rows( + user, + table, + rows_values=[ + {f"field_{field.id}": "Community Engagement"}, + {f"field_{field.id}": "Construction"}, + {f"field_{field.id}": "Complex Construction Design"}, + {f"field_{field.id}": "Simple Construction Design"}, + {f"field_{field.id}": "Landscape Design"}, + {f"field_{field.id}": "Infrastructure Design"}, + ], + ) + .created_rows ) builder = data_fixture.create_builder_application(workspace=workspace) diff --git a/backend/tests/baserow/contrib/builder/domains/test_domain_handler.py b/backend/tests/baserow/contrib/builder/domains/test_domain_handler.py index 7617009f6..da944772b 100644 --- a/backend/tests/baserow/contrib/builder/domains/test_domain_handler.py +++ b/backend/tests/baserow/contrib/builder/domains/test_domain_handler.py @@ -9,6 +9,7 @@ from baserow.contrib.builder.domains.handler import DomainHandler from baserow.contrib.builder.domains.models import Domain from baserow.contrib.builder.exceptions import BuilderDoesNotExist from baserow.contrib.builder.models import Builder +from baserow.core.cache import global_cache from baserow.core.utils import Progress @@ -171,30 +172,39 @@ def test_domain_publishing(data_fixture): page1 = data_fixture.create_builder_page(builder=builder) page2 = data_fixture.create_builder_page(builder=builder) - element1 = data_fixture.create_builder_heading_element( - page=page1, level=2, value="'foo'" - ) - element2 = data_fixture.create_builder_text_element(page=page1) - element3 = data_fixture.create_builder_heading_element(page=page2) + data_fixture.create_builder_heading_element(page=page1, level=2, value="'foo'") + data_fixture.create_builder_text_element(page=page1) + data_fixture.create_builder_heading_element(page=page2) progress = Progress(100) - DomainHandler().publish(domain1, progress) + domain1 = DomainHandler().publish(domain1, progress) + + # Pretend that someone visited the public builder-by-domain endpoint. + builder_by_domain_cache_key = DomainHandler.get_public_builder_by_domain_cache_key( + domain1.domain_name + ) + + # We populate the builder domain cache + global_cache.get(builder_by_domain_cache_key, default="before") domain1.refresh_from_db() assert domain1.published_to is not None assert domain1.published_to.workspace is None - assert domain1.published_to.page_set.count() == builder.page_set.count() - assert domain1.published_to.page_set.first().element_set.count() == 2 + assert domain1.published_to.visible_pages.count() == builder.visible_pages.count() + assert domain1.published_to.visible_pages.first().element_set.count() == 2 assert Builder.objects.count() == 2 assert progress.progress == progress.total - # Lets publish it a second time. + # Let's publish it a second time. DomainHandler().publish(domain1, progress) + # Following a re-publish, the builder-by-domain cache is invalidated + assert global_cache.get(builder_by_domain_cache_key, default="after") == "after" + assert Builder.objects.count() == 2 @@ -227,3 +237,44 @@ def test_get_domain_public_url(data_fixture): ) assert domain1.get_public_url() == "http://mytest.com:3000" + + +@pytest.mark.django_db +def test_get_published_domain_applications(data_fixture): + user = data_fixture.create_user() + + workspace1 = data_fixture.create_workspace(user=user) + data_fixture.create_builder_application(workspace=workspace1) + builder1 = data_fixture.create_builder_application(workspace=workspace1) + published_builder1 = data_fixture.create_builder_application(workspace=None) + data_fixture.create_builder_custom_domain( + builder=builder1, published_to=published_builder1 + ) + + # Get only published domain applications in workspace1 + published_applications = DomainHandler().get_published_domain_applications( + workspace1 + ) + assert published_applications.count() == 1 + assert published_applications.contains(published_builder1) + + workspace2 = data_fixture.create_workspace(user=user) + data_fixture.create_builder_application(workspace=workspace2) + builder2 = data_fixture.create_builder_application(workspace=workspace2) + published_builder2 = data_fixture.create_builder_application(workspace=None) + data_fixture.create_builder_custom_domain( + builder=builder2, published_to=published_builder2 + ) + + # Get only published domain applications in workspace2 + published_applications = DomainHandler().get_published_domain_applications( + workspace2 + ) + assert published_applications.count() == 1 + assert published_applications.contains(published_builder2) + + # Get published domain applications across the instance. + published_applications = DomainHandler().get_published_domain_applications() + assert published_applications.count() == 2 + assert published_applications.contains(published_builder1) + assert published_applications.contains(published_builder2) diff --git a/backend/tests/baserow/contrib/builder/elements/mixins/test_collection_element_type_mixin.py b/backend/tests/baserow/contrib/builder/elements/mixins/test_collection_element_type_mixin.py index c1033928b..cb18dbb73 100644 --- a/backend/tests/baserow/contrib/builder/elements/mixins/test_collection_element_type_mixin.py +++ b/backend/tests/baserow/contrib/builder/elements/mixins/test_collection_element_type_mixin.py @@ -109,7 +109,7 @@ def test_import_export_collection_element_type(collection_element_mixin_fixture) imported_field = imported_table.field_set.get() # Pluck out the imported builder records. - imported_page = imported_builder.page_set.exclude(path="__shared__")[0] + imported_page = imported_builder.visible_pages.exclude(path="__shared__")[0] imported_element = imported_page.element_set.get() imported_property_options = [ diff --git a/backend/tests/baserow/contrib/builder/elements/test_element_types.py b/backend/tests/baserow/contrib/builder/elements/test_element_types.py index 880771588..74eec7b5d 100644 --- a/backend/tests/baserow/contrib/builder/elements/test_element_types.py +++ b/backend/tests/baserow/contrib/builder/elements/test_element_types.py @@ -1542,7 +1542,7 @@ def test_repeat_element_import_export(data_fixture): imported_field = imported_table.field_set.get() # Pluck out the imported builder records. - imported_page = imported_builder.page_set.all()[0] + imported_page = imported_builder.visible_pages.all()[0] imported_data_source = imported_page.datasource_set.get() imported_root_repeat = imported_page.element_set.get( parent_element_id=None diff --git a/backend/tests/baserow/contrib/builder/elements/test_menu_element_type.py b/backend/tests/baserow/contrib/builder/elements/test_menu_element_type.py new file mode 100644 index 000000000..e75fd69a1 --- /dev/null +++ b/backend/tests/baserow/contrib/builder/elements/test_menu_element_type.py @@ -0,0 +1,439 @@ +import json +import uuid +from collections import defaultdict +from copy import deepcopy + +import pytest + +from baserow.contrib.builder.api.elements.serializers import MenuItemSerializer +from baserow.contrib.builder.elements.handler import ElementHandler +from baserow.contrib.builder.elements.models import MenuElement, MenuItemElement +from baserow.contrib.builder.workflow_actions.models import NotificationWorkflowAction +from baserow.core.utils import MirrorDict +from baserow.test_utils.helpers import AnyInt + + +@pytest.fixture +def menu_element_fixture(data_fixture): + """Fixture to help test the Menu element.""" + + user = data_fixture.create_user() + builder = data_fixture.create_builder_application(user=user) + page_a = data_fixture.create_builder_page(builder=builder, path="/page_a/:foo/") + page_b = data_fixture.create_builder_page(builder=builder, path="/page_b/") + + menu_element = data_fixture.create_builder_menu_element(user=user, page=page_a) + + return { + "page_a": page_a, + "page_b": page_b, + "menu_element": menu_element, + } + + +@pytest.mark.django_db +def test_create_menu_element(menu_element_fixture): + menu_element = menu_element_fixture["menu_element"] + + assert menu_element.menu_items.count() == 0 + assert menu_element.orientation == MenuElement.ORIENTATIONS.HORIZONTAL + + +@pytest.mark.django_db +@pytest.mark.parametrize( + "orientation", + [ + MenuElement.ORIENTATIONS.HORIZONTAL, + MenuElement.ORIENTATIONS.VERTICAL, + ], +) +def test_update_menu_element(menu_element_fixture, orientation): + menu_element = menu_element_fixture["menu_element"] + + data = { + "orientation": orientation, + "menu_items": [], + } + updated_menu_element = ElementHandler().update_element(menu_element, **data) + + assert updated_menu_element.menu_items.count() == 0 + assert updated_menu_element.orientation == orientation + + +@pytest.mark.django_db +@pytest.mark.parametrize( + "name,item_type,variant", + [ + ( + "Page 1", + MenuItemElement.TYPES.LINK, + MenuItemElement.VARIANTS.LINK, + ), + ( + "Page 2", + MenuItemElement.TYPES.LINK, + MenuItemElement.VARIANTS.BUTTON, + ), + ( + "Click me", + MenuItemElement.TYPES.BUTTON, + "", + ), + ( + "", + MenuItemElement.TYPES.SEPARATOR, + "", + ), + ( + "", + MenuItemElement.TYPES.SPACER, + "", + ), + ], +) +def test_add_menu_item(menu_element_fixture, name, item_type, variant): + menu_element = menu_element_fixture["menu_element"] + + assert menu_element.menu_items.count() == 0 + + uid = uuid.uuid4() + data = { + "menu_items": [ + { + "variant": variant, + "type": item_type, + "uid": uid, + "name": name, + "children": [], + } + ] + } + updated_menu_element = ElementHandler().update_element(menu_element, **data) + + assert updated_menu_element.menu_items.count() == 1 + menu_item = updated_menu_element.menu_items.first() + assert menu_item.variant == variant + assert menu_item.type == item_type + assert menu_item.name == name + assert menu_item.menu_item_order == AnyInt() + assert menu_item.uid == uid + assert menu_item.parent_menu_item is None + + +@pytest.mark.django_db +def test_add_sub_link(menu_element_fixture): + menu_element = menu_element_fixture["menu_element"] + + assert menu_element.menu_items.count() == 0 + + parent_uid = uuid.uuid4() + child_uid = uuid.uuid4() + + data = { + "menu_items": [ + { + "name": "Click for more links", + "type": MenuItemElement.TYPES.LINK, + "variant": MenuItemElement.VARIANTS.LINK, + "menu_item_order": 0, + "uid": parent_uid, + "navigation_type": "page", + "navigate_to_page_id": None, + "navigate_to_url": "", + "page_parameters": [], + "query_parameters": [], + "parent_menu_item": None, + "target": "self", + "children": [ + { + "name": "Sublink", + "type": MenuItemElement.TYPES.LINK, + "variant": MenuItemElement.VARIANTS.LINK, + "uid": child_uid, + } + ], + } + ] + } + updated_menu_element = ElementHandler().update_element(menu_element, **data) + + # Both parent and child are MenuItemElement instances + assert updated_menu_element.menu_items.count() == 2 + + parent_item = updated_menu_element.menu_items.get(uid=parent_uid) + assert parent_item.parent_menu_item is None + assert parent_item.uid == parent_uid + + child_item = updated_menu_element.menu_items.get(uid=child_uid) + assert child_item.parent_menu_item == parent_item + assert child_item.uid == child_uid + assert child_item.type == MenuItemElement.TYPES.LINK + assert child_item.variant == MenuItemElement.VARIANTS.LINK + assert child_item.name == "Sublink" + assert child_item.menu_item_order == AnyInt() + + +@pytest.mark.django_db +@pytest.mark.parametrize( + "field,value", + [ + ("name", "New Page"), + ("navigation_type", "link"), + # None is replaced with a valid page in the test + ("navigate_to_page_id", None), + ("navigate_to_url", "https://www.baserow.io"), + ("page_parameters", [{"name": "foo", "value": "'bar'"}]), + ("query_parameters", [{"name": "param", "value": "'baz'"}]), + ("target", "_blank"), + ], +) +def test_update_menu_item(menu_element_fixture, field, value): + menu_element = menu_element_fixture["menu_element"] + + assert menu_element.menu_items.count() == 0 + + uid = uuid.uuid4() + + if field == "navigate_to_page_id": + value = menu_element_fixture["page_b"].id + + menu_item = { + "name": "Page", + "type": MenuItemElement.TYPES.LINK.value, + "variant": MenuItemElement.VARIANTS.LINK.value, + "menu_item_order": 0, + "uid": str(uid), + "navigation_type": "page", + "navigate_to_page_id": None, + "navigate_to_url": "", + "parent_menu_item": None, + "page_parameters": [], + "query_parameters": [], + "target": "self", + "children": [], + } + + expected = deepcopy(menu_item) + expected[field] = value + expected["id"] = AnyInt() + expected["menu_item_order"] = AnyInt() + + # Create the initial Menu item + data = {"menu_items": [menu_item]} + ElementHandler().update_element(menu_element, **data) + + # Update a specific field + menu_item[field] = value + updated_menu_element = ElementHandler().update_element(menu_element, **data) + + item = updated_menu_element.menu_items.first() + updated_menu_item = MenuItemSerializer(item).data + + # Ensure that only that specific field was updated + assert updated_menu_item == expected + + +@pytest.mark.django_db +def test_workflow_action_removed_when_menu_item_deleted( + menu_element_fixture, data_fixture +): + menu_element = menu_element_fixture["menu_element"] + + uid = uuid.uuid4() + menu_item = { + "name": "Greet", + "type": MenuItemElement.TYPES.BUTTON, + "menu_item_order": 0, + "uid": uid, + "children": [], + } + data = {"menu_items": [menu_item]} + ElementHandler().update_element(menu_element, **data) + + data_fixture.create_workflow_action( + NotificationWorkflowAction, + page=menu_element_fixture["page_a"], + element=menu_element, + event=f"{uid}_click", + ) + assert NotificationWorkflowAction.objects.count() == 1 + + # Delete the field + data = {"menu_items": []} + updated_menu_element = ElementHandler().update_element(menu_element, **data) + + assert updated_menu_element.menu_items.exists() is False + + assert NotificationWorkflowAction.objects.count() == 0 + + +@pytest.mark.django_db +def test_specific_workflow_action_removed_when_menu_item_deleted( + menu_element_fixture, data_fixture +): + menu_element = menu_element_fixture["menu_element"] + + uid_1 = uuid.uuid4() + uid_2 = uuid.uuid4() + menu_item_1 = { + "name": "Greet 1", + "type": MenuItemElement.TYPES.BUTTON, + "menu_item_order": 0, + "uid": uid_1, + "children": [], + } + menu_item_2 = { + "name": "Greet 2", + "type": MenuItemElement.TYPES.BUTTON, + "menu_item_order": 0, + "uid": uid_2, + "children": [], + } + data = {"menu_items": [menu_item_1, menu_item_2]} + updated_menu_element = ElementHandler().update_element(menu_element, **data) + assert updated_menu_element.menu_items.count() == 2 + + for uid in [uid_1, uid_2]: + data_fixture.create_workflow_action( + NotificationWorkflowAction, + page=menu_element_fixture["page_a"], + element=menu_element, + event=f"{uid}_click", + ) + + assert NotificationWorkflowAction.objects.count() == 2 + + # Delete the first menu item + data = {"menu_items": [menu_item_2]} + updated_menu_element = ElementHandler().update_element(menu_element, **data) + + assert updated_menu_element.menu_items.count() == 1 + + # Ensure only the Notification for the first menu item exists + assert NotificationWorkflowAction.objects.filter(element=menu_element).count() == 1 + assert ( + NotificationWorkflowAction.objects.filter(element=menu_element).first().event + == f"{uid_2}_click" + ) + + +@pytest.mark.django_db +def test_all_workflow_actions_removed_when_menu_element_deleted( + menu_element_fixture, data_fixture +): + menu_element = menu_element_fixture["menu_element"] + + uid_1 = uuid.uuid4() + uid_2 = uuid.uuid4() + menu_item_1 = { + "name": "Greet 1", + "type": MenuItemElement.TYPES.BUTTON, + "menu_item_order": 0, + "uid": uid_1, + "children": [], + } + menu_item_2 = { + "name": "Greet 2", + "type": MenuItemElement.TYPES.BUTTON, + "menu_item_order": 0, + "uid": uid_2, + "children": [], + } + data = {"menu_items": [menu_item_1, menu_item_2]} + updated_menu_element = ElementHandler().update_element(menu_element, **data) + + for uid in [uid_1, uid_2]: + data_fixture.create_workflow_action( + NotificationWorkflowAction, + page=menu_element_fixture["page_a"], + element=menu_element, + event=f"{uid}_click", + ) + + assert updated_menu_element.menu_items.count() == 2 + assert NotificationWorkflowAction.objects.count() == 2 + + # Delete the Menu element, which will cascade delete all menu items + ElementHandler().delete_element(menu_element) + + # There should be no Menu Element, Menu items, or Notifications remaining + assert MenuElement.objects.count() == 0 + assert MenuItemElement.objects.count() == 0 + assert NotificationWorkflowAction.objects.count() == 0 + + +@pytest.mark.django_db +def test_import_export(menu_element_fixture, data_fixture): + page = menu_element_fixture["page_a"] + menu_element = menu_element_fixture["menu_element"] + + # Create a Menu Element with Menu items. + uid_1 = uuid.uuid4() + uid_2 = uuid.uuid4() + uid_3 = uuid.uuid4() + uid_4 = uuid.uuid4() + menu_item_1 = { + "name": "Greet", + "type": MenuItemElement.TYPES.BUTTON, + "menu_item_order": 0, + "uid": uid_1, + "children": [], + } + menu_item_2 = { + "name": "Link A", + "type": MenuItemElement.TYPES.LINK, + "menu_item_order": 1, + "uid": uid_2, + "children": [], + } + menu_item_3 = { + "name": "Sublinks", + "type": MenuItemElement.TYPES.LINK, + "menu_item_order": 2, + "uid": uid_3, + "children": [ + { + "name": "Sublink A", + "type": MenuItemElement.TYPES.LINK, + "menu_item_order": 3, + "uid": uid_4, + "navigate_to_page_id": page.id, + } + ], + } + + data = {"menu_items": [menu_item_1, menu_item_2, menu_item_3]} + ElementHandler().update_element(menu_element, **data) + + menu_element_type = menu_element.get_type() + + # Export the Menu element and ensure there are no Menu elements + # after deleting it. + exported = menu_element_type.export_serialized(menu_element) + assert json.dumps(exported) + + ElementHandler().delete_element(menu_element) + + assert MenuElement.objects.count() == 0 + assert MenuItemElement.objects.count() == 0 + assert NotificationWorkflowAction.objects.count() == 0 + + # After importing the Menu element the menu items should be correctly + # imported as well. + id_mapping = defaultdict(lambda: MirrorDict()) + menu_element_type.import_serialized(page, exported, id_mapping) + + menu_element = MenuElement.objects.first() + + # Ensure the Menu Items have been imported correctly + button_item = menu_element.menu_items.get(uid=uid_1) + assert button_item.name == "Greet" + + link_item = menu_element.menu_items.get(uid=uid_2) + assert link_item.name == "Link A" + + sublinks_item = menu_element.menu_items.get(uid=uid_3) + assert sublinks_item.name == "Sublinks" + + sublink_a = menu_element.menu_items.get(uid=uid_4) + assert sublink_a.name == "Sublink A" diff --git a/backend/tests/baserow/contrib/builder/elements/test_record_selector_element_type.py b/backend/tests/baserow/contrib/builder/elements/test_record_selector_element_type.py index dd1687a82..95b6f27ac 100644 --- a/backend/tests/baserow/contrib/builder/elements/test_record_selector_element_type.py +++ b/backend/tests/baserow/contrib/builder/elements/test_record_selector_element_type.py @@ -93,7 +93,9 @@ def test_export_import_record_selector_element(data_fixture): import_export_config=config, ) imported_builder = imported_apps[-1] - imported_element = imported_builder.page_set.first().element_set.first().specific + imported_element = ( + imported_builder.visible_pages.first().element_set.first().specific + ) # Check that the formula for option name suffix was updated with the new mapping import_option_name_suffix = imported_element.option_name_suffix diff --git a/backend/tests/baserow/contrib/builder/pages/test_page_handler.py b/backend/tests/baserow/contrib/builder/pages/test_page_handler.py index 44ef9ec28..8c1a2f640 100644 --- a/backend/tests/baserow/contrib/builder/pages/test_page_handler.py +++ b/backend/tests/baserow/contrib/builder/pages/test_page_handler.py @@ -1,5 +1,6 @@ import pytest +from baserow.contrib.builder.domains.handler import DomainHandler from baserow.contrib.builder.elements.models import ColumnElement, TextElement from baserow.contrib.builder.elements.registries import element_type_registry from baserow.contrib.builder.pages.constants import ILLEGAL_PATH_SAMPLE_CHARACTER @@ -17,6 +18,7 @@ from baserow.contrib.builder.pages.exceptions import ( ) from baserow.contrib.builder.pages.handler import PageHandler from baserow.contrib.builder.pages.models import Page +from baserow.core.user_sources.user_source_user import UserSourceUser @pytest.mark.django_db @@ -517,3 +519,37 @@ def test_validate_query_params_edge_cases(): invalid_params = [{"name": f"filter{char}", "type": "text"}] with pytest.raises(InvalidQueryParamName): handler.validate_query_params(path, path_params, invalid_params) + + +def test_get_page_public_records_cache_key(): + user_with_role = UserSourceUser( + None, None, 1, "username", "foo@bar.com", role="admin" + ) + assert ( + PageHandler.get_page_public_records_cache_key(123, user_with_role, "elements") + == "ab_public_page_123_admin_elements_records" + ) + user_without_role = UserSourceUser(None, None, 1, "username", "foo@bar.com") + assert ( + PageHandler.get_page_public_records_cache_key( + 123, user_without_role, "elements" + ) + == "ab_public_page_123_elements_records" + ) + + +@pytest.mark.django_db +def test_is_published_application_page(data_fixture): + user = data_fixture.create_user() + workspace = data_fixture.create_workspace(user=user) + + builder = data_fixture.create_builder_application(workspace=workspace) + page = data_fixture.create_builder_page(builder=builder) + domain = data_fixture.create_builder_custom_domain(builder=builder) + + domain = DomainHandler().publish(domain) + published_builder = domain.published_to + published_page = published_builder.visible_pages.get() + + assert not PageHandler()._is_published_application_page(page.id) + assert PageHandler()._is_published_application_page(published_page.id) diff --git a/backend/tests/baserow/contrib/builder/test_builder_application_type.py b/backend/tests/baserow/contrib/builder/test_builder_application_type.py index 79852e9fe..ce0f98a24 100644 --- a/backend/tests/baserow/contrib/builder/test_builder_application_type.py +++ b/backend/tests/baserow/contrib/builder/test_builder_application_type.py @@ -65,11 +65,11 @@ def test_builder_application_type_init_application(data_fixture): user = data_fixture.create_user() builder = data_fixture.create_builder_application(user=user) - assert Page.objects.count() == 0 + assert Page.objects_without_shared.count() == 0 BuilderApplicationType().init_application(user, builder) - assert Page.objects.count() == 2 # With demo data + assert Page.objects_without_shared.count() == 2 # With demo data @pytest.mark.django_db @@ -621,31 +621,37 @@ def test_builder_application_export(data_fixture): "heading_1_font_weight": "bold", "heading_1_text_color": "#070810ff", "heading_1_text_alignment": "left", + "heading_1_text_decoration": [False, False, False, False], "heading_2_font_family": "inter", "heading_2_font_size": 20, "heading_2_font_weight": "semi-bold", "heading_2_text_color": "#070810ff", "heading_2_text_alignment": "left", + "heading_2_text_decoration": [False, False, False, False], "heading_3_font_family": "inter", "heading_3_font_size": 16, "heading_3_font_weight": "medium", "heading_3_text_color": "#070810ff", "heading_3_text_alignment": "left", + "heading_3_text_decoration": [False, False, False, False], "heading_4_font_family": "inter", "heading_4_font_size": 16, "heading_4_font_weight": "medium", "heading_4_text_color": "#070810ff", "heading_4_text_alignment": "left", + "heading_4_text_decoration": [False, False, False, False], "heading_5_font_family": "inter", "heading_5_font_size": 14, "heading_5_font_weight": "regular", "heading_5_text_color": "#070810ff", "heading_5_text_alignment": "left", + "heading_5_text_decoration": [False, False, False, False], "heading_6_font_family": "inter", "heading_6_font_size": 14, "heading_6_font_weight": "regular", "heading_6_text_color": "#202128", "heading_6_text_alignment": "left", + "heading_6_text_decoration": [False, False, False, False], "button_font_family": "inter", "button_font_size": 13, "button_font_weight": "regular", @@ -663,12 +669,19 @@ def test_builder_application_export(data_fixture): "button_hover_background_color": "#96baf6ff", "button_hover_text_color": "#ffffffff", "button_hover_border_color": "border", + "button_active_background_color": "#4783db", + "button_active_text_color": "#ffffffff", + "button_active_border_color": "#275d9f", "link_font_family": "inter", "link_font_size": 13, "link_font_weight": "regular", "link_text_alignment": "left", "link_text_color": "primary", "link_hover_text_color": "#96baf6ff", + "link_active_text_color": "#275d9f", + "link_active_text_decoration": [True, False, False, False], + "link_default_text_decoration": [True, False, False, False], + "link_hover_text_decoration": [True, False, False, False], "image_alignment": "left", "image_border_radius": 0, "image_max_width": 100, @@ -1038,6 +1051,7 @@ IMPORT_REFERENCE = { "link_alignment": "left", "link_text_color": "primary", "link_hover_text_color": "#ccccccff", + "link_active_text_color": "#275d9f", }, "id": 999, "name": "Holly Sherman", @@ -1059,11 +1073,9 @@ def test_builder_application_import(data_fixture): ) assert builder.id != serialized_values["id"] - assert builder.page_set.count() == 2 + assert builder.visible_pages.count() == 2 # ensure we have the shared page even if it's not in the reference - assert ( - builder.page_set(manager="objects_with_shared").filter(shared=True).count() == 1 - ) + assert builder.page_set.filter(shared=True).count() == 1 assert builder.integrations.count() == 1 first_integration = builder.integrations.first().specific @@ -1071,7 +1083,7 @@ def test_builder_application_import(data_fixture): assert builder.user_sources.count() == 1 - [page1, page2] = builder.page_set.all() + [page1, page2] = builder.visible_pages.all() assert page1.element_set.count() == 6 assert page2.element_set.count() == 1 @@ -1280,7 +1292,7 @@ def test_builder_application_imports_page_with_default_visibility( workspace, serialized_values, config, {} ) - page = builder.page_set.first() + page = builder.visible_pages.first() assert getattr(page, page_property) == value @@ -1469,7 +1481,7 @@ def test_builder_application_imports_correct_default_roles(data_fixture): workspace, serialized_values, config, {} ) - new_element = builder.page_set.first().element_set.all()[0] + new_element = builder.visible_pages.first().element_set.all()[0] new_user_source = builder.user_sources.all()[0] # Ensure the "old" Default User Role doesn't exist @@ -1553,7 +1565,7 @@ def test_ensure_new_element_roles_are_sanitized_during_import_for_default_roles( expected_roles = _expected_roles # Ensure new element has roles updated - new_element = builder.page_set.all()[0].element_set.all()[0] + new_element = builder.visible_pages.all()[0].element_set.all()[0] for index, role in enumerate(new_element.roles): # Default Role's User Source should have changed for new elements if role.startswith(prefix): @@ -1630,7 +1642,7 @@ def test_ensure_new_element_roles_are_sanitized_during_import_for_roles( workspace, serialized, config, {} ) - new_element = builder.page_set.all()[0].element_set.all()[0] + new_element = builder.visible_pages.all()[0].element_set.all()[0] assert new_element.roles == expected_roles diff --git a/backend/tests/baserow/contrib/builder/test_builder_handler.py b/backend/tests/baserow/contrib/builder/test_builder_handler.py index e4b7f123c..19966fcec 100644 --- a/backend/tests/baserow/contrib/builder/test_builder_handler.py +++ b/backend/tests/baserow/contrib/builder/test_builder_handler.py @@ -4,7 +4,10 @@ from django.contrib.auth import get_user_model import pytest -from baserow.contrib.builder.handler import CACHE_KEY_PREFIX, BuilderHandler +from baserow.contrib.builder.handler import ( + USED_PROPERTIES_CACHE_KEY_PREFIX, + BuilderHandler, +) from baserow.core.exceptions import ApplicationDoesNotExist from baserow.core.user_sources.user_source_user import UserSourceUser @@ -46,17 +49,17 @@ def test_get_builder_select_related_theme_config( ( True, "", - f"{CACHE_KEY_PREFIX}_100", + f"{USED_PROPERTIES_CACHE_KEY_PREFIX}_100", ), ( True, "foo_role", - f"{CACHE_KEY_PREFIX}_100", + f"{USED_PROPERTIES_CACHE_KEY_PREFIX}_100", ), ( False, "foo_role", - f"{CACHE_KEY_PREFIX}_100_foo_role", + f"{USED_PROPERTIES_CACHE_KEY_PREFIX}_100_foo_role", ), ], ) @@ -150,3 +153,70 @@ def test_public_allowed_properties_is_cached(data_fixture, django_assert_num_que with django_assert_num_queries(0): result = handler.get_builder_public_properties(user_source_user, builder) assert result == expected_results + + +@pytest.mark.django_db +def test_aggregate_user_source_counts(data_fixture): + user = data_fixture.create_user() + workspace = data_fixture.create_workspace(user=user) + + # A builder with no domains. + builder_no_domains = data_fixture.create_builder_application(workspace=workspace) + data_fixture.create_local_baserow_table_user_source(application=builder_no_domains) + assert BuilderHandler().aggregate_user_source_counts() == 0 + + # A builder with a domain, but it hasn't been published to. + builder_with_unpublished_domains = data_fixture.create_builder_application( + workspace=workspace + ) + data_fixture.create_builder_custom_domain( + builder=builder_with_unpublished_domains, published_to=None + ) + data_fixture.create_local_baserow_table_user_source( + application=builder_with_unpublished_domains + ) + assert BuilderHandler().aggregate_user_source_counts() == 0 + + # A builder with a published domain. + builder_with_published_domains = data_fixture.create_builder_application( + workspace=workspace + ) + published_builder = data_fixture.create_builder_application(workspace=None) + data_fixture.create_builder_custom_domain( + builder=builder_with_published_domains, published_to=published_builder + ) + data_fixture.create_local_baserow_table_user_source( + application=builder_with_published_domains + ) + assert BuilderHandler().aggregate_user_source_counts() == 5 + + +@pytest.mark.django_db +def test_builder_get_published_applications(data_fixture): + user = data_fixture.create_user() + workspace = data_fixture.create_workspace(user=user) + + # A builder with no domains. + data_fixture.create_builder_application(workspace=workspace) + assert BuilderHandler().get_published_applications(workspace=workspace).count() == 0 + + # A builder with a domain, but it hasn't been published to. + builder_with_unpublished_domains = data_fixture.create_builder_application( + workspace=workspace + ) + data_fixture.create_builder_custom_domain( + builder=builder_with_unpublished_domains, published_to=None + ) + assert BuilderHandler().get_published_applications(workspace=workspace).count() == 0 + + # A builder with a published domain. + builder_with_published_domains = data_fixture.create_builder_application( + workspace=workspace + ) + published_builder = data_fixture.create_builder_application(workspace=None) + data_fixture.create_builder_custom_domain( + builder=builder_with_published_domains, published_to=published_builder + ) + qs = BuilderHandler().get_published_applications(workspace=workspace) + assert qs.contains(builder_with_published_domains) + assert qs.count() == 1 diff --git a/backend/tests/baserow/contrib/builder/test_element_formula_mixin.py b/backend/tests/baserow/contrib/builder/test_element_formula_mixin.py index 6670c2ae1..90271a5f1 100644 --- a/backend/tests/baserow/contrib/builder/test_element_formula_mixin.py +++ b/backend/tests/baserow/contrib/builder/test_element_formula_mixin.py @@ -10,6 +10,7 @@ from baserow.contrib.builder.elements.element_types import ( ImageElementType, InputTextElementType, LinkElementType, + MenuElementType, TableElementType, TextElementType, ) @@ -208,3 +209,54 @@ def test_table_element_formula_generator(data_fixture, formula_generator_fixture "label": "get('current_record.field_111')" } assert table_element.data_source_id == data_source.id + + +@pytest.mark.django_db +def test_menu_element_formula_generator(data_fixture, formula_generator_fixture): + """ + Test the MenuElementType's formula_generator(). + + The MenuElement can have one or more MenuItemElements. The MenuItemElement + has several formula fields but doesn't have a distinct type of its own. + Therefore its formula_generator() is overridden and must be tested. + """ + + page = formula_generator_fixture["page"] + menu_element = data_fixture.create_builder_menu_element_items( + user=formula_generator_fixture["user"], + page=page, + ) + menu_item = menu_element.menu_items.first() + menu_item.page_parameters = [ + { + "name": "foo_param", + "value": formula_generator_fixture["formula_1"], + } + ] + menu_item.query_parameters = [ + { + "name": "bar_query", + "value": formula_generator_fixture["formula_1"], + }, + ] + menu_item.navigate_to_url = formula_generator_fixture["formula_1"] + menu_item.save() + + serialized_element = MenuElementType().export_serialized(menu_element) + + imported_element = MenuElementType().import_serialized( + formula_generator_fixture["page"], + serialized_element, + formula_generator_fixture["id_mapping"], + ) + + imported_menu_item = imported_element.menu_items.first() + assert ( + imported_menu_item.page_parameters[0]["value"] + == formula_generator_fixture["formula_2"] + ) + assert ( + imported_menu_item.query_parameters[0]["value"] + == formula_generator_fixture["formula_2"] + ) + assert imported_menu_item.navigate_to_url == formula_generator_fixture["formula_2"] diff --git a/backend/tests/baserow/contrib/builder/test_permissions_manager.py b/backend/tests/baserow/contrib/builder/test_permissions_manager.py index 344ee0af1..7d7f6377c 100755 --- a/backend/tests/baserow/contrib/builder/test_permissions_manager.py +++ b/backend/tests/baserow/contrib/builder/test_permissions_manager.py @@ -230,7 +230,7 @@ def test_allow_if_template_permission_manager_filter_queryset(data_fixture): tests_w1 = [ ( ListPagesBuilderOperationType.type, - Page.objects_with_shared.filter(builder__workspace=workspace_2), + Page.objects.filter(builder__workspace=workspace_2), [shared_page_2.id, page_2.id], ), ( diff --git a/backend/tests/baserow/contrib/database/airtable/test_airtable_column_types.py b/backend/tests/baserow/contrib/database/airtable/test_airtable_column_types.py index 7192deca9..e50889aac 100644 --- a/backend/tests/baserow/contrib/database/airtable/test_airtable_column_types.py +++ b/backend/tests/baserow/contrib/database/airtable/test_airtable_column_types.py @@ -18,6 +18,7 @@ from baserow.contrib.database.airtable.airtable_column_types import ( TextAirtableColumnType, ) from baserow.contrib.database.airtable.config import AirtableImportConfig +from baserow.contrib.database.airtable.exceptions import AirtableSkipCellValue from baserow.contrib.database.airtable.import_report import ( SCOPE_CELL, SCOPE_FIELD, @@ -25,10 +26,12 @@ from baserow.contrib.database.airtable.import_report import ( ) from baserow.contrib.database.airtable.registry import airtable_column_type_registry from baserow.contrib.database.fields.models import ( + AutonumberField, BooleanField, CountField, CreatedOnField, DateField, + DurationField, EmailField, FileField, LastModifiedField, @@ -42,6 +45,7 @@ from baserow.contrib.database.fields.models import ( TextField, URLField, ) +from baserow.contrib.database.fields.utils.duration import D_H, H_M, H_M_S @pytest.mark.django_db @@ -87,6 +91,47 @@ def test_airtable_import_text_column(data_fixture, api_client): "name": "Single line text", "type": "text", } + import_report = AirtableImportReport() + ( + baserow_field, + airtable_column_type, + ) = airtable_column_type_registry.from_airtable_column_to_serialized( + {}, + airtable_field, + AirtableImportConfig(), + import_report, + ) + assert baserow_field.text_default == "" + assert len(import_report.items) == 0 + assert isinstance(baserow_field, TextField) + assert isinstance(airtable_column_type, TextAirtableColumnType) + + with pytest.raises(AirtableSkipCellValue): + assert ( + airtable_column_type.to_baserow_export_empty_value( + {}, + {"name": "Test"}, + {"id": "row1"}, + airtable_field, + baserow_field, + {}, + AirtableImportConfig(), + AirtableImportReport(), + ) + == "" + ) + + +@pytest.mark.django_db +@responses.activate +def test_airtable_import_text_column_preserve_default(data_fixture, api_client): + airtable_field = { + "id": "fldwSc9PqedIhTSqhi5", + "name": "Single line text", + "type": "text", + "default": "test", + } + import_report = AirtableImportReport() ( baserow_field, airtable_column_type, @@ -96,8 +141,22 @@ def test_airtable_import_text_column(data_fixture, api_client): AirtableImportConfig(), AirtableImportReport(), ) - assert isinstance(baserow_field, TextField) - assert isinstance(airtable_column_type, TextAirtableColumnType) + assert baserow_field.text_default == "test" + assert len(import_report.items) == 0 + + assert ( + airtable_column_type.to_baserow_export_empty_value( + {}, + {"name": "Test"}, + {"id": "row1"}, + airtable_field, + baserow_field, + {}, + AirtableImportConfig(), + AirtableImportReport(), + ) + == "" + ) @pytest.mark.django_db @@ -109,6 +168,7 @@ def test_airtable_import_checkbox_column(data_fixture, api_client): "type": "checkbox", "typeOptions": {"color": "green", "icon": "check"}, } + import_report = AirtableImportReport() ( baserow_field, airtable_column_type, @@ -116,12 +176,89 @@ def test_airtable_import_checkbox_column(data_fixture, api_client): {}, airtable_field, AirtableImportConfig(), - AirtableImportReport(), + import_report, ) + assert len(import_report.items) == 0 assert isinstance(baserow_field, BooleanField) assert isinstance(airtable_column_type, CheckboxAirtableColumnType) +@pytest.mark.django_db +@responses.activate +def test_airtable_import_checkbox_column_with_default_value(data_fixture, api_client): + airtable_field = { + "id": "fldTn59fpliSFcwpFA9", + "name": "Checkbox", + "type": "checkbox", + "typeOptions": {"color": "green", "icon": "check"}, + "default": True, + } + import_report = AirtableImportReport() + ( + baserow_field, + airtable_column_type, + ) = airtable_column_type_registry.from_airtable_column_to_serialized( + {}, + airtable_field, + AirtableImportConfig(), + import_report, + ) + assert len(import_report.items) == 1 + assert import_report.items[0].object_name == "Checkbox" + assert import_report.items[0].scope == SCOPE_FIELD + assert import_report.items[0].table == "" + + +@pytest.mark.django_db +@responses.activate +def test_airtable_import_checkbox_column_invalid_icon(data_fixture, api_client): + airtable_field = { + "id": "fldp1IFu0zdgRy70RoX", + "name": "Checkbox", + "type": "checkbox", + "typeOptions": {"color": "green", "icon": "TEST"}, + } + import_report = AirtableImportReport() + ( + baserow_field, + airtable_column_type, + ) = airtable_column_type_registry.from_airtable_column_to_serialized( + {}, + airtable_field, + AirtableImportConfig(), + import_report, + ) + assert len(import_report.items) == 1 + assert import_report.items[0].object_name == "Checkbox" + assert import_report.items[0].scope == SCOPE_FIELD + assert import_report.items[0].table == "" + + +@pytest.mark.django_db +@responses.activate +def test_airtable_import_checkbox_column_invalid_color(data_fixture, api_client): + airtable_field = { + "id": "fldp1IFu0zdgRy70RoX", + "name": "Checkbox", + "type": "checkbox", + "typeOptions": {"color": "TEST", "icon": "check"}, + } + import_report = AirtableImportReport() + ( + baserow_field, + airtable_column_type, + ) = airtable_column_type_registry.from_airtable_column_to_serialized( + {}, + airtable_field, + AirtableImportConfig(), + import_report, + ) + assert len(import_report.items) == 1 + assert import_report.items[0].object_name == "Checkbox" + assert import_report.items[0].scope == SCOPE_FIELD + assert import_report.items[0].table == "" + + @pytest.mark.django_db @responses.activate def test_airtable_import_created_on_column(data_fixture, api_client): @@ -156,9 +293,7 @@ def test_airtable_import_created_on_column(data_fixture, api_client): assert baserow_field.date_include_time is False assert baserow_field.date_time_format == "24" assert baserow_field.date_force_timezone is None - assert len(import_report.items) == 1 - assert import_report.items[0].object_name == "Created" - assert import_report.items[0].scope == SCOPE_FIELD + assert len(import_report.items) == 0 airtable_field = { "id": "fldcTpJuoUVpsDNoszO", @@ -232,9 +367,7 @@ def test_airtable_import_date_column(data_fixture, api_client): assert baserow_field.date_format == "US" assert baserow_field.date_include_time is False assert baserow_field.date_time_format == "24" - assert len(import_report.items) == 1 - assert import_report.items[0].object_name == "ISO DATE" - assert import_report.items[0].scope == SCOPE_FIELD + assert len(import_report.items) == 0 assert ( airtable_column_type.to_baserow_export_serialized_value( @@ -585,6 +718,37 @@ def test_airtable_import_datetime_edge_case_1(data_fixture, api_client): ) +@pytest.mark.django_db +@responses.activate +def test_airtable_import_datetime_with_default_value(data_fixture, api_client): + airtable_field = { + "id": "fldEB5dp0mNjVZu0VJI", + "name": "Date", + "type": "date", + "default": "test", + "typeOptions": { + "isDateTime": True, + "dateFormat": "Local", + "timeFormat": "24hour", + "timeZone": "client", + }, + } + import_report = AirtableImportReport() + ( + baserow_field, + airtable_column_type, + ) = airtable_column_type_registry.from_airtable_column_to_serialized( + {}, + airtable_field, + AirtableImportConfig(), + import_report, + ) + assert len(import_report.items) == 1 + assert import_report.items[0].object_name == "Date" + assert import_report.items[0].scope == SCOPE_FIELD + assert import_report.items[0].table == "" + + @pytest.mark.django_db @responses.activate def test_airtable_import_email_column(data_fixture, api_client): @@ -810,9 +974,7 @@ def test_airtable_import_last_modified_column(data_fixture, api_client): assert baserow_field.date_include_time is False assert baserow_field.date_time_format == "24" assert baserow_field.date_force_timezone is None - assert len(import_report.items) == 1 - assert import_report.items[0].object_name == "Last" - assert import_report.items[0].scope == SCOPE_FIELD + assert len(import_report.items) == 0 airtable_field = { "id": "fldws6n8xdrEJrMxJFJ", @@ -865,6 +1027,52 @@ def test_airtable_import_last_modified_column(data_fixture, api_client): ) +@pytest.mark.django_db +@responses.activate +def test_airtable_import_last_modified_column_depending_fields( + data_fixture, api_client +): + airtable_field = { + "id": "fldws6n8xdrEJrMxJFJ", + "name": "Last", + "type": "formula", + "typeOptions": { + "isDateTime": False, + "dateFormat": "Local", + "displayType": "lastModifiedTime", + "timeZone": "client", + "formulaTextParsed": "LAST_MODIFIED_TIME()", + "dependencies": { + "referencedColumnIdsForValue": [], + "referencedColumnIdsForModification": ["fld123445678"], + "dependsOnAllColumnModifications": False, + }, + "resultType": "date", + "resultIsArray": False, + }, + } + import_report = AirtableImportReport() + ( + baserow_field, + airtable_column_type, + ) = airtable_column_type_registry.from_airtable_column_to_serialized( + {}, + airtable_field, + AirtableImportConfig(), + import_report, + ) + assert isinstance(baserow_field, LastModifiedField) + assert isinstance(airtable_column_type, FormulaAirtableColumnType) + assert baserow_field.date_format == "ISO" + assert baserow_field.date_include_time is False + assert baserow_field.date_time_format == "24" + assert baserow_field.date_force_timezone is None + assert len(import_report.items) == 1 + assert import_report.items[0].object_name == "Last" + assert import_report.items[0].scope == SCOPE_FIELD + assert import_report.items[0].table == "" + + @pytest.mark.django_db @responses.activate def test_airtable_import_foreign_key_column(data_fixture, api_client): @@ -879,15 +1087,14 @@ def test_airtable_import_foreign_key_column(data_fixture, api_client): "symmetricColumnId": "fldFh5wIL430N62LN6t", }, } + import_report = AirtableImportReport() ( baserow_field, airtable_column_type, ) = airtable_column_type_registry.from_airtable_column_to_serialized( - {"id": "tblxxx"}, - airtable_field, - AirtableImportConfig(), - AirtableImportReport(), + {"id": "tblxxx"}, airtable_field, AirtableImportConfig(), import_report ) + assert len(import_report.items) == 0 assert isinstance(baserow_field, LinkRowField) assert isinstance(airtable_column_type, ForeignKeyAirtableColumnType) assert baserow_field.link_row_table_id == "tblRpq315qnnIcg5IjI" @@ -977,6 +1184,49 @@ def test_airtable_import_foreign_key_column(data_fixture, api_client): assert baserow_field.link_row_related_field_id == "fldQcEaGEe7xuhUEuPL" +@pytest.mark.django_db +@responses.activate +def test_airtable_import_foreign_key_column_failed_import(data_fixture, api_client): + airtable_field = { + "id": "fldQcEaGEe7xuhUEuPL", + "name": "Link to Users", + "type": "foreignKey", + "typeOptions": { + "foreignTableId": "tblRpq315qnnIcg5IjI", + "relationship": "one", + "unreversed": True, + "symmetricColumnId": "fldFh5wIL430N62LN6t", + "viewIdForRecordSelection": "vw1234", + "filtersForRecordSelection": [None], + "aiMatchingOptions": {"isAutoFillEnabled": False}, + }, + } + import_report = AirtableImportReport() + ( + baserow_field, + airtable_column_type, + ) = airtable_column_type_registry.from_airtable_column_to_serialized( + {"id": "tblxxx"}, airtable_field, AirtableImportConfig(), import_report + ) + assert len(import_report.items) == 4 + assert import_report.items[0].object_name == "Link to Users" + assert import_report.items[0].scope == SCOPE_FIELD + assert import_report.items[0].table == "" + assert import_report.items[1].object_name == "Link to Users" + assert import_report.items[1].scope == SCOPE_FIELD + assert import_report.items[1].table == "" + assert import_report.items[2].object_name == "Link to Users" + assert import_report.items[2].scope == SCOPE_FIELD + assert import_report.items[2].table == "" + assert import_report.items[3].object_name == "Link to Users" + assert import_report.items[3].scope == SCOPE_FIELD + assert import_report.items[3].table == "" + assert isinstance(baserow_field, LinkRowField) + assert isinstance(airtable_column_type, ForeignKeyAirtableColumnType) + assert baserow_field.link_row_table_id == "tblRpq315qnnIcg5IjI" + assert baserow_field.link_row_related_field_id == "fldFh5wIL430N62LN6t" + + @pytest.mark.django_db @responses.activate def test_airtable_import_multiline_text_column(data_fixture, api_client): @@ -1032,6 +1282,7 @@ def test_airtable_import_rich_text_column(data_fixture, api_client): ) assert isinstance(baserow_field, LongTextField) assert isinstance(airtable_column_type, RichTextTextAirtableColumnType) + assert baserow_field.long_text_enable_rich_text is True content = { "otDocumentId": "otdHtbNg2tJKWj62WMn", @@ -1043,20 +1294,19 @@ def test_airtable_import_rich_text_column(data_fixture, api_client): {"insert": " cubilia curae; Class aptent taciti sociosqu ad litora."}, ], } - assert ( - airtable_column_type.to_baserow_export_serialized_value( - {}, - {"name": "Test"}, - {"id": "row1"}, - airtable_field, - baserow_field, - content, - {}, - AirtableImportConfig(), - AirtableImportReport(), - ) - == "Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere " - "cubilia curae; Class aptent taciti sociosqu ad litora." + assert airtable_column_type.to_baserow_export_serialized_value( + {}, + {"name": "Test"}, + {"id": "row1"}, + airtable_field, + baserow_field, + content, + {}, + AirtableImportConfig(), + AirtableImportReport(), + ) == ( + "**Vestibulum** ante ipsum primis in faucibus orci luctus et ultrices " + "_posuere_ cubilia curae; Class aptent taciti sociosqu ad litora." ) @@ -1079,6 +1329,7 @@ def test_airtable_import_rich_text_column_with_mention(data_fixture, api_client) ) assert isinstance(baserow_field, LongTextField) assert isinstance(airtable_column_type, RichTextTextAirtableColumnType) + assert baserow_field.long_text_enable_rich_text is True content = { "otDocumentId": "otdHtbNg2tJKWj62WMn", @@ -1108,7 +1359,7 @@ def test_airtable_import_rich_text_column_with_mention(data_fixture, api_client) AirtableImportConfig(), AirtableImportReport(), ) == ( - "Vestibulum ante ipsum primis in faucibus orci luctus et ultrices " + "**Vestibulum** ante ipsum primis in faucibus orci luctus et ultrices " "@usrr5CVJ5Lz8ErVZS cubilia curae; Class aptent taciti sociosqu ad litora." ) @@ -1162,14 +1413,58 @@ def test_airtable_import_multi_select_column( assert len(select_options) == 2 assert select_options[0].id == "fldURNo0cvi6YWYcYj1_selEOJmenvqEd6pndFQ" assert select_options[0].value == "Option 1" - assert select_options[0].color == "blue" + assert select_options[0].color == "light-blue" assert select_options[0].order == 1 assert select_options[1].id == "fldURNo0cvi6YWYcYj1_sel5ekvuoNVvl03olMO" assert select_options[1].value == "Option 2" - assert select_options[1].color == "light-blue" + assert select_options[1].color == "light-cyan" assert select_options[1].order == 0 +@pytest.mark.django_db +@responses.activate +def test_airtable_import_multi_select_column_with_default_value( + data_fixture, api_client, django_assert_num_queries +): + table = data_fixture.create_database_table() + airtable_field = { + "id": "fldURNo0cvi6YWYcYj1", + "name": "Multiple select", + "type": "multiSelect", + "default": ["selEOJmenvqEd6pndFQ", "sel5ekvuoNVvl03olMO"], + "typeOptions": { + "choiceOrder": ["sel5ekvuoNVvl03olMO", "selEOJmenvqEd6pndFQ"], + "choices": { + "selEOJmenvqEd6pndFQ": { + "id": "selEOJmenvqEd6pndFQ", + "color": "blue", + "name": "Option 1", + }, + "sel5ekvuoNVvl03olMO": { + "id": "sel5ekvuoNVvl03olMO", + "color": "cyan", + "name": "Option 2", + }, + }, + "disableColors": False, + }, + } + import_report = AirtableImportReport() + ( + baserow_field, + airtable_column_type, + ) = airtable_column_type_registry.from_airtable_column_to_serialized( + {}, + airtable_field, + AirtableImportConfig(), + import_report, + ) + assert len(import_report.items) == 1 + assert import_report.items[0].object_name == "Multiple select" + assert import_report.items[0].scope == SCOPE_FIELD + assert import_report.items[0].table == "" + + @pytest.mark.django_db @responses.activate def test_airtable_import_number_integer_column(data_fixture, api_client): @@ -1556,7 +1851,7 @@ def test_airtable_import_currency_column_non_existing_separator_format( import_report, ) assert len(import_report.items) == 1 - assert import_report.items[0].object_name == 'Number field: "Currency"' + assert import_report.items[0].object_name == "Currency" assert import_report.items[0].scope == SCOPE_FIELD assert import_report.items[0].table == "" @@ -1663,6 +1958,219 @@ def test_airtable_import_percentage_column(data_fixture, api_client): ) +@pytest.mark.django_db +@responses.activate +def test_airtable_import_number_column_default_value(data_fixture, api_client): + airtable_field = { + "id": "fldZBmr4L45mhjILhlA", + "name": "Number", + "type": "number", + "default": 1, + "typeOptions": {}, + } + import_report = AirtableImportReport() + ( + baserow_field, + airtable_column_type, + ) = airtable_column_type_registry.from_airtable_column_to_serialized( + {}, + airtable_field, + AirtableImportConfig(), + import_report, + ) + assert len(import_report.items) == 1 + assert import_report.items[0].object_name == "Number" + assert import_report.items[0].scope == SCOPE_FIELD + assert import_report.items[0].table == "" + + +@pytest.mark.django_db +@responses.activate +def test_airtable_import_days_duration_column(data_fixture, api_client): + airtable_field = { + "id": "fldZBmr4L45mhjILhlA", + "name": "Duration", + "type": "number", + "typeOptions": { + "format": "durationInDays", + }, + } + import_report = AirtableImportReport() + ( + baserow_field, + airtable_column_type, + ) = airtable_column_type_registry.from_airtable_column_to_serialized( + {}, airtable_field, AirtableImportConfig(), import_report + ) + assert len(import_report.items) == 0 + assert isinstance(baserow_field, DurationField) + assert isinstance(airtable_column_type, NumberAirtableColumnType) + assert baserow_field.duration_format == D_H + + assert ( + airtable_column_type.to_baserow_export_serialized_value( + {}, + {"name": "Test"}, + {"id": "row1"}, + airtable_field, + baserow_field, + None, + {}, + AirtableImportConfig(), + AirtableImportReport(), + ) + is None + ) + assert ( + airtable_column_type.to_baserow_export_serialized_value( + {}, + {"name": "Test"}, + {"id": "row1"}, + airtable_field, + baserow_field, + 1, + {}, + AirtableImportConfig(), + AirtableImportReport(), + ) + == 86400 # 1 * 60 * 60 * 24 + ) + + +@pytest.mark.django_db +@responses.activate +def test_airtable_import_duration_column(data_fixture, api_client): + airtable_field = { + "id": "fldZBmr4L45mhjILhlA", + "name": "Duration", + "type": "number", + "typeOptions": {"format": "duration", "durationFormat": "h:mm"}, + } + import_report = AirtableImportReport() + ( + baserow_field, + airtable_column_type, + ) = airtable_column_type_registry.from_airtable_column_to_serialized( + {}, airtable_field, AirtableImportConfig(), import_report + ) + assert len(import_report.items) == 0 + assert isinstance(baserow_field, DurationField) + assert isinstance(airtable_column_type, NumberAirtableColumnType) + assert baserow_field.duration_format == H_M + + airtable_field["typeOptions"]["durationFormat"] = "h:mm:ss" + ( + baserow_field, + airtable_column_type, + ) = airtable_column_type_registry.from_airtable_column_to_serialized( + {}, airtable_field, AirtableImportConfig(), import_report + ) + assert baserow_field.duration_format == H_M_S + + assert ( + airtable_column_type.to_baserow_export_serialized_value( + {}, + {"name": "Test"}, + {"id": "row1"}, + airtable_field, + baserow_field, + None, + {}, + AirtableImportConfig(), + AirtableImportReport(), + ) + is None + ) + assert ( + airtable_column_type.to_baserow_export_serialized_value( + {}, + {"name": "Test"}, + {"id": "row1"}, + airtable_field, + baserow_field, + 1, + {}, + AirtableImportConfig(), + AirtableImportReport(), + ) + == 1 + ) + + +@pytest.mark.django_db +@responses.activate +def test_airtable_import_duration_column_max_value(data_fixture, api_client): + airtable_field = { + "id": "fldZBmr4L45mhjILhlA", + "name": "Duration", + "type": "number", + "typeOptions": {"format": "duration", "durationFormat": "h:mm"}, + } + import_report = AirtableImportReport() + ( + baserow_field, + airtable_column_type, + ) = airtable_column_type_registry.from_airtable_column_to_serialized( + {}, airtable_field, AirtableImportConfig(), import_report + ) + + assert ( + airtable_column_type.to_baserow_export_serialized_value( + {}, + {"name": "Test"}, + {"id": "row1"}, + airtable_field, + baserow_field, + 86399999913601, + {}, + AirtableImportConfig(), + import_report, + ) + is None + ) + assert len(import_report.items) == 1 + assert import_report.items[0].object_name == 'Row: "row1", field: "Duration"' + assert import_report.items[0].scope == SCOPE_CELL + assert import_report.items[0].table == "Test" + + +@pytest.mark.django_db +@responses.activate +def test_airtable_import_duration_column_max_negative_value(data_fixture, api_client): + airtable_field = { + "id": "fldZBmr4L45mhjILhlA", + "name": "Duration", + "type": "number", + "typeOptions": {"format": "duration", "durationFormat": "h:mm"}, + } + import_report = AirtableImportReport() + ( + baserow_field, + airtable_column_type, + ) = airtable_column_type_registry.from_airtable_column_to_serialized( + {}, airtable_field, AirtableImportConfig(), import_report + ) + + assert ( + airtable_column_type.to_baserow_export_serialized_value( + {}, + {"name": "Test"}, + {"id": "row1"}, + airtable_field, + baserow_field, + -86399999913601, + {}, + AirtableImportConfig(), + import_report, + ) + is None + ) + assert len(import_report.items) == 1 + assert import_report.items[0].object_name == 'Row: "row1", field: "Duration"' + assert import_report.items[0].scope == SCOPE_CELL + assert import_report.items[0].table == "Test" + + @pytest.mark.django_db @responses.activate def test_airtable_import_phone_column(data_fixture, api_client): @@ -1721,8 +2229,9 @@ def test_airtable_import_rating_column(data_fixture, api_client): "id": "fldp1IFu0zdgRy70RoX", "name": "Rating", "type": "rating", - "typeOptions": {"color": "yellow", "icon": "star", "max": 5}, + "typeOptions": {"color": "blue", "icon": "heart", "max": 5}, } + import_report = AirtableImportReport() ( baserow_field, airtable_column_type, @@ -1730,11 +2239,14 @@ def test_airtable_import_rating_column(data_fixture, api_client): {}, airtable_field, AirtableImportConfig(), - AirtableImportReport(), + import_report, ) + assert len(import_report.items) == 0 assert isinstance(baserow_field, RatingField) assert isinstance(airtable_column_type, RatingAirtableColumnType) assert baserow_field.max_value == 5 + assert baserow_field.color == "dark-blue" + assert baserow_field.style == "heart" assert ( airtable_column_type.to_baserow_export_serialized_value( {}, @@ -1745,12 +2257,68 @@ def test_airtable_import_rating_column(data_fixture, api_client): 5, {}, AirtableImportConfig(), - AirtableImportReport(), + import_report, ) == 5 ) +@pytest.mark.django_db +@responses.activate +def test_airtable_import_rating_column_invalid_icon(data_fixture, api_client): + airtable_field = { + "id": "fldp1IFu0zdgRy70RoX", + "name": "Rating", + "type": "rating", + "typeOptions": {"color": "blue", "icon": "TEST", "max": 5}, + } + import_report = AirtableImportReport() + ( + baserow_field, + airtable_column_type, + ) = airtable_column_type_registry.from_airtable_column_to_serialized( + {}, + airtable_field, + AirtableImportConfig(), + import_report, + ) + assert len(import_report.items) == 1 + assert import_report.items[0].object_name == "Rating" + assert import_report.items[0].scope == SCOPE_FIELD + assert import_report.items[0].table == "" + assert baserow_field.max_value == 5 + assert baserow_field.color == "dark-blue" + assert baserow_field.style == "star" + + +@pytest.mark.django_db +@responses.activate +def test_airtable_import_rating_column_invalid_color(data_fixture, api_client): + airtable_field = { + "id": "fldp1IFu0zdgRy70RoX", + "name": "Rating", + "type": "rating", + "typeOptions": {"color": "TEST", "icon": "heart", "max": 5}, + } + import_report = AirtableImportReport() + ( + baserow_field, + airtable_column_type, + ) = airtable_column_type_registry.from_airtable_column_to_serialized( + {}, + airtable_field, + AirtableImportConfig(), + import_report, + ) + assert len(import_report.items) == 1 + assert import_report.items[0].object_name == "Rating" + assert import_report.items[0].scope == SCOPE_FIELD + assert import_report.items[0].table == "" + assert baserow_field.max_value == 5 + assert baserow_field.color == "dark-blue" + assert baserow_field.style == "heart" + + @pytest.mark.django_db @responses.activate def test_airtable_import_select_column( @@ -1800,14 +2368,55 @@ def test_airtable_import_select_column( assert len(select_options) == 2 assert select_options[0].id == "fldRd2Vkzgsf6X4z6B4_selbh6rEWaaiyQvWyfg" assert select_options[0].value == "Option A" - assert select_options[0].color == "blue" + assert select_options[0].color == "light-blue" assert select_options[0].order == 0 assert select_options[1].id == "fldRd2Vkzgsf6X4z6B4_selvZgpWhbkeRVphROT" assert select_options[1].value == "Option B" - assert select_options[1].color == "light-blue" + assert select_options[1].color == "light-cyan" assert select_options[1].order == 1 +@pytest.mark.django_db +@responses.activate +def test_airtable_import_select_column_with_default_value( + data_fixture, api_client, django_assert_num_queries +): + table = data_fixture.create_database_table() + airtable_field = { + "id": "fldRd2Vkzgsf6X4z6B4", + "name": "Single select", + "type": "select", + "default": "selbh6rEWaaiyQvWyfg", + "typeOptions": { + "choiceOrder": ["selbh6rEWaaiyQvWyfg", "selvZgpWhbkeRVphROT"], + "choices": { + "selbh6rEWaaiyQvWyfg": { + "id": "selbh6rEWaaiyQvWyfg", + "color": "blue", + "name": "Option A", + }, + "selvZgpWhbkeRVphROT": { + "id": "selvZgpWhbkeRVphROT", + "color": "cyan", + "name": "Option B", + }, + }, + "disableColors": False, + }, + } + import_report = AirtableImportReport() + ( + baserow_field, + airtable_column_type, + ) = airtable_column_type_registry.from_airtable_column_to_serialized( + {}, airtable_field, AirtableImportConfig(), import_report + ) + assert len(import_report.items) == 1 + assert import_report.items[0].object_name == "Single select" + assert import_report.items[0].scope == SCOPE_FIELD + assert import_report.items[0].table == "" + + @pytest.mark.django_db @responses.activate def test_airtable_import_url_column(data_fixture, api_client): @@ -1906,3 +2515,44 @@ def test_airtable_import_count_column(data_fixture, api_client): ) is None ) + + +@pytest.mark.django_db +@responses.activate +def test_airtable_import_autonumber_column(data_fixture, api_client): + airtable_field = { + "id": "fldG9y88Zw7q7u4Z7i4", + "name": "ID", + "type": "autoNumber", + "typeOptions": { + "maxUsedAutoNumber": 8, + }, + } + import_report = AirtableImportReport() + ( + baserow_field, + airtable_column_type, + ) = airtable_column_type_registry.from_airtable_column_to_serialized( + {}, + airtable_field, + AirtableImportConfig(), + AirtableImportReport(), + ) + assert len(import_report.items) == 0 + assert isinstance(baserow_field, AutonumberField) + + assert ( + airtable_column_type.to_baserow_export_serialized_value( + {}, + {"name": "Test"}, + {"id": "row1"}, + airtable_field, + baserow_field, + 1, + {}, + AirtableImportConfig(), + import_report, + ) + == 1 + ) + assert len(import_report.items) == 0 diff --git a/backend/tests/baserow/contrib/database/airtable/test_airtable_filter_import.py b/backend/tests/baserow/contrib/database/airtable/test_airtable_filter_import.py new file mode 100644 index 000000000..1648a330f --- /dev/null +++ b/backend/tests/baserow/contrib/database/airtable/test_airtable_filter_import.py @@ -0,0 +1,1058 @@ +import json +from copy import deepcopy + +import pytest + +from baserow.contrib.database.airtable.config import AirtableImportConfig +from baserow.contrib.database.airtable.exceptions import AirtableSkipFilter +from baserow.contrib.database.airtable.import_report import AirtableImportReport +from baserow.contrib.database.airtable.registry import ( + airtable_column_type_registry, + airtable_filter_operator_registry, +) + +AIRTABLE_TABLE = { + "id": "tbl7glLIGtH8C8zGCzb", + "name": "Data", + "primaryColumnId": "", + "columns": [], + "meaningfulColumnOrder": [], + "views": [], + "viewOrder": [], + "viewsById": {}, + "viewSectionsById": {}, + "schemaChecksum": "46f523a43433afe37d63e00d1a0f36c64310f06e4e0af2c32b6e99f26ab0e51a", +} +AIRTABLE_COLUMN_PER_TYPE = { + "text": {"id": "fld2K7nZbMvWBYE6g", "name": "Single line text", "type": "text"}, + "multilineText": { + "id": "fld8arQx6h2H91ONW", + "name": "Long text", + "type": "multilineText", + }, + "multipleAttachment": { + "id": "fldRhiYOuJrWF5DUR", + "name": "Attachment", + "type": "multipleAttachment", + "typeOptions": {"unreversed": True}, + }, + "checkbox": { + "id": "fldrWHvavdw0eAV1h", + "name": "Checkbox", + "type": "checkbox", + "typeOptions": {"color": "green", "icon": "check"}, + }, + "multiSelect": { + "id": "fldE3rb2UYv3a605v", + "name": "Multiple select", + "type": "multiSelect", + "typeOptions": { + "choiceOrder": [ + "selNkxVarxxS8tRkS", + "selFSuP84urXClrlS", + "selvostaiXnRkaHXI", + ], + "choices": { + "selNkxVarxxS8tRkS": { + "id": "selNkxVarxxS8tRkS", + "color": "blue", + "name": "Option 1", + }, + "selFSuP84urXClrlS": { + "id": "selFSuP84urXClrlS", + "color": "cyan", + "name": "Option 2", + }, + "selvostaiXnRkaHXI": { + "id": "selvostaiXnRkaHXI", + "color": "teal", + "name": "Option 3", + }, + }, + "disableColors": False, + }, + }, + "select": { + "id": "fldWmh0gNFmvYHLwy", + "name": "Single select", + "type": "select", + "typeOptions": { + "choiceOrder": [ + "sela2TITKl8Ng946B", + "selTvmx6xRumPDwa7", + "selRvipUxtrC2Wc6g", + ], + "choices": { + "sela2TITKl8Ng946B": { + "id": "sela2TITKl8Ng946B", + "color": "blue", + "name": "Option A", + }, + "selTvmx6xRumPDwa7": { + "id": "selTvmx6xRumPDwa7", + "color": "cyan", + "name": "Option B", + }, + "selRvipUxtrC2Wc6g": { + "id": "selRvipUxtrC2Wc6g", + "color": "teal", + "name": "Option C", + }, + }, + "disableColors": False, + }, + }, + "collaborator": { + "id": "fldLobeVXHF0LkGUd", + "name": "Collaborator", + "type": "collaborator", + "typeOptions": { + "shouldNotify": False, + "canAddNonBaseCollaborators": False, + "createdAsPrimaryKeyForPeopleTable": False, + }, + }, + "date": { + "id": "fldVzq9v4wQr4vbFv", + "name": "Date", + "type": "date", + "typeOptions": {"isDateTime": False, "dateFormat": "Local"}, + }, + "phone": {"id": "fldfANyudw6u1hWaE", "name": "Phone", "type": "phone"}, + "number": { + "id": "fld94jstPyHsXcXmE", + "name": "Number", + "type": "number", + "typeOptions": { + "format": "decimal", + "precision": 1, + "negative": False, + "validatorName": "positive", + "separatorFormat": "local", + "shouldShowThousandsSeparator": True, + }, + }, + "duration": { + "id": "fld94jstPyHsXcXmE", + "name": "Number", + "type": "number", + "typeOptions": {"format": "duration", "durationFormat": "h:mm"}, + }, + "rating": { + "id": "fldB84fL8kshHAOLm", + "name": "Rating", + "type": "rating", + "typeOptions": {"color": "yellow", "icon": "star", "max": 5}, + }, + "autoNumber": { + "id": "fldU0DnfRMRewuH71", + "name": "ID", + "type": "autoNumber", + "typeOptions": {"maxUsedAutoNumber": 3}, + }, + "foreignKey": { + "id": "fldX30z0jmPZFKGPl", + "name": "Table 2", + "type": "foreignKey", + "typeOptions": { + "foreignTableId": "tbllhx9chTN5MFEwH", + "relationship": "many", + "unreversed": True, + "symmetricColumnId": "fldDERrIKuv3ACdr6", + }, + }, +} + +ROW_ID_MAPPING = { + "tbllhx9chTN5MFEwH": { + "rect9vRzdJvCLrRg8": 1, + "rect9vRzdJvCLrRg9": 2, + } +} + +ALL_AIRTABLE_FILTERS_PER_TYPE = { + "text": [ + { + "operator": "contains", + "value": "1", + "baserow_filter_type": "contains", + "baserow_value": "1", + }, + { + "operator": "doesNotContain", + "value": "1", + "baserow_filter_type": "contains_not", + "baserow_value": "1", + }, + { + "operator": "=", + "value": "1", + "baserow_filter_type": "equal", + "baserow_value": "1", + }, + { + "operator": "!=", + "value": "1", + "baserow_filter_type": "not_equal", + "baserow_value": "1", + }, + { + "operator": "isEmpty", + "value": None, + "baserow_filter_type": "empty", + "baserow_value": "", + }, + { + "operator": "isNotEmpty", + "value": None, + "baserow_filter_type": "not_empty", + "baserow_value": "", + }, + ], + "multilineText": [ + { + "operator": "contains", + "value": "1", + "baserow_filter_type": "contains", + "baserow_value": "1", + }, + { + "operator": "doesNotContain", + "value": "1", + "baserow_filter_type": "contains_not", + "baserow_value": "1", + }, + { + "operator": "=", + "value": "1", + "baserow_filter_type": "equal", + "baserow_value": "1", + }, + { + "operator": "!=", + "value": "1", + "baserow_filter_type": "not_equal", + "baserow_value": "1", + }, + { + "operator": "isEmpty", + "value": None, + "baserow_filter_type": "empty", + "baserow_value": "", + }, + { + "operator": "isNotEmpty", + "value": None, + "baserow_filter_type": "not_empty", + "baserow_value": "", + }, + ], + "multipleAttachment": [ + { + "operator": "filename", + "value": "test", + "baserow_filter_type": "filename_contains", + "baserow_value": "test", + }, + { + "operator": "filetype", + "value": "image", + "baserow_filter_type": "has_file_type", + "baserow_value": "image", + }, + { + "operator": "filetype", + "value": "text", + "baserow_filter_type": "has_file_type", + "baserow_value": "document", + }, + { + "operator": "isEmpty", + "value": None, + "baserow_filter_type": "empty", + "baserow_value": "", + }, + { + "operator": "isNotEmpty", + "value": None, + "baserow_filter_type": "not_empty", + "baserow_value": "", + }, + ], + "checkbox": [ + { + "operator": "=", + "value": True, + "baserow_filter_type": "boolean", + "baserow_value": "true", + }, + { + "operator": "=", + "value": False, + "baserow_filter_type": "boolean", + "baserow_value": "false", + }, + ], + "multiSelect": [ + { + "operator": "|", + "value": ["selNkxVarxxS8tRkS"], + "baserow_skip": True, + }, + { + "operator": "&", + "value": ["selFSuP84urXClrlS"], + "baserow_skip": True, + }, + { + "operator": "=", + "value": ["selvostaiXnRkaHXI"], + "baserow_filter_type": "multiple_select_has", + "baserow_value": "fldE3rb2UYv3a605v_selvostaiXnRkaHXI", + }, + { + "operator": "doesNotContain", + "value": ["selvostaiXnRkaHXI"], + "baserow_filter_type": "multiple_select_has_not", + "baserow_value": "fldE3rb2UYv3a605v_selvostaiXnRkaHXI", + }, + { + "operator": "isEmpty", + "value": None, + "baserow_filter_type": "empty", + "baserow_value": "", + }, + { + "operator": "isNotEmpty", + "value": None, + "baserow_filter_type": "not_empty", + "baserow_value": "", + }, + ], + "select": [ + { + "operator": "=", + "value": "sela2TITKl8Ng946B", + "baserow_filter_type": "single_select_equal", + "baserow_value": "fldWmh0gNFmvYHLwy_sela2TITKl8Ng946B", + }, + { + "operator": "!=", + "value": "selRvipUxtrC2Wc6g", + "baserow_filter_type": "single_select_not_equal", + "baserow_value": "fldWmh0gNFmvYHLwy_selRvipUxtrC2Wc6g", + }, + { + "operator": "isAnyOf", + "value": ["selTvmx6xRumPDwa7", "selTvmx6xRumPDwa8"], + "baserow_filter_type": "single_select_is_any_of", + "baserow_value": "fldWmh0gNFmvYHLwy_selTvmx6xRumPDwa7,fldWmh0gNFmvYHLwy_selTvmx6xRumPDwa8", + }, + { + "operator": "isNoneOf", + "value": ["selTvmx6xRumPDwa7", "selTvmx6xRumPDwa8"], + "baserow_filter_type": "single_select_is_none_of", + "baserow_value": "fldWmh0gNFmvYHLwy_selTvmx6xRumPDwa7,fldWmh0gNFmvYHLwy_selTvmx6xRumPDwa8", + }, + { + "operator": "isEmpty", + "value": None, + "baserow_filter_type": "empty", + "baserow_value": "", + }, + { + "operator": "isNotEmpty", + "value": None, + "baserow_filter_type": "not_empty", + "baserow_value": "", + }, + ], + "collaborator": [ + { + "operator": "=", + "value": "usrGIN77VWdhm7LKk", + "baserow_filter_type": "multiple_collaborators_has", + "baserow_value": "usrGIN77VWdhm7LKk", + }, + { + "operator": "!=", + "value": "usrGIN77VWdhm7LKk", + "baserow_filter_type": "multiple_collaborators_has_not", + "baserow_value": "usrGIN77VWdhm7LKk", + }, + { + "operator": "isAnyOf", + "value": ["usrGIN77VWdhm7LKk"], + "baserow_skip": True, + }, + { + "operator": "isNoneOf", + "value": ["usrGIN77VWdhm7LKk"], + "baserow_skip": True, + }, + { + "operator": "isEmpty", + "value": None, + "baserow_filter_type": "empty", + "baserow_value": "", + }, + { + "operator": "isNotEmpty", + "value": None, + "baserow_filter_type": "not_empty", + "baserow_value": "", + }, + ], + "date": [ + { + "operator": "=", + "value": { + "mode": "exactDate", + "exactDate": "2025-02-05T00:00:00.000Z", + "timeZone": "Europe/Amsterdam", + "shouldUseCorrectTimeZoneForFormulaicColumn": True, + }, + "baserow_filter_type": "date_is", + "baserow_value": "Europe/Amsterdam?2025-02-05?exact_date", + }, + { + "operator": "=", + "value": { + "mode": "tomorrow", + "timeZone": "Europe/Amsterdam", + "shouldUseCorrectTimeZoneForFormulaicColumn": True, + }, + "baserow_filter_type": "date_is", + "baserow_value": "Europe/Amsterdam??tomorrow", + }, + { + "operator": "=", + "value": { + "mode": "today", + "timeZone": "Europe/Amsterdam", + "shouldUseCorrectTimeZoneForFormulaicColumn": True, + }, + "baserow_filter_type": "date_is", + "baserow_value": "Europe/Amsterdam??today", + }, + { + "operator": "=", + "value": { + "mode": "yesterday", + "timeZone": "Europe/Amsterdam", + "shouldUseCorrectTimeZoneForFormulaicColumn": True, + }, + "baserow_filter_type": "date_is", + "baserow_value": "Europe/Amsterdam??yesterday", + }, + { + "operator": "=", + "value": { + "mode": "oneWeekAgo", + "timeZone": "Europe/Amsterdam", + "shouldUseCorrectTimeZoneForFormulaicColumn": True, + }, + "baserow_filter_type": "date_is", + "baserow_value": "Europe/Amsterdam?1?nr_weeks_ago", + }, + { + "operator": "=", + "value": { + "mode": "oneWeekFromNow", + "timeZone": "Europe/Amsterdam", + "shouldUseCorrectTimeZoneForFormulaicColumn": True, + }, + "baserow_filter_type": "date_is", + "baserow_value": "Europe/Amsterdam?1?nr_weeks_from_now", + }, + { + "operator": "=", + "value": { + "mode": "oneMonthAgo", + "timeZone": "Europe/Amsterdam", + "shouldUseCorrectTimeZoneForFormulaicColumn": True, + }, + "baserow_filter_type": "date_is", + "baserow_value": "Europe/Amsterdam??one_month_ago", + }, + { + "operator": "=", + "value": { + "mode": "oneMonthFromNow", + "timeZone": "Europe/Amsterdam", + "shouldUseCorrectTimeZoneForFormulaicColumn": True, + }, + "baserow_filter_type": "date_is", + "baserow_value": "Europe/Amsterdam?1?nr_months_from_now", + }, + { + "operator": "=", + "value": { + "mode": "daysAgo", + "numberOfDays": 1, + "timeZone": "Europe/Amsterdam", + "shouldUseCorrectTimeZoneForFormulaicColumn": True, + }, + "baserow_filter_type": "date_is", + "baserow_value": "Europe/Amsterdam?1?nr_days_ago", + }, + { + "operator": "=", + "value": { + "mode": "daysFromNow", + "numberOfDays": 1, + "timeZone": "Europe/Amsterdam", + "shouldUseCorrectTimeZoneForFormulaicColumn": True, + }, + "baserow_filter_type": "date_is", + "baserow_value": "Europe/Amsterdam?1?nr_days_from_now", + }, + { + "operator": "isWithin", + "value": { + "mode": "pastWeek", + "timeZone": "Europe/Amsterdam", + "shouldUseCorrectTimeZoneForFormulaicColumn": True, + }, + "baserow_filter_type": "date_is_within", + "baserow_value": "Europe/Amsterdam?1?nr_weeks_ago", + }, + { + "operator": "isWithin", + "value": { + "mode": "pastMonth", + "timeZone": "Europe/Amsterdam", + "shouldUseCorrectTimeZoneForFormulaicColumn": True, + }, + "baserow_filter_type": "date_is_within", + "baserow_value": "Europe/Amsterdam?1?nr_months_ago", + }, + { + "operator": "isWithin", + "value": { + "mode": "pastYear", + "timeZone": "Europe/Amsterdam", + "shouldUseCorrectTimeZoneForFormulaicColumn": True, + }, + "baserow_filter_type": "date_is_within", + "baserow_value": "Europe/Amsterdam?1?nr_years_ago", + }, + { + "operator": "isWithin", + "value": { + "mode": "nextWeek", + "timeZone": "Europe/Amsterdam", + "shouldUseCorrectTimeZoneForFormulaicColumn": True, + }, + "baserow_filter_type": "date_is_within", + "baserow_value": "Europe/Amsterdam??next_week", + }, + { + "operator": "isWithin", + "value": { + "mode": "nextMonth", + "timeZone": "Europe/Amsterdam", + "shouldUseCorrectTimeZoneForFormulaicColumn": True, + }, + "baserow_filter_type": "date_is_within", + "baserow_value": "Europe/Amsterdam??next_month", + }, + { + "operator": "isWithin", + "value": { + "mode": "thisCalendarYear", + "timeZone": "Europe/Amsterdam", + "shouldUseCorrectTimeZoneForFormulaicColumn": True, + }, + "baserow_filter_type": "date_is_within", + "baserow_value": "Europe/Amsterdam?0?nr_years_ago", + }, + { + "operator": "isWithin", + "value": { + "mode": "nextNumberOfDays", + "numberOfDays": 1, + "timeZone": "Europe/Amsterdam", + "shouldUseCorrectTimeZoneForFormulaicColumn": True, + }, + "baserow_filter_type": "date_is_within", + "baserow_value": "Europe/Amsterdam?1?nr_days_from_now", + }, + { + "operator": "isWithin", + "value": { + "mode": "pastNumberOfDays", + "numberOfDays": 1, + "timeZone": "Europe/Amsterdam", + "shouldUseCorrectTimeZoneForFormulaicColumn": True, + }, + "baserow_filter_type": "date_is_within", + "baserow_value": "Europe/Amsterdam?1?nr_days_ago", + }, + { + "operator": "<", + "value": { + "mode": "exactDate", + "exactDate": "2025-02-04T00:00:00.000Z", + "timeZone": "Europe/Amsterdam", + "shouldUseCorrectTimeZoneForFormulaicColumn": True, + }, + "baserow_filter_type": "date_is_before", + "baserow_value": "Europe/Amsterdam?2025-02-04?exact_date", + }, + { + "operator": ">", + "value": { + "mode": "exactDate", + "exactDate": "2025-02-13T00:00:00.000Z", + "timeZone": "Europe/Amsterdam", + "shouldUseCorrectTimeZoneForFormulaicColumn": True, + }, + "baserow_filter_type": "date_is_after", + "baserow_value": "Europe/Amsterdam?2025-02-13?exact_date", + }, + { + "operator": "<=", + "value": { + "mode": "exactDate", + "exactDate": "2025-02-02T00:00:00.000Z", + "timeZone": "Europe/Amsterdam", + "shouldUseCorrectTimeZoneForFormulaicColumn": True, + }, + "baserow_filter_type": "date_is_on_or_before", + "baserow_value": "Europe/Amsterdam?2025-02-02?exact_date", + }, + { + "operator": ">=", + "value": { + "mode": "exactDate", + "exactDate": "2025-02-05T00:00:00.000Z", + "timeZone": "Europe/Amsterdam", + "shouldUseCorrectTimeZoneForFormulaicColumn": True, + }, + "baserow_filter_type": "date_is_on_or_after", + "baserow_value": "Europe/Amsterdam?2025-02-05?exact_date", + }, + { + "operator": "!=", + "value": { + "mode": "exactDate", + "exactDate": "2025-02-05T00:00:00.000Z", + "timeZone": "Europe/Amsterdam", + "shouldUseCorrectTimeZoneForFormulaicColumn": True, + }, + "baserow_filter_type": "date_is_not", + "baserow_value": "Europe/Amsterdam?2025-02-05?exact_date", + }, + { + "operator": "isEmpty", + "value": None, + "baserow_filter_type": "empty", + "baserow_value": "", + }, + { + "id": "fltzpQ8PlY7w2DKb4", + "columnId": "fldVzq9v4wQr4vbFv", + "operator": "isNotEmpty", + "value": None, + "baserow_filter_type": "not_empty", + "baserow_value": "", + }, + ], + "phone": [ + { + "operator": "contains", + "value": "1", + "baserow_filter_type": "contains", + "baserow_value": "1", + }, + { + "operator": "doesNotContain", + "value": "1", + "baserow_filter_type": "contains_not", + "baserow_value": "1", + }, + { + "operator": "=", + "value": "1", + "baserow_filter_type": "equal", + "baserow_value": "1", + }, + { + "operator": "!=", + "value": "1", + "baserow_filter_type": "not_equal", + "baserow_value": "1", + }, + { + "operator": "isEmpty", + "value": None, + "baserow_filter_type": "empty", + "baserow_value": "", + }, + { + "operator": "isNotEmpty", + "value": None, + "baserow_filter_type": "not_empty", + "baserow_value": "", + }, + ], + "number": [ + { + "operator": "=", + "value": 1, + "baserow_filter_type": "equal", + "baserow_value": "1", + }, + { + "operator": "!=", + "value": 1, + "baserow_filter_type": "not_equal", + "baserow_value": "1", + }, + { + "operator": "<", + "value": 1, + "baserow_filter_type": "lower_than", + "baserow_value": "1", + }, + { + "operator": ">", + "value": 1, + "baserow_filter_type": "higher_than", + "baserow_value": "1", + }, + { + "operator": "<=", + "value": 1, + "baserow_filter_type": "lower_than_or_equal", + "baserow_value": "1", + }, + { + "operator": ">=", + "value": 1, + "baserow_filter_type": "higher_than_or_equal", + "baserow_value": "1", + }, + { + "operator": "isEmpty", + "value": None, + "baserow_filter_type": "empty", + "baserow_value": "", + }, + { + "operator": "isNotEmpty", + "value": None, + "baserow_filter_type": "not_empty", + "baserow_value": "", + }, + ], + "duration": [ + { + "operator": "=", + "value": 86399999913600, + "baserow_filter_type": "equal", + "baserow_value": "86399999913600", + }, + { + "operator": "=", + "value": 86399999913601, + "baserow_filter_type": "equal", + "baserow_skip": True, + }, + { + "operator": "!=", + "value": 86399999913601, + "baserow_filter_type": "not_equal", + "baserow_skip": True, + }, + { + "operator": "<", + "value": 86399999913601, + "baserow_filter_type": "lower_than", + "baserow_skip": True, + }, + { + "operator": ">", + "value": 86399999913601, + "baserow_filter_type": "higher_than", + "baserow_skip": True, + }, + { + "operator": "<=", + "value": 86399999913601, + "baserow_filter_type": "lower_than_or_equal", + "baserow_skip": True, + }, + { + "operator": ">=", + "value": 86399999913601, + "baserow_filter_type": "higher_than_or_equal", + "baserow_skip": True, + }, + { + "operator": "isEmpty", + "value": None, + "baserow_filter_type": "empty", + "baserow_value": "", + }, + { + "operator": "isNotEmpty", + "value": None, + "baserow_filter_type": "not_empty", + "baserow_value": "", + }, + ], + "rating": [ + { + "operator": "=", + "value": 1, + "baserow_filter_type": "equal", + "baserow_value": "1", + }, + { + "operator": "!=", + "value": 1, + "baserow_filter_type": "not_equal", + "baserow_value": "1", + }, + { + "operator": "<", + "value": 1, + "baserow_filter_type": "lower_than", + "baserow_value": "1", + }, + { + "operator": ">", + "value": 1, + "baserow_filter_type": "higher_than", + "baserow_value": "1", + }, + { + "operator": "<=", + "value": 1, + "baserow_filter_type": "lower_than_or_equal", + "baserow_value": "1", + }, + { + "operator": ">=", + "value": 1, + "baserow_filter_type": "higher_than_or_equal", + "baserow_value": "1", + }, + { + "operator": "isEmpty", + "value": None, + "baserow_filter_type": "empty", + "baserow_value": "", + }, + { + "operator": "isNotEmpty", + "value": None, + "baserow_filter_type": "not_empty", + "baserow_value": "", + }, + ], + "autoNumber": [ + { + "operator": "=", + "value": 1, + "baserow_filter_type": "equal", + "baserow_value": "1", + }, + { + "operator": "!=", + "value": 1, + "baserow_filter_type": "not_equal", + "baserow_value": "1", + }, + { + "operator": "<", + "value": 1, + "baserow_filter_type": "lower_than", + "baserow_value": "1", + }, + { + "operator": ">", + "value": 1, + "baserow_filter_type": "higher_than", + "baserow_value": "1", + }, + { + "operator": "<=", + "value": 1, + "baserow_filter_type": "lower_than_or_equal", + "baserow_value": "1", + }, + { + "operator": ">=", + "value": 1, + "baserow_filter_type": "higher_than_or_equal", + "baserow_value": "1", + }, + { + "operator": "isEmpty", + "value": None, + "baserow_filter_type": "empty", + "baserow_value": "", + }, + { + "operator": "isNotEmpty", + "value": None, + "baserow_filter_type": "not_empty", + "baserow_value": "", + }, + ], + "foreignKey": [ + { + "operator": "|", + "value": ["rect9vRzdJvCLrRg9"], + "baserow_skip": True, + }, + { + "operator": "&", + "value": ["rect9vRzdJvCLrRg9"], + "baserow_skip": True, + }, + { + "operator": "=", + "value": ["rect9vRzdJvCLrRg9"], + "baserow_filter_type": "link_row_has", + "baserow_value": "2", + }, + { + "operator": "=", + "value": ["not_existing_id"], + "baserow_filter_type": "link_row_has", + "baserow_value": "", + }, + { + "operator": "=", + "value": ["rect9vRzdJvCLrRg9", "rect9vRzdJvCLrRg8"], + "baserow_skip": True, + }, + { + "operator": "isNoneOf", + "value": ["rect9vRzdJvCLrRg9"], + "baserow_skip": True, + }, + { + "operator": "contains", + "value": "1", + "baserow_filter_type": "link_row_contains", + "baserow_value": "1", + }, + { + "operator": "doesNotContain", + "value": "1", + "baserow_filter_type": "link_row_not_contains", + "baserow_value": "1", + }, + { + "operator": "isEmpty", + "value": None, + "baserow_filter_type": "empty", + "baserow_value": "", + }, + { + "operator": "isNotEmpty", + "value": None, + "baserow_filter_type": "not_empty", + "baserow_value": "", + }, + ], +} + + +def test_if_all_airtable_filter_operators_are_in_tests(): + all_filter_operators_in_tests = { + airtable_filter["operator"] + for airtable_column_type, airtable_filters in ALL_AIRTABLE_FILTERS_PER_TYPE.items() + for airtable_filter in airtable_filters + } + + for filter_operator in airtable_filter_operator_registry.get_all(): + assert filter_operator.type in all_filter_operators_in_tests, ( + f"{filter_operator.type} must be included in the " + f"`test_if_all_airtable_filter_operators_are_in_tests` test" + ) + + +def test_all_airtable_filters(): + for airtable_column_type, airtable_filters in ALL_AIRTABLE_FILTERS_PER_TYPE.items(): + airtable_column = AIRTABLE_COLUMN_PER_TYPE[airtable_column_type] + for airtable_filter in airtable_filters: + has_baserow_skip = "baserow_skip" in airtable_filter + has_baserow_filter = ( + "baserow_filter_type" in airtable_filter + and "baserow_value" in airtable_filter + ) + + if not has_baserow_skip and not has_baserow_filter: + assert False, f"No baserow_ property in {airtable_filter}" + + import_report = AirtableImportReport() + airtable_table = deepcopy(AIRTABLE_TABLE) + airtable_table["primaryColumnId"] = airtable_column["id"] + airtable_table["columns"].append(airtable_column) + airtable_filter = deepcopy(airtable_filter) + airtable_filter["id"] = "flt1234" + airtable_filter["columnId"] = airtable_column["id"] + + ( + baserow_field, + airtable_column_type, + ) = airtable_column_type_registry.from_airtable_column_to_serialized( + {}, + airtable_column, + AirtableImportConfig(), + AirtableImportReport(), + ) + + filter_operator = airtable_filter_operator_registry.get( + airtable_filter["operator"] + ) + args = ( + ROW_ID_MAPPING, + airtable_table, + airtable_column, + baserow_field, + import_report, + airtable_filter["value"], + ) + + if has_baserow_skip: + with pytest.raises(AirtableSkipFilter): + try: + filter_operator.to_baserow_filter_and_value(*args) + except NotImplementedError: + assert False, ( + f"not implemented {json.dumps(airtable_filter, indent=4)}" + f"{json.dumps(airtable_column, indent=4)}" + ) + + if has_baserow_filter: + try: + filter_type, value = filter_operator.to_baserow_filter_and_value( + *args + ) + except NotImplementedError: + assert False, ( + f"not implemented {json.dumps(airtable_filter, indent=4)}" + f"{json.dumps(airtable_column, indent=4)}" + ) + + except AirtableSkipFilter: + assert False, ( + f"unexpected skip filter" + f" {json.dumps(airtable_filter, indent=4)}" + f"{json.dumps(airtable_column, indent=4)}" + ) + assert filter_type.type == airtable_filter["baserow_filter_type"], ( + f"filter type mismatch {json.dumps(airtable_filter, indent=4)}" + f"{json.dumps(airtable_column, indent=4)}" + ) + assert value == airtable_filter["baserow_value"], ( + f"value mismatch {json.dumps(airtable_filter, indent=4)}" + f"{json.dumps(airtable_column, indent=4)}" + ) diff --git a/backend/tests/baserow/contrib/database/airtable/test_airtable_handler.py b/backend/tests/baserow/contrib/database/airtable/test_airtable_handler.py index 1514cd9d6..85bd0b2ae 100644 --- a/backend/tests/baserow/contrib/database/airtable/test_airtable_handler.py +++ b/backend/tests/baserow/contrib/database/airtable/test_airtable_handler.py @@ -1,6 +1,5 @@ import json import os -from copy import deepcopy from pathlib import Path from unittest.mock import patch from zipfile import ZIP_DEFLATED, ZipFile @@ -33,12 +32,12 @@ def test_fetch_publicly_shared_base(): ) path = os.path.join(base_path, "airtable_base.html") - with open(path, "rb") as file: + with open(path, "rb") as file_handler: responses.add( responses.GET, "https://airtable.com/appZkaH3aWX3ZjT3b", status=200, - body=file, + body=file_handler, headers={"Set-Cookie": "brw=test;"}, ) @@ -76,12 +75,12 @@ def test_fetch_table(): application_response_path = os.path.join(base_path, "airtable_application.json") table_response_path = os.path.join(base_path, "airtable_table.json") - with open(path, "rb") as file: + with open(path, "rb") as file_handler: responses.add( responses.GET, "https://airtable.com/appZkaH3aWX3ZjT3b", status=200, - body=file, + body=file_handler, headers={"Set-Cookie": "brw=test;"}, ) request_id, init_data, cookies = AirtableHandler.fetch_publicly_shared_base( @@ -162,49 +161,83 @@ def test_to_baserow_database_export(): base_path = os.path.join( settings.BASE_DIR, "../../../tests/airtable_responses/basic" ) - path = os.path.join(base_path, "airtable_base.html") - user_table_path = os.path.join(base_path, "airtable_application.json") - data_table_path = os.path.join(base_path, "airtable_table.json") - user_table_json = json.loads(Path(user_table_path).read_text()) - data_table_json = json.loads(Path(data_table_path).read_text()) - with open(os.path.join(base_path, "file-sample.txt"), "rb") as file: + with open(os.path.join(base_path, "file-sample.txt"), "rb") as file_handler: responses.add( responses.GET, "https://dl.airtable.com/.signed/file-sample.txt", status=200, - body=file.read(), + body=file_handler.read(), ) - with open(os.path.join(base_path, "file-sample_500kB.doc"), "rb") as file: + with open(os.path.join(base_path, "file-sample_500kB.doc"), "rb") as file_handler: responses.add( responses.GET, "https://dl.airtable.com/.attachments/e93dc201ce27080d9ad9df5775527d09/93e85b28/file-sample_500kB.doc", status=200, - body=file.read(), + body=file_handler.read(), ) - with open(os.path.join(base_path, "file_example_JPG_100kB.jpg"), "rb") as file: + with open( + os.path.join(base_path, "file_example_JPG_100kB.jpg"), "rb" + ) as file_handler: responses.add( responses.GET, "https://dl.airtable.com/.attachments/025730a04991a764bb3ace6d524b45e5/bd61798a/file_example_JPG_100kB.jpg", status=200, - body=file.read(), + body=file_handler.read(), ) - with open(path, "rb") as file: + with open(os.path.join(base_path, "airtable_base.html"), "rb") as file_handler: responses.add( responses.GET, "https://airtable.com/appZkaH3aWX3ZjT3b", status=200, - body=file.read(), + body=file_handler.read(), headers={"Set-Cookie": "brw=test;"}, ) - request_id, init_data, cookies = AirtableHandler.fetch_publicly_shared_base( - "appZkaH3aWX3ZjT3b" + + with open( + os.path.join(base_path, "airtable_application.json"), "rb" + ) as file_handler: + responses.add( + responses.GET, + "https://airtable.com/v0.3/application/appZkaH3aWX3ZjT3b/read", + status=200, + body=file_handler.read(), ) - schema, tables = AirtableHandler.extract_schema([user_table_json, data_table_json]) + with open(os.path.join(base_path, "airtable_table.json"), "rb") as file_handler: + responses.add( + responses.GET, + "https://airtable.com/v0.3/table/tbl7glLIGtH8C8zGCzb/readData", + status=200, + body=file_handler.read(), + ) + + with open( + os.path.join(base_path, "airtable_view_viwDgBCKTEdCQoHTQKH.json"), "rb" + ) as file_handler: + responses.add( + responses.GET, + "https://airtable.com/v0.3/view/viwDgBCKTEdCQoHTQKH/readData", + status=200, + body=file_handler.read(), + ) + + with open( + os.path.join(base_path, "airtable_view_viwBAGnUgZ6X5Eyg5Wf.json"), "rb" + ) as file_handler: + responses.add( + responses.GET, + "https://airtable.com/v0.3/view/viwBAGnUgZ6X5Eyg5Wf/readData", + status=200, + body=file_handler.read(), + ) + + init_data, schema, tables = AirtableHandler.fetch_and_combine_airtable_data( + "appZkaH3aWX3ZjT3b" + ) baserow_database_export, files_buffer = AirtableHandler.to_baserow_database_export( init_data, schema, tables, AirtableImportConfig() ) @@ -232,7 +265,7 @@ def test_to_baserow_database_export(): assert baserow_database_export["tables"][1]["id"] == "tbl7glLIGtH8C8zGCzb" assert baserow_database_export["tables"][1]["name"] == "Data" assert baserow_database_export["tables"][1]["order"] == 1 - assert len(baserow_database_export["tables"][1]["fields"]) == 25 + assert len(baserow_database_export["tables"][1]["fields"]) == 26 # We don't have to check all the fields and rows, just a single one, because we have # separate tests for mapping the Airtable fields and values to Baserow. @@ -255,7 +288,7 @@ def test_to_baserow_database_export(): "type": "email", "id": "fldB7wkyR0buF1sRF9O", "name": "Email", - "description": None, + "description": "This is an email", "order": 1, "primary": False, "read_only": False, @@ -295,11 +328,11 @@ def test_to_baserow_database_export(): ) assert baserow_database_export["tables"][0]["views"] == [ { - "id": 1, + "id": "viwFSKLuVm97DnNVD91", "type": "grid", - "name": "Grid", + "name": "All", "order": 1, - "row_identifier_type": "id", + "row_identifier_type": "count", "row_height_size": "small", "filter_type": "AND", "filters_disabled": False, @@ -310,7 +343,44 @@ def test_to_baserow_database_export(): "group_bys": [], "ownership_type": "collaborative", "public": False, - "field_options": [], + "field_options": [ + { + "aggregation_raw_type": "", + "aggregation_type": "", + "field_id": "fldG9y88Zw7q7u4Z7i4", + "hidden": False, + "id": "viwFSKLuVm97DnNVD91_columnOrder_0", + "order": 1, + "width": 200, + }, + { + "aggregation_raw_type": "", + "aggregation_type": "", + "field_id": "fldB7wkyR0buF1sRF9O", + "hidden": False, + "id": "viwFSKLuVm97DnNVD91_columnOrder_1", + "order": 2, + "width": 200, + }, + { + "aggregation_raw_type": "", + "aggregation_type": "", + "field_id": "fldFh5wIL430N62LN6t", + "hidden": False, + "id": "viwFSKLuVm97DnNVD91_columnOrder_2", + "order": 3, + "width": 200, + }, + { + "aggregation_raw_type": "", + "aggregation_type": "", + "field_id": "fldZBmr4L45mhjILhlA", + "hidden": False, + "id": "viwFSKLuVm97DnNVD91_columnOrder_3", + "order": 4, + "width": 200, + }, + ], "owned_by": None, } ] @@ -320,17 +390,6 @@ def test_to_baserow_database_export(): "order": "1.00000000000000000000", "created_on": None, "updated_on": None, - "field_object_name": "All", - "field_scope": "scope_view", - "field_table": "table_Users", - "field_error_type": "error_type_unsupported_feature", - "field_message": 'View "All" was not imported because views are not yet supported during import.', - } - assert baserow_database_export["tables"][2]["rows"][1] == { - "id": 2, - "order": "2.00000000000000000000", - "created_on": None, - "updated_on": None, "field_object_name": "Name lookup (from Users)", "field_scope": "scope_field", "field_table": "table_Data", @@ -341,53 +400,87 @@ def test_to_baserow_database_export(): @pytest.mark.django_db @responses.activate -def test_config_skip_files(): +def test_config_skip_files(tmpdir, data_fixture): base_path = os.path.join( settings.BASE_DIR, "../../../tests/airtable_responses/basic" ) - path = os.path.join(base_path, "airtable_base.html") - user_table_path = os.path.join(base_path, "airtable_application.json") - data_table_path = os.path.join(base_path, "airtable_table.json") - user_table_json = json.loads(Path(user_table_path).read_text()) - data_table_json = json.loads(Path(data_table_path).read_text()) - with open(os.path.join(base_path, "file-sample.txt"), "rb") as file: + with open(os.path.join(base_path, "file-sample.txt"), "rb") as file_handler: responses.add( responses.GET, "https://dl.airtable.com/.signed/file-sample.txt", status=200, - body=file.read(), + body=file_handler.read(), ) - with open(os.path.join(base_path, "file-sample_500kB.doc"), "rb") as file: + with open(os.path.join(base_path, "file-sample_500kB.doc"), "rb") as file_handler: responses.add( responses.GET, "https://dl.airtable.com/.attachments/e93dc201ce27080d9ad9df5775527d09/93e85b28/file-sample_500kB.doc", status=200, - body=file.read(), + body=file_handler.read(), ) - with open(os.path.join(base_path, "file_example_JPG_100kB.jpg"), "rb") as file: + with open( + os.path.join(base_path, "file_example_JPG_100kB.jpg"), "rb" + ) as file_handler: responses.add( responses.GET, "https://dl.airtable.com/.attachments/025730a04991a764bb3ace6d524b45e5/bd61798a/file_example_JPG_100kB.jpg", status=200, - body=file.read(), + body=file_handler.read(), ) - with open(path, "rb") as file: + with open(os.path.join(base_path, "airtable_base.html"), "rb") as file_handler: responses.add( responses.GET, "https://airtable.com/appZkaH3aWX3ZjT3b", status=200, - body=file.read(), + body=file_handler.read(), headers={"Set-Cookie": "brw=test;"}, ) - request_id, init_data, cookies = AirtableHandler.fetch_publicly_shared_base( - "appZkaH3aWX3ZjT3b" + + with open( + os.path.join(base_path, "airtable_application.json"), "rb" + ) as file_handler: + responses.add( + responses.GET, + "https://airtable.com/v0.3/application/appZkaH3aWX3ZjT3b/read", + status=200, + body=file_handler.read(), ) - schema, tables = AirtableHandler.extract_schema([user_table_json, data_table_json]) + with open(os.path.join(base_path, "airtable_table.json"), "rb") as file_handler: + responses.add( + responses.GET, + "https://airtable.com/v0.3/table/tbl7glLIGtH8C8zGCzb/readData", + status=200, + body=file_handler.read(), + ) + + with open( + os.path.join(base_path, "airtable_view_viwDgBCKTEdCQoHTQKH.json"), "rb" + ) as file_handler: + responses.add( + responses.GET, + "https://airtable.com/v0.3/view/viwDgBCKTEdCQoHTQKH/readData", + status=200, + body=file_handler.read(), + ) + + with open( + os.path.join(base_path, "airtable_view_viwBAGnUgZ6X5Eyg5Wf.json"), "rb" + ) as file_handler: + responses.add( + responses.GET, + "https://airtable.com/v0.3/view/viwBAGnUgZ6X5Eyg5Wf/readData", + status=200, + body=file_handler.read(), + ) + + init_data, schema, tables = AirtableHandler.fetch_and_combine_airtable_data( + "appZkaH3aWX3ZjT3b" + ) baserow_database_export, files_buffer = AirtableHandler.to_baserow_database_export( init_data, schema, tables, AirtableImportConfig(skip_files=True) ) @@ -402,44 +495,106 @@ def test_to_baserow_database_export_without_primary_value(): base_path = os.path.join( settings.BASE_DIR, "../../../tests/airtable_responses/basic" ) - path = os.path.join(base_path, "airtable_base.html") - user_table_path = os.path.join(base_path, "airtable_application.json") - user_table_json = json.loads(Path(user_table_path).read_text()) - # Remove the data table because we don't need that one. - del user_table_json["data"]["tableSchemas"][1] - user_table_json["data"]["tableDatas"][0]["rows"] = [] + with open(os.path.join(base_path, "file-sample.txt"), "rb") as file_handler: + responses.add( + responses.GET, + "https://dl.airtable.com/.signed/file-sample.txt", + status=200, + body=file_handler.read(), + ) - # Rename the primary column so that we depend on the fallback in the migrations. - user_table_json["data"]["tableSchemas"][0][ - "primaryColumnId" - ] = "fldG9y88Zw7q7u4Z7i4_unknown" + with open(os.path.join(base_path, "file-sample_500kB.doc"), "rb") as file_handler: + responses.add( + responses.GET, + "https://dl.airtable.com/.attachments/e93dc201ce27080d9ad9df5775527d09/93e85b28/file-sample_500kB.doc", + status=200, + body=file_handler.read(), + ) - with open(path, "rb") as file: + with open( + os.path.join(base_path, "file_example_JPG_100kB.jpg"), "rb" + ) as file_handler: + responses.add( + responses.GET, + "https://dl.airtable.com/.attachments/025730a04991a764bb3ace6d524b45e5/bd61798a/file_example_JPG_100kB.jpg", + status=200, + body=file_handler.read(), + ) + + with open(os.path.join(base_path, "airtable_base.html"), "rb") as file_handler: responses.add( responses.GET, "https://airtable.com/appZkaH3aWX3ZjT3b", status=200, - body=file.read(), + body=file_handler.read(), headers={"Set-Cookie": "brw=test;"}, ) - request_id, init_data, cookies = AirtableHandler.fetch_publicly_shared_base( - "appZkaH3aWX3ZjT3b" + + with open( + os.path.join(base_path, "airtable_application.json"), "rb" + ) as file_handler: + responses.add( + responses.GET, + "https://airtable.com/v0.3/application/appZkaH3aWX3ZjT3b/read", + status=200, + body=file_handler.read(), ) - schema, tables = AirtableHandler.extract_schema(deepcopy([user_table_json])) + with open(os.path.join(base_path, "airtable_table.json"), "rb") as file_handler: + responses.add( + responses.GET, + "https://airtable.com/v0.3/table/tbl7glLIGtH8C8zGCzb/readData", + status=200, + body=file_handler.read(), + ) + + with open( + os.path.join(base_path, "airtable_view_viwDgBCKTEdCQoHTQKH.json"), "rb" + ) as file_handler: + responses.add( + responses.GET, + "https://airtable.com/v0.3/view/viwDgBCKTEdCQoHTQKH/readData", + status=200, + body=file_handler.read(), + ) + + with open( + os.path.join(base_path, "airtable_view_viwBAGnUgZ6X5Eyg5Wf.json"), "rb" + ) as file_handler: + responses.add( + responses.GET, + "https://airtable.com/v0.3/view/viwBAGnUgZ6X5Eyg5Wf/readData", + status=200, + body=file_handler.read(), + ) + + init_data, schema, tables = AirtableHandler.fetch_and_combine_airtable_data( + "appZkaH3aWX3ZjT3b" + ) + + # Rename the primary column so that we depend on the fallback in the migrations. + schema["tableSchemas"][0]["primaryColumnId"] = "fldG9y88Zw7q7u4Z7i4_unknown" + baserow_database_export, files_buffer = AirtableHandler.to_baserow_database_export( - init_data, - schema, - tables, - AirtableImportConfig(), + init_data, schema, tables, AirtableImportConfig(skip_files=True) ) assert baserow_database_export["tables"][0]["fields"][0]["primary"] is True + assert baserow_database_export["tables"][2]["rows"][0] == { + "id": 1, + "order": "1.00000000000000000000", + "created_on": None, + "updated_on": None, + "field_object_name": "Name", + "field_scope": "scope_field", + "field_table": "table_Users", + "field_error_type": "error_type_unsupported_feature", + "field_message": 'Changed primary field to "Name" because the original primary field is incompatible.', + } - user_table_json["data"]["tableSchemas"][0]["columns"] = [] - schema, tables = AirtableHandler.extract_schema(deepcopy([user_table_json])) + schema["tableSchemas"][0]["columns"] = [] baserow_database_export, files_buffer = AirtableHandler.to_baserow_database_export( - init_data, schema, tables, AirtableImportConfig() + init_data, schema, tables, AirtableImportConfig(skip_files=True) ) assert baserow_database_export["tables"][0]["fields"] == [ { @@ -455,6 +610,17 @@ def test_to_baserow_database_export_without_primary_value(): "immutable_properties": False, } ] + assert baserow_database_export["tables"][2]["rows"][0] == { + "id": 1, + "order": "1.00000000000000000000", + "created_on": None, + "updated_on": None, + "field_object_name": "Primary field (auto created)", + "field_scope": "scope_field", + "field_table": "table_Users", + "field_error_type": "error_type_unsupported_feature", + "field_message": 'Created new primary field "Primary field (auto created)" because none of the provided fields are compatible.', + } @pytest.mark.django_db @@ -468,53 +634,77 @@ def test_import_from_airtable_to_workspace( ) storage = FileSystemStorage(location=(str(tmpdir)), base_url="http://localhost") - with open(os.path.join(base_path, "file-sample.txt"), "rb") as file: + with open(os.path.join(base_path, "file-sample.txt"), "rb") as file_handler: responses.add( responses.GET, "https://dl.airtable.com/.signed/file-sample.txt", status=200, - body=file.read(), + body=file_handler.read(), ) - with open(os.path.join(base_path, "file-sample_500kB.doc"), "rb") as file: + with open(os.path.join(base_path, "file-sample_500kB.doc"), "rb") as file_handler: responses.add( responses.GET, "https://dl.airtable.com/.attachments/e93dc201ce27080d9ad9df5775527d09/93e85b28/file-sample_500kB.doc", status=200, - body=file.read(), + body=file_handler.read(), ) - with open(os.path.join(base_path, "file_example_JPG_100kB.jpg"), "rb") as file: + with open( + os.path.join(base_path, "file_example_JPG_100kB.jpg"), "rb" + ) as file_handler: responses.add( responses.GET, "https://dl.airtable.com/.attachments/025730a04991a764bb3ace6d524b45e5/bd61798a/file_example_JPG_100kB.jpg", status=200, - body=file.read(), + body=file_handler.read(), ) - with open(os.path.join(base_path, "airtable_base.html"), "rb") as file: + with open(os.path.join(base_path, "airtable_base.html"), "rb") as file_handler: responses.add( responses.GET, "https://airtable.com/appZkaH3aWX3ZjT3b", status=200, - body=file.read(), + body=file_handler.read(), headers={"Set-Cookie": "brw=test;"}, ) - with open(os.path.join(base_path, "airtable_application.json"), "rb") as file: + with open( + os.path.join(base_path, "airtable_application.json"), "rb" + ) as file_handler: responses.add( responses.GET, "https://airtable.com/v0.3/application/appZkaH3aWX3ZjT3b/read", status=200, - body=file.read(), + body=file_handler.read(), ) - with open(os.path.join(base_path, "airtable_table.json"), "rb") as file: + with open(os.path.join(base_path, "airtable_table.json"), "rb") as file_handler: responses.add( responses.GET, "https://airtable.com/v0.3/table/tbl7glLIGtH8C8zGCzb/readData", status=200, - body=file.read(), + body=file_handler.read(), + ) + + with open( + os.path.join(base_path, "airtable_view_viwDgBCKTEdCQoHTQKH.json"), "rb" + ) as file_handler: + responses.add( + responses.GET, + "https://airtable.com/v0.3/view/viwDgBCKTEdCQoHTQKH/readData", + status=200, + body=file_handler.read(), + ) + + with open( + os.path.join(base_path, "airtable_view_viwBAGnUgZ6X5Eyg5Wf.json"), "rb" + ) as file_handler: + responses.add( + responses.GET, + "https://airtable.com/v0.3/view/viwBAGnUgZ6X5Eyg5Wf/readData", + status=200, + body=file_handler.read(), ) progress = Progress(1000) @@ -540,6 +730,16 @@ def test_import_from_airtable_to_workspace( assert all_tables[1].name == "Data" assert all_tables[2].name == "Airtable import report" + table_0_views = all_tables[0].view_set.all() + assert table_0_views[0].name == "All" + table_1_views = all_tables[1].view_set.all() + assert table_1_views[0].name == "Grid view" + assert table_1_views[1].name == "With filters and sorts" + table_1_view_1_sorts = table_1_views[1].viewsort_set.all() + assert len(table_1_view_1_sorts) == 2 + table_1_view_1_group_bys = table_1_views[1].viewgroupby_set.all() + assert len(table_1_view_1_group_bys) == 1 + user_fields = all_tables[0].field_set.all() assert len(user_fields) == 4 @@ -570,53 +770,77 @@ def test_import_from_airtable_to_workspace_with_report_table(data_fixture, tmpdi ) storage = FileSystemStorage(location=(str(tmpdir)), base_url="http://localhost") - with open(os.path.join(base_path, "file-sample.txt"), "rb") as file: + with open(os.path.join(base_path, "file-sample.txt"), "rb") as file_handler: responses.add( responses.GET, "https://dl.airtable.com/.signed/file-sample.txt", status=200, - body=file.read(), + body=file_handler.read(), ) - with open(os.path.join(base_path, "file-sample_500kB.doc"), "rb") as file: + with open(os.path.join(base_path, "file-sample_500kB.doc"), "rb") as file_handler: responses.add( responses.GET, "https://dl.airtable.com/.attachments/e93dc201ce27080d9ad9df5775527d09/93e85b28/file-sample_500kB.doc", status=200, - body=file.read(), + body=file_handler.read(), ) - with open(os.path.join(base_path, "file_example_JPG_100kB.jpg"), "rb") as file: + with open( + os.path.join(base_path, "file_example_JPG_100kB.jpg"), "rb" + ) as file_handler: responses.add( responses.GET, "https://dl.airtable.com/.attachments/025730a04991a764bb3ace6d524b45e5/bd61798a/file_example_JPG_100kB.jpg", status=200, - body=file.read(), + body=file_handler.read(), ) - with open(os.path.join(base_path, "airtable_base.html"), "rb") as file: + with open(os.path.join(base_path, "airtable_base.html"), "rb") as file_handler: responses.add( responses.GET, "https://airtable.com/appZkaH3aWX3ZjT3b", status=200, - body=file.read(), + body=file_handler.read(), headers={"Set-Cookie": "brw=test;"}, ) - with open(os.path.join(base_path, "airtable_application.json"), "rb") as file: + with open( + os.path.join(base_path, "airtable_application.json"), "rb" + ) as file_handler: responses.add( responses.GET, "https://airtable.com/v0.3/application/appZkaH3aWX3ZjT3b/read", status=200, - body=file.read(), + body=file_handler.read(), ) - with open(os.path.join(base_path, "airtable_table.json"), "rb") as file: + with open(os.path.join(base_path, "airtable_table.json"), "rb") as file_handler: responses.add( responses.GET, "https://airtable.com/v0.3/table/tbl7glLIGtH8C8zGCzb/readData", status=200, - body=file.read(), + body=file_handler.read(), + ) + + with open( + os.path.join(base_path, "airtable_view_viwDgBCKTEdCQoHTQKH.json"), "rb" + ) as file_handler: + responses.add( + responses.GET, + "https://airtable.com/v0.3/view/viwDgBCKTEdCQoHTQKH/readData", + status=200, + body=file_handler.read(), + ) + + with open( + os.path.join(base_path, "airtable_view_viwBAGnUgZ6X5Eyg5Wf.json"), "rb" + ) as file_handler: + responses.add( + responses.GET, + "https://airtable.com/v0.3/view/viwBAGnUgZ6X5Eyg5Wf/readData", + status=200, + body=file_handler.read(), ) progress = Progress(1000) @@ -651,21 +875,23 @@ def test_import_from_airtable_to_workspace_duplicated_single_select( ) storage = FileSystemStorage(location=(str(tmpdir)), base_url="http://localhost") - with open(os.path.join(base_path, "airtable_base.html"), "rb") as file: + with open(os.path.join(base_path, "airtable_base.html"), "rb") as file_handler: responses.add( responses.GET, "https://airtable.com/shra2B9gmVj6kxvNz", status=200, - body=file.read(), + body=file_handler.read(), headers={"Set-Cookie": "brw=test;"}, ) - with open(os.path.join(base_path, "airtable_application.json"), "rb") as file: + with open( + os.path.join(base_path, "airtable_application.json"), "rb" + ) as file_handler: responses.add( responses.GET, "https://airtable.com/v0.3/application/appHI27Un8BKJ9iKA/read", status=200, - body=file.read(), + body=file_handler.read(), ) progress = Progress(1000) @@ -704,21 +930,23 @@ def test_import_from_airtable_to_workspace_duplicated_multi_select( ) storage = FileSystemStorage(location=(str(tmpdir)), base_url="http://localhost") - with open(os.path.join(base_path, "airtable_base.html"), "rb") as file: + with open(os.path.join(base_path, "airtable_base.html"), "rb") as file_handler: responses.add( responses.GET, "https://airtable.com/shra2B9gmVj6kxvNz", status=200, - body=file.read(), + body=file_handler.read(), headers={"Set-Cookie": "brw=test;"}, ) - with open(os.path.join(base_path, "airtable_application.json"), "rb") as file: + with open( + os.path.join(base_path, "airtable_application.json"), "rb" + ) as file_handler: responses.add( responses.GET, "https://airtable.com/v0.3/application/appHI27Un8BKJ9iKA/read", status=200, - body=file.read(), + body=file_handler.read(), ) progress = Progress(1000) @@ -760,12 +988,12 @@ def test_import_unsupported_publicly_shared_view(data_fixture, tmpdir): ) storage = FileSystemStorage(location=(str(tmpdir)), base_url="http://localhost") - with open(os.path.join(base_path, "airtable_view.html"), "rb") as file: + with open(os.path.join(base_path, "airtable_view.html"), "rb") as file_handler: responses.add( responses.GET, "https://airtable.com/appZkaH3aWX3ZjT3b", status=200, - body=file.read(), + body=file_handler.read(), headers={"Set-Cookie": "brw=test;"}, ) diff --git a/backend/tests/baserow/contrib/database/airtable/test_airtable_utils.py b/backend/tests/baserow/contrib/database/airtable/test_airtable_utils.py index 0a2c4f3d0..dc81a9ef3 100644 --- a/backend/tests/baserow/contrib/database/airtable/test_airtable_utils.py +++ b/backend/tests/baserow/contrib/database/airtable/test_airtable_utils.py @@ -1,8 +1,12 @@ import pytest from baserow.contrib.database.airtable.utils import ( + airtable_date_filter_value_to_baserow, extract_share_id_from_url, + get_airtable_column_name, get_airtable_row_primary_value, + quill_to_markdown, + unknown_value_to_human_readable, ) @@ -61,3 +65,252 @@ def test_get_airtable_row_primary_value_without_primary_column_id_in_table(): } airtable_row = {"id": "id1"} assert get_airtable_row_primary_value(airtable_table, airtable_row) == "id1" + + +def test_get_airtable_column_name(): + table = { + "columns": [ + {"id": "fldwSc9PqedIhTSqhi1", "name": "Field 1", "type": "text"}, + {"id": "fldwSc9PqedIhTSqhi2", "name": "Field 2", "type": "text"}, + ], + } + assert get_airtable_column_name(table, "fldwSc9PqedIhTSqhi1") == "Field 1" + assert get_airtable_column_name(table, "fldwSc9PqedIhTSqhi2") == "Field 2" + + +def test_get_airtable_column_name_fallback(): + table = { + "columns": [ + {"id": "fldwSc9PqedIhTSqhi1", "name": "Field 1", "type": "text"}, + {"id": "fldwSc9PqedIhTSqhi2", "name": "Field 2", "type": "text"}, + ], + } + assert ( + get_airtable_column_name(table, "fldwSc9PqedIhTSqhi3") == "fldwSc9PqedIhTSqhi3" + ) + + +def test_quill_to_markdown_airtable_example(): + markdown_value = quill_to_markdown( + [ + {"insert": "He"}, + {"attributes": {"bold": True}, "insert": "adi"}, + {"insert": "ng 1"}, + {"attributes": {"header": 1}, "insert": "\n"}, + {"insert": "He"}, + {"attributes": {"link": "https://airtable.com"}, "insert": "a"}, + { + "attributes": {"link": "https://airtable.com", "bold": True}, + "insert": "di", + }, + {"attributes": {"bold": True}, "insert": "n"}, + {"insert": "g 2"}, + {"attributes": {"header": 2}, "insert": "\n"}, + {"insert": "Heading 3"}, + {"attributes": {"header": 3}, "insert": "\n"}, + {"insert": "\none"}, + {"attributes": {"list": "ordered"}, "insert": "\n"}, + {"insert": "two"}, + {"attributes": {"list": "ordered"}, "insert": "\n"}, + {"insert": "three"}, + {"attributes": {"list": "ordered"}, "insert": "\n"}, + {"insert": "Sub 1"}, + {"attributes": {"indent": 1, "list": "ordered"}, "insert": "\n"}, + {"insert": "Sub 2"}, + {"attributes": {"indent": 1, "list": "ordered"}, "insert": "\n"}, + {"insert": "\none"}, + {"attributes": {"list": "bullet"}, "insert": "\n"}, + {"insert": "two"}, + {"attributes": {"list": "bullet"}, "insert": "\n"}, + {"insert": "three"}, + {"attributes": {"list": "bullet"}, "insert": "\n"}, + {"insert": "Sub 1"}, + {"attributes": {"indent": 1, "list": "bullet"}, "insert": "\n"}, + {"insert": "Sub 2"}, + {"attributes": {"indent": 1, "list": "bullet"}, "insert": "\n"}, + {"insert": "\nCheck 1"}, + {"attributes": {"list": "unchecked"}, "insert": "\n"}, + {"insert": "Check 2"}, + {"attributes": {"list": "unchecked"}, "insert": "\n"}, + {"insert": "Check 3"}, + {"insert": "\n", "attributes": {"list": "unchecked"}}, + {"insert": "\nLorem "}, + {"insert": "ipsum", "attributes": {"bold": True}}, + {"insert": " dolor "}, + {"attributes": {"italic": True}, "insert": "sit"}, + {"insert": " amet, "}, + {"attributes": {"strike": True}, "insert": "consectetur"}, + {"insert": " adipiscing "}, + {"attributes": {"code": True}, "insert": "elit"}, + {"insert": ". "}, + {"attributes": {"link": "https://airtable.com"}, "insert": "Proin"}, + {"insert": " ut metus quam. Ut tempus at "}, + { + "attributes": {"link": "https://airtable.com"}, + "insert": "https://airtable.com", + }, + { + "insert": " vel varius. Phasellus nec diam vitae urna mollis cursus. Donec mattis pellentesque nunc id dictum. Maecenas vel tortor quam. Vestibulum et enim ut mauris lacinia malesuada. Pellentesque euismod\niaculis felis, at posuere velit ullamcorper a. Aliquam eu ultricies neque, cursus accumsan metus. Etiam consectetur eu nisi id aliquet. " + }, + { + "insert": { + "mention": { + "userId": "usrGIN77VWdhm7LKk", + "mentionId": "menuy6d9AwkWbnNXx", + } + } + }, + { + "insert": " gravida vestibulum egestas. Praesent pretium velit eu pretium ultrices. Nullam ut est non quam vulputate " + }, + {"attributes": {"code": True}, "insert": "tempus nec vel augue"}, + { + "insert": ". Aenean dui velit, ornare nec tincidunt eget, fermentum sed arcu. Suspendisse consequat bibendum molestie. Fusce at pulvinar enim.\n" + }, + { + "insert": { + "mention": { + "userId": "usrGIN77VWdhm7LKk", + "mentionId": "menflYNpEgIJljLuR", + } + } + }, + {"insert": "\nQuote, but not actually"}, + {"attributes": {"blockquote": True}, "insert": "\n"}, + {"insert": "on multiple lines"}, + {"attributes": {"blockquote": True}, "insert": "\n"}, + {"insert": "\ncode"}, + {"attributes": {"code-block": True}, "insert": "\n"}, + {"insert": "line"}, + {"attributes": {"code-block": True}, "insert": "\n"}, + {"insert": "2"}, + {"insert": "\n", "attributes": {"code-block": True}}, + {"insert": "\n{"}, + {"insert": "\n", "attributes": {"code-block": True}}, + {"insert": ' "test": "test",'}, + {"attributes": {"code-block": True}, "insert": "\n"}, + {"insert": ' "yeah": "test"'}, + {"attributes": {"code-block": True}, "insert": "\n"}, + {"insert": "}"}, + {"insert": "\n", "attributes": {"code-block": True}}, + ] + ) + assert ( + markdown_value + == """# He**adi**ng 1 +## He[a](https://airtable.com)[**di**](https://airtable.com)**n**g 2 +### Heading 3 + +1. one +1. two +1. three + 1. Sub 1 + 1. Sub 2 + +- one +- two +- three + - Sub 1 + - Sub 2 + +- [ ] Check 1 +- [ ] Check 2 +- [ ] Check 3 + +Lorem **ipsum** dolor _sit_ amet, ~consectetur~ adipiscing `elit`. [Proin](https://airtable.com) ut metus quam. Ut tempus at [https://airtable.com](https://airtable.com) vel varius. Phasellus nec diam vitae urna mollis cursus. Donec mattis pellentesque nunc id dictum. Maecenas vel tortor quam. Vestibulum et enim ut mauris lacinia malesuada. Pellentesque euismod +iaculis felis, at posuere velit ullamcorper a. Aliquam eu ultricies neque, cursus accumsan metus. Etiam consectetur eu nisi id aliquet. @usrGIN77VWdhm7LKk gravida vestibulum egestas. Praesent pretium velit eu pretium ultrices. Nullam ut est non quam vulputate `tempus nec vel augue`. Aenean dui velit, ornare nec tincidunt eget, fermentum sed arcu. Suspendisse consequat bibendum molestie. Fusce at pulvinar enim. +@usrGIN77VWdhm7LKk +> Quote, but not actually +> on multiple lines + +``` +code +line +2 +``` + +``` +{ + "test": "test", + "yeah": "test" +} +```""" + ) + + +def test_quill_to_markdown_airtable_example_two_lists(): + markdown_value = quill_to_markdown( + [ + {"insert": "This is great"}, + {"insert": "\n", "attributes": {"header": 2}}, + {"insert": "option 1"}, + {"attributes": {"list": "unchecked"}, "insert": "\n"}, + {"insert": "option 2"}, + {"attributes": {"list": "unchecked"}, "insert": "\n"}, + {"insert": "option that is "}, + {"attributes": {"bold": True}, "insert": "bold"}, + {"attributes": {"list": "unchecked"}, "insert": "\n"}, + {"insert": "\n"}, + {"attributes": {"bold": True}, "insert": "item"}, + {"attributes": {"list": "bullet"}, "insert": "\n"}, + {"attributes": {"italic": True}, "insert": "item"}, + {"attributes": {"list": "bullet"}, "insert": "\n"}, + {"attributes": {"strike": True}, "insert": "Item"}, + {"attributes": {"list": "bullet"}, "insert": "\n"}, + {"attributes": {"link": "https://airtable.com"}, "insert": "link"}, + {"insert": "\n", "attributes": {"list": "bullet"}}, + ] + ) + assert ( + markdown_value + == """## This is great +- [ ] option 1 +- [ ] option 2 +- [ ] option that is **bold** + +- **item** +- _item_ +- ~Item~ +- [link](https://airtable.com)""" + ) + + +def test_airtable_date_filter_value_to_baserow(): + assert ( + airtable_date_filter_value_to_baserow( + { + "mode": "exactDate", + "exactDate": "2025-02-05T00:00:00.000Z", + "timeZone": "Europe/Amsterdam", + "shouldUseCorrectTimeZoneForFormulaicColumn": True, + } + ) + == "Europe/Amsterdam?2025-02-05?exact_date" + ) + + +def test_airtable_date_string_filter_value_to_baserow(): + assert ( + airtable_date_filter_value_to_baserow("2025-02-05T00:00:00.000Z") + == "?2025-02-05?exact_date" + ) + + +def test_airtable_invalid_date_filter_value_to_baserow(): + with pytest.raises(KeyError): + assert airtable_date_filter_value_to_baserow( + { + "mode": "not_found", + "exactDate": "2025-02-05T00:00:00.000Z", + "timeZone": "Europe/Amsterdam", + "shouldUseCorrectTimeZoneForFormulaicColumn": True, + } + ) + + +def test_unknown_value_to_human_readable(): + assert unknown_value_to_human_readable(None) == "" + assert unknown_value_to_human_readable(["1", "2"]) == "2 items" + assert unknown_value_to_human_readable(["1"]) == "1 item" + assert unknown_value_to_human_readable("usrGUN1234") == "1 item" + assert unknown_value_to_human_readable("random") == "random" diff --git a/backend/tests/baserow/contrib/database/airtable/test_airtable_view_types.py b/backend/tests/baserow/contrib/database/airtable/test_airtable_view_types.py new file mode 100644 index 000000000..00b4d5ceb --- /dev/null +++ b/backend/tests/baserow/contrib/database/airtable/test_airtable_view_types.py @@ -0,0 +1,750 @@ +from copy import deepcopy + +from django.contrib.contenttypes.models import ContentType + +import pytest + +from baserow.contrib.database.airtable.config import AirtableImportConfig +from baserow.contrib.database.airtable.import_report import ( + SCOPE_VIEW_COLOR, + SCOPE_VIEW_GROUP_BY, + SCOPE_VIEW_SORT, + AirtableImportReport, +) +from baserow.contrib.database.airtable.registry import airtable_view_type_registry +from baserow.contrib.database.fields.field_types import TextFieldType +from baserow.contrib.database.fields.models import TextField + +RAW_AIRTABLE_VIEW = { + "id": "viwcpYeEpAs6kZspktV", + "name": "Grid view", + "type": "grid", + "personalForUserId": None, + "description": None, + "createdByUserId": "usrdGm7k7NIVWhK7W7L", +} +RAW_AIRTABLE_TABLE = { + "id": "tbl7glLIGtH8C8zGCzb", + "name": "Data", + "primaryColumnId": "fldwSc9PqedIhTSqhi1", + "columns": [ + {"id": "fldwSc9PqedIhTSqhi1", "name": "Single line text", "type": "text"}, + {"id": "fldwSc9PqedIhTSqhi2", "name": "Single line text", "type": "text"}, + ], + "meaningfulColumnOrder": [ + {"columnId": "fldwSc9PqedIhTSqhi1", "visibility": True}, + {"columnId": "fldwSc9PqedIhTSqhi2", "visibility": True}, + ], + "views": [RAW_AIRTABLE_VIEW], + "viewOrder": [RAW_AIRTABLE_VIEW["id"]], + "viewsById": { + RAW_AIRTABLE_VIEW["id"]: RAW_AIRTABLE_VIEW, + }, + "viewSectionsById": {}, + "schemaChecksum": "46f523a43433afe37d63e00d1a0f36c64310f06e4e0af2c32b6e99f26ab0e51a", +} +ROW_ID_MAPPING = {} +FIELD_MAPPING = { + "fldwSc9PqedIhTSqhi1": { + "baserow_field": TextField( + id="fldwSc9PqedIhTSqhi1", pk="fldwSc9PqedIhTSqhi1", name="Single line text" + ), + "baserow_field_type": TextFieldType(), + "raw_airtable_column": RAW_AIRTABLE_TABLE["columns"][0], + "airtable_column_type": None, + }, + "fldwSc9PqedIhTSqhi2": { + "baserow_field": TextField( + id="fldwSc9PqedIhTSqhi2", pk="fldwSc9PqedIhTSqhi2", name="Single line text" + ), + "baserow_field_type": TextFieldType(), + "raw_airtable_column": RAW_AIRTABLE_TABLE["columns"][1], + "airtable_column_type": None, + }, +} +RAW_AIRTABLE_VIEW_DATA = { + "id": "viwcpYeEpAs6kZspktV", + "frozenColumnCount": 1, + "columnOrder": [ + {"columnId": "fldwSc9PqedIhTSqhi1", "visibility": True, "width": 172}, + {"columnId": "fldwSc9PqedIhTSqhi2", "visibility": True}, + ], + "filters": None, + "lastSortsApplied": None, + "groupLevels": None, + "colorConfig": None, + "sharesById": {}, + "metadata": {"grid": {"rowHeight": "medium"}}, + "description": None, + "createdByUserId": "usrdGm7k7NIVWhK7W7L", + "applicationTransactionNumber": 284, + "rowOrder": [ + {"rowId": "recAAA5JwFXBk4swkfB", "visibility": True}, + {"rowId": "rec9Imz1INvNXgRIXn1", "visibility": True}, + {"rowId": "recyANUudYjDqIXdq9Z", "visibility": True}, + {"rowId": "rec2O9BdjKJO6dgj6QF", "visibility": True}, + ], +} +RAW_VIEW_DATA_FILTERS = { + "filterSet": [ + { + "id": "fltp2gabc8P91234f", + "columnId": "fldwSc9PqedIhTSqhi1", + "operator": "isNotEmpty", + "value": None, + }, + { + "id": "flthuYL0uubbDF2Xy", + "type": "nested", + "conjunction": "and", + "filterSet": [ + { + "id": "flt70g1l245672xRi", + "columnId": "fldwSc9PqedIhTSqhi1", + "operator": "!=", + "value": "test", + }, + { + "id": "fltVg238719fbIKqC", + "columnId": "fldwSc9PqedIhTSqhi2", + "operator": "!=", + "value": "test2", + }, + ], + }, + ], + "conjunction": "or", +} +RAW_VIEW_DATA_SORTS = { + "sortSet": [ + { + "id": "srtglUy98ghs5ou8D", + "columnId": "fldwSc9PqedIhTSqhi1", + "ascending": True, + } + ], + "shouldAutoSort": True, + "appliedTime": "2025-02-18T19:16:10.999Z", +} +RAW_VIEW_DATA_GROUPS = [ + { + "id": "glvvqP2okySUA2345", + "columnId": "fldwSc9PqedIhTSqhi1", + "order": "ascending", + "emptyGroupState": "hidden", + } +] +RAW_VIEW_COLOR_CONFIG_SELECT_COLUMN = { + "type": "selectColumn", + "selectColumnId": "fldwSc9PqedIhTSqhi1", + "colorDefinitions": None, + "defaultColor": None, +} +RAW_VIEW_COLOR_CONFIG_COLOR_DEFINITIONS = { + "type": "colorDefinitions", + "colorDefinitions": [ + { + "filterSet": [ + { + "id": "fltp2gabc8P91234f", + "columnId": "fldwSc9PqedIhTSqhi1", + "operator": "isNotEmpty", + "value": None, + }, + { + "id": "flthuYL0uubbDF2Xy", + "type": "nested", + "conjunction": "and", + "filterSet": [ + { + "id": "flt70g1l245672xRi", + "columnId": "fldwSc9PqedIhTSqhi1", + "operator": "!=", + "value": "test", + }, + { + "id": "fltVg238719fbIKqC", + "columnId": "fldwSc9PqedIhTSqhi2", + "operator": "!=", + "value": "test2", + }, + { + "id": "flthuYL0uubbDF2Xz", + "type": "nested", + "conjunction": "or", + "filterSet": [ + { + "id": "flt70g1l245672xRi", + "columnId": "fldwSc9PqedIhTSqhi1", + "operator": "!=", + "value": "test", + }, + ], + }, + ], + }, + ], + "conjunction": "or", + "color": "yellow", + } + ], + "defaultColor": "teal", +} + + +def test_import_grid_view(): + airtable_view_type = airtable_view_type_registry.get("grid") + serialized_view = airtable_view_type.to_serialized_baserow_view( + FIELD_MAPPING, + ROW_ID_MAPPING, + RAW_AIRTABLE_TABLE, + RAW_AIRTABLE_VIEW, + RAW_AIRTABLE_VIEW_DATA, + AirtableImportConfig(), + AirtableImportReport(), + ) + + assert serialized_view == { + "decorations": [], + "field_options": [ + { + "id": "viwcpYeEpAs6kZspktV_columnOrder_0", + "field_id": "fldwSc9PqedIhTSqhi1", + "width": 172, + "hidden": False, + "order": 1, + "aggregation_type": "", + "aggregation_raw_type": "", + }, + { + "id": "viwcpYeEpAs6kZspktV_columnOrder_1", + "field_id": "fldwSc9PqedIhTSqhi2", + "width": 200, + "hidden": False, + "order": 2, + "aggregation_type": "", + "aggregation_raw_type": "", + }, + ], + "filter_groups": [], + "filter_type": "AND", + "filters": [], + "filters_disabled": False, + "group_bys": [], + "id": "viwcpYeEpAs6kZspktV", + "name": "Grid view", + "order": 1, + "owned_by": None, + "ownership_type": "collaborative", + "public": False, + "row_height_size": "medium", + "row_identifier_type": "count", + "sortings": [], + "type": "grid", + } + + +def test_import_grid_view_xlarge_row_height(): + view_data = deepcopy(RAW_AIRTABLE_VIEW_DATA) + view_data["metadata"]["grid"]["rowHeight"] = "xlarge" + + airtable_view_type = airtable_view_type_registry.get("grid") + serialized_view = airtable_view_type.to_serialized_baserow_view( + FIELD_MAPPING, + ROW_ID_MAPPING, + RAW_AIRTABLE_TABLE, + RAW_AIRTABLE_VIEW, + view_data, + AirtableImportConfig(), + AirtableImportReport(), + ) + + assert serialized_view["row_height_size"] == "large" + + +def test_import_grid_view_unknown_row_height(): + view_data = deepcopy(RAW_AIRTABLE_VIEW_DATA) + view_data["metadata"]["grid"]["rowHeight"] = "unknown" + + airtable_view_type = airtable_view_type_registry.get("grid") + serialized_view = airtable_view_type.to_serialized_baserow_view( + FIELD_MAPPING, + ROW_ID_MAPPING, + RAW_AIRTABLE_TABLE, + RAW_AIRTABLE_VIEW, + view_data, + AirtableImportConfig(), + AirtableImportReport(), + ) + + assert serialized_view["row_height_size"] == "small" + + +def test_import_grid_view_sorts(): + view_data = deepcopy(RAW_AIRTABLE_VIEW_DATA) + view_data["lastSortsApplied"] = RAW_VIEW_DATA_SORTS + airtable_view_type = airtable_view_type_registry.get("grid") + serialized_view = airtable_view_type.to_serialized_baserow_view( + FIELD_MAPPING, + ROW_ID_MAPPING, + RAW_AIRTABLE_TABLE, + RAW_AIRTABLE_VIEW, + view_data, + AirtableImportConfig(), + AirtableImportReport(), + ) + assert serialized_view["sortings"] == [ + {"id": "srtglUy98ghs5ou8D", "field_id": "fldwSc9PqedIhTSqhi1", "order": "ASC"} + ] + + view_data["lastSortsApplied"]["sortSet"][0]["ascending"] = False + airtable_view_type = airtable_view_type_registry.get("grid") + serialized_view = airtable_view_type.to_serialized_baserow_view( + FIELD_MAPPING, + ROW_ID_MAPPING, + RAW_AIRTABLE_TABLE, + RAW_AIRTABLE_VIEW, + view_data, + AirtableImportConfig(), + AirtableImportReport(), + ) + assert serialized_view["sortings"] == [ + {"id": "srtglUy98ghs5ou8D", "field_id": "fldwSc9PqedIhTSqhi1", "order": "DESC"} + ] + + +def test_import_grid_view_sort_field_not_found(): + view_data = deepcopy(RAW_AIRTABLE_VIEW_DATA) + view_data["lastSortsApplied"] = RAW_VIEW_DATA_SORTS + airtable_view_type = airtable_view_type_registry.get("grid") + import_report = AirtableImportReport() + serialized_view = airtable_view_type.to_serialized_baserow_view( + {}, + ROW_ID_MAPPING, + RAW_AIRTABLE_TABLE, + RAW_AIRTABLE_VIEW, + view_data, + AirtableImportConfig(), + import_report, + ) + assert serialized_view["sortings"] == [] + assert len(import_report.items) == 1 + assert ( + import_report.items[0].object_name + == 'View "Grid view", Field ID "Single line text"' + ) + assert import_report.items[0].scope == SCOPE_VIEW_SORT + assert import_report.items[0].table == "Data" + + +def test_import_grid_view_sort_field_unsupported(): + view_data = deepcopy(RAW_AIRTABLE_VIEW_DATA) + field_mapping = deepcopy(FIELD_MAPPING) + field_mapping["fldwSc9PqedIhTSqhi1"]["baserow_field_type"]._can_order_by_types = [] + + view_data["lastSortsApplied"] = RAW_VIEW_DATA_SORTS + airtable_view_type = airtable_view_type_registry.get("grid") + import_report = AirtableImportReport() + serialized_view = airtable_view_type.to_serialized_baserow_view( + field_mapping, + ROW_ID_MAPPING, + RAW_AIRTABLE_TABLE, + RAW_AIRTABLE_VIEW, + view_data, + AirtableImportConfig(), + import_report, + ) + assert serialized_view["sortings"] == [] + assert len(import_report.items) == 1 + assert ( + import_report.items[0].object_name + == 'View "Grid view", Field "Single line text"' + ) + assert import_report.items[0].scope == SCOPE_VIEW_SORT + assert import_report.items[0].table == "Data" + + +def test_import_grid_view_group_bys(): + view_data = deepcopy(RAW_AIRTABLE_VIEW_DATA) + view_data["groupLevels"] = RAW_VIEW_DATA_GROUPS + airtable_view_type = airtable_view_type_registry.get("grid") + serialized_view = airtable_view_type.to_serialized_baserow_view( + FIELD_MAPPING, + ROW_ID_MAPPING, + RAW_AIRTABLE_TABLE, + RAW_AIRTABLE_VIEW, + view_data, + AirtableImportConfig(), + AirtableImportReport(), + ) + assert serialized_view["group_bys"] == [ + {"id": "glvvqP2okySUA2345", "field_id": "fldwSc9PqedIhTSqhi1", "order": "ASC"} + ] + + view_data["groupLevels"][0]["order"] = "descending" + airtable_view_type = airtable_view_type_registry.get("grid") + serialized_view = airtable_view_type.to_serialized_baserow_view( + FIELD_MAPPING, + ROW_ID_MAPPING, + RAW_AIRTABLE_TABLE, + RAW_AIRTABLE_VIEW, + view_data, + AirtableImportConfig(), + AirtableImportReport(), + ) + assert serialized_view["group_bys"] == [ + {"id": "glvvqP2okySUA2345", "field_id": "fldwSc9PqedIhTSqhi1", "order": "DESC"} + ] + + +def test_import_grid_view_group_by_field_not_found(): + view_data = deepcopy(RAW_AIRTABLE_VIEW_DATA) + view_data["groupLevels"] = RAW_VIEW_DATA_GROUPS + airtable_view_type = airtable_view_type_registry.get("grid") + import_report = AirtableImportReport() + serialized_view = airtable_view_type.to_serialized_baserow_view( + {}, + ROW_ID_MAPPING, + RAW_AIRTABLE_TABLE, + RAW_AIRTABLE_VIEW, + view_data, + AirtableImportConfig(), + import_report, + ) + assert serialized_view["group_bys"] == [] + assert len(import_report.items) == 1 + assert ( + import_report.items[0].object_name + == 'View "Grid view", Field ID "Single line text"' + ) + assert import_report.items[0].scope == SCOPE_VIEW_GROUP_BY + assert import_report.items[0].table == "Data" + + +def test_import_grid_view_group_by_field_unsupported(): + view_data = deepcopy(RAW_AIRTABLE_VIEW_DATA) + field_mapping = deepcopy(FIELD_MAPPING) + field_mapping["fldwSc9PqedIhTSqhi1"]["baserow_field_type"]._can_group_by = False + + view_data["groupLevels"] = RAW_VIEW_DATA_GROUPS + airtable_view_type = airtable_view_type_registry.get("grid") + import_report = AirtableImportReport() + serialized_view = airtable_view_type.to_serialized_baserow_view( + field_mapping, + ROW_ID_MAPPING, + RAW_AIRTABLE_TABLE, + RAW_AIRTABLE_VIEW, + view_data, + AirtableImportConfig(), + import_report, + ) + assert serialized_view["group_bys"] == [] + assert len(import_report.items) == 1 + assert ( + import_report.items[0].object_name + == 'View "Grid view", Field "Single line text"' + ) + assert import_report.items[0].scope == SCOPE_VIEW_GROUP_BY + assert import_report.items[0].table == "Data" + + +def test_import_grid_view_group_by_order_unsupported(): + view_data = deepcopy(RAW_AIRTABLE_VIEW_DATA) + field_mapping = deepcopy(FIELD_MAPPING) + view_data["groupLevels"] = RAW_VIEW_DATA_GROUPS + airtable_view_type = airtable_view_type_registry.get("grid") + + view_data["groupLevels"][0]["order"] = "UNKNOWN" + import_report = AirtableImportReport() + serialized_view = airtable_view_type.to_serialized_baserow_view( + field_mapping, + ROW_ID_MAPPING, + RAW_AIRTABLE_TABLE, + RAW_AIRTABLE_VIEW, + view_data, + AirtableImportConfig(), + import_report, + ) + assert serialized_view["group_bys"] == [] + assert len(import_report.items) == 1 + assert ( + import_report.items[0].object_name + == 'View "Grid view", Field "Single line text"' + ) + assert import_report.items[0].scope == SCOPE_VIEW_GROUP_BY + assert import_report.items[0].table == "Data" + + +def test_import_grid_view_field_order_and_visibility(): + view_data = deepcopy(RAW_AIRTABLE_VIEW_DATA) + field_mapping = deepcopy(FIELD_MAPPING) + airtable_view_type = airtable_view_type_registry.get("grid") + + import_report = AirtableImportReport() + serialized_view = airtable_view_type.to_serialized_baserow_view( + field_mapping, + ROW_ID_MAPPING, + RAW_AIRTABLE_TABLE, + RAW_AIRTABLE_VIEW, + view_data, + AirtableImportConfig(), + import_report, + ) + + assert serialized_view["field_options"] == [ + { + "id": "viwcpYeEpAs6kZspktV_columnOrder_0", + "field_id": "fldwSc9PqedIhTSqhi1", + "width": 172, + "hidden": False, + "order": 1, + "aggregation_type": "", + "aggregation_raw_type": "", + }, + { + "id": "viwcpYeEpAs6kZspktV_columnOrder_1", + "field_id": "fldwSc9PqedIhTSqhi2", + "width": 200, + "hidden": False, + "order": 2, + "aggregation_type": "", + "aggregation_raw_type": "", + }, + ] + + +@pytest.mark.django_db +def test_import_grid_view_filters_and_groups(): + view_data = deepcopy(RAW_AIRTABLE_VIEW_DATA) + field_mapping = deepcopy(FIELD_MAPPING) + for field_object in field_mapping.values(): + field_object["baserow_field"].content_type = ContentType.objects.get_for_model( + field_object["baserow_field"] + ) + + view_data["filters"] = RAW_VIEW_DATA_FILTERS + + airtable_view_type = airtable_view_type_registry.get("grid") + import_report = AirtableImportReport() + serialized_view = airtable_view_type.to_serialized_baserow_view( + field_mapping, + ROW_ID_MAPPING, + RAW_AIRTABLE_TABLE, + RAW_AIRTABLE_VIEW, + view_data, + AirtableImportConfig(), + import_report, + ) + + assert serialized_view["filter_type"] == "OR" + assert serialized_view["filters_disabled"] is False + + assert serialized_view["filters"] == [ + { + "id": "fltp2gabc8P91234f", + "field_id": "fldwSc9PqedIhTSqhi1", + "type": "not_empty", + "value": "", + "group": None, + }, + { + "id": "flt70g1l245672xRi", + "field_id": "fldwSc9PqedIhTSqhi1", + "type": "not_equal", + "value": "test", + "group": "flthuYL0uubbDF2Xy", + }, + { + "id": "fltVg238719fbIKqC", + "field_id": "fldwSc9PqedIhTSqhi2", + "type": "not_equal", + "value": "test2", + "group": "flthuYL0uubbDF2Xy", + }, + ] + assert serialized_view["filter_groups"] == [ + {"id": "flthuYL0uubbDF2Xy", "filter_type": "AND", "parent_group": None} + ] + + +@pytest.mark.django_db +def test_import_grid_view_empty_filters(): + view_data = deepcopy(RAW_AIRTABLE_VIEW_DATA) + field_mapping = deepcopy(FIELD_MAPPING) + for field_object in field_mapping.values(): + field_object["baserow_field"].content_type = ContentType.objects.get_for_model( + field_object["baserow_field"] + ) + + view_data["filters"] = {"filterSet": [], "conjunction": "and"} + + airtable_view_type = airtable_view_type_registry.get("grid") + import_report = AirtableImportReport() + serialized_view = airtable_view_type.to_serialized_baserow_view( + field_mapping, + ROW_ID_MAPPING, + RAW_AIRTABLE_TABLE, + RAW_AIRTABLE_VIEW, + view_data, + AirtableImportConfig(), + import_report, + ) + + assert serialized_view["filter_type"] == "AND" + assert serialized_view["filters_disabled"] is False + assert serialized_view["filters"] == [] + assert serialized_view["filter_groups"] == [] + + +@pytest.mark.django_db +def test_import_grid_view_color_config_select_column_not_existing_column(): + view_data = deepcopy(RAW_AIRTABLE_VIEW_DATA) + field_mapping = deepcopy(FIELD_MAPPING) + for field_object in field_mapping.values(): + field_object["baserow_field"].content_type = ContentType.objects.get_for_model( + field_object["baserow_field"] + ) + + view_data["colorConfig"] = deepcopy(RAW_VIEW_COLOR_CONFIG_SELECT_COLUMN) + view_data["colorConfig"]["selectColumnId"] = "fld123" + + airtable_view_type = airtable_view_type_registry.get("grid") + import_report = AirtableImportReport() + serialized_view = airtable_view_type.to_serialized_baserow_view( + field_mapping, + ROW_ID_MAPPING, + RAW_AIRTABLE_TABLE, + RAW_AIRTABLE_VIEW, + view_data, + AirtableImportConfig(), + import_report, + ) + assert len(import_report.items) == 1 + assert import_report.items[0].object_name == "Grid view" + assert import_report.items[0].scope == SCOPE_VIEW_COLOR + assert import_report.items[0].table == "Data" + + +@pytest.mark.django_db +def test_import_grid_view_color_config_select_column(): + view_data = deepcopy(RAW_AIRTABLE_VIEW_DATA) + field_mapping = deepcopy(FIELD_MAPPING) + for field_object in field_mapping.values(): + field_object["baserow_field"].content_type = ContentType.objects.get_for_model( + field_object["baserow_field"] + ) + + view_data["colorConfig"] = RAW_VIEW_COLOR_CONFIG_SELECT_COLUMN + + airtable_view_type = airtable_view_type_registry.get("grid") + import_report = AirtableImportReport() + serialized_view = airtable_view_type.to_serialized_baserow_view( + field_mapping, + ROW_ID_MAPPING, + RAW_AIRTABLE_TABLE, + RAW_AIRTABLE_VIEW, + view_data, + AirtableImportConfig(), + import_report, + ) + assert len(import_report.items) == 0 + + assert serialized_view["decorations"] == [ + { + "id": "viwcpYeEpAs6kZspktV_decoration", + "type": "left_border_color", + "value_provider_type": "single_select_color", + "value_provider_conf": {"field_id": "fldwSc9PqedIhTSqhi1"}, + "order": 1, + } + ] + + +@pytest.mark.django_db +def test_import_grid_view_color_config_color_definitions(): + view_data = deepcopy(RAW_AIRTABLE_VIEW_DATA) + field_mapping = deepcopy(FIELD_MAPPING) + for field_object in field_mapping.values(): + field_object["baserow_field"].content_type = ContentType.objects.get_for_model( + field_object["baserow_field"] + ) + + view_data["colorConfig"] = RAW_VIEW_COLOR_CONFIG_COLOR_DEFINITIONS + + airtable_view_type = airtable_view_type_registry.get("grid") + import_report = AirtableImportReport() + serialized_view = airtable_view_type.to_serialized_baserow_view( + field_mapping, + ROW_ID_MAPPING, + RAW_AIRTABLE_TABLE, + RAW_AIRTABLE_VIEW, + view_data, + AirtableImportConfig(), + import_report, + ) + assert len(import_report.items) == 0 + + assert serialized_view["decorations"] == [ + { + "id": "viwcpYeEpAs6kZspktV_decoration", + "type": "left_border_color", + "value_provider_type": "conditional_color", + "value_provider_conf": { + "colors": [ + { + "filter_groups": [ + { + "id": "flthuYL0uubbDF2Xy", + "filter_type": "AND", + "parent_group": None, + }, + { + "id": "flthuYL0uubbDF2Xz", + "filter_type": "OR", + "parent_group": "flthuYL0uubbDF2Xy", + }, + ], + "filters": [ + { + "id": "fltp2gabc8P91234f", + "type": "not_empty", + "field": "fldwSc9PqedIhTSqhi1", + "group": None, + "value": "", + }, + { + "id": "flt70g1l245672xRi", + "type": "not_equal", + "field": "fldwSc9PqedIhTSqhi1", + "group": "flthuYL0uubbDF2Xy", + "value": "test", + }, + { + "id": "fltVg238719fbIKqC", + "type": "not_equal", + "field": "fldwSc9PqedIhTSqhi2", + "group": "flthuYL0uubbDF2Xy", + "value": "test2", + }, + { + "id": "flt70g1l245672xRi", + "type": "not_equal", + "field": "fldwSc9PqedIhTSqhi1", + "group": "flthuYL0uubbDF2Xz", + "value": "test", + }, + ], + "operator": "OR", + "color": "light-yellow", + }, + { + "filter_groups": [], + "filters": [], + "operator": "AND", + "color": "light-pink", + }, + ] + }, + "order": 1, + } + ] diff --git a/backend/tests/baserow/contrib/database/api/fields/test_field_views.py b/backend/tests/baserow/contrib/database/api/fields/test_field_views.py index a7df4d1a2..ea7852ac2 100644 --- a/backend/tests/baserow/contrib/database/api/fields/test_field_views.py +++ b/backend/tests/baserow/contrib/database/api/fields/test_field_views.py @@ -15,6 +15,8 @@ from rest_framework.status import ( from baserow.contrib.database.fields.models import Field, NumberField, TextField from baserow.contrib.database.fields.registries import field_type_registry from baserow.contrib.database.tokens.handler import TokenHandler +from baserow.contrib.database.views.handler import ViewIndexingHandler +from baserow.contrib.database.views.models import ViewSort from baserow.core.db import specific_iterator from baserow.test_utils.helpers import ( independent_test_db_connection, @@ -519,7 +521,7 @@ def test_update_field(api_client, data_fixture): url, {"name": existing_field.name}, format="json", - HTTP_AUTHORIZATION=f"JWT" f" {token}", + HTTP_AUTHORIZATION=f"JWT {token}", ) assert response.status_code == HTTP_400_BAD_REQUEST assert response.json()["error"] == "ERROR_FIELD_WITH_SAME_NAME_ALREADY_EXISTS" @@ -530,7 +532,7 @@ def test_update_field(api_client, data_fixture): url, {"name": too_long_field_name}, format="json", - HTTP_AUTHORIZATION=f"JWT" f" {token}", + HTTP_AUTHORIZATION=f"JWT {token}", ) assert response.status_code == HTTP_400_BAD_REQUEST assert response.json()["error"] == "ERROR_REQUEST_BODY_VALIDATION" @@ -717,6 +719,38 @@ def test_update_field_number_type_deprecation_error(api_client, data_fixture): ) +@pytest.mark.django_db +def test_change_field_type_with_active_sort_on_field(api_client, data_fixture): + import uuid + + user, token = data_fixture.create_user_and_token() + table = data_fixture.create_database_table(user=user) + text_field = data_fixture.create_text_field(table=table, name=uuid.uuid4()) + + grid = data_fixture.create_grid_view(table=table) + + sort = data_fixture.create_view_sort(view=grid, field=text_field, order="ASC") + ViewIndexingHandler.update_index(view=grid) + + grid.refresh_from_db() + assert grid.db_index_name is not None + + # Change the field type from text to number + url = reverse("api:database:fields:item", kwargs={"field_id": text_field.id}) + response = api_client.patch( + url, {"type": "number"}, format="json", HTTP_AUTHORIZATION=f"JWT {token}" + ) + + assert response.status_code == HTTP_200_OK + + # Sort is not removed + assert ViewSort.objects.filter(id=sort.id).exists() + + # Sort index is removed + grid.refresh_from_db() + assert grid.db_index_name is None + + @pytest.mark.django_db def test_delete_field(api_client, data_fixture): user, token = data_fixture.create_user_and_token() @@ -858,8 +892,7 @@ def test_update_field_returns_with_error_if_cant_lock_field_if_locked_for_update with conn.cursor() as cursor: # nosec cursor.execute( - f"SELECT * FROM database_field where id = {text_field.id} " - f"FOR UPDATE" + f"SELECT * FROM database_field where id = {text_field.id} FOR UPDATE" ) response = api_client.patch( url, diff --git a/backend/tests/baserow/contrib/database/api/rows/test_row_serializers.py b/backend/tests/baserow/contrib/database/api/rows/test_row_serializers.py index f31cf4365..458ecd26d 100644 --- a/backend/tests/baserow/contrib/database/api/rows/test_row_serializers.py +++ b/backend/tests/baserow/contrib/database/api/rows/test_row_serializers.py @@ -1,6 +1,7 @@ import json import pytest +from pytest_unordered import unordered from rest_framework import serializers from baserow.contrib.database.api.rows.serializers import ( @@ -432,10 +433,12 @@ def test_get_row_serializer_with_user_field_names(data_fixture): "value": "E", }, ], - "formula_multiple_collaborators": [ - {"id": u2.id, "name": u2.first_name}, - {"id": u3.id, "name": u3.first_name}, - ], + "formula_multiple_collaborators": unordered( + [ + {"id": u2.id, "name": u2.first_name}, + {"id": u3.id, "name": u3.first_name}, + ] + ), "formula_text": "test FORMULA", "count": "3", "rollup": "-122.222", @@ -449,10 +452,12 @@ def test_get_row_serializer_with_user_field_names(data_fixture): "multiple_collaborators_lookup": [ { "id": 1, - "value": [ - {"id": u2.id, "name": u2.first_name}, - {"id": u3.id, "name": u3.first_name}, - ], + "value": unordered( + [ + {"id": u2.id, "name": u2.first_name}, + {"id": u3.id, "name": u3.first_name}, + ] + ), }, { "id": 2, diff --git a/backend/tests/baserow/contrib/database/api/rows/test_row_views.py b/backend/tests/baserow/contrib/database/api/rows/test_row_views.py index 7bf5d7327..b5ebc1ef3 100644 --- a/backend/tests/baserow/contrib/database/api/rows/test_row_views.py +++ b/backend/tests/baserow/contrib/database/api/rows/test_row_views.py @@ -250,8 +250,8 @@ def test_list_rows(api_client, data_fixture): ) number_field_type = field_type_registry.get("number") - old_can_order_by = number_field_type._can_order_by - number_field_type._can_order_by = False + old_can_order_by = number_field_type._can_order_by_types + number_field_type._can_order_by_types = [] invalidate_table_in_model_cache(table.id) url = reverse("api:database:rows:list", kwargs={"table_id": table.id}) response = api_client.get( @@ -263,10 +263,10 @@ def test_list_rows(api_client, data_fixture): response_json = response.json() assert response_json["error"] == "ERROR_ORDER_BY_FIELD_NOT_POSSIBLE" assert response_json["detail"] == ( - f"It is not possible to order by field_{field_2.id} because the field type " - f"number does not support filtering." + f"It is not possible to order by field_{field_2.id} using sort type default " + f"because the field type number does not support it." ) - number_field_type._can_order_by = old_can_order_by + number_field_type._can_order_by_types = old_can_order_by invalidate_table_in_model_cache(table.id) url = reverse("api:database:rows:list", kwargs={"table_id": table.id}) @@ -419,6 +419,74 @@ def test_list_rows(api_client, data_fixture): assert response_json["error"] == "ERROR_USER_NOT_IN_GROUP" +@pytest.mark.django_db +def test_list_rows_order_by_type(api_client, data_fixture): + user, jwt_token = data_fixture.create_user_and_token( + email="test@test.nl", password="password", first_name="Test1" + ) + table = data_fixture.create_database_table(user=user) + field_1 = data_fixture.create_text_field(name="Name", table=table, primary=True) + select_1 = data_fixture.create_single_select_field(name="Select", table=table) + option_1 = data_fixture.create_select_option(field=select_1, value="A", order=3) + option_2 = data_fixture.create_select_option(field=select_1, value="B", order=1) + option_3 = data_fixture.create_select_option(field=select_1, value="C", order=2) + + model = table.get_model(attribute_names=True) + row_1 = model.objects.create(name="Product 1", select_id=option_1.id) + row_2 = model.objects.create(name="Product 2", select_id=option_2.id) + row_3 = model.objects.create(name="Product 3", select_id=option_3.id) + + url = reverse("api:database:rows:list", kwargs={"table_id": table.id}) + response = api_client.get( + f"{url}?order_by=-field_{field_1.id}[unknown]", + format="json", + HTTP_AUTHORIZATION=f"JWT {jwt_token}", + ) + response_json = response.json() + assert response.status_code == HTTP_400_BAD_REQUEST + assert response_json["error"] == "ERROR_ORDER_BY_FIELD_NOT_POSSIBLE" + assert response_json["detail"] == ( + f"It is not possible to order by field_{field_1.id} using sort type unknown " + f"because the field type text does not support it." + ) + + url = reverse("api:database:rows:list", kwargs={"table_id": table.id}) + response = api_client.get( + f"{url}?order_by=field_{field_1.id}[default]", + format="json", + HTTP_AUTHORIZATION=f"JWT {jwt_token}", + ) + response_json = response.json() + assert response.status_code == HTTP_200_OK + assert response_json["results"][0]["id"] == row_1.id + assert response_json["results"][1]["id"] == row_2.id + assert response_json["results"][2]["id"] == row_3.id + + url = reverse("api:database:rows:list", kwargs={"table_id": table.id}) + response = api_client.get( + f"{url}?order_by=-field_{field_1.id}[default]", + format="json", + HTTP_AUTHORIZATION=f"JWT {jwt_token}", + ) + response_json = response.json() + assert response.status_code == HTTP_200_OK + assert response_json["results"][0]["id"] == row_3.id + assert response_json["results"][1]["id"] == row_2.id + assert response_json["results"][2]["id"] == row_1.id + + url = reverse("api:database:rows:list", kwargs={"table_id": table.id}) + response = api_client.get( + f"{url}?order_by=field_{select_1.id}[order]", + format="json", + HTTP_AUTHORIZATION=f"JWT {jwt_token}", + ) + response_json = response.json() + assert response.status_code == HTTP_200_OK + assert response_json["results"][0]["id"] == row_2.id + assert response_json["results"][1]["id"] == row_3.id + assert response_json["results"][2]["id"] == row_1.id + + @pytest.mark.django_db def test_list_rows_adhoc_filtering_query_param_null_character(api_client, data_fixture): user, token = data_fixture.create_user_and_token() @@ -2839,8 +2907,8 @@ def test_list_rows_with_attribute_names(api_client, data_fixture): assert response.status_code == HTTP_400_BAD_REQUEST assert ( response_json["detail"] - == "It is not possible to order by Password because the field type " - "password does not support filtering." + == "It is not possible to order by Password using sort type default because " + "the field type password does not support it." ) url = reverse("api:database:rows:list", kwargs={"table_id": table.id}) @@ -3202,14 +3270,18 @@ def test_get_row_adjacent(api_client, data_fixture): table = data_fixture.create_database_table(name="table", user=user) field = data_fixture.create_text_field(name="some name", table=table) - [row_1, row_2, row_3] = RowHandler().create_rows( - user, - table, - rows_values=[ - {f"field_{field.id}": "some value"}, - {f"field_{field.id}": "some value"}, - {f"field_{field.id}": "some value"}, - ], + [row_1, row_2, row_3] = ( + RowHandler() + .create_rows( + user, + table, + rows_values=[ + {f"field_{field.id}": "some value"}, + {f"field_{field.id}": "some value"}, + {f"field_{field.id}": "some value"}, + ], + ) + .created_rows ) # Get the next row @@ -3257,14 +3329,18 @@ def test_get_row_adjacent_view_id_provided(api_client, data_fixture): user, field=field, view=view, type="contains", value="a" ) - [row_1, row_2, row_3] = RowHandler().create_rows( - user, - table, - rows_values=[ - {f"field_{field.id}": "ab"}, - {f"field_{field.id}": "b"}, - {f"field_{field.id}": "a"}, - ], + [row_1, row_2, row_3] = ( + RowHandler() + .create_rows( + user, + table, + rows_values=[ + {f"field_{field.id}": "ab"}, + {f"field_{field.id}": "b"}, + {f"field_{field.id}": "a"}, + ], + ) + .created_rows ) response = api_client.get( @@ -3290,14 +3366,18 @@ def test_get_row_adjacent_view_id_no_adjacent_row(api_client, data_fixture): table = data_fixture.create_database_table(name="table", user=user) field = data_fixture.create_text_field(name="field", table=table) - [row_1, row_2, row_3] = RowHandler().create_rows( - user, - table, - rows_values=[ - {f"field_{field.id}": "a"}, - {f"field_{field.id}": "b"}, - {f"field_{field.id}": "c"}, - ], + [row_1, row_2, row_3] = ( + RowHandler() + .create_rows( + user, + table, + rows_values=[ + {f"field_{field.id}": "a"}, + {f"field_{field.id}": "b"}, + {f"field_{field.id}": "c"}, + ], + ) + .created_rows ) response = api_client.get( @@ -3401,14 +3481,18 @@ def test_get_row_adjacent_search(api_client, data_fixture, search_mode): table = data_fixture.create_database_table(name="table", user=user) field = data_fixture.create_text_field(name="field", table=table) - [row_1, row_2, row_3] = RowHandler().create_rows( - user, - table, - rows_values=[ - {f"field_{field.id}": "a"}, - {f"field_{field.id}": "ab"}, - {f"field_{field.id}": "c"}, - ], + [row_1, row_2, row_3] = ( + RowHandler() + .create_rows( + user, + table, + rows_values=[ + {f"field_{field.id}": "a"}, + {f"field_{field.id}": "ab"}, + {f"field_{field.id}": "c"}, + ], + ) + .created_rows ) SearchHandler.update_tsvector_columns( table, update_tsvectors_for_changed_rows_only=False @@ -3892,6 +3976,9 @@ def test_list_row_history_for_different_fields(data_fixture, api_client): "value": f"unnamed row {table2_row2.id}" }, }, + "linked_table_id": linkrow_field.link_row_table_id, + "linked_field_id": linkrow_field.link_row_related_field_id, + "primary_value": "unnamed row 1", }, }, }, @@ -4364,7 +4451,7 @@ def test_link_row_field_validate_input_data_for_read_only_primary_fields( user=user, table_b=table_b ) - (row_b1,) = RowHandler().create_rows(user, table_b, [{}]) + (row_b1,) = RowHandler().create_rows(user, table_b, [{}]).created_rows row_b1_pk = str(getattr(row_b1, pk_field.db_column)) # using a valid value as reference to the row should work diff --git a/backend/tests/baserow/contrib/database/api/tables/test_table_views.py b/backend/tests/baserow/contrib/database/api/tables/test_table_views.py index d9b3c3fe9..bf24afa95 100644 --- a/backend/tests/baserow/contrib/database/api/tables/test_table_views.py +++ b/backend/tests/baserow/contrib/database/api/tables/test_table_views.py @@ -17,6 +17,7 @@ from rest_framework.status import ( from baserow.contrib.database.data_sync.handler import DataSyncHandler from baserow.contrib.database.file_import.models import FileImportJob from baserow.contrib.database.table.models import Table +from baserow.core.jobs.models import Job from baserow.test_utils.helpers import ( assert_serialized_rows_contain_same_values, independent_test_db_connection, @@ -248,7 +249,7 @@ def test_create_table_with_data( with patch_filefield_storage(): with job.data_file.open("r") as fin: data = json.load(fin) - assert data == [ + assert data.get("data") == [ ["A", "B", "C", "D"], ["1-1", "1-2", "1-3", "1-4", "1-5"], ["2-1", "2-2", "2-3"], @@ -647,3 +648,144 @@ def test_async_duplicate_interesting_table(api_client, data_fixture): for original_row, duplicated_row in zip(original_rows, duplicated_rows): assert_serialized_rows_contain_same_values(original_row, duplicated_row) + + +@pytest.mark.django_db +def test_import_table_call(api_client, data_fixture): + """ + A simple test to check import table validation + """ + + user, token = data_fixture.create_user_and_token() + database = data_fixture.create_database_application(user=user) + table = data_fixture.create_database_table(database=database) + data_fixture.create_text_field(table=table, user=user) + data_fixture.create_number_field(table=table, user=user) + + url = reverse("api:database:tables:import_async", kwargs={"table_id": table.id}) + + valid_data_no_configuration = {"data": [["1", 1], ["2", 1]]} + + response = api_client.post( + url, + HTTP_AUTHORIZATION=f"JWT {token}", + data=valid_data_no_configuration, + format="json", + ) + assert response.status_code == HTTP_200_OK + rdata = response.json() + + assert isinstance(rdata.get("id"), int) + assert rdata.get("type") == "file_import" + Job.objects.all().delete() + + valid_data_with_configuration = {"data": [["1", 1], ["2", 1]], "configuration": {}} + response = api_client.post( + url, + HTTP_AUTHORIZATION=f"JWT {token}", + data=valid_data_with_configuration, + format="json", + ) + rdata = response.json() + + assert response.status_code == HTTP_200_OK + assert isinstance(rdata.get("id"), int) + assert rdata.get("type") == "file_import" + Job.objects.all().delete() + + invalid_data_with_configuration = { + "data": [["1", 1], ["2", 1]], + "configuration": {"upsert_fields": []}, + } + response = api_client.post( + url, + HTTP_AUTHORIZATION=f"JWT {token}", + data=invalid_data_with_configuration, + format="json", + ) + rdata = response.json() + + assert response.status_code == HTTP_400_BAD_REQUEST + assert rdata == { + "error": "ERROR_REQUEST_BODY_VALIDATION", + "detail": { + "configuration": { + "upsert_fields": [ + { + "error": "Ensure this field has at least 1 elements.", + "code": "min_length", + } + ] + } + }, + } + Job.objects.all().delete() + + invalid_data = {} + response = api_client.post( + url, HTTP_AUTHORIZATION=f"JWT {token}", data=invalid_data + ) + rdata = response.json() + assert response.status_code == HTTP_400_BAD_REQUEST + assert rdata == { + "error": "ERROR_REQUEST_BODY_VALIDATION", + "detail": {"data": [{"error": "This field is required.", "code": "required"}]}, + } + + invalid_data = { + "data": [["1", 1], ["2", 1]], + "configuration": {"upsert_fields": [1, 2]}, + } + response = api_client.post( + url, + HTTP_AUTHORIZATION=f"JWT {token}", + data=invalid_data, + format="json", + ) + assert response.status_code == HTTP_400_BAD_REQUEST + rdata = response.json() + + assert rdata == { + "error": "ERROR_REQUEST_BODY_VALIDATION", + "detail": { + "configuration": { + "upsert_value": [ + { + "error": "upsert_values must not be empty when upsert_fields are provided.", + "code": "invalid", + } + ] + } + }, + } + + invalid_data = { + "data": [["1", 1], ["2", 1]], + "configuration": {"upsert_fields": [1, 2], "upsert_values": [["a"]]}, + } + response = api_client.post( + url, + HTTP_AUTHORIZATION=f"JWT {token}", + data=invalid_data, + format="json", + ) + assert response.status_code == HTTP_400_BAD_REQUEST + rdata = response.json() + + assert rdata == { + "error": "ERROR_REQUEST_BODY_VALIDATION", + "detail": { + "data": [ + { + "error": "`data` and `configuration.upsert_values` should have the same length.", + "code": "invalid", + } + ], + "configuration": { + "upsert_values": { + "error": "`data` and `configuration.upsert_values` should have the same length.", + "code": "invalid", + } + }, + }, + } diff --git a/backend/tests/baserow/contrib/database/api/views/gallery/test_gallery_view_views.py b/backend/tests/baserow/contrib/database/api/views/gallery/test_gallery_view_views.py index 5438fc53e..bd5076212 100644 --- a/backend/tests/baserow/contrib/database/api/views/gallery/test_gallery_view_views.py +++ b/backend/tests/baserow/contrib/database/api/views/gallery/test_gallery_view_views.py @@ -829,6 +829,7 @@ def test_get_public_gallery_view(api_client, data_fixture): "field": visible_sort.field.id, "id": visible_sort.id, "order": "DESC", + "type": "default", "view": gallery_view.slug, } ], diff --git a/backend/tests/baserow/contrib/database/api/views/grid/test_grid_view_views.py b/backend/tests/baserow/contrib/database/api/views/grid/test_grid_view_views.py index dd9cda5c8..a666c008f 100644 --- a/backend/tests/baserow/contrib/database/api/views/grid/test_grid_view_views.py +++ b/backend/tests/baserow/contrib/database/api/views/grid/test_grid_view_views.py @@ -3289,6 +3289,7 @@ def test_get_public_grid_view(api_client, data_fixture): "field": visible_sort.field.id, "id": visible_sort.id, "order": "DESC", + "type": "default", "view": grid_view.slug, } ], @@ -3300,6 +3301,7 @@ def test_get_public_grid_view(api_client, data_fixture): "order": "DESC", "view": grid_view.slug, "width": 200, + "type": "default", } ], "table": { @@ -3926,6 +3928,46 @@ def test_list_rows_public_with_query_param_group_by_and_empty_order_by( } +@pytest.mark.django_db +def test_list_rows_public_with_query_param_group_by_and_type(api_client, data_fixture): + user, token = data_fixture.create_user_and_token() + table = data_fixture.create_database_table(user=user) + field_1 = data_fixture.create_text_field(name="Name", table=table, primary=True) + select_1 = data_fixture.create_single_select_field(name="Select", table=table) + option_1 = data_fixture.create_select_option(field=select_1, value="A", order=3) + option_2 = data_fixture.create_select_option(field=select_1, value="B", order=1) + option_3 = data_fixture.create_select_option(field=select_1, value="C", order=2) + grid_view = data_fixture.create_grid_view( + table=table, user=user, public=True, create_options=False + ) + data_fixture.create_grid_view_field_option(grid_view, field_1, hidden=False) + data_fixture.create_grid_view_field_option(grid_view, select_1, hidden=False) + + model = table.get_model(attribute_names=True) + row_1 = model.objects.create(name="Product 1", select_id=option_1.id) + row_2 = model.objects.create(name="Product 2", select_id=option_2.id) + row_3 = model.objects.create(name="Product 3", select_id=option_3.id) + + url = reverse( + "api:database:views:grid:public_rows", kwargs={"slug": grid_view.slug} + ) + response = api_client.get( + f"{url}?group_by=field_{select_1.id}[unknown]", + ) + response_json = response.json() + assert response.status_code == HTTP_400_BAD_REQUEST + assert response_json["error"] == "ERROR_ORDER_BY_FIELD_NOT_POSSIBLE" + + response = api_client.get( + f"{url}?group_by=field_{select_1.id}[order]", + ) + response_json = response.json() + assert response.status_code == HTTP_200_OK + assert response_json["results"][0]["id"] == row_2.id + assert response_json["results"][1]["id"] == row_3.id + assert response_json["results"][2]["id"] == row_1.id + + @pytest.mark.django_db def test_list_rows_public_filters_by_visible_and_hidden_columns( api_client, data_fixture diff --git a/backend/tests/baserow/contrib/database/api/views/test_view_group_by.py b/backend/tests/baserow/contrib/database/api/views/test_view_group_by.py index fe2c3effd..2347a0580 100644 --- a/backend/tests/baserow/contrib/database/api/views/test_view_group_by.py +++ b/backend/tests/baserow/contrib/database/api/views/test_view_group_by.py @@ -189,6 +189,7 @@ def test_create_view_group_by(api_client, data_fixture): response_json = response.json() assert response.status_code == HTTP_200_OK assert response_json["order"] == "DESC" + assert response_json["type"] == "default" response = api_client.post( reverse("api:database:views:list_group_bys", kwargs={"view_id": view_1.id}), @@ -206,6 +207,36 @@ def test_create_view_group_by(api_client, data_fixture): assert ViewGroupBy.objects.all().count() == 3 +@pytest.mark.django_db +def test_create_view_group_by_with_type(api_client, data_fixture): + user, token = data_fixture.create_user_and_token() + table_1 = data_fixture.create_database_table(user=user) + field_1 = data_fixture.create_text_field(table=table_1) + select_1 = data_fixture.create_single_select_field(table=table_1) + view_1 = data_fixture.create_grid_view(table=table_1) + + response = api_client.post( + reverse("api:database:views:list_group_bys", kwargs={"view_id": view_1.id}), + {"field": field_1.id, "order": "ASC", "type": "unknown"}, + format="json", + HTTP_AUTHORIZATION=f"JWT {token}", + ) + response_json = response.json() + assert response.status_code == HTTP_400_BAD_REQUEST + assert response_json["error"] == "ERROR_VIEW_GROUP_BY_FIELD_NOT_SUPPORTED" + + response = api_client.post( + reverse("api:database:views:list_group_bys", kwargs={"view_id": view_1.id}), + {"field": select_1.id, "order": "DESC", "type": "order"}, + format="json", + HTTP_AUTHORIZATION=f"JWT {token}", + ) + response_json = response.json() + assert response.status_code == HTTP_200_OK + assert response_json["order"] == "DESC" + assert response_json["type"] == "order" + + @pytest.mark.django_db def test_cannot_created_group_by(api_client, data_fixture): user, token = data_fixture.create_user_and_token() @@ -283,6 +314,7 @@ def test_get_view_group_by(api_client, data_fixture): assert response_json["view"] == first.view_id assert response_json["field"] == first.field_id assert response_json["order"] == "DESC" + assert response_json["type"] == "default" response = api_client.delete( reverse( @@ -432,6 +464,7 @@ def test_update_view_group_by(api_client, data_fixture): assert response_json["view"] == first.view_id assert response_json["field"] == field_1.id assert response_json["order"] == "DESC" + assert response_json["type"] == "default" response = api_client.patch( reverse( @@ -452,6 +485,7 @@ def test_update_view_group_by(api_client, data_fixture): assert response_json["field"] == field_1.id assert response_json["order"] == "DESC" assert response_json["width"] == 120 + assert response_json["type"] == "default" response = api_client.patch( reverse( @@ -472,6 +506,69 @@ def test_update_view_group_by(api_client, data_fixture): assert response_json["field"] == field_1.id assert response_json["order"] == "DESC" assert response_json["width"] == 120 + assert response_json["type"] == "default" + + +@pytest.mark.django_db +def test_update_view_group_by_with_type(api_client, data_fixture): + user, token = data_fixture.create_user_and_token() + table = data_fixture.create_database_table(user=user) + field_1 = data_fixture.create_text_field(table=table) + select_2 = data_fixture.create_single_select_field(table=table) + group_by_1 = data_fixture.create_view_group_by( + user=user, order="DESC", field=field_1 + ) + group_by_2 = data_fixture.create_view_group_by( + user=user, order="DESC", field=select_2 + ) + + response = api_client.patch( + reverse( + "api:database:views:group_by_item", + kwargs={"view_group_by_id": group_by_1.id}, + ), + {"field": field_1.id, "type": "unknown"}, + format="json", + HTTP_AUTHORIZATION=f"JWT {token}", + ) + response_json = response.json() + assert response.status_code == HTTP_400_BAD_REQUEST + assert response_json["error"] == "ERROR_VIEW_GROUP_BY_FIELD_NOT_SUPPORTED" + + response = api_client.patch( + reverse( + "api:database:views:group_by_item", + kwargs={"view_group_by_id": group_by_2.id}, + ), + { + "field": select_2.id, + "order": "ASC", + "type": "order", + }, + format="json", + HTTP_AUTHORIZATION=f"JWT {token}", + ) + response_json = response.json() + assert response.status_code == HTTP_200_OK + assert response_json["order"] == "ASC" + assert response_json["type"] == "order" + + response = api_client.patch( + reverse( + "api:database:views:group_by_item", + kwargs={"view_group_by_id": group_by_2.id}, + ), + { + "field": select_2.id, + "order": "DESC", + }, + format="json", + HTTP_AUTHORIZATION=f"JWT {token}", + ) + response_json = response.json() + assert response.status_code == HTTP_200_OK + assert response_json["order"] == "DESC" + assert response_json["type"] == "order" @pytest.mark.django_db diff --git a/backend/tests/baserow/contrib/database/api/views/test_view_serializers.py b/backend/tests/baserow/contrib/database/api/views/test_view_serializers.py index 69fe67241..5a286f7f3 100644 --- a/backend/tests/baserow/contrib/database/api/views/test_view_serializers.py +++ b/backend/tests/baserow/contrib/database/api/views/test_view_serializers.py @@ -5,6 +5,7 @@ from baserow.contrib.database.api.views.serializers import serialize_group_by_me from baserow.contrib.database.fields.models import Field from baserow.contrib.database.fields.registries import field_type_registry from baserow.contrib.database.views.handler import ViewHandler +from baserow.contrib.database.views.models import DEFAULT_SORT_TYPE_KEY from baserow.test_utils.helpers import setup_interesting_test_table @@ -65,7 +66,8 @@ def test_serialize_group_by_metadata(api_client, data_fixture): @pytest.mark.django_db def test_serialize_group_by_metadata_on_all_fields_in_interesting_table(data_fixture): - table, *_ = setup_interesting_test_table(data_fixture) + table, _, _, _, context = setup_interesting_test_table(data_fixture) + user2, user3 = context["user2"], context["user3"] model = table.get_model() queryset = model.objects.all() rows = list(queryset) @@ -74,7 +76,9 @@ def test_serialize_group_by_metadata_on_all_fields_in_interesting_table(data_fix fields_to_group_by = [ field for field in all_fields - if field_type_registry.get_by_model(field).check_can_group_by(field) + if field_type_registry.get_by_model(field).check_can_group_by( + field, DEFAULT_SORT_TYPE_KEY + ) ] single_select_options = Field.objects.get(name="single_select").select_options.all() @@ -284,6 +288,14 @@ def test_serialize_group_by_metadata_on_all_fields_in_interesting_table(data_fix {"field_decimal_link_row": [], "count": 1}, {"field_decimal_link_row": [1, 2, 3], "count": 1}, ], + "multiple_collaborators_link_row": [ + {"field_multiple_collaborators_link_row": [], "count": 1}, + {"field_multiple_collaborators_link_row": [1, 2], "count": 1}, + ], + "multiple_collaborators": [ + {"field_multiple_collaborators": [], "count": 1}, + {"field_multiple_collaborators": [user2.id, user3.id], "count": 1}, + ], } for key, actual_value in actual_result_per_field_name.items(): expected_value = expected_result.get(key, None) diff --git a/backend/tests/baserow/contrib/database/api/views/test_view_sort.py b/backend/tests/baserow/contrib/database/api/views/test_view_sort.py index 2ca2762cc..b466296df 100644 --- a/backend/tests/baserow/contrib/database/api/views/test_view_sort.py +++ b/backend/tests/baserow/contrib/database/api/views/test_view_sort.py @@ -52,6 +52,7 @@ def test_list_view_sortings(api_client, data_fixture): assert response_json[0]["view"] == view_1.id assert response_json[0]["field"] == field_1.id assert response_json[0]["order"] == sort_1.order + assert response_json[0]["type"] == sort_1.type assert response_json[1]["id"] == sort_2.id response = api_client.delete( @@ -187,6 +188,7 @@ def test_create_view_sort(api_client, data_fixture): response_json = response.json() assert response.status_code == HTTP_200_OK assert response_json["order"] == "DESC" + assert response_json["type"] == "default" response = api_client.post( reverse("api:database:views:list_sortings", kwargs={"view_id": view_1.id}), @@ -199,10 +201,41 @@ def test_create_view_sort(api_client, data_fixture): response_json = response.json() assert response.status_code == HTTP_200_OK assert response_json["order"] == "ASC" + assert response_json["type"] == "default" assert ViewSort.objects.all().count() == 3 +@pytest.mark.django_db +def test_create_view_sort_with_type(api_client, data_fixture): + user, token = data_fixture.create_user_and_token() + table_1 = data_fixture.create_database_table(user=user) + field_1 = data_fixture.create_text_field(table=table_1) + select_1 = data_fixture.create_single_select_field(table=table_1) + view_1 = data_fixture.create_grid_view(table=table_1) + + response = api_client.post( + reverse("api:database:views:list_sortings", kwargs={"view_id": view_1.id}), + {"field": field_1.id, "order": "ASC", "type": "unknown"}, + format="json", + HTTP_AUTHORIZATION=f"JWT {token}", + ) + response_json = response.json() + assert response.status_code == HTTP_400_BAD_REQUEST + assert response_json["error"] == "ERROR_VIEW_SORT_FIELD_NOT_SUPPORTED" + + response = api_client.post( + reverse("api:database:views:list_sortings", kwargs={"view_id": view_1.id}), + {"field": select_1.id, "order": "DESC", "type": "order"}, + format="json", + HTTP_AUTHORIZATION=f"JWT {token}", + ) + response_json = response.json() + assert response.status_code == HTTP_200_OK + assert response_json["order"] == "DESC" + assert response_json["type"] == "order" + + @pytest.mark.django_db def test_get_view_sort(api_client, data_fixture): user, token = data_fixture.create_user_and_token() @@ -235,6 +268,7 @@ def test_get_view_sort(api_client, data_fixture): assert response_json["view"] == first.view_id assert response_json["field"] == first.field_id assert response_json["order"] == "DESC" + assert response_json["type"] == "default" response = api_client.delete( reverse( @@ -345,6 +379,7 @@ def test_update_view_sort(api_client, data_fixture): assert response_json["view"] == first.view_id assert response_json["field"] == field_1.id assert response_json["order"] == "ASC" + assert response_json["type"] == "default" response = api_client.patch( reverse("api:database:views:sort_item", kwargs={"view_sort_id": sort_1.id}), @@ -361,6 +396,7 @@ def test_update_view_sort(api_client, data_fixture): assert response_json["view"] == first.view_id assert response_json["field"] == field_1.id assert response_json["order"] == "DESC" + assert response_json["type"] == "default" response = api_client.patch( reverse("api:database:views:sort_item", kwargs={"view_sort_id": sort_1.id}), @@ -379,6 +415,56 @@ def test_update_view_sort(api_client, data_fixture): assert response_json["order"] == "DESC" +@pytest.mark.django_db +def test_update_view_sort_with_type(api_client, data_fixture): + user, token = data_fixture.create_user_and_token() + table = data_fixture.create_database_table(user=user) + field_1 = data_fixture.create_text_field(table=table) + select_2 = data_fixture.create_single_select_field(table=table) + sort_1 = data_fixture.create_view_sort(user=user, order="DESC", field=field_1) + sort_2 = data_fixture.create_view_sort(user=user, order="DESC", field=select_2) + + response = api_client.patch( + reverse("api:database:views:sort_item", kwargs={"view_sort_id": sort_1.id}), + {"field": field_1.id, "type": "unknown"}, + format="json", + HTTP_AUTHORIZATION=f"JWT {token}", + ) + response_json = response.json() + assert response.status_code == HTTP_400_BAD_REQUEST + print(response_json) + assert response_json["error"] == "ERROR_VIEW_SORT_FIELD_NOT_SUPPORTED" + + response = api_client.patch( + reverse("api:database:views:sort_item", kwargs={"view_sort_id": sort_2.id}), + { + "field": select_2.id, + "order": "ASC", + "type": "order", + }, + format="json", + HTTP_AUTHORIZATION=f"JWT {token}", + ) + response_json = response.json() + assert response.status_code == HTTP_200_OK + assert response_json["order"] == "ASC" + assert response_json["type"] == "order" + + response = api_client.patch( + reverse("api:database:views:sort_item", kwargs={"view_sort_id": sort_2.id}), + { + "field": select_2.id, + "order": "DESC", + }, + format="json", + HTTP_AUTHORIZATION=f"JWT {token}", + ) + response_json = response.json() + assert response.status_code == HTTP_200_OK + assert response_json["order"] == "DESC" + assert response_json["type"] == "order" + + @pytest.mark.django_db def test_delete_view_sort(api_client, data_fixture): user, token = data_fixture.create_user_and_token() @@ -449,6 +535,7 @@ def test_list_views_including_sortings(api_client, data_fixture): assert response_json[0]["sortings"][0]["view"] == view_1.id assert response_json[0]["sortings"][0]["field"] == field_1.id assert response_json[0]["sortings"][0]["order"] == sort_1.order + assert response_json[0]["sortings"][0]["type"] == sort_1.type assert response_json[0]["sortings"][1]["id"] == sort_2.id assert len(response_json[1]["sortings"]) == 1 assert response_json[1]["sortings"][0]["id"] == sort_3.id diff --git a/backend/tests/baserow/contrib/database/api/webhooks/test_webhook_views.py b/backend/tests/baserow/contrib/database/api/webhooks/test_webhook_views.py index 2b2bf8166..d5505749a 100644 --- a/backend/tests/baserow/contrib/database/api/webhooks/test_webhook_views.py +++ b/backend/tests/baserow/contrib/database/api/webhooks/test_webhook_views.py @@ -462,9 +462,7 @@ def test_update_webhook(api_client, data_fixture): assert response_json["include_all_events"] is False assert response_json["failed_triggers"] == 0 assert response_json["events"] == ["rows.created"] - assert response_json["event_config"] == [ - {"event_type": "rows.created", "fields": []} - ] + assert response_json["event_config"] == [{"event_type": "rows.created"}] assert response_json["headers"] == {"Baserow-add-1": "Value 1"} assert response_json["calls"] == [] @@ -530,7 +528,7 @@ def test_update_webhook_with_event_config(api_client, data_fixture): assert response_json["events"] == ["rows.updated", "rows.deleted"] assert response_json["event_config"] == [ {"event_type": "rows.updated", "fields": [field_1.id, field_2.id]}, - {"event_type": "rows.deleted", "fields": []}, + {"event_type": "rows.deleted"}, ] response = api_client.patch( @@ -545,7 +543,7 @@ def test_update_webhook_with_event_config(api_client, data_fixture): assert response.status_code == HTTP_200_OK assert response_json["events"] == ["rows.deleted"] assert response_json["event_config"] == [ - {"event_type": "rows.deleted", "fields": []}, + {"event_type": "rows.deleted"}, ] response = api_client.patch( @@ -558,7 +556,7 @@ def test_update_webhook_with_event_config(api_client, data_fixture): assert response.status_code == HTTP_200_OK assert response_json["events"] == ["rows.deleted"] assert response_json["event_config"] == [ - {"event_type": "rows.deleted", "fields": []}, + {"event_type": "rows.deleted"}, ] diff --git a/backend/tests/baserow/contrib/database/field/test_autonumber_field_type.py b/backend/tests/baserow/contrib/database/field/test_autonumber_field_type.py index da3b4b3c8..4c4c7391e 100644 --- a/backend/tests/baserow/contrib/database/field/test_autonumber_field_type.py +++ b/backend/tests/baserow/contrib/database/field/test_autonumber_field_type.py @@ -618,8 +618,10 @@ def test_autonumber_field_can_be_referenced_in_formula(data_fixture): user = data_fixture.create_user() table = data_fixture.create_database_table(user=user) data_fixture.create_autonumber_field(name="autonumber", table=table) - row_1, row_2 = RowHandler().create_rows( - user=user, table=table, rows_values=[{}, {}] + row_1, row_2 = ( + RowHandler() + .create_rows(user=user, table=table, rows_values=[{}, {}]) + .created_rows ) formula_field = data_fixture.create_formula_field( @@ -633,8 +635,10 @@ def test_autonumber_field_can_be_referenced_in_formula(data_fixture): {"id": row_2.id, f"field_{formula_field.id}": 4}, ] - (row_3,) = RowHandler().create_rows( - user=user, table=table, rows_values=[{}], model=model + (row_3,) = ( + RowHandler() + .create_rows(user=user, table=table, rows_values=[{}], model=model) + .created_rows ) row_values = model.objects.all().values("id", f"field_{formula_field.id}") assert list(row_values) == [ @@ -660,12 +664,17 @@ def test_autonumber_field_can_be_looked_up(data_fixture): row_b_2 = model_b.objects.create() model_a = table_a.get_model() - (row,) = RowHandler().create_rows( - user=user, - table=table_a, - rows_values=[ - {f"field_{link_field.id}": [row_b_1.id, row_b_2.id]}, - ], - model=model_a, + (row,) = ( + RowHandler() + .create_rows( + user=user, + table=table_a, + rows_values=[ + {f"field_{link_field.id}": [row_b_1.id, row_b_2.id]}, + ], + model=model_a, + ) + .created_rows ) + assert getattr(row, f"field_{formula_field.id}") == 3 diff --git a/backend/tests/baserow/contrib/database/field/test_boolean_field_type.py b/backend/tests/baserow/contrib/database/field/test_boolean_field_type.py index 5e00bd140..a53eaf06d 100644 --- a/backend/tests/baserow/contrib/database/field/test_boolean_field_type.py +++ b/backend/tests/baserow/contrib/database/field/test_boolean_field_type.py @@ -138,7 +138,7 @@ def test_boolean_field_adjacent_row(data_fixture): }, ], model=table_model, - ) + ).created_rows previous_row = handler.get_adjacent_row( table_model, row_c.id, previous=True, view=grid_view diff --git a/backend/tests/baserow/contrib/database/field/test_created_by_field_type.py b/backend/tests/baserow/contrib/database/field/test_created_by_field_type.py index af69ceafc..9a21e8cd5 100644 --- a/backend/tests/baserow/contrib/database/field/test_created_by_field_type.py +++ b/backend/tests/baserow/contrib/database/field/test_created_by_field_type.py @@ -132,7 +132,7 @@ def test_create_rows_created_by(data_fixture): rows = row_handler.create_rows( user=user, table=table, rows_values=[{}, {}], model=model - ) + ).created_rows assert getattr(rows[0], f"field_{field.id}") == user diff --git a/backend/tests/baserow/contrib/database/field/test_created_on_field_type.py b/backend/tests/baserow/contrib/database/field/test_created_on_field_type.py index 2b429e6c1..4b587f011 100644 --- a/backend/tests/baserow/contrib/database/field/test_created_on_field_type.py +++ b/backend/tests/baserow/contrib/database/field/test_created_on_field_type.py @@ -237,7 +237,7 @@ def test_created_on_field_adjacent_row(data_fixture): {}, ], model=table_model, - ) + ).created_rows previous_row = handler.get_adjacent_row( table_model, row_b.id, previous=True, view=grid_view diff --git a/backend/tests/baserow/contrib/database/field/test_date_field_type.py b/backend/tests/baserow/contrib/database/field/test_date_field_type.py index c495a41b8..eda572b01 100644 --- a/backend/tests/baserow/contrib/database/field/test_date_field_type.py +++ b/backend/tests/baserow/contrib/database/field/test_date_field_type.py @@ -662,7 +662,7 @@ def test_date_field_adjacent_row(data_fixture): }, ], model=table_model, - ) + ).created_rows previous_row = handler.get_adjacent_row( table_model, row_b.id, previous=True, view=grid_view @@ -700,7 +700,7 @@ def test_get_group_by_metadata_in_rows_with_date_field(data_fixture): f"field_{date_field.id}": "2010-01-02 12:01:21", }, ], - ) + ).created_rows model = table.get_model() diff --git a/backend/tests/baserow/contrib/database/field/test_duration_field_type.py b/backend/tests/baserow/contrib/database/field/test_duration_field_type.py index 3148d728c..4d823d91c 100644 --- a/backend/tests/baserow/contrib/database/field/test_duration_field_type.py +++ b/backend/tests/baserow/contrib/database/field/test_duration_field_type.py @@ -98,7 +98,7 @@ def test_create_duration_field_rows(data_fixture): {f"field_{duration_field.id}": timedelta(seconds=3661)}, ], model=model, - ) + ).created_rows assert len(rows) == 2 assert getattr(rows[0], f"field_{duration_field.id}") == timedelta(seconds=3660) @@ -779,20 +779,24 @@ def test_duration_field_view_filters(data_fixture): ) model = table.get_model() - rows = RowHandler().create_rows( - user, - table, - rows_values=[ - {field.db_column: None}, - {field.db_column: "0:1.123"}, - {field.db_column: 1.123}, - {field.db_column: 60}, # 1min - {field.db_column: "24:0:0"}, # 1day - {field.db_column: "1 0"}, # 1day - {field.db_column: 3601}, # 1hour 1sec - {field.db_column: "1:0:0"}, # 1 hour - ], - model=model, + rows = ( + RowHandler() + .create_rows( + user, + table, + rows_values=[ + {field.db_column: None}, + {field.db_column: "0:1.123"}, + {field.db_column: 1.123}, + {field.db_column: 60}, # 1min + {field.db_column: "24:0:0"}, # 1day + {field.db_column: "1 0"}, # 1day + {field.db_column: 3601}, # 1hour 1sec + {field.db_column: "1:0:0"}, # 1 hour + ], + model=model, + ) + .created_rows ) # @@ -1105,14 +1109,18 @@ def test_duration_field_can_be_looked_up(data_fixture): ) model_b = table_b.get_model() - row_b_1, row_b_2 = RowHandler().create_rows( - user=user, - table=table_b, - rows_values=[ - {duration_field.db_column: 24 * 3600}, - {duration_field.db_column: 60}, - ], - model=model_b, + row_b_1, row_b_2 = ( + RowHandler() + .create_rows( + user=user, + table=table_b, + rows_values=[ + {duration_field.db_column: 24 * 3600}, + {duration_field.db_column: 60}, + ], + model=model_b, + ) + .created_rows ) assert list(model_b.objects.values_list(duration_formula.db_column, flat=True)) == [ @@ -1121,13 +1129,17 @@ def test_duration_field_can_be_looked_up(data_fixture): ] model_a = table_a.get_model() - (row,) = RowHandler().create_rows( - user=user, - table=table_a, - rows_values=[ - {f"field_{link_field.id}": [row_b_1.id, row_b_2.id]}, - ], - model=model_a, + (row,) = ( + RowHandler() + .create_rows( + user=user, + table=table_a, + rows_values=[ + {f"field_{link_field.id}": [row_b_1.id, row_b_2.id]}, + ], + model=model_a, + ) + .created_rows ) assert getattr(row, f"field_{lookup_field.id}") == [ {"id": row_b_1.id, "value": "1 day"}, diff --git a/backend/tests/baserow/contrib/database/field/test_duration_formula_field_filters.py b/backend/tests/baserow/contrib/database/field/test_duration_formula_field_filters.py index 7d7e55183..ded72748e 100644 --- a/backend/tests/baserow/contrib/database/field/test_duration_formula_field_filters.py +++ b/backend/tests/baserow/contrib/database/field/test_duration_formula_field_filters.py @@ -79,7 +79,7 @@ def duration_formula_filter_proc( {src_field_name: 61, refname: "1m 1s"}, ] - created = t.row_handler.create_rows( + t.row_handler.create_rows( user=t.user, table=t.table, rows_values=rows, diff --git a/backend/tests/baserow/contrib/database/field/test_field_single_select_options.py b/backend/tests/baserow/contrib/database/field/test_field_single_select_options.py index 4cdd4f7a6..8afc5b533 100644 --- a/backend/tests/baserow/contrib/database/field/test_field_single_select_options.py +++ b/backend/tests/baserow/contrib/database/field/test_field_single_select_options.py @@ -40,12 +40,16 @@ def test_migration_rows_with_deleted_singleselect_options( field=single_select_field, value=f"Option B" ) - _, row_with_b = RowHandler().force_create_rows( - user=user, - table=table, - rows_values=[ - {single_select_field.db_column: opt.id} for opt in (option_a, option_b) - ], + row_with_b = ( + RowHandler() + .force_create_rows( + user=user, + table=table, + rows_values=[ + {single_select_field.db_column: opt.id} for opt in (option_a, option_b) + ], + ) + .created_rows[1] ) single_select_field_type = field_type_registry.get_by_model(single_select_field) @@ -95,12 +99,16 @@ def test_single_select_ids_are_removed_from_rows_when_deleted(data_fixture): option_a = data_fixture.create_select_option(field=single_select_field, value=f"A") option_b = data_fixture.create_select_option(field=single_select_field, value=f"B") - _, row_with_b = RowHandler().force_create_rows( - user=user, - table=table, - rows_values=[ - {single_select_field.db_column: opt.id} for opt in (option_a, option_b) - ], + row_with_b = ( + RowHandler() + .force_create_rows( + user=user, + table=table, + rows_values=[ + {single_select_field.db_column: opt.id} for opt in (option_a, option_b) + ], + ) + .created_rows[1] ) # Keep only A, and remove B diff --git a/backend/tests/baserow/contrib/database/field/test_field_tasks.py b/backend/tests/baserow/contrib/database/field/test_field_tasks.py index 30fa13c2c..0cb5f098b 100644 --- a/backend/tests/baserow/contrib/database/field/test_field_tasks.py +++ b/backend/tests/baserow/contrib/database/field/test_field_tasks.py @@ -481,14 +481,18 @@ def test_run_delete_mentions_marked_for_deletion(data_fixture): # Create a user mention with freeze_time("2023-02-27 9:00"): - row_1, row_2 = RowHandler().create_rows( - user=user, - table=table, - rows_values=[ - {f"field_{rich_text_field.id}": f"Hello @{user.id}!"}, - {f"field_{rich_text_field.id}": f"Hi @{user.id}!"}, - ], - model=model, + row_1, row_2 = ( + RowHandler() + .create_rows( + user=user, + table=table, + rows_values=[ + {f"field_{rich_text_field.id}": f"Hello @{user.id}!"}, + {f"field_{rich_text_field.id}": f"Hi @{user.id}!"}, + ], + model=model, + ) + .created_rows ) mentions = RichTextFieldMention.objects.all() diff --git a/backend/tests/baserow/contrib/database/field/test_formula_field_type.py b/backend/tests/baserow/contrib/database/field/test_formula_field_type.py index 5d4535bdc..53dbf81fb 100644 --- a/backend/tests/baserow/contrib/database/field/test_formula_field_type.py +++ b/backend/tests/baserow/contrib/database/field/test_formula_field_type.py @@ -1091,13 +1091,17 @@ def test_inserting_a_row_with_lookup_field_immediately_populates_it_with_empty_l primary_a_field = table_a.field_set.get(primary=True) primary_b_field = table_b.field_set.get(primary=True) target_field = data_fixture.create_text_field(name="target", table=table_b) - row_1, row_2 = RowHandler().create_rows( - user, - table_b, - rows_values=[ - {primary_b_field.db_column: "1", target_field.db_column: "target 1"}, - {primary_b_field.db_column: "2", target_field.db_column: "target 2"}, - ], + row_1, row_2 = ( + RowHandler() + .create_rows( + user, + table_b, + rows_values=[ + {primary_b_field.db_column: "1", target_field.db_column: "target 1"}, + {primary_b_field.db_column: "2", target_field.db_column: "target 2"}, + ], + ) + .created_rows ) RowHandler().create_rows( user, @@ -1373,7 +1377,7 @@ def test_formula_field_adjacent_row(data_fixture): f"field_{text_field.id}": "C", }, ], - ) + ).created_rows previous_row = handler.get_adjacent_row( table_model, row_b.id, previous=True, view=grid_view diff --git a/backend/tests/baserow/contrib/database/field/test_last_modified_by_field_type.py b/backend/tests/baserow/contrib/database/field/test_last_modified_by_field_type.py index 83916d720..f3dd82405 100644 --- a/backend/tests/baserow/contrib/database/field/test_last_modified_by_field_type.py +++ b/backend/tests/baserow/contrib/database/field/test_last_modified_by_field_type.py @@ -134,7 +134,7 @@ def test_create_rows_last_modified_by(data_fixture): rows = row_handler.create_rows( user=user, table=table, rows_values=[{}, {}], model=model - ) + ).created_rows assert getattr(rows[0], f"field_{field.id}") == user diff --git a/backend/tests/baserow/contrib/database/field/test_last_modified_field_type.py b/backend/tests/baserow/contrib/database/field/test_last_modified_field_type.py index 2434168a1..44cec179e 100644 --- a/backend/tests/baserow/contrib/database/field/test_last_modified_field_type.py +++ b/backend/tests/baserow/contrib/database/field/test_last_modified_field_type.py @@ -255,7 +255,7 @@ def test_last_modified_field_adjacent_row(data_fixture): {}, ], model=table_model, - ) + ).created_rows previous_row = handler.get_adjacent_row( table_model, row_b.id, previous=True, view=grid_view @@ -278,14 +278,16 @@ def test_last_modified_field_can_be_looked_up(data_fixture): row_handler = RowHandler() - row_b1, _ = row_handler.create_rows(user=user, table=table_b, rows_values=[{}, {}]) + row_b1, _ = row_handler.create_rows( + user=user, table=table_b, rows_values=[{}, {}] + ).created_rows with freeze_time("2020-01-01 12:00"): row_a1, _ = row_handler.create_rows( user=user, table=table_a, rows_values=[{link_row.db_column: [row_b1.id]}, {}], - ) + ).created_rows updated_row_b1 = row_handler.get_row(user=user, table=table_b, row_id=row_b1.id) assert getattr(updated_row_b1, lookup_last_modified_field.db_column) == [ diff --git a/backend/tests/baserow/contrib/database/field/test_link_row_field_type.py b/backend/tests/baserow/contrib/database/field/test_link_row_field_type.py index 34c5a28d5..a7dcedf28 100644 --- a/backend/tests/baserow/contrib/database/field/test_link_row_field_type.py +++ b/backend/tests/baserow/contrib/database/field/test_link_row_field_type.py @@ -2067,6 +2067,9 @@ def test_link_row_serialize_metadata_for_row_history( table2_row3.id: {"value": f"unnamed row {table2_row3.id}"}, }, "type": "link_row", + "linked_table_id": field.link_row_table_id, + "linked_field_id": field.link_row_related_field_id, + "primary_value": "unnamed row 1", } # empty values @@ -2085,6 +2088,9 @@ def test_link_row_serialize_metadata_for_row_history( "id": AnyInt(), "linked_rows": {}, "type": "link_row", + "linked_table_id": field.link_row_table_id, + "linked_field_id": field.link_row_related_field_id, + "primary_value": "unnamed row 2", } @@ -2260,11 +2266,15 @@ def test_dont_export_deleted_relations(data_fixture): row_b2 = table_b_model.objects.create() table_a_model = table_a.get_model() - (row_a1,) = RowHandler().force_create_rows( - user, - table_a, - [{link_field.db_column: [row_b1.id, row_b2.id]}], - model=table_a_model, + (row_a1,) = ( + RowHandler() + .force_create_rows( + user, + table_a, + [{link_field.db_column: [row_b1.id, row_b2.id]}], + model=table_a_model, + ) + .created_rows ) assert getattr(row_a1, link_field.db_column).count() == 2 @@ -2336,7 +2346,7 @@ def setup_table_with_single_select_pk(user, data_fixture): for (char, opt) in zip(all_chars, options) ] - rows = RowHandler().force_create_rows(user, table, rows_values) + rows = RowHandler().force_create_rows(user, table, rows_values).created_rows return LinkRowOrderSetup(table, primary_field, rows, comparable_field) @@ -2363,7 +2373,7 @@ def setup_table_with_multiple_select_pk(user, data_fixture): for (i, char) in enumerate(all_chars) ] - rows = RowHandler().force_create_rows(user, table, rows_values) + rows = RowHandler().force_create_rows(user, table, rows_values).created_rows return LinkRowOrderSetup(table, primary_field, rows, comparable_field) @@ -2410,16 +2420,22 @@ def setup_table_with_collaborator_pk(user, data_fixture): ] ) - rows = RowHandler().force_create_rows( - user, - table, - [ - { - f"{primary_field.db_column}": [{"id": usr.id, "name": usr.first_name}], - f"{comparable_field.db_column}": usr.first_name, - } - for usr in users - ], + rows = ( + RowHandler() + .force_create_rows( + user, + table, + [ + { + f"{primary_field.db_column}": [ + {"id": usr.id, "name": usr.first_name} + ], + f"{comparable_field.db_column}": usr.first_name, + } + for usr in users + ], + ) + .created_rows ) return LinkRowOrderSetup(table, primary_field, rows, comparable_field) @@ -2611,10 +2627,14 @@ def test_get_group_by_metadata_in_rows_with_many_to_many_field(data_fixture): user = data_fixture.create_user() table_a, table_b, link_a_to_b = data_fixture.create_two_linked_tables(user=user) - row_b1, row_b2, row_b3 = RowHandler().force_create_rows( - user=user, - table=table_b, - rows_values=[{}, {}, {}], + row_b1, row_b2, row_b3 = ( + RowHandler() + .force_create_rows( + user=user, + table=table_b, + rows_values=[{}, {}, {}], + ) + .created_rows ) RowHandler().force_create_rows( @@ -2727,24 +2747,28 @@ def test_list_rows_with_group_by_link_row_to_multiple_select_field( grid = data_fixture.create_grid_view(table=table_a) data_fixture.create_view_group_by(view=grid, field=link_a_to_b) - row_b1, row_b2 = RowHandler().force_create_rows( - user=user, - table=table_b, - rows_values=[ - { - f"field_{multiple_select_field.id}": [ - select_option_1.id, - select_option_2.id, - select_option_3.id, - ], - }, - { - f"field_{multiple_select_field.id}": [ - select_option_2.id, - select_option_3.id, - ], - }, - ], + row_b1, row_b2 = ( + RowHandler() + .force_create_rows( + user=user, + table=table_b, + rows_values=[ + { + f"field_{multiple_select_field.id}": [ + select_option_1.id, + select_option_2.id, + select_option_3.id, + ], + }, + { + f"field_{multiple_select_field.id}": [ + select_option_2.id, + select_option_3.id, + ], + }, + ], + ) + .created_rows ) RowHandler().force_create_rows( diff --git a/backend/tests/baserow/contrib/database/field/test_long_text_field_type.py b/backend/tests/baserow/contrib/database/field/test_long_text_field_type.py index 9166a54e5..584c86139 100644 --- a/backend/tests/baserow/contrib/database/field/test_long_text_field_type.py +++ b/backend/tests/baserow/contrib/database/field/test_long_text_field_type.py @@ -62,14 +62,18 @@ def test_perm_deleting_rows_delete_rich_text_mentions(data_fixture): table=table, long_text_enable_rich_text=True ) - row_1, row_2, row_3 = RowHandler().create_rows( - user=user, - table=table, - rows_values=[ - {field.db_column: f"Hello @{user.id}!"}, - {field.db_column: f"Ciao @{user.id}!"}, - {field.db_column: f"Hola @{user.id}!"}, - ], + row_1, row_2, row_3 = ( + RowHandler() + .create_rows( + user=user, + table=table, + rows_values=[ + {field.db_column: f"Hello @{user.id}!"}, + {field.db_column: f"Ciao @{user.id}!"}, + {field.db_column: f"Hola @{user.id}!"}, + ], + ) + .created_rows ) mentions = RichTextFieldMention.objects.all() diff --git a/backend/tests/baserow/contrib/database/field/test_lookup_field_type.py b/backend/tests/baserow/contrib/database/field/test_lookup_field_type.py index 40a033e9e..c6606f22d 100644 --- a/backend/tests/baserow/contrib/database/field/test_lookup_field_type.py +++ b/backend/tests/baserow/contrib/database/field/test_lookup_field_type.py @@ -825,19 +825,23 @@ def test_can_modify_row_containing_lookup( link_row_table=table2, ) - a, b = RowHandler().create_rows( - user, - table2, - [ - { - looked_up_field.db_column: f"2021-02-01", - table2_primary_field.db_column: "primary a", - }, - { - looked_up_field.db_column: f"2022-02-03", - table2_primary_field.db_column: "primary b", - }, - ], + a, b = ( + RowHandler() + .create_rows( + user, + table2, + [ + { + looked_up_field.db_column: f"2021-02-01", + table2_primary_field.db_column: "primary a", + }, + { + looked_up_field.db_column: f"2022-02-03", + table2_primary_field.db_column: "primary b", + }, + ], + ) + .created_rows ) table_row = RowHandler().create_row( @@ -1347,20 +1351,24 @@ def test_deleting_table_with_dependants_works( ) table2_model = table2.get_model() - a, b = RowHandler().create_rows( - user, - table2, - rows_values=[ - { - looked_up_field.db_column: "2021-02-01", - table2_primary_field.db_column: "primary a", - }, - { - looked_up_field.db_column: "2022-02-03", - table2_primary_field.db_column: "primary b", - }, - ], - model=table2_model, + a, b = ( + RowHandler() + .create_rows( + user, + table2, + rows_values=[ + { + looked_up_field.db_column: "2021-02-01", + table2_primary_field.db_column: "primary a", + }, + { + looked_up_field.db_column: "2022-02-03", + table2_primary_field.db_column: "primary b", + }, + ], + model=table2_model, + ) + .created_rows ) table_model = table.get_model() @@ -1847,34 +1855,42 @@ def test_can_modify_row_containing_lookup_diamond_dep( starting_row = RowHandler().create_row( user, table1, {primary_table1.db_column: "table1_primary_row_1"} ) - table2_row1, table2_row2 = RowHandler().create_rows( - user, - table2, - [ - { - primary_table2.db_column: "table2_row1", - table2_link_to_table1.db_column: [starting_row.id], - }, - { - primary_table2.db_column: "table2_row2", - table2_link_to_table1.db_column: [starting_row.id], - }, - ], + table2_row1, table2_row2 = ( + RowHandler() + .create_rows( + user, + table2, + [ + { + primary_table2.db_column: "table2_row1", + table2_link_to_table1.db_column: [starting_row.id], + }, + { + primary_table2.db_column: "table2_row2", + table2_link_to_table1.db_column: [starting_row.id], + }, + ], + ) + .created_rows ) - table3_row1, table3_row2 = RowHandler().create_rows( - user, - table3, - [ - { - primary_table3.db_column: "table3_row1", - table3_link_to_table2_a.db_column: [table2_row1.id], - }, - { - primary_table3.db_column: "table3_row2", - table3_link_to_table2_b.db_column: [table2_row2.id], - }, - ], + table3_row1, table3_row2 = ( + RowHandler() + .create_rows( + user, + table3, + [ + { + primary_table3.db_column: "table3_row1", + table3_link_to_table2_a.db_column: [table2_row1.id], + }, + { + primary_table3.db_column: "table3_row2", + table3_link_to_table2_b.db_column: [table2_row2.id], + }, + ], + ) + .created_rows ) FieldHandler().create_field( diff --git a/backend/tests/baserow/contrib/database/field/test_multiple_collaborators_field_type.py b/backend/tests/baserow/contrib/database/field/test_multiple_collaborators_field_type.py index c95be4666..b21dcad92 100644 --- a/backend/tests/baserow/contrib/database/field/test_multiple_collaborators_field_type.py +++ b/backend/tests/baserow/contrib/database/field/test_multiple_collaborators_field_type.py @@ -5,9 +5,11 @@ from django.apps.registry import apps from django.contrib.auth import get_user_model from django.db import connection from django.test.utils import CaptureQueriesContext +from django.urls import reverse import pytest from faker import Faker +from pytest_unordered import unordered from baserow.contrib.database.fields.field_types import MultipleCollaboratorsFieldType from baserow.contrib.database.fields.handler import FieldHandler @@ -847,12 +849,12 @@ def test_multiple_collaborators_field_type_values_can_be_searched(data_fixture): {collaborator_field.db_column: [{"id": luigi.id}]}, {collaborator_field.db_column: [{"id": mario.id}, {"id": luigi.id}]}, ], - ) + ).created_rows rows_a_to_b = row_handler.force_create_rows( user=mario, table=table_a, rows_values=[{link_a_to_b.db_column: [row_b.id]} for row_b in rows_b], - ) + ).created_rows # search in B model_b = table_b.get_model() @@ -929,7 +931,7 @@ def test_multiple_collaborators_formula_field_cache_users_query(data_fixture): {field_id: [{"id": user_2.id}, {"id": user_3.id}]}, ], model=table_model, - ) + ).created_rows # The number of queries should not increas as we export more rows with CaptureQueriesContext(connection) as queries_for_all_others: @@ -937,3 +939,164 @@ def test_multiple_collaborators_formula_field_cache_users_query(data_fixture): export_row(row) assert len(queries_for_all_others.captured_queries) == 0 + + +@pytest.mark.django_db +def test_get_group_by_metadata_in_rows_with_multiple_collaborators_field(data_fixture): + user = data_fixture.create_user(first_name="A") + user_2 = data_fixture.create_user(first_name="B") + workspace = data_fixture.create_workspace(members=[user, user_2]) + database = data_fixture.create_database_application(workspace=workspace) + table = data_fixture.create_database_table(database=database) + text_field = data_fixture.create_text_field( + table=table, order=0, name="Color", text_default="white" + ) + multiple_collaborators_field = data_fixture.create_multiple_collaborators_field( + table=table + ) + + RowHandler().force_create_rows( + user=user, + table=table, + rows_values=[ + { + f"field_{text_field.id}": "Row 1", + f"field_{multiple_collaborators_field.id}": [], + }, + { + f"field_{text_field.id}": "Row 2", + f"field_{multiple_collaborators_field.id}": [], + }, + { + f"field_{text_field.id}": "Row 3", + f"field_{multiple_collaborators_field.id}": [{"id": user.id}], + }, + { + f"field_{text_field.id}": "Row 4", + f"field_{multiple_collaborators_field.id}": [{"id": user.id}], + }, + { + f"field_{text_field.id}": "Row 5", + f"field_{multiple_collaborators_field.id}": [{"id": user_2.id}], + }, + { + f"field_{text_field.id}": "Row 6", + f"field_{multiple_collaborators_field.id}": [{"id": user_2.id}], + }, + { + f"field_{text_field.id}": "Row 7", + f"field_{multiple_collaborators_field.id}": [ + {"id": user.id}, + {"id": user_2.id}, + ], + }, + { + f"field_{text_field.id}": "Row 8", + f"field_{multiple_collaborators_field.id}": [ + {"id": user.id}, + {"id": user_2.id}, + ], + }, + { + f"field_{text_field.id}": "Row 9", + f"field_{multiple_collaborators_field.id}": [ + {"id": user_2.id}, + {"id": user.id}, + ], + }, + ], + ) + + model = table.get_model() + + queryset = model.objects.all().enhance_by_fields() + rows = list(queryset) + + handler = ViewHandler() + counts = handler.get_group_by_metadata_in_rows( + [multiple_collaborators_field], rows, queryset + ) + + # Resolve the queryset, so that we can do a comparison. + for c in counts.keys(): + counts[c] = list(counts[c]) + + assert counts == { + multiple_collaborators_field: unordered( + [ + {"count": 2, f"field_{multiple_collaborators_field.id}": []}, + { + "count": 2, + f"field_{multiple_collaborators_field.id}": [user.id], + }, + { + "count": 2, + f"field_{multiple_collaborators_field.id}": [ + user.id, + user_2.id, + ], + }, + { + "count": 2, + f"field_{multiple_collaborators_field.id}": [user_2.id], + }, + { + "count": 1, + f"field_{multiple_collaborators_field.id}": [ + user_2.id, + user.id, + ], + }, + ] + ) + } + + +@pytest.mark.django_db +def test_list_rows_with_group_by_and_multiple_collaborators_field( + api_client, data_fixture +): + user, token = data_fixture.create_user_and_token( + email="test@test.nl", password="password", first_name="A" + ) + user_2 = data_fixture.create_user(first_name="B") + user_3 = data_fixture.create_user(first_name="C") + workspace = data_fixture.create_workspace(members=[user, user_2, user_3]) + database = data_fixture.create_database_application(workspace=workspace) + table = data_fixture.create_database_table(database=database) + multiple_collaborators_field = data_fixture.create_multiple_collaborators_field( + table=table + ) + grid = data_fixture.create_grid_view(table=table) + data_fixture.create_view_group_by(view=grid, field=multiple_collaborators_field) + + RowHandler().create_row( + user=user, + table=table, + values={ + f"field_{multiple_collaborators_field.id}": [ + {"id": user.id}, + {"id": user_2.id}, + {"id": user_3.id}, + ], + }, + ) + + url = reverse("api:database:views:grid:list", kwargs={"view_id": grid.id}) + response = api_client.get(url, **{"HTTP_AUTHORIZATION": f"JWT {token}"}) + response_json = response.json() + + assert response_json["group_by_metadata"] == { + f"field_{multiple_collaborators_field.id}": unordered( + [ + { + f"field_{multiple_collaborators_field.id}": [ + user.id, + user_2.id, + user_3.id, + ], + "count": 1, + }, + ] + ), + } diff --git a/backend/tests/baserow/contrib/database/field/test_multiple_select_field_type.py b/backend/tests/baserow/contrib/database/field/test_multiple_select_field_type.py index 9c89e176b..39718dab2 100644 --- a/backend/tests/baserow/contrib/database/field/test_multiple_select_field_type.py +++ b/backend/tests/baserow/contrib/database/field/test_multiple_select_field_type.py @@ -450,7 +450,7 @@ def test_multiple_select_field_type_multiple_rows(data_fixture): assert len(row_5_field) == 1 assert getattr(row_5_field[0], "id") == select_options[0].id - _, error_report = row_handler.create_rows( + error_report = row_handler.create_rows( user, table, rows_values=[ @@ -460,7 +460,7 @@ def test_multiple_select_field_type_multiple_rows(data_fixture): {f"field_{field.id}": [99999, "missing"]}, ], generate_error_report=True, - ) + ).errors assert list(error_report.keys()) == [0, 2, 3] assert f"field_{field.id}" in error_report[0] @@ -2300,7 +2300,7 @@ def test_multiple_select_adjacent_row(data_fixture): f"field_{multiple_select_field.id}": [option_a.id], }, ], - ) + ).created_rows base_queryset = ViewHandler().apply_sorting( grid_view, table.get_model().objects.all() @@ -2595,7 +2595,7 @@ def test_get_group_by_metadata_in_rows_with_many_to_many_field(data_fixture): ], }, ], - ) + ).created_rows model = table.get_model() @@ -2792,7 +2792,7 @@ def test_get_group_by_metadata_in_rows_multiple_and_single_select_fields(data_fi ], }, ], - ) + ).created_rows model = table.get_model() @@ -2992,11 +2992,15 @@ def setup_view_for_multiple_select_field(data_fixture, option_values): return {} return {multiple_select_field.db_column: [opt.id for opt in options]} - rows = RowHandler().force_create_rows( - user, - table, - [prep_row([option] if option is not None else None) for option in options], - model=model, + rows = ( + RowHandler() + .force_create_rows( + user, + table, + [prep_row([option] if option is not None else None) for option in options], + model=model, + ) + .created_rows ) fields = { diff --git a/backend/tests/baserow/contrib/database/field/test_number_field_type.py b/backend/tests/baserow/contrib/database/field/test_number_field_type.py index ec00c4691..8f1b7b53e 100644 --- a/backend/tests/baserow/contrib/database/field/test_number_field_type.py +++ b/backend/tests/baserow/contrib/database/field/test_number_field_type.py @@ -274,7 +274,7 @@ def test_number_field_adjacent_row(data_fixture): }, ], model=table_model, - ) + ).created_rows previous_row = handler.get_adjacent_row( table_model, row_b.id, previous=True, view=grid_view diff --git a/backend/tests/baserow/contrib/database/field/test_number_lookup_field_filters.py b/backend/tests/baserow/contrib/database/field/test_number_lookup_field_filters.py index 6ecacffd0..f0edd87be 100644 --- a/backend/tests/baserow/contrib/database/field/test_number_lookup_field_filters.py +++ b/backend/tests/baserow/contrib/database/field/test_number_lookup_field_filters.py @@ -65,7 +65,7 @@ def number_lookup_filter_proc( linked_rows = t.row_handler.create_rows( user=t.user, table=t.other_table, rows_values=dict_rows - ) + ).created_rows # helper to get linked rows by indexes def get_linked_rows(*indexes) -> list[int]: diff --git a/backend/tests/baserow/contrib/database/field/test_rating_field_type.py b/backend/tests/baserow/contrib/database/field/test_rating_field_type.py index ed58c6ef0..80853d5c6 100644 --- a/backend/tests/baserow/contrib/database/field/test_rating_field_type.py +++ b/backend/tests/baserow/contrib/database/field/test_rating_field_type.py @@ -320,7 +320,7 @@ def test_rating_field_adjacent_row(data_fixture): }, ], model=table_model, - ) + ).created_rows previous_row = handler.get_adjacent_row( table_model, row_b.id, previous=True, view=grid_view diff --git a/backend/tests/baserow/contrib/database/field/test_single_select_field_type.py b/backend/tests/baserow/contrib/database/field/test_single_select_field_type.py index eb3897b93..493e5d052 100644 --- a/backend/tests/baserow/contrib/database/field/test_single_select_field_type.py +++ b/backend/tests/baserow/contrib/database/field/test_single_select_field_type.py @@ -1105,7 +1105,7 @@ def test_single_select_adjacent_row(data_fixture): }, ], model=table_model, - ) + ).created_rows previous_row = handler.get_adjacent_row( table_model, row_b.id, previous=True, view=grid_view @@ -1141,7 +1141,7 @@ def test_single_select_adjacent_row_working_with_sorts_and_null_values(data_fixt {}, ], model=table_model, - ) + ).created_rows next_row = handler.get_adjacent_row(table_model, row_a.id, view=grid_view) assert next_row.id == row_b.id @@ -1379,8 +1379,12 @@ def setup_view_for_single_select_field(data_fixture, option_values): def prep_row(option): return {single_select_field.db_column: option.id if option else None} - rows = RowHandler().force_create_rows( - user, table, [prep_row(option) for option in options], model=model + rows = ( + RowHandler() + .force_create_rows( + user, table, [prep_row(option) for option in options], model=model + ) + .created_rows ) fields = { @@ -1458,6 +1462,14 @@ def test_single_select_equal_filter_type_export_import(): assert view_filter_type.set_import_serialized_value("wrong", id_mapping) == "" +@pytest.mark.django_db +def test_single_select_equal_filter_type_export_import_string_keys(): + view_filter_type = view_filter_type_registry.get("single_select_equal") + id_mapping = {"database_field_select_options": {"test": 2}} + assert view_filter_type.set_import_serialized_value("test", id_mapping) == "2" + assert view_filter_type.set_import_serialized_value("test2", id_mapping) == "" + + @pytest.mark.django_db @pytest.mark.parametrize( "field_name", ["single_select", "ref_single_select", "ref_ref_single_select"] @@ -1755,6 +1767,36 @@ def test_single_select_is_any_of_filter_type_export_import(): assert view_filter_type.set_import_serialized_value(None, id_mapping) == "" +@pytest.mark.django_db +def test_single_select_is_any_of_filter_type_export_import_string_keys(): + view_filter_type = view_filter_type_registry.get("single_select_is_any_of") + id_mapping = {"database_field_select_options": {"test": 2, "test2": 3}} + assert view_filter_type.set_import_serialized_value("1", id_mapping) == "" + assert view_filter_type.set_import_serialized_value("", id_mapping) == "" + assert view_filter_type.set_import_serialized_value("test", id_mapping) == "2" + assert ( + view_filter_type.set_import_serialized_value("test,test2", id_mapping) == "2,3" + ) + assert ( + view_filter_type.set_import_serialized_value("test,invalid", id_mapping) == "2" + ) + + +@pytest.mark.django_db +def test_single_multiple_select_has_type_export_import_string_keys(): + view_filter_type = view_filter_type_registry.get("multiple_select_has") + id_mapping = {"database_field_select_options": {"test": 2, "test2": 3}} + assert view_filter_type.set_import_serialized_value("1", id_mapping) == "" + assert view_filter_type.set_import_serialized_value("", id_mapping) == "" + assert view_filter_type.set_import_serialized_value("test", id_mapping) == "2" + assert ( + view_filter_type.set_import_serialized_value("test,test2", id_mapping) == "2,3" + ) + assert ( + view_filter_type.set_import_serialized_value("test,invalid", id_mapping) == "2" + ) + + @pytest.mark.django_db @pytest.mark.parametrize( "field_name", ["single_select", "ref_single_select", "ref_ref_single_select"] diff --git a/backend/tests/baserow/contrib/database/field/test_uuid_field_type.py b/backend/tests/baserow/contrib/database/field/test_uuid_field_type.py index 163019734..45c7589b9 100644 --- a/backend/tests/baserow/contrib/database/field/test_uuid_field_type.py +++ b/backend/tests/baserow/contrib/database/field/test_uuid_field_type.py @@ -156,7 +156,7 @@ def test_create_uuid_row_in_bulk(data_fixture): rows = row_handler.create_rows( user=user, table=table, rows_values=[{}, {}], model=model - ) + ).created_rows assert isinstance(rows[0].uuid, UUID) assert isinstance(rows[1].uuid, UUID) diff --git a/backend/tests/baserow/contrib/database/file_import/test_file_import_tasks.py b/backend/tests/baserow/contrib/database/file_import/test_file_import_tasks.py index 2002e15fd..bdcc29d0c 100644 --- a/backend/tests/baserow/contrib/database/file_import/test_file_import_tasks.py +++ b/backend/tests/baserow/contrib/database/file_import/test_file_import_tasks.py @@ -9,6 +9,8 @@ from pyinstrument import Profiler from baserow.contrib.database.fields.dependencies.handler import FieldDependencyHandler from baserow.contrib.database.fields.exceptions import ( + FieldNotInTable, + IncompatibleField, InvalidBaserowFieldName, MaxFieldLimitExceeded, MaxFieldNameLengthExceeded, @@ -16,7 +18,10 @@ from baserow.contrib.database.fields.exceptions import ( ) from baserow.contrib.database.fields.field_cache import FieldCache from baserow.contrib.database.fields.models import SelectOption, TextField -from baserow.contrib.database.rows.exceptions import ReportMaxErrorCountExceeded +from baserow.contrib.database.rows.exceptions import ( + InvalidRowLength, + ReportMaxErrorCountExceeded, +) from baserow.contrib.database.table.exceptions import ( InitialTableDataDuplicateName, InitialTableDataLimitExceeded, @@ -43,23 +48,25 @@ def test_run_file_import_task(data_fixture, patch_filefield_storage): run_async_job(job.id) with patch_filefield_storage(), pytest.raises(InvalidInitialTableData): - job = data_fixture.create_file_import_job(data=[]) + job = data_fixture.create_file_import_job(data={"data": []}) run_async_job(job.id) with patch_filefield_storage(), pytest.raises(InvalidInitialTableData): - job = data_fixture.create_file_import_job(data=[[]]) + job = data_fixture.create_file_import_job(data={"data": [[]]}) run_async_job(job.id) with override_settings( INITIAL_TABLE_DATA_LIMIT=2 ), patch_filefield_storage(), pytest.raises(InitialTableDataLimitExceeded): - job = data_fixture.create_file_import_job(data=[[], [], []]) + job = data_fixture.create_file_import_job(data={"data": [[], [], []]}) run_async_job(job.id) with override_settings(MAX_FIELD_LIMIT=2), patch_filefield_storage(), pytest.raises( MaxFieldLimitExceeded ): - job = data_fixture.create_file_import_job(data=[["fields"] * 3, ["rows"] * 3]) + job = data_fixture.create_file_import_job( + data={"data": [["fields"] * 3, ["rows"] * 3]} + ) run_async_job(job.id) too_long_field_name = "x" * 256 @@ -73,35 +80,37 @@ def test_run_file_import_task(data_fixture, patch_filefield_storage): ] with patch_filefield_storage(), pytest.raises(MaxFieldNameLengthExceeded): - job = data_fixture.create_file_import_job(data=data) + job = data_fixture.create_file_import_job(data={"data": data}) run_async_job(job.id) data[0][0] = field_name_with_ok_length with patch_filefield_storage(): - job = data_fixture.create_file_import_job(data=data) + job = data_fixture.create_file_import_job(data={"data": data}) run_async_job(job.id) with patch_filefield_storage(), pytest.raises(ReservedBaserowFieldNameException): - job = data_fixture.create_file_import_job(data=[["id"]]) + job = data_fixture.create_file_import_job(data={"data": [["id"]]}) run_async_job(job.id) with patch_filefield_storage(), pytest.raises(InitialTableDataDuplicateName): - job = data_fixture.create_file_import_job(data=[["test", "test"]]) + job = data_fixture.create_file_import_job(data={"data": [["test", "test"]]}) run_async_job(job.id) with patch_filefield_storage(), pytest.raises(InvalidBaserowFieldName): - job = data_fixture.create_file_import_job(data=[[" "]]) + job = data_fixture.create_file_import_job(data={"data": [[" "]]}) run_async_job(job.id) # Basic use with patch_filefield_storage(): job = data_fixture.create_file_import_job( - data=[ - ["A", "B", "C", "D"], - ["1-1", "1-2", "1-3", "1-4", "1-5"], - ["2-1", "2-2", "2-3"], - ["3-1", "3-2"], - ] + data={ + "data": [ + ["A", "B", "C", "D"], + ["1-1", "1-2", "1-3", "1-4", "1-5"], + ["2-1", "2-2", "2-3"], + ["3-1", "3-2"], + ] + } ) run_async_job(job.id) @@ -130,11 +139,13 @@ def test_run_file_import_task(data_fixture, patch_filefield_storage): # Without first row header with patch_filefield_storage(): job = data_fixture.create_file_import_job( - data=[ - ["1-1"], - ["2-1", "2-2", "2-3"], - ["3-1", "3-2"], - ], + data={ + "data": [ + ["1-1"], + ["2-1", "2-2", "2-3"], + ["3-1", "3-2"], + ] + }, first_row_header=False, ) run_async_job(job.id) @@ -151,17 +162,19 @@ def test_run_file_import_task(data_fixture, patch_filefield_storage): # Robust to strange field names with patch_filefield_storage(): job = data_fixture.create_file_import_job( - data=[ - [ - "TEst 1", - "10.00", - 'Falsea"""', - 'a"a"a"a"a,', - "a", - 1.3, - "/w. r/awr", - ], - ], + data={ + "data": [ + [ + "TEst 1", + "10.00", + 'Falsea"""', + 'a"a"a"a"a,', + "a", + 1.3, + "/w. r/awr", + ], + ] + }, ) run_async_job(job.id) @@ -196,7 +209,7 @@ def test_run_file_import_task(data_fixture, patch_filefield_storage): model = table.get_model() # Import data to an existing table - data = [["baz", 3, -3, "foo", None], ["bob", -4, 2.5, "bar", "a" * 255]] + data = {"data": [["baz", 3, -3, "foo", None], ["bob", -4, 2.5, "bar", "a" * 255]]} with patch_filefield_storage(): job = data_fixture.create_file_import_job( @@ -212,13 +225,15 @@ def test_run_file_import_task(data_fixture, patch_filefield_storage): assert len(rows) == 2 # Import data with different length - data = [ - ["good", "test", "test", "Anything"], - [], - [None, None], - ["good", 2.5, None, "Anything"], - ["good", 2.5, None, "Anything", "too much", "values"], - ] + data = { + "data": [ + ["good", "test", "test", "Anything"], + [], + [None, None], + ["good", 2.5, None, "Anything"], + ["good", 2.5, None, "Anything", "too much", "values"], + ] + } with patch_filefield_storage(): job = data_fixture.create_file_import_job( @@ -331,6 +346,7 @@ def test_run_file_import_task_for_special_fields(data_fixture, patch_filefield_s [], ], ] + data = {"data": data} with patch_filefield_storage(): job = data_fixture.create_file_import_job( @@ -397,6 +413,7 @@ def test_run_file_import_task_for_special_fields(data_fixture, patch_filefield_s "bug", ], ] + data = {"data": data} with patch_filefield_storage(): job = data_fixture.create_file_import_job( @@ -454,8 +471,8 @@ def test_run_file_import_test_chunk(data_fixture, patch_filefield_storage): table, _, _ = data_fixture.build_table( columns=[ - (f"col1", "text"), - (f"col2", "number"), + ("col1", "text"), + ("col2", "number"), ], rows=[], user=user, @@ -483,11 +500,16 @@ def test_run_file_import_test_chunk(data_fixture, patch_filefield_storage): data[1024] = ["test", 2, 99999] data[1027] = ["test", "bad", single_select_option_2.id] + print("data", len(data)) + data = {"data": data} + with patch_filefield_storage(): job = data_fixture.create_file_import_job(table=table, data=data, user=user) run_async_job(job.id) job.refresh_from_db() + assert job.finished + assert not job.failed model = job.table.get_model() assert model.objects.count() == row_count - 5 @@ -509,8 +531,8 @@ def test_run_file_import_limit(data_fixture, patch_filefield_storage): table, _, _ = data_fixture.build_table( columns=[ - (f"col1", "text"), - (f"col2", "number"), + ("col1", "text"), + ("col2", "number"), ], rows=[], user=user, @@ -529,7 +551,9 @@ def test_run_file_import_limit(data_fixture, patch_filefield_storage): data += [["test", "bad", single_select_option_1.id]] * (max_error + 5) with patch_filefield_storage(): - job = data_fixture.create_file_import_job(table=table, data=data, user=user) + job = data_fixture.create_file_import_job( + table=table, data={"data": data}, user=user + ) with pytest.raises(ReportMaxErrorCountExceeded): run_async_job(job.id) @@ -550,7 +574,9 @@ def test_run_file_import_limit(data_fixture, patch_filefield_storage): data += [["test", 1, 0]] * (max_error + 5) with patch_filefield_storage(): - job = data_fixture.create_file_import_job(table=table, data=data, user=user) + job = data_fixture.create_file_import_job( + table=table, data={"data": data}, user=user + ) with pytest.raises(ReportMaxErrorCountExceeded): run_async_job(job.id) @@ -646,3 +672,315 @@ def test_cleanup_file_import_job(data_fixture, settings, patch_filefield_storage job3.refresh_from_db() assert job3.state == JOB_FINISHED assert job3.updated_on == time_before_soft_limit + + +@pytest.mark.django_db(transaction=True) +def test_run_file_import_task_with_upsert_fields_not_in_table( + data_fixture, patch_filefield_storage +): + user = data_fixture.create_user() + database = data_fixture.create_database_application(user=user) + table = data_fixture.create_database_table(user=user, database=database) + data_fixture.create_text_field(table=table, order=1, name="text 1") + init_data = [["foo"], ["bar"]] + + with pytest.raises(FieldNotInTable): + with patch_filefield_storage(): + job = data_fixture.create_file_import_job( + data={ + "data": init_data, + "configuration": {"upsert_fields": [100, 120]}, + }, + table=table, + user=user, + ) + run_async_job(job.id) + + model = table.get_model() + assert len(model.objects.all()) == 0 + + +@pytest.mark.django_db(transaction=True) +def test_run_file_import_task_with_upsert_fields_not_usable( + data_fixture, patch_filefield_storage +): + user = data_fixture.create_user() + database = data_fixture.create_database_application(user=user) + table = data_fixture.create_database_table(user=user, database=database) + f1 = data_fixture.create_text_field(table=table, order=1, name="text 1") + f2 = data_fixture.create_formula_field(table=table, order=2, name="formula field") + + model = table.get_model() + # dummy data just to ensure later on the table wasn't modified. + init_data = [ + [ + "aa-", + ], + [ + "aa-", + ], + ] + + with patch_filefield_storage(): + job = data_fixture.create_file_import_job( + data={"data": init_data}, + table=table, + user=user, + ) + run_async_job(job.id) + + job.refresh_from_db() + + assert job.state == JOB_FINISHED + assert job.progress_percentage == 100 + + with pytest.raises(IncompatibleField): + with patch_filefield_storage(): + job = data_fixture.create_file_import_job( + data={ + "data": [["bbb"], ["ccc"], ["aaa"]], + "configuration": { + # we're trying to use formula field, which is not supported + "upsert_fields": [f2.id], + "upsert_values": [["aaa"], ["aaa"], ["aaa"]], + }, + }, + table=table, + user=user, + first_row_header=False, + ) + run_async_job(job.id) + + rows = model.objects.all() + assert len(rows) == 2 + assert all([getattr(r, f1.db_column) == "aa-" for r in rows]) + + +@pytest.mark.django_db(transaction=True) +def test_run_file_import_task_with_upsert_fields_invalid_length( + data_fixture, patch_filefield_storage +): + user = data_fixture.create_user() + database = data_fixture.create_database_application(user=user) + table = data_fixture.create_database_table(user=user, database=database) + f1 = data_fixture.create_text_field(table=table, order=1, name="text 1") + + model = table.get_model() + + with pytest.raises(InvalidRowLength): + with patch_filefield_storage(): + job = data_fixture.create_file_import_job( + data={ + "data": [["bbb"], ["ccc"], ["aaa"]], + "configuration": { + # fields and values have different lengths + "upsert_fields": [f1.id], + "upsert_values": [ + ["aaa", "bbb"], + ], + }, + }, + table=table, + user=user, + first_row_header=False, + ) + run_async_job(job.id) + job.refresh_from_db() + assert job.failed + + rows = model.objects.all() + assert len(rows) == 0 + + +@pytest.mark.django_db(transaction=True) +def test_run_file_import_task_with_upsert(data_fixture, patch_filefield_storage): + user = data_fixture.create_user() + database = data_fixture.create_database_application(user=user) + table = data_fixture.create_database_table(user=user, database=database) + + f1 = data_fixture.create_text_field(table=table, order=1, name="text 1") + f2 = data_fixture.create_number_field( + table=table, order=2, name="number 1", number_negative=True + ) + f3 = data_fixture.create_date_field(user=user, table=table, order=3, name="date 1") + f4 = data_fixture.create_date_field( + user=user, table=table, order=4, name="datetime 1", date_include_time=True + ) + f5 = data_fixture.create_number_field( + table=table, + order=5, + name="value field", + number_negative=True, + number_decimal_places=10, + ) + f6 = data_fixture.create_text_field(table=table, order=6, name="text 2") + + model = table.get_model() + + init_data = [ + [ + "aaa", + 1, + "2024-01-01", + "2024-01-01T01:02:03.004+01:00", + 0.1, + "aaa-1-1", + ], + [ + "aab", + 1, + "2024-01-01", + "2024-01-01T01:02:03", + 0.2, + "aab-1-1", + ], + [ + "aac", + 1, + "2024-01-01", + "2024-01-01T01:02:03", + 0.2, + "aac-1-1", + ], + [ + None, + None, + None, + None, + None, + None, + ], + [ + None, + None, + None, + None, + None, + None, + ], + [ + "aac", + 1, + None, + "2024-01-01T01:02:03", + 0.2, + "aac-1-2", + ], + [ + "aab", + 1, + "2024-01-01", + None, + 0.2, + "aac-1-2", + ], + [ + "aaa", + 1, + "2024-01-01", + "2024-01-01T01:02:03.004+01:00", + 0.1, + "aaa-1-1", + ], + [ + "aaa", + 1, + "2024-01-02", + "2024-01-01 01:02:03.004 +01:00", + 0.1, + "aaa-1-1", + ], + ] + + with patch_filefield_storage(): + job = data_fixture.create_file_import_job( + data={"data": init_data}, + table=table, + user=user, + ) + run_async_job(job.id) + + job.refresh_from_db() + + assert job.state == JOB_FINISHED + assert job.progress_percentage == 100 + + rows = model.objects.all() + + assert len(rows) == len(init_data) + + update_with_duplicates = [ + # first three are duplicates + [ + "aab", + 1, + "2024-01-01", + "2024-01-01T01:02:03", + 0.3, + "aab-1-1-modified", + ], + [ + "aaa", + 1, + "2024-01-01", + "2024-01-01T01:02:03.004+01:00", + 0.2, + "aaa-1-1-modified", + ], + [ + "aab", + 1, + "2024-01-01", + None, + 0.33333, + "aac-1-2-modified", + ], + # insert + [ + "aab", + 1, + None, + None, + 125, + "aab-1-3-new", + ], + [ + "aab", + 1, + "2024-01-01", + None, + 0.33333, + "aab-1-4-new", + ], + ] + # Without first row header + with patch_filefield_storage(): + job = data_fixture.create_file_import_job( + data={ + "data": update_with_duplicates, + "configuration": { + "upsert_fields": [f1.id, f2.id, f3.id, f4.id], + "upsert_values": [i[:4] for i in update_with_duplicates], + }, + }, + table=table, + user=user, + first_row_header=False, + ) + run_async_job(job.id) + + job.refresh_from_db() + assert job.finished + assert not job.failed + + rows = list(model.objects.all()) + + assert len(rows) == len(init_data) + 2 + + last = rows[-1] + assert getattr(last, f1.db_column) == "aab" + assert getattr(last, f6.db_column) == "aab-1-4-new" + + last = rows[-2] + assert getattr(last, f1.db_column) == "aab" + assert getattr(last, f6.db_column) == "aab-1-3-new" diff --git a/backend/tests/baserow/contrib/database/formula/test_baserow_formula_results.py b/backend/tests/baserow/contrib/database/formula/test_baserow_formula_results.py index 168590eed..dd0da762a 100644 --- a/backend/tests/baserow/contrib/database/formula/test_baserow_formula_results.py +++ b/backend/tests/baserow/contrib/database/formula/test_baserow_formula_results.py @@ -1751,18 +1751,22 @@ def test_can_filter_in_aggregated_formulas(data_fixture): name="autonr", ) - rows_b = RowHandler().create_rows( - user, - table_b, - [ - {boolean_field.db_column: True}, - {}, - {boolean_field.db_column: True}, - {}, - {}, - {boolean_field.db_column: True}, - {}, - ], + rows_b = ( + RowHandler() + .create_rows( + user, + table_b, + [ + {boolean_field.db_column: True}, + {}, + {boolean_field.db_column: True}, + {}, + {}, + {boolean_field.db_column: True}, + {}, + ], + ) + .created_rows ) formula_field = data_fixture.create_formula_field( @@ -1771,14 +1775,18 @@ def test_can_filter_in_aggregated_formulas(data_fixture): formula=f"max(filter(lookup('link', 'autonr'), lookup('link', 'check')))", ) - row_a1, row_a2, row_a3 = RowHandler().create_rows( - user, - table_a, - [ - {link_field.db_column: [rows_b[0].id, rows_b[1].id]}, - {link_field.db_column: [rows_b[2].id, rows_b[3].id, rows_b[4].id]}, - {link_field.db_column: [rows_b[4].id, rows_b[5].id, rows_b[6].id]}, - ], + row_a1, row_a2, row_a3 = ( + RowHandler() + .create_rows( + user, + table_a, + [ + {link_field.db_column: [rows_b[0].id, rows_b[1].id]}, + {link_field.db_column: [rows_b[2].id, rows_b[3].id, rows_b[4].id]}, + {link_field.db_column: [rows_b[4].id, rows_b[5].id, rows_b[6].id]}, + ], + ) + .created_rows ) # autonr of row_b[0], because it's the only one with check=True @@ -1800,27 +1808,31 @@ def test_can_filter_in_aggregated_formulas_with_multipleselects(data_fixture): option_c = data_fixture.create_select_option(field=multiple_select_field, value="c") option_d = data_fixture.create_select_option(field=multiple_select_field, value="d") - rows_b = RowHandler().create_rows( - user, - table_b, - [ - { - boolean_field.db_column: True, - multiple_select_field.db_column: [option_a.id, option_b.id], - }, - {multiple_select_field.db_column: [option_c.id]}, - { - boolean_field.db_column: True, - multiple_select_field.db_column: [option_d.id], - }, - {multiple_select_field.db_column: [option_a.id, option_b.id]}, - {multiple_select_field.db_column: [option_c.id, option_d.id]}, - { - boolean_field.db_column: True, - multiple_select_field.db_column: [option_b.id], - }, - {}, - ], + rows_b = ( + RowHandler() + .create_rows( + user, + table_b, + [ + { + boolean_field.db_column: True, + multiple_select_field.db_column: [option_a.id, option_b.id], + }, + {multiple_select_field.db_column: [option_c.id]}, + { + boolean_field.db_column: True, + multiple_select_field.db_column: [option_d.id], + }, + {multiple_select_field.db_column: [option_a.id, option_b.id]}, + {multiple_select_field.db_column: [option_c.id, option_d.id]}, + { + boolean_field.db_column: True, + multiple_select_field.db_column: [option_b.id], + }, + {}, + ], + ) + .created_rows ) formula_field = data_fixture.create_formula_field( @@ -1829,14 +1841,18 @@ def test_can_filter_in_aggregated_formulas_with_multipleselects(data_fixture): formula=f"count(filter(lookup('link', 'mm'), lookup('link', 'check')))", ) - row_a1, row_a2, row_a3 = RowHandler().create_rows( - user, - table_a, - [ - {link_field.db_column: [rows_b[0].id, rows_b[1].id]}, - {link_field.db_column: [rows_b[2].id, rows_b[3].id, rows_b[4].id]}, - {link_field.db_column: [rows_b[4].id, rows_b[5].id, rows_b[6].id]}, - ], + row_a1, row_a2, row_a3 = ( + RowHandler() + .create_rows( + user, + table_a, + [ + {link_field.db_column: [rows_b[0].id, rows_b[1].id]}, + {link_field.db_column: [rows_b[2].id, rows_b[3].id, rows_b[4].id]}, + {link_field.db_column: [rows_b[4].id, rows_b[5].id, rows_b[6].id]}, + ], + ) + .created_rows ) # autonr of row_b[0], because it's the only one with check=True @@ -1869,19 +1885,23 @@ def test_formulas_with_lookup_url_field_type(data_fixture): table=linked_table, ) - linked_row_1, linked_row_2 = RowHandler().create_rows( - user, - linked_table, - [ - { - linked_table_primary_field.db_column: "URL #1", - linked_table_url_field.db_column: "https://baserow.io/1", - }, - { - linked_table_primary_field.db_column: "URL #2", - linked_table_url_field.db_column: "https://baserow.io/2", - }, - ], + linked_row_1, linked_row_2 = ( + RowHandler() + .create_rows( + user, + linked_table, + [ + { + linked_table_primary_field.db_column: "URL #1", + linked_table_url_field.db_column: "https://baserow.io/1", + }, + { + linked_table_primary_field.db_column: "URL #2", + linked_table_url_field.db_column: "https://baserow.io/2", + }, + ], + ) + .created_rows ) link_field = FieldHandler().create_field( @@ -1981,8 +2001,10 @@ def test_lookup_arrays(data_fixture): rows=[["b1"], ["b2"]], fields=[table_b_primary_field], ) - (row_a1,) = RowHandler().create_rows( - user, table_a, [{link_field.db_column: [row_b1.id, row_b2.id]}] + (row_a1,) = ( + RowHandler() + .create_rows(user, table_a, [{link_field.db_column: [row_b1.id, row_b2.id]}]) + .created_rows ) lookup_field = FieldHandler().create_field( user, @@ -2038,17 +2060,21 @@ def test_formulas_with_lookup_to_uuid_primary_field(data_fixture): table=linked_table, ) - linked_row_1, linked_row_2 = RowHandler().create_rows( - user, - linked_table, - [ - { - linked_table_text_field.db_column: "Linked row #1", - }, - { - linked_table_text_field.db_column: "Linked row #2", - }, - ], + linked_row_1, linked_row_2 = ( + RowHandler() + .create_rows( + user, + linked_table, + [ + { + linked_table_text_field.db_column: "Linked row #1", + }, + { + linked_table_text_field.db_column: "Linked row #2", + }, + ], + ) + .created_rows ) link_field = FieldHandler().create_field( diff --git a/backend/tests/baserow/contrib/database/rows/test_row_history.py b/backend/tests/baserow/contrib/database/rows/test_row_history.py index c8b03dd83..36131bba8 100644 --- a/backend/tests/baserow/contrib/database/rows/test_row_history.py +++ b/backend/tests/baserow/contrib/database/rows/test_row_history.py @@ -1,4 +1,5 @@ from datetime import datetime, timezone +from unittest.mock import patch import pytest from freezegun import freeze_time @@ -28,8 +29,8 @@ def test_update_rows_insert_multiple_entries_in_row_history(data_fixture): row_handler = RowHandler() - row_one = row_handler.create_row(user, table, {name_field.id: "Original 1"}) - row_two = row_handler.create_row(user, table, {name_field.id: "Original 2"}) + row_one = row_handler.force_create_row(user, table, {name_field.id: "Original 1"}) + row_two = row_handler.force_create_row(user, table, {name_field.id: "Original 2"}) with freeze_time("2021-01-01 12:00"): action_type_registry.get_by_type(UpdateRowsActionType).do( @@ -107,7 +108,7 @@ def test_history_handler_only_save_changed_fields(data_fixture): row_handler = RowHandler() - row = row_handler.create_row(user, table, {name_field.id: "Original 1"}) + row = row_handler.force_create_row(user, table, {name_field.id: "Original 1"}) with freeze_time("2021-01-01 12:00"): action_type_registry.get_by_type(UpdateRowsActionType).do( @@ -172,8 +173,8 @@ def test_update_rows_action_doesnt_insert_entries_if_row_doesnt_change(data_fixt row_handler = RowHandler() - row_one = row_handler.create_row(user, table, {name_field.id: "Original 1"}) - row_two = row_handler.create_row(user, table, {name_field.id: "Original 2"}) + row_one = row_handler.force_create_row(user, table, {name_field.id: "Original 1"}) + row_two = row_handler.force_create_row(user, table, {name_field.id: "Original 2"}) with freeze_time("2021-01-01 12:00"): action_type_registry.get_by_type(UpdateRowsActionType).do( @@ -362,3 +363,466 @@ def test_row_history_not_recorded_with_retention_zero_days(settings, data_fixtur ) assert RowHistory.objects.count() == 1 + + +@pytest.mark.django_db +@pytest.mark.row_history +def test_update_rows_insert_entries_in_linked_rows_history(data_fixture): + user = data_fixture.create_user() + database = data_fixture.create_database_application(user=user) + table_a, table_b, link_a_to_b = data_fixture.create_two_linked_tables( + user=user, database=database + ) + primary_a = table_a.get_primary_field() + primary_b = table_b.get_primary_field() + link_b_to_a = link_a_to_b.link_row_related_field + + row_handler = RowHandler() + + row_b1, row_b2 = row_handler.force_create_rows( + user, table_b, [{primary_b.db_column: "b1"}, {primary_b.db_column: "b2"}] + ).created_rows + row_a1 = row_handler.force_create_row(user, table_a, {primary_a.id: "a1"}) + + with freeze_time("2021-01-01 12:00"): + action_type_registry.get_by_type(UpdateRowsActionType).do( + user, + table_a, + [ + {"id": row_a1.id, link_a_to_b.db_column: [row_b1.id, row_b2.id]}, + ], + ) + assert RowHistory.objects.count() == 3 + + history_entries = RowHistory.objects.order_by("table_id", "row_id").values( + "user_id", + "user_name", + "table_id", + "row_id", + "action_timestamp", + "action_type", + "before_values", + "after_values", + "fields_metadata", + ) + + expected_entries = [ + { + "user_id": user.id, + "user_name": user.first_name, + "table_id": table_a.id, + "row_id": 1, + "action_timestamp": datetime(2021, 1, 1, 12, 0, tzinfo=timezone.utc), + "action_type": "update_rows", + "before_values": {link_a_to_b.db_column: []}, + "after_values": {link_a_to_b.db_column: [1, 2]}, + "fields_metadata": { + link_a_to_b.db_column: { + "id": link_a_to_b.id, + "type": "link_row", + "linked_rows": {"1": {"value": "b1"}, "2": {"value": "b2"}}, + "primary_value": "a1", + "linked_field_id": link_b_to_a.id, + "linked_table_id": table_b.id, + } + }, + }, + { + "user_id": user.id, + "user_name": user.first_name, + "table_id": table_b.id, + "row_id": 1, + "action_timestamp": datetime(2021, 1, 1, 12, 0, tzinfo=timezone.utc), + "action_type": "update_rows", + "before_values": {link_b_to_a.db_column: []}, + "after_values": {link_b_to_a.db_column: [1]}, + "fields_metadata": { + link_b_to_a.db_column: { + "id": link_b_to_a.id, + "type": "link_row", + "linked_rows": {"1": {"value": "a1"}}, + } + }, + }, + { + "user_id": user.id, + "user_name": user.first_name, + "table_id": table_b.id, + "row_id": 2, + "action_timestamp": datetime(2021, 1, 1, 12, 0, tzinfo=timezone.utc), + "action_type": "update_rows", + "before_values": {link_b_to_a.db_column: []}, + "after_values": {link_b_to_a.db_column: [1]}, + "fields_metadata": { + link_b_to_a.db_column: { + "id": link_b_to_a.id, + "type": "link_row", + "linked_rows": {"1": {"value": "a1"}}, + } + }, + }, + ] + + assert list(history_entries) == expected_entries + + # Now remove one link + + with freeze_time("2021-01-01 12:30"): + action_type_registry.get_by_type(UpdateRowsActionType).do( + user, + table_a, + [ + {"id": row_a1.id, link_a_to_b.db_column: [row_b2.id]}, + ], + ) + + history_entries = RowHistory.objects.order_by( + "-action_timestamp", "table_id", "row_id" + ).values( + "user_id", + "user_name", + "table_id", + "row_id", + "action_timestamp", + "action_type", + "before_values", + "after_values", + "fields_metadata", + ) + assert RowHistory.objects.count() == 5 + + last_entries = list(history_entries)[:2] + expected_entries = [ + { + "user_id": user.id, + "user_name": user.first_name, + "table_id": table_a.id, + "row_id": 1, + "action_timestamp": datetime(2021, 1, 1, 12, 30, tzinfo=timezone.utc), + "action_type": "update_rows", + "before_values": {link_a_to_b.db_column: [1, 2]}, + "after_values": {link_a_to_b.db_column: [2]}, + "fields_metadata": { + link_a_to_b.db_column: { + "id": link_a_to_b.id, + "type": "link_row", + "linked_rows": {"1": {"value": "b1"}, "2": {"value": "b2"}}, + "primary_value": "a1", + "linked_field_id": link_b_to_a.id, + "linked_table_id": table_b.id, + } + }, + }, + { + "user_id": user.id, + "user_name": user.first_name, + "table_id": table_b.id, + "row_id": 1, + "action_timestamp": datetime(2021, 1, 1, 12, 30, tzinfo=timezone.utc), + "action_type": "update_rows", + "before_values": {link_b_to_a.db_column: [1]}, + "after_values": {link_b_to_a.db_column: []}, + "fields_metadata": { + link_b_to_a.db_column: { + "id": link_b_to_a.id, + "type": "link_row", + "linked_rows": {"1": {"value": "a1"}}, + } + }, + }, + ] + + assert last_entries == expected_entries + + +@pytest.mark.django_db +@pytest.mark.row_history +def test_update_rows_dont_insert_entries_in_linked_rows_history_without_related_field( + data_fixture, +): + user = data_fixture.create_user() + database = data_fixture.create_database_application(user=user) + table_a, table_b, link_a_to_b = data_fixture.create_two_linked_tables( + user=user, database=database, has_related_field=False + ) + primary_a = table_a.get_primary_field() + primary_b = table_b.get_primary_field() + + row_handler = RowHandler() + + row_b1, row_b2 = row_handler.force_create_rows( + user, table_b, [{primary_b.db_column: "b1"}, {primary_b.db_column: "b2"}] + ).created_rows + row_a1 = row_handler.force_create_row(user, table_a, {primary_a.id: "a1"}) + + with freeze_time("2021-01-01 12:00"): + action_type_registry.get_by_type(UpdateRowsActionType).do( + user, + table_a, + [ + {"id": row_a1.id, link_a_to_b.db_column: [row_b1.id, row_b2.id]}, + ], + ) + assert RowHistory.objects.count() == 1 + + history_entries = RowHistory.objects.values( + "user_id", + "user_name", + "table_id", + "row_id", + "action_timestamp", + "action_type", + "before_values", + "after_values", + "fields_metadata", + ) + + expected_entries = [ + { + "user_id": user.id, + "user_name": user.first_name, + "table_id": table_a.id, + "row_id": 1, + "action_timestamp": datetime(2021, 1, 1, 12, 0, tzinfo=timezone.utc), + "action_type": "update_rows", + "before_values": {link_a_to_b.db_column: []}, + "after_values": {link_a_to_b.db_column: [1, 2]}, + "fields_metadata": { + link_a_to_b.db_column: { + "id": link_a_to_b.id, + "type": "link_row", + "linked_rows": {"1": {"value": "b1"}, "2": {"value": "b2"}}, + "primary_value": "a1", + "linked_field_id": None, + "linked_table_id": table_b.id, + } + }, + } + ] + assert list(history_entries) == expected_entries + + +@pytest.mark.django_db +@pytest.mark.row_history +def test_update_rows_insert_entries_in_linked_rows_history_in_multiple_tables( + data_fixture, +): + user = data_fixture.create_user() + database = data_fixture.create_database_application(user=user) + table_a, table_b, link_a_to_b = data_fixture.create_two_linked_tables( + user=user, database=database + ) + table_c, _, link_c_to_a = data_fixture.create_two_linked_tables( + user=user, database=database, table_b=table_a + ) + primary_a = table_a.get_primary_field() + primary_b = table_b.get_primary_field() + primary_c = table_c.get_primary_field() + link_b_to_a = link_a_to_b.link_row_related_field + link_a_to_c = link_c_to_a.link_row_related_field + + row_handler = RowHandler() + + row_b1, row_b2 = row_handler.force_create_rows( + user, table_b, [{primary_b.db_column: "b1"}, {primary_b.db_column: "b2"}] + ).created_rows + row_c1, row_c2 = row_handler.force_create_rows( + user, table_c, [{primary_c.db_column: "c1"}, {primary_c.db_column: "c2"}] + ).created_rows + row_a1, row_a2 = row_handler.force_create_rows( + user, table_a, [{primary_a.db_column: "a1"}, {primary_a.db_column: "a2"}] + ).created_rows + + with freeze_time("2021-01-01 12:00"), patch( + "baserow.contrib.database.rows.signals.rows_history_updated.send" + ) as mock_signal: + action_type_registry.get_by_type(UpdateRowsActionType).do( + user, + table_a, + [ + { + "id": row_a1.id, + link_a_to_b.db_column: [row_b1.id, row_b2.id], + link_a_to_c.db_column: [row_c1.id, row_c2.id], + }, + { + "id": row_a2.id, + link_a_to_b.db_column: [row_b1.id, row_b2.id], + link_a_to_c.db_column: [row_c1.id, row_c2.id], + }, + ], + ) + + assert RowHistory.objects.count() == 6 + + history_entries = RowHistory.objects.order_by("table_id", "row_id").values( + "user_id", + "user_name", + "table_id", + "row_id", + "action_timestamp", + "action_type", + "before_values", + "after_values", + "fields_metadata", + ) + + # Signal should be called once per table with row history entries for that table + entry_ids = [rhe.id for rhe in RowHistory.objects.order_by("table_id", "row_id")] + assert mock_signal.call_count == 3 + + per_table_args = {} + for args in mock_signal.call_args_list: + per_table_args[args[1]["table_id"]] = [ + rhe.id for rhe in args[1]["row_history_entries"] + ] + + assert len(per_table_args) == 3 + assert len(entry_ids) == 6 + + # table_a + assert table_a.id in per_table_args + assert per_table_args[table_a.id] == entry_ids[:2] + + # table_b + assert table_b.id in per_table_args + assert per_table_args[table_b.id] == entry_ids[2:4] + + # table_c + assert table_c.id in per_table_args + assert per_table_args[table_c.id] == entry_ids[4:] + + expected_entries = [ + { + "user_id": user.id, + "user_name": user.first_name, + "table_id": table_a.id, + "row_id": 1, + "action_timestamp": datetime(2021, 1, 1, 12, 0, tzinfo=timezone.utc), + "action_type": "update_rows", + "before_values": {link_a_to_b.db_column: [], link_a_to_c.db_column: []}, + "after_values": { + link_a_to_b.db_column: [1, 2], + link_a_to_c.db_column: [1, 2], + }, + "fields_metadata": { + link_a_to_b.db_column: { + "id": link_a_to_b.id, + "type": "link_row", + "linked_rows": {"1": {"value": "b1"}, "2": {"value": "b2"}}, + "primary_value": "a1", + "linked_field_id": link_b_to_a.id, + "linked_table_id": table_b.id, + }, + link_a_to_c.db_column: { + "id": link_a_to_c.id, + "type": "link_row", + "linked_rows": {"1": {"value": "c1"}, "2": {"value": "c2"}}, + "primary_value": "a1", + "linked_field_id": link_c_to_a.id, + "linked_table_id": table_c.id, + }, + }, + }, + { + "user_id": user.id, + "user_name": user.first_name, + "table_id": table_a.id, + "row_id": 2, + "action_timestamp": datetime(2021, 1, 1, 12, 0, tzinfo=timezone.utc), + "action_type": "update_rows", + "before_values": {link_a_to_b.db_column: [], link_a_to_c.db_column: []}, + "after_values": { + link_a_to_b.db_column: [1, 2], + link_a_to_c.db_column: [1, 2], + }, + "fields_metadata": { + link_a_to_b.db_column: { + "id": link_a_to_b.id, + "type": "link_row", + "linked_rows": {"1": {"value": "b1"}, "2": {"value": "b2"}}, + "primary_value": "a2", + "linked_field_id": link_b_to_a.id, + "linked_table_id": table_b.id, + }, + link_a_to_c.db_column: { + "id": link_a_to_c.id, + "type": "link_row", + "linked_rows": {"1": {"value": "c1"}, "2": {"value": "c2"}}, + "primary_value": "a2", + "linked_field_id": link_c_to_a.id, + "linked_table_id": table_c.id, + }, + }, + }, + { + "user_id": user.id, + "user_name": user.first_name, + "table_id": table_b.id, + "row_id": 1, + "action_timestamp": datetime(2021, 1, 1, 12, 0, tzinfo=timezone.utc), + "action_type": "update_rows", + "before_values": {link_b_to_a.db_column: []}, + "after_values": {link_b_to_a.db_column: [1, 2]}, + "fields_metadata": { + link_b_to_a.db_column: { + "id": link_b_to_a.id, + "type": "link_row", + "linked_rows": {"1": {"value": "a1"}, "2": {"value": "a2"}}, + } + }, + }, + { + "user_id": user.id, + "user_name": user.first_name, + "table_id": table_b.id, + "row_id": 2, + "action_timestamp": datetime(2021, 1, 1, 12, 0, tzinfo=timezone.utc), + "action_type": "update_rows", + "before_values": {link_b_to_a.db_column: []}, + "after_values": {link_b_to_a.db_column: [1, 2]}, + "fields_metadata": { + link_b_to_a.db_column: { + "id": link_b_to_a.id, + "type": "link_row", + "linked_rows": {"1": {"value": "a1"}, "2": {"value": "a2"}}, + } + }, + }, + { + "user_id": user.id, + "user_name": user.first_name, + "table_id": table_c.id, + "row_id": 1, + "action_timestamp": datetime(2021, 1, 1, 12, 0, tzinfo=timezone.utc), + "action_type": "update_rows", + "before_values": {link_c_to_a.db_column: []}, + "after_values": {link_c_to_a.db_column: [1, 2]}, + "fields_metadata": { + link_c_to_a.db_column: { + "id": link_c_to_a.id, + "type": "link_row", + "linked_rows": {"1": {"value": "a1"}, "2": {"value": "a2"}}, + } + }, + }, + { + "user_id": user.id, + "user_name": user.first_name, + "table_id": table_c.id, + "row_id": 2, + "action_timestamp": datetime(2021, 1, 1, 12, 0, tzinfo=timezone.utc), + "action_type": "update_rows", + "before_values": {link_c_to_a.db_column: []}, + "after_values": {link_c_to_a.db_column: [1, 2]}, + "fields_metadata": { + link_c_to_a.db_column: { + "id": link_c_to_a.id, + "type": "link_row", + "linked_rows": {"1": {"value": "a1"}, "2": {"value": "a2"}}, + } + }, + }, + ] + + assert list(history_entries) == expected_entries diff --git a/backend/tests/baserow/contrib/database/rows/test_rows_actions.py b/backend/tests/baserow/contrib/database/rows/test_rows_actions.py index e52326d28..79cb28731 100644 --- a/backend/tests/baserow/contrib/database/rows/test_rows_actions.py +++ b/backend/tests/baserow/contrib/database/rows/test_rows_actions.py @@ -258,23 +258,25 @@ def test_can_undo_importing_rows(data_fixture): action_type_registry.get_by_type(ImportRowsActionType).do( user, table, - data=[ - [ - "Tesla", - 240, - 59999.99, - ], - [ - "Giulietta", - 210, - 34999.99, - ], - [ - "Panda", - 160, - 8999.99, - ], - ], + data={ + "data": [ + [ + "Tesla", + 240, + 59999.99, + ], + [ + "Giulietta", + 210, + 34999.99, + ], + [ + "Panda", + 160, + 8999.99, + ], + ] + }, ) assert model.objects.all().count() == 3 @@ -314,23 +316,25 @@ def test_can_undo_redo_importing_rows(row_send_mock, table_send_mock, data_fixtu action_type_registry.get_by_type(ImportRowsActionType).do( user, table, - data=[ - [ - "Tesla", - 240, - 59999.99, - ], - [ - "Giulietta", - 210, - 34999.99, - ], - [ - "Panda", - 160, - 8999.99, - ], - ], + data={ + "data": [ + [ + "Tesla", + 240, + 59999.99, + ], + [ + "Giulietta", + 210, + 34999.99, + ], + [ + "Panda", + 160, + 8999.99, + ], + ] + }, ) table_send_mock.assert_called_once() @@ -363,14 +367,16 @@ def test_can_undo_redo_importing_rows(row_send_mock, table_send_mock, data_fixtu action_type_registry.get_by_type(ImportRowsActionType).do( user, table, - data=[ - [ - "Tesla", - 240, - 59999.99, - ], - ] - * 51, + data={ + "data": [ + [ + "Tesla", + 240, + 59999.99, + ], + ] + * 51 + }, ) row_send_mock.reset_mock() @@ -506,26 +512,30 @@ def test_can_undo_deleting_rows(data_fixture): ) model = table.get_model() - rows = RowHandler().create_rows( - user, - table, - rows_values=[ - { - f"field_{name_field.id}": "Tesla", - f"field_{speed_field.id}": 240, - f"field_{price_field.id}": 59999.99, - }, - { - f"field_{name_field.id}": "Giulietta", - f"field_{speed_field.id}": 210, - f"field_{price_field.id}": 34999.99, - }, - { - f"field_{name_field.id}": "Panda", - f"field_{speed_field.id}": 160, - f"field_{price_field.id}": 8999.99, - }, - ], + rows = ( + RowHandler() + .create_rows( + user, + table, + rows_values=[ + { + f"field_{name_field.id}": "Tesla", + f"field_{speed_field.id}": 240, + f"field_{price_field.id}": 59999.99, + }, + { + f"field_{name_field.id}": "Giulietta", + f"field_{speed_field.id}": 210, + f"field_{price_field.id}": 34999.99, + }, + { + f"field_{name_field.id}": "Panda", + f"field_{speed_field.id}": 160, + f"field_{price_field.id}": 8999.99, + }, + ], + ) + .created_rows ) assert model.objects.all().count() == 3 @@ -565,26 +575,30 @@ def test_can_undo_redo_deleting_rows(data_fixture): ) model = table.get_model() - rows = RowHandler().create_rows( - user, - table, - rows_values=[ - { - f"field_{name_field.id}": "Tesla", - f"field_{speed_field.id}": 240, - f"field_{price_field.id}": 59999.99, - }, - { - f"field_{name_field.id}": "Giulietta", - f"field_{speed_field.id}": 210, - f"field_{price_field.id}": 34999.99, - }, - { - f"field_{name_field.id}": "Panda", - f"field_{speed_field.id}": 160, - f"field_{price_field.id}": 8999.99, - }, - ], + rows = ( + RowHandler() + .create_rows( + user, + table, + rows_values=[ + { + f"field_{name_field.id}": "Tesla", + f"field_{speed_field.id}": 240, + f"field_{price_field.id}": 59999.99, + }, + { + f"field_{name_field.id}": "Giulietta", + f"field_{speed_field.id}": 210, + f"field_{price_field.id}": 34999.99, + }, + { + f"field_{name_field.id}": "Panda", + f"field_{speed_field.id}": 160, + f"field_{price_field.id}": 8999.99, + }, + ], + ) + .created_rows ) assert model.objects.all().count() == 3 diff --git a/backend/tests/baserow/contrib/database/rows/test_rows_handler.py b/backend/tests/baserow/contrib/database/rows/test_rows_handler.py index 5b82491c2..bfd78acaa 100644 --- a/backend/tests/baserow/contrib/database/rows/test_rows_handler.py +++ b/backend/tests/baserow/contrib/database/rows/test_rows_handler.py @@ -339,7 +339,7 @@ def test_get_adjacent_row(data_fixture): }, ], model=table_model, - ) + ).created_rows next_row = handler.get_adjacent_row(table_model, rows[1].id) previous_row = handler.get_adjacent_row(table_model, rows[1].id, previous=True) @@ -373,7 +373,7 @@ def test_get_adjacent_row_with_custom_filters(data_fixture): }, ], model=table_model, - ) + ).created_rows base_queryset = ( table.get_model() @@ -421,7 +421,7 @@ def test_get_adjacent_row_with_view_sort(data_fixture): }, ], model=table_model, - ) + ).created_rows next_row = handler.get_adjacent_row(table_model, row_2.id, view=view) previous_row = handler.get_adjacent_row( @@ -460,7 +460,7 @@ def test_get_adjacent_row_with_view_group_by(data_fixture): }, ], model=table_model, - ) + ).created_rows next_row = handler.get_adjacent_row(table_model, row_2.id, view=view) previous_row = handler.get_adjacent_row( @@ -497,7 +497,7 @@ def test_get_adjacent_row_with_search(data_fixture): }, ], model=table_model, - ) + ).created_rows search = "a" next_row = handler.get_adjacent_row(table_model, row_2.id, view=view, search=search) @@ -551,7 +551,7 @@ def test_get_adjacent_row_with_view_group_by_and_view_sort(data_fixture): }, ], model=table_model, - ) + ).created_rows next_row = handler.get_adjacent_row(table_model, row_2.id, view=view) previous_row = handler.get_adjacent_row( @@ -582,7 +582,7 @@ def test_get_adjacent_row_performance_many_rows(data_fixture): table_model = table.get_model() rows = handler.create_rows( user=user, table=table, rows_values=row_values, model=table_model - ) + ).created_rows profiler = Profiler() profiler.start() @@ -621,7 +621,7 @@ def test_get_adjacent_row_performance_many_fields(data_fixture): table_model = table.get_model() rows = handler.create_rows( user=user, table=table, rows_values=row_values, model=table_model - ) + ).created_rows profiler = Profiler() profiler.start() @@ -747,7 +747,7 @@ def test_update_rows_return_original_values_and_fields_metadata(data_fixture): user=user, table=table, rows_values=[{}, {}], - ) + ).created_rows result = handler.update_rows( user=user, @@ -842,7 +842,9 @@ def test_create_rows_created_on_and_last_modified(data_fixture): handler = RowHandler() with freeze_time("2020-01-01 12:00"): - rows = handler.create_rows(user=user, table=table, rows_values=[{}]) + rows = handler.create_rows( + user=user, table=table, rows_values=[{}] + ).created_rows row = rows[0] assert row.created_on == datetime(2020, 1, 1, 12, 0, tzinfo=timezone.utc) assert row.updated_on == datetime(2020, 1, 1, 12, 0, tzinfo=timezone.utc) @@ -862,7 +864,7 @@ def test_create_rows_last_modified_by(data_fixture): {f"field_{name_field.id}": "Test"}, {f"field_{name_field.id}": "Test 2"}, ], - ) + ).created_rows assert rows[0].last_modified_by == user assert rows[1].last_modified_by == user @@ -1562,15 +1564,19 @@ def test_formula_referencing_fields_add_additional_queries_on_rows_created( # An UPDATE query to set the formula field value + 1 query due # to FormulaFieldType.after_rows_created with django_assert_num_queries(len(captured.captured_queries) + 2): - (r,) = RowHandler().force_create_rows( - user=user, - table=table, - rows_values=[ - { - f"field_{name_field.id}": "Giulietta", - } - ], - model=model, + (r,) = ( + RowHandler() + .force_create_rows( + user=user, + table=table, + rows_values=[ + { + f"field_{name_field.id}": "Giulietta", + } + ], + model=model, + ) + .created_rows ) assert getattr(r, f"field_{f1.id}") == "Giulietta-a" @@ -1584,15 +1590,19 @@ def test_formula_referencing_fields_add_additional_queries_on_rows_created( model = table.get_model() with django_assert_num_queries(len(captured.captured_queries) + 2): - (r,) = RowHandler().force_create_rows( - user=user, - table=table, - rows_values=[ - { - f"field_{name_field.id}": "Stelvio", - } - ], - model=model, + (r,) = ( + RowHandler() + .force_create_rows( + user=user, + table=table, + rows_values=[ + { + f"field_{name_field.id}": "Stelvio", + } + ], + model=model, + ) + .created_rows ) assert getattr(r, f"field_{f1.id}") == "Stelvio-a" assert getattr(r, f"field_{f2.id}") == "Stelvio-b" @@ -1609,15 +1619,19 @@ def test_formula_referencing_fields_add_additional_queries_on_rows_created( # Now a second UPDATE query is needed, so that F3 can use the result # of F1 to correctly calculate its value with django_assert_num_queries(len(captured.captured_queries) + 3): - (r,) = RowHandler().force_create_rows( - user=user, - table=table, - rows_values=[ - { - f"field_{name_field.id}": "Tonale", - } - ], - model=model, + (r,) = ( + RowHandler() + .force_create_rows( + user=user, + table=table, + rows_values=[ + { + f"field_{name_field.id}": "Tonale", + } + ], + model=model, + ) + .created_rows ) assert getattr(r, f"field_{f1.id}") == "Tonale-a" assert getattr(r, f"field_{f2.id}") == "Tonale-b" @@ -1642,7 +1656,11 @@ def test_formula_referencing_fields_add_additional_queries_on_rows_updated( # in the FieldDependencyHandler: # link_row_field_content_type = ContentType.objects.get_for_model(LinkRowField) # so let's create a row first to avoid counting that query - (r,) = RowHandler().force_create_rows(user=user, table=table, rows_values=[{}]) + (r,) = ( + RowHandler() + .force_create_rows(user=user, table=table, rows_values=[{}]) + .created_rows + ) with CaptureQueriesContext(connection) as captured: RowHandler().force_update_rows( @@ -1740,18 +1758,26 @@ def test_can_move_rows_and_formulas_are_updated_correctly(data_fixture): table_a, table_b, link_a_b = data_fixture.create_two_linked_tables(user=user) prim_b = data_fixture.create_text_field(table=table_b, primary=True, name="name") - row_b1, row_b2 = RowHandler().create_rows( - user, table_b, [{prim_b.db_column: "b1"}, {prim_b.db_column: "b2"}] + row_b1, row_b2 = ( + RowHandler() + .create_rows( + user, table_b, [{prim_b.db_column: "b1"}, {prim_b.db_column: "b2"}] + ) + .created_rows ) lookup_a = data_fixture.create_formula_field( table=table_a, formula="join(lookup('link', 'name'), '')" ) - row_a1, row_a2 = RowHandler().create_rows( - user, - table_a, - [{link_a_b.db_column: [row_b1.id]}, {link_a_b.db_column: [row_b2.id]}], + row_a1, row_a2 = ( + RowHandler() + .create_rows( + user, + table_a, + [{link_a_b.db_column: [row_b1.id]}, {link_a_b.db_column: [row_b2.id]}], + ) + .created_rows ) assert getattr(row_a1, lookup_a.db_column) == "b1" diff --git a/backend/tests/baserow/contrib/database/table/test_table_models.py b/backend/tests/baserow/contrib/database/table/test_table_models.py index c21771fc2..0112e8a03 100644 --- a/backend/tests/baserow/contrib/database/table/test_table_models.py +++ b/backend/tests/baserow/contrib/database/table/test_table_models.py @@ -482,39 +482,43 @@ def test_order_by_fields_string_queryset(data_fixture): field=multiple_select_field, value="D", color="red" ) - row_1, row_2, row_3, row_4 = RowHandler().force_create_rows( - user=None, - table=table, - rows_values=[ - { - name_field.db_column: "BMW", - color_field.db_column: "Blue", - price_field.db_column: 10000, - description_field.db_column: "Sports car.", - single_select_field.db_column: option_a.id, - multiple_select_field.db_column: [option_c.id], - }, - { - name_field.db_column: "Audi", - color_field.db_column: "Orange", - price_field.db_column: 20000, - description_field.db_column: "This is the most expensive car we have.", - single_select_field.db_column: option_b.id, - multiple_select_field.db_column: [option_d.id], - }, - { - name_field.db_column: "Volkswagen", - color_field.db_column: "White", - price_field.db_column: 5000, - description_field.db_column: "A very old car.", - }, - { - name_field.db_column: "Volkswagen", - color_field.db_column: "Green", - price_field.db_column: 4000, - description_field.db_column: "Strange color.", - }, - ], + row_1, row_2, row_3, row_4 = ( + RowHandler() + .force_create_rows( + user=None, + table=table, + rows_values=[ + { + name_field.db_column: "BMW", + color_field.db_column: "Blue", + price_field.db_column: 10000, + description_field.db_column: "Sports car.", + single_select_field.db_column: option_a.id, + multiple_select_field.db_column: [option_c.id], + }, + { + name_field.db_column: "Audi", + color_field.db_column: "Orange", + price_field.db_column: 20000, + description_field.db_column: "This is the most expensive car we have.", + single_select_field.db_column: option_b.id, + multiple_select_field.db_column: [option_d.id], + }, + { + name_field.db_column: "Volkswagen", + color_field.db_column: "White", + price_field.db_column: 5000, + description_field.db_column: "A very old car.", + }, + { + name_field.db_column: "Volkswagen", + color_field.db_column: "Green", + price_field.db_column: 4000, + description_field.db_column: "Strange color.", + }, + ], + ) + .created_rows ) model = table.get_model() @@ -690,6 +694,71 @@ def test_order_by_fields_string_queryset_with_user_field_names(data_fixture): assert results[4].id == rows[3].id +@pytest.mark.django_db +def test_order_by_fields_string_queryset_with_type(data_fixture): + table = data_fixture.create_database_table(name="Cars") + name_field = data_fixture.create_text_field(table=table, order=0, name="Name") + single_select_field = data_fixture.create_single_select_field( + table=table, name="Single" + ) + option_a = data_fixture.create_select_option( + field=single_select_field, value="A", color="blue", order=2 + ) + option_b = data_fixture.create_select_option( + field=single_select_field, value="B", color="red", order=1 + ) + + row_1, row_2 = ( + RowHandler() + .force_create_rows( + user=None, + table=table, + rows_values=[ + { + name_field.db_column: "BMW", + single_select_field.db_column: option_a.id, + }, + { + name_field.db_column: "Audi", + single_select_field.db_column: option_b.id, + }, + ], + ) + .created_rows + ) + + model = table.get_model() + + with pytest.raises(OrderByFieldNotPossible): + model.objects.all().order_by_fields_string( + f"field_{single_select_field.id}[unknown]" + ) + + results = model.objects.all().order_by_fields_string( + f"field_{single_select_field.id}[default]" + ) + assert results[0].id == row_1.id + assert results[1].id == row_2.id + + results = model.objects.all().order_by_fields_string( + f"-field_{single_select_field.id}[default]" + ) + assert results[0].id == row_2.id + assert results[1].id == row_1.id + + results = model.objects.all().order_by_fields_string( + f"field_{single_select_field.id}[order]" + ) + assert results[0].id == row_2.id + assert results[1].id == row_1.id + + results = model.objects.all().order_by_fields_string( + f"-field_{single_select_field.id}[order]" + ) + assert results[0].id == row_1.id + assert results[1].id == row_2.id + + @pytest.mark.django_db def test_filter_by_fields_object_queryset(data_fixture): table = data_fixture.create_database_table(name="Cars") diff --git a/backend/tests/baserow/contrib/database/test_cachalot.py b/backend/tests/baserow/contrib/database/test_cachalot.py index f7ce090e7..f75a783cf 100644 --- a/backend/tests/baserow/contrib/database/test_cachalot.py +++ b/backend/tests/baserow/contrib/database/test_cachalot.py @@ -105,7 +105,7 @@ if settings.CACHALOT_ENABLED: {f"field_{field.id}": [select_options[0].id, select_options[1].value]}, {f"field_{field.id}": [select_options[2].value, select_options[0].id]}, ], - ) + ).created_rows url = reverse("api:database:views:grid:list", kwargs={"view_id": grid_view.id}) response = api_client.get(url, **{"HTTP_AUTHORIZATION": f"JWT {token}"}) diff --git a/backend/tests/baserow/contrib/database/test_database_application_type.py b/backend/tests/baserow/contrib/database/test_database_application_type.py index 363afda2a..fc03976f3 100644 --- a/backend/tests/baserow/contrib/database/test_database_application_type.py +++ b/backend/tests/baserow/contrib/database/test_database_application_type.py @@ -43,17 +43,27 @@ def test_import_export_database(data_fixture): data_fixture.create_view_sort(view=view, field=text_field) with freeze_time("2021-01-01 12:30"): - row, _ = RowHandler().force_create_rows( - user, - table, - [{f"field_{text_field.id}": "Test"}, {f"field_{text_field.id}": "Test 2"}], + row = ( + RowHandler() + .force_create_rows( + user, + table, + [ + {f"field_{text_field.id}": "Test"}, + {f"field_{text_field.id}": "Test 2"}, + ], + ) + .created_rows[0] ) with freeze_time("2021-01-02 13:30"): - res = RowHandler().force_update_rows( - user, table, [{"id": row.id, f"field_{text_field.id}": "Test"}] + row = ( + RowHandler() + .force_update_rows( + user, table, [{"id": row.id, f"field_{text_field.id}": "Test"}] + ) + .updated_rows[0] ) - row = res.updated_rows[0] database_type = application_type_registry.get("database") config = ImportExportConfig(include_permission_data=True) diff --git a/backend/tests/baserow/contrib/database/view/actions/test_view_group_by_actions.py b/backend/tests/baserow/contrib/database/view/actions/test_view_group_by_actions.py index 16a331bfd..84cc0a46e 100644 --- a/backend/tests/baserow/contrib/database/view/actions/test_view_group_by_actions.py +++ b/backend/tests/baserow/contrib/database/view/actions/test_view_group_by_actions.py @@ -25,7 +25,7 @@ def test_can_undo_creating_view_group_by(data_fixture): assert ViewGroupBy.objects.count() == 0 view_group_by = action_type_registry.get_by_type(CreateViewGroupByActionType).do( - user, grid_view, number_field, "DESC", 250 + user, grid_view, number_field, "DESC", 250, "default" ) assert ViewGroupBy.objects.filter(pk=view_group_by.id).count() == 1 @@ -53,7 +53,7 @@ def test_can_undo_redo_creating_view_group_by(data_fixture): assert ViewGroupBy.objects.count() == 0 view_group_by = action_type_registry.get_by_type(CreateViewGroupByActionType).do( - user, grid_view, number_field, "DESC", 250 + user, grid_view, number_field, "DESC", 250, "default" ) original_view_group_by_id = view_group_by.id @@ -78,6 +78,36 @@ def test_can_undo_redo_creating_view_group_by(data_fixture): assert updated_view_group_by.width == 250 +@pytest.mark.django_db +@pytest.mark.undo_redo +def test_can_undo_redo_creating_view_group_by_with_type(data_fixture): + session_id = "1010" + user = data_fixture.create_user(session_id=session_id) + table = data_fixture.create_database_table(user=user) + grid_view = data_fixture.create_grid_view(table=table) + single_select_field = data_fixture.create_single_select_field( + table=table, name="value" + ) + + assert ViewGroupBy.objects.count() == 0 + + view_group_by = action_type_registry.get_by_type(CreateViewGroupByActionType).do( + user, grid_view, single_select_field, "DESC", 250, "order" + ) + + assert ViewGroupBy.objects.filter(pk=view_group_by.id).count() == 1 + + ActionHandler.undo(user, [ViewActionScopeType.value(grid_view.id)], session_id) + + assert ViewGroupBy.objects.filter(pk=view_group_by.id).count() == 0 + + ActionHandler.redo(user, [ViewActionScopeType.value(grid_view.id)], session_id) + + assert ViewGroupBy.objects.filter(pk=view_group_by.id).count() == 1 + updated_view_group_by = ViewGroupBy.objects.first() + assert updated_view_group_by.type == "order" + + @pytest.mark.django_db @pytest.mark.undo_redo def test_can_undo_updating_view_group_by(data_fixture): @@ -96,18 +126,20 @@ def test_can_undo_updating_view_group_by(data_fixture): assert view_group_by.width == 250 action_type_registry.get_by_type(UpdateViewGroupByActionType).do( - user, view_group_by, order="DESC", width=300 + user, view_group_by, order="DESC", width=300, sort_type="default" ) view_group_by.refresh_from_db() assert view_group_by.order == "DESC" assert view_group_by.width == 300 + assert view_group_by.type == "default" ActionHandler.undo(user, [ViewActionScopeType.value(grid_view.id)], session_id) view_group_by.refresh_from_db() assert view_group_by.order == "ASC" assert view_group_by.width == 250 + assert view_group_by.type == "default" @pytest.mark.django_db @@ -128,24 +160,57 @@ def test_can_undo_redo_updating_view_group_by(data_fixture): assert view_group_by.width == 300 action_type_registry.get_by_type(UpdateViewGroupByActionType).do( - user, view_group_by, order="DESC", width=250 + user, view_group_by, order="DESC", width=250, sort_type="default" ) view_group_by.refresh_from_db() assert view_group_by.order == "DESC" assert view_group_by.width == 250 + assert view_group_by.type == "default" ActionHandler.undo(user, [ViewActionScopeType.value(grid_view.id)], session_id) view_group_by.refresh_from_db() assert view_group_by.order == "ASC" assert view_group_by.width == 300 + assert view_group_by.type == "default" ActionHandler.redo(user, [ViewActionScopeType.value(grid_view.id)], session_id) view_group_by.refresh_from_db() assert view_group_by.order == "DESC" assert view_group_by.width == 250 + assert view_group_by.type == "default" + + +@pytest.mark.django_db +@pytest.mark.undo_redo +def test_can_undo_redo_updating_view_group_by_with_type(data_fixture): + session_id = "1010" + user = data_fixture.create_user(session_id=session_id) + table = data_fixture.create_database_table(user=user) + grid_view = data_fixture.create_grid_view(table=table) + single_select_field = data_fixture.create_single_select_field(table=table) + view_group_by = data_fixture.create_view_group_by( + view=grid_view, field=single_select_field, type="order" + ) + + action_type_registry.get_by_type(UpdateViewGroupByActionType).do( + user, view_group_by, sort_type="default" + ) + + view_group_by.refresh_from_db() + assert view_group_by.type == "default" + + ActionHandler.undo(user, [ViewActionScopeType.value(grid_view.id)], session_id) + + view_group_by.refresh_from_db() + assert view_group_by.type == "order" + + ActionHandler.redo(user, [ViewActionScopeType.value(grid_view.id)], session_id) + + view_group_by.refresh_from_db() + assert view_group_by.type == "default" @pytest.mark.django_db @@ -215,3 +280,27 @@ def test_can_undo_redo_deleting_view_group_by(data_fixture): ActionHandler.redo(user, [ViewActionScopeType.value(grid_view.id)], session_id) assert ViewGroupBy.objects.count() == 0 + + +@pytest.mark.django_db +@pytest.mark.undo_redo +def test_can_undo_redo_deleting_view_group_by_with_type(data_fixture): + session_id = "1010" + user = data_fixture.create_user(session_id=session_id) + table = data_fixture.create_database_table(user=user) + grid_view = data_fixture.create_grid_view(table=table) + field = data_fixture.create_single_select_field(table=table) + view_group_by = data_fixture.create_view_group_by( + view=grid_view, field=field, order="ASC", width=350, type="order" + ) + + action_type_registry.get_by_type(DeleteViewGroupByActionType).do( + user, view_group_by + ) + + assert ViewGroupBy.objects.count() == 0 + + ActionHandler.undo(user, [ViewActionScopeType.value(grid_view.id)], session_id) + group_by = ViewGroupBy.objects.all() + assert len(group_by) == 1 + assert group_by[0].type == "order" diff --git a/backend/tests/baserow/contrib/database/view/actions/test_view_sort_actions.py b/backend/tests/baserow/contrib/database/view/actions/test_view_sort_actions.py index 9b0d4ff5d..4c6bf5e62 100644 --- a/backend/tests/baserow/contrib/database/view/actions/test_view_sort_actions.py +++ b/backend/tests/baserow/contrib/database/view/actions/test_view_sort_actions.py @@ -75,6 +75,35 @@ def test_can_undo_redo_creating_view_sort(data_fixture): assert updated_view_sort.order == "DESC" +@pytest.mark.django_db +@pytest.mark.undo_redo +def test_can_undo_redo_creating_view_sort_with_type(data_fixture): + session_id = "1010" + user = data_fixture.create_user(session_id=session_id) + table = data_fixture.create_database_table(user=user) + grid_view = data_fixture.create_grid_view(table=table) + field = data_fixture.create_single_select_field(table=table, name="value") + + assert ViewSort.objects.count() == 0 + + view_sort = action_type_registry.get_by_type(CreateViewSortActionType).do( + user, grid_view, field, "DESC", sort_type="order" + ) + + assert ViewSort.objects.filter(pk=view_sort.id).count() == 1 + assert view_sort.type == "order" + + ActionHandler.undo(user, [ViewActionScopeType.value(grid_view.id)], session_id) + + assert ViewSort.objects.filter(pk=view_sort.id).count() == 0 + + ActionHandler.redo(user, [ViewActionScopeType.value(grid_view.id)], session_id) + + assert ViewSort.objects.filter(pk=view_sort.id).count() == 1 + updated_view_sort = ViewSort.objects.first() + assert updated_view_sort.type == "order" + + @pytest.mark.django_db @pytest.mark.undo_redo def test_can_undo_updating_view_sort(data_fixture): @@ -138,6 +167,36 @@ def test_can_undo_redo_updating_view_sort(data_fixture): assert view_sort.order == "DESC" +@pytest.mark.django_db +@pytest.mark.undo_redo +def test_can_undo_redo_updating_view_sort_type(data_fixture): + session_id = "1010" + user = data_fixture.create_user(session_id=session_id) + table = data_fixture.create_database_table(user=user) + grid_view = data_fixture.create_grid_view(table=table) + single_select_field = data_fixture.create_single_select_field(table=table) + view_sort = data_fixture.create_view_sort( + view=grid_view, field=single_select_field, order="ASC", type="order" + ) + + action_type_registry.get_by_type(UpdateViewSortActionType).do( + user, view_sort, sort_type="default" + ) + + view_sort.refresh_from_db() + assert view_sort.type == "default" + + ActionHandler.undo(user, [ViewActionScopeType.value(grid_view.id)], session_id) + + view_sort.refresh_from_db() + assert view_sort.type == "order" + + ActionHandler.redo(user, [ViewActionScopeType.value(grid_view.id)], session_id) + + view_sort.refresh_from_db() + assert view_sort.type == "default" + + @pytest.mark.django_db @pytest.mark.undo_redo def test_can_undo_deleting_view_sort(data_fixture): @@ -198,3 +257,25 @@ def test_can_undo_redo_deleting_view_sort(data_fixture): ActionHandler.redo(user, [ViewActionScopeType.value(grid_view.id)], session_id) assert ViewSort.objects.count() == 0 + + +@pytest.mark.django_db +@pytest.mark.undo_redo +def test_can_undo_redo_deleting_view_sort_with_type(data_fixture): + session_id = "1010" + user = data_fixture.create_user(session_id=session_id) + table = data_fixture.create_database_table(user=user) + grid_view = data_fixture.create_grid_view(table=table) + field = data_fixture.create_single_select_field(table=table) + view_sort = data_fixture.create_view_sort( + view=grid_view, field=field, order="ASC", type="order" + ) + + action_type_registry.get_by_type(DeleteViewSortActionType).do(user, view_sort) + + assert ViewSort.objects.count() == 0 + + ActionHandler.undo(user, [ViewActionScopeType.value(grid_view.id)], session_id) + sorts = ViewSort.objects.all() + assert len(sorts) == 1 + assert sorts[0].type == "order" diff --git a/backend/tests/baserow/contrib/database/view/test_view_array_filters.py b/backend/tests/baserow/contrib/database/view/test_view_array_filters.py index d1e3d0049..9e3e58bed 100644 --- a/backend/tests/baserow/contrib/database/view/test_view_array_filters.py +++ b/backend/tests/baserow/contrib/database/view/test_view_array_filters.py @@ -92,7 +92,7 @@ def boolean_lookup_filter_proc( linked_rows = test_setup.row_handler.create_rows( user=test_setup.user, table=test_setup.other_table, rows_values=dict_rows - ) + ).created_rows rows = [ # mixed { @@ -126,7 +126,7 @@ def boolean_lookup_filter_proc( ] r_mixed, r_false, r_true, r_none = test_setup.row_handler.create_rows( user=test_setup.user, table=test_setup.table, rows_values=rows - ) + ).created_rows rows = [r_mixed, r_false, r_true, r_none] selected = [rows[idx] for idx in expected_rows] @@ -2423,7 +2423,7 @@ def setup_multiple_select_rows(data_fixture): {f"field_{test_setup.target_field.id}": row_B_value}, {f"field_{test_setup.target_field.id}": row_empty_value}, ], - ) + ).created_rows row_1 = test_setup.row_handler.create_row( user=test_setup.user, table=test_setup.table, @@ -2629,7 +2629,7 @@ def setup_date_rows(data_fixture, field_factory): {}, ], model=test_setup.other_table_model, - ) + ).created_rows row_1, row_2, empty_row = test_setup.row_handler.force_create_rows( user, test_setup.table, @@ -2639,7 +2639,7 @@ def setup_date_rows(data_fixture, field_factory): {test_setup.link_row_field.db_column: [other_row_3.id]}, ], model=test_setup.model, - ) + ).created_rows return test_setup, [row_1, row_2, empty_row] @@ -2745,16 +2745,20 @@ def table_view_fields_rows(data_fixture): datetime_field = data_fixture.create_date_field( table=orig_table, date_include_time=True ) - orig_rows = RowHandler().force_create_rows( - user, - orig_table, - [ - { - date_field.db_column: date_value, - datetime_field.db_column: date_value, - } - for date_value in TEST_MULTI_STEP_DATE_OPERATORS_DATETIMES - ], + orig_rows = ( + RowHandler() + .force_create_rows( + user, + orig_table, + [ + { + date_field.db_column: date_value, + datetime_field.db_column: date_value, + } + for date_value in TEST_MULTI_STEP_DATE_OPERATORS_DATETIMES + ], + ) + .created_rows ) table = data_fixture.create_database_table(database=orig_table.database) @@ -2777,10 +2781,14 @@ def table_view_fields_rows(data_fixture): through_field_name=link_field.name, target_field_name=datetime_field.name, ) - rows = RowHandler().force_create_rows( - user, - table, - [{link_field.db_column: [r.id]} for r in orig_rows], + rows = ( + RowHandler() + .force_create_rows( + user, + table, + [{link_field.db_column: [r.id]} for r in orig_rows], + ) + .created_rows ) grid_view = data_fixture.create_grid_view(table=table) diff --git a/backend/tests/baserow/contrib/database/view/test_view_filters.py b/backend/tests/baserow/contrib/database/view/test_view_filters.py index be0e1bb53..27dead907 100644 --- a/backend/tests/baserow/contrib/database/view/test_view_filters.py +++ b/backend/tests/baserow/contrib/database/view/test_view_filters.py @@ -89,33 +89,37 @@ def test_equal_filter_type(data_fixture): handler = ViewHandler() model = table.get_model() - row, row_2, row_3 = RowHandler().create_rows( - user, - table, - rows_values=[ - { - f"field_{text_field.id}": "Test", - f"field_{long_text_field.id}": "Long", - f"field_{integer_field.id}": 10, - f"field_{decimal_field.id}": 20.20, - f"field_{boolean_field.id}": True, - }, - { - f"field_{text_field.id}": "", - f"field_{long_text_field.id}": "", - f"field_{integer_field.id}": None, - f"field_{decimal_field.id}": None, - f"field_{boolean_field.id}": False, - }, - { - f"field_{text_field.id}": "NOT", - f"field_{long_text_field.id}": "NOT2", - f"field_{integer_field.id}": 99, - f"field_{decimal_field.id}": 99.99, - f"field_{boolean_field.id}": False, - }, - ], - model=model, + row, row_2, row_3 = ( + RowHandler() + .create_rows( + user, + table, + rows_values=[ + { + f"field_{text_field.id}": "Test", + f"field_{long_text_field.id}": "Long", + f"field_{integer_field.id}": 10, + f"field_{decimal_field.id}": 20.20, + f"field_{boolean_field.id}": True, + }, + { + f"field_{text_field.id}": "", + f"field_{long_text_field.id}": "", + f"field_{integer_field.id}": None, + f"field_{decimal_field.id}": None, + f"field_{boolean_field.id}": False, + }, + { + f"field_{text_field.id}": "NOT", + f"field_{long_text_field.id}": "NOT2", + f"field_{integer_field.id}": 99, + f"field_{decimal_field.id}": 99.99, + f"field_{boolean_field.id}": False, + }, + ], + model=model, + ) + .created_rows ) view_filter = data_fixture.create_view_filter( @@ -225,33 +229,37 @@ def test_not_equal_filter_type(data_fixture): handler = ViewHandler() model = table.get_model() - row, row_2, row_3 = RowHandler().create_rows( - user, - table, - rows_values=[ - { - f"field_{text_field.id}": "Test", - f"field_{long_text_field.id}": "Long", - f"field_{integer_field.id}": 10, - f"field_{decimal_field.id}": 20.20, - f"field_{boolean_field.id}": True, - }, - { - f"field_{text_field.id}": "", - f"field_{long_text_field.id}": "", - f"field_{integer_field.id}": None, - f"field_{decimal_field.id}": None, - f"field_{boolean_field.id}": False, - }, - { - f"field_{text_field.id}": "NOT", - f"field_{long_text_field.id}": "NOT2", - f"field_{integer_field.id}": 99, - f"field_{decimal_field.id}": 99.99, - f"field_{boolean_field.id}": False, - }, - ], - model=model, + row, row_2, row_3 = ( + RowHandler() + .create_rows( + user, + table, + rows_values=[ + { + f"field_{text_field.id}": "Test", + f"field_{long_text_field.id}": "Long", + f"field_{integer_field.id}": 10, + f"field_{decimal_field.id}": 20.20, + f"field_{boolean_field.id}": True, + }, + { + f"field_{text_field.id}": "", + f"field_{long_text_field.id}": "", + f"field_{integer_field.id}": None, + f"field_{decimal_field.id}": None, + f"field_{boolean_field.id}": False, + }, + { + f"field_{text_field.id}": "NOT", + f"field_{long_text_field.id}": "NOT2", + f"field_{integer_field.id}": 99, + f"field_{decimal_field.id}": 99.99, + f"field_{boolean_field.id}": False, + }, + ], + model=model, + ) + .created_rows ) view_filter = data_fixture.create_view_filter( @@ -394,36 +402,40 @@ def test_contains_filter_type(data_fixture): handler = ViewHandler() model = table.get_model() - row, _, row_3 = RowHandler().create_rows( - user, - table, - rows_values=[ - { - f"field_{text_field.id}": "My name is John Doe.", - f"field_{long_text_field.id}": "Long text that is not empty.", - f"field_{date_field.id}": "2020-02-01 01:23", - f"field_{number_field.id}": "98989898", - f"field_{single_select_field.id}": option_a, - f"field_{multiple_select_field.id}": [option_c.id, option_d.id], - }, - { - f"field_{text_field.id}": "", - f"field_{long_text_field.id}": "", - f"field_{date_field.id}": None, - f"field_{number_field.id}": None, - f"field_{single_select_field.id}": None, - }, - { - f"field_{text_field.id}": "This is a test field.", - f"field_{long_text_field.id}": "This text is a bit longer, but it also " - "contains.\n A multiline approach.", - f"field_{date_field.id}": "0001-01-02 00:12", - f"field_{number_field.id}": "10000", - f"field_{single_select_field.id}": option_b, - f"field_{multiple_select_field.id}": [option_c.id], - }, - ], - model=model, + row, _, row_3 = ( + RowHandler() + .create_rows( + user, + table, + rows_values=[ + { + f"field_{text_field.id}": "My name is John Doe.", + f"field_{long_text_field.id}": "Long text that is not empty.", + f"field_{date_field.id}": "2020-02-01 01:23", + f"field_{number_field.id}": "98989898", + f"field_{single_select_field.id}": option_a, + f"field_{multiple_select_field.id}": [option_c.id, option_d.id], + }, + { + f"field_{text_field.id}": "", + f"field_{long_text_field.id}": "", + f"field_{date_field.id}": None, + f"field_{number_field.id}": None, + f"field_{single_select_field.id}": None, + }, + { + f"field_{text_field.id}": "This is a test field.", + f"field_{long_text_field.id}": "This text is a bit longer, but it also " + "contains.\n A multiline approach.", + f"field_{date_field.id}": "0001-01-02 00:12", + f"field_{number_field.id}": "10000", + f"field_{single_select_field.id}": option_b, + f"field_{multiple_select_field.id}": [option_c.id], + }, + ], + model=model, + ) + .created_rows ) view_filter = data_fixture.create_view_filter( @@ -603,36 +615,40 @@ def test_contains_not_filter_type(data_fixture): handler = ViewHandler() model = table.get_model() - row, row_2, row_3 = RowHandler().create_rows( - user, - table, - rows_values=[ - { - f"field_{text_field.id}": "My name is John Doe.", - f"field_{long_text_field.id}": "Long text that is not empty.", - f"field_{date_field.id}": "2020-02-01 01:23", - f"field_{number_field.id}": "98989898", - f"field_{single_select_field.id}": option_a, - f"field_{multiple_select_field.id}": [option_c.id, option_d.id], - }, - { - f"field_{text_field.id}": "", - f"field_{long_text_field.id}": "", - f"field_{date_field.id}": None, - f"field_{number_field.id}": None, - f"field_{single_select_field.id}": None, - }, - { - f"field_{text_field.id}": "This is a test field.", - f"field_{long_text_field.id}": "This text is a bit longer, but it also " - "contains.\n A multiline approach.", - f"field_{date_field.id}": "0001-01-02 00:12", - f"field_{number_field.id}": "10000", - f"field_{single_select_field.id}": option_b, - f"field_{multiple_select_field.id}": [option_d.id], - }, - ], - model=model, + row, row_2, row_3 = ( + RowHandler() + .create_rows( + user, + table, + rows_values=[ + { + f"field_{text_field.id}": "My name is John Doe.", + f"field_{long_text_field.id}": "Long text that is not empty.", + f"field_{date_field.id}": "2020-02-01 01:23", + f"field_{number_field.id}": "98989898", + f"field_{single_select_field.id}": option_a, + f"field_{multiple_select_field.id}": [option_c.id, option_d.id], + }, + { + f"field_{text_field.id}": "", + f"field_{long_text_field.id}": "", + f"field_{date_field.id}": None, + f"field_{number_field.id}": None, + f"field_{single_select_field.id}": None, + }, + { + f"field_{text_field.id}": "This is a test field.", + f"field_{long_text_field.id}": "This text is a bit longer, but it also " + "contains.\n A multiline approach.", + f"field_{date_field.id}": "0001-01-02 00:12", + f"field_{number_field.id}": "10000", + f"field_{single_select_field.id}": option_b, + f"field_{multiple_select_field.id}": [option_d.id], + }, + ], + model=model, + ) + .created_rows ) view_filter = data_fixture.create_view_filter( @@ -818,36 +834,40 @@ def test_contains_word_filter_type(data_fixture): handler = ViewHandler() model = table.get_model() - row, row_2, row_3 = RowHandler().create_rows( - user, - table, - rows_values=[ - { - f"field_{text_field.id}": "My name is John Doe.", - f"field_{long_text_field.id}": "Long text that is not empty, but also not multilined.", - f"field_{url_field.id}": "https://www.example.com", - f"field_{email_field.id}": "test.user@example.com", - f"field_{single_select_field.id}": option_a, - f"field_{multiple_select_field.id}": [option_c.id, option_d.id], - }, - { - f"field_{text_field.id}": "", - f"field_{long_text_field.id}": "", - f"field_{url_field.id}": "", - f"field_{email_field.id}": "", - f"field_{single_select_field.id}": None, - }, - { - f"field_{text_field.id}": "This is a test field with the word Johny.", - f"field_{long_text_field.id}": "This text is a bit longer, but it also " - "contains.\n A multiline approach.", - f"field_{url_field.id}": "https://www.examplewebsite.com", - f"field_{email_field.id}": "test.user@examplewebsite.com", - f"field_{single_select_field.id}": option_b, - f"field_{multiple_select_field.id}": [option_c.id], - }, - ], - model=model, + row, row_2, row_3 = ( + RowHandler() + .create_rows( + user, + table, + rows_values=[ + { + f"field_{text_field.id}": "My name is John Doe.", + f"field_{long_text_field.id}": "Long text that is not empty, but also not multilined.", + f"field_{url_field.id}": "https://www.example.com", + f"field_{email_field.id}": "test.user@example.com", + f"field_{single_select_field.id}": option_a, + f"field_{multiple_select_field.id}": [option_c.id, option_d.id], + }, + { + f"field_{text_field.id}": "", + f"field_{long_text_field.id}": "", + f"field_{url_field.id}": "", + f"field_{email_field.id}": "", + f"field_{single_select_field.id}": None, + }, + { + f"field_{text_field.id}": "This is a test field with the word Johny.", + f"field_{long_text_field.id}": "This text is a bit longer, but it also " + "contains.\n A multiline approach.", + f"field_{url_field.id}": "https://www.examplewebsite.com", + f"field_{email_field.id}": "test.user@examplewebsite.com", + f"field_{single_select_field.id}": option_b, + f"field_{multiple_select_field.id}": [option_c.id], + }, + ], + model=model, + ) + .created_rows ) view_filter = data_fixture.create_view_filter( @@ -1011,36 +1031,40 @@ def test_doesnt_contain_word_filter_type(data_fixture): handler = ViewHandler() model = table.get_model() - row, row_2, row_3 = RowHandler().create_rows( - user, - table, - rows_values=[ - { - f"field_{text_field.id}": "My name is John Doe.", - f"field_{long_text_field.id}": "Long text that is not empty, but also not multilined.", - f"field_{url_field.id}": "https://www.example.com", - f"field_{email_field.id}": "test.user@example.com", - f"field_{single_select_field.id}": option_a, - f"field_{multiple_select_field.id}": [option_c.id, option_d.id], - }, - { - f"field_{text_field.id}": "", - f"field_{long_text_field.id}": "", - f"field_{url_field.id}": "", - f"field_{email_field.id}": "", - f"field_{single_select_field.id}": None, - }, - { - f"field_{text_field.id}": "This is a test field with the word Johny.", - f"field_{long_text_field.id}": "This text is a bit longer, but it also " - "contains.\n A multiline approach.", - f"field_{url_field.id}": "https://www.examplewebsite.com", - f"field_{email_field.id}": "test.user@examplewebsite.com", - f"field_{single_select_field.id}": option_b, - f"field_{multiple_select_field.id}": [option_c.id], - }, - ], - model=model, + row, row_2, row_3 = ( + RowHandler() + .create_rows( + user, + table, + rows_values=[ + { + f"field_{text_field.id}": "My name is John Doe.", + f"field_{long_text_field.id}": "Long text that is not empty, but also not multilined.", + f"field_{url_field.id}": "https://www.example.com", + f"field_{email_field.id}": "test.user@example.com", + f"field_{single_select_field.id}": option_a, + f"field_{multiple_select_field.id}": [option_c.id, option_d.id], + }, + { + f"field_{text_field.id}": "", + f"field_{long_text_field.id}": "", + f"field_{url_field.id}": "", + f"field_{email_field.id}": "", + f"field_{single_select_field.id}": None, + }, + { + f"field_{text_field.id}": "This is a test field with the word Johny.", + f"field_{long_text_field.id}": "This text is a bit longer, but it also " + "contains.\n A multiline approach.", + f"field_{url_field.id}": "https://www.examplewebsite.com", + f"field_{email_field.id}": "test.user@examplewebsite.com", + f"field_{single_select_field.id}": option_b, + f"field_{multiple_select_field.id}": [option_c.id], + }, + ], + model=model, + ) + .created_rows ) view_filter = data_fixture.create_view_filter( @@ -3275,56 +3299,60 @@ def test_empty_filter_type(data_fixture): handler = ViewHandler() model = table.get_model() - row, row_2, row_3 = RowHandler().create_rows( - user, - table, - [ - { - f"field_{text_field.id}": "", - f"field_{long_text_field.id}": "", - f"field_{integer_field.id}": None, - f"field_{decimal_field.id}": None, - f"field_{date_field.id}": None, - f"field_{date_time_field.id}": None, - f"field_{boolean_field.id}": False, - f"field_{file_field.id}": [], - f"field_{single_select_field.id}_id": None, - }, - { - f"field_{text_field.id}": "Value", - f"field_{long_text_field.id}": "Value", - f"field_{integer_field.id}": 10, - f"field_{decimal_field.id}": 1022, - f"field_{date_field.id}": date(2020, 6, 17), - f"field_{date_time_field.id}": datetime( - 2020, 6, 17, 1, 30, 0, tzinfo=timezone.utc - ), - f"field_{boolean_field.id}": True, - f"field_{file_field.id}": [{"name": file_a.name}], - f"field_{single_select_field.id}_id": option_1.id, - f"field_{link_row_field.id}": [tmp_row.id], - f"field_{multiple_select_field.id}": [option_2.id], - }, - { - f"field_{text_field.id}": "other value", - f"field_{long_text_field.id}": " ", - f"field_{integer_field.id}": 0, - f"field_{decimal_field.id}": 0.00, - f"field_{date_field.id}": date(1970, 1, 1), - f"field_{date_time_field.id}": datetime( - 1970, 1, 1, 0, 0, 0, tzinfo=timezone.utc - ), - f"field_{boolean_field.id}": True, - f"field_{file_field.id}": [ - {"name": file_a.name}, - {"name": file_b.name}, - ], - f"field_{single_select_field.id}_id": option_1.id, - f"field_{link_row_field.id}": [tmp_row.id], - f"field_{multiple_select_field.id}": [option_2.id, option_3.id], - }, - ], - model=model, + row, row_2, row_3 = ( + RowHandler() + .create_rows( + user, + table, + [ + { + f"field_{text_field.id}": "", + f"field_{long_text_field.id}": "", + f"field_{integer_field.id}": None, + f"field_{decimal_field.id}": None, + f"field_{date_field.id}": None, + f"field_{date_time_field.id}": None, + f"field_{boolean_field.id}": False, + f"field_{file_field.id}": [], + f"field_{single_select_field.id}_id": None, + }, + { + f"field_{text_field.id}": "Value", + f"field_{long_text_field.id}": "Value", + f"field_{integer_field.id}": 10, + f"field_{decimal_field.id}": 1022, + f"field_{date_field.id}": date(2020, 6, 17), + f"field_{date_time_field.id}": datetime( + 2020, 6, 17, 1, 30, 0, tzinfo=timezone.utc + ), + f"field_{boolean_field.id}": True, + f"field_{file_field.id}": [{"name": file_a.name}], + f"field_{single_select_field.id}_id": option_1.id, + f"field_{link_row_field.id}": [tmp_row.id], + f"field_{multiple_select_field.id}": [option_2.id], + }, + { + f"field_{text_field.id}": "other value", + f"field_{long_text_field.id}": " ", + f"field_{integer_field.id}": 0, + f"field_{decimal_field.id}": 0.00, + f"field_{date_field.id}": date(1970, 1, 1), + f"field_{date_time_field.id}": datetime( + 1970, 1, 1, 0, 0, 0, tzinfo=timezone.utc + ), + f"field_{boolean_field.id}": True, + f"field_{file_field.id}": [ + {"name": file_a.name}, + {"name": file_b.name}, + ], + f"field_{single_select_field.id}_id": option_1.id, + f"field_{link_row_field.id}": [tmp_row.id], + f"field_{multiple_select_field.id}": [option_2.id, option_3.id], + }, + ], + model=model, + ) + .created_rows ) view_filter = data_fixture.create_view_filter( @@ -3434,38 +3462,42 @@ def test_not_empty_filter_type(data_fixture): handler = ViewHandler() model = table.get_model() - _, row_2 = RowHandler().create_rows( - user, - table, - rows_values=[ - { - f"field_{text_field.id}": "", - f"field_{long_text_field.id}": "", - f"field_{integer_field.id}": None, - f"field_{decimal_field.id}": None, - f"field_{date_field.id}": None, - f"field_{date_time_field.id}": None, - f"field_{boolean_field.id}": False, - f"field_{file_field.id}": [], - f"field_{single_select_field.id}": None, - }, - { - f"field_{text_field.id}": "Value", - f"field_{long_text_field.id}": "Value", - f"field_{integer_field.id}": 10, - f"field_{decimal_field.id}": 1022, - f"field_{date_field.id}": date(2020, 6, 17), - f"field_{date_time_field.id}": datetime( - 2020, 6, 17, 1, 30, 0, tzinfo=timezone.utc - ), - f"field_{boolean_field.id}": True, - f"field_{file_field.id}": [{"name": file_a.name}], - f"field_{single_select_field.id}_id": option_1.id, - f"field_{link_row_field.id}": [tmp_row.id], - f"field_{multiple_select_field.id}": [option_2.id, option_3.id], - }, - ], - model=model, + _, row_2 = ( + RowHandler() + .create_rows( + user, + table, + rows_values=[ + { + f"field_{text_field.id}": "", + f"field_{long_text_field.id}": "", + f"field_{integer_field.id}": None, + f"field_{decimal_field.id}": None, + f"field_{date_field.id}": None, + f"field_{date_time_field.id}": None, + f"field_{boolean_field.id}": False, + f"field_{file_field.id}": [], + f"field_{single_select_field.id}": None, + }, + { + f"field_{text_field.id}": "Value", + f"field_{long_text_field.id}": "Value", + f"field_{integer_field.id}": 10, + f"field_{decimal_field.id}": 1022, + f"field_{date_field.id}": date(2020, 6, 17), + f"field_{date_time_field.id}": datetime( + 2020, 6, 17, 1, 30, 0, tzinfo=timezone.utc + ), + f"field_{boolean_field.id}": True, + f"field_{file_field.id}": [{"name": file_a.name}], + f"field_{single_select_field.id}_id": option_1.id, + f"field_{link_row_field.id}": [tmp_row.id], + f"field_{multiple_select_field.id}": [option_2.id, option_3.id], + }, + ], + model=model, + ) + .created_rows ) view_filter = data_fixture.create_view_filter( @@ -5729,7 +5761,7 @@ def test_multiple_collaborators_empty_filter_type(data_fixture): multiple_collaborators_field.db_column: [], }, ], - ) + ).created_rows handler = ViewHandler() for field in [multiple_collaborators_field, ref_multiple_collaborators_field]: grid_view = data_fixture.create_grid_view(table=table) @@ -5786,7 +5818,7 @@ def test_multiple_collaborators_not_empty_filter_type(data_fixture): multiple_collaborators_field.db_column: [], }, ], - ) + ).created_rows handler = ViewHandler() for field in [multiple_collaborators_field, ref_multiple_collaborators_field]: grid_view = data_fixture.create_grid_view(table=table) @@ -5852,7 +5884,7 @@ def test_multiple_collaborators_has_filter_type(data_fixture): ], }, ], - ) + ).created_rows handler = ViewHandler() for field in [multiple_collaborators_field, ref_multiple_collaborators_field]: @@ -5980,7 +6012,7 @@ def test_multiple_collaborators_has_not_filter_type(data_fixture): ], }, ], - ) + ).created_rows handler = ViewHandler() for field in [multiple_collaborators_field, ref_multiple_collaborators_field]: @@ -6668,16 +6700,20 @@ def table_view_fields_rows(data_fixture): grid_view = data_fixture.create_grid_view(table=table) date_field = data_fixture.create_date_field(table=table) datetime_field = data_fixture.create_date_field(table=table, date_include_time=True) - rows = RowHandler().create_rows( - user, - table, - [ - { - date_field.db_column: date_value, - datetime_field.db_column: date_value, - } - for date_value in TEST_MULTI_STEP_DATE_OPERATORS_DATETIMES - ], + rows = ( + RowHandler() + .create_rows( + user, + table, + [ + { + date_field.db_column: date_value, + datetime_field.db_column: date_value, + } + for date_value in TEST_MULTI_STEP_DATE_OPERATORS_DATETIMES + ], + ) + .created_rows ) return table, grid_view, date_field, datetime_field, rows diff --git a/backend/tests/baserow/contrib/database/view/test_view_handler.py b/backend/tests/baserow/contrib/database/view/test_view_handler.py index 953b22fb0..be732551f 100755 --- a/backend/tests/baserow/contrib/database/view/test_view_handler.py +++ b/backend/tests/baserow/contrib/database/view/test_view_handler.py @@ -48,6 +48,7 @@ from baserow.contrib.database.views.handler import ( ViewIndexingHandler, ) from baserow.contrib.database.views.models import ( + DEFAULT_SORT_TYPE_KEY, OWNERSHIP_TYPE_COLLABORATIVE, FormView, GridView, @@ -794,6 +795,27 @@ def test_field_type_changed(data_fixture): assert ViewGroupBy.objects.all().count() == 0 +@pytest.mark.django_db +def test_field_type_changed_unsupported_order_by_type(data_fixture): + user = data_fixture.create_user() + table = data_fixture.create_database_table(user=user) + field = data_fixture.create_single_select_field(table=table) + grid_view = data_fixture.create_grid_view(table=table) + data_fixture.create_view_sort( + view=grid_view, field=field, order="ASC", type="order" + ) + data_fixture.create_view_group_by( + view=grid_view, field=field, order="ASC", type="order" + ) + + field_handler = FieldHandler() + long_text_field = field_handler.update_field( + user=user, field=field, new_type_name="text" + ) + assert ViewSort.objects.all().count() == 0 + assert ViewGroupBy.objects.all().count() == 0 + + @pytest.mark.django_db def test_field_type_single_field_num_queries(data_fixture, django_assert_num_queries): user = data_fixture.create_user() @@ -817,7 +839,7 @@ def test_field_type_single_field_num_queries(data_fixture, django_assert_num_que handler = ViewHandler() # Should be equal to the `test_field_type_changed_two_fields_num_queries`. - with django_assert_num_queries(9): + with django_assert_num_queries(11): handler.fields_type_changed([password_field_1]) assert ViewFilter.objects.all().count() == 0 @@ -864,7 +886,7 @@ def test_field_type_changed_two_fields_num_queries( handler = ViewHandler() # Should be equal to the `test_field_type_single_field_num_queries`. - with django_assert_num_queries(9): + with django_assert_num_queries(11): handler.fields_type_changed([password_field_1, password_field_2]) assert ViewFilter.objects.all().count() == 0 @@ -4093,7 +4115,9 @@ def test_get_group_by_on_all_fields_in_interesting_table(data_fixture): fields_to_group_by = [ field for field in all_fields - if field_type_registry.get_by_model(field).check_can_group_by(field) + if field_type_registry.get_by_model(field).check_can_group_by( + field, DEFAULT_SORT_TYPE_KEY + ) ] actual_result_per_field_name = {} @@ -4383,3 +4407,44 @@ def test_get_queryset_apply_sorts(data_fixture): row_ids = [row.id for row in rows] assert row_ids == [row_3.id, row_2.id, row_1.id] + + +@pytest.mark.django_db +def test_can_duplicate_views_with_multiple_collaborator_has_filter(data_fixture): + user_1 = data_fixture.create_user() + user_2 = data_fixture.create_user() + workspace = data_fixture.create_workspace(users=[user_1, user_2]) + database = data_fixture.create_database_application(workspace=workspace) + table = data_fixture.create_database_table(database=database) + field = data_fixture.create_multiple_collaborators_field(table=table) + grid = data_fixture.create_public_password_protected_grid_view(table=table, order=1) + view_filter = data_fixture.create_view_filter( + view=grid, field=field, type="multiple_collaborators_has", value=user_1.id + ) + + rows = ( + RowHandler() + .force_create_rows( + user_1, + table, + [ + {field.db_column: []}, + {field.db_column: [{"id": user_1.id, "name": user_1.first_name}]}, + {field.db_column: [{"id": user_2.id, "name": user_2.first_name}]}, + ], + ) + .created_rows + ) + + results = ViewHandler().get_queryset(grid) + assert len(results) == 1 + assert list(getattr(results[0], field.db_column).values_list("id", flat=True)) == [ + user_1.id + ] + + new_grid = ViewHandler().duplicate_view(user_1, grid) + new_results = ViewHandler().get_queryset(new_grid) + assert len(new_results) == 1 + assert list( + getattr(new_results[0], field.db_column).values_list("id", flat=True) + ) == [user_1.id] diff --git a/backend/tests/baserow/contrib/database/view/test_view_signals.py b/backend/tests/baserow/contrib/database/view/test_view_signals.py index c14703561..4955eb0d5 100644 --- a/backend/tests/baserow/contrib/database/view/test_view_signals.py +++ b/backend/tests/baserow/contrib/database/view/test_view_signals.py @@ -1,10 +1,18 @@ from unittest.mock import patch -import pytest +from django.db import transaction +import pytest +from freezegun import freeze_time + +from baserow.contrib.database.fields.handler import FieldHandler +from baserow.contrib.database.fields.tasks import run_periodic_fields_updates +from baserow.contrib.database.rows.handler import RowHandler +from baserow.contrib.database.views.handler import ViewHandler, ViewSubscriptionHandler from baserow.contrib.database.views.signals import ( view_loaded_create_indexes_and_columns, ) +from baserow.core.trash.handler import TrashHandler @patch("baserow.contrib.database.views.handler.ViewIndexingHandler") @@ -36,3 +44,491 @@ def test_view_loaded_creates_last_modified_by_column(indexing_handler, data_fixt None, view, table_model, table=table, user=user ) setup.delay.assert_called_once_with(table_id=view.table.id) + + +@pytest.mark.django_db +def test_rows_enter_and_exit_view_are_called_when_rows_updated(data_fixture): + user = data_fixture.create_user() + table_a, table_b, link_a_to_b = data_fixture.create_two_linked_tables() + + # Create a view per table and assert that the the signal is called for both tables + # when changing the link_a_to_b data + row_handler = RowHandler() + model_a = table_a.get_model() + model_b = table_b.get_model() + row_a = model_a.objects.create() + row_b = model_b.objects.create() + + view_a = data_fixture.create_grid_view(table=table_a) + view_a_has_row_b = data_fixture.create_view_filter( + view=view_a, field=link_a_to_b, type="link_row_has", value=row_b.id + ) + + view_b = data_fixture.create_grid_view(table=table_b) + view_b_has_row_a = data_fixture.create_view_filter( + view=view_b, + field=link_a_to_b.link_row_related_field, + type="link_row_has", + value=row_a.id, + ) + + with patch("baserow.contrib.database.views.signals.rows_entered_view.send") as p: + row_handler.force_update_rows( + user, + table_a, + [{"id": row_a.id, link_a_to_b.db_column: [row_b.id]}], + model_a, + ) + p.assert_not_called() + + # let's subscribe to the view in table_a first + ViewSubscriptionHandler.subscribe_to_views(user, [view_a]) + + with patch("baserow.contrib.database.views.signals.rows_exited_view.send") as p: + row_handler.force_update_rows( + user, table_a, [{"id": row_a.id, link_a_to_b.db_column: []}] + ) + p.assert_called_once() + assert p.call_args[1]["view"].id == view_a.id + assert p.call_args[1]["row_ids"] == [row_a.id] + + # Now let's subscribe also to the view in table_b and assert that the signal is + # called for both views + ViewSubscriptionHandler.subscribe_to_views(user, [view_b]) + + with patch("baserow.contrib.database.views.signals.rows_entered_view.send") as p: + row_handler.force_update_rows( + user, + table_a, + [{"id": row_a.id, link_a_to_b.db_column: [row_b.id]}], + model_a, + ) + assert p.call_count == 2 + assert p.call_args_list[0][1]["view"].id == view_a.id + assert p.call_args_list[1][1]["row_ids"] == [row_a.id] + assert p.call_args_list[1][1]["view"].id == view_b.id + assert p.call_args_list[1][1]["row_ids"] == [row_b.id] + + with patch("baserow.contrib.database.views.signals.rows_exited_view.send") as p: + row_handler.force_update_rows( + user, table_a, [{"id": row_a.id, link_a_to_b.db_column: []}] + ) + assert p.call_count == 2 + assert p.call_args_list[0][1]["view"].id == view_a.id + assert p.call_args_list[1][1]["row_ids"] == [row_a.id] + assert p.call_args_list[1][1]["view"].id == view_b.id + assert p.call_args_list[1][1]["row_ids"] == [row_b.id] + + # Once unsubcribed, the signal should not be sent anymore + ViewSubscriptionHandler.unsubscribe_from_views(user) + with patch("baserow.contrib.database.views.signals.rows_entered_view.send") as p: + row_handler.force_update_rows( + user, + table_a, + [{"id": row_a.id, link_a_to_b.db_column: [row_b.id]}], + model_a, + ) + p.assert_not_called() + + +@pytest.mark.django_db +def test_rows_enter_and_exit_view_are_called_when_rows_created_or_deleted( + data_fixture, +): + user = data_fixture.create_user() + table_a, table_b, link_a_to_b = data_fixture.create_two_linked_tables() + + row_handler = RowHandler() + model_a = table_a.get_model() + model_b = table_b.get_model() + row_b = model_b.objects.create() + + view_a = data_fixture.create_grid_view(table=table_a) + view_a_has_row_b = data_fixture.create_view_filter( + view=view_a, field=link_a_to_b, type="link_row_has", value=row_b.id + ) + + view_b = data_fixture.create_grid_view(table=table_b) + view_b_has_row_a = data_fixture.create_view_filter( + view=view_b, field=link_a_to_b.link_row_related_field, type="not_empty" + ) + + with patch("baserow.contrib.database.views.signals.rows_entered_view.send") as p: + (new_row,) = row_handler.force_create_rows( + user, table_a, [{link_a_to_b.db_column: [row_b.id]}], model=model_a + ).created_rows + p.assert_not_called() + + with patch("baserow.contrib.database.views.signals.rows_exited_view.send") as p: + row_handler.force_delete_rows(user, table_a, [new_row.id]) + p.assert_not_called() + + # let's subscribe to the view in table_a first + ViewSubscriptionHandler.subscribe_to_views(user, [view_a]) + + with patch("baserow.contrib.database.views.signals.rows_entered_view.send") as p: + (new_row,) = row_handler.force_create_rows( + user, table_a, [{link_a_to_b.db_column: [row_b.id]}], model=model_a + ).created_rows + p.assert_called_once() + assert p.call_args[1]["view"].id == view_a.id + assert p.call_args[1]["row_ids"] == [new_row.id] + + # Deleting the row should also trigger the signal + with patch("baserow.contrib.database.views.signals.rows_exited_view.send") as p: + row_handler.force_delete_rows(user, table_a, [new_row.id]) + p.assert_called_once() + assert p.call_args[1]["view"].id == view_a.id + assert p.call_args[1]["row_ids"] == [new_row.id] + + # Now let's subscribe also to the view in table_b and assert that the signal is + # called for both views + ViewSubscriptionHandler.subscribe_to_views(user, [view_b]) + + with patch("baserow.contrib.database.views.signals.rows_entered_view.send") as p: + (new_row,) = row_handler.force_create_rows( + user, table_a, [{link_a_to_b.db_column: [row_b.id]}], model=model_a + ).created_rows + assert p.call_count == 2 + assert p.call_args_list[0][1]["view"].id == view_a.id + assert p.call_args_list[0][1]["row_ids"] == [new_row.id] + assert p.call_args_list[1][1]["view"].id == view_b.id + assert p.call_args_list[1][1]["row_ids"] == [row_b.id] + + # Deleting the row should also trigger the signal for both views + with patch("baserow.contrib.database.views.signals.rows_exited_view.send") as p: + row_handler.force_delete_rows(user, table_a, [new_row.id]) + assert p.call_count == 2 + assert p.call_args_list[0][1]["view"].id == view_a.id + assert p.call_args_list[0][1]["row_ids"] == [new_row.id] + assert p.call_args_list[1][1]["view"].id == view_b.id + assert p.call_args_list[1][1]["row_ids"] == [row_b.id] + + # Once unsubcribed, the signal should not be sent anymore + ViewSubscriptionHandler.unsubscribe_from_views(user) + with patch("baserow.contrib.database.views.signals.rows_entered_view.send") as p: + (new_row,) = row_handler.force_create_rows( + user, table_a, [{link_a_to_b.db_column: [row_b.id]}], model=model_a + ).created_rows + p.assert_not_called() + + with patch("baserow.contrib.database.views.signals.rows_exited_view.send") as p: + row_handler.force_delete_rows(user, table_a, [new_row.id]) + p.assert_not_called() + + +@pytest.mark.django_db +def test_rows_enter_and_exit_view_are_called_when_view_filters_change( + data_fixture, +): + user = data_fixture.create_user() + table_a = data_fixture.create_database_table(user=user) + text_field = data_fixture.create_text_field(table=table_a) + + model_a = table_a.get_model() + + view_a = data_fixture.create_grid_view(table=table_a) + row_1 = model_a.objects.create() + row_2 = model_a.objects.create(**{text_field.db_column: "bbb"}) + + ViewSubscriptionHandler.subscribe_to_views(user, [view_a]) + + with patch("baserow.contrib.database.views.signals.rows_exited_view.send") as p: + view_filter_1 = ViewHandler().create_filter( + user, view_a, text_field, "equal", "aaa" + ) + p.assert_called_once() + assert p.call_args[1]["view"].id == view_a.id + assert p.call_args[1]["row_ids"] == [row_1.id, row_2.id] + + with patch("baserow.contrib.database.views.signals.rows_entered_view.send") as p: + view_filter_1 = ViewHandler().delete_filter(user, view_filter_1) + p.assert_called_once() + assert p.call_args[1]["view"].id == view_a.id + assert p.call_args[1]["row_ids"] == [row_1.id, row_2.id] + + with patch("baserow.contrib.database.views.signals.rows_exited_view.send") as p: + view_filter_2 = ViewHandler().create_filter( + user, view_a, text_field, "equal", "bbb" + ) + p.assert_called_once() + assert p.call_args[1]["view"].id == view_a.id + assert p.call_args[1]["row_ids"] == [row_1.id] + + with patch( + "baserow.contrib.database.views.signals.rows_entered_view.send" + ) as entered, patch( + "baserow.contrib.database.views.signals.rows_exited_view.send" + ) as exited: + view_filter_2 = ViewHandler().update_filter( + user, view_filter_2, type_name="empty" + ) + entered.assert_called_once() + assert entered.call_args[1]["view"].id == view_a.id + assert entered.call_args[1]["row_ids"] == [row_1.id] + + exited.assert_called_once() + assert exited.call_args[1]["view"].id == view_a.id + assert exited.call_args[1]["row_ids"] == [row_2.id] + + with patch("baserow.contrib.database.views.signals.rows_exited_view.send") as p: + view_filter_3 = ViewHandler().create_filter( + user, view_a, text_field, "equal", "bbb" + ) + p.assert_called_once() + assert p.call_args[1]["view"].id == view_a.id + assert p.call_args[1]["row_ids"] == [row_1.id] + + with patch("baserow.contrib.database.views.signals.rows_entered_view.send") as p: + ViewHandler().update_view(user, view_a, filters_disabled=True) + + p.assert_called_once() + assert p.call_args[1]["view"].id == view_a.id + assert p.call_args[1]["row_ids"] == [row_1.id, row_2.id] + + +@pytest.mark.django_db +def test_rows_enter_and_exit_view_are_called_when_view_filter_groups_change( + data_fixture, +): + user = data_fixture.create_user() + table_a = data_fixture.create_database_table(user=user) + text_field = data_fixture.create_text_field(table=table_a) + + model_a = table_a.get_model() + + view = data_fixture.create_grid_view(table=table_a) + row_1 = model_a.objects.create() + row_2 = model_a.objects.create(**{text_field.db_column: "bbb"}) + + ViewSubscriptionHandler.subscribe_to_views(user, [view]) + + with patch("baserow.contrib.database.views.signals.rows_exited_view.send") as p: + filter_group_1 = ViewHandler().create_filter_group(user, view) + p.assert_not_called() + + view_filter_1 = ViewHandler().create_filter( + user, view, text_field, "empty", "", filter_group_id=filter_group_1.id + ) + + p.assert_called_once() + assert p.call_args[1]["view"].id == view.id + assert p.call_args[1]["row_ids"] == [row_2.id] + + view_filter_2 = ViewHandler().create_filter( + user, view, text_field, "equal", "bbb", filter_group_id=filter_group_1.id + ) + + p.call_count == 2 + assert p.call_args[1]["view"].id == view.id + assert p.call_args[1]["row_ids"] == [row_1.id] + + with patch("baserow.contrib.database.views.signals.rows_entered_view.send") as p: + ViewHandler().update_filter_group(user, filter_group_1, filter_type="OR") + + p.assert_called_once() + assert p.call_args[1]["view"].id == view.id + assert p.call_args[1]["row_ids"] == [row_1.id, row_2.id] + + with patch("baserow.contrib.database.views.signals.rows_exited_view.send") as p: + filter_group_2 = ViewHandler().create_filter_group(user, view) + p.assert_not_called() + + view_filter_3 = ViewHandler().create_filter( + user, view, text_field, "equal", "aaa", filter_group_id=filter_group_2.id + ) + + p.assert_called_once() + assert p.call_args[1]["view"].id == view.id + assert p.call_args[1]["row_ids"] == [row_1.id, row_2.id] + + with patch("baserow.contrib.database.views.signals.rows_entered_view.send") as p: + ViewHandler().delete_filter_group(user, filter_group_2) + + p.assert_called_once() + assert p.call_args[1]["view"].id == view.id + assert p.call_args[1]["row_ids"] == [row_1.id, row_2.id] + + +@pytest.mark.django_db +def test_rows_enter_and_exit_view_are_called_when_fields_change( + data_fixture, +): + user = data_fixture.create_user() + table_a = data_fixture.create_database_table(user=user) + primary_field = data_fixture.create_text_field(table=table_a, primary=True) + text_field = data_fixture.create_text_field(table=table_a) + text_field_id = text_field.id + + model_a = table_a.get_model() + + view = data_fixture.create_grid_view(table=table_a) + row_1 = model_a.objects.create() + row_2 = model_a.objects.create(**{text_field.db_column: "bbb"}) + view_filter_1 = data_fixture.create_view_filter( + view=view, field=text_field, type="equal", value="bbb" + ) + + ViewSubscriptionHandler.subscribe_to_views(user, [view]) + + with patch("baserow.contrib.database.views.signals.rows_entered_view.send") as p: + FieldHandler().delete_field(user, text_field) + + p.assert_called_once() + assert p.call_args[1]["view"].id == view.id + assert p.call_args[1]["row_ids"] == [row_1.id] + + with patch("baserow.contrib.database.views.signals.rows_exited_view.send") as p: + TrashHandler.restore_item(user, "field", text_field_id) + + p.assert_called_once() + assert p.call_args[1]["view"].id == view.id + assert p.call_args[1]["row_ids"] == [row_1.id] + + with patch("baserow.contrib.database.views.signals.rows_entered_view.send") as p: + FieldHandler().update_field(user, text_field, new_type_name="number") + + p.assert_called_once() + assert p.call_args[1]["view"].id == view.id + assert p.call_args[1]["row_ids"] == [row_1.id] + + +@pytest.mark.django_db +def test_rows_enter_and_exit_view_with_periodic_fields_updates(data_fixture): + user = data_fixture.create_user() + + with freeze_time("2021-01-01"): + table = data_fixture.create_database_table(user=user) + now_field = data_fixture.create_formula_field( + table=table, formula="today()", name="today" + ) + year_field = data_fixture.create_formula_field( + table=table, formula="tonumber(datetime_format(field('today'), 'YYYY'))" + ) + + model = table.get_model() + + view = data_fixture.create_grid_view(table=table) + row_1 = model.objects.create() + view_filter_1 = data_fixture.create_view_filter( + view=view, field=year_field, type="equal", value="2022" + ) + + ViewSubscriptionHandler.subscribe_to_views(user, [view]) + + with patch( + "baserow.contrib.database.views.signals.rows_entered_view.send" + ) as p, freeze_time("2022-01-01"): + run_periodic_fields_updates(table.database.workspace_id) + + p.assert_called_once() + assert p.call_args[1]["view"].id == view.id + assert p.call_args[1]["row_ids"] == [row_1.id] + + with patch( + "baserow.contrib.database.views.signals.rows_exited_view.send" + ) as p, freeze_time("2023-01-01"): + run_periodic_fields_updates(table.database.workspace_id) + + p.assert_called_once() + assert p.call_args[1]["view"].id == view.id + assert p.call_args[1]["row_ids"] == [row_1.id] + + +@pytest.mark.django_db(transaction=True) +def test_rows_enter_and_exit_view_when_time_sensitive_filters_are_used( + data_fixture, +): + user = data_fixture.create_user() + + with freeze_time("2021-01-01"): + table = data_fixture.create_database_table(user=user) + date_field = data_fixture.create_date_field(table=table) + + model = table.get_model() + + view = data_fixture.create_grid_view(table=table) + row_1 = model.objects.create(**{date_field.db_column: "2022-01-01"}) + view_filter_1 = data_fixture.create_view_filter( + view=view, field=date_field, type="date_is", value="Europe/Rome??today" + ) + ViewSubscriptionHandler.subscribe_to_views(user, [view]) + + with patch( + "baserow.contrib.database.views.signals.rows_entered_view.send" + ) as p, freeze_time("2022-01-01"): + with transaction.atomic(): + ViewSubscriptionHandler.check_views_with_time_sensitive_filters() + + p.assert_called_once() + assert p.call_args[1]["view"].id == view.id + assert p.call_args[1]["row_ids"] == [row_1.id] + + with patch( + "baserow.contrib.database.views.signals.rows_exited_view.send" + ) as p, freeze_time("2022-01-02"): + with transaction.atomic(): + ViewSubscriptionHandler.check_views_with_time_sensitive_filters() + + p.assert_called_once() + assert p.call_args[1]["view"].id == view.id + assert p.call_args[1]["row_ids"] == [row_1.id] + + +@pytest.mark.django_db +def test_rows_enter_and_exit_view_when_data_changes_in_looked_up_tables( + data_fixture, +): + user = data_fixture.create_user() + table_a, table_b, link_a_to_b = data_fixture.create_two_linked_tables() + text_field_b = data_fixture.create_text_field(table=table_b) + lookup_field = data_fixture.create_lookup_field( + name="lookup", + table=table_a, + through_field=link_a_to_b, + target_field=text_field_b, + through_field_name=link_a_to_b.name, + target_field_name=text_field_b.name, + ) + + # Create a view per table and assert that the the signal is called for both tables + # when changing the link_a_to_b data + row_handler = RowHandler() + model_a = table_a.get_model() + model_b = table_b.get_model() + (row_b1,) = row_handler.force_create_rows( + user, table_b, [{text_field_b.db_column: ""}], model=model_b + ).created_rows + _, row_a2 = row_handler.force_create_rows( + user, table_a, [{}, {link_a_to_b.db_column: [row_b1.id]}], model=model_a + ).created_rows + + view_a = data_fixture.create_grid_view(table=table_a) + view_filter = data_fixture.create_view_filter( + view=view_a, field=lookup_field, type="has_not_empty_value", value="" + ) + + ViewSubscriptionHandler.subscribe_to_views(user, [view_a]) + with patch("baserow.contrib.database.views.signals.rows_entered_view.send") as p: + row_handler.force_update_rows( + user, table_b, [{"id": row_b1.id, text_field_b.db_column: "a"}], model_b + ) + p.assert_called_once() + assert p.call_args[1]["view"].id == view_a.id + assert p.call_args[1]["row_ids"] == [row_a2.id] + + (row_a3,) = row_handler.force_create_rows( + user, table_a, [{link_a_to_b.db_column: [row_b1.id]}], model=model_a + ).created_rows + + assert p.call_count == 2 + assert p.call_args_list[1][1]["view"].id == view_a.id + assert p.call_args_list[1][1]["row_ids"] == [row_a3.id] + + with patch("baserow.contrib.database.views.signals.rows_exited_view.send") as p: + row_handler.force_update_rows( + user, table_b, [{"id": row_b1.id, text_field_b.db_column: ""}], model_b + ) + p.assert_called_once() + assert p.call_args[1]["view"].id == view_a.id + assert p.call_args[1]["row_ids"] == [row_a2.id, row_a3.id] diff --git a/backend/tests/baserow/contrib/database/webhooks/test_webhook_notification_types.py b/backend/tests/baserow/contrib/database/webhooks/test_webhook_notification_types.py new file mode 100644 index 000000000..496096f06 --- /dev/null +++ b/backend/tests/baserow/contrib/database/webhooks/test_webhook_notification_types.py @@ -0,0 +1,76 @@ +from django.test import override_settings + +import pytest + +from baserow.contrib.database.webhooks.notification_types import ( + WebhookDeactivatedNotificationType, + WebhookPayloadTooLargeNotificationType, +) + + +@pytest.mark.django_db +def test_webhook_deactivated_notification_can_be_render_as_email(data_fixture): + user = data_fixture.create_user() + workspace = data_fixture.create_workspace(user=user) + database = data_fixture.create_database_application(workspace=workspace) + table = data_fixture.create_database_table(database=database) + webhook = data_fixture.create_table_webhook( + table=table, active=True, failed_triggers=1, name="test" + ) + + notification_recipients = ( + WebhookDeactivatedNotificationType.notify_admins_in_workspace(webhook) + ) + notification = notification_recipients[0].notification + + assert ( + WebhookDeactivatedNotificationType.get_notification_title_for_email( + notification, {} + ) + == "test webhook has been deactivated." + ) + + assert ( + WebhookDeactivatedNotificationType.get_notification_description_for_email( + notification, {} + ) + == "The webhook failed more than 8 consecutive times and " + "was therefore deactivated." + ) + + +@pytest.mark.django_db +@override_settings(BASEROW_WEBHOOKS_BATCH_LIMIT=1) +def test_webhook_payload_too_large_can_be_render_as_email(data_fixture): + user = data_fixture.create_user() + workspace = data_fixture.create_workspace(user=user) + database = data_fixture.create_database_application(workspace=workspace) + table = data_fixture.create_database_table(database=database) + webhook = data_fixture.create_table_webhook( + table=table, active=True, failed_triggers=1, name="test" + ) + + notification_recipients = ( + WebhookPayloadTooLargeNotificationType.notify_admins_in_workspace( + webhook, "123" + ) + ) + notification = notification_recipients[0].notification + + email_title = ( + WebhookPayloadTooLargeNotificationType.get_notification_title_for_email( + notification, {} + ) + ) + assert email_title == "test webhook payload too large." + + email_descr = ( + WebhookPayloadTooLargeNotificationType.get_notification_description_for_email( + notification, {} + ) + ) + assert email_descr == ( + "The payload for the test webhook with event ID 123 " + "was too large. The content has been split into multiple batches, but " + "data above the batch limit of 1 was discarded." + ) diff --git a/backend/tests/baserow/contrib/database/webhooks/test_webhook_tasks.py b/backend/tests/baserow/contrib/database/webhooks/test_webhook_tasks.py index 4532e61d0..7bdcfe144 100644 --- a/backend/tests/baserow/contrib/database/webhooks/test_webhook_tasks.py +++ b/backend/tests/baserow/contrib/database/webhooks/test_webhook_tasks.py @@ -1,4 +1,3 @@ -from collections import defaultdict from unittest.mock import MagicMock, patch from django.db import transaction @@ -10,35 +9,29 @@ import responses from celery.exceptions import Retry from baserow.contrib.database.webhooks.models import TableWebhook, TableWebhookCall -from baserow.contrib.database.webhooks.tasks import call_webhook -from baserow.core.redis import RedisQueue +from baserow.contrib.database.webhooks.notification_types import ( + WebhookDeactivatedNotificationType, + WebhookPayloadTooLargeNotificationType, +) +from baserow.contrib.database.webhooks.registries import WebhookEventType +from baserow.contrib.database.webhooks.tasks import ( + call_webhook, + enqueue_webhook_task, + schedule_next_task_in_queue, +) +from baserow.core.models import WorkspaceUser +from baserow.core.notifications.models import Notification +from baserow.core.redis import WebhookRedisQueue from baserow.test_utils.helpers import stub_getaddrinfo -class MemoryQueue(RedisQueue): - queues = defaultdict(list) - - def enqueue_task(self, task_object): - self.queues[self.queue_key].append(task_object) - return True - - def get_and_pop_next(self): - try: - self.queues[self.queue_key].pop(0) - except IndexError: - return None - - def clear(self): - self.queues[self.queue_key] = [] - - @pytest.mark.django_db(transaction=True) @responses.activate @override_settings( BASEROW_WEBHOOKS_MAX_RETRIES_PER_CALL=1, BASEROW_WEBHOOKS_MAX_CONSECUTIVE_TRIGGER_FAILURES=1, ) -@patch("baserow.contrib.database.webhooks.tasks.RedisQueue", MemoryQueue) +@patch("baserow.contrib.database.webhooks.tasks.RedisQueue", WebhookRedisQueue) @patch("baserow.contrib.database.webhooks.tasks.cache", MagicMock()) @patch("baserow.contrib.database.webhooks.tasks.clear_webhook_queue") def test_call_webhook_webhook_does_not_exist(mock_clear_queue): @@ -62,7 +55,7 @@ def test_call_webhook_webhook_does_not_exist(mock_clear_queue): BASEROW_WEBHOOKS_MAX_RETRIES_PER_CALL=1, BASEROW_WEBHOOKS_MAX_CONSECUTIVE_TRIGGER_FAILURES=1, ) -@patch("baserow.contrib.database.webhooks.tasks.RedisQueue", MemoryQueue) +@patch("baserow.contrib.database.webhooks.tasks.RedisQueue", WebhookRedisQueue) @patch("baserow.contrib.database.webhooks.tasks.cache", MagicMock()) def test_call_webhook_webhook_url_cannot_be_reached(data_fixture): webhook = data_fixture.create_table_webhook() @@ -102,7 +95,7 @@ def test_call_webhook_webhook_url_cannot_be_reached(data_fixture): BASEROW_WEBHOOKS_MAX_RETRIES_PER_CALL=1, BASEROW_WEBHOOKS_MAX_CONSECUTIVE_TRIGGER_FAILURES=1, ) -@patch("baserow.contrib.database.webhooks.tasks.RedisQueue", MemoryQueue) +@patch("baserow.contrib.database.webhooks.tasks.RedisQueue", WebhookRedisQueue) @patch("baserow.contrib.database.webhooks.tasks.cache", MagicMock()) def test_call_webhook_becomes_inactive_max_failed_reached(data_fixture): webhook = data_fixture.create_table_webhook(active=True, failed_triggers=1) @@ -130,7 +123,7 @@ def test_call_webhook_becomes_inactive_max_failed_reached(data_fixture): BASEROW_WEBHOOKS_MAX_RETRIES_PER_CALL=1, BASEROW_WEBHOOKS_MAX_CONSECUTIVE_TRIGGER_FAILURES=1, ) -@patch("baserow.contrib.database.webhooks.tasks.RedisQueue", MemoryQueue) +@patch("baserow.contrib.database.webhooks.tasks.RedisQueue", WebhookRedisQueue) @patch("baserow.contrib.database.webhooks.tasks.cache", MagicMock()) def test_call_webhook_skipped_because_not_active(data_fixture): webhook = data_fixture.create_table_webhook(active=False, failed_triggers=1) @@ -157,7 +150,7 @@ def test_call_webhook_skipped_because_not_active(data_fixture): BASEROW_WEBHOOKS_MAX_RETRIES_PER_CALL=1, BASEROW_WEBHOOKS_MAX_CONSECUTIVE_TRIGGER_FAILURES=1, ) -@patch("baserow.contrib.database.webhooks.tasks.RedisQueue", MemoryQueue) +@patch("baserow.contrib.database.webhooks.tasks.RedisQueue", WebhookRedisQueue) @patch("baserow.contrib.database.webhooks.tasks.cache", MagicMock()) def test_call_webhook_reset_after_success_call(data_fixture): webhook = data_fixture.create_table_webhook(failed_triggers=1) @@ -185,7 +178,7 @@ def test_call_webhook_reset_after_success_call(data_fixture): BASEROW_WEBHOOKS_MAX_RETRIES_PER_CALL=1, BASEROW_WEBHOOKS_MAX_CONSECUTIVE_TRIGGER_FAILURES=1, ) -@patch("baserow.contrib.database.webhooks.tasks.RedisQueue", MemoryQueue) +@patch("baserow.contrib.database.webhooks.tasks.RedisQueue", WebhookRedisQueue) @patch("baserow.contrib.database.webhooks.tasks.cache", MagicMock()) def test_call_webhook(data_fixture): webhook = data_fixture.create_table_webhook() @@ -245,7 +238,7 @@ def test_call_webhook(data_fixture): @pytest.mark.django_db(transaction=True, databases=["default", "default-copy"]) @responses.activate -@patch("baserow.contrib.database.webhooks.tasks.RedisQueue", MemoryQueue) +@patch("baserow.contrib.database.webhooks.tasks.RedisQueue", WebhookRedisQueue) @patch("baserow.contrib.database.webhooks.tasks.cache", MagicMock()) def test_call_webhook_concurrent_task_moved_to_queue(data_fixture): from baserow.contrib.database.webhooks.tasks import get_queue @@ -274,7 +267,7 @@ def test_call_webhook_concurrent_task_moved_to_queue(data_fixture): @pytest.mark.django_db(transaction=True, databases=["default"]) @responses.activate -@patch("baserow.contrib.database.webhooks.tasks.RedisQueue", MemoryQueue) +@patch("baserow.contrib.database.webhooks.tasks.RedisQueue", WebhookRedisQueue) @patch("baserow.contrib.database.webhooks.tasks.cache", MagicMock()) @patch("baserow.contrib.database.webhooks.tasks.schedule_next_task_in_queue") def test_call_webhook_next_item_scheduled(mock_schedule, data_fixture): @@ -301,7 +294,7 @@ def test_call_webhook_next_item_scheduled(mock_schedule, data_fixture): BASEROW_WEBHOOKS_MAX_CONSECUTIVE_TRIGGER_FAILURES=0, ) @httpretty.activate(verbose=True, allow_net_connect=False) -@patch("baserow.contrib.database.webhooks.tasks.RedisQueue", MemoryQueue) +@patch("baserow.contrib.database.webhooks.tasks.RedisQueue", WebhookRedisQueue) @patch("baserow.contrib.database.webhooks.tasks.cache", MagicMock()) @patch("socket.getaddrinfo", wraps=stub_getaddrinfo) def test_cant_call_webhook_to_localhost_when_private_addresses_not_allowed( @@ -334,7 +327,7 @@ def test_cant_call_webhook_to_localhost_when_private_addresses_not_allowed( BASEROW_WEBHOOKS_MAX_RETRIES_PER_CALL=0, BASEROW_WEBHOOKS_MAX_CONSECUTIVE_TRIGGER_FAILURES=0, ) -@patch("baserow.contrib.database.webhooks.tasks.RedisQueue", MemoryQueue) +@patch("baserow.contrib.database.webhooks.tasks.RedisQueue", WebhookRedisQueue) @patch("baserow.contrib.database.webhooks.tasks.cache", MagicMock()) def test_can_call_webhook_to_localhost_when_private_addresses_allowed( data_fixture, @@ -361,3 +354,252 @@ def test_can_call_webhook_to_localhost_when_private_addresses_allowed( assert not call.error assert call.response_status == 201 assert webhook.active + + +@pytest.mark.django_db(transaction=True) +@responses.activate +@override_settings( + BASEROW_WEBHOOKS_MAX_RETRIES_PER_CALL=1, + BASEROW_WEBHOOKS_MAX_CONSECUTIVE_TRIGGER_FAILURES=1, +) +@patch("baserow.contrib.database.webhooks.tasks.RedisQueue", WebhookRedisQueue) +@patch("baserow.contrib.database.webhooks.tasks.cache", MagicMock()) +@patch("baserow.ws.tasks.broadcast_to_users.apply") +def test_call_webhook_failed_reached_notification_send( + mocked_broadcast_to_users, data_fixture +): + user_1 = data_fixture.create_user() + user_2 = data_fixture.create_user() + admin_1 = data_fixture.create_user() + admin_2 = data_fixture.create_user() + workspace = data_fixture.create_workspace() + + WorkspaceUser.objects.create( + user=user_1, workspace=workspace, order=1, permissions="MEMBER" + ) + WorkspaceUser.objects.create( + user=user_2, workspace=workspace, order=2, permissions="MEMBER" + ) + WorkspaceUser.objects.create( + user=admin_1, workspace=workspace, order=3, permissions="ADMIN" + ) + WorkspaceUser.objects.create( + user=admin_2, workspace=workspace, order=4, permissions="ADMIN" + ) + + database = data_fixture.create_database_application(workspace=workspace) + table = data_fixture.create_database_table(database=database) + webhook = data_fixture.create_table_webhook( + table=table, active=True, failed_triggers=1 + ) + + call_webhook.push_request(retries=1) + call_webhook.run( + webhook_id=webhook.id, + event_id="00000000-0000-0000-0000-000000000000", + event_type="rows.created", + method="POST", + url="http://localhost/", + headers={"Baserow-header-1": "Value 1"}, + payload={"type": "rows.created"}, + ) + + all_notifications = list(Notification.objects.all()) + assert len(all_notifications) == 1 + recipient_ids = [r.id for r in all_notifications[0].recipients.all()] + assert recipient_ids == [admin_1.id, admin_2.id] + assert all_notifications[0].type == WebhookDeactivatedNotificationType.type + assert all_notifications[0].broadcast is False + assert all_notifications[0].workspace_id == workspace.id + assert all_notifications[0].sender is None + assert all_notifications[0].data == { + "database_id": database.id, + "table_id": table.id, + "webhook_id": webhook.id, + "webhook_name": webhook.name, + } + + # the webhook should be deactivated after the notification is sent. + webhook.refresh_from_db() + assert webhook.active is False + + +class PaginatedWebhookEventType(WebhookEventType): + type = "test.paginated" + + def __init__(self): + self.i = 1 + + def _paginate_payload(self, webhook, event_id, payload) -> tuple[dict, dict | None]: + payload["data"] = f"part {self.i}" + self.i += 1 + return payload, {"data": f"part {self.i}"} + + +@pytest.mark.django_db(transaction=True) +@responses.activate +@patch("baserow.contrib.database.webhooks.tasks.RedisQueue", WebhookRedisQueue) +@patch("baserow.contrib.database.webhooks.tasks.cache", MagicMock()) +def test_webhook_with_paginated_payload( + mutable_webhook_event_type_registry, data_fixture +): + mutable_webhook_event_type_registry.register(PaginatedWebhookEventType()) + + webhook = data_fixture.create_table_webhook() + responses.add(responses.POST, "http://localhost/", json={}, status=200) + event_id = "00000000-0000-0000-0000-000000000002" + expected_payload = ( + webhook.id, + event_id, + "test.paginated", + "POST", + "http://localhost/", + {}, + {"batch_id": 2, "data": "part 2"}, + ) + + # The first page of the payload is sent and contains the batch_id 1. + with patch( + "baserow.contrib.database.webhooks.tasks.enqueue_webhook_task" + ) as mock_enqueue, patch( + "baserow.contrib.database.webhooks.tasks.schedule_next_task_in_queue" + ) as mock_schedule: + call_webhook( + webhook_id=webhook.id, + event_id=event_id, + event_type="test.paginated", + method="POST", + url="http://localhost/", + headers={}, + payload={}, + ) + + assert mock_enqueue.call_args[0][2] == expected_payload + mock_schedule.assert_called_with(webhook.id) + + assert TableWebhookCall.objects.all().count() == 1 + assert TableWebhookCall.objects.filter(event_id=event_id).first().batch_id == 1 + + # we mocked this function to ensure the enqueued payload is correct, now if we call + # the function again, we should see the next batch_id being sent. + enqueue_webhook_task(webhook.id, event_id, expected_payload, {}) + + with patch( + "baserow.contrib.database.webhooks.tasks.enqueue_webhook_task" + ) as mock_enqueue: + schedule_next_task_in_queue(webhook.id) + assert mock_enqueue.call_args[0][2] == ( + webhook.id, + event_id, + "test.paginated", + "POST", + "http://localhost/", + {}, + {"batch_id": 3, "data": "part 3"}, + ) + assert TableWebhookCall.objects.all().count() == 2 + # Same event_id, but different batch_id. + assert TableWebhookCall.objects.filter(event_id=event_id).first().batch_id == 2 + + +@pytest.mark.django_db(transaction=True) +@responses.activate +@override_settings(BASEROW_WEBHOOKS_BATCH_LIMIT=1) +@patch("baserow.contrib.database.webhooks.tasks.RedisQueue", WebhookRedisQueue) +@patch("baserow.contrib.database.webhooks.tasks.cache", MagicMock()) +@patch("baserow.ws.tasks.broadcast_to_users.apply") +def test_call_webhook_payload_too_large_send_notification( + mocked_broadcast_to_users, mutable_webhook_event_type_registry, data_fixture +): + user_1 = data_fixture.create_user() + user_2 = data_fixture.create_user() + admin_1 = data_fixture.create_user() + admin_2 = data_fixture.create_user() + workspace = data_fixture.create_workspace() + + WorkspaceUser.objects.create( + user=user_1, workspace=workspace, order=1, permissions="MEMBER" + ) + WorkspaceUser.objects.create( + user=user_2, workspace=workspace, order=2, permissions="MEMBER" + ) + WorkspaceUser.objects.create( + user=admin_1, workspace=workspace, order=3, permissions="ADMIN" + ) + WorkspaceUser.objects.create( + user=admin_2, workspace=workspace, order=4, permissions="ADMIN" + ) + + database = data_fixture.create_database_application(workspace=workspace) + table = data_fixture.create_database_table(database=database) + + mutable_webhook_event_type_registry.register(PaginatedWebhookEventType()) + webhook = data_fixture.create_table_webhook(table=table, active=True) + responses.add(responses.POST, "http://localhost/", json={}, status=200) + event_id = "00000000-0000-0000-0000-000000000002" + expected_payload = ( + webhook.id, + event_id, + "test.paginated", + "POST", + "http://localhost/", + {}, + {"batch_id": 2, "data": "part 2"}, + ) + + # The first page of the payload is sent and contains the batch_id 1. + with patch( + "baserow.contrib.database.webhooks.tasks.enqueue_webhook_task" + ) as mock_enqueue, patch( + "baserow.contrib.database.webhooks.tasks.schedule_next_task_in_queue" + ) as mock_schedule: + call_webhook( + webhook_id=webhook.id, + event_id=event_id, + event_type="test.paginated", + method="POST", + url="http://localhost/", + headers={}, + payload={}, + ) + + assert mock_enqueue.call_args[0][2] == expected_payload + mock_schedule.assert_called_with(webhook.id) + + assert TableWebhookCall.objects.all().count() == 1 + assert TableWebhookCall.objects.filter(event_id=event_id).first().batch_id == 1 + + # The second part of the payload exceeds the batch limit of 1. Therefore, it should + # not send the data but should trigger a notification. + enqueue_webhook_task(webhook.id, event_id, expected_payload, {}) + schedule_next_task_in_queue(webhook.id) + + # No new call should be made. + assert TableWebhookCall.objects.all().count() == 1 + + all_notifications = list(Notification.objects.all()) + assert len(all_notifications) == 1 + recipient_ids = [r.id for r in all_notifications[0].recipients.all()] + assert recipient_ids == [admin_1.id, admin_2.id] + assert all_notifications[0].type == WebhookPayloadTooLargeNotificationType.type + assert all_notifications[0].broadcast is False + assert all_notifications[0].workspace_id == workspace.id + assert all_notifications[0].sender is None + assert all_notifications[0].data == { + "database_id": database.id, + "table_id": table.id, + "webhook_id": webhook.id, + "webhook_name": webhook.name, + "event_id": event_id, + "batch_limit": 1, + } + + # The webhook should still be active, but the queue should be empty. + webhook.refresh_from_db() + assert webhook.active is True + + with patch("baserow.contrib.database.webhooks.tasks.call_webhook.delay") as mock: + schedule_next_task_in_queue(webhook.id) + mock.assert_not_called() # nothing else has been scheduled. + + assert TableWebhookCall.objects.all().count() == 1 diff --git a/backend/tests/baserow/contrib/database/ws/public/test_public_ws_rows_signals.py b/backend/tests/baserow/contrib/database/ws/public/test_public_ws_rows_signals.py index ae4479c91..44010cb67 100644 --- a/backend/tests/baserow/contrib/database/ws/public/test_public_ws_rows_signals.py +++ b/backend/tests/baserow/contrib/database/ws/public/test_public_ws_rows_signals.py @@ -203,10 +203,14 @@ def test_batch_rows_created_public_views_receive_restricted_row_created_ws_event {f"field_{visible_field.id}": "Visible", f"field_{hidden_field.id}": "Hidden"}, ] - rows = RowHandler().create_rows( - user=user, - table=table, - rows_values=rows_to_create, + rows = ( + RowHandler() + .create_rows( + user=user, + table=table, + rows_values=rows_to_create, + ) + .created_rows ) assert mock_broadcast_to_channel_group.delay.mock_calls == ( @@ -316,10 +320,14 @@ def test_batch_rows_created_public_views_receive_row_created_when_filters_match( {f"field_{visible_field.id}": "Visible", f"field_{hidden_field.id}": "Hidden"}, ] - rows = RowHandler().create_rows( - user=user, - table=table, - rows_values=rows_to_create, + rows = ( + RowHandler() + .create_rows( + user=user, + table=table, + rows_values=rows_to_create, + ) + .created_rows ) assert mock_broadcast_to_channel_group.delay.mock_calls == ( diff --git a/backend/tests/baserow/contrib/integrations/local_baserow/service_types/test_aggregate_rows_service_type.py b/backend/tests/baserow/contrib/integrations/local_baserow/service_types/test_aggregate_rows_service_type.py index ea6e7e251..e9298ac1a 100644 --- a/backend/tests/baserow/contrib/integrations/local_baserow/service_types/test_aggregate_rows_service_type.py +++ b/backend/tests/baserow/contrib/integrations/local_baserow/service_types/test_aggregate_rows_service_type.py @@ -587,3 +587,29 @@ def test_local_baserow_aggregate_rows_dispatch_data_field_type_not_compatible_an exc.value.args[0] == f"The field with ID {field.id} is not compatible " f"with the aggregation type {service.aggregation_type}" ) + + +@pytest.mark.django_db +def test_create_local_baserow_aggregate_rows_service_with_unsupported_aggregation_type( + data_fixture, +): + user = data_fixture.create_user() + page = data_fixture.create_builder_page(user=user) + dashboard = page.builder + table = data_fixture.create_database_table(user=user) + field = data_fixture.create_number_field(table=table) + view = data_fixture.create_grid_view(user=user, table=table) + integration = data_fixture.create_local_baserow_integration( + application=dashboard, user=user + ) + service = data_fixture.create_local_baserow_aggregate_rows_service( + table=table, field=field, integration=integration + ) + service_type = service.get_type() + unsupported_agg_type = service_type.unsupported_aggregation_types[0] + + with pytest.raises( + ValidationError, + match=f"The {unsupported_agg_type} aggregation type is not currently supported.", + ): + service_type.prepare_values({"aggregation_type": unsupported_agg_type}, user) diff --git a/backend/tests/baserow/contrib/integrations/local_baserow/service_types/test_list_rows_service_type.py b/backend/tests/baserow/contrib/integrations/local_baserow/service_types/test_list_rows_service_type.py index 94e1423c9..886811cea 100644 --- a/backend/tests/baserow/contrib/integrations/local_baserow/service_types/test_list_rows_service_type.py +++ b/backend/tests/baserow/contrib/integrations/local_baserow/service_types/test_list_rows_service_type.py @@ -322,14 +322,18 @@ def test_local_baserow_list_rows_service_dispatch_data_with_view_and_service_fil ], ) field = table.field_set.get(name="Ingredient") - [row_1, row_2, _] = RowHandler().create_rows( - user, - table, - rows_values=[ - {f"field_{field.id}": "Cheese"}, - {f"field_{field.id}": "Chicken"}, - {f"field_{field.id}": "Milk"}, - ], + [row_1, row_2, _] = ( + RowHandler() + .create_rows( + user, + table, + rows_values=[ + {f"field_{field.id}": "Cheese"}, + {f"field_{field.id}": "Chicken"}, + {f"field_{field.id}": "Milk"}, + ], + ) + .created_rows ) view = data_fixture.create_grid_view(user, table=table, owned_by=user) @@ -385,15 +389,19 @@ def test_local_baserow_list_rows_service_dispatch_data_with_varying_filter_types ) ingredient = table.field_set.get(name="Ingredient") cost = table.field_set.get(name="Cost") - [row_1, row_2, row_3, _] = RowHandler().create_rows( - user, - table, - rows_values=[ - {f"field_{ingredient.id}": "Duck", f"field_{cost.id}": 50}, - {f"field_{ingredient.id}": "Duckling", f"field_{cost.id}": 25}, - {f"field_{ingredient.id}": "Goose", f"field_{cost.id}": 150}, - {f"field_{ingredient.id}": "Beef", f"field_{cost.id}": 250}, - ], + [row_1, row_2, row_3, _] = ( + RowHandler() + .create_rows( + user, + table, + rows_values=[ + {f"field_{ingredient.id}": "Duck", f"field_{cost.id}": 50}, + {f"field_{ingredient.id}": "Duckling", f"field_{cost.id}": 25}, + {f"field_{ingredient.id}": "Goose", f"field_{cost.id}": 150}, + {f"field_{ingredient.id}": "Beef", f"field_{cost.id}": 250}, + ], + ) + .created_rows ) view = data_fixture.create_grid_view( @@ -470,14 +478,18 @@ def test_local_baserow_list_rows_service_dispatch_data_with_view_and_service_sor ) ingredients = table.field_set.get(name="Ingredient") cost = table.field_set.get(name="Cost") - [row_1, row_2, row_3] = RowHandler().create_rows( - user, - table, - rows_values=[ - {f"field_{ingredients.id}": "Duck", f"field_{cost.id}": 50}, - {f"field_{ingredients.id}": "Goose", f"field_{cost.id}": 150}, - {f"field_{ingredients.id}": "Beef", f"field_{cost.id}": 250}, - ], + [row_1, row_2, row_3] = ( + RowHandler() + .create_rows( + user, + table, + rows_values=[ + {f"field_{ingredients.id}": "Duck", f"field_{cost.id}": 50}, + {f"field_{ingredients.id}": "Goose", f"field_{cost.id}": 150}, + {f"field_{ingredients.id}": "Beef", f"field_{cost.id}": 250}, + ], + ) + .created_rows ) view = data_fixture.create_grid_view(user, table=table, owned_by=user) service_type = LocalBaserowListRowsUserServiceType() diff --git a/backend/tests/baserow/contrib/integrations/local_baserow/service_types/test_upsert_row_service_type.py b/backend/tests/baserow/contrib/integrations/local_baserow/service_types/test_upsert_row_service_type.py index c1d8ce9d1..eb4570bcd 100644 --- a/backend/tests/baserow/contrib/integrations/local_baserow/service_types/test_upsert_row_service_type.py +++ b/backend/tests/baserow/contrib/integrations/local_baserow/service_types/test_upsert_row_service_type.py @@ -599,7 +599,7 @@ def test_export_import_local_baserow_upsert_row_service( imported_table = imported_database.table_set.get() imported_field = imported_table.field_set.get() - imported_page = imported_builder.page_set.get() + imported_page = imported_builder.visible_pages.get() imported_data_source = imported_page.datasource_set.get() imported_integration = imported_builder.integrations.get() imported_upsert_row_service = LocalBaserowUpsertRow.objects.get( diff --git a/backend/tests/baserow/contrib/integrations/local_baserow/test_mixins.py b/backend/tests/baserow/contrib/integrations/local_baserow/test_mixins.py index e6e4db7e1..e98bc064b 100644 --- a/backend/tests/baserow/contrib/integrations/local_baserow/test_mixins.py +++ b/backend/tests/baserow/contrib/integrations/local_baserow/test_mixins.py @@ -44,15 +44,19 @@ def test_local_baserow_table_service_filterable_mixin_get_table_queryset( table_model = table.get_model() service = data_fixture.create_local_baserow_list_rows_service(table=table) - [alessia, alex, alastair, alexandra] = RowHandler().create_rows( - user, - table, - rows_values=[ - {f"field_{field.id}": "Alessia"}, - {f"field_{field.id}": "Alex"}, - {f"field_{field.id}": "Alastair"}, - {f"field_{field.id}": "Alexandra"}, - ], + [alessia, alex, alastair, alexandra] = ( + RowHandler() + .create_rows( + user, + table, + rows_values=[ + {f"field_{field.id}": "Alessia"}, + {f"field_{field.id}": "Alex"}, + {f"field_{field.id}": "Alastair"}, + {f"field_{field.id}": "Alexandra"}, + ], + ) + .created_rows ) dispatch_context = FakeDispatchContext() @@ -173,7 +177,7 @@ def test_local_baserow_table_service_filterable_mixin_import_export(data_fixture imported_select_option = imported_single_select_field.select_options.get() # Pluck out the imported builder records. - imported_page = imported_builder.page_set.get() + imported_page = imported_builder.visible_pages.get() imported_datasource = imported_page.datasource_set.get() imported_filters = [ {"field_id": sf.field_id, "value": sf.value} @@ -254,15 +258,19 @@ def test_local_baserow_table_service_sortable_mixin_get_table_queryset( table_model = table.get_model() service = data_fixture.create_local_baserow_list_rows_service(table=table) - [aardvark, badger, crow, dragonfly] = RowHandler().create_rows( - user, - table, - rows_values=[ - {f"field_{field.id}": "Aardvark"}, - {f"field_{field.id}": "Badger"}, - {f"field_{field.id}": "Crow"}, - {f"field_{field.id}": "Dragonfly"}, - ], + [aardvark, badger, crow, dragonfly] = ( + RowHandler() + .create_rows( + user, + table, + rows_values=[ + {f"field_{field.id}": "Aardvark"}, + {f"field_{field.id}": "Badger"}, + {f"field_{field.id}": "Crow"}, + {f"field_{field.id}": "Dragonfly"}, + ], + ) + .created_rows ) dispatch_context = FakeDispatchContext() @@ -357,15 +365,19 @@ def test_local_baserow_table_service_searchable_mixin_get_table_queryset( table = data_fixture.create_database_table(user=user) field = data_fixture.create_text_field(name="Names", table=table) service = data_fixture.create_local_baserow_list_rows_service(table=table) - [alessia, alex, alastair, alexandra] = RowHandler().create_rows( - user, - table, - rows_values=[ - {f"field_{field.id}": "Alessia"}, - {f"field_{field.id}": "Alex"}, - {f"field_{field.id}": "Alastair"}, - {f"field_{field.id}": "Alexandra"}, - ], + [alessia, alex, alastair, alexandra] = ( + RowHandler() + .create_rows( + user, + table, + rows_values=[ + {f"field_{field.id}": "Alessia"}, + {f"field_{field.id}": "Alex"}, + {f"field_{field.id}": "Alastair"}, + {f"field_{field.id}": "Alexandra"}, + ], + ) + .created_rows ) table_model = table.get_model() diff --git a/backend/tests/baserow/core/test_basic_permissions.py b/backend/tests/baserow/core/test_basic_permissions.py index ab0c3d517..39e03c813 100755 --- a/backend/tests/baserow/core/test_basic_permissions.py +++ b/backend/tests/baserow/core/test_basic_permissions.py @@ -1153,6 +1153,9 @@ def test_allow_if_template_permission_manager_query_count(data_fixture): integration_1 = data_fixture.create_integration_with_first_type( application=application_1 ) + # Make sure settings exists, otherwise the first time they will be created and + # the query count will be off. + CoreHandler().get_settings() with CaptureQueriesContext(connection) as query_for_template: CoreHandler().check_permissions( diff --git a/backend/tests/baserow/core/test_core_handler.py b/backend/tests/baserow/core/test_core_handler.py index 4706ca5f2..5a4ff427c 100755 --- a/backend/tests/baserow/core/test_core_handler.py +++ b/backend/tests/baserow/core/test_core_handler.py @@ -1330,6 +1330,34 @@ def test_sync_templates(data_fixture, tmpdir): settings.APPLICATION_TEMPLATES_DIR = old_templates +@pytest.mark.django_db +def test_sync_templates_mapped_open_application_id(data_fixture, tmpdir): + old_templates = settings.APPLICATION_TEMPLATES_DIR + settings.APPLICATION_TEMPLATES_DIR = os.path.join( + settings.BASE_DIR, "../../../tests/templates" + ) + + storage = FileSystemStorage(location=str(tmpdir), base_url="http://localhost") + + handler = CoreHandler() + handler.sync_templates(storage=storage) + + template_1 = Template.objects.get(slug="example-template") + template_2 = Template.objects.get(slug="example-template-2") + + application = template_2.workspace.application_set.all().first() + + assert template_1.open_application is None + assert template_2.open_application == application.id + + handler.sync_templates(storage=storage) + + assert template_1.open_application is None + assert template_2.open_application == application.id + + settings.APPLICATION_TEMPLATES_DIR = old_templates + + @pytest.mark.django_db @patch("baserow.core.signals.application_created.send") def test_install_template(send_mock, tmpdir, data_fixture): diff --git a/backend/tests/baserow/core/test_core_utils_cache.py b/backend/tests/baserow/core/test_core_utils_cache.py index f40e1201c..1d9518864 100755 --- a/backend/tests/baserow/core/test_core_utils_cache.py +++ b/backend/tests/baserow/core/test_core_utils_cache.py @@ -1,132 +1,123 @@ -from django.core.cache import cache - -from baserow.core.utils import invalidate_versioned_cache, safe_get_or_set_cache +from baserow.core.cache import GlobalCache -def test_safe_get_or_set_cache_literally_stores_default(): +def test_local_cache_get_literally_stores_default(): """If the cache is empty, a literal default value is stored and returned.""" cache_key = "test_literal_default" - cache.delete(cache_key) - result = safe_get_or_set_cache( - cache_key=cache_key, + result = GlobalCache().get( + key=cache_key, default="my_default_value", - timeout=60, + timeout=6, ) assert result == "my_default_value" - assert cache.get(cache_key) == "my_default_value" -def test_safe_get_or_set_cache_callable_stores_return_value(): +def test_local_cache_get_callable_stores_return_value(): """ If the cache is empty, a callable default's return value is stored and returned. """ cache_key = "test_callable_default" - cache.delete(cache_key) def some_callable(): return "callable_value" - result = safe_get_or_set_cache( - cache_key=cache_key, + result = GlobalCache().get( + key=cache_key, default=some_callable, - timeout=60, + timeout=6, ) assert result == "callable_value" - assert cache.get(cache_key) == "callable_value" -def test_safe_get_or_set_cache_uses_existing_value(): +def test_local_cache_get_uses_existing_value(): """ If the cache key already has a value, it should be returned without overwriting. """ cache_key = "test_existing" - cache.delete(cache_key) - cache.set(cache_key, "existing_value", 60) - result = safe_get_or_set_cache( - cache_key=cache_key, + result = GlobalCache().get( + key=cache_key, + default="existing_value", + timeout=60, + ) + + result = GlobalCache().get( + key=cache_key, default="unused_default", - timeout=60, + timeout=6, ) + assert result == "existing_value" - # Confirm it didn't overwrite with 'unused_default' - assert cache.get(cache_key) == "existing_value" -def test_versioned_cache_set_and_retrieve(): +def test_versioned_cache_invalidation(): """ - When a version_cache_key is given and the value does not exist, - it should store and retrieve the value under <cache_key>__version_X. - """ - - base_key = "test_versioned_base" - version_cache_key = "test_versioned_key" - cache.delete(base_key) - cache.delete(version_cache_key) - - # No version exists, so this should initialize version=0 - result = safe_get_or_set_cache( - cache_key=base_key, - version_cache_key=version_cache_key, - default="versioned_value", - timeout=60, - ) - assert result == "versioned_value" - # Confirm the value is stored under the versioned key - assert cache.get(f"{base_key}__version_0") == "versioned_value" - - -def test_versioned_cache_hit(): - """ - If a versioned key already exists, safe_get_or_set_cache should retrieve + If a versioned key already exists, local_cache_get should retrieve that existing value rather than setting a new one. """ base_key = "test_versioned_base2" - version_cache_key = "test_versioned_key2" - cache.delete(base_key) - cache.delete(version_cache_key) - # Manually set version=5 - cache.set(version_cache_key, 5) - full_key = f"{base_key}__version_5" - cache.set(full_key, "already_versioned", 60) - - result = safe_get_or_set_cache( - cache_key=base_key, - version_cache_key=version_cache_key, - default="unused_default", - timeout=60, + result = GlobalCache().get( + key=base_key, + default="already_versioned", + timeout=6, ) - assert result == "already_versioned" - assert cache.get(full_key) == "already_versioned" + + GlobalCache().invalidate(base_key) + + result = GlobalCache().get( + key=base_key, + default="new_value", + timeout=6, + ) + + assert result == "new_value" -def test_invalidate_versioned_cache_increments_existing(): +def test_versioned_cache_invalidation_with_invalidation_key(): """ - If a version_cache_key already exists, calling invalidate_versioned_cache should - increment the version. + If a versioned key already exists, local_cache_get should retrieve + that existing value rather than setting a new one. """ - version_key = "test_invalidate_existing" - cache.set(version_key, 3) + base_key = "test_versioned_base3_" + invalidate_key = "test_invalidate_key" - invalidate_versioned_cache(version_key) - assert cache.get(version_key) == 4 + result = GlobalCache().get( + key=base_key + "1", + invalidate_key=invalidate_key, + default="already_versioned", + timeout=6, + ) + result = GlobalCache().get( + key=base_key + "2", + invalidate_key=invalidate_key, + default="already_versioned", + timeout=6, + ) -def test_invalidate_versioned_cache_sets_new_if_absent(): - """ - If a versioned cache key doesn't exist, calling invalidate_versioned_cache should - create it and set it to 1. - """ + GlobalCache().invalidate(invalidate_key=invalidate_key) - version_key = "test_invalidate_absent" - cache.delete(version_key) + result = GlobalCache().get( + key=base_key + "1", + invalidate_key=invalidate_key, + default="new_value", + timeout=6, + ) - invalidate_versioned_cache(version_key) - assert cache.get(version_key) == 1 + assert result == "new_value" + + result = GlobalCache().get( + key=base_key + "2", + invalidate_key=invalidate_key, + default="new_value", + timeout=6, + ) + + assert result == "new_value" diff --git a/backend/tests/baserow/core/user/test_user_handler.py b/backend/tests/baserow/core/user/test_user_handler.py index e096afb94..3adecfa7f 100755 --- a/backend/tests/baserow/core/user/test_user_handler.py +++ b/backend/tests/baserow/core/user/test_user_handler.py @@ -11,7 +11,7 @@ import pytest import responses from freezegun import freeze_time from itsdangerous.exc import BadSignature, SignatureExpired -from responses import json_params_matcher +from responses.matchers import json_params_matcher from baserow.contrib.database.fields.models import SelectOption from baserow.contrib.database.models import Database, Table diff --git a/backend/tests/baserow/core/user_sources/test_user_source_handler.py b/backend/tests/baserow/core/user_sources/test_user_source_handler.py index 6b0425dce..48153c816 100644 --- a/backend/tests/baserow/core/user_sources/test_user_source_handler.py +++ b/backend/tests/baserow/core/user_sources/test_user_source_handler.py @@ -675,3 +675,33 @@ def test_update_all_user_source_counts_in_chunks(data_fixture): assert ( _count_user_sources_with_cached_value(user_sources) == 10 ) # [1,2,3,4,5,6,7,8,9,10] + + +@pytest.mark.django_db +def test_aggregate_user_counts(data_fixture): + user = data_fixture.create_user() + workspace1 = data_fixture.create_workspace(user=user) + + # Workspace1 has two builder applications, with two user sources, + # pointing to the same table. + builder1a = data_fixture.create_builder_application(workspace=workspace1) + user_source1a = data_fixture.create_local_baserow_table_user_source( + application=builder1a + ) + builder1b = data_fixture.create_builder_application(workspace=workspace1) + data_fixture.create_local_baserow_table_user_source( + application=builder1b, table=user_source1a.table + ) + + # The table contains 5 rows, and is used twice, so the usage for both is 10. + assert UserSourceHandler().aggregate_user_counts(workspace1) == 10 + + workspace2 = data_fixture.create_workspace(user=user) + builder2 = data_fixture.create_builder_application(workspace=workspace2) + data_fixture.create_local_baserow_table_user_source(application=builder2) + + # The table contains 5 rows, and is used once, so the usage is 5. + assert UserSourceHandler().aggregate_user_counts(workspace2) == 5 + + # Globally, on this instance, we have a usage of 15. + assert UserSourceHandler().aggregate_user_counts() == 15 diff --git a/backend/tests/templates/example-template-2.json b/backend/tests/templates/example-template-2.json index 36a7669f2..11593f530 100644 --- a/backend/tests/templates/example-template-2.json +++ b/backend/tests/templates/example-template-2.json @@ -4,6 +4,7 @@ "icon": "file", "keywords": ["Example", "Template", "For", "Search"], "categories": ["Test category 1"], + "open_application": 2, "export": [ { "id": 2, diff --git a/changelog.md b/changelog.md index 2dffc7052..48665be21 100644 --- a/changelog.md +++ b/changelog.md @@ -1,5 +1,74 @@ # Changelog +## Released 1.32.0 + +### New features +* Add support for collaborator fields in form views. [#1554](https://gitlab.com/baserow/baserow/-/issues/1554) +* [Dashboard] Introduce dashboards with summary and chart widgets [#2206](https://gitlab.com/baserow/baserow/-/issues/2206) +* [Database] Introduce row update functionality during table import [#2213](https://gitlab.com/baserow/baserow/-/issues/2213) +* [Database] Add rows enter view webhook event type. [#3009](https://gitlab.com/baserow/baserow/-/issues/3009) +* [Core] Hide Baserow description in all emails if logo is changed. [#3066](https://gitlab.com/baserow/baserow/-/issues/3066) +* [Builder] Allow to customize table header filter/sort/search buttons [#3151](https://gitlab.com/baserow/baserow/-/issues/3151) +* [Builder] Introduced Saml and OpenID Connect authentication in the application builder. [#3167](https://gitlab.com/baserow/baserow/-/issues/3167) +* [Builder] Added a shortcut in the publishing modal so that domains can be created if an application doesn't yet have any. [#3170](https://gitlab.com/baserow/baserow/-/issues/3170) +* [Builder] Improve 'Add new element' modal. [#3172](https://gitlab.com/baserow/baserow/-/issues/3172) +* Add abilty to export files in grid [#3203](https://gitlab.com/baserow/baserow/-/issues/3203) +* Airtable import report. [#3263](https://gitlab.com/baserow/baserow/-/issues/3263) +* [Database] Show relationship changes (added or removed) in the related row's change history. [#3264](https://gitlab.com/baserow/baserow/-/issues/3264) +* Multiple collaborator field group by support. [#3447](https://gitlab.com/baserow/baserow/-/issues/3447) +* Airtable import field type improvements. [#3455](https://gitlab.com/baserow/baserow/-/issues/3455) +* [Builder] Added a container element to group multiple elements. [#3458](https://gitlab.com/baserow/baserow/-/issues/3458) +* [Builder] Improved the performance of published applications. [#3472](https://gitlab.com/baserow/baserow/-/issues/3472) +* [Builder] Added the Menu element. [#3477](https://gitlab.com/baserow/baserow/-/issues/3477) +* [Builder] Added theme setting to configure Link decoration. [#3515](https://gitlab.com/baserow/baserow/-/issues/3515) +* [Database] Introduced the ability to sort by single select option order. [#786](https://gitlab.com/baserow/baserow/-/issues/786) +* [Database] Import Airtable view colors. [#793](https://gitlab.com/baserow/baserow/-/issues/793) +* [Database] Import Airtable view filters. [#793](https://gitlab.com/baserow/baserow/-/issues/793) +* Import Airtable grid views, their sorts, group by, and field options. [#793](https://gitlab.com/baserow/baserow/-/issues/793) +* Add SegmentControl variants +* [Builder] Introduced a shortcut in the Login form configuration so that it's easier to create a new user source. +* Send notification to authorized user when periodic data sync is deactivated. +* Send notification to all admins when a webhook is deactivated. + +### Bug fixes +* Preserve the precision of the currency field in the Airtable import. [#1058](https://gitlab.com/baserow/baserow/-/issues/1058) +* [Builder] Fixed element position resets on editing of it's properties [#2342](https://gitlab.com/baserow/baserow/-/issues/2342) +* Fix pasting markdown text into rich edit that resulted in unformatted markdown [#2383](https://gitlab.com/baserow/baserow/-/issues/2383) +* [Database] Fixed a bug that prevented duplicating views filtered by a collaborator correctly. [#3017](https://gitlab.com/baserow/baserow/-/issues/3017) +* [Database] Fixed unscrollable timezone dropdown issue when creating/editing a field. [#3041](https://gitlab.com/baserow/baserow/-/issues/3041) +* [Database] Fix protected fields in the data sync forms. [#3191](https://gitlab.com/baserow/baserow/-/issues/3191) +* Database: when an error is returned by the backend, it will be shown inside of the body of the view, so user still have access to navigation interface. [#3331](https://gitlab.com/baserow/baserow/-/issues/3331) +* [Database] Fix issue with unexpected temperature argument passed to OpenAI messages.create [#3384](https://gitlab.com/baserow/baserow/-/issues/3384) +* [Database] Allow bigger image dimensions. [#3387](https://gitlab.com/baserow/baserow/-/issues/3387) +* Preserve the currency symbol and formatting of the currency field in Airtable import. [#3395](https://gitlab.com/baserow/baserow/-/issues/3395) +* Prevent view from updated state with data from wrong view when pending request completes. [#3398](https://gitlab.com/baserow/baserow/-/issues/3398) +* [Database] Fix for data sync failing when syncing baserow table with AIField [#3403](https://gitlab.com/baserow/baserow/-/issues/3403) +* Use BigIntegerField for ImportExportResource.size [#3424](https://gitlab.com/baserow/baserow/-/issues/3424) +* [Builder] Fix updating of page parameters when URL query parameters change. [#3434](https://gitlab.com/baserow/baserow/-/issues/3434) +* [Database] Fix field formatting options in rollup fields targeting formula fields [#3443](https://gitlab.com/baserow/baserow/-/issues/3443) +* Fixed null check for query parameters in link URL generation [#3444](https://gitlab.com/baserow/baserow/-/issues/3444) +* [Database] Do not register jobs that have unknown job type in the job type in the registry. [#3447](https://gitlab.com/baserow/baserow/-/issues/3447) +* Fix for Secure File Serve with SSO SAML/OIDC authentication [#3449](https://gitlab.com/baserow/baserow/-/issues/3449) +* [Builder] Resolved a bug where creating an element with an invalid parent would raise an error. [#3452](https://gitlab.com/baserow/baserow/-/issues/3452) +* [Builder] Add page background color to theme block [#3457](https://gitlab.com/baserow/baserow/-/issues/3457) +* [Database] Updating a cell no longer fails when a view is sorted or grouped by a linked field whose primary field is a formula. [#3484](https://gitlab.com/baserow/baserow/-/issues/3484) +* [Database] Fix for creating snapshot triggers infinite loop for checking status update [#3490](https://gitlab.com/baserow/baserow/-/issues/3490) +* [Database] Allow change field type with active sort [#3519](https://gitlab.com/baserow/baserow/-/issues/3519) +* [Builder] Fix broken pagination after filtering collection elements +* [Builder] Fix crash when creating a builder application after deleting another one +* Fix error when syncing a table with a trashed field. +* [Database] Fix the progress bar percentage when importing applications into the workspace. + +### Refactors +* Upgrade vuelidate [#2805](https://gitlab.com/baserow/baserow/-/issues/2805) +* [Builder] Improve data dispatching performances [#2978](https://gitlab.com/baserow/baserow/-/issues/2978) +* Reduce the number of queries when logging in or load Baserow. [#3364](https://gitlab.com/baserow/baserow/-/issues/3364) +* [Builder] Improve integration endpoint performances [#3418](https://gitlab.com/baserow/baserow/-/issues/3418) +* Lowered grid view minimum field with from 100 to 78. [#3428](https://gitlab.com/baserow/baserow/-/issues/3428) +* [Builder] Improved performance in preview mode +* Speed up database setup for tests + + ## Released 1.31.1 ### Bug fixes diff --git a/changelog/entries/unreleased/bug/1058_preserve_airtable_import_currency_precision.json b/changelog/entries/1.32.0/bug/1058_preserve_airtable_import_currency_precision.json similarity index 100% rename from changelog/entries/unreleased/bug/1058_preserve_airtable_import_currency_precision.json rename to changelog/entries/1.32.0/bug/1058_preserve_airtable_import_currency_precision.json diff --git a/changelog/entries/unreleased/bug/2342_builder_fix_element_position_reset_on_edit.json b/changelog/entries/1.32.0/bug/2342_builder_fix_element_position_reset_on_edit.json similarity index 100% rename from changelog/entries/unreleased/bug/2342_builder_fix_element_position_reset_on_edit.json rename to changelog/entries/1.32.0/bug/2342_builder_fix_element_position_reset_on_edit.json diff --git a/changelog/entries/1.32.0/bug/2383_fix_paste_for_single_line_and_long_text_fields_in_edit_mode.json b/changelog/entries/1.32.0/bug/2383_fix_paste_for_single_line_and_long_text_fields_in_edit_mode.json new file mode 100644 index 000000000..1221106db --- /dev/null +++ b/changelog/entries/1.32.0/bug/2383_fix_paste_for_single_line_and_long_text_fields_in_edit_mode.json @@ -0,0 +1,7 @@ +{ + "type": "bug", + "message": "Fix pasting markdown text into rich edit that resulted in unformatted markdown", + "issue_number": 2383, + "bullet_points": [], + "created_at": "2025-02-07" +} \ No newline at end of file diff --git a/changelog/entries/1.32.0/bug/3017_.json b/changelog/entries/1.32.0/bug/3017_.json new file mode 100644 index 000000000..c6e62ce2a --- /dev/null +++ b/changelog/entries/1.32.0/bug/3017_.json @@ -0,0 +1,8 @@ +{ + "type": "bug", + "message": "Fixed a bug that prevented duplicating views filtered by a collaborator correctly.", + "domain": "database", + "issue_number": 3017, + "bullet_points": [], + "created_at": "2025-03-10" +} \ No newline at end of file diff --git a/changelog/entries/1.32.0/bug/3041_.json b/changelog/entries/1.32.0/bug/3041_.json new file mode 100644 index 000000000..ff976c003 --- /dev/null +++ b/changelog/entries/1.32.0/bug/3041_.json @@ -0,0 +1,8 @@ +{ + "type": "bug", + "message": "Fixed unscrollable timezone dropdown issue when creating/editing a field.", + "domain": "database", + "issue_number": 3041, + "bullet_points": [], + "created_at": "2025-03-10" +} \ No newline at end of file diff --git a/changelog/entries/1.32.0/bug/3191_fix_data_sync_form_protected_fields.json b/changelog/entries/1.32.0/bug/3191_fix_data_sync_form_protected_fields.json new file mode 100644 index 000000000..01bc1e1ea --- /dev/null +++ b/changelog/entries/1.32.0/bug/3191_fix_data_sync_form_protected_fields.json @@ -0,0 +1,8 @@ +{ + "type": "bug", + "message": "Fix protected fields in the data sync forms.", + "domain": "database", + "issue_number": 3191, + "bullet_points": [], + "created_at": "2025-02-27" +} diff --git a/changelog/entries/1.32.0/bug/3331_database_enhance_backend_errors_handling_in_ui.json b/changelog/entries/1.32.0/bug/3331_database_enhance_backend_errors_handling_in_ui.json new file mode 100644 index 000000000..477ff7eb1 --- /dev/null +++ b/changelog/entries/1.32.0/bug/3331_database_enhance_backend_errors_handling_in_ui.json @@ -0,0 +1,7 @@ +{ + "type": "bug", + "message": "Database: when an error is returned by the backend, it will be shown inside of the body of the view, so user still have access to navigation interface.", + "issue_number": 3331, + "bullet_points": [], + "created_at": "2025-01-31" +} diff --git a/changelog/entries/1.32.0/bug/3384_fix_issue_with_temperature_passed_to_openai_messagescreate.json b/changelog/entries/1.32.0/bug/3384_fix_issue_with_temperature_passed_to_openai_messagescreate.json new file mode 100644 index 000000000..1cc3b504c --- /dev/null +++ b/changelog/entries/1.32.0/bug/3384_fix_issue_with_temperature_passed_to_openai_messagescreate.json @@ -0,0 +1,8 @@ +{ + "type": "bug", + "message": "Fix issue with unexpected temperature argument passed to OpenAI messages.create", + "domain": "database", + "issue_number": 3384, + "bullet_points": [], + "created_at": "2025-03-13" +} \ No newline at end of file diff --git a/changelog/entries/1.32.0/bug/3387_allow_bigger_image_dimensions.json b/changelog/entries/1.32.0/bug/3387_allow_bigger_image_dimensions.json new file mode 100644 index 000000000..a9a03f771 --- /dev/null +++ b/changelog/entries/1.32.0/bug/3387_allow_bigger_image_dimensions.json @@ -0,0 +1,8 @@ +{ + "type": "bug", + "message": "Allow bigger image dimensions.", + "domain": "database", + "issue_number": 3387, + "bullet_points": [], + "created_at": "2025-03-13" +} diff --git a/changelog/entries/unreleased/bug/3395_preserve_currency_symbol_and_formatting.json b/changelog/entries/1.32.0/bug/3395_preserve_currency_symbol_and_formatting.json similarity index 100% rename from changelog/entries/unreleased/bug/3395_preserve_currency_symbol_and_formatting.json rename to changelog/entries/1.32.0/bug/3395_preserve_currency_symbol_and_formatting.json diff --git a/changelog/entries/unreleased/bug/3398_prevent_view_update_with_wrong_data.json b/changelog/entries/1.32.0/bug/3398_prevent_view_update_with_wrong_data.json similarity index 100% rename from changelog/entries/unreleased/bug/3398_prevent_view_update_with_wrong_data.json rename to changelog/entries/1.32.0/bug/3398_prevent_view_update_with_wrong_data.json diff --git a/changelog/entries/1.32.0/bug/3403_fix_for_data_sync_fails_when_syncing_baserow_table_with_aifi.json b/changelog/entries/1.32.0/bug/3403_fix_for_data_sync_fails_when_syncing_baserow_table_with_aifi.json new file mode 100644 index 000000000..f4b27223c --- /dev/null +++ b/changelog/entries/1.32.0/bug/3403_fix_for_data_sync_fails_when_syncing_baserow_table_with_aifi.json @@ -0,0 +1,8 @@ +{ + "type": "bug", + "message": "Fix for data sync failing when syncing baserow table with AIField", + "domain": "database", + "issue_number": 3403, + "bullet_points": [], + "created_at": "2025-03-12" +} \ No newline at end of file diff --git a/changelog/entries/unreleased/bug/3424_use_bigintegerfield_for_importexportresourcesize.json b/changelog/entries/1.32.0/bug/3424_use_bigintegerfield_for_importexportresourcesize.json similarity index 100% rename from changelog/entries/unreleased/bug/3424_use_bigintegerfield_for_importexportresourcesize.json rename to changelog/entries/1.32.0/bug/3424_use_bigintegerfield_for_importexportresourcesize.json diff --git a/changelog/entries/1.32.0/bug/3434_fix_automatically_upd.json b/changelog/entries/1.32.0/bug/3434_fix_automatically_upd.json new file mode 100644 index 000000000..376495454 --- /dev/null +++ b/changelog/entries/1.32.0/bug/3434_fix_automatically_upd.json @@ -0,0 +1,7 @@ +{ + "type": "bug", + "message": "[Builder] Fix updating of page parameters when URL query parameters change.", + "issue_number": 3434, + "bullet_points": [], + "created_at": "2025-02-19" +} diff --git a/changelog/entries/1.32.0/bug/3443_.json b/changelog/entries/1.32.0/bug/3443_.json new file mode 100644 index 000000000..089ec0fce --- /dev/null +++ b/changelog/entries/1.32.0/bug/3443_.json @@ -0,0 +1,8 @@ +{ + "type": "bug", + "message": "Fix field formatting options in rollup fields targeting formula fields", + "domain": "database", + "issue_number": 3443, + "bullet_points": [], + "created_at": "2025-03-13" +} \ No newline at end of file diff --git a/changelog/entries/unreleased/bug/3444_fix_urlresolution_query_param_null_check.json b/changelog/entries/1.32.0/bug/3444_fix_urlresolution_query_param_null_check.json similarity index 100% rename from changelog/entries/unreleased/bug/3444_fix_urlresolution_query_param_null_check.json rename to changelog/entries/1.32.0/bug/3444_fix_urlresolution_query_param_null_check.json diff --git a/changelog/entries/1.32.0/bug/3447_do_not_register_jobs_that_have_unknown_job_type_in_the_job_t.json b/changelog/entries/1.32.0/bug/3447_do_not_register_jobs_that_have_unknown_job_type_in_the_job_t.json new file mode 100644 index 000000000..c0d47d725 --- /dev/null +++ b/changelog/entries/1.32.0/bug/3447_do_not_register_jobs_that_have_unknown_job_type_in_the_job_t.json @@ -0,0 +1,8 @@ +{ + "type": "bug", + "message": "Do not register jobs that have unknown job type in the job type in the registry.", + "domain": "database", + "issue_number": 3447, + "bullet_points": [], + "created_at": "2025-03-14" +} \ No newline at end of file diff --git a/changelog/entries/1.32.0/bug/3449_fix_for_secure_file_serve_with_sso_samloidc_authentication.json b/changelog/entries/1.32.0/bug/3449_fix_for_secure_file_serve_with_sso_samloidc_authentication.json new file mode 100644 index 000000000..e091abc63 --- /dev/null +++ b/changelog/entries/1.32.0/bug/3449_fix_for_secure_file_serve_with_sso_samloidc_authentication.json @@ -0,0 +1,7 @@ +{ + "type": "bug", + "message": "Fix for Secure File Serve with SSO SAML/OIDC authentication", + "issue_number": 3449, + "bullet_points": [], + "created_at": "2025-02-27" +} \ No newline at end of file diff --git a/changelog/entries/unreleased/bug/3452_builder_resolved_a_bug_where_creating_an_element_with_an_inv.json b/changelog/entries/1.32.0/bug/3452_builder_resolved_a_bug_where_creating_an_element_with_an_inv.json similarity index 100% rename from changelog/entries/unreleased/bug/3452_builder_resolved_a_bug_where_creating_an_element_with_an_inv.json rename to changelog/entries/1.32.0/bug/3452_builder_resolved_a_bug_where_creating_an_element_with_an_inv.json diff --git a/changelog/entries/1.32.0/bug/3457_builder_add_background_color_to_theme_block.json b/changelog/entries/1.32.0/bug/3457_builder_add_background_color_to_theme_block.json new file mode 100644 index 000000000..ec0f1dd24 --- /dev/null +++ b/changelog/entries/1.32.0/bug/3457_builder_add_background_color_to_theme_block.json @@ -0,0 +1,7 @@ +{ + "type": "bug", + "message": "[Builder] Add page background color to theme block", + "issue_number": 3457, + "bullet_points": [], + "created_at": "2025-02-18" +} diff --git a/changelog/entries/1.32.0/bug/3484_.json b/changelog/entries/1.32.0/bug/3484_.json new file mode 100644 index 000000000..a258ed939 --- /dev/null +++ b/changelog/entries/1.32.0/bug/3484_.json @@ -0,0 +1,8 @@ +{ + "type": "bug", + "message": "Updating a cell no longer fails when a view is sorted or grouped by a linked field whose primary field is a formula.", + "domain": "database", + "issue_number": 3484, + "bullet_points": [], + "created_at": "2025-03-10" +} \ No newline at end of file diff --git a/changelog/entries/1.32.0/bug/3490_creating_snapshot_triggers_infinite_loop_for_checking_status.json b/changelog/entries/1.32.0/bug/3490_creating_snapshot_triggers_infinite_loop_for_checking_status.json new file mode 100644 index 000000000..831e57e18 --- /dev/null +++ b/changelog/entries/1.32.0/bug/3490_creating_snapshot_triggers_infinite_loop_for_checking_status.json @@ -0,0 +1,8 @@ +{ + "type": "bug", + "message": "Fix for creating snapshot triggers infinite loop for checking status update", + "domain": "database", + "issue_number": 3490, + "bullet_points": [], + "created_at": "2025-03-06" +} \ No newline at end of file diff --git a/changelog/entries/1.32.0/bug/3519_allow_change_field_type_with_active_sort.json b/changelog/entries/1.32.0/bug/3519_allow_change_field_type_with_active_sort.json new file mode 100644 index 000000000..f8982060c --- /dev/null +++ b/changelog/entries/1.32.0/bug/3519_allow_change_field_type_with_active_sort.json @@ -0,0 +1,8 @@ +{ + "type": "bug", + "message": "Allow change field type with active sort", + "domain": "database", + "issue_number": 3519, + "bullet_points": [], + "created_at": "2025-03-18" +} \ No newline at end of file diff --git a/changelog/entries/unreleased/bug/builder_fix_broken_pagination_after_search_for_collection_el.json b/changelog/entries/1.32.0/bug/builder_fix_broken_pagination_after_search_for_collection_el.json similarity index 100% rename from changelog/entries/unreleased/bug/builder_fix_broken_pagination_after_search_for_collection_el.json rename to changelog/entries/1.32.0/bug/builder_fix_broken_pagination_after_search_for_collection_el.json diff --git a/changelog/entries/1.32.0/bug/builder_fix_crash_when_creating_a_builder_application_after_.json b/changelog/entries/1.32.0/bug/builder_fix_crash_when_creating_a_builder_application_after_.json new file mode 100644 index 000000000..9e2d1b57d --- /dev/null +++ b/changelog/entries/1.32.0/bug/builder_fix_crash_when_creating_a_builder_application_after_.json @@ -0,0 +1,7 @@ +{ + "type": "bug", + "message": "[Builder] Fix crash when creating a builder application after deleting another one", + "issue_number": null, + "bullet_points": [], + "created_at": "2025-02-24" +} \ No newline at end of file diff --git a/changelog/entries/unreleased/bug/fix_error_with_trashed_data_sync_property_field.json b/changelog/entries/1.32.0/bug/fix_error_with_trashed_data_sync_property_field.json similarity index 100% rename from changelog/entries/unreleased/bug/fix_error_with_trashed_data_sync_property_field.json rename to changelog/entries/1.32.0/bug/fix_error_with_trashed_data_sync_property_field.json diff --git a/changelog/entries/1.32.0/bug/fix_the_progress_bar_percentage_when_importing_applications_.json b/changelog/entries/1.32.0/bug/fix_the_progress_bar_percentage_when_importing_applications_.json new file mode 100644 index 000000000..6b815b965 --- /dev/null +++ b/changelog/entries/1.32.0/bug/fix_the_progress_bar_percentage_when_importing_applications_.json @@ -0,0 +1,8 @@ +{ + "type": "bug", + "message": "Fix the progress bar percentage when importing applications into the workspace.", + "domain": "database", + "issue_number": null, + "bullet_points": [], + "created_at": "2025-03-07" +} \ No newline at end of file diff --git a/changelog/entries/unreleased/feature/1554_collaborator_field_support_in_form_views.json b/changelog/entries/1.32.0/feature/1554_collaborator_field_support_in_form_views.json similarity index 100% rename from changelog/entries/unreleased/feature/1554_collaborator_field_support_in_form_views.json rename to changelog/entries/1.32.0/feature/1554_collaborator_field_support_in_form_views.json diff --git a/changelog/entries/1.32.0/feature/2206_introduce_dashboards_with_summary_and_chart_widgets.json b/changelog/entries/1.32.0/feature/2206_introduce_dashboards_with_summary_and_chart_widgets.json new file mode 100644 index 000000000..8bd5b6536 --- /dev/null +++ b/changelog/entries/1.32.0/feature/2206_introduce_dashboards_with_summary_and_chart_widgets.json @@ -0,0 +1,8 @@ +{ + "type": "feature", + "message": "Introduce dashboards with summary and chart widgets", + "domain": "dashboard", + "issue_number": 2206, + "bullet_points": [], + "created_at": "2025-03-13" +} \ No newline at end of file diff --git a/changelog/entries/1.32.0/feature/2213_introduce_row_update_functionality_during_table_import.json b/changelog/entries/1.32.0/feature/2213_introduce_row_update_functionality_during_table_import.json new file mode 100644 index 000000000..be73ac0b3 --- /dev/null +++ b/changelog/entries/1.32.0/feature/2213_introduce_row_update_functionality_during_table_import.json @@ -0,0 +1,8 @@ +{ + "type": "feature", + "message": "Introduce row update functionality during table import", + "domain": "database", + "issue_number": 2213, + "bullet_points": [], + "created_at": "2025-03-13" +} \ No newline at end of file diff --git a/changelog/entries/1.32.0/feature/3009_add_rows_enter_view_webhook_event_type.json b/changelog/entries/1.32.0/feature/3009_add_rows_enter_view_webhook_event_type.json new file mode 100644 index 000000000..b7c16320a --- /dev/null +++ b/changelog/entries/1.32.0/feature/3009_add_rows_enter_view_webhook_event_type.json @@ -0,0 +1,8 @@ +{ + "type": "feature", + "message": "Add rows enter view webhook event type.", + "domain": "database", + "issue_number": 3009, + "bullet_points": [], + "created_at": "2025-03-07" +} \ No newline at end of file diff --git a/changelog/entries/1.32.0/feature/3066_hide_baserow_description_in_emails_if_logo_is_changed.json b/changelog/entries/1.32.0/feature/3066_hide_baserow_description_in_emails_if_logo_is_changed.json new file mode 100644 index 000000000..0325ab5eb --- /dev/null +++ b/changelog/entries/1.32.0/feature/3066_hide_baserow_description_in_emails_if_logo_is_changed.json @@ -0,0 +1,8 @@ +{ + "type": "feature", + "message": "Hide Baserow description in all emails if logo is changed.", + "domain": "core", + "issue_number": 3066, + "bullet_points": [], + "created_at": "2025-03-06" +} diff --git a/changelog/entries/1.32.0/feature/3151_builder_allow_to_customize_table_header_filtersortsearch_but.json b/changelog/entries/1.32.0/feature/3151_builder_allow_to_customize_table_header_filtersortsearch_but.json new file mode 100644 index 000000000..452041db0 --- /dev/null +++ b/changelog/entries/1.32.0/feature/3151_builder_allow_to_customize_table_header_filtersortsearch_but.json @@ -0,0 +1,7 @@ +{ + "type": "feature", + "message": "[Builder] Allow to customize table header filter/sort/search buttons", + "issue_number": 3151, + "bullet_points": [], + "created_at": "2025-02-18" +} \ No newline at end of file diff --git a/changelog/entries/1.32.0/feature/3167_introduced_saml_and_openid_connect_authentication_in_the_app.json b/changelog/entries/1.32.0/feature/3167_introduced_saml_and_openid_connect_authentication_in_the_app.json new file mode 100644 index 000000000..b58caba04 --- /dev/null +++ b/changelog/entries/1.32.0/feature/3167_introduced_saml_and_openid_connect_authentication_in_the_app.json @@ -0,0 +1,8 @@ +{ + "type": "feature", + "message": "Introduced Saml and OpenID Connect authentication in the application builder.", + "domain": "builder", + "issue_number": 3167, + "bullet_points": [], + "created_at": "2025-03-07" +} diff --git a/changelog/entries/1.32.0/feature/3170_added_a_shortcut_in_the_publishing_modal_so_that_domains_can.json b/changelog/entries/1.32.0/feature/3170_added_a_shortcut_in_the_publishing_modal_so_that_domains_can.json new file mode 100644 index 000000000..2661fedbf --- /dev/null +++ b/changelog/entries/1.32.0/feature/3170_added_a_shortcut_in_the_publishing_modal_so_that_domains_can.json @@ -0,0 +1,8 @@ +{ + "type": "feature", + "message": "Added a shortcut in the publishing modal so that domains can be created if an application doesn't yet have any.", + "domain": "builder", + "issue_number": 3170, + "bullet_points": [], + "created_at": "2025-03-13" +} \ No newline at end of file diff --git a/changelog/entries/1.32.0/feature/3172_improve_add_new_element_modal.json b/changelog/entries/1.32.0/feature/3172_improve_add_new_element_modal.json new file mode 100644 index 000000000..54b222d00 --- /dev/null +++ b/changelog/entries/1.32.0/feature/3172_improve_add_new_element_modal.json @@ -0,0 +1,8 @@ +{ + "type": "feature", + "message": "Improve 'Add new element' modal.", + "domain": "builder", + "issue_number": 3172, + "bullet_points": [], + "created_at": "2025-03-06" +} \ No newline at end of file diff --git a/changelog/entries/1.32.0/feature/3203_add_abilty_to_export_files_in_grid.json b/changelog/entries/1.32.0/feature/3203_add_abilty_to_export_files_in_grid.json new file mode 100644 index 000000000..3f0290031 --- /dev/null +++ b/changelog/entries/1.32.0/feature/3203_add_abilty_to_export_files_in_grid.json @@ -0,0 +1,7 @@ +{ + "type": "feature", + "message": "Add abilty to export files in grid", + "issue_number": 3203, + "bullet_points": [], + "created_at": "2025-02-20" +} \ No newline at end of file diff --git a/changelog/entries/unreleased/feature/3263_missing_airtable_import.json b/changelog/entries/1.32.0/feature/3263_missing_airtable_import.json similarity index 100% rename from changelog/entries/unreleased/feature/3263_missing_airtable_import.json rename to changelog/entries/1.32.0/feature/3263_missing_airtable_import.json diff --git a/changelog/entries/1.32.0/feature/3264_show_relationship_changes_in_row_change_history.json b/changelog/entries/1.32.0/feature/3264_show_relationship_changes_in_row_change_history.json new file mode 100644 index 000000000..3494db555 --- /dev/null +++ b/changelog/entries/1.32.0/feature/3264_show_relationship_changes_in_row_change_history.json @@ -0,0 +1,8 @@ +{ + "type": "feature", + "message": "Show relationship changes (added or removed) in the related row's change history.", + "domain": "database", + "issue_number": 3264, + "bullet_points": [], + "created_at": "2025-03-18" +} \ No newline at end of file diff --git a/changelog/entries/1.32.0/feature/3448_multiple_collaborator_group_by_support.json b/changelog/entries/1.32.0/feature/3448_multiple_collaborator_group_by_support.json new file mode 100644 index 000000000..936d9de1f --- /dev/null +++ b/changelog/entries/1.32.0/feature/3448_multiple_collaborator_group_by_support.json @@ -0,0 +1,7 @@ +{ + "type": "feature", + "message": "Multiple collaborator field group by support.", + "issue_number": 3447, + "bullet_points": [], + "created_at": "2025-02-25" +} diff --git a/changelog/entries/1.32.0/feature/3455_airtable_import_field_type_improvements.json b/changelog/entries/1.32.0/feature/3455_airtable_import_field_type_improvements.json new file mode 100644 index 000000000..aee3295fb --- /dev/null +++ b/changelog/entries/1.32.0/feature/3455_airtable_import_field_type_improvements.json @@ -0,0 +1,7 @@ +{ + "type": "feature", + "message": "Airtable import field type improvements.", + "issue_number": 3455, + "bullet_points": [], + "created_at": "2025-02-17" +} diff --git a/changelog/entries/1.32.0/feature/3458_add_simple_container_element_to_group_multiple_elements.json b/changelog/entries/1.32.0/feature/3458_add_simple_container_element_to_group_multiple_elements.json new file mode 100644 index 000000000..b69086cec --- /dev/null +++ b/changelog/entries/1.32.0/feature/3458_add_simple_container_element_to_group_multiple_elements.json @@ -0,0 +1,8 @@ +{ + "type": "feature", + "message": "Added a container element to group multiple elements.", + "domain": "builder", + "issue_number": 3458, + "bullet_points": [], + "created_at": "2025-03-08" +} diff --git a/changelog/entries/1.32.0/feature/3472_builder_improved_the_performance_of_published_applications.json b/changelog/entries/1.32.0/feature/3472_builder_improved_the_performance_of_published_applications.json new file mode 100644 index 000000000..441188665 --- /dev/null +++ b/changelog/entries/1.32.0/feature/3472_builder_improved_the_performance_of_published_applications.json @@ -0,0 +1,7 @@ +{ + "type": "feature", + "message": "[Builder] Improved the performance of published applications.", + "issue_number": 3472, + "bullet_points": [], + "created_at": "2025-02-25" +} \ No newline at end of file diff --git a/changelog/entries/1.32.0/feature/3477_add_menu_element.json b/changelog/entries/1.32.0/feature/3477_add_menu_element.json new file mode 100644 index 000000000..103262204 --- /dev/null +++ b/changelog/entries/1.32.0/feature/3477_add_menu_element.json @@ -0,0 +1,8 @@ +{ + "type": "feature", + "message": "Added the Menu element.", + "domain": "builder", + "issue_number": 3477, + "bullet_points": [], + "created_at": "2025-03-05" +} diff --git a/changelog/entries/1.32.0/feature/3515_added_theme_setting_to_configure_link_decoration.json b/changelog/entries/1.32.0/feature/3515_added_theme_setting_to_configure_link_decoration.json new file mode 100644 index 000000000..a357d92f4 --- /dev/null +++ b/changelog/entries/1.32.0/feature/3515_added_theme_setting_to_configure_link_decoration.json @@ -0,0 +1,8 @@ +{ + "type": "feature", + "message": "Added theme setting to configure Link decoration.", + "domain": "builder", + "issue_number": 3515, + "bullet_points": [], + "created_at": "2025-03-14" +} \ No newline at end of file diff --git a/changelog/entries/1.32.0/feature/786_sort_by_single_select_option_order.json b/changelog/entries/1.32.0/feature/786_sort_by_single_select_option_order.json new file mode 100644 index 000000000..375631fc4 --- /dev/null +++ b/changelog/entries/1.32.0/feature/786_sort_by_single_select_option_order.json @@ -0,0 +1,8 @@ +{ + "type": "feature", + "message": "Introduced the ability to sort by single select option order.", + "domain": "database", + "issue_number": 786, + "bullet_points": [], + "created_at": "2025-03-10" +} diff --git a/changelog/entries/1.32.0/feature/793_import_airtable_colors.json b/changelog/entries/1.32.0/feature/793_import_airtable_colors.json new file mode 100644 index 000000000..1ff5cbf04 --- /dev/null +++ b/changelog/entries/1.32.0/feature/793_import_airtable_colors.json @@ -0,0 +1,8 @@ +{ + "type": "feature", + "message": "Import Airtable view colors.", + "domain": "database", + "issue_number": 793, + "bullet_points": [], + "created_at": "2025-03-13" +} diff --git a/changelog/entries/1.32.0/feature/793_import_airtable_filters.json b/changelog/entries/1.32.0/feature/793_import_airtable_filters.json new file mode 100644 index 000000000..50e2d33fb --- /dev/null +++ b/changelog/entries/1.32.0/feature/793_import_airtable_filters.json @@ -0,0 +1,8 @@ +{ + "type": "feature", + "message": "Import Airtable view filters.", + "domain": "database", + "issue_number": 793, + "bullet_points": [], + "created_at": "2025-03-04" +} diff --git a/changelog/entries/1.32.0/feature/793_import_airtable_grid_view_sort_group_and_options.json b/changelog/entries/1.32.0/feature/793_import_airtable_grid_view_sort_group_and_options.json new file mode 100644 index 000000000..9703dfb32 --- /dev/null +++ b/changelog/entries/1.32.0/feature/793_import_airtable_grid_view_sort_group_and_options.json @@ -0,0 +1,7 @@ +{ + "type": "feature", + "message": "Import Airtable grid views, their sorts, group by, and field options.", + "issue_number": 793, + "bullet_points": [], + "created_at": "2025-02-24" +} diff --git a/changelog/entries/1.32.0/feature/add_segmentcontrol_variants.json b/changelog/entries/1.32.0/feature/add_segmentcontrol_variants.json new file mode 100644 index 000000000..f13b34862 --- /dev/null +++ b/changelog/entries/1.32.0/feature/add_segmentcontrol_variants.json @@ -0,0 +1,7 @@ +{ + "type": "feature", + "message": "Add SegmentControl variants", + "issue_number": null, + "bullet_points": [], + "created_at": "2025-02-21" +} \ No newline at end of file diff --git a/changelog/entries/1.32.0/feature/introduced_a_shortcut_in_the_login_form_configuration_so_tha.json b/changelog/entries/1.32.0/feature/introduced_a_shortcut_in_the_login_form_configuration_so_tha.json new file mode 100644 index 000000000..53677ca0a --- /dev/null +++ b/changelog/entries/1.32.0/feature/introduced_a_shortcut_in_the_login_form_configuration_so_tha.json @@ -0,0 +1,8 @@ +{ + "type": "feature", + "message": "Introduced a shortcut in the Login form configuration so that it's easier to create a new user source.", + "domain": "builder", + "issue_number": null, + "bullet_points": [], + "created_at": "2025-03-14" +} \ No newline at end of file diff --git a/changelog/entries/1.32.0/feature/send_notification_when_a_periodic_data_sync_is_deactivated.json b/changelog/entries/1.32.0/feature/send_notification_when_a_periodic_data_sync_is_deactivated.json new file mode 100644 index 000000000..9f150f20c --- /dev/null +++ b/changelog/entries/1.32.0/feature/send_notification_when_a_periodic_data_sync_is_deactivated.json @@ -0,0 +1,7 @@ +{ + "type": "feature", + "message": "Send notification to authorized user when periodic data sync is deactivated.", + "issue_number": null, + "bullet_points": [], + "created_at": "2025-02-13" +} diff --git a/changelog/entries/1.32.0/feature/send_notification_when_a_webhook_is_deactivated.json b/changelog/entries/1.32.0/feature/send_notification_when_a_webhook_is_deactivated.json new file mode 100644 index 000000000..8782d0a45 --- /dev/null +++ b/changelog/entries/1.32.0/feature/send_notification_when_a_webhook_is_deactivated.json @@ -0,0 +1,7 @@ +{ + "type": "feature", + "message": "Send notification to all admins when a webhook is deactivated.", + "issue_number": null, + "bullet_points": [], + "created_at": "2025-02-11" +} diff --git a/changelog/entries/unreleased/refactor/2805_upgrade_vuelidate.json b/changelog/entries/1.32.0/refactor/2805_upgrade_vuelidate.json similarity index 100% rename from changelog/entries/unreleased/refactor/2805_upgrade_vuelidate.json rename to changelog/entries/1.32.0/refactor/2805_upgrade_vuelidate.json diff --git a/changelog/entries/unreleased/refactor/2978_builder_improve_data_dispatching_performances.json b/changelog/entries/1.32.0/refactor/2978_builder_improve_data_dispatching_performances.json similarity index 100% rename from changelog/entries/unreleased/refactor/2978_builder_improve_data_dispatching_performances.json rename to changelog/entries/1.32.0/refactor/2978_builder_improve_data_dispatching_performances.json diff --git a/changelog/entries/unreleased/refactor/3364_login_is_slow.json b/changelog/entries/1.32.0/refactor/3364_login_is_slow.json similarity index 100% rename from changelog/entries/unreleased/refactor/3364_login_is_slow.json rename to changelog/entries/1.32.0/refactor/3364_login_is_slow.json diff --git a/changelog/entries/unreleased/refactor/3418_builder_improve_integration_endpoint_performances.json b/changelog/entries/1.32.0/refactor/3418_builder_improve_integration_endpoint_performances.json similarity index 100% rename from changelog/entries/unreleased/refactor/3418_builder_improve_integration_endpoint_performances.json rename to changelog/entries/1.32.0/refactor/3418_builder_improve_integration_endpoint_performances.json diff --git a/changelog/entries/unreleased/refactor/3428_lowered_grid_view_min_field_width.json b/changelog/entries/1.32.0/refactor/3428_lowered_grid_view_min_field_width.json similarity index 100% rename from changelog/entries/unreleased/refactor/3428_lowered_grid_view_min_field_width.json rename to changelog/entries/1.32.0/refactor/3428_lowered_grid_view_min_field_width.json diff --git a/changelog/entries/unreleased/refactor/builder_improved_performance_in_preview_mode.json b/changelog/entries/1.32.0/refactor/builder_improved_performance_in_preview_mode.json similarity index 100% rename from changelog/entries/unreleased/refactor/builder_improved_performance_in_preview_mode.json rename to changelog/entries/1.32.0/refactor/builder_improved_performance_in_preview_mode.json diff --git a/changelog/entries/1.32.0/refactor/speed_up_database_setup_for_tests.json b/changelog/entries/1.32.0/refactor/speed_up_database_setup_for_tests.json new file mode 100644 index 000000000..b6febec15 --- /dev/null +++ b/changelog/entries/1.32.0/refactor/speed_up_database_setup_for_tests.json @@ -0,0 +1,7 @@ +{ + "type": "refactor", + "message": "Speed up database setup for tests", + "issue_number": null, + "bullet_points": [], + "created_at": "2025-02-20" +} \ No newline at end of file diff --git a/changelog/releases.json b/changelog/releases.json index b44a17c3c..48e249f5b 100644 --- a/changelog/releases.json +++ b/changelog/releases.json @@ -1,5 +1,9 @@ { "releases": [ + { + "name": "1.32.0", + "created_at": "2025-03-18" + }, { "name": "1.31.1", "created_at": "2025-02-10" diff --git a/changelog/src/changelog.py b/changelog/src/changelog.py index 766940e24..1bd581a33 100755 --- a/changelog/src/changelog.py +++ b/changelog/src/changelog.py @@ -6,7 +6,9 @@ from pathlib import Path from typing import Optional import typer -from changelog_entry import changelog_entry_types + +from domains import domain_types, DatabaseDomain +from changelog_entry import changelog_entry_types, BugChangelogEntry from click import Choice from handler import ChangelogHandler @@ -18,16 +20,21 @@ default_path = str(Path(os.path.dirname(__file__)).parent) @app.command() def add(working_dir: Optional[str] = typer.Option(default=default_path)): + domain_type = typer.prompt( + "Domain", + type=Choice(list(domain_types.keys())), + default=DatabaseDomain.type, + ) changelog_type = typer.prompt( "Type of changelog", type=Choice(list(changelog_entry_types.keys())), - default="bug", + default=BugChangelogEntry.type, ) issue_number = typer.prompt( "Issue number", type=str, default=ChangelogHandler.get_issue_number() or "" ) - message = typer.prompt("Message", default=ChangelogHandler.get_message()) + message = typer.prompt("Message", default="") if issue_number.isdigit(): issue_number = int(issue_number) @@ -36,7 +43,7 @@ def add(working_dir: Optional[str] = typer.Option(default=default_path)): issue_number = None ChangelogHandler(working_dir).add_entry( - changelog_type, message, issue_number=issue_number + domain_type, changelog_type, message, issue_number=issue_number ) diff --git a/changelog/src/changelog_entry.py b/changelog/src/changelog_entry.py index 1effebef7..b8a59e23b 100644 --- a/changelog/src/changelog_entry.py +++ b/changelog/src/changelog_entry.py @@ -15,6 +15,7 @@ class ChangelogEntry(abc.ABC): def generate_entry_dict( self, + domain_type_name: str, message: str, issue_number: Optional[int] = None, bullet_points: List[str] = None, @@ -25,6 +26,7 @@ class ChangelogEntry(abc.ABC): return { "type": self.type, "message": message, + "domain": domain_type_name, "issue_number": issue_number, "bullet_points": bullet_points, "created_at": datetime.now(tz=timezone.utc).strftime("%Y-%m-%d"), diff --git a/changelog/src/changelog_legacy_converter.py b/changelog/src/changelog_legacy_converter.py index baea9f5e3..00c26226a 100644 --- a/changelog/src/changelog_legacy_converter.py +++ b/changelog/src/changelog_legacy_converter.py @@ -1,6 +1,7 @@ from pathlib import Path from typing import List +from domains import DatabaseDomain from changelog_entry import ( BreakingChangeChangelogEntry, BugChangelogEntry, @@ -67,7 +68,7 @@ def sanitise_release_name(release_name: str): def main(): - changelog_file = open("../../changelog.md", "r") + changelog_file = open("../changelog.md", "r") lines = changelog_file.readlines() @@ -110,6 +111,7 @@ def main(): current_changelog_type = FeatureChangelogEntry.type ChangelogHandler().add_entry( + DatabaseDomain.type, current_changelog_type, message, issue_number, diff --git a/changelog/src/domains.py b/changelog/src/domains.py new file mode 100644 index 000000000..2676ca82c --- /dev/null +++ b/changelog/src/domains.py @@ -0,0 +1,44 @@ +from typing import Dict + + +class BaserowDomain: + type = None + heading = None + + @property + def message_prefix(self) -> str: + return f"[{self.heading}] " + + +class CoreDomain(BaserowDomain): + type = "core" + heading = "Core" + + +class DashboardDomain(BaserowDomain): + type = "dashboard" + heading = "Dashboard" + + +class DatabaseDomain(BaserowDomain): + type = "database" + heading = "Database" + + +class BuilderDomain(BaserowDomain): + type = "builder" + heading = "Builder" + + +class AutomationDomain(BaserowDomain): + type = "automation" + heading = "Automation" + + +domain_types: Dict[str, type[BaserowDomain]] = { + CoreDomain.type: CoreDomain, + DashboardDomain.type: DashboardDomain, + DatabaseDomain.type: DatabaseDomain, + BuilderDomain.type: BuilderDomain, + AutomationDomain.type: AutomationDomain, +} diff --git a/changelog/src/handler.py b/changelog/src/handler.py index 689283c5a..c7fb7c743 100644 --- a/changelog/src/handler.py +++ b/changelog/src/handler.py @@ -5,6 +5,7 @@ from json import JSONDecodeError from pathlib import Path from typing import Dict, List, Optional, Union +from domains import domain_types from changelog_entry import changelog_entry_types from pygit2 import Repository @@ -33,6 +34,7 @@ class ChangelogHandler: def add_entry( self, + domain_type_name: str, changelog_entry_type_name: str, message: str, issue_number: Optional[int] = None, @@ -53,7 +55,7 @@ class ChangelogHandler: with open(full_path, "w+") as entry_file: entry = changelog_entry_type().generate_entry_dict( - message, issue_number, bullet_points=bullet_points + domain_type_name, message, issue_number, bullet_points=bullet_points ) json.dump(entry, entry_file, indent=4) @@ -126,6 +128,11 @@ class ChangelogHandler: changelog_file.write(f"# Changelog{LINE_BREAK_CHARACTER}{LINE_BREAK_CHARACTER}") + domain_prefixes = { + domain_type: domain().message_prefix + for domain_type, domain in domain_types.items() + } + for release_folder in release_folders: entries = self.get_changelog_entries(release_folder) @@ -144,8 +151,16 @@ class ChangelogHandler: changelog_file.write(f"{heading}{LINE_BREAK_CHARACTER}") for entry in entries_of_type: + # Prefix the entry's message with the domain prefix. + # Prefix with nothing if the `domain` doesn't exist, + # for compatibility with older entries. + domain_prefix = ( + domain_prefixes[entry["domain"]] if "domain" in entry else "" + ) + entry_message = f"{domain_prefix}{entry['message']}" + entry_markdown_string = entry_type.get_markdown_string( - entry["message"], entry["issue_number"] + entry_message, entry["issue_number"] ) changelog_file.write( @@ -209,18 +224,6 @@ class ChangelogHandler: except ValueError: return None - @staticmethod - def get_message() -> str: - branch_name = Repository(".").head.shorthand - branch_has_issue_number = ChangelogHandler.get_issue_number() is not None - - if branch_has_issue_number: - message = " ".join(branch_name.split("-")[1:]) - else: - message = branch_name - - return message.replace("-", " ") - def write_release_meta_data(self, name: str): # Make sure the parent dirs exist path = Path(self.release_meta_data_file_path) diff --git a/changelog/tests/changelog/test_changelog_handler.py b/changelog/tests/changelog/test_changelog_handler.py index ce7c9c5de..b9b0dc245 100644 --- a/changelog/tests/changelog/test_changelog_handler.py +++ b/changelog/tests/changelog/test_changelog_handler.py @@ -2,38 +2,45 @@ import json from src.changelog_entry import BugChangelogEntry from src.handler import MAXIMUM_FILE_NAME_MESSAGE_LENGTH, ChangelogHandler +from src.domains import BuilderDomain, DatabaseDomain def test_add_entry(fs): - file_path = ChangelogHandler().add_entry(BugChangelogEntry.type, "message") + file_path = ChangelogHandler().add_entry( + DatabaseDomain.type, BugChangelogEntry.type, "Introducing a new feature." + ) assert fs.isfile(file_path) + with open(file_path, "r") as entry_file: + entry = json.load(entry_file) + assert entry["message"] == "Introducing a new feature." + assert entry["domain"] == DatabaseDomain.type def test_get_changelog_entries(fs): handler = ChangelogHandler() - handler.add_entry(BugChangelogEntry.type, "1") - handler.add_entry(BugChangelogEntry.type, "2") + handler.add_entry(DatabaseDomain.type, BugChangelogEntry.type, "1") + handler.add_entry(DatabaseDomain.type, BugChangelogEntry.type, "2") changelog_entries = handler.get_changelog_entries() assert BugChangelogEntry.type in changelog_entries assert [ - BugChangelogEntry().generate_entry_dict("1"), - BugChangelogEntry().generate_entry_dict("2"), + BugChangelogEntry().generate_entry_dict(DatabaseDomain.type, "1"), + BugChangelogEntry().generate_entry_dict(DatabaseDomain.type, "2"), ] in changelog_entries.values() def test_get_changelog_entries_order(fs): handler = ChangelogHandler() - handler.add_entry(BugChangelogEntry.type, "2") - handler.add_entry(BugChangelogEntry.type, "1") + handler.add_entry(DatabaseDomain.type, BugChangelogEntry.type, "2") + handler.add_entry(DatabaseDomain.type, BugChangelogEntry.type, "1") changelog_entries = handler.get_changelog_entries() assert BugChangelogEntry.type in changelog_entries assert [ - BugChangelogEntry().generate_entry_dict("1"), - BugChangelogEntry().generate_entry_dict("2"), + BugChangelogEntry().generate_entry_dict(DatabaseDomain.type, "1"), + BugChangelogEntry().generate_entry_dict(DatabaseDomain.type, "2"), ] in changelog_entries.values() @@ -63,9 +70,9 @@ def test_order_release_folders(fs): def test_move_entries_to_release_folder(fs): handler = ChangelogHandler() - handler.add_entry(BugChangelogEntry.type, "1") - handler.add_entry(BugChangelogEntry.type, "2") - handler.add_entry(BugChangelogEntry.type, "3") + handler.add_entry(DatabaseDomain.type, BugChangelogEntry.type, "1") + handler.add_entry(DatabaseDomain.type, BugChangelogEntry.type, "2") + handler.add_entry(DatabaseDomain.type, BugChangelogEntry.type, "3") assert fs.isdir(f"{handler.entries_file_path}/{handler.UNRELEASED_FOLDER_NAME}") @@ -78,9 +85,9 @@ def test_move_entries_to_release_folder(fs): def test_move_entries_to_release_folder_release_already_exists(fs): handler = ChangelogHandler() - handler.add_entry(BugChangelogEntry.type, "1") - handler.add_entry(BugChangelogEntry.type, "2") - handler.add_entry(BugChangelogEntry.type, "3") + handler.add_entry(DatabaseDomain.type, BugChangelogEntry.type, "1") + handler.add_entry(DatabaseDomain.type, BugChangelogEntry.type, "2") + handler.add_entry(DatabaseDomain.type, BugChangelogEntry.type, "3") assert fs.isdir(f"{handler.entries_file_path}/{handler.UNRELEASED_FOLDER_NAME}") diff --git a/deploy/all-in-one/README.md b/deploy/all-in-one/README.md index c1b6cfbe8..efd7e165f 100644 --- a/deploy/all-in-one/README.md +++ b/deploy/all-in-one/README.md @@ -15,7 +15,7 @@ tool gives you the powers of a developer without leaving your browser. [Vue.js](https://vuejs.org/) and [PostgreSQL](https://www.postgresql.org/). ```bash -docker run -v baserow_data:/baserow/data -p 80:80 -p 443:443 baserow/baserow:1.31.1 +docker run -v baserow_data:/baserow/data -p 80:80 -p 443:443 baserow/baserow:1.32.0 ``` ## Quick Reference @@ -52,7 +52,7 @@ docker run \ -p 80:80 \ -p 443:443 \ --restart unless-stopped \ - baserow/baserow:1.31.1 + baserow/baserow:1.32.0 ``` * Change `BASEROW_PUBLIC_URL` to `https://YOUR_DOMAIN` or `http://YOUR_IP` to enable @@ -75,7 +75,7 @@ docker run \ ## Image Feature Overview -The `baserow/baserow:1.31.1` image by default runs all of Baserow's various services in +The `baserow/baserow:1.32.0` image by default runs all of Baserow's various services in a single container for maximum ease of use. > This image is designed for simple single server deployments or simple container @@ -223,7 +223,7 @@ docker run \ -p 80:80 \ -p 443:443 \ --restart unless-stopped \ - baserow/baserow:1.31.1 + baserow/baserow:1.32.0 ``` ### Behind a reverse proxy already handling ssl @@ -236,7 +236,7 @@ docker run \ -v baserow_data:/baserow/data \ -p 80:80 \ --restart unless-stopped \ - baserow/baserow:1.31.1 + baserow/baserow:1.32.0 ``` ### On a nonstandard HTTP port @@ -249,7 +249,7 @@ docker run \ -v baserow_data:/baserow/data \ -p 3001:80 \ --restart unless-stopped \ - baserow/baserow:1.31.1 + baserow/baserow:1.32.0 ``` ### With an external PostgresSQL server @@ -268,7 +268,7 @@ docker run \ -p 80:80 \ -p 443:443 \ --restart unless-stopped \ - baserow/baserow:1.31.1 + baserow/baserow:1.32.0 ``` ### With an external Redis server @@ -287,7 +287,7 @@ docker run \ -p 80:80 \ -p 443:443 \ --restart unless-stopped \ - baserow/baserow:1.31.1 + baserow/baserow:1.32.0 ``` ### With an external email server @@ -307,7 +307,7 @@ docker run \ -p 80:80 \ -p 443:443 \ --restart unless-stopped \ - baserow/baserow:1.31.1 + baserow/baserow:1.32.0 ``` ### With a Postgresql server running on the same host as the Baserow docker container @@ -345,7 +345,7 @@ docker run \ -v baserow_data:/baserow/data \ -p 80:80 \ -p 443:443 \ - baserow/baserow:1.31.1 + baserow/baserow:1.32.0 ``` ### Supply secrets using files @@ -372,7 +372,7 @@ docker run \ -v baserow_data:/baserow/data \ -p 80:80 \ -p 443:443 \ - baserow/baserow:1.31.1 + baserow/baserow:1.32.0 ``` ### Start just the embedded database @@ -385,7 +385,7 @@ docker run -it \ --name baserow \ -p 5432:5432 \ -v baserow_data:/baserow/data \ - baserow/baserow:1.31.1 \ + baserow/baserow:1.32.0 \ start-only-db # Now get the password from docker exec -it baserow cat /baserow/data/.pgpass @@ -417,7 +417,7 @@ docker run -it \ --rm \ --name baserow \ -v baserow_data:/baserow/data \ - baserow/baserow:1.31.1 \ + baserow/baserow:1.32.0 \ backend-cmd-with-db manage dbshell ``` @@ -540,19 +540,19 @@ the command below. ```bash # First read the help message for this command -docker run -it --rm -v baserow_data:/baserow/data baserow/baserow:1.31.1 \ +docker run -it --rm -v baserow_data:/baserow/data baserow/baserow:1.32.0 \ backend-cmd-with-db backup --help # Stop Baserow instance docker stop baserow # The command below backs up Baserow to the backups folder in the baserow_data volume: -docker run -it --rm -v baserow_data:/baserow/data baserow/baserow:1.31.1 \ +docker run -it --rm -v baserow_data:/baserow/data baserow/baserow:1.32.0 \ backend-cmd-with-db backup -f /baserow/data/backups/backup.tar.gz # Or backup to a file on your host instead run something like: docker run -it --rm -v baserow_data:/baserow/data -v $PWD:/baserow/host \ - baserow/baserow:1.31.1 backend-cmd-with-db backup -f /baserow/host/backup.tar.gz + baserow/baserow:1.32.0 backend-cmd-with-db backup -f /baserow/host/backup.tar.gz ``` ### Restore only Baserow's Postgres Database @@ -568,13 +568,13 @@ docker stop baserow docker run -it --rm \ -v old_baserow_data_volume_containing_the_backup_tar_gz:/baserow/old_data \ -v new_baserow_data_volume_to_restore_into:/baserow/data \ - baserow/baserow:1.31.1 backend-cmd-with-db restore -f /baserow/old_data/backup.tar.gz + baserow/baserow:1.32.0 backend-cmd-with-db restore -f /baserow/old_data/backup.tar.gz # Or to restore from a file on your host instead run something like: docker run -it --rm \ -v baserow_data:/baserow/data -v \ $(pwd):/baserow/host \ - baserow/baserow:1.31.1 backend-cmd-with-db restore -f /baserow/host/backup.tar.gz + baserow/baserow:1.32.0 backend-cmd-with-db restore -f /baserow/host/backup.tar.gz ``` ## Running healthchecks on Baserow @@ -625,7 +625,7 @@ docker run \ -p 80:80 \ -p 443:443 \ --restart unless-stopped \ - baserow/baserow:1.31.1 + baserow/baserow:1.32.0 ``` Or you can just store it directly in the volume at `baserow_data/env` meaning it will be @@ -634,7 +634,7 @@ loaded whenever you mount in this data volume. ### Building your own image from Baserow ```dockerfile -FROM baserow/baserow:1.31.1 +FROM baserow/baserow:1.32.0 # Any .sh files found in /baserow/supervisor/env/ will be sourced and loaded at startup # useful for storing your own environment variable overrides. diff --git a/deploy/all-in-one/supervisor/start.sh b/deploy/all-in-one/supervisor/start.sh index 06f4ff6d5..919e95d82 100755 --- a/deploy/all-in-one/supervisor/start.sh +++ b/deploy/all-in-one/supervisor/start.sh @@ -14,7 +14,7 @@ cat << EOF ██████╔╝██║ ██║███████║███████╗██║ ██║╚██████╔╝╚███╔███╔╝ ╚═════╝ ╚═╝ ╚═╝╚══════╝╚══════╝╚═╝ ╚═╝ ╚═════╝ ╚══╝╚══╝ -Version 1.31.1 +Version 1.32.0 ========================================================================================= EOF diff --git a/deploy/cloudron/CloudronManifest.json b/deploy/cloudron/CloudronManifest.json index 3d57ff3cd..fb8268b13 100644 --- a/deploy/cloudron/CloudronManifest.json +++ b/deploy/cloudron/CloudronManifest.json @@ -8,7 +8,7 @@ "contactEmail": "bram@baserow.io", "icon": "file://logo.png", "tags": ["no-code", "nocode", "database", "data", "collaborate", "airtable"], - "version": "1.31.1", + "version": "1.32.0", "healthCheckPath": "/api/_health/", "httpPort": 80, "addons": { diff --git a/deploy/cloudron/Dockerfile b/deploy/cloudron/Dockerfile index 1f85ad451..50221589f 100644 --- a/deploy/cloudron/Dockerfile +++ b/deploy/cloudron/Dockerfile @@ -1,4 +1,4 @@ -ARG FROM_IMAGE=baserow/baserow:1.31.1 +ARG FROM_IMAGE=baserow/baserow:1.32.0 # This is pinned as version pinning is done by the CI setting FROM_IMAGE. # hadolint ignore=DL3006 FROM $FROM_IMAGE as image_base diff --git a/deploy/helm/baserow/Chart.lock b/deploy/helm/baserow/Chart.lock index af047dfb6..8aadf445c 100644 --- a/deploy/helm/baserow/Chart.lock +++ b/deploy/helm/baserow/Chart.lock @@ -1,25 +1,25 @@ dependencies: - name: baserow repository: file://charts/baserow-common - version: 1.0.14 + version: 1.0.15 - name: baserow repository: file://charts/baserow-common - version: 1.0.14 + version: 1.0.15 - name: baserow repository: file://charts/baserow-common - version: 1.0.14 + version: 1.0.15 - name: baserow repository: file://charts/baserow-common - version: 1.0.14 + version: 1.0.15 - name: baserow repository: file://charts/baserow-common - version: 1.0.14 + version: 1.0.15 - name: baserow repository: file://charts/baserow-common - version: 1.0.14 + version: 1.0.15 - name: baserow repository: file://charts/baserow-common - version: 1.0.14 + version: 1.0.15 - name: redis repository: https://charts.bitnami.com/bitnami version: 19.5.5 @@ -32,5 +32,5 @@ dependencies: - name: caddy-ingress-controller repository: https://caddyserver.github.io/ingress version: 1.1.0 -digest: sha256:c80fd45c820ddb8ca86bfb6edf4d0c2071e52b4ce20c8de47a30bd2a90482583 -generated: "2025-02-07T14:07:29.81321+01:00" +digest: sha256:d921363d9be6a7f8425b9844409dda118bede83ddde8c44881cf4e5d5a4e6af0 +generated: "2025-03-18T15:00:40.464957+01:00" diff --git a/deploy/helm/baserow/Chart.yaml b/deploy/helm/baserow/Chart.yaml index dc11ba51c..83dfa111a 100644 --- a/deploy/helm/baserow/Chart.yaml +++ b/deploy/helm/baserow/Chart.yaml @@ -2,8 +2,8 @@ apiVersion: v2 name: baserow description: The open platform to create scalable databases and applications—without coding. type: application -version: 1.0.14 -appVersion: "1.31.1" +version: 1.0.15 +appVersion: "1.32.0" home: https://gitlab.com/baserow/baserow/-/tree/develop/deploy/helm/baserow?ref_type=heads icon: https://baserow.io/img/favicon_192.png sources: @@ -13,37 +13,37 @@ sources: dependencies: - name: baserow alias: baserow-backend-asgi - version: "1.0.14" + version: "1.0.15" repository: "file://charts/baserow-common" - name: baserow alias: baserow-backend-wsgi - version: "1.0.14" + version: "1.0.15" repository: "file://charts/baserow-common" - name: baserow alias: baserow-frontend - version: "1.0.14" + version: "1.0.15" repository: "file://charts/baserow-common" - name: baserow alias: baserow-celery-beat-worker - version: "1.0.14" + version: "1.0.15" repository: "file://charts/baserow-common" - name: baserow alias: baserow-celery-export-worker - version: "1.0.14" + version: "1.0.15" repository: "file://charts/baserow-common" - name: baserow alias: baserow-celery-worker - version: "1.0.14" + version: "1.0.15" repository: "file://charts/baserow-common" - name: baserow alias: baserow-celery-flower - version: "1.0.14" + version: "1.0.15" repository: "file://charts/baserow-common" condition: baserow-celery-flower.enabled diff --git a/deploy/helm/baserow/README.md b/deploy/helm/baserow/README.md index 3b401d8b6..c70b0080c 100644 --- a/deploy/helm/baserow/README.md +++ b/deploy/helm/baserow/README.md @@ -202,7 +202,7 @@ caddy: | ------------------------------------------------------------------ | --------------------------------------------------------------------------------------- | ----------------------- | | `global.baserow.imageRegistry` | Global Docker image registry | `baserow` | | `global.baserow.imagePullSecrets` | Global Docker registry secret names as an array | `[]` | -| `global.baserow.image.tag` | Global Docker image tag | `1.31.1` | +| `global.baserow.image.tag` | Global Docker image tag | `1.32.0` | | `global.baserow.serviceAccount.shared` | Set to true to share the service account between all application components. | `true` | | `global.baserow.serviceAccount.create` | Set to true to create a service account to share between all application components. | `true` | | `global.baserow.serviceAccount.name` | Configure a name for service account to share between all application components. | `baserow` | diff --git a/deploy/helm/baserow/charts/baserow-common/Chart.yaml b/deploy/helm/baserow/charts/baserow-common/Chart.yaml index 250dca3f2..8d9c8aba2 100644 --- a/deploy/helm/baserow/charts/baserow-common/Chart.yaml +++ b/deploy/helm/baserow/charts/baserow-common/Chart.yaml @@ -15,10 +15,10 @@ type: application # This is the chart version. This version number should be incremented each time you make changes # to the chart and its templates, including the app version. # Versions are expected to follow Semantic Versioning (https://semver.org/) -version: 1.0.14 +version: 1.0.15 # This is the version number of the application being deployed. This version number should be # incremented each time you make changes to the application. Versions are not expected to # follow Semantic Versioning. They should reflect the version the application is using. # It is recommended to use it with quotes. -appVersion: "1.31.1" +appVersion: "1.32.0" diff --git a/deploy/helm/baserow/charts/baserow-common/README.md b/deploy/helm/baserow/charts/baserow-common/README.md index 6f5f1a4bb..6ecc7f724 100644 --- a/deploy/helm/baserow/charts/baserow-common/README.md +++ b/deploy/helm/baserow/charts/baserow-common/README.md @@ -6,7 +6,7 @@ | ------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------- | | `global.baserow.imageRegistry` | Global Docker image registry | `baserow` | | `global.baserow.imagePullSecrets` | Global Docker registry secret names as an array | `[]` | -| `global.baserow.image.tag` | Global Docker image tag | `1.31.1` | +| `global.baserow.image.tag` | Global Docker image tag | `1.32.0` | | `global.baserow.serviceAccount.shared` | Set to true to share the service account between all application components. | `true` | | `global.baserow.serviceAccount.create` | Set to true to create a service account to share between all application components. | `true` | | `global.baserow.serviceAccount.name` | Configure a name for service account to share between all application components. | `baserow` | diff --git a/deploy/helm/baserow/charts/baserow-common/values.yaml b/deploy/helm/baserow/charts/baserow-common/values.yaml index 0f8f058c2..682a29a7d 100644 --- a/deploy/helm/baserow/charts/baserow-common/values.yaml +++ b/deploy/helm/baserow/charts/baserow-common/values.yaml @@ -38,7 +38,7 @@ global: baserow: imageRegistry: baserow image: - tag: 1.31.1 + tag: 1.32.0 imagePullSecrets: [] serviceAccount: shared: true @@ -83,7 +83,7 @@ global: ## image: repository: baserow/baserow # Docker image repository - tag: 1.31.1 # Docker image tag + tag: 1.32.0 # Docker image tag pullPolicy: IfNotPresent # Image pull policy ## @param workingDir Application container working directory diff --git a/deploy/helm/baserow/values.yaml b/deploy/helm/baserow/values.yaml index 60d6136e7..9202cf64e 100644 --- a/deploy/helm/baserow/values.yaml +++ b/deploy/helm/baserow/values.yaml @@ -43,7 +43,7 @@ global: baserow: imageRegistry: baserow image: - tag: 1.31.1 + tag: 1.32.0 imagePullSecrets: [] serviceAccount: shared: true diff --git a/deploy/render/Dockerfile b/deploy/render/Dockerfile index f49b6246d..5a2d7f107 100644 --- a/deploy/render/Dockerfile +++ b/deploy/render/Dockerfile @@ -1,4 +1,4 @@ -ARG FROM_IMAGE=baserow/baserow:1.31.1 +ARG FROM_IMAGE=baserow/baserow:1.32.0 # This is pinned as version pinning is done by the CI setting FROM_IMAGE. # hadolint ignore=DL3006 FROM $FROM_IMAGE as image_base diff --git a/docker-compose.all-in-one.yml b/docker-compose.all-in-one.yml index 629562322..156698399 100644 --- a/docker-compose.all-in-one.yml +++ b/docker-compose.all-in-one.yml @@ -4,7 +4,7 @@ version: "3.4" services: baserow: container_name: baserow - image: baserow/baserow:1.31.1 + image: baserow/baserow:1.32.0 environment: BASEROW_PUBLIC_URL: 'http://localhost' ports: diff --git a/docker-compose.local-build.yml b/docker-compose.local-build.yml index 123afaf02..5448147c3 100644 --- a/docker-compose.local-build.yml +++ b/docker-compose.local-build.yml @@ -156,6 +156,8 @@ x-backend-variables: &backend-variables BASEROW_BUILDER_DOMAINS: BASEROW_FRONTEND_SAME_SITE_COOKIE: BASEROW_ICAL_VIEW_MAX_EVENTS: ${BASEROW_ICAL_VIEW_MAX_EVENTS:-} + BASEROW_WEBHOOK_ROWS_ENTER_VIEW_BATCH_SIZE: + BASEROW_ENTERPRISE_GROUPED_AGGREGATE_SERVICE_MAX_SERIES: services: # A caddy reverse proxy sitting in-front of all the services. Responsible for routing diff --git a/docker-compose.no-caddy.yml b/docker-compose.no-caddy.yml index 9c4ec9380..dd14626e5 100644 --- a/docker-compose.no-caddy.yml +++ b/docker-compose.no-caddy.yml @@ -174,10 +174,12 @@ x-backend-variables: &backend-variables BASEROW_AUTO_VACUUM: BASEROW_BUILDER_DOMAINS: BASEROW_ICAL_VIEW_MAX_EVENTS: ${BASEROW_ICAL_VIEW_MAX_EVENTS:-} + BASEROW_WEBHOOK_ROWS_ENTER_VIEW_BATCH_SIZE: + BASEROW_ENTERPRISE_GROUPED_AGGREGATE_SERVICE_MAX_SERIES: services: backend: - image: baserow/backend:1.31.1 + image: baserow/backend:1.32.0 restart: unless-stopped ports: - "${HOST_PUBLISH_IP:-127.0.0.1}:8000:8000" @@ -192,7 +194,7 @@ services: local: web-frontend: - image: baserow/web-frontend:1.31.1 + image: baserow/web-frontend:1.32.0 restart: unless-stopped ports: - "${HOST_PUBLISH_IP:-127.0.0.1}:3000:3000" @@ -227,7 +229,7 @@ services: local: celery: - image: baserow/backend:1.31.1 + image: baserow/backend:1.32.0 restart: unless-stopped environment: <<: *backend-variables @@ -244,7 +246,7 @@ services: local: celery-export-worker: - image: baserow/backend:1.31.1 + image: baserow/backend:1.32.0 restart: unless-stopped command: celery-exportworker environment: @@ -261,7 +263,7 @@ services: local: celery-beat-worker: - image: baserow/backend:1.31.1 + image: baserow/backend:1.32.0 restart: unless-stopped command: celery-beat environment: diff --git a/docker-compose.yml b/docker-compose.yml index a4b895d96..4f88f35db 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -200,6 +200,9 @@ x-backend-variables: &backend-variables BASEROW_ENTERPRISE_PERIODIC_DATA_SYNC_CHECK_INTERVAL_MINUTES: BASEROW_ENTERPRISE_MAX_PERIODIC_DATA_SYNC_CONSECUTIVE_ERRORS: BASEROW_USE_LOCAL_CACHE: + BASEROW_WEBHOOKS_BATCH_LIMIT: + BASEROW_WEBHOOK_ROWS_ENTER_VIEW_BATCH_SIZE: + BASEROW_ENTERPRISE_GROUPED_AGGREGATE_SERVICE_MAX_SERIES: services: # A caddy reverse proxy sitting in-front of all the services. Responsible for routing @@ -226,7 +229,7 @@ services: local: backend: - image: baserow/backend:1.31.1 + image: baserow/backend:1.32.0 restart: unless-stopped environment: @@ -240,7 +243,7 @@ services: local: web-frontend: - image: baserow/web-frontend:1.31.1 + image: baserow/web-frontend:1.32.0 restart: unless-stopped environment: BASEROW_PUBLIC_URL: ${BASEROW_PUBLIC_URL-http://localhost} @@ -270,13 +273,14 @@ services: BASEROW_BUILDER_DOMAINS: BASEROW_FRONTEND_SAME_SITE_COOKIE: SENTRY_DSN: + BASEROW_ENTERPRISE_GROUPED_AGGREGATE_SERVICE_MAX_SERIES: depends_on: - backend networks: local: celery: - image: baserow/backend:1.31.1 + image: baserow/backend:1.32.0 restart: unless-stopped environment: <<: *backend-variables @@ -293,7 +297,7 @@ services: local: celery-export-worker: - image: baserow/backend:1.31.1 + image: baserow/backend:1.32.0 restart: unless-stopped command: celery-exportworker environment: @@ -310,7 +314,7 @@ services: local: celery-beat-worker: - image: baserow/backend:1.31.1 + image: baserow/backend:1.32.0 restart: unless-stopped command: celery-beat environment: diff --git a/docs/development/running-tests.md b/docs/development/running-tests.md index c51b22e02..d76df3ed6 100644 --- a/docs/development/running-tests.md +++ b/docs/development/running-tests.md @@ -20,6 +20,27 @@ backend directory. For example: BASEROW_MAX_FIELD_LIMIT=1 ``` +### Migrations and database setup + +By default, `BASEROW_TESTS_SETUP_DB_FIXTURE` is considered `on` in the +`config.settings.tests` configuration. This means that the database will be +set up without running the migrations, but only installing the database +formulas needed for the tests. This is done to speed up the test setup +process. + +If you want to run the migrations, you can run +`BASEROW_TESTS_SETUP_DB_FIXTURE=off pytest` to run them all. This is useful +when you want to test the migrations and you don't care about the speed of +the test setup. + +If you want to install the custom formula pgSQL functions only once and then +reuse the database between tests, you can run +`BASEROW_TESTS_SETUP_DB_FIXTURE=off pytest --no-migrations --reuse-db`. + +You can even omit `--no-migrations` to apply any new migrations coming from +the current branch to avoid recreating the database from scratch. + + ### Running Tests Outside the Backend Container To run tests outside the backend container, follow these steps: diff --git a/docs/installation/configuration.md b/docs/installation/configuration.md index ca911fec8..27b2e1a3e 100644 --- a/docs/installation/configuration.md +++ b/docs/installation/configuration.md @@ -120,6 +120,8 @@ The installation methods referred to in the variable descriptions are: | BASEROW\_WEBHOOKS\_MAX\_CALL\_LOG\_ENTRIES | The maximum number of call log entries stored per webhook. | 10 | | BASEROW\_WEBHOOKS\_REQUEST\_TIMEOUT\_SECONDS | How long to wait on making the webhook request before timing out. | 5 | | BASEROW\_MAX\_WEBHOOK\_CALLS\_IN\_QUEUE\_PER\_WEBHOOK | Maximum number of calls that can be in the webhook's queue. Can be useful to limit when massive numbers of webhooks are triggered due an automation loop. If not set or set to `0`, then there is no limit. | 0 | +| BASEROW\_WEBHOOKS\_BATCH\_LIMIT | This limit applies to all webhook_event_types that split large payloads into multiple batches. Each batch is a separate request with the same event_id and an incremental batch_id. This parameter sets the maximum number of batches per event. Set to 0 for unlimited batches. | 5 | +| BASEROW\_WEBHOOK\_ROWS\_ENTER\_VIEW\_BATCH\_SIZE | Defines the number of rows that can be sent in a single webhook call of type `view.rows_entered`. This is used to prevent the webhook call from being too large and potentially causing issues while serializing the data or sending it over the network to the webhook endpoint. | 200 | ### Generative AI configuration diff --git a/docs/installation/install-behind-apache.md b/docs/installation/install-behind-apache.md index 4954a8696..177df0762 100644 --- a/docs/installation/install-behind-apache.md +++ b/docs/installation/install-behind-apache.md @@ -3,7 +3,7 @@ If you have an [Apache server](https://www.apache.com/) this guide will explain how to configure it to pass requests through to Baserow. -We strongly recommend you use our `baserow/baserow:1.31.1` image or the example +We strongly recommend you use our `baserow/baserow:1.32.0` image or the example `docker-compose.yml` files (excluding the `.no-caddy.yml` variant) provided in our [git repository](https://gitlab.com/baserow/baserow/-/tree/master/deploy/apache/). @@ -18,8 +18,8 @@ simplifies your life by: > If you do not want to use our embedded Caddy service behind your Apache then > make sure you are using one of the two following deployment methods: > -> * Your own container setup with our single service `baserow/backend:1.31.1` - and `baserow/web-frontend:1.31.1` images. +> * Your own container setup with our single service `baserow/backend:1.32.0` + and `baserow/web-frontend:1.32.0` images. > * Or our `docker-compose.no-caddy.yml` example file in our [git repository](https://gitlab.com/baserow/baserow/-/tree/master/deploy/apache/). > > Then you should use **Option 2: Without our embedded Caddy** section instead. @@ -32,7 +32,7 @@ simplifies your life by: Follow this option if you are using: -* The all-in-one Baserow image `baserow/baserow:1.31.1` +* The all-in-one Baserow image `baserow/baserow:1.32.0` * Any of the example compose files found in the root of our git repository `docker-compose.yml`/`docker-compose.local-build.yml` /`docker-compose.all-in-one.yml` @@ -116,7 +116,7 @@ You should now be able to access Baserow on you configured subdomain. Follow this option if you are using: -* Our standalone `baserow/backend:1.31.1` and `baserow/web-frontend:1.31.1` images with +* Our standalone `baserow/backend:1.32.0` and `baserow/web-frontend:1.32.0` images with your own container orchestrator. * Or the `docker-compose.no-caddy.yml` example docker compose file in the root of our git repository. @@ -148,7 +148,7 @@ sudo systemctl restart apache2 You need to ensure user uploaded files are accessible in a folder for Apache to serve. In the rest of the guide we will use the example `/var/web` folder for this purpose. -If you are using the `baserow/backend:1.31.1` image then you can do this by adding +If you are using the `baserow/backend:1.32.0` image then you can do this by adding `-v /var/web:/baserow/data/media` to your normal `docker run` command used to launch the Baserow backend. diff --git a/docs/installation/install-behind-nginx.md b/docs/installation/install-behind-nginx.md index 408d59992..b0ede7177 100644 --- a/docs/installation/install-behind-nginx.md +++ b/docs/installation/install-behind-nginx.md @@ -3,7 +3,7 @@ If you have an [Nginx server](https://www.nginx.com/) this guide will explain how to configure it to pass requests through to Baserow. -We strongly recommend you use our `baserow/baserow:1.31.1` image or the example +We strongly recommend you use our `baserow/baserow:1.32.0` image or the example `docker-compose.yml` files (excluding the `.no-caddy.yml` variant) provided in our [git repository](https://gitlab.com/baserow/baserow/-/tree/master/deploy/nginx/). @@ -18,8 +18,8 @@ simplifies your life by: > If you do not want to use our embedded Caddy service behind your Nginx then > make sure you are using one of the two following deployment methods: > -> * Your own container setup with our single service `baserow/backend:1.31.1` - and `baserow/web-frontend:1.31.1` images. +> * Your own container setup with our single service `baserow/backend:1.32.0` + and `baserow/web-frontend:1.32.0` images. > * Or our `docker-compose.no-caddy.yml` example file in our [git repository](https://gitlab.com/baserow/baserow/-/tree/master/deploy/nginx/). > > Then you should use **Option 2: Without our embedded Caddy** section instead. @@ -32,7 +32,7 @@ simplifies your life by: Follow this option if you are using: -* The all-in-one Baserow image `baserow/baserow:1.31.1` +* The all-in-one Baserow image `baserow/baserow:1.32.0` * Any of the example compose files found in the root of our git repository `docker-compose.yml`/`docker-compose.local-build.yml` /`docker-compose.all-in-one.yml` @@ -108,7 +108,7 @@ You should now be able to access Baserow on you configured subdomain. Follow this option if you are using: -* Our standalone `baserow/backend:1.31.1` and `baserow/web-frontend:1.31.1` images with +* Our standalone `baserow/backend:1.32.0` and `baserow/web-frontend:1.32.0` images with your own container orchestrator. * Or the `docker-compose.no-caddy.yml` example docker compose file in the root of our git repository. @@ -127,7 +127,7 @@ but you might have to run different commands. You need to ensure user uploaded files are accessible in a folder for Nginx to serve. In the rest of the guide we will use the example `/var/web` folder for this purpose. -If you are using the `baserow/backend:1.31.1` image then you can do this by adding +If you are using the `baserow/backend:1.32.0` image then you can do this by adding `-v /var/web:/baserow/data/media` to your normal `docker run` command used to launch the Baserow backend. diff --git a/docs/installation/install-on-aws.md b/docs/installation/install-on-aws.md index 1813c79ad..6e0544aa8 100644 --- a/docs/installation/install-on-aws.md +++ b/docs/installation/install-on-aws.md @@ -49,7 +49,7 @@ overview this is what any AWS deployment of Baserow will need: ## Option 1) Deploying the all-in-one image to Fargate/ECS -The `baserow/baserow:1.31.1` image runs all of Baserow’s various services inside the +The `baserow/baserow:1.32.0` image runs all of Baserow’s various services inside the container for ease of use. This image is designed for single server deployments or simple deployments to @@ -67,7 +67,7 @@ Run. * You don't need to worry about configuring and linking together the different services that make up a Baserow deployment. * Configuring load balancers is easier as you can just directly route through all - requests to any horizontally scaled container running `baserow/baserow:1.31.1`. + requests to any horizontally scaled container running `baserow/baserow:1.32.0`. #### Cons @@ -75,7 +75,7 @@ Run. * Potentially higher resource usage overall as each of the all-in-one containers will come with its internal services, so you have less granular control over scaling specific services. - * For example if you deploy 10 `baserow/baserow:1.31.1` containers horizontally you + * For example if you deploy 10 `baserow/baserow:1.32.0` containers horizontally you by default end up with: * 10 web-frontend services * 10 backend services @@ -188,18 +188,18 @@ Generally, the Redis server is not the bottleneck in Baserow deployments as they Now create a target group on port 80 and ALB ready to route traffic to the Baserow containers. -When setting up the health check for the ALB the `baserow/baserow:1.31.1` container +When setting up the health check for the ALB the `baserow/baserow:1.32.0` container ,which you'll be deploying next, choose port `80` and health check URL `/api/_health/`. We recommend a long grace period of 900 seconds to account for first-time migrations being run on the first container's startup. #### 5) Launching Baserow on ECS/Fargate -Now we are ready to spin up our `baserow/baserow:1.31.1` containers. See below for a +Now we are ready to spin up our `baserow/baserow:1.32.0` containers. See below for a full task definition and environment variables. We recommend launching the containers with 2vCPUs and 4 GB of RAM each to start with. In short, you will want to: -1. Select the `baserow/baserow:1.31.1` image. +1. Select the `baserow/baserow:1.32.0` image. 2. Add a port mapping of `80` on TCP as this is where this images HTTP server is listening by default. 3. Mark the container as essential. @@ -244,7 +244,7 @@ container_definitions = <<DEFINITION [ { "name": "baserow_task", - "image": "baserow/baserow:1.31.1", + "image": "baserow/baserow:1.32.0", "logConfiguration": { #logs are not mandatory "logDriver": "awslogs", "options": { @@ -368,7 +368,7 @@ in-tool settings, active enterprise licenses, promote other users to being staff ## Option 2) Deploying Baserow as separate services to Fargate/ECS -The `baserow/backend:1.31.1` and `baserow/web-frontend:1.31.1` images allow you to run +The `baserow/backend:1.32.0` and `baserow/web-frontend:1.32.0` images allow you to run Baserow's various services as separate containers. These images are used by the community Helm chart, our various docker-compose.yml @@ -441,7 +441,7 @@ Alternatively [this docker-compose](https://gitlab.com/baserow/baserow/-/blob/de This service is our HTTP REST API service. When creating the task definition you should: -1. In the task defintion use the `baserow/backend:1.31.1` image +1. In the task defintion use the `baserow/backend:1.32.0` image 2. Under docker configuration set `gunicorn-wsgi,--timeout,60` as the Command. > We recommend setting the timeout of each HTTP API request to 60 seconds in the @@ -484,7 +484,7 @@ This service is our HTTP REST API service. When creating the task definition you This service is our Websocket API service and when configuring the task definition you should: -1. Use the `baserow/backend:1.31.1` +1. Use the `baserow/backend:1.32.0` 2. Under docker configuration set `gunicorn` as the Command. 3. We recommend 2vCPUs and 4 GB of RAM per container to start with. 4. Map the container port `8000`/`TCP` @@ -496,7 +496,7 @@ should: This service is our asynchronous high priority task worker queue used for realtime collaboration and sending emails. -1. Use the `baserow/backend:1.31.1` image with `celery-worker` as the image command. +1. Use the `baserow/backend:1.32.0` image with `celery-worker` as the image command. 2. Under docker configuration set `celery-worker` as the Command. 3. No port mappings needed. 4. We recommend 2vCPUs and 4 GB of RAM per container to start with. @@ -509,7 +509,7 @@ This service is our asynchronous slow/low priority task worker queue for batch processes and running potentially slow operations for users like table exports and imports etc. -1. Use the `baserow/backend:1.31.1` image. +1. Use the `baserow/backend:1.32.0` image. 2. Under docker configuration set `celery-exportworker` as the Command. 3. No port mappings needed. 4. We recommend 2vCPUs and 4 GB of RAM per container to start with. @@ -520,7 +520,7 @@ imports etc. This service is our CRON task scheduler that can have multiple replicas deployed. -1. Use the `baserow/backend:1.31.1` image. +1. Use the `baserow/backend:1.32.0` image. 2. Under docker configuration set `celery-beat` as the Command. 3. No port mapping needed. 4. We recommend 1vCPUs and 3 GB of RAM per container to start with. @@ -537,7 +537,7 @@ This service is our CRON task scheduler that can have multiple replicas deployed Finally, this service is used for server side rendering and serving the frontend of Baserow. -1. Use the `baserow/web-frontend:1.31.1` image with no arguments needed. +1. Use the `baserow/web-frontend:1.32.0` image with no arguments needed. 2. Map the container port `3000` 3. We recommend 2vCPUs and 4 GB of RAM per container to start with. 4. Mark the container as essential. diff --git a/docs/installation/install-on-cloudron.md b/docs/installation/install-on-cloudron.md index 340326f71..9064350e6 100644 --- a/docs/installation/install-on-cloudron.md +++ b/docs/installation/install-on-cloudron.md @@ -46,7 +46,7 @@ $ cd baserow/deploy/cloudron After that you can install the Baserow Cloudron app by executing the following commands. ``` -$ cloudron install -l baserow.{YOUR_DOMAIN} --image baserow/cloudron:1.31.1 +$ cloudron install -l baserow.{YOUR_DOMAIN} --image baserow/cloudron:1.32.0 App is being installed. ... App is installed. @@ -89,7 +89,7 @@ the `baserow/deploy/cloudron` folder, you can upgrade your cloudron baserow serv the latest version by running the following command: ``` -cloudron update --app {YOUR_APP_ID} --image baserow/cloudron:1.31.1 +cloudron update --app {YOUR_APP_ID} --image baserow/cloudron:1.32.0 ``` > Note that you must replace the image with the most recent image of Baserow. The diff --git a/docs/installation/install-on-digital-ocean.md b/docs/installation/install-on-digital-ocean.md index a35fd91b3..f69bc4dce 100644 --- a/docs/installation/install-on-digital-ocean.md +++ b/docs/installation/install-on-digital-ocean.md @@ -51,7 +51,7 @@ Navigate to the `Apps` page in the left sidebar of your Digital Ocean dashboard. on `Create App`, select `Docker Hub`, and fill out the following: Repository: `baserow/baserow` -Image tag or digest: `1.31.1` +Image tag or digest: `1.32.0` Click on `Next`, then on the `Edit` button of the `baserow-baserow` web service. Here you must change the HTTP Port to 80, and then click on `Back`. Click on the `Next` @@ -124,7 +124,7 @@ environment. In order to update the Baserow version, you simply need to replace the image tag. Navigate to the `Settings` tag of your created app, click on the `baserow-baserow` component, then click on the `Edit` button next to source, change the `Image tag` into -the desired version (latest is `1.31.1`), and click on save. The app will redeploy +the desired version (latest is `1.32.0`), and click on save. The app will redeploy with the latest version. ## External email server diff --git a/docs/installation/install-on-ubuntu.md b/docs/installation/install-on-ubuntu.md index c6d5c93b7..3dea2b9a2 100644 --- a/docs/installation/install-on-ubuntu.md +++ b/docs/installation/install-on-ubuntu.md @@ -34,7 +34,7 @@ docker run -e BASEROW_PUBLIC_URL=http://localhost \ -v baserow_data:/baserow/data \ -p 80:80 \ -p 443:443 \ -baserow/baserow:1.31.1 +baserow/baserow:1.32.0 # Watch the logs for Baserow to come available by running: docker logs baserow ``` @@ -147,7 +147,7 @@ docker run \ -v /baserow/media:/baserow/data/media \ -p 80:80 \ -p 443:443 \ - baserow/baserow:1.31.1 + baserow/baserow:1.32.0 # Check the logs and wait for Baserow to become available docker logs baserow ``` diff --git a/docs/installation/install-using-standalone-images.md b/docs/installation/install-using-standalone-images.md index 6abfb7fa2..b1800a9a1 100644 --- a/docs/installation/install-using-standalone-images.md +++ b/docs/installation/install-using-standalone-images.md @@ -10,9 +10,9 @@ Baserow consists of a number of services, two of which are built and provided as separate standalone images by us: -* `baserow/backend:1.31.1` which by default starts the Gunicorn Django backend server +* `baserow/backend:1.32.0` which by default starts the Gunicorn Django backend server for Baserow but is also used to start the celery workers and celery beat services. -* `baserow/web-frontend:1.31.1` which is a Nuxt server providing Server Side rendering +* `baserow/web-frontend:1.32.0` which is a Nuxt server providing Server Side rendering for the website. If you want to use your own container orchestration software like Kubernetes then these @@ -27,10 +27,10 @@ in the root of our repository. These are all the services you need to set up to run a Baserow using the standalone images: -* `baserow/backend:1.31.1` (default command is `gunicorn`) -* `baserow/backend:1.31.1` with command `celery-worker` -* `baserow/backend:1.31.1` with command `celery-export-worker` -* `baserow/web-frontend:1.31.1` (default command is `nuxt-local`) +* `baserow/backend:1.32.0` (default command is `gunicorn`) +* `baserow/backend:1.32.0` with command `celery-worker` +* `baserow/backend:1.32.0` with command `celery-export-worker` +* `baserow/web-frontend:1.32.0` (default command is `nuxt-local`) * A postgres database * A redis server diff --git a/docs/installation/install-with-docker-compose.md b/docs/installation/install-with-docker-compose.md index ffb7330c8..56bf83a26 100644 --- a/docs/installation/install-with-docker-compose.md +++ b/docs/installation/install-with-docker-compose.md @@ -16,7 +16,7 @@ version: "3.4" services: baserow: container_name: baserow - image: baserow/baserow:1.31.1 + image: baserow/baserow:1.32.0 environment: BASEROW_PUBLIC_URL: 'http://localhost' ports: diff --git a/docs/installation/install-with-docker.md b/docs/installation/install-with-docker.md index 9259f34a2..57e159860 100644 --- a/docs/installation/install-with-docker.md +++ b/docs/installation/install-with-docker.md @@ -29,7 +29,7 @@ docker run \ -p 80:80 \ -p 443:443 \ --restart unless-stopped \ - baserow/baserow:1.31.1 + baserow/baserow:1.32.0 ``` * Change `BASEROW_PUBLIC_URL` to `https://YOUR_DOMAIN` or `http://YOUR_IP` to enable @@ -52,7 +52,7 @@ docker run \ ## Image Feature Overview -The `baserow/baserow:1.31.1` image by default runs all of Baserow's various services in +The `baserow/baserow:1.32.0` image by default runs all of Baserow's various services in a single container for maximum ease of use. > This image is designed for simple single server deployments or simple container @@ -200,7 +200,7 @@ docker run \ -p 80:80 \ -p 443:443 \ --restart unless-stopped \ - baserow/baserow:1.31.1 + baserow/baserow:1.32.0 ``` ### Behind a reverse proxy already handling ssl @@ -213,7 +213,7 @@ docker run \ -v baserow_data:/baserow/data \ -p 80:80 \ --restart unless-stopped \ - baserow/baserow:1.31.1 + baserow/baserow:1.32.0 ``` ### On a nonstandard HTTP port @@ -226,7 +226,7 @@ docker run \ -v baserow_data:/baserow/data \ -p 3001:80 \ --restart unless-stopped \ - baserow/baserow:1.31.1 + baserow/baserow:1.32.0 ``` ### With an external PostgresSQL server @@ -245,7 +245,7 @@ docker run \ -p 80:80 \ -p 443:443 \ --restart unless-stopped \ - baserow/baserow:1.31.1 + baserow/baserow:1.32.0 ``` ### With an external Redis server @@ -264,7 +264,7 @@ docker run \ -p 80:80 \ -p 443:443 \ --restart unless-stopped \ - baserow/baserow:1.31.1 + baserow/baserow:1.32.0 ``` ### With an external email server @@ -284,7 +284,7 @@ docker run \ -p 80:80 \ -p 443:443 \ --restart unless-stopped \ - baserow/baserow:1.31.1 + baserow/baserow:1.32.0 ``` ### With a Postgresql server running on the same host as the Baserow docker container @@ -322,7 +322,7 @@ docker run \ -v baserow_data:/baserow/data \ -p 80:80 \ -p 443:443 \ - baserow/baserow:1.31.1 + baserow/baserow:1.32.0 ``` ### Supply secrets using files @@ -349,7 +349,7 @@ docker run \ -v baserow_data:/baserow/data \ -p 80:80 \ -p 443:443 \ - baserow/baserow:1.31.1 + baserow/baserow:1.32.0 ``` ### Start just the embedded database @@ -362,7 +362,7 @@ docker run -it \ --name baserow \ -p 5432:5432 \ -v baserow_data:/baserow/data \ - baserow/baserow:1.31.1 \ + baserow/baserow:1.32.0 \ start-only-db # Now get the password from docker exec -it baserow cat /baserow/data/.pgpass @@ -394,7 +394,7 @@ docker run -it \ --rm \ --name baserow \ -v baserow_data:/baserow/data \ - baserow/baserow:1.31.1 \ + baserow/baserow:1.32.0 \ backend-cmd-with-db manage dbshell ``` @@ -517,19 +517,19 @@ the command below. ```bash # First read the help message for this command -docker run -it --rm -v baserow_data:/baserow/data baserow/baserow:1.31.1 \ +docker run -it --rm -v baserow_data:/baserow/data baserow/baserow:1.32.0 \ backend-cmd-with-db backup --help # Stop Baserow instance docker stop baserow # The command below backs up Baserow to the backups folder in the baserow_data volume: -docker run -it --rm -v baserow_data:/baserow/data baserow/baserow:1.31.1 \ +docker run -it --rm -v baserow_data:/baserow/data baserow/baserow:1.32.0 \ backend-cmd-with-db backup -f /baserow/data/backups/backup.tar.gz # Or backup to a file on your host instead run something like: docker run -it --rm -v baserow_data:/baserow/data -v $PWD:/baserow/host \ - baserow/baserow:1.31.1 backend-cmd-with-db backup -f /baserow/host/backup.tar.gz + baserow/baserow:1.32.0 backend-cmd-with-db backup -f /baserow/host/backup.tar.gz ``` ### Restore only Baserow's Postgres Database @@ -545,13 +545,13 @@ docker stop baserow docker run -it --rm \ -v old_baserow_data_volume_containing_the_backup_tar_gz:/baserow/old_data \ -v new_baserow_data_volume_to_restore_into:/baserow/data \ - baserow/baserow:1.31.1 backend-cmd-with-db restore -f /baserow/old_data/backup.tar.gz + baserow/baserow:1.32.0 backend-cmd-with-db restore -f /baserow/old_data/backup.tar.gz # Or to restore from a file on your host instead run something like: docker run -it --rm \ -v baserow_data:/baserow/data -v \ $(pwd):/baserow/host \ - baserow/baserow:1.31.1 backend-cmd-with-db restore -f /baserow/host/backup.tar.gz + baserow/baserow:1.32.0 backend-cmd-with-db restore -f /baserow/host/backup.tar.gz ``` ## Running healthchecks on Baserow @@ -602,7 +602,7 @@ docker run \ -p 80:80 \ -p 443:443 \ --restart unless-stopped \ - baserow/baserow:1.31.1 + baserow/baserow:1.32.0 ``` Or you can just store it directly in the volume at `baserow_data/env` meaning it will be @@ -611,7 +611,7 @@ loaded whenever you mount in this data volume. ### Building your own image from Baserow ```dockerfile -FROM baserow/baserow:1.31.1 +FROM baserow/baserow:1.32.0 # Any .sh files found in /baserow/supervisor/env/ will be sourced and loaded at startup # useful for storing your own environment variable overrides. diff --git a/docs/installation/install-with-helm.md b/docs/installation/install-with-helm.md index be3075ce5..593d06e2b 100644 --- a/docs/installation/install-with-helm.md +++ b/docs/installation/install-with-helm.md @@ -37,7 +37,7 @@ file directly. ``` global: baserow: - image: 1.31.1 + image: 1.32.0 ``` Or use the latest Helm chart default. Then run the following command to upgrade your diff --git a/docs/installation/install-with-k8s.md b/docs/installation/install-with-k8s.md index 6678ac71b..0d03753b2 100644 --- a/docs/installation/install-with-k8s.md +++ b/docs/installation/install-with-k8s.md @@ -165,7 +165,7 @@ spec: topologyKey: "kubernetes.io/hostname" containers: - name: backend-asgi - image: baserow/backend:1.31.1 + image: baserow/backend:1.32.0 workingDir: /baserow args: - "gunicorn" @@ -222,7 +222,7 @@ spec: topologyKey: "kubernetes.io/hostname" containers: - name: backend-wsgi - image: baserow/backend:1.31.1 + image: baserow/backend:1.32.0 workingDir: /baserow args: - "gunicorn-wsgi" @@ -281,7 +281,7 @@ spec: topologyKey: "kubernetes.io/hostname" containers: - name: backend-worker - image: baserow/backend:1.31.1 + image: baserow/backend:1.32.0 args: - "celery-worker" imagePullPolicy: Always @@ -298,7 +298,7 @@ spec: - secretRef: name: YOUR_ENV_SECRET_REF - name: backend-export-worker - image: baserow/backend:1.31.1 + image: baserow/backend:1.32.0 args: - "celery-exportworker" imagePullPolicy: Always @@ -315,7 +315,7 @@ spec: - secretRef: name: YOUR_ENV_SECRET_REF - name: backend-beat-worker - image: baserow/backend:1.31.1 + image: baserow/backend:1.32.0 args: - "celery-beat" imagePullPolicy: Always @@ -356,7 +356,7 @@ spec: topologyKey: "kubernetes.io/hostname" containers: - name: web-frontend - image: baserow/web-frontend:1.31.1 + image: baserow/web-frontend:1.32.0 args: - nuxt ports: diff --git a/docs/installation/install-with-traefik.md b/docs/installation/install-with-traefik.md index 33dba1091..6e7164b3f 100644 --- a/docs/installation/install-with-traefik.md +++ b/docs/installation/install-with-traefik.md @@ -11,7 +11,7 @@ See below for an example docker-compose file that will enable Baserow with Traef version: "3.4" services: baserow: - image: baserow/baserow:1.31.1 + image: baserow/baserow:1.32.0 container_name: baserow labels: # Explicitly tell Traefik to expose this container diff --git a/docs/plugins/creation.md b/docs/plugins/creation.md index 794f13348..5c85b0bdc 100644 --- a/docs/plugins/creation.md +++ b/docs/plugins/creation.md @@ -122,7 +122,7 @@ containing metadata about your plugin. It should have the following JSON structu { "name": "TODO", "version": "TODO", - "supported_baserow_versions": "1.31.1", + "supported_baserow_versions": "1.32.0", "plugin_api_version": "0.0.1-alpha", "description": "TODO", "author": "TODO", diff --git a/docs/plugins/installation.md b/docs/plugins/installation.md index 435d9c516..e891443da 100644 --- a/docs/plugins/installation.md +++ b/docs/plugins/installation.md @@ -36,7 +36,7 @@ build your own image based off the Baserow all-in-one image. 4. Next copy the contents shown into your `Dockerfile` ```dockerfile -FROM baserow/baserow:1.31.1 +FROM baserow/baserow:1.32.0 # You can install a plugin found in a git repo: RUN /baserow/plugins/install_plugin.sh \ @@ -70,9 +70,9 @@ RUN /baserow/plugins/install_plugin.sh \ 5. Choose which of the `RUN` commands you'd like to use to install your plugins and delete the rest, replace the example URLs with ones pointing to your plugin. 6. Now build your custom Baserow with the plugin installed by running: - `docker build -t my-customized-baserow:1.31.1 .` + `docker build -t my-customized-baserow:1.32.0 .` 7. Finally, you can run your new customized image just like the normal Baserow image: - `docker run -p 80:80 -v baserow_data:/baserow/data my-customized-baserow:1.31.1` + `docker run -p 80:80 -v baserow_data:/baserow/data my-customized-baserow:1.32.0` ### Installing in an existing Baserow all-in-one container @@ -111,7 +111,7 @@ docker run \ -v baserow_data:/baserow/data \ # ... All your normal launch args go here -e BASEROW_PLUGIN_GIT_REPOS=https://example.com/example/plugin1.git,https://example.com/example/plugin2.git - baserow:1.31.1 + baserow:1.32.0 ``` These variables will only trigger and installation when found on startup of the @@ -120,7 +120,7 @@ container. To uninstall a plugin you must still manually follow the instructions ### Caveats when installing into an existing container If you ever delete the container you've installed plugins into at runtime and re-create -it, the new container is created from the `baserow/baserow:1.31.1` image which does not +it, the new container is created from the `baserow/baserow:1.32.0` image which does not have any plugins installed. However, when a plugin is installed at runtime or build time it is stored in the @@ -135,7 +135,7 @@ scratch. ### Installing into standalone Baserow service images -Baserow also provides `baserow/backend:1.31.1` and `baserow/web-frontend:1.31.1` images +Baserow also provides `baserow/backend:1.32.0` and `baserow/web-frontend:1.32.0` images which only run the respective backend/celery/web-frontend services. These images are used for more advanced self-hosted deployments like a multi-service docker-compose, k8s etc. @@ -145,8 +145,8 @@ used with docker run and a specified command and the plugin env vars shown above example: ``` -docker run --rm baserow/backend:1.31.1 install-plugin ... -docker run -e BASEROW_PLUGIN_GIT_REPOS=https://example.com/example/plugin1.git,https://example.com/example/plugin2.git --rm baserow/backend:1.31.1 +docker run --rm baserow/backend:1.32.0 install-plugin ... +docker run -e BASEROW_PLUGIN_GIT_REPOS=https://example.com/example/plugin1.git,https://example.com/example/plugin2.git --rm baserow/backend:1.32.0 ``` You can use these scripts exactly as you would in the sections above to install a plugin @@ -169,13 +169,13 @@ associated data permanently. [Docker install guide backup section](../installation/install-with-docker.md) for more details on how to do this. 2. Stop your Baserow server first - `docker stop baserow` -3. `docker run --rm -v baserow_data:/baserow/data baserow:1.31.1 uninstall-plugin plugin_name` +3. `docker run --rm -v baserow_data:/baserow/data baserow:1.32.0 uninstall-plugin plugin_name` 4. Now the plugin has uninstalled itself and all associated data has been removed. 5. Edit your custom `Dockerfile` and remove the plugin. -6. Rebuild your image - `docker build -t my-customized-baserow:1.31.1 .` +6. Rebuild your image - `docker build -t my-customized-baserow:1.32.0 .` 7. Remove the old container using the old image - `docker rm baserow` 8. Run your new image with the plugin removed - - `docker run -p 80:80 -v baserow_data:/baserow/data my-customized-baserow:1.31.1` + - `docker run -p 80:80 -v baserow_data:/baserow/data my-customized-baserow:1.32.0` 9. If you fail to do this if you ever recreate the container, your custom image still has the plugin installed and the new container will start up again with the plugin re-installed. @@ -207,7 +207,7 @@ associated data permanently. restart as the environment variable will still contain the old plugin. To do this you must: 1. `docker stop baserow` - 2. `docker run --rm -v baserow_data:/baserow/data baserow:1.31.1 uninstall-plugin plugin_name` + 2. `docker run --rm -v baserow_data:/baserow/data baserow:1.32.0 uninstall-plugin plugin_name` 3. Now the plugin has uninstalled itself and all associated data has been removed. 4. Finally, recreate your Baserow container by using the same `docker run` command you launched it with, just make sure the plugin you uninstalled has been removed @@ -222,7 +222,7 @@ check what plugins are currently installed. docker run \ --rm \ -v baserow_data:/baserow/data \ - baserow:1.31.1 list-plugins + baserow:1.32.0 list-plugins # or on a running container diff --git a/e2e-tests/tests/builder/builderPage.spec.ts b/e2e-tests/tests/builder/builderPage.spec.ts index 4785e6061..3eb4e53ec 100644 --- a/e2e-tests/tests/builder/builderPage.spec.ts +++ b/e2e-tests/tests/builder/builderPage.spec.ts @@ -109,7 +109,7 @@ test.describe("Builder page test suite", () => { await page.getByTitle("Close").click(); await expect(page.locator(".box__title").getByText("Page")).toBeHidden(); await page.getByText('Click to create an element').click(); - await page.getByText('Link A link to page/URL').click(); + await page.locator('.add-element-card__element-type-icon-link').click(); await page.getByLabel('my_param=').fill("foo") await page.getByRole('complementary').getByRole('textbox').click(); await page.getByRole('complementary').getByRole('textbox').locator('div').first().fill('linkim'); diff --git a/enterprise/backend/pyproject.toml b/enterprise/backend/pyproject.toml index 086576820..068888621 100644 --- a/enterprise/backend/pyproject.toml +++ b/enterprise/backend/pyproject.toml @@ -12,7 +12,7 @@ description="""Baserow is an open source no-code database tool and Airtable \ # mixed license license={file="LICENSE"} requires-python=">=3.11" -version = "1.31.1" +version = "1.32.0" classifiers = [] [project.urls] diff --git a/enterprise/backend/src/baserow_enterprise/api/integrations/local_baserow/serializers.py b/enterprise/backend/src/baserow_enterprise/api/integrations/local_baserow/serializers.py index 1fb0d376a..a1919915c 100644 --- a/enterprise/backend/src/baserow_enterprise/api/integrations/local_baserow/serializers.py +++ b/enterprise/backend/src/baserow_enterprise/api/integrations/local_baserow/serializers.py @@ -3,6 +3,7 @@ from rest_framework import serializers from baserow_enterprise.integrations.local_baserow.models import ( LocalBaserowTableServiceAggregationGroupBy, LocalBaserowTableServiceAggregationSeries, + LocalBaserowTableServiceAggregationSortBy, ) @@ -22,3 +23,11 @@ class LocalBaserowTableServiceAggregationGroupBySerializer(serializers.ModelSeri class Meta: model = LocalBaserowTableServiceAggregationGroupBy fields = ("order", "field_id") + + +class LocalBaserowTableServiceAggregationSortBySerializer(serializers.ModelSerializer): + order = serializers.IntegerField(read_only=True) + + class Meta: + model = LocalBaserowTableServiceAggregationSortBy + fields = ("order", "sort_on", "reference", "direction") diff --git a/enterprise/backend/src/baserow_enterprise/api/sso/utils.py b/enterprise/backend/src/baserow_enterprise/api/sso/utils.py index ab0d43aac..cfdb3151e 100644 --- a/enterprise/backend/src/baserow_enterprise/api/sso/utils.py +++ b/enterprise/backend/src/baserow_enterprise/api/sso/utils.py @@ -11,7 +11,7 @@ from django.shortcuts import redirect from requests.models import PreparedRequest -from baserow.core.user.utils import generate_session_tokens_for_user +from baserow.core.user.utils import generate_session_tokens_for_user, sign_user_session # please keep this in sync with baserow_enterprise/locales/en.json @@ -179,10 +179,10 @@ def get_valid_frontend_url( return requested_url_parsed.geturl() -def urlencode_user_token(frontend_url: str, user: AbstractUser) -> str: +def urlencode_user_tokens(frontend_url: str, user: AbstractUser) -> str: """ - Adds the token as a query parameter to the provided frontend url. Please - ensure to call the get_url_for_frontend_page_if_valid_or_default() method + Adds the token and user_session as a query parameters to the provided frontend url. + Please ensure to call the get_url_for_frontend_page_if_valid_or_default() method before calling this method, so to be sure to encode the refresh token in a valid Baserow frontend url. @@ -190,11 +190,19 @@ def urlencode_user_token(frontend_url: str, user: AbstractUser) -> str: redirected after a successful login. :param user: The user that sign in with an external provider and is going to start a new session in Baserow. - :return: The url with the token as a query parameter. + :return: The url with the token and user_session as query parameters. """ user_tokens = generate_session_tokens_for_user(user, include_refresh_token=True) - return urlencode_query_params(frontend_url, {"token": user_tokens["refresh_token"]}) + refresh_token = user_tokens["refresh_token"] + user_session = sign_user_session(user.id, refresh_token) + return urlencode_query_params( + frontend_url, + { + "token": refresh_token, + "user_session": user_session, + }, + ) def redirect_user_on_success( @@ -214,7 +222,7 @@ def redirect_user_on_success( """ valid_frontend_url = get_valid_frontend_url(requested_original_url) - redirect_url = urlencode_user_token(valid_frontend_url, user) + redirect_url = urlencode_user_tokens(valid_frontend_url, user) return redirect(redirect_url) diff --git a/enterprise/backend/src/baserow_enterprise/apps.py b/enterprise/backend/src/baserow_enterprise/apps.py index 31ac1b1b5..f0b6bb3b3 100755 --- a/enterprise/backend/src/baserow_enterprise/apps.py +++ b/enterprise/backend/src/baserow_enterprise/apps.py @@ -3,8 +3,6 @@ from django.db.models.signals import post_migrate from tqdm import tqdm -from baserow.core.feature_flags import FF_DASHBOARDS, feature_flag_is_enabled - class BaserowEnterpriseConfig(AppConfig): name = "baserow_enterprise" @@ -156,6 +154,33 @@ class BaserowEnterpriseConfig(AppConfig): grouped_aggregation_registry.register(VarianceFieldAggregationType()) grouped_aggregation_registry.register(MedianFieldAggregationType()) + from baserow.contrib.database.fields.field_types import ( + AutonumberFieldType, + BooleanFieldType, + EmailFieldType, + LongTextFieldType, + NumberFieldType, + PhoneNumberFieldType, + RatingFieldType, + SingleSelectFieldType, + TextFieldType, + URLFieldType, + ) + from baserow_enterprise.integrations.registries import ( + grouped_aggregation_group_by_registry, + ) + + grouped_aggregation_group_by_registry.register(TextFieldType()) + grouped_aggregation_group_by_registry.register(LongTextFieldType()) + grouped_aggregation_group_by_registry.register(URLFieldType()) + grouped_aggregation_group_by_registry.register(EmailFieldType()) + grouped_aggregation_group_by_registry.register(NumberFieldType()) + grouped_aggregation_group_by_registry.register(RatingFieldType()) + grouped_aggregation_group_by_registry.register(BooleanFieldType()) + grouped_aggregation_group_by_registry.register(PhoneNumberFieldType()) + grouped_aggregation_group_by_registry.register(AutonumberFieldType()) + grouped_aggregation_group_by_registry.register(SingleSelectFieldType()) + from baserow.core.registries import subject_type_registry subject_type_registry.register(TeamSubjectType()) @@ -236,11 +261,10 @@ class BaserowEnterpriseConfig(AppConfig): LocalBaserowGroupedAggregateRowsUserServiceType, ) - if feature_flag_is_enabled(FF_DASHBOARDS): - service_type_registry.register( - LocalBaserowGroupedAggregateRowsUserServiceType() - ) - widget_type_registry.register(ChartWidgetType()) + service_type_registry.register( + LocalBaserowGroupedAggregateRowsUserServiceType() + ) + widget_type_registry.register(ChartWidgetType()) from baserow.contrib.builder.elements.registries import element_type_registry from baserow_enterprise.builder.elements.element_types import ( @@ -272,6 +296,13 @@ class BaserowEnterpriseConfig(AppConfig): action_type_registry.register(UpdatePeriodicDataSyncIntervalActionType()) + from baserow.contrib.database.webhooks.registries import ( + webhook_event_type_registry, + ) + from baserow_enterprise.webhook_event_types import RowsEnterViewEventType + + webhook_event_type_registry.register(RowsEnterViewEventType()) + # Create default roles post_migrate.connect(sync_default_roles_after_migrate, sender=self) @@ -287,6 +318,15 @@ class BaserowEnterpriseConfig(AppConfig): connect_to_post_delete_signals_to_cascade_deletion_to_role_assignments() + from baserow.core.notifications.registries import notification_type_registry + from baserow_enterprise.data_sync.notification_types import ( + PeriodicDataSyncDeactivatedNotificationType, + ) + + notification_type_registry.register( + PeriodicDataSyncDeactivatedNotificationType() + ) + # The signals must always be imported last because they use the registries # which need to be filled first. import baserow_enterprise.audit_log.signals # noqa: F diff --git a/enterprise/backend/src/baserow_enterprise/data_sync/handler.py b/enterprise/backend/src/baserow_enterprise/data_sync/handler.py index 841066bd4..d9f249e6e 100644 --- a/enterprise/backend/src/baserow_enterprise/data_sync/handler.py +++ b/enterprise/backend/src/baserow_enterprise/data_sync/handler.py @@ -24,6 +24,7 @@ from baserow_enterprise.data_sync.models import ( ) from baserow_enterprise.features import DATA_SYNC +from .notification_types import PeriodicDataSyncDeactivatedNotificationType from .tasks import sync_periodic_data_sync @@ -216,6 +217,15 @@ class EnterpriseDataSyncHandler: >= settings.BASEROW_ENTERPRISE_MAX_PERIODIC_DATA_SYNC_CONSECUTIVE_ERRORS ): periodic_data_sync.automatically_deactivated = True + + # Send a notification to the authorized user that the periodic data + # sync was deactivated. + transaction.on_commit( + lambda: PeriodicDataSyncDeactivatedNotificationType.notify_authorized_user( + periodic_data_sync + ) + ) + periodic_data_sync.save() elif periodic_data_sync.consecutive_failed_count > 0: # Once it runs successfully, the consecutive count can be reset because we diff --git a/enterprise/backend/src/baserow_enterprise/data_sync/notification_types.py b/enterprise/backend/src/baserow_enterprise/data_sync/notification_types.py new file mode 100644 index 000000000..2c1bd21a2 --- /dev/null +++ b/enterprise/backend/src/baserow_enterprise/data_sync/notification_types.py @@ -0,0 +1,77 @@ +from dataclasses import asdict, dataclass +from typing import List, Optional + +from django.conf import settings +from django.utils.translation import gettext as _ + +from baserow.core.notifications.handler import NotificationHandler +from baserow.core.notifications.models import NotificationRecipient +from baserow.core.notifications.registries import ( + EmailNotificationTypeMixin, + NotificationType, +) + +from .models import PeriodicDataSyncInterval + + +@dataclass +class DeactivatedPeriodicDataSyncData: + data_sync_id: int + table_name: str + table_id: int + database_id: int + + @classmethod + def from_periodic_data_sync(cls, periodic_data_sync: PeriodicDataSyncInterval): + return cls( + data_sync_id=periodic_data_sync.data_sync_id, + table_name=periodic_data_sync.data_sync.table.name, + table_id=periodic_data_sync.data_sync.table.id, + database_id=periodic_data_sync.data_sync.table.database_id, + ) + + +class PeriodicDataSyncDeactivatedNotificationType( + EmailNotificationTypeMixin, NotificationType +): + type = "periodic_data_sync_deactivated" + has_web_frontend_route = True + + @classmethod + def notify_authorized_user( + cls, periodic_data_sync: PeriodicDataSyncInterval + ) -> Optional[List[NotificationRecipient]]: + """ + Creates a notification for the authorized user of the periodic data sync + that was deactivated. + + :param periodic_data_sync: The periodic data sync that was deactivated. + """ + + workspace = periodic_data_sync.data_sync.table.database.workspace + return NotificationHandler.create_direct_notification_for_users( + notification_type=PeriodicDataSyncDeactivatedNotificationType.type, + recipients=[periodic_data_sync.authorized_user], + data=asdict( + DeactivatedPeriodicDataSyncData.from_periodic_data_sync( + periodic_data_sync + ) + ), + sender=None, + workspace=workspace, + ) + + @classmethod + def get_notification_title_for_email(cls, notification, context): + return _("%(name)s periodic data sync has been deactivated.") % { + "name": notification.data["table_name"], + } + + @classmethod + def get_notification_description_for_email(cls, notification, context): + return _( + "The periodic data sync failed more than %(max_failures)s consecutive times" + "and was therefore deactivated." + ) % { + "max_failures": settings.BASEROW_ENTERPRISE_MAX_PERIODIC_DATA_SYNC_CONSECUTIVE_ERRORS, + } diff --git a/enterprise/backend/src/baserow_enterprise/emails_context_types.py b/enterprise/backend/src/baserow_enterprise/emails_context_types.py index e5ccb2981..73185ba1e 100644 --- a/enterprise/backend/src/baserow_enterprise/emails_context_types.py +++ b/enterprise/backend/src/baserow_enterprise/emails_context_types.py @@ -27,5 +27,6 @@ class EnterpriseEmailContextType(EmailContextType): ): email_context["logo_url"] = UserFileSerializer(custom_logo).data["url"] email_context["logo_additional_text"] = "by Baserow" + email_context["show_baserow_description"] = False return email_context diff --git a/enterprise/backend/src/baserow_enterprise/features.py b/enterprise/backend/src/baserow_enterprise/features.py index f650a0afb..cd9ec03cb 100644 --- a/enterprise/backend/src/baserow_enterprise/features.py +++ b/enterprise/backend/src/baserow_enterprise/features.py @@ -8,3 +8,6 @@ SECURE_FILE_SERVE = "secure_file_serve" ENTERPRISE_SETTINGS = "ENTERPRISE_SETTINGS" DATA_SYNC = "data_sync" CHART_WIDGET = "chart_widget" +ADVANCED_WEBHOOKS = "advanced_webhooks" + +BUILDER_SSO = "application_user_sso" diff --git a/enterprise/backend/src/baserow_enterprise/integrations/local_baserow/models.py b/enterprise/backend/src/baserow_enterprise/integrations/local_baserow/models.py index 00f9c1c83..a10e2b621 100644 --- a/enterprise/backend/src/baserow_enterprise/integrations/local_baserow/models.py +++ b/enterprise/backend/src/baserow_enterprise/integrations/local_baserow/models.py @@ -118,3 +118,35 @@ class LocalBaserowTableServiceAggregationGroupBy(models.Model): class Meta: ordering = ("order", "id") + + +class SortOn(models.TextChoices): + SERIES = "SERIES", "Series" + GROUP_BY = "GROUP_BY", "Group by" + PRIMARY = "PRIMARY", "Primary" + + +class SortDirection(models.TextChoices): + ASCENDING = "ASC", "Ascending" + DESCENDING = "DESC", "Descending" + + +class LocalBaserowTableServiceAggregationSortBy(models.Model): + """ + A sort by for aggregations applicable to a `LocalBaserowTableService` + integration service. + """ + + service = models.ForeignKey( + Service, + related_name="service_aggregation_sorts", + help_text="The service which this aggregation series belongs to.", + on_delete=models.CASCADE, + ) + sort_on = models.CharField(max_length=255, choices=SortOn.choices) + reference = models.CharField(max_length=255) + direction = models.CharField(max_length=255, choices=SortDirection.choices) + order = models.PositiveIntegerField() + + class Meta: + ordering = ("order", "id") diff --git a/enterprise/backend/src/baserow_enterprise/integrations/local_baserow/service_types.py b/enterprise/backend/src/baserow_enterprise/integrations/local_baserow/service_types.py index 061755b99..e8ce68672 100644 --- a/enterprise/backend/src/baserow_enterprise/integrations/local_baserow/service_types.py +++ b/enterprise/backend/src/baserow_enterprise/integrations/local_baserow/service_types.py @@ -1,56 +1,58 @@ -from typing import TYPE_CHECKING, Type +import re from django.conf import settings -from django.db.models import OrderBy, QuerySet +from django.db.models import F from rest_framework.exceptions import ValidationError as DRFValidationError +from baserow.contrib.database.api.fields.serializers import FieldSerializer +from baserow.contrib.database.fields.exceptions import FieldTypeDoesNotExist +from baserow.contrib.database.fields.registries import field_type_registry from baserow.contrib.database.views.exceptions import AggregationTypeDoesNotExist +from baserow.contrib.database.views.models import DEFAULT_SORT_TYPE_KEY from baserow.contrib.database.views.utils import AnnotatedAggregation from baserow.contrib.integrations.local_baserow.integration_types import ( LocalBaserowIntegrationType, ) from baserow.contrib.integrations.local_baserow.mixins import ( LocalBaserowTableServiceFilterableMixin, - LocalBaserowTableServiceSortableMixin, -) -from baserow.contrib.integrations.local_baserow.models import ( - LocalBaserowTableServiceSort, - Service, ) +from baserow.contrib.integrations.local_baserow.models import Service from baserow.contrib.integrations.local_baserow.service_types import ( LocalBaserowViewServiceType, ) from baserow.core.services.dispatch_context import DispatchContext from baserow.core.services.exceptions import ServiceImproperlyConfigured from baserow.core.services.registries import DispatchTypes -from baserow.core.services.types import DispatchResult, ServiceSortDictSubClass +from baserow.core.services.types import DispatchResult from baserow.core.utils import atomic_if_not_already from baserow_enterprise.api.integrations.local_baserow.serializers import ( LocalBaserowTableServiceAggregationGroupBySerializer, LocalBaserowTableServiceAggregationSeriesSerializer, + LocalBaserowTableServiceAggregationSortBySerializer, ) from baserow_enterprise.integrations.local_baserow.models import ( LocalBaserowGroupedAggregateRows, ) -from baserow_enterprise.integrations.registries import grouped_aggregation_registry +from baserow_enterprise.integrations.registries import ( + grouped_aggregation_group_by_registry, + grouped_aggregation_registry, +) from baserow_enterprise.services.types import ( ServiceAggregationGroupByDict, ServiceAggregationSeriesDict, + ServiceAggregationSortByDict, ) from .models import ( LocalBaserowTableServiceAggregationGroupBy, LocalBaserowTableServiceAggregationSeries, + LocalBaserowTableServiceAggregationSortBy, ) -if TYPE_CHECKING: - from baserow.contrib.database.table.models import GeneratedTableModel - class LocalBaserowGroupedAggregateRowsUserServiceType( LocalBaserowTableServiceFilterableMixin, - LocalBaserowTableServiceSortableMixin, LocalBaserowViewServiceType, ): """ @@ -62,10 +64,7 @@ class LocalBaserowGroupedAggregateRowsUserServiceType( type = "local_baserow_grouped_aggregate_rows" model_class = LocalBaserowGroupedAggregateRows dispatch_type = DispatchTypes.DISPATCH_DATA_SOURCE - serializer_mixins = ( - LocalBaserowTableServiceFilterableMixin.mixin_serializer_mixins - + LocalBaserowTableServiceSortableMixin.mixin_serializer_mixins - ) + serializer_mixins = LocalBaserowTableServiceFilterableMixin.mixin_serializer_mixins def get_schema_name(self, service: LocalBaserowGroupedAggregateRows) -> str: return f"GroupedAggregation{service.id}Schema" @@ -80,7 +79,9 @@ class LocalBaserowGroupedAggregateRowsUserServiceType( super() .enhance_queryset(queryset) .prefetch_related( - "service_aggregation_series", "service_aggregation_group_bys" + "service_aggregation_series", + "service_aggregation_group_bys", + "service_aggregation_sorts", ) ) @@ -96,21 +97,22 @@ class LocalBaserowGroupedAggregateRowsUserServiceType( return ( super().serializer_field_names + LocalBaserowTableServiceFilterableMixin.mixin_serializer_field_names - + LocalBaserowTableServiceSortableMixin.mixin_serializer_field_names - ) + ["aggregation_series", "aggregation_group_bys"] + ) + ["aggregation_series", "aggregation_group_bys", "aggregation_sorts"] @property def serializer_field_overrides(self): return { **super().serializer_field_overrides, **LocalBaserowTableServiceFilterableMixin.mixin_serializer_field_overrides, - **LocalBaserowTableServiceSortableMixin.mixin_serializer_field_overrides, "aggregation_series": LocalBaserowTableServiceAggregationSeriesSerializer( many=True, source="service_aggregation_series", required=False ), "aggregation_group_bys": LocalBaserowTableServiceAggregationGroupBySerializer( many=True, source="service_aggregation_group_bys", required=False ), + "aggregation_sorts": LocalBaserowTableServiceAggregationSortBySerializer( + many=True, source="service_aggregation_sorts", required=False + ), } class SerializedDict( @@ -119,6 +121,7 @@ class LocalBaserowGroupedAggregateRowsUserServiceType( ): service_aggregation_series: list[ServiceAggregationSeriesDict] service_aggregation_group_bys: list[ServiceAggregationGroupByDict] + service_aggregation_sorts: list[ServiceAggregationSortByDict] def _update_service_aggregation_series( self, @@ -128,6 +131,7 @@ class LocalBaserowGroupedAggregateRowsUserServiceType( with atomic_if_not_already(): table_fields = service.table.field_set.all() table_field_ids = [field.id for field in table_fields] + series_agg_used = set() def validate_agg_series(agg_series): if agg_series["aggregation_type"]: @@ -164,6 +168,20 @@ class LocalBaserowGroupedAggregateRowsUserServiceType( code="invalid_aggregation_raw_type", ) + series_aggregation_reference = ( + f"field_{agg_series['field_id']}_{agg_series['aggregation_type']}" + ) + if series_aggregation_reference in series_agg_used: + raise DRFValidationError( + detail=f"The series with the field ID {agg_series['field_id']} and " + f"aggregation type {agg_series['aggregation_type']} can only be defined once.", + code="invalid_aggregation_raw_type", + ) + else: + # It is still possible to have multiple undefined series + if agg_series["field_id"] and agg_series["aggregation_type"]: + series_agg_used.add(series_aggregation_reference) + return True service.service_aggregation_series.all().delete() @@ -192,7 +210,8 @@ class LocalBaserowGroupedAggregateRowsUserServiceType( group_bys: list[ServiceAggregationGroupByDict] | None = None, ): with atomic_if_not_already(): - table_field_ids = service.table.field_set.values_list("id", flat=True) + table_fields = service.table.field_set.all() + table_field_ids = [field.id for field in table_fields] def validate_agg_group_by(group_by): if ( @@ -205,6 +224,26 @@ class LocalBaserowGroupedAggregateRowsUserServiceType( code="invalid_field", ) + if group_by["field_id"] is None: + return True + + field = next( + ( + field + for field in table_fields + if field.id == group_by["field_id"] + ) + ) + + try: + grouped_aggregation_group_by_registry.get_by_type(field.get_type()) + except FieldTypeDoesNotExist: + raise DRFValidationError( + detail=f"The field with ID {group_by['field_id']} cannot " + "be used as a group by field.", + code="invalid_field", + ) + return True service.service_aggregation_group_bys.all().delete() @@ -224,48 +263,43 @@ class LocalBaserowGroupedAggregateRowsUserServiceType( ] ) - def _update_service_sortings( + def _update_service_sorts( self, service: LocalBaserowGroupedAggregateRows, - service_sorts: list[ServiceSortDictSubClass] | None = None, + service_sorts: list[ServiceAggregationSortByDict] | None = None, ): with atomic_if_not_already(): - service.service_sorts.all().delete() + service.service_aggregation_sorts.all().delete() if service_sorts is not None: - table_field_ids = service.table.field_set.values_list("id", flat=True) model = service.table.get_model() - allowed_sort_field_ids = [ - series.field_id + allowed_sort_references = [ + f"field_{series.field_id}_{series.aggregation_type}" for series in service.service_aggregation_series.all() + if series.aggregation_type is not None + and series.field_id is not None ] if service.service_aggregation_group_bys.count() > 0: group_by = service.service_aggregation_group_bys.all()[0] - allowed_sort_field_ids += ( - [group_by.field_id] + allowed_sort_references += ( + [f"field_{group_by.field_id}"] if group_by.field_id is not None - else [model.get_primary_field().id] + else [f"field_{model.get_primary_field().id}"] ) def validate_sort(service_sort): - if service_sort["field"].id not in table_field_ids: + if service_sort["reference"] not in allowed_sort_references: raise DRFValidationError( - detail=f"The field with ID {service_sort['field'].id} is not " - "related to the given table.", - code="invalid_field", - ) - if service_sort["field"].id not in allowed_sort_field_ids: - raise DRFValidationError( - detail=f"The field with ID {service_sort['field'].id} cannot be used for sorting.", - code="invalid_field", + detail=f"The reference sort '{service_sort['reference']}' cannot be used for sorting.", + code="invalid", ) return True - LocalBaserowTableServiceSort.objects.bulk_create( + LocalBaserowTableServiceAggregationSortBy.objects.bulk_create( [ - LocalBaserowTableServiceSort( + LocalBaserowTableServiceAggregationSortBy( **service_sort, service=service, order=index ) for index, service_sort in enumerate(service_sorts) @@ -290,8 +324,10 @@ class LocalBaserowGroupedAggregateRowsUserServiceType( self._update_service_aggregation_group_bys( instance, values.pop("service_aggregation_group_bys") ) - if "service_sorts" in values: - self._update_service_sortings(instance, values.pop("service_sorts")) + if "service_aggregation_sorts" in values: + self._update_service_sorts( + instance, values.pop("service_aggregation_sorts") + ) def after_update( self, @@ -328,10 +364,12 @@ class LocalBaserowGroupedAggregateRowsUserServiceType( elif from_table and to_table: instance.service_aggregation_group_bys.all().delete() - if "service_sorts" in values: - self._update_service_sortings(instance, values.pop("service_sorts")) + if "service_aggregation_sorts" in values: + self._update_service_sorts( + instance, values.pop("service_aggregation_sorts") + ) elif from_table and to_table: - instance.service_sorts.all().delete() + instance.service_aggregation_sorts.all().delete() def export_prepared_values(self, instance: Service) -> dict[str, any]: values = super().export_prepared_values(instance) @@ -351,30 +389,52 @@ class LocalBaserowGroupedAggregateRowsUserServiceType( if prop_name == "filters": return self.serialize_filters(service) - # FIXME: aggregation_series, aggregation_group_bys + if prop_name == "service_aggregation_series": + return [ + { + "field_id": series.field_id, + "aggregation_type": series.aggregation_type, + } + for series in service.service_aggregation_series.all() + ] + + if prop_name == "service_aggregation_group_bys": + return [ + { + "field_id": group_by.field_id, + } + for group_by in service.service_aggregation_group_bys.all() + ] + + if prop_name == "service_aggregation_sorts": + return [ + { + "sort_on": sort.sort_on, + "reference": sort.reference, + "direction": sort.direction, + } + for sort in service.service_aggregation_sorts.all() + ] return super().serialize_property( service, prop_name, files_zip=files_zip, storage=storage, cache=cache ) - def deserialize_property( + def create_instance_from_serialized( self, - prop_name: str, - value: any, - id_mapping: dict[str, any], + serialized_values, + id_mapping, files_zip=None, storage=None, cache=None, **kwargs, - ): - if prop_name == "filters": - return self.deserialize_filters(value, id_mapping) + ) -> "LocalBaserowGroupedAggregateRowsUserServiceType": + series = serialized_values.pop("service_aggregation_series", []) + group_bys = serialized_values.pop("service_aggregation_group_bys", []) + sorts = serialized_values.pop("service_aggregation_sorts", []) - # FIXME: aggregation_series, aggregation_group_bys - - return super().deserialize_property( - prop_name, - value, + service = super().create_instance_from_serialized( + serialized_values, id_mapping, files_zip=files_zip, storage=storage, @@ -382,15 +442,63 @@ class LocalBaserowGroupedAggregateRowsUserServiceType( **kwargs, ) - def get_dispatch_sorts( + if "database_fields" in id_mapping: + for current_series in series: + if current_series["field_id"] is not None: + current_series["field_id"] = id_mapping["database_fields"].get( + current_series["field_id"], None + ) + for group_by in group_bys: + if group_by["field_id"] is not None: + group_by["field_id"] = id_mapping["database_fields"].get( + group_by["field_id"], None + ) + for sort in sorts: + match = re.search(r"\d+", sort["reference"]) + sort_field_id = match.group() + remapped_id = id_mapping["database_fields"].get( + int(sort_field_id), None + ) + if remapped_id is not None: + sort["reference"] = sort["reference"].replace( + sort_field_id, str(remapped_id) + ) + else: + sort["reference"] = None + + self._update_service_aggregation_series(service, series) + self._update_service_aggregation_group_bys(service, group_bys) + self._update_service_sorts( + service, [sort for sort in sorts if sort["reference"] is not None] + ) + + return service + + def get_context_data( self, service: LocalBaserowGroupedAggregateRows, - queryset: QuerySet, - model: Type["GeneratedTableModel"], - ) -> tuple[list[OrderBy], QuerySet]: - service_sorts = service.service_sorts.all() - sort_ordering = [service_sort.get_order_by() for service_sort in service_sorts] - return sort_ordering, queryset + allowed_fields: list[str] | None = None, + ) -> dict: + context_data = {} + + if service.table: + model = service.table.get_model() + + def get_group_by_field(field): + return model.get_primary_field() if field is None else field + + def serialize_field(field): + return field_type_registry.get_serializer(field, FieldSerializer).data + + fields = [ + get_group_by_field(group_by.field) + for group_by in service.service_aggregation_group_bys.all() + ] + context_data["fields"] = { + field.db_column: serialize_field(field) for field in fields + } + + return context_data def dispatch_data( self, @@ -412,24 +520,6 @@ class LocalBaserowGroupedAggregateRowsUserServiceType( model = self.get_table_model(service) queryset = self.build_queryset(service, table, dispatch_context, model=model) - allowed_sort_field_ids = [ - series.field_id for series in service.service_aggregation_series.all() - ] - - if service.service_aggregation_group_bys.count() > 0: - group_by = service.service_aggregation_group_bys.all()[0] - allowed_sort_field_ids += ( - [group_by.field_id] - if group_by.field_id is not None - else [model.get_primary_field().id] - ) - - for sort_by in service.service_sorts.all(): - if sort_by.field_id not in allowed_sort_field_ids: - raise ServiceImproperlyConfigured( - f"The field with ID {sort_by.field.id} cannot be used for sorting." - ) - group_by_values = [] for group_by in service.service_aggregation_group_bys.all(): if group_by.field is None: @@ -440,6 +530,14 @@ class LocalBaserowGroupedAggregateRowsUserServiceType( raise ServiceImproperlyConfigured( f"The field with ID {group_by.field.id} is trashed." ) + try: + grouped_aggregation_group_by_registry.get_by_type( + group_by.field.get_type() + ) + except FieldTypeDoesNotExist: + raise ServiceImproperlyConfigured( + f"The field with ID {group_by.field.id} cannot be used for group by." + ) group_by_values.append(group_by.field.db_column) if len(group_by_values) > 0: @@ -451,6 +549,8 @@ class LocalBaserowGroupedAggregateRowsUserServiceType( raise ServiceImproperlyConfigured( f"There are no aggregation series defined." ) + + series_agg_used = set() for agg_series in defined_agg_series: if agg_series.field is None: raise ServiceImproperlyConfigured( @@ -473,6 +573,18 @@ class LocalBaserowGroupedAggregateRowsUserServiceType( f"with the aggregation type {agg_series.aggregation_type}." ) + series_aggregation_reference = ( + f"field_{agg_series.field.id}_{agg_series.aggregation_type}" + ) + if series_aggregation_reference in series_agg_used: + raise ServiceImproperlyConfigured( + f"The series with field ID {agg_series.field.id} and " + f"aggregation type {agg_series.aggregation_type} can only be defined once." + ) + else: + if agg_series.field and agg_series.aggregation_type: + series_agg_used.add(series_aggregation_reference) + combined_agg_dict |= agg_type._get_aggregation_dict( queryset, model_field, agg_series.field, include_agg_type=True ) @@ -482,6 +594,57 @@ class LocalBaserowGroupedAggregateRowsUserServiceType( queryset = queryset.annotate(**value.annotations) combined_agg_dict[key] = value.aggregation + allowed_sort_references = [ + f"field_{series.field_id}_{series.aggregation_type}" + for series in service.service_aggregation_series.all() + if series.aggregation_type is not None and series.field_id is not None + ] + + if service.service_aggregation_group_bys.count() > 0: + group_by = service.service_aggregation_group_bys.all()[0] + allowed_sort_references += ( + [f"field_{group_by.field_id}"] + if group_by.field_id is not None + else [f"field_{model.get_primary_field().id}"] + ) + + sorts = [] + sort_annotations = {} + for sort_by in service.service_aggregation_sorts.all(): + if sort_by.reference not in allowed_sort_references: + raise ServiceImproperlyConfigured( + f"The sort reference '{sort_by.reference}' cannot be used for sorting." + ) + + if sort_by.sort_on == "SERIES": + expression = F(f"{sort_by.reference}_raw") + if sort_by.direction == "ASC": + expression = expression.asc(nulls_first=True) + else: + expression = expression.desc(nulls_last=True) + sorts.append(expression) + else: + field_obj = model.get_field_object(sort_by.reference) + field_type = field_obj["type"] + field_annotated_order_by = field_type.get_order( + field=field_obj["field"], + field_name=sort_by.reference, + order_direction=sort_by.direction, + # The application builder does not yet have compatibility with + # different sort types, so it uses the default one instead. + sort_type=DEFAULT_SORT_TYPE_KEY, + ) + if field_annotated_order_by.annotation is not None: + sort_annotations = { + **sort_annotations, + **field_annotated_order_by.annotation, + } + field_order_bys = field_annotated_order_by.order_bys + for field_order_by in field_order_bys: + sorts.append(field_order_by) + + queryset = queryset.annotate(**sort_annotations) + def process_individual_result(result: dict): for agg_series in defined_agg_series: key = f"{agg_series.field.db_column}_{agg_series.aggregation_type}" @@ -495,9 +658,12 @@ class LocalBaserowGroupedAggregateRowsUserServiceType( return result if len(group_by_values) > 0: - queryset = queryset.annotate(**combined_agg_dict)[ + queryset = queryset.annotate(**combined_agg_dict) + queryset = queryset.order_by(*sorts) + queryset = queryset[ : settings.BASEROW_ENTERPRISE_GROUPED_AGGREGATE_SERVICE_MAX_AGG_BUCKETS ] + results = [process_individual_result(result) for result in queryset] else: results = queryset.aggregate(**combined_agg_dict) diff --git a/enterprise/backend/src/baserow_enterprise/integrations/registries.py b/enterprise/backend/src/baserow_enterprise/integrations/registries.py index f0c197275..d392ff547 100644 --- a/enterprise/backend/src/baserow_enterprise/integrations/registries.py +++ b/enterprise/backend/src/baserow_enterprise/integrations/registries.py @@ -1,4 +1,8 @@ -from baserow.contrib.database.fields.registries import FieldAggregationType +from baserow.contrib.database.fields.exceptions import ( + FieldTypeAlreadyRegistered, + FieldTypeDoesNotExist, +) +from baserow.contrib.database.fields.registries import FieldAggregationType, FieldType from baserow.contrib.database.views.exceptions import ( AggregationTypeAlreadyRegistered, AggregationTypeDoesNotExist, @@ -20,3 +24,20 @@ class GroupedAggregationTypeRegistry(Registry[FieldAggregationType]): grouped_aggregation_registry: GroupedAggregationTypeRegistry = ( GroupedAggregationTypeRegistry() ) + + +class GroupedAggregationGroupByRegistry(Registry[FieldType]): + """ + The main registry for storing field types compatible + with the grouped aggregate service to be used as group by + fields. + """ + + name = "grouped_aggregations_group_by" + does_not_exist_exception_class = FieldTypeDoesNotExist + already_registered_exception_class = FieldTypeAlreadyRegistered + + +grouped_aggregation_group_by_registry: GroupedAggregationGroupByRegistry = ( + GroupedAggregationGroupByRegistry() +) diff --git a/enterprise/backend/src/baserow_enterprise/license_types.py b/enterprise/backend/src/baserow_enterprise/license_types.py index 1ed41d93e..89e8ba65a 100755 --- a/enterprise/backend/src/baserow_enterprise/license_types.py +++ b/enterprise/backend/src/baserow_enterprise/license_types.py @@ -6,7 +6,9 @@ from baserow_premium.license.registries import LicenseType, SeatUsageSummary from baserow.core.models import Workspace from baserow_enterprise.features import ( + ADVANCED_WEBHOOKS, AUDIT_LOG, + BUILDER_SSO, CHART_WIDGET, DATA_SYNC, ENTERPRISE_SETTINGS, @@ -34,6 +36,8 @@ class EnterpriseWithoutSupportLicenseType(LicenseType): ENTERPRISE_SETTINGS, DATA_SYNC, CHART_WIDGET, + BUILDER_SSO, + ADVANCED_WEBHOOKS, ] instance_wide = True seats_manually_assigned = False @@ -54,6 +58,13 @@ class EnterpriseWithoutSupportLicenseType(LicenseType): # We don't have to do anything because the seat limit is a soft limit. pass + def handle_application_user_overflow( + self, application_users_taken: int, license_object: License + ): + # We don't have to do anything because the application user limit + # is a soft limit? + pass + class EnterpriseLicenseType(EnterpriseWithoutSupportLicenseType): type = "enterprise" diff --git a/enterprise/backend/src/baserow_enterprise/locale/en/LC_MESSAGES/django.po b/enterprise/backend/src/baserow_enterprise/locale/en/LC_MESSAGES/django.po index 689290852..b2c7c2bc8 100644 --- a/enterprise/backend/src/baserow_enterprise/locale/en/LC_MESSAGES/django.po +++ b/enterprise/backend/src/baserow_enterprise/locale/en/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2024-12-17 08:48+0000\n" +"POT-Creation-Date: 2025-03-05 11:01+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Language-Team: LANGUAGE <LL@li.org>\n" @@ -62,6 +62,27 @@ msgstr "" msgid "REDONE" msgstr "" +#: src/baserow_enterprise/data_sync/actions.py:21 +msgid "Update periodic data sync interval" +msgstr "" + +#: src/baserow_enterprise/data_sync/actions.py:22 +#, python-format +msgid "Data sync table \"%(table_name)s\" (%(table_id)s) updated" +msgstr "" + +#: src/baserow_enterprise/data_sync/notification_types.py:66 +#, python-format +msgid "%(name)s periodic data sync has been deactivated." +msgstr "" + +#: src/baserow_enterprise/data_sync/notification_types.py:73 +#, python-format +msgid "" +"The periodic data sync failed more than %(max_failures)s consecutive " +"timesand was therefore deactivated." +msgstr "" + #: src/baserow_enterprise/role/actions.py:28 msgid "Assign multiple roles" msgstr "" diff --git a/enterprise/backend/src/baserow_enterprise/locale/fr/LC_MESSAGES/django.po b/enterprise/backend/src/baserow_enterprise/locale/fr/LC_MESSAGES/django.po index f8a261c99..13b39cee7 100644 --- a/enterprise/backend/src/baserow_enterprise/locale/fr/LC_MESSAGES/django.po +++ b/enterprise/backend/src/baserow_enterprise/locale/fr/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2023-01-26 15:50+0000\n" -"PO-Revision-Date: 2023-03-07 19:25+0000\n" +"PO-Revision-Date: 2025-03-18 13:24+0000\n" "Last-Translator: Jérémie Pardou-Piquemal <jrmi@jeremiez.net>\n" "Language-Team: French <https://hosted.weblate.org/projects/baserow/" "enterprise-backend/fr/>\n" @@ -17,7 +17,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n > 1;\n" -"X-Generator: Weblate 4.16.2-dev\n" +"X-Generator: Weblate 5.11-dev\n" #: audit_log/job_types.py:143 msgid "User Email" @@ -49,7 +49,7 @@ msgstr "Heure" #: audit_log/job_types.py:150 msgid "IP Address" -msgstr "Addresse IP" +msgstr "Adresse IP" #: audit_log/models.py:30 msgid "DONE" @@ -65,7 +65,7 @@ msgstr "Fait" #: role/actions.py:28 msgid "Assign multiple roles" -msgstr "Assignation de roles" +msgstr "Assigner plusieurs roles" #: role/actions.py:29 msgid "Multiple roles have been assigned" diff --git a/enterprise/backend/src/baserow_enterprise/migrations/0042_localbaserowtableserviceaggregationsortby.py b/enterprise/backend/src/baserow_enterprise/migrations/0042_localbaserowtableserviceaggregationsortby.py new file mode 100644 index 000000000..c050e9d62 --- /dev/null +++ b/enterprise/backend/src/baserow_enterprise/migrations/0042_localbaserowtableserviceaggregationsortby.py @@ -0,0 +1,63 @@ +# Generated by Django 5.0.9 on 2025-03-03 02:31 + +import django.db.models.deletion +from django.db import migrations, models + + +class Migration(migrations.Migration): + dependencies = [ + ( + "baserow_enterprise", + "0041_alter_localbaserowtableserviceaggregationseries_field", + ), + ("core", "0094_alter_importexportresource_size"), + ] + + operations = [ + migrations.CreateModel( + name="LocalBaserowTableServiceAggregationSortBy", + fields=[ + ( + "id", + models.AutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ( + "sort_on", + models.CharField( + choices=[ + ("SERIES", "Series"), + ("GROUP_BY", "Group by"), + ("PRIMARY", "Primary"), + ], + max_length=255, + ), + ), + ("reference", models.CharField(max_length=255)), + ( + "direction", + models.CharField( + choices=[("ASC", "Ascending"), ("DESC", "Descending")], + max_length=255, + ), + ), + ("order", models.PositiveIntegerField()), + ( + "service", + models.ForeignKey( + help_text="The service which this aggregation series belongs to.", + on_delete=django.db.models.deletion.CASCADE, + related_name="service_aggregation_sorts", + to="core.service", + ), + ), + ], + options={ + "ordering": ("order", "id"), + }, + ), + ] diff --git a/enterprise/backend/src/baserow_enterprise/services/types.py b/enterprise/backend/src/baserow_enterprise/services/types.py index 082d70fd0..3b82c3599 100644 --- a/enterprise/backend/src/baserow_enterprise/services/types.py +++ b/enterprise/backend/src/baserow_enterprise/services/types.py @@ -2,9 +2,15 @@ from typing import TypedDict class ServiceAggregationSeriesDict(TypedDict): - field_id: int + field_id: int | None aggregation_type: str class ServiceAggregationGroupByDict(TypedDict): - field_id: int + field_id: int | None + + +class ServiceAggregationSortByDict(TypedDict): + sort_on: str + reference: str + direction: str diff --git a/enterprise/backend/src/baserow_enterprise/webhook_event_types.py b/enterprise/backend/src/baserow_enterprise/webhook_event_types.py new file mode 100644 index 000000000..49f8a8b7f --- /dev/null +++ b/enterprise/backend/src/baserow_enterprise/webhook_event_types.py @@ -0,0 +1,117 @@ +from django.conf import settings +from django.db.models import Q + +from baserow_premium.license.handler import LicenseHandler + +from baserow.contrib.database.api.rows.serializers import ( + RowSerializer, + get_row_serializer_class, +) +from baserow.contrib.database.api.views.serializers import ViewSerializer +from baserow.contrib.database.views.handler import ViewSubscriptionHandler +from baserow.contrib.database.views.models import GridView +from baserow.contrib.database.views.signals import rows_entered_view +from baserow.contrib.database.webhooks.registries import WebhookEventType +from baserow_enterprise.features import ADVANCED_WEBHOOKS + + +class EnterpriseWebhookEventType(WebhookEventType): + def listener(self, **kwargs: dict): + """ + Only calls the super listener if the workspace has a valid license. + """ + + table = self.get_table_object(**kwargs) + if LicenseHandler.workspace_has_feature( + ADVANCED_WEBHOOKS, table.database.workspace + ): + super().listener(**kwargs) + + +class RowsEnterViewEventType(EnterpriseWebhookEventType): + type = "view.rows_entered" + signal = rows_entered_view + should_trigger_when_all_event_types_selected = False + + def get_table_object(self, model, **kwargs): + return model.baserow_table + + def get_additional_filters_for_webhooks_to_call(self, view, **kwargs): + return Q(events__views=view) + + def serialize_rows(self, model, rows, use_user_field_names): + rows_serializer = get_row_serializer_class( + model, + RowSerializer, + is_response=True, + user_field_names=use_user_field_names, + ) + return rows_serializer(rows, many=True).data + + def serialize_view(self, view): + return ViewSerializer(view).data + + def _paginate_payload(self, webhook, event_id, payload): + """ + Paginates the payload if it's too large. This is done by splitting the rows + into multiple payloads and returning a list of them. This method also replaces + the row_ids with the actual row data. + """ + + row_ids = payload.pop("row_ids") + batch_size = settings.BASEROW_WEBHOOK_ROWS_ENTER_VIEW_BATCH_SIZE + current_batch_row_ids = row_ids[:batch_size] + if len(current_batch_row_ids) < payload["total_count"]: + payload["offset"] = (payload.get("batch_id", 1) - 1) * batch_size + payload["batch_size"] = len(current_batch_row_ids) + + # prepare the remaining payload with the other row ids for the next batch + remaining = None + if len(row_ids) > batch_size: + remaining = payload.copy() + remaining["row_ids"] = row_ids[batch_size:] + + # get_payload only serialized row_ids, but since this method runs in the + # celery worker, we have more time to fully serialize fields data. + table = webhook.table + model = table.get_model() + + row_fields = [ + field.name if webhook.use_user_field_names else field.db_column + for field in model.get_fields() + ] + payload["fields"] = ["id", "order", *row_fields] + + rows = model.objects_and_trash.filter( + id__in=current_batch_row_ids + ).enhance_by_fields() + payload["rows"] = self.serialize_rows(model, rows, webhook.use_user_field_names) + + return payload, remaining + + def get_test_call_payload(self, table, model, event_id, webhook): + view = GridView(id=0, name="View", table=table, order=1) + row = model(id=0, order=0) + payload = self.get_payload( + event_id=event_id, webhook=webhook, view=view, row_ids=[row.id] + ) + return payload + + def get_payload(self, event_id, webhook, view, row_ids, **kwargs): + payload = super().get_payload(event_id, webhook, **kwargs) + payload["view"] = self.serialize_view(view) + payload["row_ids"] = row_ids + payload["total_count"] = len(row_ids) + + return payload + + def after_create(self, webhook_event): + views = webhook_event.views.all() + if views: + ViewSubscriptionHandler.subscribe_to_views(webhook_event, views) + + def after_update(self, webhook_event): + ViewSubscriptionHandler.unsubscribe_from_views(webhook_event) + views = webhook_event.views.all() + if views: + ViewSubscriptionHandler.subscribe_to_views(webhook_event, views) diff --git a/enterprise/backend/tests/baserow_enterprise_tests/api/dashboard/test_grouped_aggregate_rows_data_source_type.py b/enterprise/backend/tests/baserow_enterprise_tests/api/dashboard/test_grouped_aggregate_rows_data_source_type.py index 895282ef1..1ff5c3f68 100644 --- a/enterprise/backend/tests/baserow_enterprise_tests/api/dashboard/test_grouped_aggregate_rows_data_source_type.py +++ b/enterprise/backend/tests/baserow_enterprise_tests/api/dashboard/test_grouped_aggregate_rows_data_source_type.py @@ -4,14 +4,12 @@ from rest_framework.status import HTTP_200_OK from baserow.contrib.database.rows.handler import RowHandler from baserow.contrib.database.views.models import SORT_ORDER_ASC -from baserow.contrib.integrations.local_baserow.models import ( - LocalBaserowTableServiceSort, -) from baserow.test_utils.helpers import AnyDict, AnyInt from baserow_enterprise.integrations.local_baserow.models import ( LocalBaserowGroupedAggregateRows, LocalBaserowTableServiceAggregationGroupBy, LocalBaserowTableServiceAggregationSeries, + LocalBaserowTableServiceAggregationSortBy, ) @@ -39,6 +37,13 @@ def test_grouped_aggregate_rows_get_dashboard_data_sources( LocalBaserowTableServiceAggregationGroupBy.objects.create( service=data_source1.service, field=field_3, order=1 ) + LocalBaserowTableServiceAggregationSortBy.objects.create( + service=data_source1.service, + sort_on="GROUP_BY", + reference=f"field_{field_3.id}", + direction="ASC", + order=1, + ) enterprise_data_fixture.create_local_baserow_table_service_sort( service=data_source1.service, field=field_3, @@ -69,18 +74,37 @@ def test_grouped_aggregate_rows_get_dashboard_data_sources( {"aggregation_type": "sum", "field_id": field.id, "order": 1}, {"aggregation_type": "sum", "field_id": field_2.id, "order": 1}, ], - "context_data": {}, + "context_data": { + "fields": { + f"field_{field_3.id}": { + "description": None, + "id": field_3.id, + "immutable_properties": False, + "immutable_type": False, + "name": field_3.name, + "number_decimal_places": 0, + "number_negative": False, + "number_prefix": "", + "number_separator": "", + "number_suffix": "", + "order": 0, + "primary": False, + "read_only": False, + "table_id": table.id, + "type": "number", + }, + }, + }, "context_data_schema": None, "dashboard_id": dashboard.id, "filter_type": "AND", "filters": [], - "sortings": [ + "aggregation_sorts": [ { - "field": field_3.id, - "id": AnyInt(), - "trashed": False, - "order": 2, - "order_by": "ASC", + "sort_on": "GROUP_BY", + "reference": f"field_{field_3.id}", + "direction": "ASC", + "order": 1, } ], "id": data_source1.id, @@ -138,7 +162,13 @@ def test_grouped_aggregate_rows_update_data_source(api_client, enterprise_data_f {"field_id": field_2.id, "aggregation_type": "sum"}, ], "aggregation_group_bys": [{"field_id": field_3.id}], - "sortings": [{"field": field.id}], + "aggregation_sorts": [ + { + "sort_on": "SERIES", + "reference": f"field_{field.id}_sum", + "direction": "ASC", + } + ], }, format="json", HTTP_AUTHORIZATION=f"JWT {token}", @@ -164,13 +194,12 @@ def test_grouped_aggregate_rows_update_data_source(api_client, enterprise_data_f assert response_json["aggregation_group_bys"] == [ {"field_id": field_3.id, "order": 0} ] - assert response_json["sortings"] == [ + assert response_json["aggregation_sorts"] == [ { - "id": AnyInt(), - "field": field.id, - "trashed": False, + "sort_on": "SERIES", + "reference": f"field_{field.id}_sum", + "direction": "ASC", "order": 0, - "order_by": "ASC", } ] @@ -212,11 +241,19 @@ def test_grouped_aggregate_rows_dispatch_dashboard_data_source( LocalBaserowTableServiceAggregationGroupBy.objects.create( service=service, field=field, order=1 ) - LocalBaserowTableServiceSort.objects.create( - service=service, field=field_3, order=1, order_by="ASC" + LocalBaserowTableServiceAggregationSortBy.objects.create( + service=service, + sort_on="SERIES", + reference=f"field_{field_3.id}_sum", + order=1, + direction="ASC", ) - LocalBaserowTableServiceSort.objects.create( - service=service, field=field_2, order=2, order_by="DESC" + LocalBaserowTableServiceAggregationSortBy.objects.create( + service=service, + sort_on="SERIES", + reference=f"field_{field_2.id}_sum", + order=2, + direction="DESC", ) RowHandler().create_rows( diff --git a/enterprise/backend/tests/baserow_enterprise_tests/api/sso/test_saml_views.py b/enterprise/backend/tests/baserow_enterprise_tests/api/sso/test_saml_views.py index 5d59522f4..1bf09d64e 100644 --- a/enterprise/backend/tests/baserow_enterprise_tests/api/sso/test_saml_views.py +++ b/enterprise/backend/tests/baserow_enterprise_tests/api/sso/test_saml_views.py @@ -303,7 +303,11 @@ def test_saml_assertion_consumer_service(api_client, enterprise_data_fixture): assert response.headers["Location"].startswith( f"{get_frontend_default_redirect_url()}?token=" ) - token = response.headers["Location"].split("=")[1] + # Extract the token from the URL, handling the new format with user_session + redirect_url = response.headers["Location"] + query_params = dict(parse_qsl(urlparse(redirect_url).query)) + token = query_params.get("token") + # ensure the token is valid and a user has been created response = api_client.post( reverse("api:user:token_verify"), diff --git a/enterprise/backend/tests/baserow_enterprise_tests/dashboard/test_dashboard_application_types_charts_.py b/enterprise/backend/tests/baserow_enterprise_tests/dashboard/test_dashboard_application_types_charts_.py new file mode 100644 index 000000000..02158ba21 --- /dev/null +++ b/enterprise/backend/tests/baserow_enterprise_tests/dashboard/test_dashboard_application_types_charts_.py @@ -0,0 +1,271 @@ +import json +from decimal import Decimal +from typing import cast + +from django.contrib.contenttypes.models import ContentType +from django.test.utils import override_settings + +import pytest + +from baserow.contrib.dashboard.application_types import DashboardApplicationType +from baserow.contrib.dashboard.data_sources.models import DashboardDataSource +from baserow.contrib.dashboard.models import Dashboard +from baserow.contrib.dashboard.widgets.models import Widget +from baserow.contrib.dashboard.widgets.service import WidgetService +from baserow.contrib.integrations.local_baserow.models import LocalBaserowIntegration +from baserow.core.handler import CoreHandler +from baserow.core.integrations.models import Integration +from baserow.core.registries import ImportExportConfig +from baserow.core.utils import ChildProgressBuilder, Progress +from baserow_enterprise.dashboard.widgets.models import ChartWidget +from baserow_enterprise.integrations.local_baserow.models import ( + LocalBaserowGroupedAggregateRows, + LocalBaserowTableServiceAggregationGroupBy, + LocalBaserowTableServiceAggregationSeries, + LocalBaserowTableServiceAggregationSortBy, +) + + +@pytest.mark.django_db +@override_settings(DEBUG=True) +def test_dashboard_export_serialized_with_chart_widget(enterprise_data_fixture): + enterprise_data_fixture.enable_enterprise() + user = enterprise_data_fixture.create_user() + workspace = enterprise_data_fixture.create_workspace(user=user) + database = enterprise_data_fixture.create_database_application( + user=user, workspace=workspace + ) + table = enterprise_data_fixture.create_database_table(database=database) + field = enterprise_data_fixture.create_number_field(table=table) + dashboard = cast( + Dashboard, + CoreHandler().create_application( + user, + workspace, + type_name="dashboard", + description="Dashboard description", + init_with_data=True, + ), + ) + integration = Integration.objects.filter(application=dashboard).first() + dashboard_widget = WidgetService().create_widget( + user, "chart", dashboard.id, title="Widget 1", description="Description 1" + ) + service = dashboard_widget.data_source.service + service.table = table + service.save() + LocalBaserowTableServiceAggregationSeries.objects.create( + service=service, field=field, aggregation_type="sum", order=1 + ) + LocalBaserowTableServiceAggregationGroupBy.objects.create( + service=service, field=None, order=1 + ) + LocalBaserowTableServiceAggregationSortBy.objects.create( + service=service, + sort_on="SERIES", + reference=f"field_{field.id}_sum", + order=1, + direction="ASC", + ) + + serialized = DashboardApplicationType().export_serialized( + dashboard, ImportExportConfig(include_permission_data=True) + ) + + serialized = json.loads(json.dumps(serialized)) + assert serialized == { + "id": dashboard.id, + "name": dashboard.name, + "description": "Dashboard description", + "order": dashboard.order, + "type": "dashboard", + "integrations": [ + { + "authorized_user": user.email, + "id": integration.id, + "name": "", + "order": "1.00000000000000000000", + "type": "local_baserow", + }, + ], + "data_sources": [ + { + "id": dashboard_widget.data_source.id, + "name": dashboard_widget.data_source.name, + "order": "1.00000000000000000000", + "service": { + "filter_type": "AND", + "filters": [], + "id": service.id, + "integration_id": service.integration.id, + "service_aggregation_group_bys": [ + {"field_id": None}, + ], + "service_aggregation_series": [ + {"aggregation_type": "sum", "field_id": field.id}, + ], + "service_aggregation_sorts": [ + { + "direction": "ASC", + "reference": f"field_{field.id}_sum", + "sort_on": "SERIES", + }, + ], + "table_id": table.id, + "type": "local_baserow_grouped_aggregate_rows", + "view_id": None, + }, + }, + ], + "widgets": [ + { + "data_source_id": dashboard_widget.data_source.id, + "description": "Description 1", + "id": dashboard_widget.id, + "order": "1.00000000000000000000", + "title": "Widget 1", + "type": "chart", + }, + ], + "role_assignments": [], + } + + +@pytest.mark.django_db() +@override_settings(DEBUG=True) +def test_dashboard_import_serialized_with_widgets(enterprise_data_fixture): + enterprise_data_fixture.enable_enterprise() + user = enterprise_data_fixture.create_user() + workspace = enterprise_data_fixture.create_workspace(user=user) + database = enterprise_data_fixture.create_database_application( + user=user, workspace=workspace + ) + table = enterprise_data_fixture.create_database_table(database=database) + field = enterprise_data_fixture.create_number_field(table=table) + field_2 = enterprise_data_fixture.create_number_field(table=table, primary=True) + + id_mapping = { + "database_tables": {1: table.id}, + "database_fields": {1: field.id}, + } + + serialized = { + "id": "999", + "name": "Dashboard 1", + "description": "Description 1", + "order": 99, + "type": "dashboard", + "integrations": [ + { + "authorized_user": user.email, + "id": 1, + "name": "IntegrationName", + "order": "1.00000000000000000000", + "type": "local_baserow", + }, + ], + "data_sources": [ + { + "id": 1, + "name": "DataSource1", + "order": "1.00000000000000000000", + "service": { + "filter_type": "AND", + "filters": [], + "id": 1, + "integration_id": 1, + "service_aggregation_group_bys": [ + {"field_id": None}, + ], + "service_aggregation_series": [ + {"aggregation_type": "sum", "field_id": 1}, + ], + "service_aggregation_sorts": [ + { + "direction": "ASC", + "reference": f"field_1_sum", + "sort_on": "SERIES", + }, + ], + "table_id": 1, + "type": "local_baserow_grouped_aggregate_rows", + "view_id": None, + }, + }, + ], + "widgets": [ + { + "data_source_id": 1, + "description": "Description 1", + "id": 45, + "order": "1.00000000000000000000", + "title": "Widget 1", + "type": "chart", + }, + ], + } + + progress = Progress(100) + progress_builder = ChildProgressBuilder(parent=progress, represents_progress=100) + assert progress.progress == 0 + + dashboard = DashboardApplicationType().import_serialized( + workspace, + serialized, + ImportExportConfig(include_permission_data=True), + id_mapping, + progress_builder=progress_builder, + ) + + assert dashboard.name == "Dashboard 1" + assert dashboard.description == "Description 1" + assert dashboard.order == 99 + + integrations = Integration.objects.filter(application=dashboard) + integration = integrations[0].specific + assert integrations.count() == 1 + assert integration.content_type == ContentType.objects.get_for_model( + LocalBaserowIntegration + ) + assert integration.authorized_user.id == user.id + assert integration.name == "IntegrationName" + assert integration.order == Decimal("1.0") + + data_sources = DashboardDataSource.objects.filter(dashboard=dashboard) + assert data_sources.count() == 1 + + ds1 = data_sources[0] + ds1.name = "DataSource1" + ds1.order = Decimal("1.0") + service = ds1.service.specific + assert service.content_type == ContentType.objects.get_for_model( + LocalBaserowGroupedAggregateRows + ) + assert service.integration_id == integration.id + assert service.filter_type == "AND" + + series = service.service_aggregation_series.all() + assert series.count() == 1 + assert series[0].aggregation_type == "sum" + assert series[0].field_id == field.id + + group_bys = service.service_aggregation_group_bys.all() + assert group_bys.count() == 1 + assert group_bys[0].field_id is None + + sorts = service.service_aggregation_sorts.all() + assert sorts.count() == 1 + assert sorts[0].direction == "ASC" + assert sorts[0].sort_on == "SERIES" + assert sorts[0].reference == f"field_{field.id}_sum" + + widgets = Widget.objects.filter(dashboard=dashboard) + assert widgets.count() == 1 + widget1 = widgets[0].specific + assert widget1.content_type == ContentType.objects.get_for_model(ChartWidget) + assert widget1.title == "Widget 1" + assert widget1.description == "Description 1" + assert widget1.order == Decimal("1.0") + assert widget1.data_source.id == ds1.id + + assert progress.progress == 100 diff --git a/enterprise/backend/tests/baserow_enterprise_tests/data_sync/test_data_sync_ai_field.py b/enterprise/backend/tests/baserow_enterprise_tests/data_sync/test_data_sync_ai_field.py new file mode 100644 index 000000000..0df8a8bb7 --- /dev/null +++ b/enterprise/backend/tests/baserow_enterprise_tests/data_sync/test_data_sync_ai_field.py @@ -0,0 +1,61 @@ +from django.test.utils import override_settings + +import pytest + +from baserow.contrib.database.data_sync.handler import DataSyncHandler + + +@pytest.mark.django_db +@override_settings(DEBUG=True) +def test_sync_table_with_ai_field(enterprise_data_fixture, premium_data_fixture): + enterprise_data_fixture.enable_enterprise() + + user = enterprise_data_fixture.create_user() + + source_table = enterprise_data_fixture.create_database_table( + user=user, name="Source" + ) + field_1 = enterprise_data_fixture.create_text_field( + table=source_table, name="Text", primary=True + ) + ai_field = premium_data_fixture.create_ai_field( + table=source_table, + name="ai_field", + ai_generative_ai_type="test_generative_ai", + ai_generative_ai_model="test_1", + ai_prompt="field('text_field')", + ) + source_model = source_table.get_model() + source_row_1 = source_model.objects.create( + **{ + f"field_{field_1.id}": "Text field", + f"field_{ai_field.id}": "AI Field value #1", + } + ) + + database = enterprise_data_fixture.create_database_application(user=user) + handler = DataSyncHandler() + + data_sync = handler.create_data_sync_table( + user=user, + database=database, + table_name="Test", + type_name="local_baserow_table", + synced_properties=["id", f"field_{field_1.id}", f"field_{ai_field.id}"], + source_table_id=source_table.id, + ) + handler.sync_data_sync_table(user=user, data_sync=data_sync) + + source_row_1.refresh_from_db() + + # We don't need AI calculations for this test. We just need value changed to + # trigger the sync. + setattr(source_row_1, f"field_{ai_field.id}", "AI Field value #2") + source_row_1.save() + + handler.sync_data_sync_table(user=user, data_sync=data_sync) + + source_row_1.refresh_from_db() + + assert data_sync.last_sync is not None + assert data_sync.last_error is None diff --git a/enterprise/backend/tests/baserow_enterprise_tests/data_sync/test_enterprise_data_sync_handler.py b/enterprise/backend/tests/baserow_enterprise_tests/data_sync/test_enterprise_data_sync_handler.py index 66d370d1d..da6d42591 100644 --- a/enterprise/backend/tests/baserow_enterprise_tests/data_sync/test_enterprise_data_sync_handler.py +++ b/enterprise/backend/tests/baserow_enterprise_tests/data_sync/test_enterprise_data_sync_handler.py @@ -14,8 +14,12 @@ from freezegun.api import freeze_time from baserow.contrib.database.data_sync.handler import DataSyncHandler from baserow.contrib.database.data_sync.models import DataSync from baserow.core.exceptions import UserNotInWorkspace +from baserow.core.notifications.models import Notification from baserow_enterprise.data_sync.handler import EnterpriseDataSyncHandler from baserow_enterprise.data_sync.models import PeriodicDataSyncInterval +from baserow_enterprise.data_sync.notification_types import ( + PeriodicDataSyncDeactivatedNotificationType, +) @pytest.mark.django_db @@ -611,6 +615,53 @@ def test_sync_periodic_data_sync_deactivated_max_failure(enterprise_data_fixture assert periodic_data_sync.automatically_deactivated is True +@pytest.mark.django_db(transaction=True) +@override_settings(DEBUG=True) +@responses.activate +def test_sync_periodic_data_sync_deactivated_max_failure_notification_send( + enterprise_data_fixture, +): + responses.add( + responses.GET, + "https://baserow.io/ical.ics", + status=404, + body="", + ) + + enterprise_data_fixture.enable_enterprise() + user = enterprise_data_fixture.create_user() + + periodic_data_sync = EnterpriseDataSyncHandler.update_periodic_data_sync_interval( + user=user, + data_sync=enterprise_data_fixture.create_ical_data_sync(user=user), + interval="DAILY", + when=time(hour=12, minute=10, second=1, microsecond=1), + ) + periodic_data_sync.consecutive_failed_count = 3 + periodic_data_sync.save() + + with transaction.atomic(): + EnterpriseDataSyncHandler.sync_periodic_data_sync(periodic_data_sync.id) + + all_notifications = list(Notification.objects.all()) + assert len(all_notifications) == 1 + recipient_ids = [r.id for r in all_notifications[0].recipients.all()] + assert recipient_ids == [user.id] + assert all_notifications[0].type == PeriodicDataSyncDeactivatedNotificationType.type + assert all_notifications[0].broadcast is False + assert ( + all_notifications[0].workspace_id + == periodic_data_sync.data_sync.table.database.workspace_id + ) + assert all_notifications[0].sender is None + assert all_notifications[0].data == { + "data_sync_id": periodic_data_sync.data_sync_id, + "table_name": periodic_data_sync.data_sync.table.name, + "table_id": periodic_data_sync.data_sync.table.id, + "database_id": periodic_data_sync.data_sync.table.database_id, + } + + @pytest.mark.django_db @override_settings(DEBUG=True) def test_sync_periodic_data_sync_authorized_user_is_none(enterprise_data_fixture): diff --git a/enterprise/backend/tests/baserow_enterprise_tests/data_sync/test_periodic_data_sync_notification_types.py b/enterprise/backend/tests/baserow_enterprise_tests/data_sync/test_periodic_data_sync_notification_types.py new file mode 100644 index 000000000..9e67e406a --- /dev/null +++ b/enterprise/backend/tests/baserow_enterprise_tests/data_sync/test_periodic_data_sync_notification_types.py @@ -0,0 +1,47 @@ +from datetime import time + +from django.test.utils import override_settings + +import pytest + +from baserow_enterprise.data_sync.handler import EnterpriseDataSyncHandler +from baserow_enterprise.data_sync.notification_types import ( + PeriodicDataSyncDeactivatedNotificationType, +) + + +@override_settings(DEBUG=True) +@pytest.mark.django_db(transaction=True) +def test_webhook_deactivated_notification_can_be_render_as_email( + api_client, enterprise_data_fixture +): + enterprise_data_fixture.enable_enterprise() + + user = enterprise_data_fixture.create_user() + periodic_data_sync = EnterpriseDataSyncHandler.update_periodic_data_sync_interval( + user=user, + data_sync=enterprise_data_fixture.create_ical_data_sync(user=user), + interval="DAILY", + when=time(hour=12, minute=10, second=1, microsecond=1), + ) + + notification_recipients = ( + PeriodicDataSyncDeactivatedNotificationType.notify_authorized_user( + periodic_data_sync + ) + ) + notification = notification_recipients[0].notification + + assert PeriodicDataSyncDeactivatedNotificationType.get_notification_title_for_email( + notification, {} + ) == "%(name)s periodic data sync has been deactivated." % { + "name": periodic_data_sync.data_sync.table.name, + } + + assert ( + PeriodicDataSyncDeactivatedNotificationType.get_notification_description_for_email( + notification, {} + ) + == "The periodic data sync failed more than 4 consecutive times" + "and was therefore deactivated." + ) diff --git a/enterprise/backend/tests/baserow_enterprise_tests/enterprise/test_enterprise_license.py b/enterprise/backend/tests/baserow_enterprise_tests/enterprise/test_enterprise_license.py index 08ab10fcc..0f899b005 100755 --- a/enterprise/backend/tests/baserow_enterprise_tests/enterprise/test_enterprise_license.py +++ b/enterprise/backend/tests/baserow_enterprise_tests/enterprise/test_enterprise_license.py @@ -17,7 +17,7 @@ from baserow_premium.license.handler import LicenseHandler from baserow_premium.license.registries import SeatUsageSummary from freezegun import freeze_time from PIL import Image -from responses import json_params_matcher +from responses.matchers import json_params_matcher from baserow.api.user.registries import user_data_registry from baserow.contrib.database.models import Database @@ -261,7 +261,7 @@ def test_user_data_no_enterprise_features_instance_wide_not_active( @pytest.mark.django_db @override_settings(DEBUG=True) @responses.activate -def test_check_licenses_with_enterprise_license_sends_seat_data( +def test_check_licenses_with_enterprise_license_sends_usage_data( enterprise_data_fixture, ): license_object = enterprise_data_fixture.enable_enterprise() @@ -283,9 +283,11 @@ def test_check_licenses_with_enterprise_license_sends_seat_data( "instance_id": Settings.objects.get().instance_id, "extra_license_info": [ { - "id": license_object.id, + "id": license_object.license_id, "free_users_count": 0, - "seats_taken": 1, + "seats_taken": 0, + "application_users_taken": 0, + "highest_role_per_user_id": {}, } ], } diff --git a/enterprise/backend/tests/baserow_enterprise_tests/integrations/local_baserow/service_types/test_grouped_aggregate_rows_service_type.py b/enterprise/backend/tests/baserow_enterprise_tests/integrations/local_baserow/service_types/test_grouped_aggregate_rows_service_type.py index 8fd9ea0ce..bb2b19c3b 100644 --- a/enterprise/backend/tests/baserow_enterprise_tests/integrations/local_baserow/service_types/test_grouped_aggregate_rows_service_type.py +++ b/enterprise/backend/tests/baserow_enterprise_tests/integrations/local_baserow/service_types/test_grouped_aggregate_rows_service_type.py @@ -7,9 +7,6 @@ import pytest from rest_framework.exceptions import ValidationError from baserow.contrib.database.rows.handler import RowHandler -from baserow.contrib.integrations.local_baserow.models import ( - LocalBaserowTableServiceSort, -) from baserow.core.services.exceptions import ServiceImproperlyConfigured from baserow.core.services.handler import ServiceHandler from baserow.core.services.registries import service_type_registry @@ -18,6 +15,10 @@ from baserow_enterprise.integrations.local_baserow.models import ( LocalBaserowGroupedAggregateRows, LocalBaserowTableServiceAggregationGroupBy, LocalBaserowTableServiceAggregationSeries, + LocalBaserowTableServiceAggregationSortBy, +) +from baserow_enterprise.integrations.local_baserow.service_types import ( + LocalBaserowGroupedAggregateRowsUserServiceType, ) @@ -219,6 +220,76 @@ def test_create_grouped_aggregate_rows_service_group_by_field_not_in_table( ServiceHandler().create_service(service_type, **values) +@pytest.mark.django_db +def test_create_grouped_aggregate_rows_service_group_by_field_not_compatible( + data_fixture, +): + user = data_fixture.create_user() + dashboard = data_fixture.create_dashboard_application(user=user) + table = data_fixture.create_database_table(user=user) + table_2 = data_fixture.create_database_table(user=user) + field = data_fixture.create_number_field(table=table) + field_2 = data_fixture.create_uuid_field(table=table) + view = data_fixture.create_grid_view(user=user, table=table) + integration = data_fixture.create_local_baserow_integration( + application=dashboard, user=user + ) + service_type = service_type_registry.get("local_baserow_grouped_aggregate_rows") + values = service_type.prepare_values( + { + "view_id": view.id, + "table_id": view.table_id, + "integration_id": integration.id, + "service_aggregation_series": [ + {"field_id": field.id, "aggregation_type": "sum"}, + ], + "service_aggregation_group_bys": [{"field_id": field_2.id}], + }, + user, + ) + + with pytest.raises( + ValidationError, + match=f"The field with ID {field_2.id} cannot be used as a group by field.", + ): + ServiceHandler().create_service(service_type, **values) + + +@pytest.mark.django_db +def test_create_grouped_aggregate_rows_service_duplicate_series( + data_fixture, +): + user = data_fixture.create_user() + dashboard = data_fixture.create_dashboard_application(user=user) + table = data_fixture.create_database_table(user=user) + field = data_fixture.create_number_field(table=table) + field_2 = data_fixture.create_number_field(table=table) + view = data_fixture.create_grid_view(user=user, table=table) + integration = data_fixture.create_local_baserow_integration( + application=dashboard, user=user + ) + service_type = service_type_registry.get("local_baserow_grouped_aggregate_rows") + values = service_type.prepare_values( + { + "view_id": view.id, + "table_id": view.table_id, + "integration_id": integration.id, + "service_aggregation_series": [ + {"field_id": field.id, "aggregation_type": "sum"}, + {"field_id": field_2.id, "aggregation_type": "sum"}, + {"field_id": field_2.id, "aggregation_type": "sum"}, + ], + }, + user, + ) + + with pytest.raises( + ValidationError, + match=f"The series with the field ID {field_2.id} and aggregation type sum can only be defined once.", + ): + ServiceHandler().create_service(service_type, **values) + + @pytest.mark.django_db def test_create_grouped_aggregate_rows_service_max_series_exceeded( data_fixture, @@ -317,8 +388,12 @@ def test_create_grouped_aggregate_rows_service_sort_by_field_outside_of_series_g {"field_id": field.id, "aggregation_type": "sum"}, ], "service_aggregation_group_bys": [{"field_id": field.id}], - "service_sorts": [ - {"field": field_2}, + "service_aggregation_sorts": [ + { + "sort_on": "SERIES", + "reference": f"field_{field_2.id}", + "direction": "ASC", + }, ], }, user, @@ -326,7 +401,7 @@ def test_create_grouped_aggregate_rows_service_sort_by_field_outside_of_series_g with pytest.raises( ValidationError, - match=f"The field with ID {field_2.id} cannot be used for sorting.", + match=f"The reference sort 'field_{field_2.id}' cannot be used for sorting.", ): ServiceHandler().create_service(service_type, **values) @@ -354,8 +429,12 @@ def test_create_grouped_aggregate_rows_service_sort_by_primary_field_no_group_by {"field_id": field.id, "aggregation_type": "sum"}, ], "service_aggregation_group_bys": [], - "service_sorts": [ - {"field": field_2}, + "service_aggregation_sorts": [ + { + "sort_on": "PRIMARY", + "reference": f"field_{field_2.id}", + "direction": "ASC", + }, ], }, user, @@ -363,7 +442,7 @@ def test_create_grouped_aggregate_rows_service_sort_by_primary_field_no_group_by with pytest.raises( ValidationError, - match=f"The field with ID {field_2.id} cannot be used for sorting.", + match=f"The reference sort 'field_{field_2.id}' cannot be used for sorting.", ): ServiceHandler().create_service(service_type, **values) @@ -389,8 +468,12 @@ def test_create_grouped_aggregate_rows_service_sort_by_primary_field_with_group_ "integration_id": integration.id, "service_aggregation_series": [], "service_aggregation_group_bys": [{"field_id": field_2.id}], - "service_sorts": [ - {"field": field}, + "service_aggregation_sorts": [ + { + "sort_on": "PRIMARY", + "reference": f"field_{field.id}", + "direction": "ASC", + }, ], }, user, @@ -398,7 +481,7 @@ def test_create_grouped_aggregate_rows_service_sort_by_primary_field_with_group_ with pytest.raises( ValidationError, - match=f"The field with ID {field.id} cannot be used for sorting.", + match=f"The reference sort 'field_{field.id}' cannot be used for sorting.", ): ServiceHandler().create_service(service_type, **values) @@ -649,6 +732,46 @@ def test_update_grouped_aggregate_rows_service_group_by_field_not_in_table( ServiceHandler().update_service(service_type, service=service, **values) +@pytest.mark.django_db +def test_update_grouped_aggregate_rows_service_group_by_field_not_in_compatible( + data_fixture, +): + user = data_fixture.create_user() + dashboard = data_fixture.create_dashboard_application(user=user) + table = data_fixture.create_database_table(user=user) + field = data_fixture.create_number_field(table=table) + field_2 = data_fixture.create_uuid_field(table=table) + view = data_fixture.create_grid_view(user=user, table=table) + integration = data_fixture.create_local_baserow_integration( + application=dashboard, user=user + ) + service_type = service_type_registry.get("local_baserow_grouped_aggregate_rows") + service = data_fixture.create_service( + LocalBaserowGroupedAggregateRows, + integration=integration, + table=table, + view=view, + ) + + values = service_type.prepare_values( + { + "table_id": table.id, + "service_aggregation_series": [ + {"field_id": field.id, "aggregation_type": "sum"}, + ], + "service_aggregation_group_bys": [{"field_id": field_2.id}], + }, + user, + service, + ) + + with pytest.raises( + ValidationError, + match=f"The field with ID {field_2.id} cannot be used as a group by field.", + ): + ServiceHandler().update_service(service_type, service=service, **values) + + @pytest.mark.django_db def test_update_grouped_aggregate_rows_service_max_series_exceeded( data_fixture, @@ -765,8 +888,12 @@ def test_update_grouped_aggregate_rows_service_sort_by_field_outside_of_series_g {"field_id": field.id, "aggregation_type": "sum"}, ], "service_aggregation_group_bys": [{"field_id": field.id}], - "service_sorts": [ - {"field": field_2}, + "service_aggregation_sorts": [ + { + "sort_on": "GROUP_BY", + "reference": f"field_{field_2.id}", + "direction": "ASC", + }, ], }, user, @@ -774,7 +901,7 @@ def test_update_grouped_aggregate_rows_service_sort_by_field_outside_of_series_g with pytest.raises( ValidationError, - match=f"The field with ID {field_2.id} cannot be used for sorting.", + match=f"The reference sort 'field_{field_2.id}' cannot be used for sorting.", ): ServiceHandler().update_service(service_type, service=service, **values) @@ -808,8 +935,12 @@ def test_update_grouped_aggregate_rows_service_sort_by_primary_field_no_group_by {"field_id": field.id, "aggregation_type": "sum"}, ], "service_aggregation_group_bys": [], - "service_sorts": [ - {"field": field_2}, + "service_aggregation_sorts": [ + { + "sort_on": "PRIMARY", + "reference": f"field_{field_2.id}", + "direction": "ASC", + }, ], }, user, @@ -817,7 +948,7 @@ def test_update_grouped_aggregate_rows_service_sort_by_primary_field_no_group_by with pytest.raises( ValidationError, - match=f"The field with ID {field_2.id} cannot be used for sorting.", + match=f"The reference sort 'field_{field_2.id}' cannot be used for sorting.", ): ServiceHandler().update_service(service_type, service=service, **values) @@ -849,8 +980,12 @@ def test_update_grouped_aggregate_rows_service_sort_by_primary_field_with_group_ "integration_id": integration.id, "service_aggregation_series": [], "service_aggregation_group_bys": [{"field_id": field_2.id}], - "service_sorts": [ - {"field": field}, + "service_aggregation_sorts": [ + { + "sort_on": "PRIMARY", + "reference": f"field_{field.id}", + "direction": "ASC", + }, ], }, user, @@ -858,7 +993,7 @@ def test_update_grouped_aggregate_rows_service_sort_by_primary_field_with_group_ with pytest.raises( ValidationError, - match=f"The field with ID {field.id} cannot be used for sorting.", + match=f"The reference sort 'field_{field.id}' cannot be used for sorting.", ): ServiceHandler().update_service(service_type, service=service, **values) @@ -887,8 +1022,12 @@ def test_update_grouped_aggregate_rows_service_reset_after_table_change(data_fix LocalBaserowTableServiceAggregationGroupBy.objects.create( service=service, field=field, order=1 ) - LocalBaserowTableServiceSort.objects.create( - service=service, field=field, order=2, order_by="ASC" + LocalBaserowTableServiceAggregationSortBy.objects.create( + service=service, + sort_on="SERIES", + reference=f"field_{field.id}_sum", + order=2, + direction="ASC", ) values = service_type.prepare_values( @@ -911,7 +1050,7 @@ def test_update_grouped_aggregate_rows_service_reset_after_table_change(data_fix assert service.view is None assert service.service_aggregation_series.all().count() == 0 assert service.service_aggregation_group_bys.all().count() == 0 - assert service.service_sorts.all().count() == 0 + assert service.service_aggregation_sorts.all().count() == 0 @pytest.mark.django_db @@ -1214,6 +1353,41 @@ def test_grouped_aggregate_rows_service_dispatch_incompatible_aggregation(data_f ) +@pytest.mark.django_db +def test_dispatch_grouped_aggregate_rows_service_duplicate_series( + data_fixture, +): + user = data_fixture.create_user() + dashboard = data_fixture.create_dashboard_application(user=user) + table = data_fixture.create_database_table(user=user) + field = data_fixture.create_number_field(table=table) + view = data_fixture.create_grid_view(user=user, table=table) + integration = data_fixture.create_local_baserow_integration( + application=dashboard, user=user + ) + service = data_fixture.create_service( + LocalBaserowGroupedAggregateRows, + integration=integration, + table=table, + view=view, + ) + LocalBaserowTableServiceAggregationSeries.objects.create( + service=service, field=field, aggregation_type="sum", order=1 + ) + LocalBaserowTableServiceAggregationSeries.objects.create( + service=service, field=field, aggregation_type="sum", order=1 + ) + + dispatch_context = FakeDispatchContext() + + with pytest.raises(ServiceImproperlyConfigured) as exc: + ServiceHandler().dispatch_service(service, dispatch_context) + assert ( + exc.value.args[0] + == f"The series with field ID {field.id} and aggregation type sum can only be defined once." + ) + + @pytest.mark.django_db def test_grouped_aggregate_rows_service_agg_series_field_trashed(data_fixture): user = data_fixture.create_user() @@ -1269,6 +1443,38 @@ def test_grouped_aggregate_rows_service_group_by_field_trashed(data_fixture): assert exc.value.args[0] == f"The field with ID {field_2.id} is trashed." +@pytest.mark.django_db +def test_grouped_aggregate_rows_service_group_by_field_not_compatible(data_fixture): + user = data_fixture.create_user() + dashboard = data_fixture.create_dashboard_application(user=user) + table = data_fixture.create_database_table(user=user) + field = data_fixture.create_number_field(table=table) + field_2 = data_fixture.create_uuid_field(table=table) + integration = data_fixture.create_local_baserow_integration( + application=dashboard, user=user + ) + service = data_fixture.create_service( + LocalBaserowGroupedAggregateRows, + integration=integration, + table=table, + ) + LocalBaserowTableServiceAggregationSeries.objects.create( + service=service, field=field, aggregation_type="sum", order=1 + ) + LocalBaserowTableServiceAggregationGroupBy.objects.create( + service=service, field=field_2, order=1 + ) + + dispatch_context = FakeDispatchContext() + + with pytest.raises(ServiceImproperlyConfigured) as exc: + ServiceHandler().dispatch_service(service, dispatch_context) + assert ( + exc.value.args[0] + == f"The field with ID {field_2.id} cannot be used for group by." + ) + + @pytest.mark.django_db def test_grouped_aggregate_rows_service_table_trashed(data_fixture): user = data_fixture.create_user() @@ -1548,11 +1754,19 @@ def test_grouped_aggregate_rows_service_dispatch_sort_by_series_with_group_by( LocalBaserowTableServiceAggregationGroupBy.objects.create( service=service, field=field, order=1 ) - LocalBaserowTableServiceSort.objects.create( - service=service, field=field_3, order=1, order_by="ASC" + LocalBaserowTableServiceAggregationSortBy.objects.create( + service=service, + sort_on="SERIES", + reference=f"field_{field_3.id}_sum", + order=1, + direction="ASC", ) - LocalBaserowTableServiceSort.objects.create( - service=service, field=field_2, order=2, order_by="DESC" + LocalBaserowTableServiceAggregationSortBy.objects.create( + service=service, + sort_on="SERIES", + reference=f"field_{field_2.id}_sum", + order=2, + direction="DESC", ) RowHandler().create_rows( @@ -1682,11 +1896,19 @@ def test_grouped_aggregate_rows_service_dispatch_sort_by_series_with_group_by_ro LocalBaserowTableServiceAggregationGroupBy.objects.create( service=service, field=None, order=1 ) - LocalBaserowTableServiceSort.objects.create( - service=service, field=field_3, order=1, order_by="ASC" + LocalBaserowTableServiceAggregationSortBy.objects.create( + service=service, + sort_on="SERIES", + reference=f"field_{field_3.id}_sum", + order=1, + direction="ASC", ) - LocalBaserowTableServiceSort.objects.create( - service=service, field=field_2, order=2, order_by="DESC" + LocalBaserowTableServiceAggregationSortBy.objects.create( + service=service, + sort_on="SERIES", + reference=f"field_{field_2.id}_sum", + order=2, + direction="DESC", ) RowHandler().create_rows( @@ -1795,11 +2017,19 @@ def test_grouped_aggregate_rows_service_dispatch_sort_by_series_without_group_by LocalBaserowTableServiceAggregationSeries.objects.create( service=service, field=field_3, aggregation_type="sum", order=3 ) - LocalBaserowTableServiceSort.objects.create( - service=service, field=field_3, order=1, order_by="ASC" + LocalBaserowTableServiceAggregationSortBy.objects.create( + service=service, + sort_on="SERIES", + reference=f"field_{field.id}_sum", + order=1, + direction="ASC", ) - LocalBaserowTableServiceSort.objects.create( - service=service, field=field_2, order=2, order_by="DESC" + LocalBaserowTableServiceAggregationSortBy.objects.create( + service=service, + sort_on="SERIES", + reference=f"field_{field_2.id}_sum", + order=2, + direction="DESC", ) RowHandler().create_rows( @@ -1875,8 +2105,12 @@ def test_grouped_aggregate_rows_service_dispatch_sort_by_group_by_field(data_fix LocalBaserowTableServiceAggregationGroupBy.objects.create( service=service, field=field, order=1 ) - LocalBaserowTableServiceSort.objects.create( - service=service, field=field, order=1, order_by="ASC" + LocalBaserowTableServiceAggregationSortBy.objects.create( + service=service, + sort_on="GROUP_BY", + reference=f"field_{field.id}", + order=1, + direction="ASC", ) RowHandler().create_rows( @@ -1997,8 +2231,12 @@ def test_grouped_aggregate_rows_service_dispatch_sort_by_group_by_row_id(data_fi LocalBaserowTableServiceAggregationGroupBy.objects.create( service=service, field=None, order=1 ) - LocalBaserowTableServiceSort.objects.create( - service=service, field=field, order=1, order_by="ASC" + LocalBaserowTableServiceAggregationSortBy.objects.create( + service=service, + sort_on="GROUP_BY", + reference=f"field_{field.id}", + order=1, + direction="ASC", ) RowHandler().create_rows( @@ -2095,15 +2333,19 @@ def test_grouped_aggregate_rows_service_dispatch_sort_by_field_outside_series_or LocalBaserowTableServiceAggregationSeries.objects.create( service=service, field=field, aggregation_type="sum", order=2 ) - LocalBaserowTableServiceSort.objects.create( - service=service, field=field_2, order=1, order_by="ASC" + LocalBaserowTableServiceAggregationSortBy.objects.create( + service=service, + sort_on="GROUP_BY", + reference=f"field_{field_2.id}", + order=1, + direction="ASC", ) dispatch_context = FakeDispatchContext() with pytest.raises( ServiceImproperlyConfigured, - match=f"The field with ID {field_2.id} cannot be used for sorting.", + match=f"The sort reference 'field_{field_2.id}' cannot be used for sorting.", ): ServiceHandler().dispatch_service(service, dispatch_context) @@ -2130,15 +2372,19 @@ def test_grouped_aggregate_rows_service_dispatch_sort_by_primary_field_no_group_ LocalBaserowTableServiceAggregationSeries.objects.create( service=service, field=field_2, aggregation_type="sum", order=2 ) - LocalBaserowTableServiceSort.objects.create( - service=service, field=field, order=2, order_by="ASC" + LocalBaserowTableServiceAggregationSortBy.objects.create( + service=service, + sort_on="PRIMARY", + reference=f"field_{field.id}", + order=2, + direction="ASC", ) dispatch_context = FakeDispatchContext() with pytest.raises( ServiceImproperlyConfigured, - match=f"The field with ID {field.id} cannot be used for sorting.", + match=f"The sort reference 'field_{field.id}' cannot be used for sorting.", ): ServiceHandler().dispatch_service(service, dispatch_context) @@ -2168,15 +2414,19 @@ def test_grouped_aggregate_rows_service_dispatch_sort_by_primary_field_group_by_ LocalBaserowTableServiceAggregationGroupBy.objects.create( service=service, field=field_2, order=1 ) - LocalBaserowTableServiceSort.objects.create( - service=service, field=field, order=2, order_by="ASC" + LocalBaserowTableServiceAggregationSortBy.objects.create( + service=service, + sort_on="PRIMARY", + reference=f"field_{field.id}", + order=2, + direction="ASC", ) dispatch_context = FakeDispatchContext() with pytest.raises( ServiceImproperlyConfigured, - match=f"The field with ID {field.id} cannot be used for sorting.", + match=f"The sort reference 'field_{field.id}' cannot be used for sorting.", ): ServiceHandler().dispatch_service(service, dispatch_context) @@ -2338,8 +2588,12 @@ def test_grouped_aggregate_rows_service_dispatch_max_buckets_sort_on_group_by_fi LocalBaserowTableServiceAggregationGroupBy.objects.create( service=service, field=field_2, order=1 ) - LocalBaserowTableServiceSort.objects.create( - service=service, field=field_2, order=1, order_by="ASC" + LocalBaserowTableServiceAggregationSortBy.objects.create( + service=service, + sort_on="GROUP_BY", + reference=f"field_{field_2.id}", + order=1, + direction="ASC", ) RowHandler().create_rows( @@ -2425,8 +2679,12 @@ def test_grouped_aggregate_rows_service_dispatch_max_buckets_sort_on_series( LocalBaserowTableServiceAggregationGroupBy.objects.create( service=service, field=field_2, order=1 ) - LocalBaserowTableServiceSort.objects.create( - service=service, field=field, order=1, order_by="ASC" + LocalBaserowTableServiceAggregationSortBy.objects.create( + service=service, + sort_on="SERIES", + reference=f"field_{field.id}_sum", + order=1, + direction="ASC", ) RowHandler().create_rows( @@ -2512,39 +2770,47 @@ def test_grouped_aggregate_rows_service_dispatch_max_buckets_sort_on_primary_fie LocalBaserowTableServiceAggregationGroupBy.objects.create( service=service, field=None, order=1 ) - LocalBaserowTableServiceSort.objects.create( - service=service, field=field_2, order=1, order_by="ASC" + LocalBaserowTableServiceAggregationSortBy.objects.create( + service=service, + sort_on="GROUP_BY", + reference=f"field_{field_2.id}", + order=1, + direction="ASC", ) - rows = RowHandler().create_rows( - user, - table, - rows_values=[ - { - f"field_{field.id}": 40, - f"field_{field_2.id}": "Z", - }, - { - f"field_{field.id}": 20, - f"field_{field_2.id}": "K", - }, - { - f"field_{field.id}": 30, - f"field_{field_2.id}": "L", - }, - { - f"field_{field.id}": 10, - f"field_{field_2.id}": "A", - }, - { - f"field_{field.id}": 60, - f"field_{field_2.id}": "H", - }, - { - f"field_{field.id}": 50, - f"field_{field_2.id}": "M", - }, - ], + rows = ( + RowHandler() + .create_rows( + user, + table, + rows_values=[ + { + f"field_{field.id}": 40, + f"field_{field_2.id}": "Z", + }, + { + f"field_{field.id}": 20, + f"field_{field_2.id}": "K", + }, + { + f"field_{field.id}": 30, + f"field_{field_2.id}": "L", + }, + { + f"field_{field.id}": 10, + f"field_{field_2.id}": "A", + }, + { + f"field_{field.id}": 60, + f"field_{field_2.id}": "H", + }, + { + f"field_{field.id}": 50, + f"field_{field_2.id}": "M", + }, + ], + ) + .created_rows ) dispatch_context = FakeDispatchContext() @@ -2575,3 +2841,169 @@ def test_grouped_aggregate_rows_service_dispatch_max_buckets_sort_on_primary_fie }, ], } + + +@pytest.mark.django_db +def test_grouped_aggregate_rows_service_export_serialized( + data_fixture, +): + user = data_fixture.create_user() + dashboard = data_fixture.create_dashboard_application(user=user) + table = data_fixture.create_database_table(user=user) + field = data_fixture.create_number_field(table=table) + field_2 = data_fixture.create_number_field(table=table) + field_3 = data_fixture.create_number_field(table=table) + view = data_fixture.create_grid_view(user=user, table=table) + integration = data_fixture.create_local_baserow_integration( + application=dashboard, user=user + ) + service = data_fixture.create_service( + LocalBaserowGroupedAggregateRows, + integration=integration, + table=table, + view=view, + ) + LocalBaserowTableServiceAggregationSeries.objects.create( + service=service, field=field, aggregation_type="sum", order=1 + ) + LocalBaserowTableServiceAggregationSeries.objects.create( + service=service, field=field_2, aggregation_type="min", order=2 + ) + LocalBaserowTableServiceAggregationSeries.objects.create( + service=service, field=field_3, aggregation_type="max", order=3 + ) + LocalBaserowTableServiceAggregationGroupBy.objects.create( + service=service, field=field_3, order=1 + ) + LocalBaserowTableServiceAggregationSortBy.objects.create( + service=service, + sort_on="SERIES", + reference=f"field_{field.id}_sum", + order=1, + direction="ASC", + ) + LocalBaserowTableServiceAggregationSortBy.objects.create( + service=service, + sort_on="SERIES", + reference=f"field_{field_2.id}_min", + order=1, + direction="ASC", + ) + + result = LocalBaserowGroupedAggregateRowsUserServiceType().export_serialized( + service, import_export_config=None, files_zip=None, storage=None, cache=None + ) + + assert result == { + "filter_type": "AND", + "filters": [], + "id": service.id, + "integration_id": service.integration.id, + "service_aggregation_group_bys": [ + {"field_id": field_3.id}, + ], + "service_aggregation_series": [ + {"aggregation_type": "sum", "field_id": field.id}, + {"aggregation_type": "min", "field_id": field_2.id}, + {"aggregation_type": "max", "field_id": field_3.id}, + ], + "service_aggregation_sorts": [ + { + "direction": "ASC", + "reference": f"field_{field.id}_sum", + "sort_on": "SERIES", + }, + { + "direction": "ASC", + "reference": f"field_{field_2.id}_min", + "sort_on": "SERIES", + }, + ], + "table_id": table.id, + "type": "local_baserow_grouped_aggregate_rows", + "view_id": view.id, + } + + +@pytest.mark.django_db +def test_grouped_aggregate_rows_service_import_serialized(data_fixture): + user = data_fixture.create_user() + dashboard = data_fixture.create_dashboard_application(user=user) + table = data_fixture.create_database_table(user=user) + field = data_fixture.create_number_field(table=table) + field_2 = data_fixture.create_number_field(table=table) + field_3 = data_fixture.create_number_field(table=table) + view = data_fixture.create_grid_view(user=user, table=table) + integration = data_fixture.create_local_baserow_integration( + application=dashboard, user=user + ) + + serialized_service = { + "filter_type": "AND", + "filters": [], + "id": 999, + "integration_id": integration.id, + "service_aggregation_group_bys": [ + {"field_id": field_3.id}, + ], + "service_aggregation_series": [ + {"aggregation_type": "sum", "field_id": field.id}, + {"aggregation_type": "min", "field_id": field_2.id}, + {"aggregation_type": "max", "field_id": field_3.id}, + ], + "service_aggregation_sorts": [ + { + "direction": "ASC", + "reference": f"field_{field.id}_sum", + "sort_on": "SERIES", + }, + { + "direction": "DESC", + "reference": f"field_{field_2.id}_min", + "sort_on": "SERIES", + }, + ], + "table_id": table.id, + "type": "local_baserow_grouped_aggregate_rows", + "view_id": view.id, + } + id_mapping = {} + + instance = LocalBaserowGroupedAggregateRowsUserServiceType().import_serialized( + parent=integration, + serialized_values=serialized_service, + id_mapping=id_mapping, + import_formula=Mock(), + ) + + assert instance.content_type == ContentType.objects.get_for_model( + LocalBaserowGroupedAggregateRows + ) + assert instance.filter_type == "AND" + assert instance.service_filters.count() == 0 + assert instance.id != 999 + assert instance.integration_id == integration.id + assert instance.table_id == table.id + assert instance.view_id == view.id + + series = instance.service_aggregation_series.all() + assert series.count() == 3 + assert series[0].aggregation_type == "sum" + assert series[0].field_id == field.id + assert series[1].aggregation_type == "min" + assert series[1].field_id == field_2.id + assert series[2].aggregation_type == "max" + assert series[2].field_id == field_3.id + + group_bys = instance.service_aggregation_group_bys.all() + assert group_bys.count() == 1 + assert group_bys[0].field_id == field_3.id + + sorts = instance.service_aggregation_sorts.all() + assert sorts.count() == 2 + assert sorts[0].direction == "ASC" + assert sorts[0].sort_on == "SERIES" + assert sorts[0].reference == f"field_{field.id}_sum" + assert sorts[1].direction == "DESC" + assert sorts[1].sort_on == "SERIES" + assert sorts[1].reference == f"field_{field_2.id}_min" diff --git a/enterprise/backend/tests/baserow_enterprise_tests/integrations/local_baserow/test_user_source_types.py b/enterprise/backend/tests/baserow_enterprise_tests/integrations/local_baserow/test_user_source_types.py index 35067c202..290b499cb 100644 --- a/enterprise/backend/tests/baserow_enterprise_tests/integrations/local_baserow/test_user_source_types.py +++ b/enterprise/backend/tests/baserow_enterprise_tests/integrations/local_baserow/test_user_source_types.py @@ -1148,7 +1148,7 @@ def test_public_dispatch_data_source_with_ab_user_using_user_source( refresh_token = user_source_user.get_refresh_token() access_token = refresh_token.access_token - published_page = domain1.published_to.page_set.first() + published_page = domain1.published_to.visible_pages.first() published_data_source = published_page.datasource_set.first() url = reverse( diff --git a/enterprise/backend/tests/baserow_enterprise_tests/sso/test_sso_utils.py b/enterprise/backend/tests/baserow_enterprise_tests/sso/test_sso_utils.py index a9e4a0316..6ae15d15e 100644 --- a/enterprise/backend/tests/baserow_enterprise_tests/sso/test_sso_utils.py +++ b/enterprise/backend/tests/baserow_enterprise_tests/sso/test_sso_utils.py @@ -1,4 +1,10 @@ -from baserow_enterprise.api.sso.utils import get_valid_frontend_url +import pytest + +from baserow_enterprise.api.sso.utils import ( + get_valid_frontend_url, + redirect_user_on_success, + urlencode_user_tokens, +) def test_get_valid_front_url(): @@ -98,3 +104,22 @@ def test_get_valid_front_url_w_params(): ) == "http://localhost:3000/dashboard?test=value" ) + + +@pytest.mark.django_db() +def test_urlencode_user_tokens(enterprise_data_fixture): + user = enterprise_data_fixture.create_user() + url = urlencode_user_tokens("http://localhost:3000/dashboard", user) + assert "token=" in url + assert "user_session=" in url + + +@pytest.mark.django_db() +def test_redirect_user_on_success(enterprise_data_fixture): + user = enterprise_data_fixture.create_user() + response = redirect_user_on_success(user) + assert response.status_code == 302 + assert response.has_header("Location") + location = response.headers["Location"] + assert "token=" in location + assert "user_session=" in location diff --git a/enterprise/backend/tests/baserow_enterprise_tests/webhooks/__init__.py b/enterprise/backend/tests/baserow_enterprise_tests/webhooks/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/enterprise/backend/tests/baserow_enterprise_tests/webhooks/test_webhook_event_types.py b/enterprise/backend/tests/baserow_enterprise_tests/webhooks/test_webhook_event_types.py new file mode 100644 index 000000000..9aaf20bd0 --- /dev/null +++ b/enterprise/backend/tests/baserow_enterprise_tests/webhooks/test_webhook_event_types.py @@ -0,0 +1,443 @@ +from unittest.mock import MagicMock, patch + +from django.db import transaction +from django.test.utils import override_settings + +import pytest +import responses + +from baserow.contrib.database.rows.handler import RowHandler +from baserow.contrib.database.webhooks.handler import WebhookHandler +from baserow.contrib.database.webhooks.registries import webhook_event_type_registry +from baserow.core.redis import WebhookRedisQueue + + +@pytest.mark.django_db() +def test_rows_enter_view_event_type(enterprise_data_fixture): + user = enterprise_data_fixture.create_user() + table = enterprise_data_fixture.create_database_table(user=user) + view = enterprise_data_fixture.create_grid_view(table=table) + field = enterprise_data_fixture.create_text_field( + table=table, primary=True, name="Test 1" + ) + + model = table.get_model() + row = model.objects.create() + webhook = enterprise_data_fixture.create_table_webhook( + table=table, + request_method="POST", + url="http://localhost", + use_user_field_names=False, + ) + payload = webhook_event_type_registry.get("view.rows_entered").get_payload( + event_id="1", webhook=webhook, view=view, row_ids=[row.id] + ) + serialized_view = { + "id": view.id, + "table_id": table.id, + "order": 0, + "type": "grid", + "name": view.name, + "table": { + "id": table.id, + "order": 0, + "name": table.name, + "database_id": table.database_id, + }, + "type": "grid", + "filters_disabled": False, + "show_logo": True, + "allow_public_export": False, + "public_view_has_password": False, + "filter_type": "AND", + "ownership_type": "collaborative", + "owned_by_id": None, + } + expected_payload = { + "table_id": table.id, + "database_id": table.database_id, + "workspace_id": table.database.workspace_id, + "event_id": "1", + "event_type": "view.rows_entered", + "total_count": 1, + "view": serialized_view, + "row_ids": [row.id], + } + + assert payload == expected_payload + + paginated_payload, _ = webhook_event_type_registry.get( + "view.rows_entered" + ).paginate_payload(webhook, "1", payload) + + assert paginated_payload == { + "table_id": table.id, + "database_id": table.database_id, + "workspace_id": table.database.workspace_id, + "event_id": "1", + "event_type": "view.rows_entered", + "total_count": 1, + "view": serialized_view, + "fields": ["id", "order", field.db_column], + "rows": [ + { + "id": 1, + "order": "1.00000000000000000000", + field.db_column: None, + } + ], + } + + webhook.use_user_field_names = True + webhook.save() + payload = webhook_event_type_registry.get("view.rows_entered").get_payload( + event_id="1", webhook=webhook, view=view, row_ids=[row.id] + ) + assert payload == expected_payload + + paginated_payload, _ = webhook_event_type_registry.get( + "view.rows_entered" + ).paginate_payload(webhook, "1", payload) + + assert paginated_payload == { + "table_id": table.id, + "database_id": table.database_id, + "workspace_id": table.database.workspace_id, + "event_id": "1", + "event_type": "view.rows_entered", + "total_count": 1, + "view": serialized_view, + "fields": ["id", "order", "Test 1"], + "rows": [ + { + "id": 1, + "order": "1.00000000000000000000", + "Test 1": None, + } + ], + } + + +@pytest.mark.django_db(transaction=True) +@override_settings(DEBUG=True) +@patch("baserow.contrib.database.webhooks.registries.call_webhook") +def test_rows_enter_view_event_type_require_enterprise_license( + mock_call_webhook, enterprise_data_fixture +): + user = enterprise_data_fixture.create_user() + table = enterprise_data_fixture.create_database_table(user=user) + view = enterprise_data_fixture.create_grid_view(table=table) + with transaction.atomic(): + webhook = WebhookHandler().create_table_webhook( + user=user, + table=table, + url="http://localhost/", + include_all_events=False, + events=["view.rows_entered"], + event_config=[{"event_type": "view.rows_entered", "views": [view.id]}], + headers={"Baserow-header-1": "Value 1"}, + ) + + RowHandler().force_create_rows(user=user, table=table, rows_values=[{}]) + + mock_call_webhook.delay.assert_not_called() + + # From now on, the webhook should be called. + enterprise_data_fixture.enable_enterprise() + with transaction.atomic(): + RowHandler().force_create_rows(user=user, table=table, rows_values=[{}]) + + mock_call_webhook.delay.assert_called_once() + mock_call_webhook.reset_mock() + + enterprise_data_fixture.delete_all_licenses() + with transaction.atomic(): + RowHandler().force_create_rows(user=user, table=table, rows_values=[{}]) + + mock_call_webhook.delay.assert_not_called() + + +@pytest.mark.django_db(transaction=True) +@override_settings(DEBUG=True) +@patch("baserow.contrib.database.webhooks.registries.call_webhook") +def test_rows_enter_view_event_type_not_triggerd_with_include_all_events( + mock_call_webhook, enterprise_data_fixture, enable_enterprise +): + user = enterprise_data_fixture.create_user() + table = enterprise_data_fixture.create_database_table(user=user) + view = enterprise_data_fixture.create_grid_view(table=table) + + with transaction.atomic(): + webhook = WebhookHandler().create_table_webhook( + user=user, table=table, url="http://localhost/", include_all_events=True + ) + + RowHandler().force_create_rows(user=user, table=table, rows_values=[{}]) + + assert mock_call_webhook.delay.call_count == 1 + assert mock_call_webhook.delay.call_args[1]["event_type"] == "rows.created" + + +@pytest.mark.django_db() +def test_rows_enter_view_event_event_type_test_payload(enterprise_data_fixture): + user = enterprise_data_fixture.create_user() + table = enterprise_data_fixture.create_database_table(user=user) + field = enterprise_data_fixture.create_text_field( + table=table, primary=True, name="Test 1" + ) + + model = table.get_model() + webhook = enterprise_data_fixture.create_table_webhook( + table=table, + request_method="POST", + url="http://localhost", + use_user_field_names=False, + ) + webhook_event_type = webhook_event_type_registry.get("view.rows_entered") + payload = webhook_event_type.get_test_call_payload(table, model, "1", webhook) + serialized_view = { + "id": 0, + "table_id": table.id, + "order": 1, + "type": "grid", + "name": "View", + "table": { + "id": table.id, + "order": 0, + "name": table.name, + "database_id": table.database_id, + }, + "type": "grid", + "filters_disabled": False, + "show_logo": True, + "allow_public_export": False, + "public_view_has_password": False, + "filter_type": "AND", + "ownership_type": "collaborative", + "owned_by_id": None, + } + assert payload == { + "table_id": table.id, + "database_id": table.database_id, + "workspace_id": table.database.workspace_id, + "event_id": "1", + "event_type": "view.rows_entered", + "total_count": 1, + "view": serialized_view, + "row_ids": [0], + } + + +@pytest.mark.django_db(transaction=True) +@override_settings(DEBUG=True) +@patch("baserow.contrib.database.webhooks.registries.call_webhook") +def test_rows_enter_view_event_type_not_called_without_view( + mock_call_webhook, enterprise_data_fixture, enable_enterprise +): + user = enterprise_data_fixture.create_user() + table = enterprise_data_fixture.create_database_table(user=user) + view = enterprise_data_fixture.create_grid_view(table=table) + + with transaction.atomic(): # No views + webhook = WebhookHandler().create_table_webhook( + user=user, + table=table, + url="http://localhost/", + include_all_events=False, + events=["view.rows_entered"], + event_config=[{"event_type": "view.rows_entered", "views": []}], + headers={"Baserow-header-1": "Value 1"}, + ) + + RowHandler().force_create_rows(user=user, table=table, rows_values=[{}]) + + mock_call_webhook.delay.assert_not_called() + + with transaction.atomic(): # Now with a view + WebhookHandler().update_table_webhook( + user=user, + webhook=webhook, + events=["view.rows_entered"], + event_config=[{"event_type": "view.rows_entered", "views": [view.id]}], + headers={"Baserow-header-1": "Value 1"}, + ) + + RowHandler().force_create_rows(user=user, table=table, rows_values=[{}]) + + mock_call_webhook.delay.assert_called_once() + + +@pytest.mark.django_db(transaction=True) +@override_settings(DEBUG=True) +@patch("baserow.contrib.database.webhooks.registries.call_webhook") +def test_rows_enter_view_event_type_called_once_per_view( + mock_call_webhook, enterprise_data_fixture, enable_enterprise +): + user = enterprise_data_fixture.create_user() + table = enterprise_data_fixture.create_database_table(user=user) + view_a = enterprise_data_fixture.create_grid_view(table=table) + view_b = enterprise_data_fixture.create_grid_view(table=table) + + with transaction.atomic(): + WebhookHandler().create_table_webhook( + user=user, + table=table, + url="http://localhost/", + include_all_events=False, + events=["view.rows_entered"], + event_config=[ + {"event_type": "view.rows_entered", "views": [view_a.id, view_b.id]} + ], + headers={"Baserow-header-1": "Value 1"}, + ) + + RowHandler().force_create_rows(user=user, table=table, rows_values=[{}]) + + assert mock_call_webhook.delay.call_count == 2 + + +@pytest.mark.django_db(transaction=True) +@override_settings(DEBUG=True) +@patch("baserow.contrib.database.webhooks.registries.call_webhook") +def test_rows_enter_view_event_type_only_right_webhook_is_called( + mock_call_webhook, enterprise_data_fixture, enable_enterprise +): + user = enterprise_data_fixture.create_user() + table_a = enterprise_data_fixture.create_database_table(user=user) + view_a = enterprise_data_fixture.create_grid_view(table=table_a) + + table_b = enterprise_data_fixture.create_database_table(user=user) + view_b = enterprise_data_fixture.create_grid_view(table=table_b) + + with transaction.atomic(): + WebhookHandler().create_table_webhook( + user=user, + table=table_a, + url="http://localhost/", + include_all_events=False, + events=["view.rows_entered"], + event_config=[{"event_type": "view.rows_entered", "views": [view_a.id]}], + headers={"Baserow-header-1": "Value 1"}, + ) + WebhookHandler().create_table_webhook( + user=user, + table=table_b, + url="http://localhost/", + include_all_events=False, + events=["view.rows_entered"], + event_config=[{"event_type": "view.rows_entered", "views": [view_b.id]}], + headers={"Baserow-header-1": "Value 1"}, + ) + + RowHandler().force_create_rows(user=user, table=table_a, rows_values=[{}]) + + assert mock_call_webhook.delay.call_count == 1 + + +@pytest.mark.django_db(transaction=True) +@responses.activate +@patch("baserow.contrib.database.webhooks.tasks.RedisQueue", WebhookRedisQueue) +@patch("baserow.contrib.database.webhooks.tasks.cache", MagicMock()) +@patch( + "baserow.contrib.database.webhooks.tasks.make_request_and_save_result", + side_effect=lambda *args, **kwargs: True, +) +@override_settings(DEBUG=True, BASEROW_WEBHOOK_ROWS_ENTER_VIEW_BATCH_SIZE=2) +def test_rows_enter_view_event_type_paginate_data( + mock_make_request, enterprise_data_fixture, enable_enterprise +): + user = enterprise_data_fixture.create_user() + table = enterprise_data_fixture.create_database_table(user=user) + text_field = enterprise_data_fixture.create_text_field(table=table, name="text") + view = enterprise_data_fixture.create_grid_view(table=table) + + responses.add(responses.POST, "http://localhost/", json={}, status=200) + + serialized_view = { + "id": view.id, + "table_id": table.id, + "order": 0, + "type": "grid", + "name": view.name, + "table": { + "id": table.id, + "order": 0, + "name": table.name, + "database_id": table.database_id, + }, + "type": "grid", + "filters_disabled": False, + "show_logo": True, + "allow_public_export": False, + "public_view_has_password": False, + "filter_type": "AND", + "ownership_type": "collaborative", + "owned_by_id": None, + } + expected_first_page_payload = { + "table_id": table.id, + "database_id": table.database_id, + "workspace_id": table.database.workspace_id, + "event_type": "view.rows_entered", + "offset": 0, + "total_count": 3, + "batch_id": 1, + "batch_size": 2, + "view": serialized_view, + "fields": ["id", "order", "text"], + "rows": [ + {"id": 1, "order": "1.00000000000000000000", "text": "a"}, + {"id": 2, "order": "2.00000000000000000000", "text": "b"}, + ], + } + + with transaction.atomic(): + WebhookHandler().create_table_webhook( + user=user, + table=table, + url="http://localhost/", + include_all_events=False, + events=["view.rows_entered"], + event_config=[{"event_type": "view.rows_entered", "views": [view.id]}], + headers={"Baserow-header-1": "Value 1"}, + use_user_field_names=True, + ) + + RowHandler().force_create_rows( + user=user, + table=table, + rows_values=[ + {text_field.db_column: "a"}, + {text_field.db_column: "b"}, + {text_field.db_column: "c"}, + ], + ) + + assert mock_make_request.call_count == 2 + first_call_args = mock_make_request.call_args_list[0][0] + event_id = first_call_args[1] + first_page_payload = first_call_args[6] + + # first batch + expected_first_page_payload["event_id"] = event_id + assert first_page_payload == expected_first_page_payload + + # second batch + second_call_args = mock_make_request.call_args_list[1][0] + second_page_payload = second_call_args[6] + assert second_page_payload == { + "event_id": event_id, + "table_id": table.id, + "database_id": table.database_id, + "workspace_id": table.database.workspace_id, + "event_type": "view.rows_entered", + "offset": 2, + "total_count": 3, + "batch_id": 2, + "batch_size": 1, + "view": serialized_view, + "fields": ["id", "order", "text"], + "rows": [ + {"id": 3, "order": "3.00000000000000000000", "text": "c"}, + ], + } diff --git a/enterprise/web-frontend/modules/baserow_enterprise/assets/scss/components/chart.scss b/enterprise/web-frontend/modules/baserow_enterprise/assets/scss/components/chart.scss index 172a17c31..6de5bd78a 100644 --- a/enterprise/web-frontend/modules/baserow_enterprise/assets/scss/components/chart.scss +++ b/enterprise/web-frontend/modules/baserow_enterprise/assets/scss/components/chart.scss @@ -1,3 +1,25 @@ .chart { max-height: 320px; } + +.chart__no-data { + display: flex; + justify-content: center; + align-items: center; + height: 100%; + padding: 10px 0; + flex-direction: column; + gap: 36px; +} + +.chart__no-data-dashed-line { + border-top: 1px dashed $palette-neutral-200; + width: 100%; + height: 1px; +} + +.chart__no-data-plain-line { + border-top: 1px solid $palette-neutral-200; + width: 100%; + height: 1px; +} diff --git a/enterprise/web-frontend/modules/baserow_enterprise/assets/scss/components/dashboard_chart_widget.scss b/enterprise/web-frontend/modules/baserow_enterprise/assets/scss/components/dashboard_chart_widget.scss index 254e3bd9b..6a3a4a9fb 100644 --- a/enterprise/web-frontend/modules/baserow_enterprise/assets/scss/components/dashboard_chart_widget.scss +++ b/enterprise/web-frontend/modules/baserow_enterprise/assets/scss/components/dashboard_chart_widget.scss @@ -1,3 +1,15 @@ .dashboard-chart-widget { - padding: 0 24px 24px; + // nothing +} + +.dashboard-chart-widget__content { + height: 280px; +} + +.dashboard-chart-widget__loading { + height: 341px; + + .dashboard-chart-widget--with-header-description & { + height: 362.8px; + } } diff --git a/enterprise/web-frontend/modules/baserow_enterprise/assets/scss/default.scss b/enterprise/web-frontend/modules/baserow_enterprise/assets/scss/default.scss index ce24697d8..6b3cba8ad 100644 --- a/enterprise/web-frontend/modules/baserow_enterprise/assets/scss/default.scss +++ b/enterprise/web-frontend/modules/baserow_enterprise/assets/scss/default.scss @@ -1,2 +1,2 @@ -@import "@baserow_premium/assets/scss/default"; -@import "components/all"; +@import '@baserow_premium/assets/scss/default'; +@import 'components/all'; diff --git a/enterprise/web-frontend/modules/baserow_enterprise/builder/components/elements/AuthFormElement.vue b/enterprise/web-frontend/modules/baserow_enterprise/builder/components/elements/AuthFormElement.vue index 70b7a6b0f..a32456890 100644 --- a/enterprise/web-frontend/modules/baserow_enterprise/builder/components/elements/AuthFormElement.vue +++ b/enterprise/web-frontend/modules/baserow_enterprise/builder/components/elements/AuthFormElement.vue @@ -53,9 +53,7 @@ export default { }, computed: { isAuthenticated() { - return this.$store.getters['userSourceUser/isAuthenticated']( - this.application - ) + return this.$store.getters['userSourceUser/isAuthenticated'](this.builder) }, isEditMode() { return this.mode === 'editing' diff --git a/enterprise/web-frontend/modules/baserow_enterprise/builder/components/elements/AuthFormElementForm.vue b/enterprise/web-frontend/modules/baserow_enterprise/builder/components/elements/AuthFormElementForm.vue index 97749cb2b..b7082012f 100644 --- a/enterprise/web-frontend/modules/baserow_enterprise/builder/components/elements/AuthFormElementForm.vue +++ b/enterprise/web-frontend/modules/baserow_enterprise/builder/components/elements/AuthFormElementForm.vue @@ -12,14 +12,11 @@ required class="margin-bottom-2" > - <Dropdown v-model="values.user_source_id" :show-search="false"> - <DropdownItem - v-for="userSource in userSources" - :key="userSource.id" - :name="userSource.name" - :value="userSource.id" - /> - </Dropdown> + <UserSourceDropdown + v-model="values.user_source_id" + :builder="builder" + :user-sources="userSources" + ></UserSourceDropdown> </FormGroup> <CustomStyle v-model="values.styles" @@ -45,10 +42,12 @@ import elementForm from '@baserow/modules/builder/mixins/elementForm' import CustomStyle from '@baserow/modules/builder/components/elements/components/forms/style/CustomStyle' import InjectedFormulaInput from '@baserow/modules/core/components/formula/InjectedFormulaInput' +import UserSourceDropdown from '@baserow/modules/builder/components/userSource/UserSourceDropdown' export default { name: 'AuthFormElementForm', components: { + UserSourceDropdown, CustomStyle, InjectedFormulaInput, }, @@ -69,9 +68,5 @@ export default { return this.$store.getters['userSource/getUserSources'](this.builder) }, }, - methods: {}, - validations() { - return {} - }, } </script> diff --git a/enterprise/web-frontend/modules/baserow_enterprise/components/EnterpriseFeatures.vue b/enterprise/web-frontend/modules/baserow_enterprise/components/EnterpriseFeatures.vue index 9611d68f5..7cb260b1f 100644 --- a/enterprise/web-frontend/modules/baserow_enterprise/components/EnterpriseFeatures.vue +++ b/enterprise/web-frontend/modules/baserow_enterprise/components/EnterpriseFeatures.vue @@ -35,6 +35,13 @@ <i class="iconoir-check premium-features__feature-icon"></i> {{ $t('enterpriseFeatures.coBranding') }} </li> + <li + v-if="!hiddenFeatures.includes(enterpriseFeatures.ADVANCED_WEBHOOKS)" + class="premium-features__feature" + > + <i class="iconoir-check premium-features__feature-icon"></i> + {{ $t('enterpriseFeatures.advancedWebhooks') }} + </li> <li v-if="!hiddenFeatures.includes(enterpriseFeatures.SUPPORT)" class="premium-features__feature" @@ -42,6 +49,13 @@ <i class="iconoir-check premium-features__feature-icon"></i> {{ $t('enterpriseFeatures.support') }} </li> + <li + v-if="!hiddenFeatures.includes(enterpriseFeatures.CHART_WIDGET)" + class="premium-features__feature" + > + <i class="iconoir-check premium-features__feature-icon"></i> + {{ $t('enterpriseFeatures.chartWidget') }} + </li> </ul> </template> diff --git a/enterprise/web-frontend/modules/baserow_enterprise/components/EnterpriseSettings.vue b/enterprise/web-frontend/modules/baserow_enterprise/components/EnterpriseSettings.vue index 65b580069..c59d2675e 100644 --- a/enterprise/web-frontend/modules/baserow_enterprise/components/EnterpriseSettings.vue +++ b/enterprise/web-frontend/modules/baserow_enterprise/components/EnterpriseSettings.vue @@ -79,10 +79,16 @@ import { notifyIf } from '@baserow/modules/core/utils/error' import UserFilesModal from '@baserow/modules/core/components/files/UserFilesModal' import { UploadFileUserFileUploadType } from '@baserow/modules/core/userFileUploadTypes' import EnterpriseFeatures from '@baserow_enterprise/features' +import { useVuelidate } from '@vuelidate/core' export default { name: 'EnterpriseSettings', components: { UserFilesModal }, + setup() { + return { + v$: useVuelidate({ $lazy: true }), + } + }, computed: { IMAGE_FILE_TYPES() { return IMAGE_FILE_TYPES diff --git a/enterprise/web-frontend/modules/baserow_enterprise/components/admin/forms/GitLabSettingsForm.vue b/enterprise/web-frontend/modules/baserow_enterprise/components/admin/forms/GitLabSettingsForm.vue index 4105d4650..875ffe201 100644 --- a/enterprise/web-frontend/modules/baserow_enterprise/components/admin/forms/GitLabSettingsForm.vue +++ b/enterprise/web-frontend/modules/baserow_enterprise/components/admin/forms/GitLabSettingsForm.vue @@ -13,6 +13,7 @@ size="large" :error="fieldHasErrors('name')" :placeholder="$t('oauthSettingsForm.providerNamePlaceholder')" + @blur="v$.values.name.$touch" ></FormInput> <template #error> @@ -33,6 +34,7 @@ size="large" :error="fieldHasErrors('base_url')" :placeholder="$t('oauthSettingsForm.baseUrlPlaceholder')" + @blur="v$.values.base_url.$touch" ></FormInput> <template #error> @@ -53,6 +55,7 @@ size="large" :error="fieldHasErrors('client_id')" :placeholder="$t('oauthSettingsForm.clientIdPlaceholder')" + @blur="v$.values.client_id.$touch" ></FormInput> <template #error> @@ -73,6 +76,7 @@ size="large" :placeholder="$t('oauthSettingsForm.secretPlaceholder')" :error="fieldHasErrors('secret')" + @blur="v$.values.secret.$touch" ></FormInput> <template #error> diff --git a/enterprise/web-frontend/modules/baserow_enterprise/components/admin/forms/OAuth2SettingsForm.vue b/enterprise/web-frontend/modules/baserow_enterprise/components/admin/forms/OAuth2SettingsForm.vue index aa0ef72cd..cb4164a9a 100644 --- a/enterprise/web-frontend/modules/baserow_enterprise/components/admin/forms/OAuth2SettingsForm.vue +++ b/enterprise/web-frontend/modules/baserow_enterprise/components/admin/forms/OAuth2SettingsForm.vue @@ -13,6 +13,7 @@ size="large" :error="fieldHasErrors('name')" :placeholder="$t('oauthSettingsForm.providerNamePlaceholder')" + @blur="v$.values.name.$touch" ></FormInput> <template #error> @@ -33,6 +34,7 @@ size="large" :error="fieldHasErrors('client_id')" :placeholder="$t('oauthSettingsForm.clientIdPlaceholder')" + @blur="v$.values.client_id.$touch" ></FormInput> <template #error> @@ -53,6 +55,7 @@ size="large" :error="fieldHasErrors('secret')" :placeholder="$t('oauthSettingsForm.secretPlaceholder')" + @blur="v$.values.secret.$touch" ></FormInput> <template #error> diff --git a/enterprise/web-frontend/modules/baserow_enterprise/components/admin/forms/OpenIdConnectSettingsForm.vue b/enterprise/web-frontend/modules/baserow_enterprise/components/admin/forms/OpenIdConnectSettingsForm.vue index cc70cb51e..39056c832 100644 --- a/enterprise/web-frontend/modules/baserow_enterprise/components/admin/forms/OpenIdConnectSettingsForm.vue +++ b/enterprise/web-frontend/modules/baserow_enterprise/components/admin/forms/OpenIdConnectSettingsForm.vue @@ -13,6 +13,7 @@ size="large" :error="fieldHasErrors('name')" :placeholder="$t('oauthSettingsForm.providerNamePlaceholder')" + @blur="v$.values.name.$touch" ></FormInput> <template #error> @@ -69,6 +70,7 @@ size="large" :error="fieldHasErrors('client_id')" :placeholder="$t('oauthSettingsForm.clientIdPlaceholder')" + @blur="v$.values.client_id.$touch" ></FormInput> <template #error> @@ -89,6 +91,7 @@ size="large" :error="fieldHasErrors('secret')" :placeholder="$t('oauthSettingsForm.secretPlaceholder')" + @blur="v$.values.secret.$touch" ></FormInput> <template #error> diff --git a/enterprise/web-frontend/modules/baserow_enterprise/components/admin/forms/SamlSettingsForm.vue b/enterprise/web-frontend/modules/baserow_enterprise/components/admin/forms/SamlSettingsForm.vue index fba290dd6..9f4a34161 100644 --- a/enterprise/web-frontend/modules/baserow_enterprise/components/admin/forms/SamlSettingsForm.vue +++ b/enterprise/web-frontend/modules/baserow_enterprise/components/admin/forms/SamlSettingsForm.vue @@ -3,7 +3,7 @@ <FormGroup small-label required - :error="fieldHasErrors('domain')" + :error="fieldHasErrors('domain') || !!serverErrors.domain" class="margin-bottom-2" > <template #label> @@ -21,12 +21,15 @@ ref="domain" v-model="v$.values.domain.$model" size="large" - :error="fieldHasErrors('domain') || serverErrors.domain" + :error="fieldHasErrors('domain') || !!serverErrors.domain" :placeholder="$t('samlSettingsForm.domainPlaceholder')" @input="onDomainInput()" + @blur="v$.values.domain.$touch" ></FormInput> <template #error> - {{ v$.values.domain.$errors[0]?.$message }} + {{ + v$.values.domain.$errors[0]?.$message || serverErrors.domain[0].error + }} </template> </FormGroup> @@ -41,13 +44,17 @@ ref="metadata" v-model="v$.values.metadata.$model" :rows="12" - :error="fieldHasErrors('metadata') || serverErrors.metadata" + :error="fieldHasErrors('metadata') || !!serverErrors.metadata" :placeholder="$t('samlSettingsForm.metadataPlaceholder')" @input="onMetadataInput()" + @blur="v$.values.metadata.$touch" ></FormTextarea> <template #error> - {{ v$.values.metadata.$errors[0]?.$message }} + {{ + v$.values.metadata.$errors[0]?.$message || + serverErrors.metadata[0].error + }} </template> </FormGroup> @@ -110,6 +117,7 @@ v-model="v$.values.email_attr_key.$model" :error="fieldHasErrors('email_attr_key')" :placeholder="defaultAttrs.email_attr_key" + @blur="v$.values.email_attr_key.$touch" ></FormInput> <template #helper> {{ $t('samlSettingsForm.emailAttrKeyHelper') }} @@ -131,6 +139,7 @@ v-model="v$.values.first_name_attr_key.$model" :error="fieldHasErrors('first_name_attr_key')" :placeholder="defaultAttrs.first_name_attr_key" + @blur="v$.values.first_name_attr_key.$touch" ></FormInput> <template #helper> {{ $t('samlSettingsForm.firstNameAttrKeyHelper') }} diff --git a/enterprise/web-frontend/modules/baserow_enterprise/components/admin/modals/AuditLogExportModal.vue b/enterprise/web-frontend/modules/baserow_enterprise/components/admin/modals/AuditLogExportModal.vue index df0d726ff..75aa8cae7 100644 --- a/enterprise/web-frontend/modules/baserow_enterprise/components/admin/modals/AuditLogExportModal.vue +++ b/enterprise/web-frontend/modules/baserow_enterprise/components/admin/modals/AuditLogExportModal.vue @@ -42,6 +42,7 @@ <DownloadLink :url="finishedJob.url" :filename="getExportedFilename(finishedJob)" + loading-class="button-icon--loading" > <template #default="{ loading: downloadLoading }"> <div v-if="downloadLoading" class="loading"></div> diff --git a/enterprise/web-frontend/modules/baserow_enterprise/components/dataSync/GitHubIssuesDataSyncForm.vue b/enterprise/web-frontend/modules/baserow_enterprise/components/dataSync/GitHubIssuesDataSyncForm.vue index b00d79efa..fd81bb37b 100644 --- a/enterprise/web-frontend/modules/baserow_enterprise/components/dataSync/GitHubIssuesDataSyncForm.vue +++ b/enterprise/web-frontend/modules/baserow_enterprise/components/dataSync/GitHubIssuesDataSyncForm.vue @@ -13,6 +13,7 @@ :error="fieldHasErrors('github_issues_owner')" :disabled="disabled" size="large" + @blur="v$.values.github_issues_owner.$touch" /> <template #error> <span> @@ -34,6 +35,7 @@ :error="fieldHasErrors('github_issues_repo')" :disabled="disabled" size="large" + @blur="v$.values.github_issues_repo.$touch" /> <template #error> {{ v$.values.github_issues_repo.$errors[0]?.$message }} @@ -47,16 +49,8 @@ :helper-text="$t('githubIssuesDataSync.apiTokenHelper')" small-label :protected-edit="update" - @enabled-protected-edit="allowedValues.push('github_issues_api_token')" - @disable-protected-edit=" - ;[ - allowedValues.splice( - allowedValues.indexOf('github_issues_api_token'), - 1 - ), - delete values['github_issues_api_token'], - ] - " + @enabled-protected-edit="values.github_issues_api_token = ''" + @disable-protected-edit="values.github_issues_api_token = undefined" > <FormInput v-model="v$.values.github_issues_api_token.$model" @@ -96,15 +90,16 @@ export default { return { v$: useVuelidate({ $lazy: true }) } }, data() { - const allowedValues = ['github_issues_owner', 'github_issues_repo'] - if (!this.update) { - allowedValues.push('github_issues_api_token') - } return { - allowedValues: ['github_issues_owner', 'github_issues_repo'], + allowedValues: [ + 'github_issues_owner', + 'github_issues_repo', + 'github_issues_api_token', + ], values: { github_issues_owner: '', github_issues_repo: '', + github_issues_api_token: this.update ? undefined : '', }, } }, @@ -127,7 +122,7 @@ export default { required: helpers.withMessage( this.$t('error.requiredField'), requiredIf(() => { - return this.allowedValues.includes('github_issues_api_token') + return this.values.github_issues_api_token !== undefined }) ), }, diff --git a/enterprise/web-frontend/modules/baserow_enterprise/components/dataSync/GitLabIssuesDataSyncForm.vue b/enterprise/web-frontend/modules/baserow_enterprise/components/dataSync/GitLabIssuesDataSyncForm.vue index daef43dd6..862a69c45 100644 --- a/enterprise/web-frontend/modules/baserow_enterprise/components/dataSync/GitLabIssuesDataSyncForm.vue +++ b/enterprise/web-frontend/modules/baserow_enterprise/components/dataSync/GitLabIssuesDataSyncForm.vue @@ -15,6 +15,7 @@ :error="fieldHasErrors('gitlab_url')" :disabled="disabled" @focus.once="$event.target.select()" + @blur="v$.values.gitlab_url.$touch" /> <template #error> {{ v$.values.gitlab_url.$errors[0]?.$message }} @@ -34,6 +35,7 @@ :error="fieldHasErrors('gitlab_project_id')" :disabled="disabled" size="large" + @blur="v$.values.gitlab_project_id.$touch" /> <template #error> {{ v$.values.gitlab_project_id.$errors[0]?.$message }} @@ -48,19 +50,15 @@ :helper-text="$t('gitlabIssuesDataSync.accessTokenHelper')" small-label :protected-edit="update" - @enabled-protected-edit="allowedValues.push('gitlab_access_token')" - @disable-protected-edit=" - ;[ - allowedValues.splice(allowedValues.indexOf('gitlab_access_token'), 1), - delete values['gitlab_access_token'], - ] - " + @enabled-protected-edit="values.gitlab_access_token = ''" + @disable-protected-edit="values.gitlab_access_token = undefined" > <FormInput v-model="v$.values.gitlab_access_token.$model" :error="fieldHasErrors('gitlab_access_token')" :disabled="disabled" size="large" + @blur="v$.values.gitlab_access_token.$touch" /> <template #error> {{ v$.values.gitlab_access_token.$errors[0]?.$message }} @@ -93,15 +91,17 @@ export default { return { v$: useVuelidate({ $lazy: true }) } }, data() { - const allowedValues = ['gitlab_url', 'gitlab_project_id'] - if (!this.update) { - allowedValues.push('gitlab_access_token') - } + const allowedValues = [ + 'gitlab_url', + 'gitlab_project_id', + 'gitlab_access_token', + ] return { allowedValues, values: { gitlab_url: 'https://gitlab.com', gitlab_project_id: '', + gitlab_access_token: this.update ? undefined : '', }, } }, @@ -125,7 +125,7 @@ export default { required: helpers.withMessage( this.$t('error.requiredField'), requiredIf(() => { - return this.allowedValues.includes('gitlab_access_token') + return this.values.gitlab_access_token !== undefined }) ), }, diff --git a/enterprise/web-frontend/modules/baserow_enterprise/components/dataSync/HubspotContactsDataSyncForm.vue b/enterprise/web-frontend/modules/baserow_enterprise/components/dataSync/HubspotContactsDataSyncForm.vue index 184eafa81..935bf3055 100644 --- a/enterprise/web-frontend/modules/baserow_enterprise/components/dataSync/HubspotContactsDataSyncForm.vue +++ b/enterprise/web-frontend/modules/baserow_enterprise/components/dataSync/HubspotContactsDataSyncForm.vue @@ -8,12 +8,15 @@ :helper-text="$t('hubspotContactsDataSync.accessTokenHelper')" :protected-edit="update" small-label + @enabled-protected-edit="values.hubspot_access_token = ''" + @disable-protected-edit="values.hubspot_access_token = undefined" > <FormInput v-model="v$.values.hubspot_access_token.$model" :error="fieldHasErrors('hubspot_access_token')" :disabled="disabled" size="large" + @blur="v$.values.hubspot_access_token.$touch" /> <template #error> {{ v$.values.hubspot_access_token.$errors[0]?.$message }} @@ -49,7 +52,7 @@ export default { return { allowedValues: ['hubspot_access_token'], values: { - hubspot_access_token: '', + hubspot_access_token: this.update ? undefined : '', }, } }, diff --git a/enterprise/web-frontend/modules/baserow_enterprise/components/dataSync/JiraIssuesDataSyncForm.vue b/enterprise/web-frontend/modules/baserow_enterprise/components/dataSync/JiraIssuesDataSyncForm.vue index d6e4c6393..fd487ab59 100644 --- a/enterprise/web-frontend/modules/baserow_enterprise/components/dataSync/JiraIssuesDataSyncForm.vue +++ b/enterprise/web-frontend/modules/baserow_enterprise/components/dataSync/JiraIssuesDataSyncForm.vue @@ -15,6 +15,7 @@ :error="fieldHasErrors('jira_url')" :disabled="disabled" @focus.once="$event.target.select()" + @blur="v$.values.jira_url.$touch" /> <template #error> {{ v$.values.jira_url.$errors[0]?.$message }} @@ -36,6 +37,7 @@ :error="fieldHasErrors('jira_username')" :disabled="disabled" @focus.once="$event.target.select()" + @blur="v$.values.jira_username.$touch" /> <template #error> {{ v$.values.jira_username.$errors[0]?.$message }} @@ -49,13 +51,8 @@ small-label class="margin-bottom-2" :protected-edit="update" - @enabled-protected-edit="allowedValues.push('jira_api_token')" - @disable-protected-edit=" - ;[ - allowedValues.splice(allowedValues.indexOf('jira_api_token'), 1), - delete values['jira_api_token'], - ] - " + @enabled-protected-edit="values.jira_api_token = ''" + @disable-protected-edit="values.jira_api_token = undefined" > <template #label>{{ $t('jiraIssuesDataSync.apiToken') }}</template> <FormInput @@ -65,6 +62,7 @@ :error="fieldHasErrors('jira_api_token')" :disabled="disabled" @focus.once="$event.target.select()" + @blur="v$.values.jira_api_token.$touch" /> <template #error> {{ v$.values.jira_api_token.$errors[0]?.$message }} @@ -111,17 +109,19 @@ export default { return { v$: useVuelidate({ $lazy: true }) } }, data() { - const allowedValues = ['jira_url', 'jira_username', 'jira_project_key'] - if (!this.update) { - allowedValues.push('jira_api_token') - } + const allowedValues = [ + 'jira_url', + 'jira_username', + 'jira_project_key', + 'jira_api_token', + ] return { allowedValues, values: { jira_url: '', jira_username: '', jira_project_key: '', - jira_api_token: '', + jira_api_token: this.update ? undefined : '', }, } }, @@ -145,7 +145,7 @@ export default { required: helpers.withMessage( this.$t('error.requiredField'), requiredIf(() => { - return this.allowedValues.includes('gitlab_access_token') + return this.values.jira_api_token !== undefined }) ), }, diff --git a/enterprise/web-frontend/modules/baserow_enterprise/components/notifications/PeriodicDataSyncDeactivatedNotification.vue b/enterprise/web-frontend/modules/baserow_enterprise/components/notifications/PeriodicDataSyncDeactivatedNotification.vue new file mode 100644 index 000000000..8b5c0066e --- /dev/null +++ b/enterprise/web-frontend/modules/baserow_enterprise/components/notifications/PeriodicDataSyncDeactivatedNotification.vue @@ -0,0 +1,29 @@ +<template> + <nuxt-link + class="notification-panel__notification-link" + :to="route" + @click.native="markAsReadAndHandleClick" + > + <div class="notification-panel__notification-content-title"> + <i18n path="periodicDataSyncDeactivatedNotification.body" tag="span"> + <template #name> + <strong>{{ notification.data.table_name }}</strong> + </template> + </i18n> + </div> + </nuxt-link> +</template> + +<script> +import notificationContent from '@baserow/modules/core/mixins/notificationContent' + +export default { + name: 'PeriodicDataSyncDeactivatedNotification', + mixins: [notificationContent], + methods: { + handleClick() { + this.$emit('close-panel') + }, + }, +} +</script> diff --git a/enterprise/web-frontend/modules/baserow_enterprise/dashboard/chartFieldFormatting.js b/enterprise/web-frontend/modules/baserow_enterprise/dashboard/chartFieldFormatting.js new file mode 100644 index 000000000..0248802c3 --- /dev/null +++ b/enterprise/web-frontend/modules/baserow_enterprise/dashboard/chartFieldFormatting.js @@ -0,0 +1,32 @@ +import { Registerable } from '@baserow/modules/core/registry' + +export class ChartFieldFormattingType extends Registerable { + constructor(...args) { + super(...args) + this.type = this.getType() + + if (this.type === null) { + throw new Error('The type has to be set.') + } + } + + formatGroupByFieldValue(field, value) { + return value ?? '' + } +} + +export class SingleSelectFormattingType extends ChartFieldFormattingType { + static getType() { + return 'single_select' + } + + formatGroupByFieldValue(field, value) { + const selectOption = field.select_options.find((item) => item.id === value) + + if (selectOption) { + return selectOption.value + } + + return value ?? '' + } +} diff --git a/enterprise/web-frontend/modules/baserow_enterprise/dashboard/components/data_source/AggregationGroupByForm.vue b/enterprise/web-frontend/modules/baserow_enterprise/dashboard/components/data_source/AggregationGroupByForm.vue index 7ad791a5a..2eacd906c 100644 --- a/enterprise/web-frontend/modules/baserow_enterprise/dashboard/components/data_source/AggregationGroupByForm.vue +++ b/enterprise/web-frontend/modules/baserow_enterprise/dashboard/components/data_source/AggregationGroupByForm.vue @@ -6,6 +6,7 @@ <Dropdown :value="aggregationGroupBy" :show-search="true" + :error="v$.aggregationGroupBy?.$error || false" fixed-items @change="groupByChangedByUser($event)" > @@ -22,6 +23,15 @@ </template> <script> +import { useVuelidate } from '@vuelidate/core' + +const includesIfSet = (array) => (value) => { + if (value === null || value === undefined) { + return true + } + return array.includes(value) +} + export default { name: 'AggregationGroupByForm', props: { @@ -34,14 +44,22 @@ export default { required: true, }, }, + setup() { + return { v$: useVuelidate() } + }, data() { return { aggregationGroupBy: 'none', } }, computed: { + compatibleFields() { + return this.tableFields.filter((field) => + this.$registry.exists('groupedAggregationGroupedBy', field.type) + ) + }, groupByOptions() { - const tableFieldOptions = this.tableFields.map((field) => { + const tableFieldOptions = this.compatibleFields.map((field) => { return { name: field.name, value: field.id, @@ -65,6 +83,22 @@ export default { immediate: true, }, }, + mounted() { + this.v$.$touch() + }, + validations() { + const self = this + return { + aggregationGroupBy: { + isValidGroupBy: (value) => { + const validGroupByValues = self.groupByOptions.map( + (item) => item.value + ) + return includesIfSet(validGroupByValues)(value) + }, + }, + } + }, methods: { groupByChangedByUser(value) { this.aggregationGroupBy = value diff --git a/enterprise/web-frontend/modules/baserow_enterprise/dashboard/components/data_source/AggregationSeriesForm.vue b/enterprise/web-frontend/modules/baserow_enterprise/dashboard/components/data_source/AggregationSeriesForm.vue index ecdee18d9..eae2a4170 100644 --- a/enterprise/web-frontend/modules/baserow_enterprise/dashboard/components/data_source/AggregationSeriesForm.vue +++ b/enterprise/web-frontend/modules/baserow_enterprise/dashboard/components/data_source/AggregationSeriesForm.vue @@ -10,12 +10,12 @@ class="margin-bottom-2" > <Dropdown - v-model="values.aggregation_type" + :value="values.aggregation_type" :error="fieldHasErrors('aggregation_type')" - @change="v$.values.aggregation_type.$touch" + @change="aggregationTypeChanged" > <DropdownItem - v-for="aggregation in groupedAggregationTypes" + v-for="aggregation in aggregationTypesAvailableForSelection" :key="aggregation.getType()" :name="aggregation.getName()" :value="aggregation.getType()" @@ -33,11 +33,10 @@ <Dropdown v-model="values.field_id" :error="fieldHasErrors('field_id')" - :disabled="compatibleFields.length === 0" @change="v$.values.field_id.$touch" > <DropdownItem - v-for="field in compatibleFields" + v-for="field in fieldsAvailableForSelection" :key="field.id" :name="field.name" :value="field.id" @@ -47,7 +46,7 @@ </Dropdown> </FormGroup> </FormSection> - <FormSection> + <FormSection v-if="aggregationSeries.length > 1"> <ButtonText icon="iconoir-bin" type="secondary" @@ -75,6 +74,10 @@ export default { type: Array, required: true, }, + aggregationSeries: { + type: Array, + required: true, + }, seriesIndex: { type: Number, required: true, @@ -90,16 +93,42 @@ export default { field_id: null, aggregation_type: null, }, - emitValuesOnReset: false, + skipFirstValuesEmit: true, } }, computed: { groupedAggregationTypes() { - return this.$registry.getOrderedList('groupedAggregation') + const allAggregationTypes = + this.$registry.getOrderedList('groupedAggregation') + return allAggregationTypes.filter((aggType) => { + return this.tableFields.some((tableField) => + aggType.fieldIsCompatible(tableField) + ) + }) + }, + aggregationTypesAvailableForSelection() { + return this.groupedAggregationTypes.filter( + (aggregationType) => + this.isSeriesRepeated( + this.values.field_id, + aggregationType.getType() + ) === false || + this.values.aggregation_type === aggregationType.getType() + ) }, aggregationTypeNames() { return this.groupedAggregationTypes.map((aggType) => aggType.getType()) }, + usedSeries() { + return this.aggregationSeries + .filter( + (series) => + series.aggregation_type !== null && series.field_id !== null + ) + .map((series) => { + return `${series.field_id}_${series.aggregation_type}` + }) + }, compatibleFields() { if (!this.values.aggregation_type) { return [] @@ -112,36 +141,17 @@ export default { aggType.fieldIsCompatible(tableField) ) }, + fieldsAvailableForSelection() { + return this.compatibleFields.filter( + (field) => + this.isSeriesRepeated(field.id, this.values.aggregation_type) === + false || this.values.field_id === field.id + ) + }, compatibleTableFieldIds() { return this.compatibleFields.map((field) => field.id) }, }, - watch: { - 'values.aggregation_type': { - handler(aggregationType) { - if ( - aggregationType !== null && - aggregationType !== this.defaultValues.aggregation_type && - this.values.field_id !== null - ) { - // If both the field and aggregation type - // are selected, check if they are still - // compatible. - const aggType = this.$registry.get( - 'groupedAggregation', - aggregationType - ) - const field = this.tableFields.filter( - (field) => field.id === this.values.field_id - ) - if (!aggType.fieldIsCompatible(field)) { - this.values.field_id = null - } - } - }, - immediate: true, - }, - }, mounted() { this.v$.$touch() }, @@ -167,10 +177,30 @@ export default { } }, methods: { + isSeriesRepeated(fieldId, aggregationType) { + if (fieldId === null || aggregationType === null) { + return false + } + return this.usedSeries.includes(`${fieldId}_${aggregationType}`) + }, fieldIconClass(field) { const fieldType = this.$registry.get('field', field.type) return fieldType.iconClass }, + aggregationTypeChanged(aggregationType) { + this.values.aggregation_type = aggregationType + const aggType = this.$registry.get('groupedAggregation', aggregationType) + const field = this.tableFields.find( + (field) => field.id === this.values.field_id + ) + if ( + (field && !aggType.fieldIsCompatible(field)) || + this.fieldHasErrors('field_id') + ) { + this.values.field_id = null + } + this.v$.values.aggregation_type.$touch() + }, }, } </script> diff --git a/enterprise/web-frontend/modules/baserow_enterprise/dashboard/components/data_source/AggregationSortByForm.vue b/enterprise/web-frontend/modules/baserow_enterprise/dashboard/components/data_source/AggregationSortByForm.vue index c2825a20c..041b2effc 100644 --- a/enterprise/web-frontend/modules/baserow_enterprise/dashboard/components/data_source/AggregationSortByForm.vue +++ b/enterprise/web-frontend/modules/baserow_enterprise/dashboard/components/data_source/AggregationSortByForm.vue @@ -4,30 +4,32 @@ class="margin-bottom-2" > <Dropdown - :value="sortByField" + :value="sortReference" :show-search="true" fixed-items class="margin-bottom-1" - :error="v$.sortByField?.$error || false" - @change="sortByFieldChangedByUser($event)" + :error="v$.sortReference?.$error || false" + @change="sortReferenceChangedByUser($event)" > <DropdownItem :name="$t('aggregationSortByForm.none')" :value="null" ></DropdownItem> <DropdownItem - v-for="field in allowedSortFields" - :key="field.id" - :name="field.name" - :value="field.id" - :icon="fieldIconClass(field)" + v-for="allowedSortReference in allowedSortReferences" + :key="allowedSortReference.reference" + :name="allowedSortReference.name" + :value="allowedSortReference.reference" + :icon="fieldIconClass(allowedSortReference.field)" > </DropdownItem> </Dropdown> <SegmentControl - :active-index="orderByIndex" - :segments="orderByOptions" - :initial-active-index="orderByIndex" + v-if="aggregationSorts.length > 0 && v$.sortReference?.$error === false" + ref="sortDirectionSegment" + :active-index="orderDirectionIndex" + :segments="orderDirectionOptions" + :initial-active-index="orderDirectionIndex" @update:activeIndex="orderByChangedByUser" ></SegmentControl> </FormSection> @@ -46,7 +48,7 @@ const includesIfSet = (array) => (value) => { export default { name: 'AggregationSortByForm', props: { - allowedSortFields: { + allowedSortReferences: { type: Array, required: true, }, @@ -60,12 +62,12 @@ export default { }, data() { return { - sortByField: null, - orderByIndex: 0, + sortReference: null, + orderDirectionIndex: 0, } }, computed: { - orderByOptions() { + orderDirectionOptions() { return [ { label: this.$t('aggregationSortByForm.ascending'), value: 'ASC' }, { label: this.$t('aggregationSortByForm.descending'), value: 'DESC' }, @@ -76,13 +78,16 @@ export default { aggregationSorts: { handler(aggregationSorts) { if (aggregationSorts.length !== 0) { - this.sortByField = aggregationSorts[0].field - this.orderByIndex = this.orderByOptions.findIndex( - (item) => item.value === aggregationSorts[0].order_by + this.sortReference = aggregationSorts[0].reference + this.orderDirectionIndex = this.orderDirectionOptions.findIndex( + (item) => item.value === aggregationSorts[0].direction ) + if (this.$refs.sortDirectionSegment) { + this.$refs.sortDirectionSegment.reset() + } } else { - this.sortByField = null - this.orderByIndex = 0 + this.sortReference = null + this.orderDirectionIndex = 0 } }, immediate: true, @@ -94,27 +99,38 @@ export default { validations() { const self = this return { - sortByField: { - isValidSortFieldId: (value) => { - const ids = self.allowedSortFields.map((item) => item.id) - return includesIfSet(ids)(value) + sortReference: { + isValidSortReference: (value) => { + const sortReferences = self.allowedSortReferences.map( + (item) => item.reference + ) + return includesIfSet(sortReferences)(value) }, }, } }, methods: { - sortByFieldChangedByUser(value) { - this.sortByField = value - this.$emit('value-changed', { - field: value, - order_by: this.orderByOptions[this.orderByIndex].value, - }) + sortReferenceChangedByUser(value) { + this.sortReference = value + this.emitValue() }, orderByChangedByUser(index) { - this.orderByIndex = index + this.orderDirectionIndex = index + this.emitValue() + }, + emitValue() { + if (this.sortReference === null) { + this.$emit('value-changed', null) + return + } + + const chosenReference = this.allowedSortReferences.find( + (item) => item.reference === this.sortReference + ) this.$emit('value-changed', { - field: this.sortByField, - order_by: this.orderByOptions[index].value, + sort_on: chosenReference.sort_on, + reference: chosenReference.reference, + direction: this.orderDirectionOptions[this.orderDirectionIndex].value, }) }, fieldIconClass(field) { diff --git a/enterprise/web-frontend/modules/baserow_enterprise/dashboard/components/data_source/GroupedAggregateRowsDataSourceForm.vue b/enterprise/web-frontend/modules/baserow_enterprise/dashboard/components/data_source/GroupedAggregateRowsDataSourceForm.vue index 133da433d..040d67942 100644 --- a/enterprise/web-frontend/modules/baserow_enterprise/dashboard/components/data_source/GroupedAggregateRowsDataSourceForm.vue +++ b/enterprise/web-frontend/modules/baserow_enterprise/dashboard/components/data_source/GroupedAggregateRowsDataSourceForm.vue @@ -76,15 +76,23 @@ class="margin-bottom-2" > <template #title-slot> - <ButtonText icon="iconoir-plus" type="secondary" @click="addSeries">{{ - $t('groupedAggregateRowsDataSourceForm.addSeries') - }}</ButtonText> + <ButtonText + icon="iconoir-plus" + type="secondary" + :disabled="!canAddSeries" + tooltip-position="bottom-left" + @click="addSeries" + > + {{ $t('groupedAggregateRowsDataSourceForm.addSeries') }} + </ButtonText> </template> <div class="margin-bottom-2"></div> <AggregationSeriesForm v-for="(series, index) in values.aggregation_series" + ref="aggregationSeriesForms" :key="index" :table-fields="tableFields" + :aggregation-series="values.aggregation_series" :series-index="index" :default-values="series" @delete-series="deleteSeries" @@ -101,8 +109,8 @@ </AggregationGroupByForm> <AggregationSortByForm v-if="values.table_id && !fieldHasErrors('table_id')" - :aggregation-sorts="values.sortings" - :allowed-sort-fields="allowedSortFields" + :aggregation-sorts="values.aggregation_sorts" + :allowed-sort-references="allowedSortReferences" @value-changed="onSortByUpdated($event)" > </AggregationSortByForm> @@ -161,18 +169,18 @@ export default { 'view_id', 'aggregation_series', 'aggregation_group_bys', - 'sortings', + 'aggregation_sorts', ], values: { table_id: null, view_id: null, aggregation_series: [], aggregation_group_bys: [], - sortings: [], + aggregation_sorts: [], }, tableLoading: false, databaseSelectedId: null, - emitValuesOnReset: false, + skipFirstValuesEmit: true, } }, computed: { @@ -201,6 +209,9 @@ export default { tableFields() { return this.tableSelected?.fields || [] }, + primaryTableField() { + return this.tableFields.find((item) => item.primary === true) + }, tableFieldIds() { return this.tableFields.map((field) => field.id) }, @@ -214,28 +225,66 @@ export default { tableViewIds() { return this.tableViews.map((view) => view.id) }, - allowedSortFields() { - const seriesFieldIds = this.values.aggregation_series.map( - (item) => item.field_id + allowedSortReferences() { + const seriesSortReferences = this.values.aggregation_series + .filter( + (item) => + item.field_id && + item.aggregation_type && + this.getTableFieldById(item.field_id) + ) + .map((item) => { + const field = this.getTableFieldById(item.field_id) + return { + sort_on: 'SERIES', + reference: `field_${item.field_id}_${item.aggregation_type}`, + field, + name: `${field.name} (${this.getAggregationName( + item.aggregation_type + )})`, + } + }) + const groupBySortReferences = this.values.aggregation_group_bys.reduce( + (acc, item) => { + const field = + item.field_id === null + ? this.primaryTableField + : this.getTableFieldById(item.field_id) + + if (field !== undefined) { + acc.push({ + sort_on: 'GROUP_BY', + reference: `field_${field.id}`, + field, + name: field.name, + }) + } + + return acc + }, + [] ) - const groupByFieldIds = this.values.aggregation_group_bys.map( - (item) => item.field_id + return seriesSortReferences.concat(groupBySortReferences) + }, + canAddSeries() { + return ( + this.values.aggregation_series.length < + this.$config.BASEROW_ENTERPRISE_GROUPED_AGGREGATE_SERVICE_MAX_SERIES ) - const allowedFieldIds = seriesFieldIds.concat(groupByFieldIds) - return this.tableFields.filter((item) => { - return allowedFieldIds.includes(item.id) - }) }, }, watch: { dataSource: { async handler(values) { + this.setEmitValues(false) // Reset the form to set default values // again after a different widget is selected await this.reset(true) // Run form validation so that // problems are highlighted immediately this.v$.$touch() + await this.$nextTick() + this.setEmitValues(true) }, deep: true, }, @@ -277,22 +326,50 @@ export default { } }, methods: { - changeTableId(tableId) { - this.values.table_id = tableId - this.values.view_id = null - this.values.aggregation_series = [] - this.values.aggregation_group_bys = [] - this.values.sortings = [] - this.v$.values.table_id.$touch() + getTableFieldById(fieldId) { + return this.tableFields.find((tableField) => { + return tableField.id === fieldId + }) }, - addSeries() { + getAggregationName(aggregationType) { + const aggType = this.$registry.get('groupedAggregation', aggregationType) + return aggType.getName() + }, + changeTableId(tableId) { + if (this.values.table_id !== tableId) { + this.values.table_id = tableId + this.values.view_id = null + this.values.aggregation_series = [ + { field_id: null, aggregation_type: '' }, + ] + this.values.aggregation_group_bys = [] + this.values.aggregation_sorts = [] + this.v$.values.table_id.$touch() + } + }, + async addSeries() { + this.setEmitValues(false) this.values.aggregation_series.push({ field_id: null, aggregation_type: '', }) + this.$emit('values-changed', { + aggregation_series: this.values.aggregation_series, + }) + await this.$nextTick() + this.setEmitValues(true) }, - deleteSeries(index) { + async deleteSeries(index) { + this.setEmitValues(false) this.values.aggregation_series.splice(index, 1) + await this.$nextTick() + this.$refs.aggregationSeriesForms.forEach((form) => form.reset()) + this.$emit('values-changed', { + aggregation_series: this.values.aggregation_series, + }) + await this.$nextTick() + this.setEmitValues(true) + this.v$.$touch() }, onAggregationSeriesUpdated(index, aggregationSeriesValues) { const updatedAggregationSeries = this.values.aggregation_series @@ -312,10 +389,10 @@ export default { aggregation_group_bys: aggregationGroupBys, }) }, - onSortByUpdated(sortBy) { - const aggregationSorts = sortBy.field !== null ? [sortBy] : [] + onSortByUpdated(sort) { + const aggregationSorts = sort !== null ? [sort] : [] this.$emit('values-changed', { - sortings: aggregationSorts, + aggregation_sorts: aggregationSorts, }) }, }, diff --git a/enterprise/web-frontend/modules/baserow_enterprise/dashboard/components/widget/Chart.vue b/enterprise/web-frontend/modules/baserow_enterprise/dashboard/components/widget/Chart.vue index 937e69574..63ecb1ab8 100644 --- a/enterprise/web-frontend/modules/baserow_enterprise/dashboard/components/widget/Chart.vue +++ b/enterprise/web-frontend/modules/baserow_enterprise/dashboard/components/widget/Chart.vue @@ -1,5 +1,20 @@ <template> - <Bar id="chart-id" :options="chartOptions" :data="chartData" class="chart" /> + <Bar + v-if="chartData.datasets.length > 0" + id="chart-id" + :options="chartOptions" + :data="chartData" + class="chart" + /> + + <div v-else class="chart__no-data"> + <span class="chart__no-data-dashed-line"></span> + <span class="chart__no-data-dashed-line"></span> + <span class="chart__no-data-dashed-line"></span> + <span class="chart__no-data-dashed-line"></span> + <span class="chart__no-data-dashed-line"></span> + <span class="chart__no-data-plain-line"></span> + </div> </template> <script> @@ -50,6 +65,36 @@ export default { display: true, align: 'start', position: 'bottom', + labels: { + usePointStyle: true, + boxWidth: 14, + pointStyle: 'circle', + padding: 20, + }, + }, + tooltip: { + backgroundColor: '#202128', + padding: 10, + bodyFont: { + size: 12, + }, + titleFont: { + size: 12, + }, + }, + }, + elements: { + bar: { + borderRadius: { + topLeft: 4, + topRight: 4, + bottomLeft: 0, + bottomRight: 0, + }, + borderWidth: 1, + borderColor: '#5190ef', + backgroundColor: '#5190ef', + hoverBackgroundColor: '#5190ef', }, }, } @@ -74,10 +119,10 @@ export default { this.dataSource.schema.properties ).find((item) => item.metadata?.primary === true) const labels = this.result.map((item) => { - if (item[`field_${groupByFieldId}`]) { - return item[`field_${groupByFieldId}`] + if (item[`field_${groupByFieldId}`] !== undefined) { + return this.getGroupByValue(`field_${groupByFieldId}`, item) } - return item[`field_${primaryField.metadata.id}`] + return this.getGroupByValue(`field_${primaryField.metadata.id}`, item) }) const datasets = [] for (const [index, series] of this.seriesConfig.entries()) { @@ -88,7 +133,7 @@ export default { datasets.push({ data: seriesData, label, - backgroundColor: this.chartColors[index], + ...this.chartColors[index], }) } return { @@ -107,7 +152,7 @@ export default { datasets.push({ data: seriesData, label, - backgroundColor: this.chartColors[index], + ...this.chartColors[index], }) } return { @@ -124,7 +169,33 @@ export default { }) }, chartColors() { - return ['#4E5CFE', '#2BC3F1', '#FFC744', '#E26AB0', '#3E4ACB'] + return [ + { + backgroundColor: '#5190ef', + borderColor: '#5190ef', + hoverBackgroundColor: '#5190ef', + }, + { + backgroundColor: '#2BC3F1', + borderColor: '#2BC3F1', + hoverBackgroundColor: '#2BC3F1', + }, + { + backgroundColor: '#FFC744', + borderColor: '#FFC744', + hoverBackgroundColor: '#FFC744', + }, + { + backgroundColor: '#E26AB0', + borderColor: '#E26AB0', + hoverBackgroundColor: '#E26AB0', + }, + { + backgroundColor: '#3E4ACB', + borderColor: '#3E4ACB', + hoverBackgroundColor: '#3E4ACB', + }, + ] }, }, methods: { @@ -141,6 +212,23 @@ export default { } return label }, + getGroupByValue(fieldName, item) { + const serializedField = this.dataSource.context_data.fields[fieldName] + const fieldType = serializedField.type + + if (this.$registry.exists('chartFieldFormatting', fieldType)) { + const fieldFormatter = this.$registry.get( + 'chartFieldFormatting', + fieldType + ) + return fieldFormatter.formatGroupByFieldValue( + serializedField, + item[fieldName] + ) + } + + return item[fieldName] ?? '' + }, }, } </script> diff --git a/enterprise/web-frontend/modules/baserow_enterprise/dashboard/components/widget/ChartWidget.vue b/enterprise/web-frontend/modules/baserow_enterprise/dashboard/components/widget/ChartWidget.vue index 21f26ab60..152c85f44 100644 --- a/enterprise/web-frontend/modules/baserow_enterprise/dashboard/components/widget/ChartWidget.vue +++ b/enterprise/web-frontend/modules/baserow_enterprise/dashboard/components/widget/ChartWidget.vue @@ -1,38 +1,48 @@ <template> - <div class="dashboard-chart-widget"> - <div class="widget-header"> - <div class="widget-header__main"> - <div class="widget-header__title-wrapper"> - <div class="widget-header__title">{{ widget.title }}</div> - <div - v-if="dataSourceMisconfigured" - class="widget-header__fix-configuration" - > - <svg - width="5" - height="6" - viewBox="0 0 5 6" - fill="none" - xmlns="http://www.w3.org/2000/svg" + <div + class="dashboard-chart-widget" + :class="{ + 'dashboard-chart-widget--with-header-description': widget.description, + }" + > + <template v-if="!loading"> + <div + class="widget__header" + :class="{ + 'widget__header--edit-mode': editMode, + }" + > + <div class="widget__header-main"> + <div class="widget__header-title-wrapper"> + <div class="widget__header-title">{{ widget.title }}</div> + + <Badge + v-if="dataSourceMisconfigured" + color="red" + size="small" + indicator + rounded + >{{ $t('widget.fixConfiguration') }}</Badge > - <circle cx="2.5" cy="3" r="2.5" fill="#FF5A44" /> - </svg> - {{ $t('widget.fixConfiguration') }} + </div> + <div v-if="widget.description" class="widget__header-description"> + {{ widget.description }} </div> </div> - <div v-if="widget.description" class="widget-header__description"> - {{ widget.description }} - </div> + <WidgetContextMenu + v-if="isEditMode" + :widget="widget" + :dashboard="dashboard" + @delete-widget="$emit('delete-widget', $event)" + ></WidgetContextMenu> </div> - <WidgetContextMenu - v-if="isEditMode" - :widget="widget" - :dashboard="dashboard" - @delete-widget="$emit('delete-widget', $event)" - ></WidgetContextMenu> - </div> - <Chart :data-source="dataSource" :data-source-data="dataForDataSource"> - </Chart> + + <div class="dashboard-chart-widget__content widget__content"> + <Chart :data-source="dataSource" :data-source-data="dataForDataSource"> + </Chart> + </div> + </template> + <div v-else class="dashboard-chart-widget__loading loading-spinner"></div> </div> </template> @@ -57,6 +67,16 @@ export default { required: false, default: '', }, + loading: { + type: Boolean, + required: false, + default: false, + }, + editMode: { + type: Boolean, + required: false, + default: false, + }, }, computed: { dataSource() { diff --git a/enterprise/web-frontend/modules/baserow_enterprise/dashboard/components/widget/ChartWidgetSettings.vue b/enterprise/web-frontend/modules/baserow_enterprise/dashboard/components/widget/ChartWidgetSettings.vue index 5328ac169..142b4a1ba 100644 --- a/enterprise/web-frontend/modules/baserow_enterprise/dashboard/components/widget/ChartWidgetSettings.vue +++ b/enterprise/web-frontend/modules/baserow_enterprise/dashboard/components/widget/ChartWidgetSettings.vue @@ -1,6 +1,6 @@ <template> <GroupedAggregateRowsDataSourceForm - v-if="dataSource" + v-if="dataSource && integration" ref="dataSourceForm" :dashboard="dashboard" :widget="widget" diff --git a/enterprise/web-frontend/modules/baserow_enterprise/features.js b/enterprise/web-frontend/modules/baserow_enterprise/features.js index 151681e00..0764d0992 100644 --- a/enterprise/web-frontend/modules/baserow_enterprise/features.js +++ b/enterprise/web-frontend/modules/baserow_enterprise/features.js @@ -7,6 +7,8 @@ const EnterpriseFeatures = { ENTERPRISE_SETTINGS: 'ENTERPRISE_SETTINGS', DATA_SYNC: 'DATA_SYNC', CHART_WIDGET: 'CHART_WIDGET', + BUILDER_SSO: 'BUILDER_SSO', + ADVANCED_WEBHOOKS: 'ADVANCED_WEBHOOKS', } export default EnterpriseFeatures diff --git a/enterprise/web-frontend/modules/baserow_enterprise/integrations/appAuthProviderTypes.js b/enterprise/web-frontend/modules/baserow_enterprise/integrations/appAuthProviderTypes.js index 7f3b6e418..15c0dca74 100644 --- a/enterprise/web-frontend/modules/baserow_enterprise/integrations/appAuthProviderTypes.js +++ b/enterprise/web-frontend/modules/baserow_enterprise/integrations/appAuthProviderTypes.js @@ -12,6 +12,7 @@ import SamlAuthLink from '@baserow_enterprise/integrations/common/components/Sam import OIDCAuthLink from '@baserow_enterprise/integrations/common/components/OIDCAuthLink' import OpenIdIcon from '@baserow_enterprise/assets/images/providers/OpenID.svg' import { PasswordFieldType } from '@baserow/modules/database/fieldTypes' +import EnterpriseFeatures from '@baserow_enterprise/features' export class LocalBaserowPasswordAppAuthProviderType extends AppAuthProviderType { static getType() { @@ -146,6 +147,15 @@ export class SamlAppAuthProviderType extends SamlAuthProviderTypeMixin( getOrder() { return 20 } + + /** + * `SamlAppAuthProviderType` requires the `BUILDER_SSO` feature to be enabled. + * @param {Number} workspaceId The workspace id. + * @returns {Boolean} True if the provider is disabled, false otherwise. + */ + isDeactivated(workspaceId) { + return !this.app.$hasFeature(EnterpriseFeatures.BUILDER_SSO, workspaceId) + } } export class OpenIdConnectAppAuthProviderType extends OAuth2AuthProviderTypeMixin( @@ -229,4 +239,13 @@ export class OpenIdConnectAppAuthProviderType extends OAuth2AuthProviderTypeMixi getOrder() { return 50 } + + /** + * `OpenIdConnectAppAuthProviderType` requires the `BUILDER_SSO` feature to be enabled. + * @param {Number} workspaceId The workspace id. + * @returns {Boolean} True if the provider is disabled, false otherwise. + */ + isDeactivated(workspaceId) { + return !this.app.$hasFeature(EnterpriseFeatures.BUILDER_SSO, workspaceId) + } } diff --git a/enterprise/web-frontend/modules/baserow_enterprise/integrations/localBaserow/components/appAuthProviders/LocalBaserowAuthPassword.vue b/enterprise/web-frontend/modules/baserow_enterprise/integrations/localBaserow/components/appAuthProviders/LocalBaserowAuthPassword.vue index 62e16354e..f57ae6eee 100644 --- a/enterprise/web-frontend/modules/baserow_enterprise/integrations/localBaserow/components/appAuthProviders/LocalBaserowAuthPassword.vue +++ b/enterprise/web-frontend/modules/baserow_enterprise/integrations/localBaserow/components/appAuthProviders/LocalBaserowAuthPassword.vue @@ -4,7 +4,7 @@ <ABFormGroup :label="$t('authFormElement.email')" :error-message="getFirstErrorMessage('email')" - :autocomplete="isEditMode ? 'off' : ''" + :autocomplete="readOnly ? 'off' : ''" required > <ABInput @@ -129,7 +129,6 @@ export default { if (response && response.status === 401) { this.values.password = '' this.v$.$reset() - this.v$.$touch() this.$refs.passwordRef.focus() if (response.data?.error === 'ERROR_INVALID_CREDENTIALS') { diff --git a/enterprise/web-frontend/modules/baserow_enterprise/licenseTypes.js b/enterprise/web-frontend/modules/baserow_enterprise/licenseTypes.js index d1b2cd7e4..1220653a9 100644 --- a/enterprise/web-frontend/modules/baserow_enterprise/licenseTypes.js +++ b/enterprise/web-frontend/modules/baserow_enterprise/licenseTypes.js @@ -45,6 +45,8 @@ export class EnterpriseWithoutSupportLicenseType extends LicenseType { EnterpriseFeaturesObject.ENTERPRISE_SETTINGS, EnterpriseFeaturesObject.DATA_SYNC, EnterpriseFeaturesObject.CHART_WIDGET, + EnterpriseFeaturesObject.BUILDER_SSO, + EnterpriseFeaturesObject.ADVANCED_WEBHOOKS, ] } diff --git a/enterprise/web-frontend/modules/baserow_enterprise/locales/de.json b/enterprise/web-frontend/modules/baserow_enterprise/locales/de.json index 6799d7386..04eed141a 100644 --- a/enterprise/web-frontend/modules/baserow_enterprise/locales/de.json +++ b/enterprise/web-frontend/modules/baserow_enterprise/locales/de.json @@ -94,11 +94,20 @@ "invalidMetadata": "Ungültige XML-Metadaten für den Identity Provider", "relayStateUrl": "Standard-Relaystatus-URL", "acsUrl": "Single Sign On-URL", - "domain": "Domain", + "domain": "SAML-Domain", "metadataPlaceholder": "Fügen Sie die Metadaten des Identitätsanbieters ein...", "invalidDomain": "Ungültiger Domainname", "metadata": "Metadaten", - "providerIsVerified": "Der Anbieter wurde verifiziert" + "providerIsVerified": "Der Anbieter wurde verifiziert", + "emailAttrKey": "E-Mail", + "firstNameAttrKeyHelper": "Der Vorname des Benutzers oder der vollständige Name, wenn 'Nachname' nicht angegeben ist.", + "samlResponseSettings": "SAML-Antwortattribute", + "emailAttrKeyHelper": "Die E-Mail-Adresse, die als Benutzername für den Benutzer verwendet werden soll.", + "lastNameAttrKeyHelper": "Nachname des Benutzers (optional). Löschen Sie diesen Wert, um den vollständigen Namen über 'Vorname' anzugeben.", + "defaultAttrs": "Standard", + "customAttrs": "Benutzerdefiniert", + "firstNameAttrKey": "Vorname", + "lastNameAttrKey": "Nachname" }, "deleteAuthProviderModal": { "comment": "Möchten Sie diesen {type} wirklich löschen?", @@ -177,7 +186,11 @@ "remove": "Team löschen" }, "authProviderTypes": { - "password": "E-Mail und Passwort-Authentifizierung" + "password": "E-Mail und Passwort-Authentifizierung", + "ssoSamlProviderNameUnconfigured": "Nicht konfigurierter SSO SAML", + "saml": "SSO-SAML-Provider", + "ssoOIDCProviderNameUnconfigured": "Nicht konfigurierter OpenID-Connect", + "ssoSamlProviderName": "SSO SAML: {domain}" }, "createSettingsAuthProviderModal": { "title": "Neuen {type} hinzufügen" @@ -193,7 +206,7 @@ "onlyYouHaveAccess": "Nur Sie können auf diese Datenbank zugreifen.", "warningTitle": "Andere Benutzer könnten den Zugang erben!", "warningMessage": "Andere Benutzer erben möglicherweise den Zugriff über ihre jeweiligen Rollen in der übergeordneten Arbeitsbereich.", - "headerTooltip": "Datenbankrollen überschreiben Arbeitsbereichnrollen." + "headerTooltip": "Datenbankrollen überschreiben Arbeitsbereichsrollen." }, "table": { "title": "{name} Tabelle", @@ -256,7 +269,8 @@ "secret": "Geheimnis", "clientId": "Client-ID", "clientIdPlaceholder": "Client-ID des Anbieters", - "providerNamePlaceholder": "Benutzerdefinierter Anbietername" + "providerNamePlaceholder": "Benutzerdefinierter Anbietername", + "duplicateBaseUrl": "Die eingegebene URL existiert bereits in einem anderen Anbieter" }, "loginButton": { "continueWith": "Weitermachen mit" @@ -267,7 +281,7 @@ "coBranding": "Co-Branding Logo-Ersatz", "auditLogs": "Audit-Logs", "support": "Direkte Unterstützung", - "dataSync": "Datensynchronisation" + "dataSync": "Datenabgleich" }, "chatwootSupportSidebarWorkspace": { "directSupport": "Direkte Unterstützung" @@ -346,5 +360,48 @@ }, "enterpriseDataSyncType": { "localBaserowTable": "Baserow-Tabelle synchronisieren" + }, + "samlAuthLink": { + "placeholderWithSaml": "{login} mit SAML", + "provideEmail": "Geben Sie die E-Mailadresse Ihres SAML-Accounts ein", + "emailPlaceholder": "Geben Sie Ihre E-Mailadresse ein..." + }, + "configureDataSyncPeriodicInterval": { + "deactivatedText": "Der periodische Datenabgleich wurde deaktiviert, weil sie zu oft hintereinander fehlgeschlagen ist. Versuchen Sie bitte, den Abgleich manuell durchzuführen. Wenn er wie erwartet funktioniert, klicken Sie auf die Schaltfläche Aktivieren.", + "saved": "Gespeichert", + "deactivatedTitle": "Periodischer Datenabgleich deaktiviert", + "title": "Periodische EInstellungen", + "more": "Weitere Informationen", + "activate": "Periodischen Datenabgleich aktivieren", + "enterprise": "Der periodische Datenabgleich ist eine Advanced/Enterprise-Funktionalität." + }, + "gitlabIssuesDataSync": { + "url": "Basis-URL", + "accessToken": "Zugriffstoken", + "accessTokenHelper": "Kann hier erstellt werden: https://gitlab.com/-/user_settings/personal_access_tokens indem man auf `Add new token` klickt und `read_api` auswählt.", + "urlHelper": "Die Basis-URL Ihrer GitLab-Instanz. (z.B. https://gitlab.com)", + "projectId": "Projekt-ID", + "projectIdHelper": "Die ID des Projekts, von dem Sie die Tickets synchronisieren möchten. Sie finden sie, indem Sie auf Ihre Projektseite gehen (z.B. https://gitlab.com/baserow/baserow), auf die drei Punkte in der oberen rechten Ecke klicken und anschließend auf 'Projekt-ID kopieren: 12345678'." + }, + "hubspotContactsDataSync": { + "accessToken": "Zugriffstoken für die private App", + "accessTokenHelper": "Um ein Zugriffstoken für eine private App in HubSpot zu erstellen, klicken Sie in der oberen Leiste auf Einstellungen, navigieren Sie zu Integrationen > Private Apps und erstellen Sie eine neue private App. Weisen Sie die folgenden Bereiche zu: crm.objects.contacts.read, crm.schemas.contacts.read, und crm.objects.custom.read. Klicken Sie abschließend auf App erstellen, um das Token zu generieren." + }, + "configureDataSyncModal": { + "periodicInterval": "Periodische Einstellungen" + }, + "dataSyncPeriodicIntervalForm": { + "intervalLabel": "Intervall", + "intervalHelper": "Wie häufig der automatische Datenabgleich erfolgen soll.", + "manual": "Manuell", + "daily": "Täglich", + "hourly": "Stündlich", + "whenHelper": "Geben Sie die genaue Stunde, Minute und Sekunde an, zu der die Daten abgeglichen werden sollen.", + "minute": "Minute", + "second": "Sekunde", + "hour": "Stunde" + }, + "oidcAuthLink": { + "placeholderWithOIDC": "{login} mit {provider}" } } diff --git a/enterprise/web-frontend/modules/baserow_enterprise/locales/en.json b/enterprise/web-frontend/modules/baserow_enterprise/locales/en.json index 8705dadab..460c897ed 100644 --- a/enterprise/web-frontend/modules/baserow_enterprise/locales/en.json +++ b/enterprise/web-frontend/modules/baserow_enterprise/locales/en.json @@ -9,7 +9,8 @@ "rbac": "RBAC", "sso": "SSO", "licenseDescription": "Viewers are free with Baserow Enterprise. If a user has any other role, in any workspace then they will use a paid seat automatically.", - "overflowWarning": "You have too many non-viewer users and have used up all of your paid seats. Change users to become viewers on each workspaces members page." + "overflowWarning": "You have too many non-viewer users and have used up all of your paid seats. Change users to become viewers on each workspaces members page.", + "deactivated": "Available in the advanced/enterprise version" }, "trashType": { "team": "team" @@ -285,7 +286,9 @@ "auditLogs": "Audit logs", "dataSync": "Data sync", "coBranding": "Co-branding logo replacement", - "support": "Direct support" + "support": "Direct support", + "chartWidget": "Chart widget", + "advancedWebhooks": "Advanced webhooks" }, "chatwootSupportSidebarWorkspace": { "directSupport": "Direct support" @@ -340,7 +343,7 @@ "showBaserowHelpMessageDescription": "Indicates whether the help request message should be shown on the dashboard.", "deactivated": "Available in enterprise", "coBrandingLogo": "Logo", - "coBrandingLogoDescription": "Replaces the Baserow logo for a custom co-branded alternative (176x29).", + "coBrandingLogoDescription": "Replaces the Baserow logo for a custom co-branded alternative (176x29). If set, it also removes the Baserow description in the footer of all emails.", "uploadFileButton": "Upload image" }, "enterpriseModal": { @@ -453,7 +456,7 @@ }, "aggregationSeriesForm": { "aggregationFieldLabel": "Field", - "aggregationTypeLabel": "Summary type", + "aggregationTypeLabel": "Summary", "deleteSeries": "Delete series" }, "aggregationGroupByForm": { @@ -466,5 +469,15 @@ "none": "None", "ascending": "Ascending", "descending": "Descending" + }, + "periodicDataSyncDeactivatedNotification": { + "body": "{name} periodic data sync has been deactivated because it failed too many times consecutively." + }, + "webhook": { + "rowsEnterVieweventType": "Rows enter view" + }, + "webhookForm": { + "triggerWhenRowsEnterView": "Triggered when rows enter the view.", + "helpTriggerWhenRowsEnterView": "Triggers only when `Rows enter view` is selected and rows that now match the filters enter the view." } } diff --git a/enterprise/web-frontend/modules/baserow_enterprise/locales/fr.json b/enterprise/web-frontend/modules/baserow_enterprise/locales/fr.json index c58fd4f3a..d0015fcd5 100644 --- a/enterprise/web-frontend/modules/baserow_enterprise/locales/fr.json +++ b/enterprise/web-frontend/modules/baserow_enterprise/locales/fr.json @@ -4,7 +4,7 @@ "rbac": "RBAC", "sso": "SSO", "deactivated": "Disponible dans la version avancée/entreprise", - "licenseDescription": "Avoir le rôle de spectateur est inclus dans Baserow Entreprise. Si un utilisateur a un tout autre role, dans n'importe quel projet, il utilisera automatiquement un siège payant.", + "licenseDescription": "Avoir le rôle de spectateur est inclus dans Baserow Entreprise. Si un utilisateur a un tout autre rôle, dans n'importe quel projet, il utilisera automatiquement un siège payant.", "sidebarTooltip": "Votre compte a un accès global aux fonctions entreprise", "overflowWarning": "Vous avez trop d'utilisateurs non-spectateurs et avez utilisé tous vos sièges payants. Changez les utilisateurs pour qu'ils deviennent des spectateurs sur la page des membres de chaque projet." }, @@ -284,7 +284,9 @@ "coBranding": "Remplacement du logo de co-branding", "auditLogs": "Journaux d'audit", "support": "Assistance en ligne", - "dataSync": "Synchronisation de données" + "dataSync": "Synchronisation de données", + "chartWidget": "Graphique", + "advancedWebhooks": "Webhooks avancés" }, "chatwootSupportSidebarWorkspace": { "directSupport": "Assistance" @@ -332,7 +334,7 @@ "branding": "Image de marque", "showBaserowHelpMessage": "Afficher le message d'aide", "coBrandingLogo": "Logo", - "coBrandingLogoDescription": "Remplace le logo Baserow par une alternative co-brandée personnalisée (176x29)." + "coBrandingLogoDescription": "Remplace le logo Baserow par une alternative co-brandée personnalisée (176x29). Si défini, cela supprime également la description de Baserow dans le pied de tous les emails." }, "enterpriseModal": { "title": "Changer de plan pour utiliser : {name}", @@ -377,7 +379,7 @@ "apiTokenHelper": "Le jeton d'API du compte Jira utilisé pour l'authentification. Il peut être créé à l'adresse https://id.atlassian.com/manage-profile/security/api-tokens.", "jiraUrl": "URL de l'instance Jira", "urlHelper": "L'URL de base de votre instance Jira (par exemple, https://your-domain.atlassian.net).", - "projectKeyHelper": "La clé de projet du projet Jira (par exemple, PROJ). On peut la trouver en cliquant sur \"Paramètres du projet\" dans Jira. Si elle n'est pas fournie, touts les tickets seront renvoyés.", + "projectKeyHelper": "La clé de projet du projet Jira (par exemple, PROJ). On peut la trouver en cliquant sur \"Paramètres du projet\" dans Jira. Si elle n'est pas fournie, tous les tickets seront renvoyés.", "jiraUsername": "Nom d'utilisateur Jira", "usernameHelper": "Le nom d'utilisateur du compte Jira utilisé pour l'authentification. Il s'agit de l'email que vous utilisez pour vous connecter.", "apiToken": "Jeton d'API Jira" @@ -429,7 +431,8 @@ "hour": "Heure", "minute": "Minute", "second": "Seconde", - "hourly": "Toutes les heures" + "hourly": "Toutes les heures", + "whenHourlyHelper": "Indiquez l'heure, la minute et la seconde exactes auxquelles la synchronisation des données doit avoir lieu." }, "commonOidcSettingForm": { "callbackTitle": "URL de Callback (Cliquez pour copier)", @@ -450,5 +453,42 @@ }, "oidcAuthLink": { "placeholderWithOIDC": "{login} avec {provider}" + }, + "groupedAggregateRowsDataSourceForm": { + "data": "Données", + "sourceFieldLabel": "Source", + "viewFieldLabel": "Vue", + "notSelected": "Non sélectionnée", + "addSeries": "Ajouter une série", + "series": "Série" + }, + "aggregationSeriesForm": { + "aggregationFieldLabel": "Champ", + "aggregationTypeLabel": "Résumé", + "deleteSeries": "Supprimer la série" + }, + "aggregationGroupByForm": { + "groupByFieldLabel": "Grouper par", + "groupByNone": "Aucun", + "groupByRowId": "ID de ligne" + }, + "aggregationSortByForm": { + "none": "Aucun", + "ascending": "Ascendant", + "descending": "Descendant", + "sortByFieldLabel": "Trier par" + }, + "periodicDataSyncDeactivatedNotification": { + "body": "La synchronisation périodique des données de {name} a été désactivée car elle a échoué consécutivement trop de fois." + }, + "webhook": { + "rowsEnterVieweventType": "Des lignes entrent dans la vue" + }, + "webhookForm": { + "helpTriggerWhenRowsEnterView": "Se déclenche uniquement lorsque l'option « Des lignes entrent dans la vue » est sélectionnée et que les lignes qui correspondent aux filtres entrent dans la vue.", + "triggerWhenRowsEnterView": "Déclenché lorsque de nouvelles lignes entrent dans la vue." + }, + "chartWidget": { + "name": "Graphique" } } diff --git a/enterprise/web-frontend/modules/baserow_enterprise/locales/nl.json b/enterprise/web-frontend/modules/baserow_enterprise/locales/nl.json index 56df5dcd7..fbb34d80d 100644 --- a/enterprise/web-frontend/modules/baserow_enterprise/locales/nl.json +++ b/enterprise/web-frontend/modules/baserow_enterprise/locales/nl.json @@ -255,7 +255,9 @@ "auditLogs": "Audit logs", "coBranding": "Co-branding logo vervanging", "support": "Directe ondersteuning", - "dataSync": "Data sync" + "dataSync": "Data sync", + "chartWidget": "Grafiek widget", + "advancedWebhooks": "Geavanceerde webhooks" }, "chatwootSupportSidebarWorkspace": { "directSupport": "Directe ondersteuning" @@ -443,12 +445,50 @@ "hourly": "Uurlijks", "hour": "Uur", "minute": "Minuut", - "second": "Seconde" + "second": "Seconde", + "whenHourlyHelper": "Geef de exacte minuut en seconde wanneer de gegevenssynchronisatie moet plaatsvinden." }, "configureDataSyncModal": { "periodicInterval": "Periodieke instellingen" }, "oidcAuthLink": { "placeholderWithOIDC": "{login} met {provider}" + }, + "groupedAggregateRowsDataSourceForm": { + "addSeries": "Series toevoegen", + "data": "Data", + "sourceFieldLabel": "Bron", + "viewFieldLabel": "Weergave", + "notSelected": "Niet geselecteerd", + "series": "Series" + }, + "aggregationSeriesForm": { + "aggregationTypeLabel": "Samenvatting", + "deleteSeries": "Serie verwijderen", + "aggregationFieldLabel": "Veld" + }, + "aggregationGroupByForm": { + "groupByFieldLabel": "Groep door", + "groupByNone": "Geen", + "groupByRowId": "Rij Id" + }, + "aggregationSortByForm": { + "sortByFieldLabel": "Sorteer op", + "none": "Geen", + "ascending": "Oplopend", + "descending": "Aflopend" + }, + "periodicDataSyncDeactivatedNotification": { + "body": "{name} periodieke gegevenssynchronisatie is gedeactiveerd omdat het te vaak achter elkaar mislukte." + }, + "webhook": { + "rowsEnterVieweventType": "Rij komt in weergave" + }, + "webhookForm": { + "triggerWhenRowsEnterView": "Geactiveerd wanneer rijen de weergave binnenkomen.", + "helpTriggerWhenRowsEnterView": "Triggert alleen wanneer `Rijen in de weergave komen` is geselecteerd en rijen die nu overeenkomen met de filters worden weergegeven." + }, + "chartWidget": { + "name": "Grafiek" } } diff --git a/enterprise/web-frontend/modules/baserow_enterprise/module.js b/enterprise/web-frontend/modules/baserow_enterprise/module.js index c598b39c0..807443dc7 100644 --- a/enterprise/web-frontend/modules/baserow_enterprise/module.js +++ b/enterprise/web-frontend/modules/baserow_enterprise/module.js @@ -19,6 +19,11 @@ export default function () { // Register new alias to the web-frontend directory. this.options.alias['@baserow_enterprise'] = path.resolve(__dirname, './') + if (this.options.publicRuntimeConfig) { + this.options.publicRuntimeConfig.BASEROW_ENTERPRISE_GROUPED_AGGREGATE_SERVICE_MAX_SERIES = + process.env.BASEROW_ENTERPRISE_GROUPED_AGGREGATE_SERVICE_MAX_SERIES || 3 + } + // Remove the existing index route and add our own routes. this.extendRoutes((configRoutes) => { const settingsRoute = configRoutes.find( diff --git a/enterprise/web-frontend/modules/baserow_enterprise/notificationTypes.js b/enterprise/web-frontend/modules/baserow_enterprise/notificationTypes.js new file mode 100644 index 000000000..70384cd5e --- /dev/null +++ b/enterprise/web-frontend/modules/baserow_enterprise/notificationTypes.js @@ -0,0 +1,29 @@ +import { NotificationType } from '@baserow/modules/core/notificationTypes' + +import PeriodicDataSyncDeactivatedNotification from '@baserow_enterprise/components/notifications/PeriodicDataSyncDeactivatedNotification' +import { PeriodicIntervalFieldsConfigureDataSyncType } from '@baserow_enterprise/configureDataSyncTypes' + +export class PeriodicDataSyncDeactivatedNotificationType extends NotificationType { + static getType() { + return 'periodic_data_sync_deactivated' + } + + getIconComponent() { + return null + } + + getContentComponent() { + return PeriodicDataSyncDeactivatedNotification + } + + getRoute(notificationData) { + return { + name: 'database-table-open-configure-data-sync', + params: { + databaseId: notificationData.database_id, + tableId: notificationData.table_id, + selectedPage: PeriodicIntervalFieldsConfigureDataSyncType.getType(), + }, + } + } +} diff --git a/enterprise/web-frontend/modules/baserow_enterprise/plugin.js b/enterprise/web-frontend/modules/baserow_enterprise/plugin.js index 1fb5b9678..48f9b2262 100644 --- a/enterprise/web-frontend/modules/baserow_enterprise/plugin.js +++ b/enterprise/web-frontend/modules/baserow_enterprise/plugin.js @@ -51,6 +51,7 @@ import { HubspotContactsDataSyncType, } from '@baserow_enterprise/dataSyncTypes' import { ChartWidgetType } from '@baserow_enterprise/dashboard/widgetTypes' +import { SingleSelectFormattingType } from '@baserow_enterprise/dashboard/chartFieldFormatting' import { PeriodicIntervalFieldsConfigureDataSyncType } from '@baserow_enterprise/configureDataSyncTypes' import { CountViewAggregationType, @@ -71,10 +72,20 @@ import { VarianceViewAggregationType, MedianViewAggregationType, } from '@baserow/modules/database/viewAggregationTypes' +import { PeriodicDataSyncDeactivatedNotificationType } from '@baserow_enterprise/notificationTypes' +import { RowsEnterViewWebhookEventType } from '@baserow_enterprise/webhookEventTypes' import { - FF_AB_SSO, - FF_DASHBOARDS, -} from '@baserow/modules/core/plugins/featureFlags' + TextFieldType, + LongTextFieldType, + URLFieldType, + EmailFieldType, + NumberFieldType, + RatingFieldType, + BooleanFieldType, + SingleSelectFieldType, + PhoneNumberFieldType, + AutonumberFieldType, +} from '@baserow/modules/database/fieldTypes' export default (context) => { const { app, isDev, store } = context @@ -145,16 +156,14 @@ export default (context) => { new LocalBaserowPasswordAppAuthProviderType(context) ) - if (app.$featureFlagIsEnabled(FF_AB_SSO)) { - app.$registry.register( - 'appAuthProvider', - new SamlAppAuthProviderType(context) - ) - app.$registry.register( - 'appAuthProvider', - new OpenIdConnectAppAuthProviderType(context) - ) - } + app.$registry.register( + 'appAuthProvider', + new SamlAppAuthProviderType(context) + ) + app.$registry.register( + 'appAuthProvider', + new OpenIdConnectAppAuthProviderType(context) + ) app.$registry.register('roles', new EnterpriseAdminRoleType(context)) app.$registry.register('roles', new EnterpriseMemberRoleType(context)) @@ -242,12 +251,65 @@ export default (context) => { new UniqueCountViewAggregationType(context) ) + app.$registry.register( + 'groupedAggregationGroupedBy', + new TextFieldType(context) + ) + app.$registry.register( + 'groupedAggregationGroupedBy', + new LongTextFieldType(context) + ) + app.$registry.register( + 'groupedAggregationGroupedBy', + new NumberFieldType(context) + ) + app.$registry.register( + 'groupedAggregationGroupedBy', + new URLFieldType(context) + ) + app.$registry.register( + 'groupedAggregationGroupedBy', + new RatingFieldType(context) + ) + app.$registry.register( + 'groupedAggregationGroupedBy', + new BooleanFieldType(context) + ) + app.$registry.register( + 'groupedAggregationGroupedBy', + new EmailFieldType(context) + ) + app.$registry.register( + 'groupedAggregationGroupedBy', + new SingleSelectFieldType(context) + ) + app.$registry.register( + 'groupedAggregationGroupedBy', + new PhoneNumberFieldType(context) + ) + app.$registry.register( + 'groupedAggregationGroupedBy', + new AutonumberFieldType(context) + ) + + app.$registry.register( + 'notification', + new PeriodicDataSyncDeactivatedNotificationType(context) + ) + app.$registry.register( 'configureDataSync', new PeriodicIntervalFieldsConfigureDataSyncType(context) ) - if (app.$featureFlagIsEnabled(FF_DASHBOARDS)) { - app.$registry.register('dashboardWidget', new ChartWidgetType(context)) - } + app.$registry.register( + 'webhookEvent', + new RowsEnterViewWebhookEventType(context) + ) + + app.$registry.register('dashboardWidget', new ChartWidgetType(context)) + app.$registry.register( + 'chartFieldFormatting', + new SingleSelectFormattingType(context) + ) } diff --git a/enterprise/web-frontend/modules/baserow_enterprise/webhookEventTypes.js b/enterprise/web-frontend/modules/baserow_enterprise/webhookEventTypes.js new file mode 100644 index 000000000..2af5b661c --- /dev/null +++ b/enterprise/web-frontend/modules/baserow_enterprise/webhookEventTypes.js @@ -0,0 +1,61 @@ +import { + WebhookEventType, + viewExample, +} from '@baserow/modules/database/webhookEventTypes' +import EnterpriseModal from '@baserow_enterprise/components/EnterpriseModal' +import EnterpriseFeatures from '@baserow_enterprise/features' + +class EnterpriseWebhookEventType extends WebhookEventType { + getDeactivatedText() { + return this.app.i18n.t('enterprise.deactivated') + } + + getDeactivatedClickModal() { + return EnterpriseModal + } + + isDeactivated(workspaceId) { + return !this.app.$hasFeature( + EnterpriseFeatures.ADVANCED_WEBHOOKS, + workspaceId + ) + } + + getFeatureName() { + return this.app.i18n.t('enterpriseFeatures.advancedWebhooks') + } +} + +export class RowsEnterViewWebhookEventType extends EnterpriseWebhookEventType { + static getType() { + return 'view.rows_entered' + } + + getName() { + const { i18n } = this.app + return i18n.t('webhook.rowsEnterVieweventType') + } + + getExamplePayload(database, table, rowExample) { + const payload = super.getExamplePayload(database, table, rowExample) + payload.view = viewExample + payload.fields = Object.keys(rowExample) + payload.rows = [rowExample] + payload.total_count = 1 + return payload + } + + getHasRelatedView() { + return true + } + + getRelatedViewPlaceholder() { + const { i18n } = this.app + return i18n.t('webhookForm.triggerWhenRowsEnterView') + } + + getRelatedViewHelpText() { + const { i18n } = this.app + return i18n.t('webhookForm.helpTriggerWhenRowsEnterView') + } +} diff --git a/heroku.Dockerfile b/heroku.Dockerfile index 435cba40a..779d673cd 100644 --- a/heroku.Dockerfile +++ b/heroku.Dockerfile @@ -1,4 +1,4 @@ -ARG FROM_IMAGE=baserow/baserow:1.31.1 +ARG FROM_IMAGE=baserow/baserow:1.32.0 # This is pinned as version pinning is done by the CI setting FROM_IMAGE. # hadolint ignore=DL3006 FROM $FROM_IMAGE as image_base diff --git a/plugin-boilerplate/{{ cookiecutter.project_slug }}/Dockerfile b/plugin-boilerplate/{{ cookiecutter.project_slug }}/Dockerfile index aacf09296..ddf983756 100644 --- a/plugin-boilerplate/{{ cookiecutter.project_slug }}/Dockerfile +++ b/plugin-boilerplate/{{ cookiecutter.project_slug }}/Dockerfile @@ -1,4 +1,4 @@ -FROM baserow/baserow:1.31.1 +FROM baserow/baserow:1.32.0 COPY ./plugins/{{ cookiecutter.project_module }}/ /baserow/plugins/{{ cookiecutter.project_module }}/ RUN /baserow/plugins/install_plugin.sh --folder /baserow/plugins/{{ cookiecutter.project_module }} diff --git a/plugin-boilerplate/{{ cookiecutter.project_slug }}/backend-dev.Dockerfile b/plugin-boilerplate/{{ cookiecutter.project_slug }}/backend-dev.Dockerfile index cd6d7acfb..0361feeea 100644 --- a/plugin-boilerplate/{{ cookiecutter.project_slug }}/backend-dev.Dockerfile +++ b/plugin-boilerplate/{{ cookiecutter.project_slug }}/backend-dev.Dockerfile @@ -1,7 +1,7 @@ # This a dev image for testing your plugin when installed into the Baserow backend image -FROM baserow/backend:1.31.1 as base +FROM baserow/backend:1.32.0 as base -FROM baserow/backend:1.31.1 +FROM baserow/backend:1.32.0 USER root diff --git a/plugin-boilerplate/{{ cookiecutter.project_slug }}/backend.Dockerfile b/plugin-boilerplate/{{ cookiecutter.project_slug }}/backend.Dockerfile index cf6ea7ff5..232e6e0e6 100644 --- a/plugin-boilerplate/{{ cookiecutter.project_slug }}/backend.Dockerfile +++ b/plugin-boilerplate/{{ cookiecutter.project_slug }}/backend.Dockerfile @@ -1,4 +1,4 @@ -FROM baserow/backend:1.31.1 +FROM baserow/backend:1.32.0 USER root diff --git a/plugin-boilerplate/{{ cookiecutter.project_slug }}/dev.Dockerfile b/plugin-boilerplate/{{ cookiecutter.project_slug }}/dev.Dockerfile index 7fde9eeb9..47da3ab06 100644 --- a/plugin-boilerplate/{{ cookiecutter.project_slug }}/dev.Dockerfile +++ b/plugin-boilerplate/{{ cookiecutter.project_slug }}/dev.Dockerfile @@ -1,7 +1,7 @@ # This a dev image for testing your plugin when installed into the Baserow all-in-one image -FROM baserow/baserow:1.31.1 as base +FROM baserow/baserow:1.32.0 as base -FROM baserow/baserow:1.31.1 +FROM baserow/baserow:1.32.0 ARG PLUGIN_BUILD_UID ENV PLUGIN_BUILD_UID=${PLUGIN_BUILD_UID:-9999} diff --git a/plugin-boilerplate/{{ cookiecutter.project_slug }}/plugins/{{ cookiecutter.project_module }}/baserow_plugin_info.json b/plugin-boilerplate/{{ cookiecutter.project_slug }}/plugins/{{ cookiecutter.project_module }}/baserow_plugin_info.json index b57a69cf8..0b28d2fee 100644 --- a/plugin-boilerplate/{{ cookiecutter.project_slug }}/plugins/{{ cookiecutter.project_module }}/baserow_plugin_info.json +++ b/plugin-boilerplate/{{ cookiecutter.project_slug }}/plugins/{{ cookiecutter.project_module }}/baserow_plugin_info.json @@ -1,7 +1,7 @@ { "name": "{{ cookiecutter.project_name }}", "version": "0.0.1", - "supported_baserow_versions": "1.31.1", + "supported_baserow_versions": "1.32.0", "plugin_api_version": "0.0.1-alpha", "description": "TODO", "author": "TODO", diff --git a/plugin-boilerplate/{{ cookiecutter.project_slug }}/web-frontend-dev.Dockerfile b/plugin-boilerplate/{{ cookiecutter.project_slug }}/web-frontend-dev.Dockerfile index 628ac8f6f..dcba24eec 100644 --- a/plugin-boilerplate/{{ cookiecutter.project_slug }}/web-frontend-dev.Dockerfile +++ b/plugin-boilerplate/{{ cookiecutter.project_slug }}/web-frontend-dev.Dockerfile @@ -1,6 +1,6 @@ # This a dev image for testing your plugin when installed into the Baserow web-frontend image -FROM baserow/web-frontend:1.31.1 as base -FROM baserow/web-frontend:1.31.1 +FROM baserow/web-frontend:1.32.0 as base +FROM baserow/web-frontend:1.32.0 USER root diff --git a/plugin-boilerplate/{{ cookiecutter.project_slug }}/web-frontend.Dockerfile b/plugin-boilerplate/{{ cookiecutter.project_slug }}/web-frontend.Dockerfile index 1bc13ef3f..53784868a 100644 --- a/plugin-boilerplate/{{ cookiecutter.project_slug }}/web-frontend.Dockerfile +++ b/plugin-boilerplate/{{ cookiecutter.project_slug }}/web-frontend.Dockerfile @@ -1,4 +1,4 @@ -FROM baserow/web-frontend:1.31.1 +FROM baserow/web-frontend:1.32.0 USER root diff --git a/premium/backend/pyproject.toml b/premium/backend/pyproject.toml index bd4f6efd8..89cb038db 100644 --- a/premium/backend/pyproject.toml +++ b/premium/backend/pyproject.toml @@ -12,7 +12,7 @@ description = """Baserow is an open source no-code database tool and Airtable \ # mixed license license={file="LICENSE"} requires-python=">=3.11" -version = "1.31.1" +version = "1.32.0" classifiers = [] [project.urls] diff --git a/premium/backend/src/baserow_premium/api/license/serializers.py b/premium/backend/src/baserow_premium/api/license/serializers.py index a37a1b116..3c14ae898 100644 --- a/premium/backend/src/baserow_premium/api/license/serializers.py +++ b/premium/backend/src/baserow_premium/api/license/serializers.py @@ -32,6 +32,12 @@ class LicenseSerializer(serializers.ModelSerializer): seats = serializers.IntegerField( help_text="The maximum amount of users that can use the license." ) + application_users = serializers.IntegerField( + help_text="The amount of application builder users permitted in this license." + ) + application_users_taken = serializers.SerializerMethodField( + help_text="The amount of application builder users used so far in this license." + ) product_code = serializers.CharField( help_text="The product code that indicates what the license unlocks." ) @@ -59,6 +65,8 @@ class LicenseSerializer(serializers.ModelSerializer): "free_users_count", "seats_taken", "seats", + "application_users_taken", + "application_users", "product_code", "issued_on", "issued_to_email", @@ -79,6 +87,11 @@ class LicenseSerializer(serializers.ModelSerializer): self.get_cached_seat_usage_summary(obj), "free_users_count", None ) + @extend_schema_field(OpenApiTypes.INT) + def get_application_users_taken(self, obj) -> Optional[int]: + usage = obj.license_type.get_builder_usage_summary(obj) + return usage.application_users_taken if usage else None + class RegisterLicenseSerializer(serializers.Serializer): license = serializers.CharField(help_text="The license that you want to register.") @@ -97,14 +110,14 @@ class LicenseWithUsersSerializer(LicenseSerializer): fields = LicenseSerializer.Meta.fields + ("users",) @extend_schema_field(LicenseUserSerializer(many=True)) - def get_users(self, object): - users = [user.user for user in object.users.all()] + def get_users(self, instance): + users = [user.user for user in instance.users.all()] return LicenseUserSerializer(users, many=True).data class LicenseUserLookupSerializer(serializers.ModelSerializer): value = serializers.SerializerMethodField( - help_text="The name and the email " "address of the user." + help_text="The name and the email address of the user." ) class Meta: @@ -112,5 +125,5 @@ class LicenseUserLookupSerializer(serializers.ModelSerializer): fields = ("id", "value") @extend_schema_field(OpenApiTypes.STR) - def get_value(self, object): - return f"{object.first_name} ({object.email})" + def get_value(self, instance): + return f"{instance.first_name} ({instance.email})" diff --git a/premium/backend/src/baserow_premium/api/license/views.py b/premium/backend/src/baserow_premium/api/license/views.py index 8874ef480..a9611b4d0 100644 --- a/premium/backend/src/baserow_premium/api/license/views.py +++ b/premium/backend/src/baserow_premium/api/license/views.py @@ -61,7 +61,7 @@ class AdminLicensesView(APIView): "Lists all the valid licenses that are registered to this instance. A " "premium license can be used to unlock the premium features for a fixed " "amount of users. An enterprise license can similarly be used to " - "unlock enterpise features. More information about self hosted licenses " + "unlock enterprise features. More information about self hosted licenses " "can be found on our pricing page https://baserow.io/pricing." ), responses={ diff --git a/premium/backend/src/baserow_premium/apps.py b/premium/backend/src/baserow_premium/apps.py index be259036d..0140a99ed 100644 --- a/premium/backend/src/baserow_premium/apps.py +++ b/premium/backend/src/baserow_premium/apps.py @@ -53,6 +53,7 @@ class BaserowPremiumConfig(AppConfig): from .export.exporter_types import ( ExcelTableExporter, + FileTableExporter, JSONTableExporter, XMLTableExporter, ) @@ -74,6 +75,7 @@ class BaserowPremiumConfig(AppConfig): table_exporter_registry.register(JSONTableExporter()) table_exporter_registry.register(XMLTableExporter()) table_exporter_registry.register(ExcelTableExporter()) + table_exporter_registry.register(FileTableExporter()) row_metadata_registry.register(RowCommentCountMetadataType()) row_metadata_registry.register(RowCommentsNotificationModeMetadataType()) diff --git a/premium/backend/src/baserow_premium/export/exporter_types.py b/premium/backend/src/baserow_premium/export/exporter_types.py index 627aa38d6..257d14b40 100644 --- a/premium/backend/src/baserow_premium/export/exporter_types.py +++ b/premium/backend/src/baserow_premium/export/exporter_types.py @@ -2,19 +2,24 @@ import json from collections import OrderedDict from typing import List, Optional, Type +import zipstream from baserow_premium.license.handler import LicenseHandler from openpyxl import Workbook +from baserow.config.settings.base import BASEROW_DEFAULT_ZIP_COMPRESS_LEVEL from baserow.contrib.database.api.export.serializers import ( BaseExporterOptionsSerializer, ) from baserow.contrib.database.export.file_writer import FileWriter, QuerysetSerializer from baserow.contrib.database.export.registries import TableExporter from baserow.contrib.database.export.utils import view_is_publicly_exportable +from baserow.contrib.database.fields.field_helpers import prepare_files_for_export +from baserow.contrib.database.fields.field_types import FileFieldType from baserow.contrib.database.views.view_types import GridViewType +from baserow.core.storage import ExportZipFile, get_default_storage from ..license.features import PREMIUM -from .serializers import ExcelExporterOptionsSerializer +from .serializers import ExcelExporterOptionsSerializer, FileExporterOptionsSerializer from .utils import get_unique_name, safe_xml_tag_name, to_xml @@ -225,3 +230,100 @@ class ExcelTableExporter(PremiumTableExporter): @property def queryset_serializer_class(self): return ExcelQuerysetSerializer + + +class FileQuerysetSerializer(QuerysetSerializer): + can_handle_rich_value = True + + def write_to_file( + self, + file_writer: FileWriter, + export_charset: str = "utf-8", + organize_files: bool = True, + ): + """ + Writes files from the queryset to a zip archive. Will create a directory + structure based on field names and include all files found in the rows. + + :param file_writer: The FileWriter instance to write to. + :param export_charset: The charset to use for writing metadata. + :param organize_files: Whether or not to group files by row id in the export + """ + + file_writer.update_check() + + storage = get_default_storage() + field_serializers = [] + + zip_file = ExportZipFile( + compress_level=BASEROW_DEFAULT_ZIP_COMPRESS_LEVEL, + compress_type=zipstream.ZIP_DEFLATED, + ) + + file_fields = [] + # Get list of file-type fields + for field_object in self.ordered_field_objects: + if isinstance(field_object["type"], FileFieldType): + file_fields.append(field_object) + field_serializers.append(self._get_field_serializer(field_object)) + + progress = 0 + + def write_row(row, is_last): + file_data = {} + row_folder = f"row_{row.id}/" if organize_files else "" + + for file_field_data in file_fields: + file_field = file_field_data["type"] + + records = file_field.get_internal_value_from_db( + row, file_field_data["name"] + ) + file_serialized_data = prepare_files_for_export( + records, + {}, + zip_file, + storage, + row_folder, + ) + for file in file_serialized_data: + file_data[file["name"]] = file["size"] + return file_data + + # processing rows is 15% of total progress + processed_files = file_writer.write_rows( + self.queryset, write_row, progress_weight=15 + ) + unique_files = {key: value for d in processed_files for key, value in d.items()} + total_size = sum(unique_files.values()) or 1 + + # 85% for writing chunks + for chunk in zip_file: + size = len(chunk) + progress += size / total_size * 85 + file_writer._file.write(chunk) + file_writer._check_and_update_job(15 + progress, 100) + + +class FileTableExporter(PremiumTableExporter): + type = "file" + + @property + def option_serializer_class(self) -> Type[BaseExporterOptionsSerializer]: + return FileExporterOptionsSerializer + + @property + def can_export_table(self) -> bool: + return True + + @property + def supported_views(self) -> List[str]: + return [GridViewType.type] + + @property + def file_extension(self) -> str: + return ".zip" + + @property + def queryset_serializer_class(self): + return FileQuerysetSerializer diff --git a/premium/backend/src/baserow_premium/export/serializers.py b/premium/backend/src/baserow_premium/export/serializers.py index 2a1ddc70e..63ca8f856 100644 --- a/premium/backend/src/baserow_premium/export/serializers.py +++ b/premium/backend/src/baserow_premium/export/serializers.py @@ -11,3 +11,10 @@ class ExcelExporterOptionsSerializer(BaseExporterOptionsSerializer): help_text="Whether or not to generate the field names as header row at the top " "of the Excel file.", ) + + +class FileExporterOptionsSerializer(BaseExporterOptionsSerializer): + organize_files = fields.BooleanField( + default=True, + help_text="Whether or not to group files by row id in the export.", + ) diff --git a/premium/backend/src/baserow_premium/fields/field_types.py b/premium/backend/src/baserow_premium/fields/field_types.py index 21b610bce..16720185a 100644 --- a/premium/backend/src/baserow_premium/fields/field_types.py +++ b/premium/backend/src/baserow_premium/fields/field_types.py @@ -168,13 +168,13 @@ class AIFieldType(CollationSortMixin, SelectOptionBaseFieldType): field_name, value, model_field, field ) - def check_can_order_by(self, field: Field) -> bool: + def check_can_order_by(self, field: Field, sort_type: str) -> bool: baserow_field_type = self.get_baserow_field_type(field) - return baserow_field_type.check_can_order_by(field) + return baserow_field_type.check_can_order_by(field, sort_type) - def check_can_group_by(self, field: Field) -> bool: + def check_can_group_by(self, field: Field, sort_type: str) -> bool: baserow_field_type = self.get_baserow_field_type(field) - return baserow_field_type.check_can_group_by(field) + return baserow_field_type.check_can_group_by(field, sort_type) def get_search_expression(self, field: Field, queryset): baserow_field_type = self.get_baserow_field_type(field) @@ -189,15 +189,22 @@ class AIFieldType(CollationSortMixin, SelectOptionBaseFieldType): return baserow_field_type.enhance_queryset(queryset, field, name) def get_sortable_column_expression( - self, field: Field, field_name: str + self, + field: Field, + field_name: str, + sort_type: str, ) -> Expression | F: baserow_field_type = self.get_baserow_field_type(field) - return baserow_field_type.get_sortable_column_expression(field, field_name) + return baserow_field_type.get_sortable_column_expression( + field, field_name, sort_type + ) - def get_order(self, field, field_name, order_direction, table_model=None): + def get_order( + self, field, field_name, order_direction, sort_type, table_model=None + ): baserow_field_type = self.get_baserow_field_type(field) return baserow_field_type.get_order( - field, field_name, order_direction, table_model=table_model + field, field_name, order_direction, sort_type, table_model=table_model ) def serialize_to_input_value(self, field, value): diff --git a/premium/backend/src/baserow_premium/license/handler.py b/premium/backend/src/baserow_premium/license/handler.py index 6f38bea08..24a9e655c 100755 --- a/premium/backend/src/baserow_premium/license/handler.py +++ b/premium/backend/src/baserow_premium/license/handler.py @@ -258,6 +258,42 @@ class LicenseHandler: return payload + @classmethod + def collect_extra_license_info(cls, license_object: License) -> dict[str, any]: + """ + Collects extra information about the license that can be sent to the authority + to check the state of the license. + + :param license_object: The license object to collect the extra information from. + :return: A dictionary containing the extra information. + """ + + extra_info = {} + try: + license_type = license_object.license_type + seat_usage = license_type.get_seat_usage_summary(license_object) + builder_usage = license_type.get_builder_usage_summary(license_object) + if seat_usage or builder_usage: + extra_info["id"] = license_object.license_id + if seat_usage: + extra_info.update( + { + "seats_taken": seat_usage.seats_taken, + "free_users_count": seat_usage.free_users_count, + "highest_role_per_user_id": seat_usage.highest_role_per_user_id, + } + ) + if builder_usage: + extra_info.update( + { + "application_users_taken": builder_usage.application_users_taken, + } + ) + except (InvalidLicenseError, UnsupportedLicenseError, DatabaseError): + pass + + return extra_info + @classmethod def send_license_info_and_fetch_license_status_with_authority( cls, license_objects: List[License] @@ -267,20 +303,7 @@ class LicenseHandler: for license_object in license_objects: license_payloads.append(license_object.license) - - try: - license_type = license_object.license_type - usage = license_type.get_seat_usage_summary(license_object) - if usage is not None: - extra_info = { - "id": license_object.license_id, - "seats_taken": usage.seats_taken, - "free_users_count": usage.free_users_count, - "highest_role_per_user_id": usage.highest_role_per_user_id, - } - extra_license_info.append(extra_info) - except (InvalidLicenseError, UnsupportedLicenseError, DatabaseError): - pass + extra_license_info.append(cls.collect_extra_license_info(license_object)) return cls.fetch_license_status_with_authority( license_payloads, extra_license_info @@ -328,7 +351,13 @@ class LicenseHandler: "The license authority can't be reached because it didn't returned " "with an ok response." ) - except RequestException: + except RequestException as exc: + # If we're running tests with the `responses` mocking library, and we are + # matching responses with the `json_params_matcher` matcher, we don't want + # to raise `LicenseAuthorityUnavailable`, we want the error to propagate + # and fail our tests. + if settings.TESTS and "request.body doesn't match" in str(exc.args[0]): + raise exc raise LicenseAuthorityUnavailable( "The license authority can't be reached because of a network error." ) @@ -401,10 +430,28 @@ class LicenseHandler: license_object.delete() continue - summary = license_object.license_type.get_seat_usage_summary(license_object) - if summary is not None and summary.seats_taken > license_object.seats: + seat_summary = license_object.license_type.get_seat_usage_summary( + license_object + ) + if ( + seat_summary is not None + and seat_summary.seats_taken > license_object.seats + ): license_object.license_type.handle_seat_overflow( - summary.seats_taken, license_object + seat_summary.seats_taken, license_object + ) + + builder_summary = license_object.license_type.get_builder_usage_summary( + license_object + ) + if ( + builder_summary is not None + and license_object.application_users is not None + and builder_summary.application_users_taken + > license_object.application_users + ): + license_object.license_type.handle_application_user_overflow( + builder_summary.application_users_taken, license_object ) license_object.last_check = datetime.now(tz=timezone.utc) diff --git a/premium/backend/src/baserow_premium/license/license_types.py b/premium/backend/src/baserow_premium/license/license_types.py index f92d45eb0..c8f2b3fcd 100644 --- a/premium/backend/src/baserow_premium/license/license_types.py +++ b/premium/backend/src/baserow_premium/license/license_types.py @@ -10,12 +10,18 @@ class PremiumLicenseType(LicenseType): order = 10 features = [PREMIUM] - def get_seat_usage_summary(self, obj: License) -> SeatUsageSummary: + def get_seat_usage_summary(self, license_object: License) -> SeatUsageSummary: + # The attributes will exist on `license_object` if this method is + # called at least once by `LicenseSerializer`. seats_taken = ( - obj.seats_taken if hasattr(obj, "seats_taken") else obj.users.all().count() + license_object.seats_taken + if hasattr(license_object, "seats_taken") + else license_object.users.all().count() ) total_users = ( - obj.total_users if hasattr(obj, "total_users") else User.objects.count() + license_object.total_users + if hasattr(license_object, "total_users") + else User.objects.count() ) free_users = total_users - seats_taken return SeatUsageSummary( diff --git a/premium/backend/src/baserow_premium/license/models.py b/premium/backend/src/baserow_premium/license/models.py index d96b2c90f..cc7e96d98 100644 --- a/premium/backend/src/baserow_premium/license/models.py +++ b/premium/backend/src/baserow_premium/license/models.py @@ -1,9 +1,11 @@ from datetime import datetime, timezone +from typing import Optional from django.contrib.auth import get_user_model from django.db import models from django.utils.functional import cached_property +from baserow_premium.license.exceptions import InvalidLicenseError from dateutil import parser User = get_user_model() @@ -64,6 +66,19 @@ class License(models.Model): and self.valid_cached_properties ) + @property + def valid_payload(self) -> bool: + """ + Responsible for checking if the license payload is valid. If the payload is + invalid then it should raise an InvalidLicenseError. + """ + + try: + _ = self.payload + return True + except InvalidLicenseError: + return False + @property def valid_cached_properties(self): """ @@ -82,6 +97,11 @@ class License(models.Model): def seats(self): return self.payload["seats"] + @property + def application_users(self) -> Optional[int]: + # `application_users` is only present >=v1.32 + return self.payload.get("application_users") + @property def issued_on(self): return parser.parse(self.payload["issued_on"]).replace(tzinfo=timezone.utc) diff --git a/premium/backend/src/baserow_premium/license/registries.py b/premium/backend/src/baserow_premium/license/registries.py index 183a77f5b..8987f2135 100644 --- a/premium/backend/src/baserow_premium/license/registries.py +++ b/premium/backend/src/baserow_premium/license/registries.py @@ -4,6 +4,8 @@ from typing import Dict, List, Optional from baserow_premium.license.models import License +from baserow.contrib.builder.handler import BuilderHandler +from baserow.core.cache import local_cache from baserow.core.models import Workspace from baserow.core.registry import Instance, Registry @@ -18,6 +20,12 @@ class SeatUsageSummary: highest_role_per_user_id: Dict[int, str] = dataclasses.field(default_factory=dict) +@dataclasses.dataclass +class BuilderUsageSummary: + # How many application users are currently being used. + application_users_taken: int + + class LicenseType(abc.ABC, Instance): """ A type of license that a user can install into Baserow to unlock extra @@ -25,25 +33,21 @@ class LicenseType(abc.ABC, Instance): to have different behaviour by implementing the various hook methods differently. """ + # A list of features that this license type grants. features: List[str] = [] - """ - A list of features that this license type grants. - """ + # The higher the order the more features/more expensive the license is. Out of + # all instance-wide licenses a user might have, the one with the highest order will + # be shown as a badge in the top of the sidebar in the GUI. order: int - """The higher the order the more features/more expensive the license is. Out of - all instance-wide licenses a user might have, the one with the highest order will - be shown as a badge in the top of the sidebar in the GUI. """ + # When true every user in the instance will have this license if it is active + # regardless of if they are added to a seat on the license or not. instance_wide: bool = False - """ - When true every user in the instance will have this license if it is active - regardless of if they are added to a seat on the license or not. - """ seats_manually_assigned: bool = True - def has_feature(self, feature: str): + def has_feature(self, feature: str) -> bool: return feature in self.features def get_seat_usage_summary( @@ -51,7 +55,7 @@ class LicenseType(abc.ABC, Instance): ) -> Optional[SeatUsageSummary]: """ If it makes sense for a license to have seat usage then it should be calculated - and returned herre. + and returned here. If it doesn't make sense for this license type then this should return None. """ @@ -72,6 +76,129 @@ class LicenseType(abc.ABC, Instance): def handle_seat_overflow(self, seats_taken: int, license_object: License): pass + def _calculate_stacked_license_builder_usage( + self, total_application_users_taken: int + ) -> dict[str, BuilderUsageSummary]: + """ + Given the total count of application users used in this instance, this method + is responsible for returning a `BuilderUsageSummary` for each license in this + instance. + + The `BuilderUsageSummary.application_users_taken` is the key here. If there are + multiple stacked licenses, then we will spread the usage of the application + users across these licenses, filling the `application_users_taken` up, starting + with the earliest license first. + + :param total_application_users_taken: the total number of application users + taken in the instance. + :return: A dictionary of `license_id` to `BuilderUsageSummary`. + """ + + # How many licenses do we have with application users? + all_licenses = License.objects.all() + builder_enabled_licenses = [ + license + for license in all_licenses + if license.valid_payload # Ensure the license can be decoded + and license.application_users is not None # Restrict to only builder usage + ] + + # Pluck out all the active licenses. We'll only iterate over these when we + # spread the builder usage. Any expired licenses will have a usage of 0. + active_builder_licenses = [ + license for license in builder_enabled_licenses if license.is_active + ] + + # 1) If there are multiple stacked licenses, and we know that they have + # application users assigned to them, then the usage of those application + # users will be spread across these licenses. For example: + # - LicenseA: application_users=10 + # - LicenseB: application_users=15 + # - `total_application_users_taken` = 26 + # LicenseA will have 10 `application_users_taken`, and LicenseB will have 16 + # `application_users_taken` (one over limit). + # 2) If the instance just has a single license, then the usage of the + # application users will be the total count. + # 3) Any expired licenses will report an application user usage of 0. + + usage_per_license = { + license.license_id: BuilderUsageSummary(application_users_taken=0) + for license in all_licenses + } + + # Fill the licenses with the smallest application user quotas first. + active_builder_licenses.sort( + key=lambda license: (license.application_users, license.id) + ) + for index, builder_license in enumerate(active_builder_licenses): + if index < len(active_builder_licenses) - 1: + assignable = min( + builder_license.application_users, total_application_users_taken + ) + usage_per_license[builder_license.license_id] = BuilderUsageSummary( + application_users_taken=assignable + ) + total_application_users_taken -= assignable + else: + usage_per_license[builder_license.license_id] = BuilderUsageSummary( + application_users_taken=total_application_users_taken + ) + + return usage_per_license + + def get_builder_usage_summary(self, license_object: License) -> BuilderUsageSummary: + """ + This method is used to calculate the number of application users that are + being used and how many are remaining. + + :param license_object: The License instance. + :return: A summary of the builder usage. + """ + + # Count the total number of application users in this instance + total_application_users_taken = BuilderHandler().aggregate_user_source_counts() + + # If there are no user source users, just exit early here. + if not total_application_users_taken: + return BuilderUsageSummary( + application_users_taken=total_application_users_taken + ) + + # Do we have a short-lived cache of the stacked license builder usage? + cached_stacked_summary = local_cache.get( + "stacked_instance_builder_license_usage", + lambda: self._calculate_stacked_license_builder_usage( + total_application_users_taken + ), + ) + + return cached_stacked_summary[license_object.license_id] + + def get_builder_usage_summary_for_workspace( + self, workspace: Workspace + ) -> Optional[BuilderUsageSummary]: + """ + This method is used to calculate the number of external users that are being + used in this workspace and how many are remaining. + + :param workspace: The workspace we are calculating the builder usage for. + :return: A summary of the builder usage. + """ + + from baserow.contrib.builder.handler import BuilderHandler + + return BuilderUsageSummary( + application_users_taken=BuilderHandler().aggregate_user_source_counts( + workspace + ) + ) + + def handle_application_user_overflow( + self, application_users_taken: int, license_object: License + ): + # TODO: send a notification, we are over limit. + ... + class LicenseTypeRegistry(Registry[LicenseType]): name = "license_type" diff --git a/premium/backend/tests/baserow_premium_tests/api/fields/test_ai_field_views.py b/premium/backend/tests/baserow_premium_tests/api/fields/test_ai_field_views.py index cc77f2dd5..d0b7ebf6c 100644 --- a/premium/backend/tests/baserow_premium_tests/api/fields/test_ai_field_views.py +++ b/premium/backend/tests/baserow_premium_tests/api/fields/test_ai_field_views.py @@ -33,10 +33,14 @@ def test_generate_ai_field_value_without_license(premium_data_fixture, api_clien table = premium_data_fixture.create_database_table(name="table", database=database) field = premium_data_fixture.create_ai_field(table=table, name="ai") - rows = RowHandler().create_rows( - user, - table, - rows_values=[{}], + rows = ( + RowHandler() + .create_rows( + user, + table, + rows_values=[{}], + ) + .created_rows ) response = api_client.post( @@ -71,10 +75,14 @@ def test_generate_ai_field_value_view_field_does_not_exist( table = premium_data_fixture.create_database_table(name="table", database=database) field = premium_data_fixture.create_ai_field(table=table, name="ai") - rows = RowHandler().create_rows( - user, - table, - rows_values=[{}], + rows = ( + RowHandler() + .create_rows( + user, + table, + rows_values=[{}], + ) + .created_rows ) response = api_client.post( @@ -110,10 +118,14 @@ def test_generate_ai_field_value_view_row_does_not_exist( table = premium_data_fixture.create_database_table(name="table", database=database) field = premium_data_fixture.create_ai_field(table=table, name="ai") - rows = RowHandler().create_rows( - user, - table, - rows_values=[{}], + rows = ( + RowHandler() + .create_rows( + user, + table, + rows_values=[{}], + ) + .created_rows ) response = api_client.post( @@ -155,10 +167,14 @@ def test_generate_ai_field_value_view_user_not_in_workspace( table = premium_data_fixture.create_database_table(name="table", database=database) field = premium_data_fixture.create_ai_field(table=table, name="ai") - rows = RowHandler().create_rows( - user, - table, - rows_values=[{}], + rows = ( + RowHandler() + .create_rows( + user, + table, + rows_values=[{}], + ) + .created_rows ) response = api_client.post( @@ -196,10 +212,14 @@ def test_generate_ai_field_value_view_generative_ai_does_not_exist( table=table, name="ai", ai_generative_ai_type="does_not_exist" ) - rows = RowHandler().create_rows( - user, - table, - rows_values=[{}], + rows = ( + RowHandler() + .create_rows( + user, + table, + rows_values=[{}], + ) + .created_rows ) response = api_client.post( @@ -237,12 +257,16 @@ def test_generate_ai_field_value_view_generative_ai_model_does_not_belong_to_typ table=table, name="ai", ai_generative_ai_model="does_not_exist" ) - rows = RowHandler().create_rows( - user, - table, - rows_values=[ - {}, - ], + rows = ( + RowHandler() + .create_rows( + user, + table, + rows_values=[ + {}, + ], + ) + .created_rows ) response = api_client.post( @@ -281,10 +305,14 @@ def test_generate_ai_field_value_view_generative_ai( table=table, name="ai", ai_prompt="'Hello'" ) - rows = RowHandler().create_rows( - user, - table, - rows_values=[{}], + rows = ( + RowHandler() + .create_rows( + user, + table, + rows_values=[{}], + ) + .created_rows ) assert patched_generate_ai_values_for_rows.call_count == 0 @@ -313,10 +341,14 @@ def test_batch_generate_ai_field_value_limit(api_client, premium_data_fixture): field = premium_data_fixture.create_ai_field( table=table, name="ai", ai_prompt="'Hello'" ) - rows = RowHandler().create_rows( - user, - table, - rows_values=[{}] * (settings.BATCH_ROWS_SIZE_LIMIT + 1), + rows = ( + RowHandler() + .create_rows( + user, + table, + rows_values=[{}] * (settings.BATCH_ROWS_SIZE_LIMIT + 1), + ) + .created_rows ) row_ids = [row.id for row in rows] diff --git a/premium/backend/tests/baserow_premium_tests/api/license/test_premium_license_views.py b/premium/backend/tests/baserow_premium_tests/api/license/test_premium_license_views.py index 4e160b291..571942b3c 100644 --- a/premium/backend/tests/baserow_premium_tests/api/license/test_premium_license_views.py +++ b/premium/backend/tests/baserow_premium_tests/api/license/test_premium_license_views.py @@ -107,7 +107,7 @@ def test_admin_list_licenses(api_client, data_fixture, django_assert_num_queries # We expect one to count the total number of users, one query for the user # check, one for the fetching the licenses including the count of # seats that are taken. - with django_assert_num_queries(3): + with django_assert_num_queries(5): response = api_client.get( reverse("api:premium:license:list"), format="json", @@ -303,7 +303,7 @@ def test_admin_get_license(api_client, data_fixture, django_assert_num_queries): with freeze_time("2021-09-01 00:00"): admin_token = data_fixture.generate_token(admin_user) - with django_assert_num_queries(5): + with django_assert_num_queries(6): response = api_client.get( reverse("api:premium:license:item", kwargs={"id": license.id}), format="json", diff --git a/premium/backend/tests/baserow_premium_tests/api/views/views/test_timeline_views.py b/premium/backend/tests/baserow_premium_tests/api/views/views/test_timeline_views.py index 771f8d775..e17a30bc0 100644 --- a/premium/backend/tests/baserow_premium_tests/api/views/views/test_timeline_views.py +++ b/premium/backend/tests/baserow_premium_tests/api/views/views/test_timeline_views.py @@ -1162,6 +1162,7 @@ def test_get_public_timeline_view(api_client, premium_data_fixture): "field": visible_sort.field.id, "id": visible_sort.id, "order": "DESC", + "type": "default", "view": timeline_view.slug, } ], diff --git a/premium/backend/tests/baserow_premium_tests/export/test_premium_export_types.py b/premium/backend/tests/baserow_premium_tests/export/test_premium_export_types.py index 359ea4ae1..af317fd9a 100644 --- a/premium/backend/tests/baserow_premium_tests/export/test_premium_export_types.py +++ b/premium/backend/tests/baserow_premium_tests/export/test_premium_export_types.py @@ -1,3 +1,4 @@ +import zipfile from io import BytesIO from unittest.mock import MagicMock, patch @@ -8,7 +9,9 @@ from baserow_premium.license.exceptions import FeaturesNotAvailableError from openpyxl import load_workbook from baserow.contrib.database.export.handler import ExportHandler +from baserow.contrib.database.export.models import EXPORT_JOB_FINISHED_STATUS from baserow.contrib.database.rows.handler import RowHandler +from baserow.core.storage import get_default_storage from baserow.test_utils.helpers import setup_interesting_test_table @@ -982,3 +985,270 @@ def test_can_export_every_interesting_different_field_to_excel_without_header( # Verify headers actual_headers = [cell.value for cell in worksheet[1]] assert actual_headers[0] == "1" + + +@pytest.mark.django_db +@override_settings(DEBUG=True) +def test_can_trigger_export_files_with_premium_license(premium_data_fixture): + options = {"exporter_type": "file"} + + user = premium_data_fixture.create_user(has_active_premium_license=True) + database = premium_data_fixture.create_database_application(user=user) + table = premium_data_fixture.create_database_table(database=database) + grid_view = premium_data_fixture.create_grid_view(table=table) + + ExportHandler().create_pending_export_job(user, table, grid_view, options) + + +@pytest.mark.django_db +@override_settings(DEBUG=True) +def test_cannot_trigger_export_files_without_premium_license(premium_data_fixture): + options = {"exporter_type": "file"} + + user = premium_data_fixture.create_user() + database = premium_data_fixture.create_database_application(user=user) + table = premium_data_fixture.create_database_table(database=database) + grid_view = premium_data_fixture.create_grid_view(table=table) + + with pytest.raises(FeaturesNotAvailableError): + ExportHandler().create_pending_export_job(user, table, grid_view, options) + + +@pytest.mark.django_db +@override_settings(DEBUG=True) +def test_cannnot_trigger_export_files_without_premium_license_for_group( + premium_data_fixture, alternative_per_workspace_license_service +): + options = {"exporter_type": "file"} + user = premium_data_fixture.create_user(has_active_premium_license=True) + database = premium_data_fixture.create_database_application(user=user) + table = premium_data_fixture.create_database_table(database=database) + + alternative_per_workspace_license_service.restrict_user_premium_to(user, [0]) + + grid_view = premium_data_fixture.create_grid_view(table=table) + + with pytest.raises(FeaturesNotAvailableError): + ExportHandler().create_pending_export_job(user, table, grid_view, options) + + +@pytest.mark.django_db +@override_settings(DEBUG=True) +def test_export_empty_files_does_not_fail(premium_data_fixture): + storage = get_default_storage() + + options = {"exporter_type": "file"} + user = premium_data_fixture.create_user(has_active_premium_license=True) + database = premium_data_fixture.create_database_application(user=user) + table = premium_data_fixture.create_database_table(database=database) + grid_view = premium_data_fixture.create_grid_view(table=table) + + handler = ExportHandler() + job = handler.create_pending_export_job(user, table, grid_view, options) + + handler.run_export_job(job) + + job.refresh_from_db() + + assert job.state == EXPORT_JOB_FINISHED_STATUS + assert job.exported_file_name is not None + + file_name = job.exported_file_name + + export_file_path = ExportHandler.export_file_path(file_name) + + assert storage.exists(export_file_path) + + with storage.open(export_file_path, "rb") as zip_file: + with zipfile.ZipFile(zip_file) as archive: + file_list = archive.namelist() + assert len(file_list) == 0 + + +@pytest.mark.django_db +@override_settings(DEBUG=True) +def test_export_non_empty_files_flat(premium_data_fixture, use_tmp_media_root): + storage = get_default_storage() + + user = premium_data_fixture.create_user(has_active_premium_license=True) + database = premium_data_fixture.create_database_application(user=user) + table = premium_data_fixture.create_database_table(database=database) + file_field = premium_data_fixture.create_file_field(table=table, name="File") + + row_handler = RowHandler() + model = table.get_model() + + user_file_1 = premium_data_fixture.create_user_file( + original_name="a.txt", + size=16, + mime_type="text/plain", + uploaded_by=user, + ) + premium_data_fixture.save_content_in_user_file( + user_file_1, storage, "Content of a.txt" + ) + + user_file_2 = premium_data_fixture.create_user_file( + original_name="b.txt", + size=16, + mime_type="text/plain", + uploaded_by=user, + ) + premium_data_fixture.save_content_in_user_file( + user_file_2, storage, "Content of b.txt" + ) + + user_file_3 = premium_data_fixture.create_user_file( + original_name="c.txt", + size=16, + mime_type="text/plain", + uploaded_by=user, + ) + premium_data_fixture.save_content_in_user_file( + user_file_3, storage, "Content of c.txt" + ) + + row_handler.create_row( + user=user, + table=table, + values={ + f"field_{file_field.id}": [ + {"name": user_file_1.name, "visible_name": "a.txt"}, + {"name": user_file_2.name, "visible_name": "b.txt"}, + ] + }, + model=model, + ) + row_handler.create_row( + user=user, + table=table, + values={ + f"field_{file_field.id}": [ + {"name": user_file_2.name, "visible_name": "b.txt"}, + {"name": user_file_3.name, "visible_name": "c.txt"}, + ] + }, + model=model, + ) + + grid_view = premium_data_fixture.create_grid_view(table=table) + + options = {"exporter_type": "file", "organize_files": False} + handler = ExportHandler() + job = handler.create_pending_export_job(user, table, grid_view, options) + + handler.run_export_job(job) + + job.refresh_from_db() + + assert job.state == EXPORT_JOB_FINISHED_STATUS + assert job.exported_file_name is not None + + file_name = job.exported_file_name + + export_file_path = ExportHandler.export_file_path(file_name) + + assert storage.exists(export_file_path) + + with storage.open(export_file_path, "rb") as zip_file: + with zipfile.ZipFile(zip_file) as archive: + file_list = archive.namelist() + assert len(file_list) == 3 + assert user_file_1.name in file_list + assert user_file_2.name in file_list + assert user_file_3.name in file_list + + +@pytest.mark.django_db +@override_settings(DEBUG=True) +def test_export_non_empty_files_group_by_row(premium_data_fixture, use_tmp_media_root): + storage = get_default_storage() + + user = premium_data_fixture.create_user(has_active_premium_license=True) + database = premium_data_fixture.create_database_application(user=user) + table = premium_data_fixture.create_database_table(database=database) + file_field = premium_data_fixture.create_file_field(table=table, name="File") + + row_handler = RowHandler() + model = table.get_model() + + user_file_1 = premium_data_fixture.create_user_file( + original_name="a.txt", + size=16, + mime_type="text/plain", + uploaded_by=user, + ) + premium_data_fixture.save_content_in_user_file( + user_file_1, storage, "Content of a.txt" + ) + + user_file_2 = premium_data_fixture.create_user_file( + original_name="b.txt", + size=16, + mime_type="text/plain", + uploaded_by=user, + ) + premium_data_fixture.save_content_in_user_file( + user_file_2, storage, "Content of b.txt" + ) + + user_file_3 = premium_data_fixture.create_user_file( + original_name="c.txt", + size=16, + mime_type="text/plain", + uploaded_by=user, + ) + premium_data_fixture.save_content_in_user_file( + user_file_3, storage, "Content of c.txt" + ) + + row_1 = row_handler.create_row( + user=user, + table=table, + values={ + f"field_{file_field.id}": [ + {"name": user_file_1.name, "visible_name": "a.txt"}, + {"name": user_file_2.name, "visible_name": "b.txt"}, + ] + }, + model=model, + ) + row_2 = row_handler.create_row( + user=user, + table=table, + values={ + f"field_{file_field.id}": [ + {"name": user_file_2.name, "visible_name": "b.txt"}, + {"name": user_file_3.name, "visible_name": "c.txt"}, + ] + }, + model=model, + ) + + grid_view = premium_data_fixture.create_grid_view(table=table) + + options = {"exporter_type": "file", "organize_files": True} + handler = ExportHandler() + job = handler.create_pending_export_job(user, table, grid_view, options) + + handler.run_export_job(job) + + job.refresh_from_db() + + assert job.state == EXPORT_JOB_FINISHED_STATUS + assert job.exported_file_name is not None + + file_name = job.exported_file_name + + export_file_path = ExportHandler.export_file_path(file_name) + + assert storage.exists(export_file_path) + + with storage.open(export_file_path, "rb") as zip_file: + with zipfile.ZipFile(zip_file) as archive: + file_list = archive.namelist() + assert len(file_list) == 4 + assert f"row_{row_1.id}/{user_file_1.name}" in file_list + assert f"row_{row_1.id}/{user_file_2.name}" in file_list + assert f"row_{row_2.id}/{user_file_2.name}" in file_list + assert f"row_{row_2.id}/{user_file_3.name}" in file_list diff --git a/premium/backend/tests/baserow_premium_tests/fields/test_ai_field_tasks.py b/premium/backend/tests/baserow_premium_tests/fields/test_ai_field_tasks.py index 32621d9ed..d3cceb7aa 100644 --- a/premium/backend/tests/baserow_premium_tests/fields/test_ai_field_tasks.py +++ b/premium/backend/tests/baserow_premium_tests/fields/test_ai_field_tasks.py @@ -29,7 +29,7 @@ def test_generate_ai_field_value_view_generative_ai( table=table, name="ai", ai_prompt="'Hello'" ) - rows = RowHandler().create_rows(user, table, rows_values=[{}]) + rows = RowHandler().create_rows(user, table, rows_values=[{}]).created_rows assert patched_rows_updated.call_count == 0 generate_ai_values_for_rows(user.id, field.id, [rows[0].id]) @@ -61,7 +61,7 @@ def test_generate_ai_field_value_view_generative_ai_with_temperature( table=table, name="ai", ai_prompt="'Hello'", ai_temperature=0.7 ) - rows = RowHandler().create_rows(user, table, rows_values=[{}]) + rows = RowHandler().create_rows(user, table, rows_values=[{}]).created_rows generate_ai_values_for_rows(user.id, field.id, [rows[0].id]) updated_row = patched_rows_updated.call_args[1]["rows"][0] @@ -92,12 +92,16 @@ def test_generate_ai_field_value_view_generative_ai_parse_formula( table=table, name="ai", ai_prompt=formula ) - rows = RowHandler().create_rows( - user, - table, - rows_values=[ - {f"field_{firstname.id}": "Bram", f"field_{lastname.id}": "Wiepjes"}, - ], + rows = ( + RowHandler() + .create_rows( + user, + table, + rows_values=[ + {f"field_{firstname.id}": "Bram", f"field_{lastname.id}": "Wiepjes"}, + ], + ) + .created_rows ) assert patched_rows_updated.call_count == 0 @@ -132,10 +136,14 @@ def test_generate_ai_field_value_view_generative_ai_invalid_field( table=table, name="ai", ai_prompt=formula ) - rows = RowHandler().create_rows( - user, - table, - rows_values=[{f"field_{firstname.id}": "Bram"}], + rows = ( + RowHandler() + .create_rows( + user, + table, + rows_values=[{f"field_{firstname.id}": "Bram"}], + ) + .created_rows ) assert patched_rows_updated.call_count == 0 generate_ai_values_for_rows(user.id, field.id, [rows[0].id]) @@ -172,10 +180,14 @@ def test_generate_ai_field_value_view_generative_ai_invalid_prompt( ai_prompt=formula, ) - rows = RowHandler().create_rows( - user, - table, - rows_values=[{f"field_{firstname.id}": "Bram"}], + rows = ( + RowHandler() + .create_rows( + user, + table, + rows_values=[{f"field_{firstname.id}": "Bram"}], + ) + .created_rows ) assert patched_rows_ai_values_generation_error.call_count == 0 diff --git a/premium/backend/tests/baserow_premium_tests/fields/test_ai_field_type.py b/premium/backend/tests/baserow_premium_tests/fields/test_ai_field_type.py index e67c14f0b..caf4a5c8c 100644 --- a/premium/backend/tests/baserow_premium_tests/fields/test_ai_field_type.py +++ b/premium/backend/tests/baserow_premium_tests/fields/test_ai_field_type.py @@ -1066,13 +1066,17 @@ def test_link_row_field_can_be_sorted_when_linking_an_ai_field(premium_data_fixt field=primary_b, value="b", color="green", order=0 ) - row_b1, row_b2 = RowHandler().force_create_rows( - user, - table_b, - [ - {primary_b.db_column: opt_1.id}, - {primary_b.db_column: opt_2.id}, - ], + row_b1, row_b2 = ( + RowHandler() + .force_create_rows( + user, + table_b, + [ + {primary_b.db_column: opt_1.id}, + {primary_b.db_column: opt_2.id}, + ], + ) + .created_rows ) table_a, table_b, link_field = premium_data_fixture.create_two_linked_tables( diff --git a/premium/backend/tests/baserow_premium_tests/license/test_license_handler.py b/premium/backend/tests/baserow_premium_tests/license/test_license_handler.py index cb84568bc..4bf5b9e0e 100644 --- a/premium/backend/tests/baserow_premium_tests/license/test_license_handler.py +++ b/premium/backend/tests/baserow_premium_tests/license/test_license_handler.py @@ -83,6 +83,8 @@ VALID_INSTANCE_TWO_LICENSE = ( b"=" ) VALID_ENTERPRISE_FIVE_SEAT_LICENSE = ( + # id: "3f0168af-afaf-4426-896b-b388391076e7" + # instance_id: "6d6366b8-6f32-4549-81c2-d4a0c07a334b" b"eyJ2ZXJzaW9uIjogMSwgImlkIjogIjNmMDE2OGFmLWFmYWYtNDQyNi04OTZiLWIzODgzOTEwNzZlNyIsI" b"CJ2YWxpZF9mcm9tIjogIjIwMjEtMDEtMDFUMDA6MDA6MDAiLCAidmFsaWRfdGhyb3VnaCI6ICIyMDIxLT" b"EyLTMxVDIzOjU5OjU5IiwgInByb2R1Y3RfY29kZSI6ICJlbnRlcnByaXNlIiwgInNlYXRzIjogNSwgIml" @@ -95,6 +97,46 @@ VALID_ENTERPRISE_FIVE_SEAT_LICENSE = ( b"oowm_5CZm8Ba6eL-YgI2vKTWfMsVZ9GkJxcaiK3d-AB_ipjub-VVyNXPiVWab7108w3EXmoZIvmhCc67g" b"bL3jA==" ) +VALID_PREMIUM_TEN_SEAT_TEN_APP_USER_LICENSE = ( + # id: "c26e4ef2-0492-4571-ad0d-49ca808c14b5" + # instance_id: "1" + b"eyJ2ZXJzaW9uIjogMSwgImlkIjogImMyNmU0ZWYyLTA0OTItNDU3MS1hZDBkLTQ5Y2E4MDhjMTRiNSIsI" + b"CJ2YWxpZF9mcm9tIjogIjIwMjUtMDItMDFUMDA6MDA6MDAiLCAidmFsaWRfdGhyb3VnaCI6ICIyMDI4LT" + b"AxLTAxVDIzOjU5OjU5IiwgInByb2R1Y3RfY29kZSI6ICJwcmVtaXVtIiwgInNlYXRzIjogMTAsICJhcHB" + b"saWNhdGlvbl91c2VycyI6IDEwLCAiaXNzdWVkX29uIjogIjIwMjUtMDItMTFUMTM6MzY6MjEuMDc1ODcz" + b"IiwgImlzc3VlZF90b19lbWFpbCI6ICJwZXRlckBiYXNlcm93LmlvIiwgImlzc3VlZF90b19uYW1lIjogI" + b"lBldGVyIiwgImluc3RhbmNlX2lkIjogIjEifQ==.tEholymqZF9aoYUAPDvufzCLylDk92MVpb6J7XJEs" + b"k0zdgMdKwlrvCqNBpqtfDWJYJWKVxX4xk4NjTPBjdPbSRZM--kSL1uBa6djpLUU0XoXaOg74P39PW7gcQ" + b"qrsWbZRdDWn6fFePWQ4U9w83t5OvxflZE2Qd8tvWYAVbgKRZXbpkzKoJgMrGoC2QVBIqy6KA3FZxw5EVT" + b"KfMTkE34y8SsmTsvlDmLlt2fpkrFwM2Vpi4mE7GiY4nf5f4_8UHckpG8tqA-OK6KV4kPL_aTTLwdcZDL-" + b"aULpNydqXUfGMMgKzjq1L1cULsoZQc9ueFZBh8KmA2PEjw4i1o70-xePIA==" +) +VALID_PREMIUM_5_SEAT_15_APP_USER_LICENSE = ( + b"eyJ2ZXJzaW9uIjogMSwgImlkIjogImY4YjRlOTk1LTJhMmEtNDg0NS04ZWI1LWM2MjBiYzA5YTdiMiIsI" + b"CJ2YWxpZF9mcm9tIjogIjIwMjUtMDItMDFUMDA6MDA6MDAiLCAidmFsaWRfdGhyb3VnaCI6ICIyMDI2LT" + b"AxLTAxVDIzOjU5OjU5IiwgInByb2R1Y3RfY29kZSI6ICJwcmVtaXVtIiwgInNlYXRzIjogNSwgImFwcGx" + b"pY2F0aW9uX3VzZXJzIjogMTUsICJpc3N1ZWRfb24iOiAiMjAyNS0wMi0xN1QxMTo0NToyNC44NjM3NjQi" + b"LCAiaXNzdWVkX3RvX2VtYWlsIjogInBldGVyQGJhc2Vyb3cuaW8iLCAiaXNzdWVkX3RvX25hbWUiOiAiU" + b"GV0ZXIiLCAiaW5zdGFuY2VfaWQiOiAiMSJ9.GsYLPV63FG5FAncOp6dyLysDqVSMR37C1zwTT-otZgGuu" + b"TpYg4aa9x-2ODonL9IAUmosyy6FZ1LcI4i8YdDyQ_rt-X_KhwR2S7Eotl6ZEepOYTbC7qKuG30szAKM6d" + b"4eL0unPB48pLJhSS_j745WgMn-4vUMmm6FTWaIPJaWFzwUjOp5zLgNpvvgkayzQ608XdYVjilVBcTlszj" + b"hxi00g0la2nMdCqDytZdJCn7XwAMA8itvSjYrWL1gMqTtPL6U92bJz97n8wQRBFW8kNKb2JTPfcbwozeg" + b"Vd44sPwBqWaA0wwpKyNs-Sa43FHcbQKIGG8A68hKQy2MG3EWHgLWTA==" +) +VALID_ENTERPRISE_FIFTEEN_SEAT_FIFTEEN_APP_USER_LICENSE = ( + # id: "06b9bec3-d5d9-4286-be5a-c25b94188303" + # instance_id: "1" + b"eyJ2ZXJzaW9uIjogMSwgImlkIjogIjA2YjliZWMzLWQ1ZDktNDI4Ni1iZTVhLWMyNWI5NDE4ODMwMyIsI" + b"CJ2YWxpZF9mcm9tIjogIjIwMjUtMDItMDFUMDA6MDA6MDAiLCAidmFsaWRfdGhyb3VnaCI6ICIyMDI4LT" + b"AxLTAxVDIzOjU5OjU5IiwgInByb2R1Y3RfY29kZSI6ICJlbnRlcnByaXNlIiwgInNlYXRzIjogMTUsICJ" + b"hcHBsaWNhdGlvbl91c2VycyI6IDE1LCAiaXNzdWVkX29uIjogIjIwMjUtMDItMTFUMTM6MzU6MjYuODYy" + b"NTg3IiwgImlzc3VlZF90b19lbWFpbCI6ICJwZXRlckBiYXNlcm93LmlvIiwgImlzc3VlZF90b19uYW1lI" + b"jogIlBldGVyIiwgImluc3RhbmNlX2lkIjogIjEifQ==.u1ws8JSZHta15GVqiUdQRb592aeIuAUxSNMDm" + b"_WAY1rSFzeY74MLhl7aQ3ZB5JalUwuT8Bi1PqCBqiSSVJGdF5pL4u25Gwn10mNDvfXmRh34DvV7ZIYdpV" + b"C_WiPOkeojoXtawuNmIzePON1pAv6TfG9Qq_57vSshht49TiG2PTYGdeeZa9sbrP589dhkIk0UY6Z6aCZ" + b"voGAXz0rbrsS6lQUFqkYdBgA4LpgsrWWjLRxKdmy64CYj1k37ERtU8w-uauhYW3IUHDmDiZQYjNrL7g7q" + b"Elk5YJBqjseMM_J4VkgULax1TDyG-q114UKCeCrCFA4pqsbxvGJ41-Le_-JOEg==" +) INVALID_SIGNATURE_LICENSE = ( b"eyJ2ZXJzaW9uIjogMSwgImlkIjogMSwgInZhbGlkX2Zyb20iOiAiMjAyMS0wOC0yOVQxOTo1NDoxMi4w" b"NjY4NDYiLCAidmFsaWRfdGhyb3VnaCI6ICIyMDIxLTA5LTI5VDE5OjU0OjEyLjA2Njg0NiIsICJwcm9k" @@ -119,6 +161,18 @@ INVALID_VERSION_LICENSE = ( b"CVof8RBUq1DgMcDKEGE7WRHYDVP1QugBjf4GZlvIE4ZVr3tKr0aKPX8nuNVhbQeudCW8tnturmxevpRN" b"vLS5ETSQzJoP46cGuw0HUV20P4SnvQP_NRd5zifgllJqsUw==" ) +INVALID_PREMIUM_FIVE_SEAT_10_APP_USER_EXPIRED_LICENSE = ( + b"eyJ2ZXJzaW9uIjogMSwgImlkIjogIjkzZDExODYwLTU1Y2UtNDJhYy05NGI5LTY0YTlhMTBiNzI3MiIsI" + b"CJ2YWxpZF9mcm9tIjogIjIwMjUtMDItMDFUMDA6MDA6MDAiLCAidmFsaWRfdGhyb3VnaCI6ICIyMDI1LT" + b"AyLTA4VDIzOjU5OjU5IiwgInByb2R1Y3RfY29kZSI6ICJwcmVtaXVtIiwgInNlYXRzIjogNSwgImFwcGx" + b"pY2F0aW9uX3VzZXJzIjogMTAsICJpc3N1ZWRfb24iOiAiMjAyNS0wMi0xOFQxMToxMDowNS40NjE3NzAi" + b"LCAiaXNzdWVkX3RvX2VtYWlsIjogInBldGVyQGJhc2Vyb3cuaW8iLCAiaXNzdWVkX3RvX25hbWUiOiAiU" + b"GV0ZXIiLCAiaW5zdGFuY2VfaWQiOiAiMSJ9.DJXyKA1MEMcR7hLFiITLteBQbgZhLpOVqLT1GoWqiC60B" + b"WiEz223qTnYE06ibqMF_YF__Cr1ejS7brplUa1_56G0MDtTobVzH5-IJIiVt1KXGkUoYZdCuD6ouk9maH" + b"2ycOWEqZZsWROaLJ_ipzyxbYeiVrBuYEv5P5IhsmeEbAH9Gj5e4vjkwHmZjZGlW-4Ejo8NXC6uhdcxx7b" + b"t89MaAKEk-cYmtKL0eJEUrKvU2drHuo0ft6QusXHyzROPD82h1pgBNQNDSkHwmY9hxaHdbCjsojPVLARU" + b"tsAx2YIDwpQ5QDyPA1s6OqG4e72l1sUUE4fxjHF7-FKEHQwAsvOZzg==" +) NOT_JSON_PAYLOAD_LICENSE = ( b"dGVzdA==.I37aSmuKN0WSrw6IDTg2xBOlQ3UOE5cjaWfc4MF5pgIadMUjkOh0D32R7RqRhmsxhdsqK6a" b"bU8u8cT6ZG0PxjsRnFjrkbhdcFR1Yw9fHQ7plHShnpsj0NT8fMuDaVfCibKxyi-Z8nVmwHEIlyRkLfKV" @@ -191,19 +245,19 @@ def test_has_active_premium_license(data_fixture): @override_settings(DEBUG=True) def test_check_active_premium_license_for_workspace_with_valid_license(data_fixture): user_in_license = data_fixture.create_user() - group = data_fixture.create_workspace(user=user_in_license) + workspace = data_fixture.create_workspace(user=user_in_license) license = License.objects.create(license=VALID_TWO_SEAT_LICENSE.decode()) LicenseUser.objects.create(license=license, user=user_in_license) with freeze_time("2021-08-01 12:00"): with pytest.raises(FeaturesNotAvailableError): LicenseHandler.raise_if_user_doesnt_have_feature( - PREMIUM, user_in_license, group + PREMIUM, user_in_license, workspace ) with freeze_time("2021-09-01 12:00"): LicenseHandler.raise_if_user_doesnt_have_feature( - PREMIUM, user_in_license, group + PREMIUM, user_in_license, workspace ) @@ -385,9 +439,12 @@ def test_check_licenses_with_authority_check(premium_data_fixture): license="instance_id_mismatch" ) updated_license = premium_data_fixture.create_premium_license(license="update") - ok_license = premium_data_fixture.create_premium_license( + valid_license_without_builder = premium_data_fixture.create_premium_license( license=VALID_TWO_SEAT_LICENSE.decode() ) + valid_license_with_builder = premium_data_fixture.create_premium_license( + license=VALID_PREMIUM_TEN_SEAT_TEN_APP_USER_LICENSE.decode() + ) with freeze_time("2021-07-01 12:00"): responses.add( @@ -406,6 +463,10 @@ def test_check_licenses_with_authority_check(premium_data_fixture): "new_license_payload": VALID_ONE_SEAT_LICENSE.decode(), }, VALID_TWO_SEAT_LICENSE.decode(): {"type": "ok", "detail": ""}, + VALID_PREMIUM_TEN_SEAT_TEN_APP_USER_LICENSE.decode(): { + "type": "ok", + "detail": "", + }, }, status=200, ) @@ -416,18 +477,21 @@ def test_check_licenses_with_authority_check(premium_data_fixture): does_not_exist_license, instance_id_mismatch_license, updated_license, - ok_license, + valid_license_without_builder, + valid_license_with_builder, ] ) all_licenses = License.objects.all().order_by("id") - assert len(all_licenses) == 2 + assert len(all_licenses) == 3 assert all_licenses[0].id == updated_license.id assert all_licenses[0].license == VALID_ONE_SEAT_LICENSE.decode() assert all_licenses[0].license_id == "1" assert all_licenses[0].last_check.year == 2021 - assert all_licenses[1].id == ok_license.id + assert all_licenses[1].id == valid_license_without_builder.id assert all_licenses[1].last_check.year == 2021 + assert all_licenses[2].id == valid_license_with_builder.id + assert all_licenses[2].last_check.year == 2021 @pytest.mark.django_db @@ -540,6 +604,48 @@ def test_decode_license_with_valid_license(): "issued_to_name": "Bram", "instance_id": "2", } + assert LicenseHandler.decode_license(VALID_ENTERPRISE_FIVE_SEAT_LICENSE) == { + "version": 1, + "id": "3f0168af-afaf-4426-896b-b388391076e7", + "valid_from": "2021-01-01T00:00:00", + "valid_through": "2021-12-31T23:59:59", + "product_code": "enterprise", + "seats": 5, + "issued_on": "2023-01-11T14:53:45.372950", + "issued_to_email": "petr@example.com", + "issued_to_name": "petr@example.com", + "instance_id": "6d6366b8-6f32-4549-81c2-d4a0c07a334b", + } + assert LicenseHandler.decode_license( + VALID_ENTERPRISE_FIFTEEN_SEAT_FIFTEEN_APP_USER_LICENSE + ) == { + "version": 1, + "id": "06b9bec3-d5d9-4286-be5a-c25b94188303", + "valid_from": "2025-02-01T00:00:00", + "valid_through": "2028-01-01T23:59:59", + "product_code": "enterprise", + "seats": 15, + "application_users": 15, + "issued_on": "2025-02-11T13:35:26.862587", + "issued_to_email": "peter@baserow.io", + "issued_to_name": "Peter", + "instance_id": "1", + } + assert LicenseHandler.decode_license( + VALID_PREMIUM_TEN_SEAT_TEN_APP_USER_LICENSE + ) == { + "version": 1, + "id": "c26e4ef2-0492-4571-ad0d-49ca808c14b5", + "valid_from": "2025-02-01T00:00:00", + "valid_through": "2028-01-01T23:59:59", + "product_code": "premium", + "seats": 10, + "application_users": 10, + "issued_on": "2025-02-11T13:36:21.075873", + "issued_to_email": "peter@baserow.io", + "issued_to_name": "Peter", + "instance_id": "1", + } @override_settings(DEBUG=True) @@ -961,7 +1067,7 @@ def test_check_active_premium_license_for_workspace_with_license_pretending_to_b data_fixture, ): user_in_license = data_fixture.create_user() - group = data_fixture.create_workspace(user=user_in_license) + workspace = data_fixture.create_workspace(user=user_in_license) license = License.objects.create( license=VALID_TWO_SEAT_LICENSE.decode(), cached_untrusted_instance_wide=True ) @@ -970,13 +1076,13 @@ def test_check_active_premium_license_for_workspace_with_license_pretending_to_b with freeze_time("2021-08-01 12:00"): with pytest.raises(FeaturesNotAvailableError): LicenseHandler.raise_if_user_doesnt_have_feature( - PREMIUM, user_in_license, group + PREMIUM, user_in_license, workspace ) with freeze_time("2021-09-01 12:00"): with pytest.raises(FeaturesNotAvailableError): LicenseHandler.raise_if_user_doesnt_have_feature( - PREMIUM, user_in_license, group + PREMIUM, user_in_license, workspace ) with freeze_time("2021-09-01 12:00"): @@ -1003,3 +1109,74 @@ def test_add_active_licenses_to_settings(api_client, data_fixture): response_json = response.json() assert len(response_json.keys()) > 1 assert response_json["instance_wide_licenses"] == {"enterprise": True} + + +@pytest.mark.django_db +@override_settings(DEBUG=True) +@patch("baserow_premium.license.registries.BuilderHandler.aggregate_user_source_counts") +def test_premium_license_builder_usage_license_extra_info( + mock_aggregate_user_source_counts, premium_data_fixture +): + # We have a single premium license, with 5 application users taken. + mock_aggregate_user_source_counts.return_value = 5 + first_license = premium_data_fixture.create_premium_license( + license=VALID_PREMIUM_TEN_SEAT_TEN_APP_USER_LICENSE.decode() + ) + with local_cache.context(): + assert LicenseHandler.collect_extra_license_info(first_license) == { + "id": first_license.license_id, + "seats_taken": 0, + "free_users_count": 0, + "highest_role_per_user_id": {}, + "application_users_taken": 5, + } + + # Introduce a second premium license, so we now have 25 application + # users available, but now our application users taken is 30. + mock_aggregate_user_source_counts.return_value = 30 + second_license = premium_data_fixture.create_premium_license( + license=VALID_PREMIUM_5_SEAT_15_APP_USER_LICENSE.decode() + ) + + with local_cache.context(): + # Re-check the first license, its `application_users_taken` + # count is the `application_users` count. + assert LicenseHandler.collect_extra_license_info(first_license) == { + "id": first_license.license_id, + "seats_taken": 0, + "free_users_count": 0, + "highest_role_per_user_id": {}, + "application_users_taken": 10, + } + # The second license `application_users_taken` count overflows. + assert LicenseHandler.collect_extra_license_info(second_license) == { + "id": second_license.license_id, + "seats_taken": 0, + "free_users_count": 0, + "highest_role_per_user_id": {}, + "application_users_taken": 20, + } + + first_license.delete() + + with local_cache.context(): + # An expired license reports an application user usage of 0. + expired_license = premium_data_fixture.create_premium_license( + license=INVALID_PREMIUM_FIVE_SEAT_10_APP_USER_EXPIRED_LICENSE.decode() + ) + assert LicenseHandler.collect_extra_license_info(expired_license) == { + "id": expired_license.license_id, + "seats_taken": 0, + "free_users_count": 0, + "highest_role_per_user_id": {}, + "application_users_taken": 0, + } + # The second license is now the only active license, so it reports the + # full application user usage, which overflows. + assert LicenseHandler.collect_extra_license_info(second_license) == { + "id": second_license.license_id, + "seats_taken": 0, + "free_users_count": 0, + "highest_role_per_user_id": {}, + "application_users_taken": 30, + } diff --git a/premium/backend/tests/baserow_premium_tests/license/test_license_models.py b/premium/backend/tests/baserow_premium_tests/license/test_license_models.py index b259de38c..a99bea19c 100644 --- a/premium/backend/tests/baserow_premium_tests/license/test_license_models.py +++ b/premium/backend/tests/baserow_premium_tests/license/test_license_models.py @@ -72,6 +72,15 @@ def test_premium_license_model_is_active(): assert not license.is_active +@pytest.mark.django_db +@override_settings(DEBUG=True) +def test_premium_license_model_valid_payload(): + invalid_license = License(license="invalid") + assert not invalid_license.valid_payload + valid_license = License(license=VALID_ONE_SEAT_LICENSE.decode()) + assert valid_license.valid_payload + + @pytest.mark.django_db @override_settings(DEBUG=True) def test_premium_license_model_save(): diff --git a/premium/backend/tests/baserow_premium_tests/license/test_license_types.py b/premium/backend/tests/baserow_premium_tests/license/test_license_types.py new file mode 100644 index 000000000..5734c3e80 --- /dev/null +++ b/premium/backend/tests/baserow_premium_tests/license/test_license_types.py @@ -0,0 +1,138 @@ +from unittest.mock import patch + +from django.test.utils import override_settings + +import pytest + +VALID_FIRST_PREMIUM_5_SEAT_10_APP_USER_LICENSE = ( + b"eyJ2ZXJzaW9uIjogMSwgImlkIjogIjhiZmMwNzA1LWUwZGEtNGNkNy1hMWE0LWNjNDNiYjViMTE4OCIsI" + b"CJ2YWxpZF9mcm9tIjogIjIwMjUtMDItMDFUMDA6MDA6MDAiLCAidmFsaWRfdGhyb3VnaCI6ICIyMDI2LT" + b"AxLTAxVDIzOjU5OjU5IiwgInByb2R1Y3RfY29kZSI6ICJwcmVtaXVtIiwgInNlYXRzIjogNSwgImFwcGx" + b"pY2F0aW9uX3VzZXJzIjogMTAsICJpc3N1ZWRfb24iOiAiMjAyNS0wMi0xN1QxMTo0NToxOS44NDI3OTYi" + b"LCAiaXNzdWVkX3RvX2VtYWlsIjogInBldGVyQGJhc2Vyb3cuaW8iLCAiaXNzdWVkX3RvX25hbWUiOiAiU" + b"GV0ZXIiLCAiaW5zdGFuY2VfaWQiOiAiMSJ9.oSV2phIkZHsVXsQN1X2E4hKab7_-JLaz2b93M3GHx3zvt" + b"_XTdeZRd-VK8ZvFdFDLh1LkKa4NAs8tSg8H1jN1xprkr-VFGA_-_owZrn59jK7UBOrd8p1WZur36ud5uG" + b"DRsyw-yLmBhuFj27jE_3GZz-93xPnrDATjbT9NrXfrOggsyhn36tNLqydmrdpu45KdLD1SRrm7zcKaG8L" + b"CHnlgSAd8md0923z7xf5vpTtB1rdJKUGj8kpjK7bxNojgmzZasGG424YbmSmk0B6yLvm18hIwv7_2Telk" + b"hs8huMXL7HHDlEK2O7GmmCBoWT0ACNmcBhq4OcZ0K1pPX7MXvU3RNQ==" +) + +VALID_SECOND_PREMIUM_5_SEAT_15_APP_USER_LICENSE = ( + b"eyJ2ZXJzaW9uIjogMSwgImlkIjogImY4YjRlOTk1LTJhMmEtNDg0NS04ZWI1LWM2MjBiYzA5YTdiMiIsI" + b"CJ2YWxpZF9mcm9tIjogIjIwMjUtMDItMDFUMDA6MDA6MDAiLCAidmFsaWRfdGhyb3VnaCI6ICIyMDI2LT" + b"AxLTAxVDIzOjU5OjU5IiwgInByb2R1Y3RfY29kZSI6ICJwcmVtaXVtIiwgInNlYXRzIjogNSwgImFwcGx" + b"pY2F0aW9uX3VzZXJzIjogMTUsICJpc3N1ZWRfb24iOiAiMjAyNS0wMi0xN1QxMTo0NToyNC44NjM3NjQi" + b"LCAiaXNzdWVkX3RvX2VtYWlsIjogInBldGVyQGJhc2Vyb3cuaW8iLCAiaXNzdWVkX3RvX25hbWUiOiAiU" + b"GV0ZXIiLCAiaW5zdGFuY2VfaWQiOiAiMSJ9.GsYLPV63FG5FAncOp6dyLysDqVSMR37C1zwTT-otZgGuu" + b"TpYg4aa9x-2ODonL9IAUmosyy6FZ1LcI4i8YdDyQ_rt-X_KhwR2S7Eotl6ZEepOYTbC7qKuG30szAKM6d" + b"4eL0unPB48pLJhSS_j745WgMn-4vUMmm6FTWaIPJaWFzwUjOp5zLgNpvvgkayzQ608XdYVjilVBcTlszj" + b"hxi00g0la2nMdCqDytZdJCn7XwAMA8itvSjYrWL1gMqTtPL6U92bJz97n8wQRBFW8kNKb2JTPfcbwozeg" + b"Vd44sPwBqWaA0wwpKyNs-Sa43FHcbQKIGG8A68hKQy2MG3EWHgLWTA==" +) + +VALID_ENTERPRISE_15_SEAT_15_APP_USER_LICENSE = ( + b"eyJ2ZXJzaW9uIjogMSwgImlkIjogIjA2YjliZWMzLWQ1ZDktNDI4Ni1iZTVhLWMyNWI5NDE4ODMwMyIsI" + b"CJ2YWxpZF9mcm9tIjogIjIwMjUtMDItMDFUMDA6MDA6MDAiLCAidmFsaWRfdGhyb3VnaCI6ICIyMDI4LT" + b"AxLTAxVDIzOjU5OjU5IiwgInByb2R1Y3RfY29kZSI6ICJlbnRlcnByaXNlIiwgInNlYXRzIjogMTUsICJ" + b"hcHBsaWNhdGlvbl91c2VycyI6IDE1LCAiaXNzdWVkX29uIjogIjIwMjUtMDItMTFUMTM6MzU6MjYuODYy" + b"NTg3IiwgImlzc3VlZF90b19lbWFpbCI6ICJwZXRlckBiYXNlcm93LmlvIiwgImlzc3VlZF90b19uYW1lI" + b"jogIlBldGVyIiwgImluc3RhbmNlX2lkIjogIjEifQ==.u1ws8JSZHta15GVqiUdQRb592aeIuAUxSNMDm" + b"_WAY1rSFzeY74MLhl7aQ3ZB5JalUwuT8Bi1PqCBqiSSVJGdF5pL4u25Gwn10mNDvfXmRh34DvV7ZIYdpV" + b"C_WiPOkeojoXtawuNmIzePON1pAv6TfG9Qq_57vSshht49TiG2PTYGdeeZa9sbrP589dhkIk0UY6Z6aCZ" + b"voGAXz0rbrsS6lQUFqkYdBgA4LpgsrWWjLRxKdmy64CYj1k37ERtU8w-uauhYW3IUHDmDiZQYjNrL7g7q" + b"Elk5YJBqjseMM_J4VkgULax1TDyG-q114UKCeCrCFA4pqsbxvGJ41-Le_-JOEg==" +) +VALID_ENTERPRISE_FIVE_SEAT_LICENSE = ( + b"eyJ2ZXJzaW9uIjogMSwgImlkIjogIjNmMDE2OGFmLWFmYWYtNDQyNi04OTZiLWIzODgzOTEwNzZlNyIsI" + b"CJ2YWxpZF9mcm9tIjogIjIwMjEtMDEtMDFUMDA6MDA6MDAiLCAidmFsaWRfdGhyb3VnaCI6ICIyMDIxLT" + b"EyLTMxVDIzOjU5OjU5IiwgInByb2R1Y3RfY29kZSI6ICJlbnRlcnByaXNlIiwgInNlYXRzIjogNSwgIml" + b"zc3VlZF9vbiI6ICIyMDIzLTAxLTExVDE0OjUzOjQ1LjM3Mjk1MCIsICJpc3N1ZWRfdG9fZW1haWwiOiAi" + b"cGV0ckBleGFtcGxlLmNvbSIsICJpc3N1ZWRfdG9fbmFtZSI6ICJwZXRyQGV4YW1wbGUuY29tIiwgImluc" + b"3RhbmNlX2lkIjogIjZkNjM2NmI4LTZmMzItNDU0OS04MWMyLWQ0YTBjMDdhMzM0YiJ9.B6os-CyNrp5wW" + b"3gDTwjariLS6KhUBFYBwOlDlpVkTB8BPe1yjVIxw7nRH09TXovp9oTc2iJkGY5znBxuFMbCotmnIkBTnw" + b"p6uOhBMlPQFydzUXt1GmaWpEEcTSV7hKNVykPasEBCTK3Z4CA-eTjJBKo7vGCT7qTu01I4ghgI4aBEM5J" + b"qMe-ngEomRVnRMPAEgCNjFB44rVAB3zcJfPuBoukRB2FjOw1ddEkA3DjwcHlhkj1NcETlyUpFbFtCjhtL" + b"oowm_5CZm8Ba6eL-YgI2vKTWfMsVZ9GkJxcaiK3d-AB_ipjub-VVyNXPiVWab7108w3EXmoZIvmhCc67g" + b"bL3jA==" +) + + +@pytest.mark.django_db +@override_settings(DEBUG=True) +@patch("baserow_premium.license.registries.BuilderHandler.aggregate_user_source_counts") +def test_get_builder_usage_summary_for_single_premium_license( + mock_aggregate_user_source_counts, premium_data_fixture +): + mock_aggregate_user_source_counts.return_value = 5 + valid_license = premium_data_fixture.create_premium_license( + license=VALID_FIRST_PREMIUM_5_SEAT_10_APP_USER_LICENSE.decode() + ) + summary = valid_license.license_type.get_builder_usage_summary(valid_license) + + assert summary.application_users_taken == 5 + assert valid_license.application_users == 10 + + +@pytest.mark.django_db +@override_settings(DEBUG=True) +@patch("baserow_premium.license.registries.BuilderHandler.aggregate_user_source_counts") +def test_get_builder_usage_summary_for_multiple_stacked_premium_licenses( + mock_aggregate_user_source_counts, premium_data_fixture +): + mock_aggregate_user_source_counts.return_value = 26 # one more than allowed + + valid_license_a = premium_data_fixture.create_premium_license( + license=VALID_FIRST_PREMIUM_5_SEAT_10_APP_USER_LICENSE.decode() + ) + valid_license_b = premium_data_fixture.create_premium_license( + license=VALID_SECOND_PREMIUM_5_SEAT_15_APP_USER_LICENSE.decode() + ) + + summary_a = valid_license_a.license_type.get_builder_usage_summary(valid_license_a) + assert summary_a.application_users_taken == 10 + assert valid_license_a.application_users == 10 + + summary_b = valid_license_b.license_type.get_builder_usage_summary(valid_license_b) + assert summary_b.application_users_taken == 16 + assert valid_license_b.application_users == 15 + + +@pytest.mark.django_db +@override_settings(DEBUG=True) +@patch("baserow_premium.license.registries.BuilderHandler.aggregate_user_source_counts") +def test_get_builder_usage_summary_for_multiple_stacked_premium_and_enterprise_licenses( + mock_aggregate_user_source_counts, premium_data_fixture +): + from baserow_premium.license.models import License + + mock_aggregate_user_source_counts.return_value = 26 # one more than allowed + + valid_builder_license_a = premium_data_fixture.create_premium_license( + license=VALID_FIRST_PREMIUM_5_SEAT_10_APP_USER_LICENSE.decode() + ) + valid_builder_license_b = License.objects.create( + license=VALID_ENTERPRISE_15_SEAT_15_APP_USER_LICENSE.decode(), + cached_untrusted_instance_wide=True, + ) + valid_non_builder_license_c = License.objects.create( + license=VALID_ENTERPRISE_FIVE_SEAT_LICENSE.decode(), + cached_untrusted_instance_wide=True, + ) + + summary_a = valid_builder_license_a.license_type.get_builder_usage_summary( + valid_builder_license_a + ) + assert summary_a.application_users_taken == 10 + assert valid_builder_license_a.application_users == 10 + + summary_b = valid_builder_license_b.license_type.get_builder_usage_summary( + valid_builder_license_b + ) + assert summary_b.application_users_taken == 16 + assert valid_builder_license_b.application_users == 15 + + summary_c = valid_non_builder_license_c.license_type.get_builder_usage_summary( + valid_non_builder_license_c + ) + assert summary_c.application_users_taken == 0 + assert valid_non_builder_license_c.application_users is None diff --git a/premium/web-frontend/modules/baserow_premium/assets/scss/components/licenses.scss b/premium/web-frontend/modules/baserow_premium/assets/scss/components/licenses.scss index ce4bda1bc..27eed2fb6 100644 --- a/premium/web-frontend/modules/baserow_premium/assets/scss/components/licenses.scss +++ b/premium/web-frontend/modules/baserow_premium/assets/scss/components/licenses.scss @@ -81,7 +81,7 @@ .licenses__item-details { list-style: none; - margin: 0; + margin: 15px 0 0; padding: 0; display: flex; } diff --git a/premium/web-frontend/modules/baserow_premium/assets/scss/components/row_edit_modal_comments_notification_mode.scss b/premium/web-frontend/modules/baserow_premium/assets/scss/components/row_edit_modal_comments_notification_mode.scss index 936e1a9fc..a14ba2843 100644 --- a/premium/web-frontend/modules/baserow_premium/assets/scss/components/row_edit_modal_comments_notification_mode.scss +++ b/premium/web-frontend/modules/baserow_premium/assets/scss/components/row_edit_modal_comments_notification_mode.scss @@ -6,4 +6,4 @@ &:hover { color: $color-neutral-800; } - } \ No newline at end of file +} diff --git a/premium/web-frontend/modules/baserow_premium/assets/scss/components/views/all.scss b/premium/web-frontend/modules/baserow_premium/assets/scss/components/views/all.scss index dca9222ff..285d56b22 100644 --- a/premium/web-frontend/modules/baserow_premium/assets/scss/components/views/all.scss +++ b/premium/web-frontend/modules/baserow_premium/assets/scss/components/views/all.scss @@ -4,4 +4,4 @@ @import 'kanban'; @import 'decorators'; @import 'view_date_selector'; -@import 'view_date_indicator'; \ No newline at end of file +@import 'view_date_indicator'; diff --git a/premium/web-frontend/modules/baserow_premium/assets/scss/components/views/timeline/all.scss b/premium/web-frontend/modules/baserow_premium/assets/scss/components/views/timeline/all.scss index ca40c0336..d564dbe25 100644 --- a/premium/web-frontend/modules/baserow_premium/assets/scss/components/views/timeline/all.scss +++ b/premium/web-frontend/modules/baserow_premium/assets/scss/components/views/timeline/all.scss @@ -4,4 +4,4 @@ @import 'timeline_date_settings_init_box'; @import 'timeline_grid'; @import 'timeline_grid_row'; -@import 'timeline_timescale_context'; \ No newline at end of file +@import 'timeline_timescale_context'; diff --git a/premium/web-frontend/modules/baserow_premium/assets/scss/components/views/timeline/timeline_grid_row.scss b/premium/web-frontend/modules/baserow_premium/assets/scss/components/views/timeline/timeline_grid_row.scss index a50855a7e..83609103b 100644 --- a/premium/web-frontend/modules/baserow_premium/assets/scss/components/views/timeline/timeline_grid_row.scss +++ b/premium/web-frontend/modules/baserow_premium/assets/scss/components/views/timeline/timeline_grid_row.scss @@ -44,7 +44,7 @@ .timeline-grid-row__label { @extend %ellipsis; - + margin-right: 8px; font-size: 12px; line-height: 20px; diff --git a/premium/web-frontend/modules/baserow_premium/assets/scss/components/views/timeline/timeline_timescale_context.scss b/premium/web-frontend/modules/baserow_premium/assets/scss/components/views/timeline/timeline_timescale_context.scss index 9e53a49ef..1b5cc9e9a 100644 --- a/premium/web-frontend/modules/baserow_premium/assets/scss/components/views/timeline/timeline_timescale_context.scss +++ b/premium/web-frontend/modules/baserow_premium/assets/scss/components/views/timeline/timeline_timescale_context.scss @@ -6,4 +6,4 @@ display: flex; align-items: center; justify-content: space-between; -} \ No newline at end of file +} diff --git a/premium/web-frontend/modules/baserow_premium/assets/scss/components/views/timeline/timeline_view.scss b/premium/web-frontend/modules/baserow_premium/assets/scss/components/views/timeline/timeline_view.scss index 9aa640b54..6e1e507be 100644 --- a/premium/web-frontend/modules/baserow_premium/assets/scss/components/views/timeline/timeline_view.scss +++ b/premium/web-frontend/modules/baserow_premium/assets/scss/components/views/timeline/timeline_view.scss @@ -2,4 +2,4 @@ width: 100%; height: 100%; overflow-y: auto; -} \ No newline at end of file +} diff --git a/premium/web-frontend/modules/baserow_premium/components/exporter/TableFileExporter.vue b/premium/web-frontend/modules/baserow_premium/components/exporter/TableFileExporter.vue new file mode 100644 index 000000000..1ead48535 --- /dev/null +++ b/premium/web-frontend/modules/baserow_premium/components/exporter/TableFileExporter.vue @@ -0,0 +1,40 @@ +<template> + <div> + <div class="row"> + <div class="col col-12"> + <FormGroup + :label="$t('tableFileExporter.organizeFiles')" + required + small-label + class="margin-bottom-2" + > + <Checkbox v-model="values.organize_files" :disabled="loading">{{ + $t('common.yes') + }}</Checkbox> + </FormGroup> + </div> + </div> + </div> +</template> + +<script> +import form from '@baserow/modules/core/mixins/form' + +export default { + name: 'TableFileExporter', + mixins: [form], + props: { + loading: { + type: Boolean, + required: true, + }, + }, + data() { + return { + values: { + organize_files: false, + }, + } + }, +} +</script> diff --git a/premium/web-frontend/modules/baserow_premium/components/license/RegisterLicenseForm.vue b/premium/web-frontend/modules/baserow_premium/components/license/RegisterLicenseForm.vue index 93e39e13d..27e1c3398 100644 --- a/premium/web-frontend/modules/baserow_premium/components/license/RegisterLicenseForm.vue +++ b/premium/web-frontend/modules/baserow_premium/components/license/RegisterLicenseForm.vue @@ -11,6 +11,7 @@ v-model="v$.values.license.$model" :error="fieldHasErrors('license')" :rows="6" + @blur="v$.values.license.$touch()" /> <template #error> diff --git a/premium/web-frontend/modules/baserow_premium/fieldTypes.js b/premium/web-frontend/modules/baserow_premium/fieldTypes.js index 83be13a27..4ef1b520b 100644 --- a/premium/web-frontend/modules/baserow_premium/fieldTypes.js +++ b/premium/web-frontend/modules/baserow_premium/fieldTypes.js @@ -137,11 +137,11 @@ export class AIFieldType extends FieldType { .toHumanReadableString(field, value) } - getSortIndicator(field, registry) { + getSortIndicator(field) { return this.app.$registry .get('aiFieldOutputType', field.ai_output_type) .getBaserowFieldType() - .getSortIndicator(field, registry) + .getSortIndicator(field) } canRepresentDate(field) { @@ -207,13 +207,6 @@ export class AIFieldType extends FieldType { .getGroupByComponent(field) } - getGroupByIndicator(field, registry) { - return this.app.$registry - .get('aiFieldOutputType', field.ai_output_type) - .getBaserowFieldType() - .getGroupByIndicator(field, registry) - } - getRowValueFromGroupValue(field, value) { return this.app.$registry .get('aiFieldOutputType', field.ai_output_type) diff --git a/premium/web-frontend/modules/baserow_premium/licenseTypes.js b/premium/web-frontend/modules/baserow_premium/licenseTypes.js index ee7bf9a68..cd5d42e5a 100644 --- a/premium/web-frontend/modules/baserow_premium/licenseTypes.js +++ b/premium/web-frontend/modules/baserow_premium/licenseTypes.js @@ -22,7 +22,7 @@ export class LicenseType extends Registerable { } /** - * The a list of features that this license provides. + * A list of features that this license provides. */ getFeatures() { throw new Error('Must be set by the implementing sub class.') @@ -127,3 +127,4 @@ export class PremiumLicenseType extends LicenseType { return PremiumFeatures } } + diff --git a/premium/web-frontend/modules/baserow_premium/locales/de.json b/premium/web-frontend/modules/baserow_premium/locales/de.json index 9a21dfa0f..6812e73bd 100644 --- a/premium/web-frontend/modules/baserow_premium/locales/de.json +++ b/premium/web-frontend/modules/baserow_premium/locales/de.json @@ -10,7 +10,8 @@ }, "exporterType": { "json": "Nach JSON exportieren", - "xml": "Exportieren nach XML" + "xml": "Exportieren nach XML", + "excel": "In Excel exportieren" }, "deactivated": "Verfügbar in der Premium-Version" }, @@ -190,7 +191,8 @@ "publicLogoRemoval": "Entfernung des öffentlichen Logos", "personalViews": "Persönliche Ansichten", "calendarView": "Kalenderansicht", - "aiFeatures": "KI-Feld" + "aiFeatures": "KI-Feld", + "timelineView": "Zeitleisten-Ansicht" }, "premiumModal": { "description": "Ihr Konto hat keinen Zugang zu den Premium-Funktionen. Führen Sie ein Upgrade auf die Premium-Version durch, um {name} nutzen zu können. Sie können Ihr Konto erweitern, indem Sie eine Lizenz erwerben. Klicken Sie auf den Knopf unten, um die Preise zu sehen.", @@ -211,7 +213,8 @@ "baserowLogo": { "premiumModalName": "Entfernung des öffentlichen Logos", "label": "Baserow-Logo in öffentlicher Ansicht ausblenden" - } + }, + "allowPublicExportLabel": "Export der geteilten Ansicht zulassen" }, "viewsContext": { "personal": "Persönlich" @@ -334,5 +337,8 @@ "week": "Woche", "year": "Jahr", "disabledTooltip": "Diese Option ist nur für Datumsfelder verfügbar, bei denen „Zeit einschließen“ aktiviert ist." + }, + "tableExcelExporter": { + "includeHeader": "Feldnamen als Überschrift einfügen" } } diff --git a/premium/web-frontend/modules/baserow_premium/locales/en.json b/premium/web-frontend/modules/baserow_premium/locales/en.json index ba0b1c8fd..bc7660141 100644 --- a/premium/web-frontend/modules/baserow_premium/locales/en.json +++ b/premium/web-frontend/modules/baserow_premium/locales/en.json @@ -11,7 +11,8 @@ "exporterType": { "json": "Export to JSON", "xml": "Export to XML", - "excel": "Export to Excel" + "excel": "Export to Excel", + "file": "Export files" }, "deactivated": "Available in premium version" }, @@ -91,6 +92,9 @@ "tableExcelExporter": { "includeHeader": "Include field names as header" }, + "tableFileExporter": { + "organizeFiles": "Group files by row id" + }, "kanbanViewStackContext": { "createCard": "Create card", "editStack": "Edit stack", @@ -191,7 +195,8 @@ "premium": "Premium", "expired": "Expired", "validity": "Valid from {start} through {end}", - "seats": "seats" + "seats": "seats", + "applicationUsers": "Application users" }, "license": { "title": "{name} plan", @@ -212,6 +217,8 @@ "lastCheckDescription": "The license is periodically checked for changes. If you for example renewed or upgraded your license, the changes become active after the check.", "checkNow": "check now", "seats": "Seats (amount of users)", + "applicationUsers": "Application users", + "applicationUsersDescription": "The total number of application users in published application builder user sources.", "licensedTo": "Licensed to", "applications": "Applications / databases", "unlimited": "Unlimited", diff --git a/premium/web-frontend/modules/baserow_premium/locales/fr.json b/premium/web-frontend/modules/baserow_premium/locales/fr.json index 62c4c4f23..eb6ce4393 100644 --- a/premium/web-frontend/modules/baserow_premium/locales/fr.json +++ b/premium/web-frontend/modules/baserow_premium/locales/fr.json @@ -8,7 +8,8 @@ "exporterType": { "json": "Exporter vers JSON", "xml": "Exporter vers XML", - "excel": "Exporter vers Excel" + "excel": "Exporter vers Excel", + "file": "Exporter les fichiers" }, "deactivated": "Disponible en version premium", "adminType": { @@ -49,7 +50,7 @@ "unsupported": "La licence fournie est incompatible avec la version actuelle de Baserow. Veuillez mettre à jour votre instance avec la dernière version et essayez de nouveau.", "expiredTitle": "Expirée", "expired": "La licence fournie a expiré.", - "duplicateTitle": "Déja enregistrée", + "duplicateTitle": "Déjà enregistrée", "duplicate": "La licence fournie est déjà enregistrée sur cette instance.", "instanceMismatchTitle": "Instance incorrecte", "instanceMismatch": "La licence fournie n'a pas été créée pour cette instance." @@ -57,7 +58,7 @@ }, "disconnectLicenseModal": { "disconnectLicense": "Déconnecter la licence", - "disconnectDescription": "Êtes-vous sur·e de vouloir déconnecter la licence ? Si vous déconnectez la licence alors que celle-ci est active, les utilisateurs associés n'auront plus accès aux fonctionnalités qu'elle offre. Cela retire définitivement la licence. Veuillez contacter notre support via {contact} si vous souhaitez utiliser cette licence sur une autre instance hebergée." + "disconnectDescription": "Êtes-vous sûr·e de vouloir déconnecter la licence ? Si vous déconnectez la licence alors que celle-ci est active, les utilisateurs associés n'auront plus accès aux fonctionnalités qu'elle offre. Cela retire définitivement la licence. Veuillez contacter notre support via {contact} si vous souhaitez utiliser cette licence sur une autre instance hébergée." }, "registerLicenseForm": { "licenseKey": "Clé de licence" @@ -93,7 +94,7 @@ "new": "Nouveau" }, "licenses": { - "titleNoLicenses": "Aucune licences trouvée", + "titleNoLicenses": "Aucune licence trouvée", "titleLicenses": "Licences", "noLicensesDescription": "Votre instance de Baserow n'a aucune licence enregistrée. Une licence premium vous donne immédiatement accès à plusieurs fonctionnalités additionnelles. Si vous avez déjà une licence, vous pouvez l'enregistrer ici. Vous pouvez également en obtenir une en cliquant sur le bouton ci-dessous.", "rowComments": "Commentaires par lignes", @@ -109,7 +110,8 @@ "expired": "Expirée", "validity": "Valide du {start} au {end}", "seats": "places", - "premiumFeatures": "Fonctionnalités premium" + "premiumFeatures": "Fonctionnalités premium", + "applicationUsers": "Utilisateurs de l'application" }, "license": { "title": "Plan {name}", @@ -129,7 +131,7 @@ "lastCheck": "Dernière vérification", "lastCheckDescription": "La licence est vérifiée régulièrement. Si vous avez, par exemple, renouvelé ou mis à jour votre licence, les changements ne deviennent actifs qu'après la vérification.", "checkNow": "Vérifier maintenant", - "seats": "Places (nombre d'utilisateur max.)", + "seats": "Places (nombre d'utilisateurs max.)", "licensedTo": "Attribuée à", "premiumFeatures": "Fonctionnalités premium", "applications": "Applications / Bases de données", @@ -137,13 +139,15 @@ "rowUsage": "Nombre de ligne", "storeUsage": "Espace disponible", "disconnectLicense": "Déconnecter la licence", - "disconnectDescription": "Si vous déconnectez la licence alors que celle-ci est active, les utilisateurs associés n'auront plus accès aux fonctionnalités qu'elle offre. Cela retire définitivement la licence. Veuillez contacter notre support via {contact} si vous souhaitez utiliser cette licence sur une autre instance hebergée.", + "disconnectDescription": "Si vous déconnectez la licence alors que celle-ci est active, les utilisateurs associés n'auront plus accès aux fonctionnalités qu'elle offre. Cela retire définitivement la licence. Veuillez contacter notre support via {contact} si vous souhaitez utiliser cette licence sur une autre instance hébergée.", "moreSeatsNeededTitle": "Besoin de plus d´utilisateurs", "automaticSeatsProgressBarStatus": "{seats_taken} / {seats} utilisateurs payants et {free_users_count} utilisateurs gratuits", "contactSalesMoreSeats": "Contacter un Vendeur pour plus d´utilisateurs", "premiumFeatureName": "Premium", "supportFeatureName": "Support", - "enterpriseFeatureName": "Enterprise" + "enterpriseFeatureName": "Enterprise", + "applicationUsers": "Utilisateurs des applications", + "applicationUsersDescription": "Le nombre total d'utilisateurs de chaque source d'utilisateurs des applications publiées." }, "viewDecoratorType": { "onlyOneDecoratorPerView": "Vous ne pouvez utiliser qu'une seule décoration de ce type par vue", @@ -200,7 +204,7 @@ "timelineView": "Vue chronologique" }, "formViewModePreviewSurvey": { - "deactivated": "Les sondage sont disponibles dans la version premium.", + "deactivated": "Les sondages sont disponibles dans la version premium.", "orderFields": "Ordonner les champs", "more": "Plus d'informations" }, @@ -213,7 +217,8 @@ "baserowLogo": { "label": "Masquer le logo Baserow sur la vue partagée", "premiumModalName": "suppression du logo public" - } + }, + "allowPublicExportLabel": "Autoriser l'export des vues partagées" }, "viewsContext": { "personal": "Privée" @@ -256,14 +261,14 @@ "deletedUser": "Un utilisateur a été supprimé" }, "RowEditModalCommentNotificationMode": { - "modeMentionsDesc": "Vous ne recevrez les notifications uniquement lorsque vous serez mentionné·e.", + "modeMentionsDesc": "Vous recevez les notifications uniquement lorsque vous êtes mentionné·e.", "modeAllTitle": "Tous les commentaires", "modeAllDesc": "Vous recevrez des notifications pour tous les commentaires de cette ligne.", "modeMentionsTitle": "Seulement les mentions" }, "gridViewFieldAI": { "generate": "Générer", - "regenerate": "Re-générer" + "regenerate": "Regénérer" }, "premiumFieldType": { "ai": "Prompt pour l'IA", @@ -317,11 +322,11 @@ "timelineDateSettingsForm": { "startDateField": "Date de début", "endDateField": "Date de fin", - "incompatibleFieldsErrorTitle": "Champs incomptabiles", + "incompatibleFieldsErrorTitle": "Champs incompatibles", "includeTime": "date et heure", "dateOnly": "date seulement", - "noCompatibleDateFields": "Aucun champs date dans la table. Ajoutez un champs date de début et de fin dans la table pour commencer.", - "incompatibleFieldsErrorMessage": "Les champs sont incompatibles.Choisissez deux champs dates valides qui utilisent le même paramètre d'inclusion de l'heure et la même timezone pour tous les collaborateurs.", + "noCompatibleDateFields": "Aucun champ date dans la table. Ajoutez un champ date de début et de fin dans la table pour commencer.", + "incompatibleFieldsErrorMessage": "Les champs sont incompatibles. Choisissez deux champs dates valides qui utilisent le même paramètre d'inclusion de l'heure et la même timezone pour tous les collaborateurs.", "forceTimezone": "{timezone}" }, "initTimelineViewSettings": { @@ -350,5 +355,11 @@ }, "tableExcelExporter": { "includeHeader": "Inclure les noms de champs comme en-tête" + }, + "publicViewExport": { + "export": "Exporter" + }, + "tableFileExporter": { + "organizeFiles": "Grouper les fichiers par identifiant de ligne" } } diff --git a/premium/web-frontend/modules/baserow_premium/locales/nl.json b/premium/web-frontend/modules/baserow_premium/locales/nl.json index ba8e3f529..37b65349f 100644 --- a/premium/web-frontend/modules/baserow_premium/locales/nl.json +++ b/premium/web-frontend/modules/baserow_premium/locales/nl.json @@ -11,7 +11,8 @@ "exporterType": { "json": "Exporteren naar JSON", "xml": "Exporteren naar XML", - "excel": "Exporteren naar Excel" + "excel": "Exporteren naar Excel", + "file": "Exporteer bestanden" }, "deactivated": "Beschikbaar in de premium versie" }, @@ -109,7 +110,8 @@ "expired": "Verlopen", "validity": "Geldig van {start} tot {einde}", "seats": "plaatsen", - "premiumFeatures": "Premium functies" + "premiumFeatures": "Premium functies", + "applicationUsers": "Applicatie gebruikers" }, "license": { "title": "{product_code} plan", @@ -143,7 +145,9 @@ "contactSalesMoreSeats": "Neem contact op met sales voor meer seats", "supportFeatureName": "Support", "premiumFeatureName": "Premium", - "enterpriseFeatureName": "Enterprise" + "enterpriseFeatureName": "Enterprise", + "applicationUsers": "Applicatie gebruikers", + "applicationUsersDescription": "Het totale aantal applicatiegebruikers in gepubliceerde applicatiebouwer gebruikersbronnen." }, "viewDecoratorType": { "leftBorderColor": "Linkerrand", @@ -354,5 +358,8 @@ }, "publicViewExport": { "export": "Exporteren" + }, + "tableFileExporter": { + "organizeFiles": "Groepeer bestanden bij rij ID" } } diff --git a/premium/web-frontend/modules/baserow_premium/pages/admin/license.vue b/premium/web-frontend/modules/baserow_premium/pages/admin/license.vue index bf3d56370..e811f6c3a 100644 --- a/premium/web-frontend/modules/baserow_premium/pages/admin/license.vue +++ b/premium/web-frontend/modules/baserow_premium/pages/admin/license.vue @@ -35,11 +35,11 @@ </div> <div class="license-detail__item-value"> <Badge :color="licenseType.getLicenseBadgeColor()" bold> - {{ licenseType.getName() }}</Badge - > - <Badge v-if="!license.is_active" color="red">{{ - $t('licenses.expired') - }}</Badge> + {{ licenseType.getName() }} + </Badge> + <Badge v-if="!license.is_active" color="red" + >{{ $t('licenses.expired') }} + </Badge> </div> </div> <div class="license-detail__item"> @@ -92,6 +92,21 @@ {{ license.seats_taken }} / {{ license.seats }} </div> </div> + + <div v-if="license.application_users" class="license-detail__item"> + <div class="license-detail__item-label"> + <div class="license-detail__item-name"> + {{ $t('license.applicationUsers') }} + </div> + <div class="license-detail__item-description"> + {{ $t('license.applicationUsersDescription') }} + </div> + </div> + <div class="license-detail__item-value"> + {{ license.application_users_taken }} / + {{ license.application_users }} + </div> + </div> <div class="license-detail__item"> <div class="license-detail__item-label"> <div class="license-detail__item-name"> @@ -170,8 +185,8 @@ </i18n> <Button type="danger" @click="$refs.disconnectModal.show()"> - {{ $t('license.disconnectLicense') }}</Button - > + {{ $t('license.disconnectLicense') }} + </Button> <DisconnectLicenseModal ref="disconnectModal" :license="license" diff --git a/premium/web-frontend/modules/baserow_premium/pages/admin/licenses.vue b/premium/web-frontend/modules/baserow_premium/pages/admin/licenses.vue index 6da4765d1..b44f61843 100644 --- a/premium/web-frontend/modules/baserow_premium/pages/admin/licenses.vue +++ b/premium/web-frontend/modules/baserow_premium/pages/admin/licenses.vue @@ -127,7 +127,16 @@ {{ license.seats_taken }} / {{ license.seats }} {{ $t('licenses.seats') }} </li> - + <li + v-if="license.application_users" + class="licenses__item-detail-item" + > + {{ license.application_users_taken }} / + {{ license.application_users }} + {{ $t('licenses.applicationUsers') }} + </li> + </ul> + <ul class="licenses__item-details"> <li class="licenses__item-detail-item" v-for="(feature, index) in licenseFeatureDescription(license)" @@ -197,6 +206,7 @@ export default { .sort((a, b) => a.is_active === b.is_active ? 0 : a.is_active ? -1 : 1 ) + .sort((a, b) => a.application_users - b.application_users) }, licenseTypesWithFeatureComponent() { return Object.values(this.$registry.getAll('license')).filter( diff --git a/premium/web-frontend/modules/baserow_premium/plugin.js b/premium/web-frontend/modules/baserow_premium/plugin.js index f4a3506c3..3378af6d4 100644 --- a/premium/web-frontend/modules/baserow_premium/plugin.js +++ b/premium/web-frontend/modules/baserow_premium/plugin.js @@ -3,6 +3,7 @@ import { JSONTableExporter, XMLTableExporter, ExcelTableExporterType, + FileTableExporter, } from '@baserow_premium/tableExporterTypes' import { LicensesAdminType } from '@baserow_premium/adminTypes' import rowCommentsStore from '@baserow_premium/store/row_comments' @@ -103,6 +104,7 @@ export default (context) => { app.$registry.register('exporter', new JSONTableExporter(context)) app.$registry.register('exporter', new XMLTableExporter(context)) app.$registry.register('exporter', new ExcelTableExporterType(context)) + app.$registry.register('exporter', new FileTableExporter(context)) app.$registry.register('field', new AIFieldType(context)) app.$registry.register('field', new PremiumFormulaFieldType(context)) app.$registry.register('view', new KanbanViewType(context)) diff --git a/premium/web-frontend/modules/baserow_premium/store/view/calendar.js b/premium/web-frontend/modules/baserow_premium/store/view/calendar.js index aced00d1c..a65a9e37d 100644 --- a/premium/web-frontend/modules/baserow_premium/store/view/calendar.js +++ b/premium/web-frontend/modules/baserow_premium/store/view/calendar.js @@ -25,6 +25,7 @@ import { getRowMetadata, } from '@baserow/modules/database/utils/row' import { getDefaultSearchModeFromEnv } from '@baserow/modules/database/utils/search' +import { DEFAULT_SORT_TYPE_KEY } from '@baserow/modules/database/constants' export function populateRow(row, metadata = {}) { row._ = { @@ -581,7 +582,14 @@ export const actions = { if (stack === undefined) { return } - const sortings = [{ field: dateFieldId, value: 'ASC', order: 'ASC' }] + const sortings = [ + { + field: dateFieldId, + value: 'ASC', + order: 'ASC', + type: DEFAULT_SORT_TYPE_KEY, + }, + ] const sortedRows = clone(stack.results) sortedRows.push(row) sortedRows.sort(getRowSortFunction(this.$registry, sortings, fields)) @@ -726,7 +734,14 @@ export const actions = { } newStackResults.push(newRow) newStackCount++ - const sortings = [{ field: dateFieldId, value: 'ASC', order: 'ASC' }] + const sortings = [ + { + field: dateFieldId, + value: 'ASC', + order: 'ASC', + type: DEFAULT_SORT_TYPE_KEY, + }, + ] newStackResults.sort(getRowSortFunction(this.$registry, sortings, fields)) newIndex = newStackResults.findIndex((r) => r.id === newRow.id) const newIsLast = newIndex === newStackResults.length - 1 diff --git a/premium/web-frontend/modules/baserow_premium/tableExporterTypes.js b/premium/web-frontend/modules/baserow_premium/tableExporterTypes.js index 0e121e07d..b9bb66fde 100644 --- a/premium/web-frontend/modules/baserow_premium/tableExporterTypes.js +++ b/premium/web-frontend/modules/baserow_premium/tableExporterTypes.js @@ -5,6 +5,7 @@ import TableXMLExporter from '@baserow_premium/components/exporter/TableXMLExpor import PremiumModal from '@baserow_premium/components/PremiumModal' import PremiumFeatures from '@baserow_premium/features' import TableExcelExporter from '@baserow_premium/components/exporter/TableExcelExporter' +import TableFileExporter from '@baserow_premium/components/exporter/TableFileExporter' class PremiumTableExporterType extends TableExporterType { getDeactivatedText() { @@ -109,3 +110,34 @@ export class ExcelTableExporterType extends PremiumTableExporterType { return [GridViewType.getType()] } } + +export class FileTableExporter extends PremiumTableExporterType { + static getType() { + return 'file' + } + + getFileExtension() { + return 'zip' + } + + getIconClass() { + return 'baserow-icon-file-code' + } + + getName() { + const { i18n } = this.app + return i18n.t('premium.exporterType.file') + } + + getFormComponent() { + return TableFileExporter + } + + getCanExportTable() { + return true + } + + getSupportedViews() { + return [GridViewType.getType()] + } +} diff --git a/web-frontend/docker/docker-entrypoint.sh b/web-frontend/docker/docker-entrypoint.sh index 8a49bbaf5..99ded3126 100755 --- a/web-frontend/docker/docker-entrypoint.sh +++ b/web-frontend/docker/docker-entrypoint.sh @@ -2,7 +2,7 @@ # Bash strict mode: http://redsymbol.net/articles/unofficial-bash-strict-mode/ set -euo pipefail -export BASEROW_VERSION="1.31.1" +export BASEROW_VERSION="1.32.0" BASEROW_WEBFRONTEND_PORT="${BASEROW_WEBFRONTEND_PORT:-3000}" show_help() { diff --git a/web-frontend/locales/de.json b/web-frontend/locales/de.json index a60deb705..1bf4104f8 100644 --- a/web-frontend/locales/de.json +++ b/web-frontend/locales/de.json @@ -8,7 +8,12 @@ "comingSoon": "In Kürze verfügbar...", "billable": "Abrechenbar", "all": "Alle", - "beta": "Beta" + "beta": "Beta", + "enabled": "Aktiviert", + "summarize": "Zusammenfassen", + "disabled": "Deaktiviert", + "or": "oder", + "and": "und" }, "action": { "upload": "Hochladen", @@ -40,7 +45,10 @@ "reset": "Zurücksetzen", "set": "Festlegen", "logout": "Abmelden", - "backToHome": "Zurück zur Startseite" + "backToHome": "Zurück zur Startseite", + "hide": "Verstecken", + "close": "Schließen", + "getStarted": "Erste Schritte" }, "adminType": { "settings": "Einstellungen", @@ -58,7 +66,11 @@ "databases": "Datenbanken", "databaseDesc": "Erstellen Sie eine geordnete Sammlung strukturierter Daten.", "builders": "Anwendungen", - "builderDesc": "Erstellen Sie Websites, Webanwendungen und Portale ganz einfach ohne Code." + "builderDesc": "Erstellen Sie Websites, Webanwendungen und Portale ganz einfach ohne Code.", + "dashboard": "Dashboard", + "dashboardDesc": "Visualisieren Sie Ihre Daten und Metriken mit Diagrammen, Tabellen oder Graphen.", + "dashboards": "Dashboards", + "dashboardDefaultName": "Unbenanntes Dashboard" }, "settingType": { "account": "Konto", @@ -88,7 +100,9 @@ "invalidNumber": "Das Feld muss eine Zahl sein.", "email": "Das Feld muss eine E-Mailadresse sein.", "invalidURL": "Bitte geben Sie eine gültige URL ein.", - "alreadyInUse": "Dieser Feldname wird bereits verwendet." + "alreadyInUse": "Dieser Feldname wird bereits verwendet.", + "invalidCharacters": "Das Feld beinhaltet ungültige Zeichen.", + "decimalField": "Das Feld muss eine Dezimalzahl sein." }, "permission": { "admin": "Administration", @@ -255,7 +269,11 @@ "hasNotValueEqual": "hat nicht den gleichen Wert", "hasValueContains": "enthält einen Wert", "hasNotValueContains": "enthält keinen Wert", - "hasValueContainsWord": "enthält ein Wort als Wert" + "hasValueContainsWord": "enthält ein Wort als Wert", + "hasAnySelectOptionEqual": "hat eine beliebige Select-Option gleich", + "hasNoneSelectOptionEqual": "hat keine Select-Option gleich", + "hasDateWithin": "Datum liegt zwischen", + "hasNotDateWithin": "Datum liegt nicht zwischen" }, "viewType": { "grid": "Gitternetz", @@ -384,7 +402,13 @@ "maxNumberOfPendingWorkspaceInvitesReachedDescription": "Sie haben die maximale Anzahl an ausstehenden Einladungen für diesen Arbeitsbereich erreicht. Bitte lassen Sie die Eingeladenen die Einladung annehmen oder sagen Sie bestehende Einladungen ab um fortzufahren.", "outputParserDescription": "Das Modell hat mit einer falschen Ausgabe geantwortet. Bitte versuchen Sie es erneut.", "maxNumberOfPendingWorkspaceInvitesReachedTitle": "Maximale Anzahl an ausstehenden Einladungen erreicht", - "modelDoesNotBelongToTypeDescription": "Das ausgewählte Modell gehört nicht zum ausgewählten KI-Typ." + "modelDoesNotBelongToTypeDescription": "Das ausgewählte Modell gehört nicht zum ausgewählten KI-Typ.", + "cannotCreateRowsInTableDescription": "Es ist nicht möglich, in dieser Tabelle Zeilen zu erstellen.", + "fieldIsAlreadyPrimaryDescription": "Das gewählte neue Primärfeld ist bereits das Primärfeld.", + "cannotCreateRowsInTableTitle": "Zeilen können nicht erstellt werden", + "incompatiblePrimaryFieldTypeTitle": "Das Feld ist nicht kompatibel", + "incompatiblePrimaryFieldTypeDescription": "Das ausgewählte Feld kann nicht das Primärfeld sein, da es nicht kompatibel ist.", + "fieldIsAlreadyPrimaryTitle": "Das Feld ist bereits das Primärfeld" }, "importerType": { "csv": "Importieren einer CSV-Datei", @@ -409,7 +433,7 @@ "queryParameters": "Abfrage Parameter", "pathParameters": "Pfad-Parameter", "requestBodySchema": "Aufbauschema anfordern", - "userFieldNamesDescription": "Wenn für den GET-Parameter \"user_field_names\" ein beliebiger Wert angegeben wird, sind die von diesem Endpunkt zurückgegebenen Feldnamen die tatsächlichen Namen der Felder.\n\n Wenn der GET-Parameter \"user_field_names\" nicht angegeben wird, lauten alle zurückgegebenen Feldnamen \"field_\", gefolgt von der ID des Feldes. Zum Beispiel bezieht sich \"field_1\" auf das Feld mit der ID \"1\".", + "userFieldNamesDescription": "Wenn für den GET-Parameter \"user_field_names\" ein Wert angegeben wird und dessen Inhalt einem der folgenden Werte entspricht: `y`, `yes`, `true`, `t`, `on`, `1` oder eine leere Zeichenkenne, sind die von diesem Endpunkt zurückgegebenen Feldnamen die tatsächlichen Namen der Felder.\n\nWenn der GET-Parameter \"user_field_names\" nicht angegeben wird oder nicht einem der oben genannten Werte entspricht, lauten alle zurückgegebenen Feldnamen \"field_\", gefolgt von der ID des Feldes. Zum Beispiel bezieht sich \"field_1\" auf das Feld mit der ID \"1\".", "singleRow": "Einzeln", "deleteRows": "Zeilen löschen", "updateRows": "Zeilen aktualisieren", @@ -419,7 +443,8 @@ "uploadFileDescription": "Der `file` Multipart, der den Dateiinhalt enthält.", "uploadFileViaUrl": "Datei per URL hochladen", "uploadFileViaUrlDescription": "Lädt eine Datei auf Baserow hoch, indem es sie von der angegebenen URL herunterlädt.", - "fileUploads": "Datei-Uploads" + "fileUploads": "Datei-Uploads", + "sendWebhookEventsDescription": "Ein Flag-Abfrageparameter, der nach der Operation Webhooks auslöst, wenn er auf `y`, `yes`, `true`, `t`, `on`, `1` oder `or` gesetzt wird und leer bleibt. Standardwert ist `true`" }, "exporterType": { "csv": "Exportieren in CSV" @@ -475,7 +500,7 @@ "leftDescription": "Extrahiert die am weitesten links stehenden Zeichen aus der ersten Eingabe und hält an, wenn die durch die zweite Eingabe angegebene Anzahl von Zeichen extrahiert wurde.", "rightDescription": "Extrahiert die am weitesten rechts stehenden Zeichen aus der ersten Eingabe und hält an, wenn die durch die zweite Eingabe angegebene Anzahl von Zeichen extrahiert wurde.", "trimDescription": "Entfernt alle Leerzeichen auf der linken und rechten Seite der Eingabe.", - "regexReplaceDescription": "Ersetzt jeden Text in der ersten Eingabe, der mit der in der zweiten Eingabe angegebenen Regex übereinstimmt, durch den Text in der dritten Eingabe.", + "regexReplaceDescription": "Ersetzt jeden Text in der ersten Eingabe, der mit der in der zweiten Eingabe angegebenen Regex übereinstimmt, durch den Text in der dritten Eingabe. Gibt '#ERROR!' zurück, wenn das Regex-Muster ungültig ist.", "greatestDescription": "Gibt den größten Wert der beiden Eingaben zurück.", "leastDescription": "Gibt die kleinste der beiden Eingaben zurück.", "monthDescription": "Gibt die Anzahl der Monate im angegebenen Datum zurück.", diff --git a/web-frontend/locales/fr.json b/web-frontend/locales/fr.json index 105b41659..1e01d5516 100644 --- a/web-frontend/locales/fr.json +++ b/web-frontend/locales/fr.json @@ -146,7 +146,9 @@ "multipleSelectCheckboxes": "Cases à cocher", "duration": "Durée", "password": "Mot de passe", - "ai": "Prompt pour l'IA" + "ai": "Prompt pour l'IA", + "multipleCollaboratorsCheckboxes": "Cases à cocher", + "multipleCollaboratorsDropdown": "Liste déroulante" }, "fieldErrors": { "invalidNumber": "Nombre invalide", diff --git a/web-frontend/locales/nl.json b/web-frontend/locales/nl.json index a74e41e20..c000b1ed3 100644 --- a/web-frontend/locales/nl.json +++ b/web-frontend/locales/nl.json @@ -146,7 +146,9 @@ "multipleSelectCheckboxes": "Selectievakjes", "duration": "Duur", "password": "Wachtwoord", - "ai": "AI prompt" + "ai": "AI prompt", + "multipleCollaboratorsDropdown": "Dropdown", + "multipleCollaboratorsCheckboxes": "Selectievakjes" }, "fieldErrors": { "invalidNumber": "Ongeldig nummer", diff --git a/web-frontend/locales/ru.json b/web-frontend/locales/ru.json index bad99f3c3..7264ec336 100644 --- a/web-frontend/locales/ru.json +++ b/web-frontend/locales/ru.json @@ -1,403 +1,590 @@ { - "common": { - "yes": "", - "no": "", - "wrong": "", - "none": "", - "free": "" - }, - "action": { - "upload": "", - "back": "", - "backToLogin": "", - "signUp": "", - "signIn": "", - "login": "", - "createNew": "", - "create": "", - "edit": "", - "change": "", - "delete": "", - "rename": "", - "remove": "", - "duplicate": "", - "add": "", - "makeChoice": "", - "cancel": "", - "save": "", - "retry": "", - "search": "", - "copy": "", - "paste": "", - "activate": "", - "deactivate": "", - "download": "" - }, - "adminType": { - "settings": "" - }, - "applicationType": { - "database": "", - "databaseDefaultName": "", - "builder": "", - "builderDefaultName": "", - "cantSelectTableTitle": "", - "cantSelectTableDescription": "", - "cantSelectPageTitle": "", - "cantSelectPageDescription": "" - }, - "settingType": { - "account": "", - "password": "", - "tokens": "", - "deleteAccount": "" - }, - "userFileUploadType": { - "file": "", - "url": "" - }, - "field": { - "emailAddress": "" - }, - "error": { - "invalidEmail": "", - "notMatchingPassword": "", - "minLength": "", - "maxLength": "", - "minMaxLength": "", - "requiredField": "" - }, - "permission": { - "admin": "", - "adminDescription": "", - "member": "", - "memberDescription": "" - }, - "fieldType": { - "singleLineText": "", - "longText": "", - "linkToTable": "", - "number": "", - "rating": "", - "boolean": "", - "date": "", - "lastModified": "", - "createdOn": "", - "url": "", - "email": "", - "file": "", - "singleSelect": "", - "multipleSelect": "", - "phoneNumber": "", - "formula": "", - "lookup": "", - "multipleCollaborators": "" - }, - "fieldErrors": { - "invalidNumber": "", - "maxDigits": "", - "invalidUrl": "", - "max254Chars": "", - "invalidEmail": "", - "invalidPhoneNumber": "" - }, - "fieldDocs": { - "readOnly": "", - "text": "", - "longText": "", - "linkRow": "", - "number": "", - "numberPositive": "", - "decimal": "", - "decimalPositive": "", - "rating": "", - "boolean": "", - "date": "", - "dateTime": "", - "dateResponse": "", - "dateTimeResponse": "", - "lastModifiedReadOnly": "", - "createdOnReadOnly": "", - "url": "", - "email": "", - "file": "", - "singleSelect": "", - "multipleSelect": "", - "phoneNumber": "", - "formula": "", - "lookup": "", - "multipleCollaborators": "" - }, - "viewFilter": { - "contains": "", - "containsNot": "", - "containsWord": "", - "doesntContainWord": "", - "filenameContains": "", - "has": "", - "hasNot": "", - "higherThan": "", - "is": "", - "isNot": "", - "isEmpty": "", - "isNotEmpty": "", - "isDate": "", - "isDayOfMonth": "", - "isBeforeDate": "", - "isAfterDate": "", - "isNotDate": "", - "isToday": "", - "beforeToday": "", - "afterToday": "", - "isDaysAgo": "", - "isMonthsAgo": "", - "isYearsAgo": "", - "inThisWeek": "", - "inThisMonth": "", - "inThisYear": "", - "lowerThan": "", - "lengthIsLowerThan": "", - "hasFileType": "" - }, - "viewType": { - "grid": "", - "gallery": "", - "form": "", - "sharing": { - "linkName": "", - "formLinkName": "" - } - }, - "trashType": { - "workspace": "", - "application": "", - "table": "", - "field": "", - "row": "", - "rows": "", - "view": "" - }, - "webhook": { - "request": "", - "response": "", - "successfullyUpdated": "", - "form": { - "invalidURLTitle": "", - "invalidURLDescription": "" - }, - "status": { - "noStatus": "", - "statusOK": "", - "statusNotOK": "" - }, - "eventType": { - "rowCreated": "", - "rowsCreated": "", - "rowUpdated": "", - "rowsUpdated": "", - "rowDeleted": "", - "rowsDeleted": "" - } - }, - "clientHandler": { - "notFoundTitle": "", - "notFoundDescription": "", - "networkErrorTitle": "", - "networkErrorDescription": "", - "tooManyRequestsTitle": "", - "tooManyRequestsDescription": "", - "notCompletedTitle": "", - "notCompletedDescription": "", - "userNotInWorkspaceTitle": "", - "userNotInWorkspaceDescription": "", - "invalidWorkspacePermissionsTitle": "", - "invalidWorkspacePermissionsDescription": "", - "tableDoesNotExistTitle": "", - "tableDoesNotExistDescription": "", - "rowDoesNotExistTitle": "", - "rowDoesNotExistDescription": "", - "fileSizeTooLargeTitle": "", - "fileSizeTooLargeDescription": "", - "invalidFileTitle": "", - "invalidFileDescription": "", - "fileUrlCouldNotBeReachedTitle": "", - "fileUrlCouldNotBeReachedDescription": "", - "invalidFileUrlTitle": "", - "invalidFileUrlDescription": "", - "adminCannotDeactivateSelfTitle": "", - "adminCannotDeactivateSelfDescription": "", - "adminCannotDeleteSelfTitle": "", - "adminCannotDeleteSelfDescription": "", - "maxFieldCountExceededTitle": "", - "maxFieldCountExceededDescription": "", - "cannotRestoreParentBeforeChildTitle": "", - "cannotRestoreParentBeforeChildDescription": "", - "cannotRestoreAsRelatedTableTrashedTitle": "", - "cannotRestoreAsRelatedTableTrashedDescription": "", - "workspaceUserIsLastAdminTitle": "", - "workspaceUserIsLastAdminDescription": "", - "errorMaxJobCountExceededTitle": "", - "errorMaxJobCountExceededDescription": "", - "failedToLockFieldDueToConflictTitle": "", - "failedToLockFieldDueToConflictDescription": "", - "failedToLockTableDueToConflictTitle": "", - "failedToLockTableDueToConflictDescription": "", - "failedToUndoRedoDueToConflictTitle": "", - "failedToUndoRedoDueToConflictDescription": "", - "maximumSnapshotsReachedTitle": "", - "maximumSnapshotsReachedDescription": "", - "snapshotBeingCreatedTitle": "", - "snapshotBeingCreatedDescription": "", - "snapshotBeingRestoredTitle": "", - "snapshotBeingRestoredDescription": "", - "snapshotBeingDeletedTitle": "", - "snapshotBeingDeletedDescription": "", - "snapshotNameNotUniqueTitle": "", - "snapshotNameNotUniqueDescription": "", - "snapshotOperationLimitExceededTitle": "", - "snapshotOperationLimitExceededDescription": "", - "disabledPasswordProviderTitle": "", - "disabledPasswordProviderMessage": "", - "maxLocksPerTransactionExceededTitle": "", - "maxLocksPerTransactionExceededDescription": "", - "lastAdminTitle": "", - "lastAdminMessage": "" - }, - "importerType": { - "csv": "", - "paste": "", - "xml": "", - "json": "" - }, - "apiDocs": { - "intro": "", - "authent": "", - "table": "", - "filters": "", - "errors": "", - "fields": "", - "listFields": "", - "listRows": "", - "getRow": "", - "createRow": "", - "createRows": "", - "updateRow": "", - "updateRows": "", - "moveRow": "", - "deleteRow": "", - "deleteRows": "", - "uploadFile": "", - "uploadFileDescription": "", - "uploadFileViaUrl": "", - "uploadFileViaUrlDescription": "", - "queryParameters": "", - "pathParameters": "", - "requestBodySchema": "", - "userFieldNamesDescription": "", - "singleRow": "", - "batchRows": "", - "fileUploads": "" - }, - "exporterType": { - "csv": "" - }, - "previewType": { - "imageBrowser": "", - "videoBrowser": "", - "AudioBrowser": "", - "pdfBrowser": "", - "googleDocs": "" - }, - "humanDateFormat": { - "dd/mm/yyyy": "", - "mm/dd/yyyy": "", - "yyyy-mm-dd": "" - }, - "formulaFunctions": { - "upperDescription": "", - "lowerDescription": "", - "concatDescription": "", - "addDescription": "", - "minusDescription": "", - "multiplyDescription": "", - "divideDescription": "", - "equalDescription": "", - "ifDescription": "", - "toTextDescription": "", - "datetimeFormatDescription": "", - "toNumberDescription": "", - "fieldDescription": "", - "lookupDescription": "", - "isBlankDescription": "", - "isNullDescription": "", - "tDescription": "", - "notDescription": "", - "greaterThanDescription": "", - "greaterThanOrEqualDescription": "", - "lessThanDescription": "", - "lessThanOrEqualDescription": "", - "toDateDescription": "", - "dayDescription": "", - "dateDiffDescription": "", - "andDescription": "", - "orDescription": "", - "dateIntervalDescription": "", - "replaceDescription": "", - "searchDescription": "", - "rowIdDescription": "", - "lengthDescription": "", - "reverseDescription": "", - "notEqualDescription": "", - "countDescription": "", - "containsDescription": "", - "leftDescription": "", - "rightDescription": "", - "trimDescription": "", - "regexReplaceDescription": "", - "greatestDescription": "", - "leastDescription": "", - "monthDescription": "", - "yearDescription": "", - "secondDescription": "", - "whenEmptyDescription": "", - "anyDescription": "", - "everyDescription": "", - "maxDescription": "", - "minDescription": "", - "joinDescription": "", - "stddevPopDescription": "", - "stddevSampleDescription": "", - "varianceSampleDescription": "", - "variancePopDescription": "", - "avgDescription": "", - "sumDescription": "", - "filterDescription": "", - "linkDescription": "", - "buttonDescription": "", - "getLinkLabelDescription": "", - "getLinkUrlDescription": "", - "evenDescription": "", - "oddDescription": "", - "modDescription": "", - "powerDescription": "", - "logDescription": "", - "expDescription": "", - "lnDescription": "", - "signDescription": "", - "sqrtDescription": "", - "roundDescription": "", - "truncDescription": "", - "isNanDescription": "", - "wheNanDescription": "", - "absDescription": "", - "ceilDescription": "", - "floorDescription": "" - }, - "functionnalGridViewFieldLinkRow": { - "unnamed": "" - }, - "urlCheck": { - "invalidUrlEnvVarTitle": "", - "invalidUrlEnvVarDescription": "" + "common": { + "yes": "да", + "no": "нет", + "wrong": "Что-то пошло не так", + "none": "Нет", + "free": "Бесплатно", + "comingSoon": "Скоро...", + "billable": "Платно", + "all": "Все", + "beta": "Бета", + "summarize": "Подвести итог", + "enabled": "Включено", + "disabled": "Отключено", + "or": "или", + "and": "и" + }, + "action": { + "close": "Закрыть", + "upload": "Загрузить", + "back": "Назад", + "backToLogin": "Вернуться к входу", + "backToHome": "Вернуться на главную", + "signUp": "Зарегистрироваться", + "getStarted": "Начать", + "signIn": "Войти", + "login": "Вход", + "logout": "Выйти", + "createNew": "Добавить новое", + "create": "Создать", + "edit": "Редактировать", + "change": "Изменить", + "delete": "Удалить", + "rename": "Переименовать", + "remove": "Удалить", + "duplicate": "Дублировать", + "add": "Добавить", + "makeChoice": "Сделайте выбор", + "cancel": "Отмена", + "save": "Сохранить", + "set": "Установить", + "retry": "Повторить", + "search": "Поиск", + "copy": "Копировать", + "paste": "Вставить", + "activate": "Активировать", + "deactivate": "Деактивировать", + "download": "Скачать", + "copyToClipboard": "Копировать в буфер обмена", + "reset": "Сбросить", + "hide": "Скрыть" + }, + "adminType": { + "settings": "Настройки", + "health": "Состояние" + }, + "applicationType": { + "database": "База данных", + "databases": "Базы данных", + "databaseDefaultName": "База данных без названия", + "databaseDesc": "Создайте организованную коллекцию структурированных данных.", + "builder": "Приложение", + "builders": "Приложения", + "builderDefaultName": "Приложение без названия", + "builderDesc": "Легко создавайте веб-сайты, веб-приложения и порталы без кода.", + "dashboard": "Панель мониторинга", + "dashboards": "Панели мониторинга", + "dashboardDefaultName": "Панель мониторинга без названия", + "dashboardDesc": "Визуализируйте ваши данные и метрики с помощью графиков, таблиц или диаграмм.", + "cantSelectTableTitle": "Не удалось выбрать базу данных.", + "cantSelectTableDescription": "База данных не может быть выбрана, так как в ней нет таблиц. Используйте боковую панель для создания таблицы.", + "cantSelectPageTitle": "Не удалось выбрать приложение.", + "cantSelectPageDescription": "Конструктор приложений не может быть выбран, так как в нем нет страниц. Используйте боковую панель для создания страницы." + }, + "settingType": { + "account": "Аккаунт", + "password": "Пароль", + "emailNotifications": "Уведомления по электронной почте", + "tokens": "Токены базы данных", + "deleteAccount": "Удалить аккаунт" + }, + "userFileUploadType": { + "file": "моего устройства", + "url": "URL-адреса" + }, + "field": { + "emailAddress": "Адрес электронной почты" + }, + "error": { + "invalidEmail": "Пожалуйста, введите действительный адрес электронной почты.", + "invalidNumber": "Поле должно быть числом.", + "notMatchingPassword": "Это поле должно соответствовать вашему паролю.", + "minLength": "Здесь требуется минимум {min} символов.", + "maxLength": "Здесь допускается максимум {max} символов.", + "minMaxLength": "Здесь допускается минимум {min} и максимум {max} символов.", + "invalidCharacters": "Это поле содержит недопустимые символы.", + "requiredField": "Это поле обязательно для заполнения.", + "integerField": "Поле должно быть целым числом.", + "decimalField": "Поле должно быть десятичным числом.", + "minValueField": "Поле должно быть больше или равно {min}.", + "maxValueField": "Поле должно быть меньше или равно {max}.", + "minMaxValueField": "Значение поля должно быть между {min} и {max}.", + "invalidURL": "Пожалуйста, введите действительный URL.", + "email": "Поле должно быть электронной почтой.", + "alreadyInUse": "Это имя поля уже используется." + }, + "permission": { + "admin": "Администратор", + "adminDescription": "Может полностью настраивать и редактировать рабочие пространства и приложения.", + "member": "Участник", + "memberDescription": "Может полностью настраивать и редактировать приложения." + }, + "fieldType": { + "singleLineText": "Однострочный текст", + "longText": "Длинный текст", + "linkToTable": "Связь с таблицей", + "number": "Число", + "rating": "Рейтинг", + "boolean": "Логическое значение", + "date": "Дата", + "lastModified": "Последнее изменение", + "lastModifiedBy": "Кем изменено последним", + "createdOn": "Дата создания", + "createdBy": "Кем создано", + "duration": "Продолжительность", + "url": "URL", + "email": "Электронная почта", + "file": "Файл", + "singleSelect": "Одиночный выбор", + "multipleSelect": "Множественный выбор", + "phoneNumber": "Номер телефона", + "formula": "Формула", + "count": "Количество", + "rollup": "Свёртка", + "lookup": "Поиск", + "multipleCollaborators": "Соавторы", + "defaultFormViewComponent": "По умолчанию", + "linkRowSingle": "Одиночный", + "linkRowMultiple": "Множественный", + "uuid": "UUID", + "multipleSelectDropdown": "Выпадающий список", + "multipleSelectCheckboxes": "Флажки", + "singleSelectDropdown": "Выпадающий список", + "singleSelectRadios": "Радиокнопки", + "autonumber": "Автонумерация", + "password": "Пароль", + "ai": "AI-запрос", + "multipleCollaboratorsDropdown": "Выпадающий список", + "multipleCollaboratorsCheckboxes": "Флажки" + }, + "fieldErrors": { + "invalidNumber": "Недопустимое число", + "maxDigits": "Максимально допустимо {max} цифр.", + "invalidUrl": "Недопустимый URL", + "max254Chars": "Максимум 254 символа", + "invalidEmail": "Недопустимый адрес электронной почты", + "invalidPhoneNumber": "Недопустимый номер телефона", + "invalidDuration": "Недопустимый формат ({durationFormat}).", + "overflowDuration": "Значение выходит за пределы допустимого.", + "maxChars": "Максимум {max} символов.", + "minChars": "Минимум {min} символов." + }, + "fieldDocs": { + "readOnly": "Это поле только для чтения.", + "text": "Принимает однострочный текст.", + "longText": "Принимает многострочный текст. Если включено форматирование текста, вы можете использовать markdown для форматирования текста.", + "linkRow": "Принимает массив, содержащий идентификаторы или текстовые значения основного поля связанных строк из таблицы с идентификатором {table}. Все идентификаторы должны быть предоставлены каждый раз при обновлении связей. Если предоставлен пустой массив, все связи будут удалены. В случае текстового значения вместо идентификатора будет выполнен поиск строки с соответствующим значением для ее основного поля. Если найдено более одного совпадения, выбирается первое по порядку в таблице. Вы можете отправить строку с именами, разделенными запятыми, и в этом случае строка будет преобразована в массив имен строк. Вы также можете отправить только идентификатор строки.", + "number": "Принимает число.", + "numberPositive": "Принимает положительное число.", + "decimal": "Принимает десятичное число с {places} десятичными знаками после точки.", + "decimalPositive": "Принимает положительное десятичное число с {places} десятичными знаками после точки.", + "rating": "Принимает число.", + "boolean": "Принимает логическое значение.", + "date": "Принимает дату и время в формате ISO.", + "dateTime": "Принимает дату в формате ISO.", + "dateResponse": "Ответ будет датой и временем в формате ISO.", + "dateTimeResponse": "Ответ будет датой в формате ISO.", + "lastModifiedReadOnly": "Поле последнего изменения является полем только для чтения.", + "lastModifiedBy": "Поле 'Кем изменено последним' является полем только для чтения.", + "createdOnReadOnly": "Поле даты создания является полем только для чтения.", + "createdBy": "Поле 'Кем создано' является полем только для чтения, показывающим пользователя, который создал строку.", + "duration": "Принимает продолжительность на основе времени в виде строки в формате {format} или в виде числа, представляющего общее количество секунд.", + "url": "Принимает строку, которая должна быть URL-адресом.", + "email": "Принимает строку, которая должна быть адресом электронной почты.", + "file": "Принимает массив объектов, содержащих как минимум имя пользовательского файла. В качестве альтернативы вы можете предоставить список имен файлов, разделенных запятыми, или массив имен файлов. Вы можете использовать конечные точки 'Загрузки файлов' для загрузки файла. Ответ этих вызовов может быть предоставлен здесь непосредственно как объект. Конечные точки можно найти в левой боковой панели.", + "singleSelect": "Принимает целое число или текстовое значение, представляющее выбранный идентификатор опции или значение опции. Значение null означает, что ничего не выбрано. В случае текстового значения выбирается первая совпадающая опция.", + "multipleSelect": "Принимает массив смешанных целых чисел или текстовых значений, каждое из которых представляет выбранный идентификатор опции или значение. В случае текстового значения выбирается первая совпадающая опция. Вы можете отправить строку с именами, разделенными запятыми, в качестве значения, и в этом случае строка будет преобразована в массив имен опций.", + "phoneNumber": "Принимает номер телефона, который имеет максимальную длину 100 символов, состоящих исключительно из цифр, пробелов и следующих символов: Nx,._+*()#=;/- .", + "formula": "Поле только для чтения, определенное формулой, написанной на языке формул Baserow.", + "count": "Поле только для чтения, связанное с полем ссылки на таблицу, которое возвращает количество связей.", + "rollup": "Поле только для чтения, связанное с полем ссылки на таблицу, которое сворачивает значения из выбранного поля поиска в связанной таблице.", + "lookup": "Поле только для чтения, связанное с полем ссылки на таблицу, которое возвращает массив значений и идентификаторов строк из выбранного поля поиска в связанной таблице.", + "multipleCollaborators": "Принимает массив объектов, где каждый объект содержит идентификатор пользователя.", + "uuid": "Поле только для чтения, содержащее уникальный и неизменный uuid.", + "autonumber": "Поле только для чтения, которое автоматически увеличивает число для каждой новой строки.", + "password": "Поле только для записи, которое хранит хешированный пароль. Значение будет `null`, если не установлено, или `true`, если оно было установлено. Оно принимает строку для установки." + }, + "viewFilter": { + "hasEmptyValue": "имеет пустое значение", + "hasNotEmptyValue": "не имеет пустого значения", + "hasValueEqual": "имеет значение равное", + "hasNotValueEqual": "не имеет значения равного", + "hasValueContains": "имеет значение, содержащее", + "hasNotValueContains": "не имеет значения, содержащего", + "hasValueContainsWord": "имеет значение, содержащее слово", + "hasNotValueContainsWord": "не имеет значения, содержащего слово", + "hasValueLengthIsLowerThan": "имеет длину значения меньше, чем", + "hasAnySelectOptionEqual": "имеет любую выбранную опцию, равную", + "hasNoneSelectOptionEqual": "не имеет выбранной опции, равной", + "contains": "содержит", + "containsNot": "не содержит", + "containsWord": "содержит слово", + "doesntContainWord": "не содержит слово", + "filenameContains": "имя файла содержит", + "has": "имеет", + "hasNot": "не имеет", + "higherThan": "больше, чем", + "higherThanOrEqual": "больше или равно", + "is": "равно", + "isNot": "не равно", + "isEmpty": "пустое", + "isNotEmpty": "не пустое", + "isDate": "это дата", + "isDayOfMonth": "день месяца равен", + "isBeforeDate": "до даты", + "isBeforeOrEqualDate": "до или равно дате", + "isAfterDate": "после даты", + "isAfterOrEqualDate": "после или равно дате", + "isAfterDaysAgo": "после дней назад", + "isNotDate": "не дата", + "isToday": "сегодня", + "beforeToday": "до сегодня", + "afterToday": "после сегодня", + "isDaysAgo": "дней назад", + "isMonthsAgo": "месяцев назад", + "isYearsAgo": "лет назад", + "inThisWeek": "на этой неделе", + "inThisMonth": "в этом месяце", + "inThisYear": "в этом году", + "isWithinDays": "в течение дней", + "isWithinWeeks": "в течение недель", + "isWithinMonths": "в течение месяцев", + "lowerThan": "меньше, чем", + "lowerThanOrEqual": "меньше или равно", + "isEvenAndWhole": "четное и целое", + "lengthIsLowerThan": "длина меньше, чем", + "hasFileType": "имеет тип файла", + "filesLowerThan": "файлов меньше, чем", + "isAnyOf": "любой из", + "isNoneOf": "ни один из", + "today": "сегодня", + "yesterday": "вчера", + "tomorrow": "завтра", + "thisWeek": "эта неделя", + "oneWeekAgo": "одна неделя назад", + "nextWeek": "следующая неделя", + "thisMonth": "этот месяц", + "oneMonthAgo": "один месяц назад", + "nextMonth": "следующий месяц", + "thisYear": "этот год", + "oneYearAgo": "один год назад", + "nextYear": "следующий год", + "nrDaysAgo": "дней назад", + "nrWeeksAgo": "недель назад", + "nrMonthsAgo": "месяцев назад", + "nrYearsAgo": "лет назад", + "nrDaysFromNow": "дней с сегодняшнего дня", + "nrWeeksFromNow": "недель с сегодняшнего дня", + "nrMonthsFromNow": "месяцев с сегодняшнего дня", + "nrYearsFromNow": "лет с сегодняшнего дня", + "exactDate": "точная дата", + "isBefore": "до", + "isAfter": "после", + "isOnOrBefore": "равно или до", + "isOnOrAfter": "равно или после", + "isWithin": "в пределах", + "hasDateEqual": "имеет дату, равную", + "hasNotDateEqual": "не имеет даты, равной", + "hasDateBefore": "имеет дату до", + "hasNotDateBefore": "не имеет даты до", + "hasDateOnOrBefore": "имеет дату равную или до", + "hasNotDateOnOrBefore": "не имеет даты равной или до", + "hasDateAfter": "имеет дату после", + "hasNotDateAfter": "не имеет даты после", + "hasDateOnOrAfter": "имеет дату равную или после", + "hasNotDateOnOrAfter": "не имеет даты равной или после", + "hasDateWithin": "имеет дату в пределах", + "hasNotDateWithin": "не имеет даты в пределах" + }, + "viewType": { + "grid": "Таблица", + "gallery": "Галерея", + "form": "Форма", + "sharing": { + "linkName": "представление", + "formLinkName": "форма" } + }, + "trashType": { + "workspace": "рабочее пространство", + "application": "приложение", + "table": "таблица", + "field": "поле", + "row": "строка", + "rows": "строки", + "view": "представление" + }, + "webhook": { + "request": "Запрос", + "response": "Ответ", + "successfullyUpdated": "Веб-хук успешно обновлен.", + "form": { + "invalidURLTitle": "Недопустимый URL.", + "invalidURLDescription": "URL веб-хука недействителен, недоступен или запрещен." + }, + "status": { + "noStatus": "БЕЗ СТАТУСА", + "statusOK": "ОК", + "statusNotOK": "НЕ ОК" + }, + "eventType": { + "rowCreated": "Когда строка создана", + "rowsCreated": "Строки созданы", + "rowUpdated": "Когда строка обновлена", + "rowsUpdated": "Строки обновлены", + "rowDeleted": "Когда строка удалена", + "rowsDeleted": "Строки удалены", + "fieldCreated": "Поле создано", + "fieldUpdated": "Поле обновлено", + "fieldDeleted": "Поле удалено", + "viewCreated": "Представление создано", + "viewUpdated": "Представление обновлено", + "viewDeleted": "Представление удалено" + } + }, + "clientHandler": { + "notFoundTitle": "{name} не найден(а).", + "notFoundDescription": "Выбранный(ая) {name} не найден(а), возможно, он(а) уже был(а) удален(а).", + "networkErrorTitle": "Ошибка сети", + "networkErrorDescription": "Не удалось подключиться к серверу API.", + "tooManyRequestsTitle": "Слишком много запросов", + "tooManyRequestsDescription": "Вы отправляете слишком много запросов на сервер. Пожалуйста, подождите немного.", + "notCompletedTitle": "Действие не выполнено.", + "notCompletedDescription": "Действие не удалось выполнить из-за неизвестной ошибки.", + "userNotInWorkspaceTitle": "Действие запрещено.", + "userNotInWorkspaceDescription": "Действие не удалось выполнить, поскольку вы не являетесь участником связанного рабочего пространства.", + "invalidWorkspacePermissionsTitle": "Действие запрещено.", + "invalidWorkspacePermissionsDescription": "Действие не удалось выполнить, поскольку у вас нет соответствующих прав для связанного рабочего пространства.", + "tableDoesNotExistTitle": "Таблица не существует.", + "tableDoesNotExistDescription": "Действие не удалось выполнить, поскольку связанная таблица больше не существует.", + "rowDoesNotExistTitle": "Строка не существует.", + "rowDoesNotExistDescription": "Действие не удалось выполнить, поскольку связанная строка больше не существует.", + "notificationDoesNotExistTitle": "Уведомление не существует.", + "notificationDoesNotExistDescription": "Действие не удалось выполнить, поскольку связанное уведомление больше не существует.", + "fileSizeTooLargeTitle": "Файл слишком большой", + "fileSizeTooLargeDescription": "Предоставленный файл слишком большой.", + "invalidFileTitle": "Недопустимый файл", + "invalidFileDescription": "Предоставленный файл не является допустимым файлом.", + "fileUrlCouldNotBeReachedTitle": "Недопустимый URL", + "fileUrlCouldNotBeReachedDescription": "Указанный URL-адрес файла недоступен.", + "invalidFileUrlTitle": "Недопустимый URL", + "invalidFileUrlDescription": "Указанный URL-адрес файла недействителен или не разрешен.", + "adminCannotDeactivateSelfTitle": "Действие запрещено.", + "adminCannotDeactivateSelfDescription": "Вы не можете деактивировать или лишить себя прав администратора.", + "adminCannotDeleteSelfTitle": "Действие запрещено.", + "adminCannotDeleteSelfDescription": "Вы не можете удалить себя.", + "maxFieldCountExceededTitle": "Не удалось создать поле.", + "maxFieldCountExceededDescription": "Действие не удалось выполнить, поскольку количество полей превышает лимит", + "cannotRestoreParentBeforeChildTitle": "Сначала восстановите родительский элемент.", + "cannotRestoreParentBeforeChildDescription": "Вы не можете восстановить этот элемент, поскольку он зависит от удаленного элемента. Сначала восстановите родительский элемент.", + "cannotRestoreAsRelatedTableTrashedTitle": "Сначала восстановите связанные таблицы.", + "cannotRestoreAsRelatedTableTrashedDescription": "Вы не можете восстановить это поле, поскольку оно зависит от других таблиц, которые все еще находятся в корзине. Сначала восстановите другие связанные таблицы.", + "workspaceUserIsLastAdminTitle": "Нельзя покинуть рабочее пространство", + "workspaceUserIsLastAdminDescription": "Невозможно покинуть рабочее пространство, поскольку вы последний администратор или потому что учетные записи других администраторов ожидают удаления. Пожалуйста, удалите рабочее пространство или предоставьте другому пользователю права администратора.", + "errorMaxJobCountExceededTitle": "Не удалось начать действие.", + "errorMaxJobCountExceededDescription": "Вы не можете начать больше таких действий, так как у вас есть другие, все еще выполняющиеся в фоновом режиме. Пожалуйста, повторите попытку после завершения предыдущих действий.", + "failedToLockFieldDueToConflictTitle": "Нельзя изменить поле", + "failedToLockFieldDueToConflictDescription": "Другая операция в настоящее время обновляет или использует это поле, пожалуйста, дождитесь ее завершения, прежде чем повторить попытку.", + "failedToLockTableDueToConflictTitle": "Нельзя создать поле", + "failedToLockTableDueToConflictDescription": "Другая операция в настоящее время обновляет или использует эту таблицу, пожалуйста, дождитесь ее завершения, прежде чем повторить попытку.", + "failedToUndoRedoDueToConflictTitle": "Нельзя отменить/повторить", + "failedToUndoRedoDueToConflictDescription": "В настоящее время выполняется другая операция, блокирующая отмену или повтор, пожалуйста, дождитесь ее завершения, прежде чем повторить попытку.", + "maximumSnapshotsReachedTitle": "Достигнут лимит снимков", + "maximumSnapshotsReachedDescription": "Достигнуто максимальное количество снимков в рабочем пространстве.", + "snapshotBeingCreatedTitle": "Снимок уже создается", + "snapshotBeingCreatedDescription": "Невозможно создать несколько снимков одновременно.", + "snapshotBeingRestoredTitle": "Снимок восстанавливается", + "snapshotBeingRestoredDescription": "Невозможно использовать снимки, которые в настоящее время восстанавливаются.", + "snapshotBeingDeletedTitle": "Снимок удаляется", + "snapshotBeingDeletedDescription": "Невозможно использовать снимки, которые в настоящее время удаляются.", + "snapshotNameNotUniqueTitle": "Имя снимка должно быть уникальным.", + "snapshotNameNotUniqueDescription": "Все имена снимков должны быть уникальными для каждого приложения.", + "snapshotOperationLimitExceededTitle": "Достигнут лимит", + "snapshotOperationLimitExceededDescription": "Вы достигли лимита на количество выполняемых операций со снимками. Пожалуйста, дождитесь завершения предыдущей операции.", + "disabledPasswordProviderTitle": "Аутентификация по паролю отключена.", + "disabledPasswordProviderMessage": "Пожалуйста, используйте другой способ аутентификации.", + "maxLocksPerTransactionExceededTitle": "Обнаружена проблема с PostgreSQL", + "maxLocksPerTransactionExceededDescription": "Baserow попытался окончательно удалить элементы из корзины, но превысил доступные блокировки, указанные в `max_locks_per_transaction`.", + "lastAdminTitle": "Нельзя удалить последнего администратора рабочего пространства", + "lastAdminMessage": "В рабочем пространстве должен быть хотя бы один администратор.", + "adminAlreadyExistsTitle": "Нельзя использовать это имя пользователя", + "adminAlreadyExistsDescription": "Это имя пользователя не может быть использовано, поскольку оно уже существует.", + "cannotCreateFieldTypeTitle": "Не удается создать поле", + "cannotCreateFieldTypeDescription": "Запрошенный тип поля в данный момент не может быть создан. Возможно, это временная проблема со старыми таблицами. Пожалуйста, повторите попытку позже.", + "generativeAIDoesNotExistTitle": "Генеративный ИИ не существует", + "generativeAIDoesNotExistDescription": "Модель генеративного ИИ не существует.", + "modelDoesNotBelongToTypeTitle": "Выбранная модель не принадлежит к типу ИИ", + "modelDoesNotBelongToTypeDescription": "Выбранная модель не принадлежит к выбранному типу ИИ.", + "outputParserTitle": "Неверный вывод", + "outputParserDescription": "Модель ответила с некорректным выводом. Пожалуйста, попробуйте еще раз.", + "generateAIPromptTitle": "Ошибка запроса", + "generateAIPromptDescription": "Что-то было не так с составленным запросом.", + "maxNumberOfPendingWorkspaceInvitesReachedTitle": "Достигнуто максимальное количество ожидающих приглашений", + "maxNumberOfPendingWorkspaceInvitesReachedDescription": "Вы достигли максимального количества ожидающих приглашений для этого рабочего пространства. Пожалуйста, дождитесь, пока приглашенные примут приглашение или отмените существующие, чтобы продолжить.", + "fieldIsAlreadyPrimaryTitle": "Поле уже является основным", + "fieldIsAlreadyPrimaryDescription": "Выбранное новое основное поле уже является основным полем.", + "incompatiblePrimaryFieldTypeTitle": "Поле несовместимо", + "incompatiblePrimaryFieldTypeDescription": "Выбранное поле не может быть основным полем, поскольку оно несовместимо.", + "cannotCreateRowsInTableTitle": "Нельзя создать строки", + "cannotCreateRowsInTableDescription": "Невозможно создать строки в этой таблице." + }, + "importerType": { + "csv": "Импортировать CSV-файл", + "paste": "Вставить данные таблицы", + "xml": "Импортировать XML-файл", + "json": "Импортировать JSON-файл" + }, + "apiDocs": { + "intro": "Введение", + "authent": "Аутентификация", + "table": "Таблица {name}", + "filters": "Фильтры", + "errors": "HTTP-ошибки", + "fields": "Поля", + "listFields": "Список полей", + "listRows": "Список строк", + "getRow": "Получить строку", + "createRow": "Создать строку", + "createRows": "Создать строки", + "updateRow": "Обновить строку", + "updateRows": "Обновить строки", + "moveRow": "Переместить строку", + "deleteRow": "Удалить строку", + "deleteRows": "Удалить строки", + "uploadFile": "Загрузить файл", + "uploadFileDescription": "Часть `file` multipart, содержащая содержимое файла.", + "uploadFileViaUrl": "Загрузить файл по URL", + "uploadFileViaUrlDescription": "Загружает файл в Baserow, скачивая его с указанного URL.", + "queryParameters": "Параметры запроса", + "pathParameters": "Параметры пути", + "requestBodySchema": "Схема тела запроса", + "userFieldNamesDescription": "Когда параметр GET `user_field_names` предоставлен и его значение является одним из следующих: `y`, `yes`, `true`, `t`, `on`, `1` или пустая строка, имена полей, возвращаемые этой конечной точкой, будут фактическими именами полей.\n\nЕсли параметр GET `user_field_names` не предоставлен или если он не соответствует ни одному из указанных выше значений, то все возвращаемые имена полей будут представлять собой `field_`, за которым следует id поля. Например, `field_1` относится к полю с id `1`.", + "sendWebhookEventsDescription": "Параметр запроса-флаг, который запускает веб-хуки после операции, если установлен на `y`, `yes`, `true`, `t`, `on`, `1`, `или` оставлен пустым. По умолчанию `true`", + "singleRow": "Одиночная", + "batchRows": "Пакетная", + "fileUploads": "Загрузки файлов" + }, + "exporterType": { + "csv": "Экспорт в CSV" + }, + "previewType": { + "imageBrowser": "Открыть в браузере", + "videoBrowser": "Открыть в браузере", + "AudioBrowser": "Открыть в браузере", + "pdfBrowser": "Открыть в браузере", + "googleDocs": "Открыть с помощью Google Docs" + }, + "humanDateFormat": { + "dd/mm/yyyy": "дд/мм/гггг", + "mm/dd/yyyy": "мм/дд/гггг", + "yyyy-mm-dd": "гггг-мм-дд" + }, + "formulaFunctions": { + "upperDescription": "Возвращает аргумент в верхнем регистре.", + "lowerDescription": "Возвращает аргумент в нижнем регистре.", + "splitPartDescription": "Извлекает сегмент из разделенной строки на основе разделителя и индекса (числового индикатора, указывающего какой элемент из строки должен быть возвращен)", + "concatDescription": "Возвращает аргументы, объединенные вместе как один фрагмент текста.", + "addDescription": "Возвращает сумму двух аргументов.", + "minusDescription": "Возвращает разность двух аргументов.", + "multiplyDescription": "Возвращает произведение двух аргументов.", + "divideDescription": "Возвращает результат деления аргументов, первый делится на второй.", + "equalDescription": "Возвращает, имеют ли два аргумента одинаковое значение.", + "ifDescription": "Если первый аргумент истинен, возвращает второй аргумент, иначе возвращает третий.", + "toTextDescription": "Преобразует ввод в текст.", + "datetimeFormatDescription": "Преобразует дату в текст, учитывая формат даты. Всегда в UTC. Используйте `datetime_format_tz` для указания часового пояса.", + "datetimeFormatTzDescription": "Преобразует дату в текст, учитывая формат даты в указанном часовом поясе.", + "toNumberDescription": "Преобразует ввод в число, если возможно.", + "fieldDescription": "Возвращает поле с именем, указанным в текстовом аргументе.", + "lookupDescription": "Ищет значения из поля в другой таблице для строк в поле связи с таблицей. Первым аргументом должно быть имя поля связи с таблицей в текущей таблице, а вторым должно быть имя поля в связанной таблице.", + "isBlankDescription": "Возвращает true, если аргумент равен null, пуст или пробел, иначе false.", + "isNullDescription": "Возвращает true, если аргумент равен null, иначе false.", + "tDescription": "Возвращает значение аргумента, если это текст, иначе ''.", + "notDescription": "Возвращает false, если аргумент истинен, и true, если аргумент ложен.", + "greaterThanDescription": "Возвращает true, если первый аргумент больше второго, иначе false.", + "greaterThanOrEqualDescription": "Возвращает true, если первый аргумент больше или равен второму, иначе false.", + "lessThanDescription": "Возвращает true, если первый аргумент меньше второго, иначе false.", + "lessThanOrEqualDescription": "Возвращает true, если первый аргумент меньше или равен второму, иначе false.", + "nowDescription": "Возвращает текущую дату и время в UTC.", + "todayDescription": "Возвращает текущую дату в UTC.", + "toDateDescription": "Возвращает первый аргумент, преобразованный в дату с использованием строки формата даты в качестве второго аргумента. Всегда в UTC. Используйте `to_date_tz` для указания часового пояса.", + "toDateTzDescription": "Возвращает первый аргумент, преобразованный в дату с использованием строки формата даты в качестве второго аргумента и часового пояса, указанного в третьем аргументе.", + "dayDescription": "Возвращает день месяца в виде числа от 1 до 31 из аргумента.", + "dateDiffDescription": "Учитывая единицу измерения даты в качестве первого аргумента ('год', 'месяц', 'неделя', 'день', 'час', 'минута', 'секунды'), вычисляет и возвращает количество единиц от второго аргумента до третьего.", + "andDescription": "Возвращает логическое И первого и второго аргумента, так что если оба истинны, то результат истинен, иначе ложен.", + "orDescription": "Возвращает логическое ИЛИ первого и второго аргумента, так что если любой из них истинен, то результат истинен, иначе ложен.", + "dateIntervalDescription": "Возвращает интервал даты, соответствующий предоставленному аргументу.", + "replaceDescription": "Заменяет все вхождения второго аргумента в первом аргументе третьим аргументом.", + "searchDescription": "Возвращает положительное целое число, начиная с 1 для первого вхождения второго аргумента внутри первого, или 0, если вхождение не найдено.", + "rowIdDescription": "Возвращает уникальный идентификационный номер строки.", + "lengthDescription": "Возвращает количество символов в первом предоставленном аргументе.", + "reverseDescription": "Возвращает обратный текст предоставленного первого аргумента.", + "notEqualDescription": "Возвращает, имеют ли два аргумента разные значения.", + "countDescription": "Возвращает количество элементов в первом аргументе.", + "containsDescription": "Возвращает true, если первый фрагмент текста содержит хотя бы раз второй.", + "leftDescription": "Извлекает самые левые символы из первого ввода, останавливается, когда извлечено количество символов, указанное вторым вводом.", + "rightDescription": "Извлекает самые правые символы из первого ввода, останавливается, когда извлечено количество символов, указанное вторым вводом.", + "trimDescription": "Удаляет все пробелы с левой и правой сторон ввода.", + "regexReplaceDescription": "Заменяет любой текст в первом вводе, который соответствует регулярному выражению, указанному вторым вводом, текстом в третьем вводе. Возвращает '#ERROR!', если шаблон регулярного выражения недействителен.", + "greatestDescription": "Возвращает наибольшее значение из двух вводов.", + "leastDescription": "Возвращает наименьшее из двух вводов.", + "monthDescription": "Возвращает номер месяца в предоставленной дате.", + "yearDescription": "Возвращает номер года в предоставленной дате.", + "secondDescription": "Возвращает количество секунд в предоставленной дате.", + "whenEmptyDescription": "Если первый ввод вычисляется как пустой, вместо него будет возвращен второй ввод, в противном случае, если первый ввод не пустой, будет возвращен первый.", + "anyDescription": "Возвращает true, если хотя бы одно из предоставленных найденных значений истинно, false, если все они ложны.", + "everyDescription": "Возвращает true, если каждое из предоставленных найденных значений истинно, false в противном случае.", + "maxDescription": "Возвращает наибольшее число из всех предоставленных найденных значений.", + "minDescription": "Возвращает наименьшее число из всех предоставленных найденных значений.", + "joinDescription": "Объединяет все значения из первого ввода вместе, используя значения из второго ввода.", + "stddevPopDescription": "Вычисляет генеральное стандартное отклонение значений и возвращает результат. Генеральное стандартное отклонение следует использовать, когда предоставленные значения содержат значение для каждого элемента данных в генеральной совокупности.", + "stddevSampleDescription": "Вычисляет выборочное стандартное отклонение значений и возвращает результат. Выборочное отклонение следует использовать, когда предоставленные значения являются только выборкой или подмножеством значений для основной генеральной совокупности.", + "varianceSampleDescription": "Вычисляет выборочную дисперсию значений и возвращает результат. Выборочную дисперсию следует использовать, когда предоставленные значения являются только выборкой или подмножеством значений для основной генеральной совокупности.", + "variancePopDescription": "Вычисляет генеральную дисперсию значений и возвращает результат. Генеральную дисперсию следует использовать, когда предоставленные значения содержат значение для каждого элемента данных в генеральной совокупности.", + "avgDescription": "Вычисляет среднее значение всех значений и возвращает результат.", + "sumDescription": "Суммирует все значения и возвращает результат.", + "filterDescription": "Фильтрует выражение, включающее ссылку на поле поиска/связи или вызов функции поиска.", + "linkDescription": "Создает гиперссылку, используя URI, предоставленный в первом аргументе.", + "buttonDescription": "Создает кнопку, используя URI (первый аргумент) и метку (второй аргумент).", + "getLinkLabelDescription": "Получает метку из формулы, использующей функции ссылки или кнопки.", + "getLinkUrlDescription": "Получает URL из формулы, использующей функции ссылки или кнопки.", + "evenDescription": "Возвращает true, если предоставленный аргумент является четным числом, false в противном случае.", + "oddDescription": "Возвращает true, если предоставленный аргумент является нечетным числом, false в противном случае.", + "modDescription": "Возвращает остаток от деления первого аргумента на второй аргумент.", + "powerDescription": "Возвращает результат возведения первого аргумента в степень второго аргумента.", + "logDescription": "Логарифмическая функция: возвращает показатель степени, в которую нужно возвести первый аргумент, чтобы получить второй аргумент.", + "expDescription": "Возвращает результат возведения константы e ≈ 2.718 в степень предоставленного аргумента-числа.", + "lnDescription": "Функция натурального логарифма: возвращает показатель степени, в которую нужно возвести константу e ≈ 2.718, чтобы получить аргумент.", + "signDescription": "Возвращает 1, если аргумент является положительным числом, -1, если аргумент является отрицательным, 0 в противном случае.", + "sqrtDescription": "Возвращает квадратный корень предоставленного аргумента.", + "roundDescription": "Возвращает первый аргумент, округленный до количества цифр, указанного вторым аргументом.", + "truncDescription": "Возвращает только первый аргумент, преобразованный в целое число путем отбрасывания десятичных знаков.", + "isNanDescription": "Возвращает true, если аргумент является 'NaN', возвращает false в противном случае.", + "whenNanDescription": "Возвращает первый аргумент, если он не 'NaN'. Возвращает второй аргумент, если первый аргумент - 'NaN'", + "absDescription": "Возвращает абсолютное значение для предоставленного аргумента-числа.", + "ceilDescription": "Возвращает наименьшее целое число, которое больше или равно предоставленному аргументу-числу.", + "floorDescription": "Возвращает наибольшее целое число, которое меньше или равно предоставленному аргументу-числу.", + "encodeUriDescription": "Возвращает закодированную URI-строку из предоставленного аргумента.", + "encodeUriComponentDescription": "Возвращает закодированный компонент URI-строки из предоставленного аргумента.", + "getFileVisibleNameDescription": "Возвращает видимое имя файла из одного файла, возвращенного функцией index.", + "getFileMimeTypeDescription": "Возвращает MIME-тип файла из одного файла, возвращенного функцией index.", + "getFileCountDescription": "Возвращает количество файлов в указанном поле файла", + "getFileSizeDescription": "Возвращает размер файла из одного файла, возвращенного функцией index.", + "getImageWidthDescription": "Возвращает ширину изображения из одного файла, возвращенного функцией index.", + "getImageHeightDescription": "Возвращает высоту изображения из одного файла, возвращенного функцией index.", + "getIsImageDescription": "Возвращает, является ли один файл, возвращенный функцией index, изображением или нет.", + "indexDescription": "Возвращает файл из поля файла в позиции, предоставленной вторым аргументом.", + "secondsToDurationDescription": "Преобразует количество секунд, предоставленное в продолжительность.", + "durationToSecondsDescription": "Преобразует предоставленную продолжительность в соответствующее количество секунд.", + "hasOptionDescription": "Возвращает true, если первый аргумент является полем множественного выбора или поиском в поле одиночного выбора, а второй аргумент - одна из опций." + }, + "functionnalGridViewFieldLinkRow": { + "unnamed": "безымянная строка {value}" + }, + "urlCheck": { + "invalidUrlEnvVarTitle": "Недопустимый {name}", + "invalidUrlEnvVarDescription": "Переменная окружения {name} установлена на недопустимое значение. Ваш администратор сайта должен изменить {name} на действительный URL, начинающийся с http:// или https://, а затем перезапустить Baserow для исправления этой ошибки." + }, + "health": { + "title": "Проверки работоспособности Baserow", + "description": "Эти проверки показывают текущее состояние вашей установки Baserow." + }, + "emailTester": { + "title": "Тестирование электронной почты", + "targetEmailLabel": "Целевая электронная почта", + "invalidTargetEmail": "Недопустимый адрес электронной почты", + "submit": "Отправить тестовое письмо", + "success": "Тестовое письмо успешно отправлено", + "configLink": "Помощь по настройке электронной почты" + } } diff --git a/web-frontend/modules/builder/applicationTypes.js b/web-frontend/modules/builder/applicationTypes.js index ac0e6b801..b89b19e3c 100644 --- a/web-frontend/modules/builder/applicationTypes.js +++ b/web-frontend/modules/builder/applicationTypes.js @@ -60,6 +60,17 @@ export class BuilderApplicationType extends ApplicationType { return PageTemplate } + getTemplatePage(application) { + const notSharedPages = application.pages.filter((p) => p.shared === false) + if (notSharedPages.length === 0) { + return null + } + return { + builder: application, + page: notSharedPages[0], + } + } + populate(application) { const values = super.populate(application) values.pages = values.pages.map(populatePage) diff --git a/web-frontend/modules/builder/assets/icons/element-auth_form.svg b/web-frontend/modules/builder/assets/icons/element-auth_form.svg new file mode 100644 index 000000000..4ebdabf62 --- /dev/null +++ b/web-frontend/modules/builder/assets/icons/element-auth_form.svg @@ -0,0 +1,24 @@ +<svg width="120" height="80" viewBox="0 0 120 80" fill="none" xmlns="http://www.w3.org/2000/svg"> +<g filter="url(#filter0_d_2154_91958)"> +<rect x="2" y="1" width="116" height="76" rx="6" fill="#FAFAFA"/> +<rect x="2.5" y="1.5" width="115" height="75" rx="5.5" stroke="#EDEDED"/> +<rect x="25.25" y="22.25" width="69.5" height="34.5" rx="4.75" fill="white"/> +<rect x="25.25" y="22.25" width="69.5" height="34.5" rx="4.75" stroke="#E6E6E7" stroke-width="1.5"/> +<rect x="76" y="48" width="14" height="4" rx="2" fill="#4E5CFE"/> +<rect x="26" y="43" width="68" height="1" fill="#EDEDED"/> +<rect opacity="0.48" x="48" y="31" width="38" height="4" rx="2" fill="#E6E6E7"/> +<path d="M39.25 33H39.775C40.1064 33 40.375 33.2686 40.375 33.6V36.9C40.375 37.2314 40.1064 37.5 39.775 37.5H34.225C33.8936 37.5 33.625 37.2314 33.625 36.9V33.6C33.625 33.2686 33.8936 33 34.225 33H34.75M39.25 33V30.75C39.25 30 38.8 28.5 37 28.5C35.2 28.5 34.75 30 34.75 30.75V33M39.25 33H34.75" stroke="#D7D8D9" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/> +</g> +<defs> +<filter id="filter0_d_2154_91958" x="0" y="0" width="120" height="80" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB"> +<feFlood flood-opacity="0" result="BackgroundImageFix"/> +<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/> +<feOffset dy="1"/> +<feGaussianBlur stdDeviation="1"/> +<feColorMatrix type="matrix" values="0 0 0 0 0.027451 0 0 0 0 0.0313726 0 0 0 0 0.0627451 0 0 0 0.1 0"/> +<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_2154_91958"/> +<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_2154_91958" result="shape"/> +</filter> +</defs> +</svg> + diff --git a/web-frontend/modules/builder/assets/icons/element-button.svg b/web-frontend/modules/builder/assets/icons/element-button.svg new file mode 100644 index 000000000..3cabf288f --- /dev/null +++ b/web-frontend/modules/builder/assets/icons/element-button.svg @@ -0,0 +1,19 @@ +<svg width="120" height="80" viewBox="0 0 120 80" fill="none" xmlns="http://www.w3.org/2000/svg"> +<g filter="url(#filter0_d_1314_36243)"> +<rect x="2" y="1" width="116" height="76" rx="6" fill="#FAFAFA"/> +<rect x="2.5" y="1.5" width="115" height="75" rx="5.5" stroke="#EDEDED"/> +<rect x="36" y="29" width="48" height="20" rx="4" fill="#4E5CFE"/> +<rect opacity="0.48" x="46" y="37" width="28" height="4" rx="2" fill="white"/> +</g> +<defs> +<filter id="filter0_d_1314_36243" x="0" y="0" width="120" height="80" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB"> +<feFlood flood-opacity="0" result="BackgroundImageFix"/> +<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/> +<feOffset dy="1"/> +<feGaussianBlur stdDeviation="1"/> +<feColorMatrix type="matrix" values="0 0 0 0 0.027451 0 0 0 0 0.0313726 0 0 0 0 0.0627451 0 0 0 0.1 0"/> +<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_1314_36243"/> +<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_1314_36243" result="shape"/> +</filter> +</defs> +</svg> diff --git a/web-frontend/modules/builder/assets/icons/element-checkbox.svg b/web-frontend/modules/builder/assets/icons/element-checkbox.svg new file mode 100644 index 000000000..b2481a290 --- /dev/null +++ b/web-frontend/modules/builder/assets/icons/element-checkbox.svg @@ -0,0 +1,27 @@ +<svg width="120" height="80" viewBox="0 0 120 80" fill="none" xmlns="http://www.w3.org/2000/svg"> +<g filter="url(#filter0_d_2154_91994)"> +<rect x="2" y="1" width="116" height="76" rx="6" fill="#FAFAFA"/> +<rect x="2.5" y="1.5" width="115" height="75" rx="5.5" stroke="#EDEDED"/> +<rect x="51" y="33" width="44" height="4" rx="2" fill="#E6E6E7"/> +<rect opacity="0.48" x="51" y="41" width="32" height="4" rx="2" fill="#E6E6E7"/> +<g clip-path="url(#clip0_2154_91994)"> +<rect x="27" y="31" width="16" height="16" rx="4" fill="white"/> +<path d="M32.0179 39.4821L33.6821 41.1821L37.9248 37.1537" stroke="#4E5CFE" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> +</g> +<rect x="26.25" y="30.25" width="17.5" height="17.5" rx="4.75" stroke="#E6E6E7" stroke-width="1.5"/> +</g> +<defs> +<filter id="filter0_d_2154_91994" x="0" y="0" width="120" height="80" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB"> +<feFlood flood-opacity="0" result="BackgroundImageFix"/> +<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/> +<feOffset dy="1"/> +<feGaussianBlur stdDeviation="1"/> +<feColorMatrix type="matrix" values="0 0 0 0 0.027451 0 0 0 0 0.0313726 0 0 0 0 0.0627451 0 0 0 0.1 0"/> +<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_2154_91994"/> +<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_2154_91994" result="shape"/> +</filter> +<clipPath id="clip0_2154_91994"> +<rect x="27" y="31" width="16" height="16" rx="4" fill="white"/> +</clipPath> +</defs> +</svg> diff --git a/web-frontend/modules/builder/assets/icons/element-choice.svg b/web-frontend/modules/builder/assets/icons/element-choice.svg new file mode 100644 index 000000000..6d92217e3 --- /dev/null +++ b/web-frontend/modules/builder/assets/icons/element-choice.svg @@ -0,0 +1,33 @@ +<svg width="120" height="80" viewBox="0 0 120 80" fill="none" xmlns="http://www.w3.org/2000/svg"> +<g filter="url(#filter0_d_2154_91891)"> +<rect x="2" y="1" width="116" height="76" rx="6" fill="#FAFAFA"/> +<rect x="2.5" y="1.5" width="115" height="75" rx="5.5" stroke="#EDEDED"/> +<rect x="25.25" y="16.25" width="69.5" height="17.5" rx="4.75" fill="white"/> +<rect x="25.25" y="16.25" width="69.5" height="17.5" rx="4.75" stroke="#EDEDED" stroke-width="1.5"/> +<rect opacity="0.48" x="32" y="23" width="42" height="4" rx="2" fill="#E6E6E7"/> +<path d="M87.5 23.75L85 26.25L82.5 23.75" stroke="#D7D8D9" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/> +<g clip-path="url(#clip0_2154_91891)"> +<rect x="34" y="39" width="60" height="25" rx="4" fill="white"/> +<rect x="34" y="39" width="68" height="13" fill="#FAFAFA"/> +<rect x="40" y="43" width="26" height="4" rx="2" fill="#E6E6E7"/> +<path d="M83.0134 45.4866L84.2616 46.7616L87.4436 43.7403" stroke="#4E5CFE" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/> +<rect opacity="0.48" x="40" y="56" width="34" height="4" rx="2" fill="#E6E6E7"/> +<rect x="34" y="51" width="68" height="1" fill="#EDEDED"/> +</g> +<rect x="33.25" y="38.25" width="61.5" height="26.5" rx="4.75" stroke="#E6E6E7" stroke-width="1.5"/> +</g> +<defs> +<filter id="filter0_d_2154_91891" x="0" y="0" width="120" height="80" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB"> +<feFlood flood-opacity="0" result="BackgroundImageFix"/> +<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/> +<feOffset dy="1"/> +<feGaussianBlur stdDeviation="1"/> +<feColorMatrix type="matrix" values="0 0 0 0 0.027451 0 0 0 0 0.0313726 0 0 0 0 0.0627451 0 0 0 0.1 0"/> +<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_2154_91891"/> +<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_2154_91891" result="shape"/> +</filter> +<clipPath id="clip0_2154_91891"> +<rect x="34" y="39" width="60" height="25" rx="4" fill="white"/> +</clipPath> +</defs> +</svg> diff --git a/web-frontend/modules/builder/assets/icons/element-column.svg b/web-frontend/modules/builder/assets/icons/element-column.svg new file mode 100644 index 000000000..321cacf98 --- /dev/null +++ b/web-frontend/modules/builder/assets/icons/element-column.svg @@ -0,0 +1,22 @@ +<svg width="120" height="80" viewBox="0 0 120 80" fill="none" xmlns="http://www.w3.org/2000/svg"> +<g filter="url(#filter0_d_1314_36373)"> +<rect x="2" y="1" width="116" height="76" rx="6" fill="#FAFAFA"/> +<rect x="2.5" y="1.5" width="115" height="75" rx="5.5" stroke="#EDEDED"/> +<rect x="25.25" y="16.25" width="69.5" height="45.5" rx="4.75" fill="white"/> +<rect x="25.25" y="16.25" width="69.5" height="45.5" rx="4.75" stroke="#E6E6E7" stroke-width="1.5"/> +<rect x="32.75" y="23.75" width="14.5" height="30.5" rx="3.25" fill="#F7F7F7" stroke="#E6E6E7" stroke-width="1.5" stroke-dasharray="4 4"/> +<rect x="52.75" y="23.75" width="14.5" height="30.5" rx="3.25" fill="#F7F7F7" stroke="#E6E6E7" stroke-width="1.5" stroke-dasharray="4 4"/> +<rect x="72.75" y="23.75" width="14.5" height="30.5" rx="3.25" fill="#F7F7F7" stroke="#E6E6E7" stroke-width="1.5" stroke-dasharray="4 4"/> +</g> +<defs> +<filter id="filter0_d_1314_36373" x="0" y="0" width="120" height="80" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB"> +<feFlood flood-opacity="0" result="BackgroundImageFix"/> +<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/> +<feOffset dy="1"/> +<feGaussianBlur stdDeviation="1"/> +<feColorMatrix type="matrix" values="0 0 0 0 0.027451 0 0 0 0 0.0313726 0 0 0 0 0.0627451 0 0 0 0.1 0"/> +<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_1314_36373"/> +<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_1314_36373" result="shape"/> +</filter> +</defs> +</svg> diff --git a/web-frontend/modules/builder/assets/icons/element-container.svg b/web-frontend/modules/builder/assets/icons/element-container.svg new file mode 100644 index 000000000..219d26f82 --- /dev/null +++ b/web-frontend/modules/builder/assets/icons/element-container.svg @@ -0,0 +1,22 @@ +<svg width="120" height="80" viewBox="0 0 120 80" fill="none" xmlns="http://www.w3.org/2000/svg"> +<g filter="url(#filter0_d_1409_24006)"> +<rect x="2" y="1" width="116" height="76" rx="6" fill="#FAFAFA"/> +<rect x="2.5" y="1.5" width="115" height="75" rx="5.5" stroke="#EDEDED"/> +<rect x="25.25" y="28.25" width="69.5" height="21.5" rx="4.75" fill="white"/> +<rect x="25.25" y="28.25" width="69.5" height="21.5" rx="4.75" stroke="#E6E6E7" stroke-width="1.5"/> +<rect opacity="0.48" x="66" y="37" width="20" height="4" rx="2" fill="#E6E6E7"/> +<rect x="48" y="37" width="14" height="4" rx="2" fill="#E6E6E7"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M39 37.5V35H39.5C39.775 35 40 34.775 40 34.5C40 34.225 39.775 34 39.5 34H34.5C34.225 34 34 34.225 34 34.5C34 34.775 34.225 35 34.5 35H35V37.5C35 38.33 34.33 39 33.5 39V40H36.485V43.5L36.985 44L37.485 43.5V40H40.5V39C39.67 39 39 38.33 39 37.5Z" fill="#D7D8D9"/> +</g> +<defs> +<filter id="filter0_d_1409_24006" x="0" y="0" width="120" height="80" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB"> +<feFlood flood-opacity="0" result="BackgroundImageFix"/> +<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/> +<feOffset dy="1"/> +<feGaussianBlur stdDeviation="1"/> +<feColorMatrix type="matrix" values="0 0 0 0 0.027451 0 0 0 0 0.0313726 0 0 0 0 0.0627451 0 0 0 0.1 0"/> +<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_1409_24006"/> +<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_1409_24006" result="shape"/> +</filter> +</defs> +</svg> diff --git a/web-frontend/modules/builder/assets/icons/element-datetime_picker.svg b/web-frontend/modules/builder/assets/icons/element-datetime_picker.svg new file mode 100644 index 000000000..3849eb9fe --- /dev/null +++ b/web-frontend/modules/builder/assets/icons/element-datetime_picker.svg @@ -0,0 +1,39 @@ +<svg width="120" height="80" viewBox="0 0 120 80" fill="none" xmlns="http://www.w3.org/2000/svg"> +<g filter="url(#filter0_d_3714_70853)"> +<rect x="2" y="1" width="116" height="76" rx="6" fill="#FAFAFA"/> +<rect x="2.5" y="1.5" width="115" height="75" rx="5.5" stroke="#EDEDED"/> +<g clip-path="url(#clip0_3714_70853)"> +<rect x="26" y="17" width="68" height="44" rx="4" fill="white"/> +<rect x="26" y="17" width="68" height="9" fill="#FAFAFA"/> +<rect opacity="0.64" x="29" y="20" width="6.8" height="3" rx="1.5" fill="#E6E6E7"/> +<rect opacity="0.64" x="42.7998" y="20" width="6.8" height="3" rx="1.5" fill="#E6E6E7"/> +<rect opacity="0.64" x="56.6001" y="20" width="6.8" height="3" rx="1.5" fill="#E6E6E7"/> +<rect opacity="0.64" x="70.3999" y="20" width="6.8" height="3" rx="1.5" fill="#E6E6E7"/> +<rect opacity="0.64" x="84.2002" y="20" width="6.8" height="3" rx="1.5" fill="#E6E6E7"/> +<rect x="38.7998" y="26" width="1" height="35" fill="#EDEDED"/> +<rect x="52.5996" y="26" width="1" height="35" fill="#EDEDED"/> +<rect x="66.3999" y="26" width="1" height="35" fill="#EDEDED"/> +<rect x="80.1997" y="26" width="1" height="35" fill="#EDEDED"/> +<rect x="26" y="34" width="68" height="1" fill="#EDEDED"/> +<rect x="26" y="25" width="68" height="1" fill="#EDEDED"/> +<rect x="26" y="43" width="68" height="1" fill="#EDEDED"/> +<rect x="26" y="52" width="68" height="1" fill="#EDEDED"/> +<rect x="55.1001" y="36.5" width="9.8" height="5" rx="2" fill="#4E5CFE"/> +</g> +<rect x="25.25" y="16.25" width="69.5" height="45.5" rx="4.75" stroke="#E6E6E7" stroke-width="1.5"/> +</g> +<defs> +<filter id="filter0_d_3714_70853" x="0" y="0" width="120" height="80" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB"> +<feFlood flood-opacity="0" result="BackgroundImageFix"/> +<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/> +<feOffset dy="1"/> +<feGaussianBlur stdDeviation="1"/> +<feColorMatrix type="matrix" values="0 0 0 0 0.027451 0 0 0 0 0.0313726 0 0 0 0 0.0627451 0 0 0 0.1 0"/> +<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_3714_70853"/> +<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_3714_70853" result="shape"/> +</filter> +<clipPath id="clip0_3714_70853"> +<rect x="26" y="17" width="68" height="44" rx="4" fill="white"/> +</clipPath> +</defs> +</svg> diff --git a/web-frontend/modules/builder/assets/icons/element-fields.svg b/web-frontend/modules/builder/assets/icons/element-fields.svg new file mode 100644 index 000000000..68f580d4b --- /dev/null +++ b/web-frontend/modules/builder/assets/icons/element-fields.svg @@ -0,0 +1,27 @@ +<svg width="120" height="80" viewBox="0 0 120 80" fill="none" xmlns="http://www.w3.org/2000/svg"> +<g filter="url(#filter0_d_1314_36316)"> +<rect x="2" y="1" width="116" height="76" rx="6" fill="#FAFAFA"/> +<rect x="2.5" y="1.5" width="115" height="75" rx="5.5" stroke="#EDEDED"/> +<rect x="25.25" y="16.25" width="69.5" height="45.5" rx="4.75" fill="white"/> +<rect x="25.25" y="16.25" width="69.5" height="45.5" rx="4.75" stroke="#E6E6E7" stroke-width="1.5"/> +<rect x="32" y="23" width="14" height="4" rx="2" fill="#E6E6E7"/> +<rect x="32" y="43" width="14" height="4" rx="2" fill="#E6E6E7"/> +<rect x="67" y="23" width="14" height="4" rx="2" fill="#E6E6E7"/> +<rect x="67" y="43" width="14" height="4" rx="2" fill="#E6E6E7"/> +<rect opacity="0.48" x="32" y="31" width="21" height="4" rx="2" fill="#E6E6E7"/> +<rect opacity="0.48" x="32" y="51" width="21" height="4" rx="2" fill="#E6E6E7"/> +<rect opacity="0.48" x="67" y="31" width="21" height="4" rx="2" fill="#E6E6E7"/> +<rect opacity="0.48" x="67" y="51" width="21" height="4" rx="2" fill="#E6E6E7"/> +</g> +<defs> +<filter id="filter0_d_1314_36316" x="0" y="0" width="120" height="80" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB"> +<feFlood flood-opacity="0" result="BackgroundImageFix"/> +<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/> +<feOffset dy="1"/> +<feGaussianBlur stdDeviation="1"/> +<feColorMatrix type="matrix" values="0 0 0 0 0.027451 0 0 0 0 0.0313726 0 0 0 0 0.0627451 0 0 0 0.1 0"/> +<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_1314_36316"/> +<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_1314_36316" result="shape"/> +</filter> +</defs> +</svg> diff --git a/web-frontend/modules/builder/assets/icons/element-footer.svg b/web-frontend/modules/builder/assets/icons/element-footer.svg new file mode 100644 index 000000000..1897c1d04 --- /dev/null +++ b/web-frontend/modules/builder/assets/icons/element-footer.svg @@ -0,0 +1,32 @@ +<svg width="120" height="80" viewBox="0 0 120 80" fill="none" xmlns="http://www.w3.org/2000/svg"> +<g filter="url(#filter0_d_2043_89937)"> +<rect x="2" y="1" width="116" height="76" rx="6" fill="#FAFAFA"/> +<rect x="2.5" y="1.5" width="115" height="75" rx="5.5" stroke="#EDEDED"/> +<rect x="25.25" y="16.25" width="69.5" height="45.5" rx="4.75" fill="#F7F7F7" stroke="#E6E6E7" stroke-width="1.5" stroke-dasharray="4 4"/> +<path d="M26 40.25H25.25V41V57C25.25 59.6234 27.3766 61.75 30 61.75H90C92.6234 61.75 94.75 59.6234 94.75 57V41V40.25H94H26Z" fill="white"/> +<path d="M26 40.25H25.25V41V57C25.25 59.6234 27.3766 61.75 30 61.75H90C92.6234 61.75 94.75 59.6234 94.75 57V41V40.25H94H26Z" stroke="#E6E6E7" stroke-width="1.5"/> +<rect opacity="0.48" x="63" y="49" width="11" height="4" rx="2" fill="#E6E6E7"/> +<rect opacity="0.48" x="78" y="49" width="10" height="4" rx="2" fill="#E6E6E7"/> +<rect x="48" y="49" width="11" height="4" rx="2" fill="#E6E6E7"/> +<g clip-path="url(#clip0_2043_89937)"> +<path fill-rule="evenodd" clip-rule="evenodd" d="M32.8311 51.3977C32.6114 51.1781 32.6114 50.8219 32.8311 50.6023L33.9507 49.4827C34.1704 49.263 34.5265 49.263 34.7462 49.4827L35.8658 50.6023C36.0854 50.8219 36.0854 51.1781 35.8658 51.3977L34.7462 52.5173C34.5265 52.737 34.1704 52.737 33.9507 52.5173L32.8311 51.3977Z" fill="#CDCECF"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M35.4826 54.0494C35.2629 53.8298 35.2629 53.4736 35.4826 53.2539L36.6022 52.1343C36.8218 51.9147 37.178 51.9147 37.3977 52.1343L38.5173 53.2539C38.7369 53.4736 38.7369 53.8298 38.5173 54.0494L37.3977 55.169C37.178 55.3887 36.8218 55.3887 36.6022 55.169L35.4826 54.0494Z" fill="#CDCECF"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M35.4826 48.7461C35.2629 48.5264 35.2629 48.1702 35.4826 47.9506L36.6022 46.831C36.8218 46.6113 37.178 46.6113 37.3977 46.831L38.5173 47.9506C38.7369 48.1702 38.7369 48.5264 38.5173 48.7461L37.3977 49.8657C37.178 50.0853 36.8218 50.0853 36.6022 49.8657L35.4826 48.7461Z" fill="#CDCECF"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M38.1344 51.3977C37.9148 51.1781 37.9148 50.8219 38.1344 50.6023L39.254 49.4827C39.4737 49.263 39.8299 49.263 40.0495 49.4827L41.1691 50.6023C41.3888 50.8219 41.3888 51.1781 41.1691 51.3977L40.0495 52.5173C39.8299 52.737 39.4737 52.737 39.254 52.5173L38.1344 51.3977Z" fill="#CDCECF"/> +</g> +</g> +<defs> +<filter id="filter0_d_2043_89937" x="0" y="0" width="120" height="80" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB"> +<feFlood flood-opacity="0" result="BackgroundImageFix"/> +<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/> +<feOffset dy="1"/> +<feGaussianBlur stdDeviation="1"/> +<feColorMatrix type="matrix" values="0 0 0 0 0.027451 0 0 0 0 0.0313726 0 0 0 0 0.0627451 0 0 0 0.1 0"/> +<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_2043_89937"/> +<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_2043_89937" result="shape"/> +</filter> +<clipPath id="clip0_2043_89937"> +<rect width="10" height="10" fill="white" transform="translate(32 46)"/> +</clipPath> +</defs> +</svg> diff --git a/web-frontend/modules/builder/assets/icons/element-form_container.svg b/web-frontend/modules/builder/assets/icons/element-form_container.svg new file mode 100644 index 000000000..cb6933814 --- /dev/null +++ b/web-frontend/modules/builder/assets/icons/element-form_container.svg @@ -0,0 +1,30 @@ +<svg width="120" height="80" viewBox="0 0 120 80" fill="none" xmlns="http://www.w3.org/2000/svg"> +<g filter="url(#filter0_d_1314_36388)"> +<rect x="2" y="1" width="116" height="76" rx="6" fill="#FAFAFA"/> +<rect x="2.5" y="1.5" width="115" height="75" rx="5.5" stroke="#EDEDED"/> +<rect x="25.25" y="20.25" width="69.5" height="38.5" rx="4.75" fill="white"/> +<rect x="25.25" y="20.25" width="69.5" height="38.5" rx="4.75" stroke="#E6E6E7" stroke-width="1.5"/> +<rect x="76" y="50" width="14" height="4" rx="2" fill="#4E5CFE"/> +<rect x="26" y="45" width="68" height="1" fill="#EDEDED"/> +<rect x="32" y="27" width="40" height="4" rx="2" fill="#E6E6E7"/> +<rect opacity="0.48" x="32" y="35" width="32" height="4" rx="2" fill="#E6E6E7"/> +<g clip-path="url(#clip0_1314_36388)"> +<path d="M83.0625 30.1875L78.1875 35.0625C78.0625 35.1875 78 35.3125 78 35.5V37.375C78 37.75 78.25 38 78.625 38H80.5C80.6875 38 80.8125 37.9375 80.9375 37.8125L85.8125 32.9375L83.0625 30.1875Z" fill="#D7D8D9"/> +<path d="M87.8125 30.0625L85.9375 28.1875C85.6875 27.9375 85.3125 27.9375 85.0625 28.1875L83.9375 29.3125L86.6875 32.0625L87.8125 30.9375C88.0625 30.6875 88.0625 30.3125 87.8125 30.0625Z" fill="#D7D8D9"/> +</g> +</g> +<defs> +<filter id="filter0_d_1314_36388" x="0" y="0" width="120" height="80" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB"> +<feFlood flood-opacity="0" result="BackgroundImageFix"/> +<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/> +<feOffset dy="1"/> +<feGaussianBlur stdDeviation="1"/> +<feColorMatrix type="matrix" values="0 0 0 0 0.027451 0 0 0 0 0.0313726 0 0 0 0 0.0627451 0 0 0 0.1 0"/> +<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_1314_36388"/> +<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_1314_36388" result="shape"/> +</filter> +<clipPath id="clip0_1314_36388"> +<rect width="10" height="10" fill="white" transform="translate(78 28)"/> +</clipPath> +</defs> +</svg> diff --git a/web-frontend/modules/builder/assets/icons/element-header.svg b/web-frontend/modules/builder/assets/icons/element-header.svg new file mode 100644 index 000000000..d21439d27 --- /dev/null +++ b/web-frontend/modules/builder/assets/icons/element-header.svg @@ -0,0 +1,32 @@ +<svg width="120" height="80" viewBox="0 0 120 80" fill="none" xmlns="http://www.w3.org/2000/svg"> +<g filter="url(#filter0_d_2043_89952)"> +<rect x="2" y="1" width="116" height="76" rx="6" fill="#FAFAFA"/> +<rect x="2.5" y="1.5" width="115" height="75" rx="5.5" stroke="#EDEDED"/> +<rect x="25.25" y="16.25" width="69.5" height="45.5" rx="4.75" fill="#F7F7F7" stroke="#E6E6E7" stroke-width="1.5" stroke-dasharray="4 4"/> +<path d="M94 37.75H94.75V37V21C94.75 18.3766 92.6234 16.25 90 16.25H30C27.3766 16.25 25.25 18.3766 25.25 21V37V37.75H26H94Z" fill="white"/> +<path d="M94 37.75H94.75V37V21C94.75 18.3766 92.6234 16.25 90 16.25H30C27.3766 16.25 25.25 18.3766 25.25 21V37V37.75H26H94Z" stroke="#E6E6E7" stroke-width="1.5"/> +<rect opacity="0.48" x="63" y="25" width="11" height="4" rx="2" fill="#E6E6E7"/> +<rect opacity="0.48" x="78" y="25" width="10" height="4" rx="2" fill="#E6E6E7"/> +<rect x="48" y="25" width="11" height="4" rx="2" fill="#E6E6E7"/> +<g clip-path="url(#clip0_2043_89952)"> +<path fill-rule="evenodd" clip-rule="evenodd" d="M32.8311 27.3977C32.6114 27.1781 32.6114 26.8219 32.8311 26.6023L33.9507 25.4827C34.1704 25.263 34.5265 25.263 34.7462 25.4827L35.8658 26.6023C36.0854 26.8219 36.0854 27.1781 35.8658 27.3977L34.7462 28.5173C34.5265 28.737 34.1704 28.737 33.9507 28.5173L32.8311 27.3977Z" fill="#CDCECF"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M35.4826 30.0494C35.2629 29.8298 35.2629 29.4736 35.4826 29.2539L36.6022 28.1343C36.8218 27.9147 37.178 27.9147 37.3977 28.1343L38.5173 29.2539C38.7369 29.4736 38.7369 29.8298 38.5173 30.0494L37.3977 31.169C37.178 31.3887 36.8218 31.3887 36.6022 31.169L35.4826 30.0494Z" fill="#CDCECF"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M35.4826 24.7461C35.2629 24.5264 35.2629 24.1702 35.4826 23.9506L36.6022 22.831C36.8218 22.6113 37.178 22.6113 37.3977 22.831L38.5173 23.9506C38.7369 24.1702 38.7369 24.5264 38.5173 24.7461L37.3977 25.8657C37.178 26.0853 36.8218 26.0853 36.6022 25.8657L35.4826 24.7461Z" fill="#CDCECF"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M38.1344 27.3977C37.9148 27.1781 37.9148 26.8219 38.1344 26.6023L39.254 25.4827C39.4737 25.263 39.8299 25.263 40.0495 25.4827L41.1691 26.6023C41.3888 26.8219 41.3888 27.1781 41.1691 27.3977L40.0495 28.5173C39.8299 28.737 39.4737 28.737 39.254 28.5173L38.1344 27.3977Z" fill="#CDCECF"/> +</g> +</g> +<defs> +<filter id="filter0_d_2043_89952" x="0" y="0" width="120" height="80" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB"> +<feFlood flood-opacity="0" result="BackgroundImageFix"/> +<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/> +<feOffset dy="1"/> +<feGaussianBlur stdDeviation="1"/> +<feColorMatrix type="matrix" values="0 0 0 0 0.027451 0 0 0 0 0.0313726 0 0 0 0 0.0627451 0 0 0 0.1 0"/> +<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_2043_89952"/> +<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_2043_89952" result="shape"/> +</filter> +<clipPath id="clip0_2043_89952"> +<rect width="10" height="10" fill="white" transform="translate(32 22)"/> +</clipPath> +</defs> +</svg> diff --git a/web-frontend/modules/builder/assets/icons/element-heading.svg b/web-frontend/modules/builder/assets/icons/element-heading.svg new file mode 100644 index 000000000..f3c4ea5ba --- /dev/null +++ b/web-frontend/modules/builder/assets/icons/element-heading.svg @@ -0,0 +1,27 @@ +<svg width="120" height="80" viewBox="0 0 120 80" fill="none" xmlns="http://www.w3.org/2000/svg"> +<g filter="url(#filter0_d_1314_36266)"> +<rect x="2" y="1" width="116" height="76" rx="6" fill="#FAFAFA"/> +<rect x="2.5" y="1.5" width="115" height="75" rx="5.5" stroke="#EDEDED"/> +<rect x="25.25" y="28.25" width="69.5" height="21.5" rx="4.75" fill="white"/> +<rect x="25.25" y="28.25" width="69.5" height="21.5" rx="4.75" stroke="#E6E6E7" stroke-width="1.5"/> +<rect opacity="0.48" x="48" y="37" width="38" height="4" rx="2" fill="#E6E6E7"/> +<rect x="32" y="34" width="4" height="2" rx="1" fill="#D7D8D9"/> +<rect x="33" y="38" width="8" height="2" rx="1" fill="#D7D8D9"/> +<rect x="38" y="34" width="4" height="2" rx="1" fill="#D7D8D9"/> +<rect x="33" y="34" width="2" height="10" rx="1" fill="#D7D8D9"/> +<rect x="39" y="34" width="2" height="10" rx="1" fill="#D7D8D9"/> +<rect x="32" y="42" width="4" height="2" rx="1" fill="#D7D8D9"/> +<rect x="38" y="42" width="4" height="2" rx="1" fill="#D7D8D9"/> +</g> +<defs> +<filter id="filter0_d_1314_36266" x="0" y="0" width="120" height="80" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB"> +<feFlood flood-opacity="0" result="BackgroundImageFix"/> +<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/> +<feOffset dy="1"/> +<feGaussianBlur stdDeviation="1"/> +<feColorMatrix type="matrix" values="0 0 0 0 0.027451 0 0 0 0 0.0313726 0 0 0 0 0.0627451 0 0 0 0.1 0"/> +<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_1314_36266"/> +<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_1314_36266" result="shape"/> +</filter> +</defs> +</svg> diff --git a/web-frontend/modules/builder/assets/icons/element-iframe.svg b/web-frontend/modules/builder/assets/icons/element-iframe.svg new file mode 100644 index 000000000..b265f7b28 --- /dev/null +++ b/web-frontend/modules/builder/assets/icons/element-iframe.svg @@ -0,0 +1,24 @@ +<svg width="120" height="80" viewBox="0 0 120 80" fill="none" xmlns="http://www.w3.org/2000/svg"> +<g filter="url(#filter0_d_2154_91943)"> +<rect x="2" y="1" width="116" height="76" rx="6" fill="#FAFAFA"/> +<rect x="2.5" y="1.5" width="115" height="75" rx="5.5" stroke="#EDEDED"/> +<rect x="25.25" y="16.25" width="69.5" height="45.5" rx="4.75" fill="white"/> +<rect x="25.25" y="16.25" width="69.5" height="45.5" rx="4.75" stroke="#E6E6E7" stroke-width="1.5"/> +<path d="M40.9998 25L38.6665 33.3333" stroke="#D7D8D9" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/> +<path d="M36.3333 26.6667L34 29L36.3333 31.3333" stroke="#D7D8D9" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/> +<path d="M43.6667 26.6667L46 29L43.6667 31.3333" stroke="#D7D8D9" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/> +<rect x="32" y="43" width="56" height="4" rx="2" fill="#E6E6E7"/> +<rect opacity="0.48" x="32" y="51" width="40" height="4" rx="2" fill="#E6E6E7"/> +</g> +<defs> +<filter id="filter0_d_2154_91943" x="0" y="0" width="120" height="80" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB"> +<feFlood flood-opacity="0" result="BackgroundImageFix"/> +<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/> +<feOffset dy="1"/> +<feGaussianBlur stdDeviation="1"/> +<feColorMatrix type="matrix" values="0 0 0 0 0.027451 0 0 0 0 0.0313726 0 0 0 0 0.0627451 0 0 0 0.1 0"/> +<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_2154_91943"/> +<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_2154_91943" result="shape"/> +</filter> +</defs> +</svg> diff --git a/web-frontend/modules/builder/assets/icons/element-image.svg b/web-frontend/modules/builder/assets/icons/element-image.svg new file mode 100644 index 000000000..b5dbe9278 --- /dev/null +++ b/web-frontend/modules/builder/assets/icons/element-image.svg @@ -0,0 +1,26 @@ +<svg width="120" height="80" viewBox="0 0 120 80" fill="none" xmlns="http://www.w3.org/2000/svg"> +<g filter="url(#filter0_d_1314_36328)"> +<rect x="2" y="1" width="116" height="76" rx="6" fill="#FAFAFA"/> +<rect x="2.5" y="1.5" width="115" height="75" rx="5.5" stroke="#EDEDED"/> +<rect x="37.25" y="24.25" width="45.5" height="29.5" rx="4.75" fill="white"/> +<rect x="37.25" y="24.25" width="45.5" height="29.5" rx="4.75" stroke="#E6E6E7" stroke-width="1.5"/> +<g clip-path="url(#clip0_1314_36328)"> +<path d="M67.8949 44.553L63.8949 36.553C63.7419 36.248 63.4449 36.041 63.1059 36.006C62.7679 35.967 62.4329 36.11 62.2199 36.375L58.7919 40.659L56.5549 39.168C56.3269 39.017 56.0459 38.964 55.7809 39.024C55.5139 39.084 55.2829 39.251 55.1429 39.485L52.1429 44.485C51.9569 44.794 51.9529 45.178 52.1299 45.493C52.3069 45.807 52.6399 46 52.9999 46H66.9999C67.3469 46 67.6679 45.82 67.8509 45.525C68.0339 45.23 68.0489 44.862 67.8949 44.553Z" fill="#12D452"/> +<path d="M56.5 36C57.8807 36 59 34.8807 59 33.5C59 32.1193 57.8807 31 56.5 31C55.1193 31 54 32.1193 54 33.5C54 34.8807 55.1193 36 56.5 36Z" fill="#FFC744"/> +</g> +</g> +<defs> +<filter id="filter0_d_1314_36328" x="0" y="0" width="120" height="80" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB"> +<feFlood flood-opacity="0" result="BackgroundImageFix"/> +<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/> +<feOffset dy="1"/> +<feGaussianBlur stdDeviation="1"/> +<feColorMatrix type="matrix" values="0 0 0 0 0.027451 0 0 0 0 0.0313726 0 0 0 0 0.0627451 0 0 0 0.1 0"/> +<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_1314_36328"/> +<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_1314_36328" result="shape"/> +</filter> +<clipPath id="clip0_1314_36328"> +<rect width="16" height="16" fill="white" transform="translate(52 31)"/> +</clipPath> +</defs> +</svg> diff --git a/web-frontend/modules/builder/assets/icons/element-input_text.svg b/web-frontend/modules/builder/assets/icons/element-input_text.svg new file mode 100644 index 000000000..a0529831a --- /dev/null +++ b/web-frontend/modules/builder/assets/icons/element-input_text.svg @@ -0,0 +1,25 @@ +<svg width="120" height="80" viewBox="0 0 120 80" fill="none" xmlns="http://www.w3.org/2000/svg"> +<g filter="url(#filter0_d_1314_36279)"> +<rect x="2" y="1" width="116" height="76" rx="6" fill="#FAFAFA"/> +<rect x="2.5" y="1.5" width="115" height="75" rx="5.5" stroke="#EDEDED"/> +<rect x="25.25" y="28.25" width="69.5" height="21.5" rx="4.75" fill="white"/> +<rect x="25.25" y="28.25" width="69.5" height="21.5" rx="4.75" stroke="#E6E6E7" stroke-width="1.5"/> +<rect x="48" y="37" width="28" height="4" rx="2" fill="#E6E6E7"/> +<rect x="82" y="33" width="6" height="2" rx="1" fill="#D7D8D9"/> +<rect x="84" y="34" width="2" height="10" rx="1" fill="#D7D8D9"/> +<rect x="82" y="43" width="6" height="2" rx="1" fill="#D7D8D9"/> +<path d="M41.1666 36.0238V34.8333H32.8333V36.0238" stroke="#D7D8D9" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> +<path d="M36.9998 34.8333V43.1667M36.9998 43.1667H35.8093M36.9998 43.1667H38.1903" stroke="#D7D8D9" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> +</g> +<defs> +<filter id="filter0_d_1314_36279" x="0" y="0" width="120" height="80" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB"> +<feFlood flood-opacity="0" result="BackgroundImageFix"/> +<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/> +<feOffset dy="1"/> +<feGaussianBlur stdDeviation="1"/> +<feColorMatrix type="matrix" values="0 0 0 0 0.027451 0 0 0 0 0.0313726 0 0 0 0 0.0627451 0 0 0 0.1 0"/> +<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_1314_36279"/> +<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_1314_36279" result="shape"/> +</filter> +</defs> +</svg> diff --git a/web-frontend/modules/builder/assets/icons/element-link.svg b/web-frontend/modules/builder/assets/icons/element-link.svg new file mode 100644 index 000000000..cb6933814 --- /dev/null +++ b/web-frontend/modules/builder/assets/icons/element-link.svg @@ -0,0 +1,30 @@ +<svg width="120" height="80" viewBox="0 0 120 80" fill="none" xmlns="http://www.w3.org/2000/svg"> +<g filter="url(#filter0_d_1314_36388)"> +<rect x="2" y="1" width="116" height="76" rx="6" fill="#FAFAFA"/> +<rect x="2.5" y="1.5" width="115" height="75" rx="5.5" stroke="#EDEDED"/> +<rect x="25.25" y="20.25" width="69.5" height="38.5" rx="4.75" fill="white"/> +<rect x="25.25" y="20.25" width="69.5" height="38.5" rx="4.75" stroke="#E6E6E7" stroke-width="1.5"/> +<rect x="76" y="50" width="14" height="4" rx="2" fill="#4E5CFE"/> +<rect x="26" y="45" width="68" height="1" fill="#EDEDED"/> +<rect x="32" y="27" width="40" height="4" rx="2" fill="#E6E6E7"/> +<rect opacity="0.48" x="32" y="35" width="32" height="4" rx="2" fill="#E6E6E7"/> +<g clip-path="url(#clip0_1314_36388)"> +<path d="M83.0625 30.1875L78.1875 35.0625C78.0625 35.1875 78 35.3125 78 35.5V37.375C78 37.75 78.25 38 78.625 38H80.5C80.6875 38 80.8125 37.9375 80.9375 37.8125L85.8125 32.9375L83.0625 30.1875Z" fill="#D7D8D9"/> +<path d="M87.8125 30.0625L85.9375 28.1875C85.6875 27.9375 85.3125 27.9375 85.0625 28.1875L83.9375 29.3125L86.6875 32.0625L87.8125 30.9375C88.0625 30.6875 88.0625 30.3125 87.8125 30.0625Z" fill="#D7D8D9"/> +</g> +</g> +<defs> +<filter id="filter0_d_1314_36388" x="0" y="0" width="120" height="80" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB"> +<feFlood flood-opacity="0" result="BackgroundImageFix"/> +<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/> +<feOffset dy="1"/> +<feGaussianBlur stdDeviation="1"/> +<feColorMatrix type="matrix" values="0 0 0 0 0.027451 0 0 0 0 0.0313726 0 0 0 0 0.0627451 0 0 0 0.1 0"/> +<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_1314_36388"/> +<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_1314_36388" result="shape"/> +</filter> +<clipPath id="clip0_1314_36388"> +<rect width="10" height="10" fill="white" transform="translate(78 28)"/> +</clipPath> +</defs> +</svg> diff --git a/web-frontend/modules/builder/assets/icons/element-map.svg b/web-frontend/modules/builder/assets/icons/element-map.svg new file mode 100644 index 000000000..b28e20352 --- /dev/null +++ b/web-frontend/modules/builder/assets/icons/element-map.svg @@ -0,0 +1,38 @@ +<svg width="120" height="80" viewBox="0 0 120 80" fill="none" xmlns="http://www.w3.org/2000/svg"> +<g filter="url(#filter0_d_1314_36343)"> +<rect x="2" y="1" width="116" height="76" rx="6" fill="#FAFAFA"/> +<rect x="2.5" y="1.5" width="115" height="75" rx="5.5" stroke="#EDEDED"/> +<g clip-path="url(#clip0_1314_36343)"> +<rect x="26" y="21" width="68" height="36" rx="4" fill="white"/> +<g opacity="0.56"> +<path d="M58.7717 95.777L58.6539 95.7299L58.5297 95.7845L58.4478 95.9483L56.5856 98.0023L56.4236 98.142L56.1193 98.2648L55.8974 98.3006L55.236 98.2938L54.823 98.3828L54.4723 98.5549L54.1594 98.8532L53.8664 99.3221L53.5225 100.392L53.5603 100.43L53.629 100.528L53.6713 100.685L53.6203 100.905L53.5248 100.976L53.2605 100.983L53.1983 100.996L53.0472 101.638L52.9918 102.048L52.8362 102.312L52.1749 102.578L51.6354 102.685L51.4134 102.669L51.2069 102.564L50.7807 102.252L50.5833 102.184L50.1148 102.295L49.2847 102.778L48.7407 102.821L48.3213 102.742L48.2013 102.371L48.29 101.289L48.2345 100.8L48.1303 100.353L48.108 99.883L48.2968 99.3274L47.6754 98.9474L45.549 98.7511L45.64 98.2001L45.5777 97.5175L45.2692 96.1088L45.1737 95.8097L44.9208 95.2323L44.8208 94.9144L44.6766 93.7754L44.5879 93.517L44.2658 93.2774L43.9306 93.3354L43.5954 93.4808L43.2825 93.5064L43.0118 93.3437L42.5901 92.8457L42.3104 92.6164L42.0042 92.5241L41.3429 92.4657L41.0563 92.2653L40.9208 92.0171L40.7056 91.0528L40.1994 90.0106L39.8265 89.0022L39.8178 88.1114L40.4082 87.4263L39.8378 87.1189L39.7445 86.7117L39.7978 86.2013L39.6645 85.5979L39.347 85.4054L38.5014 85.9471L38.002 85.949L36.4063 85.0668L35.5762 84.7711L34.7106 84.8777H34.7574L34.7951 84.8966L34.8238 84.9342L34.8484 84.9911L34.247 85.5154L33.9363 85.5772L33.5101 85.228L33.3905 85.0028L33.2417 84.4868L33.1507 84.3044L32.8955 84.115L32.3916 84.0099L32.1387 83.8961L31.4618 83.3127L31.1356 83.1319L29.7638 82.872L29.4841 82.548L29.6238 81.933L28.3697 81.1126L28.0654 81.0365L28.0658 81.0316L28.0968 80.4764L29.3731 77.9768L32.0809 77.4118L33.3704 76.4351L35.4478 75.4603L35.6789 74.4866L35.6966 72.7702L35.3327 68.4626L35.5279 67.7744L35.9895 67.684L36.4622 67.4614L36.5044 66.8569L36.2647 66.2644L36.549 65.5028L37.1772 65.3532L40.2976 65.3818L40.0556 64.1694L39.3651 63.433L38.6728 62.897L38.1024 62.1233L37.6853 60.8385L38.1979 59.4603L38.5796 57.3381L39.1545 56.1283L40.8325 55.0457L40.9876 53.8438L40.6992 53.2148L40.566 52.4426L40.7257 51.9175L40.9941 51.5962L41.7355 48.9806L42.8121 48.4544L45.8461 48.3531L46.5475 48.0239L47.2288 47.5538L47.9835 47.7026L48.6426 48.3723L51.45 49.8896L52.8415 50.1796L54.555 50.169L55.2941 49.5246L56.7392 49.7927L58.0333 50.9826L60.0374 54.1775L60.7633 54.3967L62.914 54.2792L65.2488 55.4676L67.0865 55.8251L67.3549 55.9723L67.4349 56.3505L67.4394 56.7671L67.3371 57.0349L65.8656 57.2764L65.0578 58.8071L65.6482 59.51L67.2662 59.9748L68.0076 60.539L68.6067 61.8728L69.6255 63.1185L68.7645 63.2458L67.2839 64.4937L66.8532 65.4289L67.6055 65.8207L69.0661 66.0399L69.6674 66.2749L69.8117 67.0049L69.8671 67.6076L67.1525 69.309L66.4734 69.4175L65.2684 69.3195L64.0922 69.5037L62.1899 70.9829L61.6441 71.1068L61.0937 71.1094L59.9042 70.4231L59.327 71.2846L58.7301 72.4847L57.7981 73.8154L56.3643 73.6094L55.6875 74.136L56.8283 75.2742L57.8294 76.6623L52.7358 82.3767L52.2655 83.0716L51.7883 84.051L51.544 85.1648L51.977 85.7305L52.5474 85.7889L53.0069 86.3697L53.0533 87.4794L53.6947 88.6305L54.789 89.0587L55.2239 89.8573L55.5501 90.8765L56.2469 91.5285L57.0503 91.8924L58.5017 92.1493L58.4285 93.0205L58.0623 93.7614L57.8804 94.4522L58.1533 95.0489L58.6595 95.3905L58.7717 95.777Z" stroke="#E6E6E7" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/> +<path d="M4.9801 68.4385L5.07108 68.0381L6.62034 64.1769L7.74566 63.3132L9.04615 63.1004L9.81851 61.773L10.3134 59.875L11.8559 56.9359L13.6449 54.2852L14.4127 52.5036L15.4335 51.1811L16.1148 50.7261L16.461 49.6933L16.5988 48.8093L16.8253 47.9768L18.0748 45.1029L18.632 44.4994L19.3311 44.2674L20.068 44.3194L20.8159 44.1341L21.5282 43.6998L22.2719 43.6576L22.9797 44.023L23.2658 44.7571L23.3878 45.5903L24.5153 46.5026L25.8827 46.5783L28.4263 45.6441L30.8811 44.1793L31.3628 45.0456L31.9955 45.5526L36.7984 46.79L38.3167 46.7485L38.5965 46.5026L38.7939 46.15L39.0491 46.0054L39.6263 46.7112L40.1257 47.6827L41.7369 48.9833L40.9955 51.5989L40.7271 51.9202L40.5674 52.4452L40.7007 53.2174L40.9891 53.8464L40.8339 55.0484L39.1559 56.1309L38.581 57.3408L38.1993 59.4629L37.6867 60.8411L38.1038 62.1259L38.6742 62.8996L39.3666 63.4356L40.057 64.172L40.299 65.3845L37.1786 65.3558L36.5504 65.5054L36.2662 66.267L36.5059 66.8595L36.4636 67.4641L35.991 67.6867L35.5293 67.7771L35.3341 68.4652L35.698 72.7728L35.6803 74.4893L35.4493 75.4629L33.3719 76.4378L32.0823 77.4145L29.3745 77.9795L28.0982 80.479L28.0672 81.0342L28.0669 81.0391L27.7098 80.9499L27.8053 81.7051L27.9185 81.7533L28.0895 81.6998L28.2737 81.7051L28.4247 81.936L28.4625 82.2686L28.3538 82.4151L27.6546 82.6234L26.7936 82.6494L26.4028 82.7511L25.7702 83.3161L24.9887 83.5538L24.2077 83.3884L22.8162 82.0034L22.5742 81.6689L22.4055 81.2708L22.2855 80.8587L22.139 80.4896L21.9015 80.2048L21.6996 80.0029L21.6331 79.8112L21.7018 79.6281L21.9015 79.4571L21.9102 79.433L21.9147 79.407L21.9102 79.3761L21.9015 79.3434L21.5995 79.2793L21.0159 78.9893L20.7339 78.9132L20.5052 78.9667L20.3232 79.0722L20.1058 79.1117L19.7705 78.9599L18.7275 77.6386L18.683 77.3949L18.8408 77.0578L19.076 76.9383L20.1126 76.8984L20.6852 76.6736L21.5995 76.1255L22.0344 75.7485L22.2364 75.2415L21.9012 74.6219L21.6747 74.3966L21.626 74.0591L21.6682 73.7525L21.9012 73.1254L21.9499 73.0195L21.9653 72.9189L21.9544 72.8289L21.9012 72.7528L21.5059 72.2187L21.3859 72.1061L21.022 71.9709L20.8823 72.0609L20.8268 72.2899L20.7068 72.5637L20.0699 73.4459L19.7015 73.7472L19.2043 73.8772L17.2843 73.5378L16.2613 73.6312L15.6309 74.3966L15.5199 74.4712L15.4067 74.4953L15.2911 74.4693L15.1824 74.3966L14.9827 73.7732L14.5142 73.3939L14.0393 73.4305L13.8064 74.0437L13.5199 73.8271L13.3712 73.4824L13.3289 73.0579L13.3557 72.6214L13.2579 72.5366L13.1692 72.4394L13.0937 72.3268L13.0337 72.2003L13.4289 72.0409L12.985 71.8518L11.9774 71.8812L11.4671 71.7339L10.7102 71.2552L10.4992 71.0262L10.3704 70.7346L10.2372 70.3007L10.1639 69.9361L10.2104 69.8423L9.95971 69.7659L9.30474 69.9015L9.00954 69.8981L8.73434 69.7523L8.23491 69.3319L7.99972 69.1877L5.79361 68.5692L5.29645 68.6283L4.9801 68.4385Z" stroke="#E6E6E7" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/> +<path d="M103.312 -36.6741L103.598 -35.4243L104.091 -34.26L104.435 -32.8472L104.974 -28.7287L106.168 -25.7225L106.958 -24.1966L108.099 -23.5744L109.28 -23.4038L110.265 -22.641L109.917 -21.9984L110.006 -21.0925L110.554 -20.1121L111.372 -19.6623L111.898 -19.1199L112.211 -18.237L112.506 -16.9334L113.075 -15.8949L114.606 -15.099L116.235 -15.3408L117.307 -16.4998L118.346 -15.713L118.006 -13.7558L118.546 -12.9976L119.216 -12.5298L120.426 -13.1366L121.671 -13.4873L122.006 -11.8228L122.139 -9.97898L122.399 -8.73146L122.468 -7.412L122.401 -6.64624L123.602 -5.36595L124.048 -4.74671L124.523 -4.34254L124.672 -4.13312L124.725 -3.78734L124.652 -3.49806L124.559 -3.2197L124.539 -2.90857L124.616 -2.4577L124.718 -2.16127L124.898 -1.99779L125.2 -1.94883L125.255 -1.78159L125.127 -0.618058L125.278 -0.241391L125.639 0.273135L126.074 0.607994L126.445 0.450169L126.696 0.862987L127.219 0.991064L128.351 0.92929L131.694 1.62198L133.372 1.38995L134 1.59109L134.495 2.07172L134.697 2.86724L135.154 2.62616L135.545 2.85556L136.148 3.58667L136.042 3.77689L135.933 4.14262L135.868 4.30384L136.226 4.52457L136.574 4.41609L136.898 4.19235L136.21 5.48544L134.17 8.4969L133.556 9.93162L132.845 10.8413L132.009 11.155L129.492 9.86043L128.613 9.65665L128.222 9.91806L127.867 10.2951L127.729 10.7388L127.627 11.2597L126.433 12.2308L124.073 12.0067L123.248 12.1031L121.197 13.6388L120.445 13.8817L119.355 13.6768L116.414 14.2625L113.305 14.2437L111.671 14.7138L110.146 15.8491L110.282 16.7267L110.628 17.7023L111.052 18.61L111.138 19.5298L111.66 20.818L112.413 21.9676L111.229 22.6833L110.402 23.8476L111.485 25.5121L111.34 26.3004L110.805 26.8074L109.283 27.3445L107.718 27.1001L106.95 26.7859L106.174 26.9927L105.952 27.8756L105.981 28.2305L106.254 28.6904L106.571 29.0682L107.168 29.3443L108.274 29.5786L108.651 29.5386L109.179 29.3055L109.383 29.3251L109.716 29.5514L109.794 29.8562L109.776 30.2479L109.823 30.7364L110.209 31.3368L110.282 31.7621L109.956 32.1463V32.3828L110.617 32.4495L110.595 33.8579L110.076 34.5788L109.572 34.9852L109.527 35.8211L110.386 36.8478L110.255 37.8332L109.993 38.8694L110.033 39.5881L109.798 39.6235L109.596 39.7953L109.334 40.3422L108.943 42.4722L108.764 42.9702L108.684 43.267L108.65 43.6591L108.697 43.9273L108.896 44.5398L109.065 45.6351L109.591 46.9482L102.722 48.3761L99.166 47.2634L97.5148 47.1207L96.0456 46.1666L95.9078 45.6475L95.8168 45.0799L95.1732 44.3556L94.9935 43.2075L94.3453 42.9849L93.6708 43.6222L93.0403 44.501L92.3303 44.9059L89.3473 45.3831L86.7482 44.8445L86.1955 44.4256L85.7406 43.702L85.2412 43.1318L81.7055 40.961L81.0687 39.3485L79.8833 38.9218L79.8101 37.9123L80.083 36.9793L81.459 35.6918L81.8184 34.7475L81.8207 33.6439L81.5432 33.3294L80.7508 32.949L80.5889 32.3926L80.5088 31.2954L80.2982 30.2347L79.6591 28.7028L80.2163 26.7626L81.8897 26.7607L83.177 27.4564L84.7372 27.6722L85.0147 27.105L85.0702 26.2823L84.7418 25.4021L83.5855 24.1979L83.3858 23.2091L83.499 22.7699L83.7142 22.4524L83.9052 22.055L83.7674 21.4859L82.5024 19.7946L80.9464 18.5889L79.5194 17.9305L77.2423 18.1915L76.47 17.9422L76.2835 17.3806L76.3367 16.7252L75.8263 15.959L75.2469 15.2969L75.0694 14.5578L75.7863 14.1386L76.0106 12.3946L75.7131 12.0199L74.8743 11.4579L73.3983 10.8631L73.0653 10.9441L72.7569 10.7791L72.322 9.80695L72.2465 8.58089L71.9758 7.68894L71.3832 7.27687L70.624 7.05087L69.9494 6.70208L69.4322 5.80184L68.8486 5.05755L68.0495 5.12912L67.3658 5.82935L62.9045 6.7533L60.9181 5.15021L59.815 4.63192L57.5557 4.15392L55.4847 2.72862L55.6267 2.12859L55.7131 1.53949L57.3001 -1.07948L57.2137 -1.73073L56.772 -2.18236L56.8853 -3.53459L57.4557 -4.69962L58.9007 -8.9051L59.8218 -9.15257L59.8041 -10.3225L59.185 -11.8164L58.8256 -12.4842L58.5882 -13.2247L58.7701 -13.9408L59.1986 -14.4161L59.3073 -15.725L58.9744 -17.1816L60.0242 -17.0449L60.9208 -17.8005L61.3224 -18.4065L61.7773 -18.8438L62.1925 -18.6709L62.5897 -18.3881L62.9981 -18.3402L63.2046 -18.9467L63.3179 -19.6397L63.3802 -20.3422L63.2069 -21.3912L63.1891 -22.0945L63.0604 -22.7668L64.1612 -23.2847L65.191 -24.1179L65.9324 -24.3059L66.5515 -24.8223L67.1065 -25.9222L67.9589 -26.1881L68.3273 -26.1086L68.6625 -25.8777L68.8022 -25.5621L68.9909 -25.3368L75.7716 -24.2908L77.3873 -24.5876L78.0355 -24.9142L78.5927 -25.5666L78.9566 -26.7723L79.6202 -27.2906L80.4458 -27.2036L81.2314 -27.4382L84.2344 -29.1743L84.9467 -30.0225L85.7236 -30.6538L87.2619 -30.6354L88.6247 -30.9198L90.1981 -31.8256L92.2514 -31.8174L94.1823 -32.4347L95.8116 -34.3742L97.7202 -34.1941L98.6945 -34.3444L99.5711 -34.9655L100.186 -36.1814L100.714 -36.4677L103.312 -36.6741Z" stroke="#E6E6E7" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/> +<path d="M55.487 2.72486L57.5579 4.15016L59.8173 4.62814L60.9203 5.14644L62.9067 6.74954L67.368 5.82557L68.0517 5.12535L68.8508 5.05378L69.4345 5.79808L69.9516 6.6983L70.6262 7.0471L71.3854 7.2731L71.9781 7.68517L72.2487 8.57712L72.3242 9.80317L72.7591 10.7753L73.0675 10.9403L73.4005 10.8593L74.8765 11.4541L75.7153 12.0161L76.0128 12.3909L75.7885 14.1348L75.0717 14.5541L75.2491 15.2931L75.8286 15.9553L76.3389 16.7214L76.2857 17.3768L76.4722 17.9384L77.2446 18.1878L79.5216 17.9267L80.9486 18.5852L82.5046 19.7909L83.7696 21.4821L83.9074 22.0512L83.7164 22.4486L83.5012 22.7662L83.388 23.2053L83.5877 24.1941L84.744 25.3983L85.0724 26.2786L85.0169 27.1012L84.7394 27.6685L83.1792 27.4526L81.892 26.7569L80.2185 26.7588L79.6613 28.699L80.3004 30.2309L80.5111 31.2916L80.5911 32.3889L80.753 32.9452L81.5454 33.3256L81.8229 33.6401L81.8206 34.7438L81.4612 35.6881L80.0852 36.9755L79.8123 37.9085L79.8855 38.918L79.2706 39.3764L78.4805 41.3256L77.7682 41.6526L77.0535 41.7648L76.3722 42.0971L74.8806 43.5145L74.1906 43.7115L71.8157 43.3804L71.1453 43.6256L70.6194 44.3175L70.0868 46.3771L71.0679 47.8638L71.7316 48.3953L71.9403 49.5343L71.7693 50.6463L71.2831 51.2218L68.4465 49.1449L67.6851 49.282L67.4099 50.3792L67.3944 51.4659L67.4809 52.5379L67.1147 53.5564L66.371 54.057L65.7497 54.6329L65.2503 55.471L62.9154 54.2826L60.7648 54.4001L60.0389 54.1809L58.0347 50.986L56.7407 49.7961L55.2956 49.5279L54.5564 50.1724L52.843 50.183L51.4515 49.8929L48.644 48.3757L47.9849 47.706L47.2303 47.5572L46.5489 48.0273L45.8475 48.3565L42.8135 48.4578L41.7369 48.984L40.1257 47.6834L39.6263 46.712L39.0491 46.0061L38.7939 46.1507L38.5965 46.5033L38.3168 46.7493L36.7984 46.7907L31.9955 45.5534L31.3628 45.0464L30.8811 44.18L30.7456 42.5849L30.5259 41.6466L29.2964 40.546L28.8947 39.5986L28.8347 38.4905L29.1809 37.7277L30.7524 37.3812L31.2919 36.5265L31.6494 35.4481L32.7215 35.125L33.8913 35.7016L34.9121 34.9705L35.5112 33.335L35.4757 31.5037L35.2624 29.6177L35.3689 27.3299L35.9215 25.2247L36.9204 22.84L37.4753 22.0814L38.7048 21.5006L41.8143 21.8388L42.0585 21.5721L43.0906 19.7521L43.1771 18.6594L42.7732 17.5414L42.5312 16.3195L42.6844 15.1315L42.9796 14.0614L43.6588 14.0019L44.4002 14.0874L45.8384 13.7484L46.926 12.467L47.1235 10.2845L47.3477 9.30673L49.4896 8.3918L50.8192 7.11491L50.7614 6.77515L50.4439 6.68287L50.031 5.80523L49.9955 4.679L50.1997 4.4093L50.3552 4.08161L50.7305 3.87519L53.3805 3.82096L54.1929 3.57649L54.3903 3.17986L54.6565 2.78324L55.0649 2.70715L55.487 2.72486Z" stroke="#E6E6E7" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/> +<path d="M49.9959 4.679L50.0314 5.80523L50.4444 6.68287L50.7618 6.77515L50.8196 7.11491L49.49 8.3918L47.3481 9.30673L47.1239 10.2845L46.9264 12.467L45.8389 13.7484L44.4006 14.0874L43.6592 14.0019L42.98 14.0614L42.6848 15.1315L42.5316 16.3195L42.7736 17.5414L43.1775 18.6594L43.091 19.7521L42.0589 21.5721L41.8147 21.8388L38.7052 21.5006L37.4757 22.0814L36.9208 22.84L35.9219 25.2247L35.3693 27.3299L35.2628 29.6177L35.4761 31.5037L35.5116 33.335L34.9125 34.9705L33.8917 35.7016L32.7219 35.125L31.6498 35.4481L31.2923 36.5265L30.7528 37.3812L29.1813 37.7277L28.8351 38.4905L28.8952 39.5986L29.2968 40.546L30.5263 41.6466L30.746 42.5849L30.8816 44.18L28.4267 45.6449L25.8831 46.579L24.5158 46.5033L23.3882 45.591L23.2662 44.7578L22.9801 44.0237L22.2723 43.6584L21.5286 43.7005L21.2489 41.998L21.0046 38.4863L21.6105 37.0422L20.8359 36.4199L20.019 36.1928L18.703 36.458L17.4335 36.1619L16.9341 34.9031L16.8163 33.4156L17.1024 32.6827L17.6241 32.3388L17.9216 31.4894L18.1349 30.498L16.002 29.116L13.6294 28.4655L11.1058 28.455L10.207 28.6403L9.39463 30.4863L4.95788 31.2687L2.48336 30.3858L1.30934 29.09L-0.77258 27.9306L-1.70274 26.2869L-1.7737 25.1629L-2.15309 24.2909L-4.57438 22.9748L-5.44678 22.7424L-7.3222 23.1037L-7.99264 20.5242L-9.39316 18.9784L-10.9647 20.0459L-11.939 19.725L-12.8624 19.0922L-13.1799 18.1648L-13.0821 16.9677L-12.8869 16.2988L-12.9201 15.6023L-13.2754 15.3793L-13.6461 15.5394L-14.4471 15.5251L-15.2085 14.762L-15.7035 13.8565L-16.0874 12.7702L-17.2705 12.14L-17.8586 11.5302L-18.3626 10.784L-18.5313 9.68376L-18.5181 8.50631L-18.2716 7.47688L-18.2229 6.94653L-18.1119 6.44143L-17.415 4.37842L-17.4619 2.22276L-17.8903 1.18014L-18.8024 -0.436887L-18.3429 -0.756677L-17.7657 -0.754792L-17.7635 -1.81021L-17.9322 -3.09577L-18.1942 -4.32597L-18.9533 -6.40818L-19.0356 -8.37815L-18.9424 -9.12772L-18.9201 -9.92135L-18.7714 -10.2521L-18.4452 -10.2136L-16.4124 -10.857L-15.9975 -11.1259L-15.791 -11.6819L-16.2527 -13.4259L-16.9118 -14.0394L-14.8235 -16.7236L-14.8945 -18.9926L-14.466 -21.0421L-13.2788 -20.6466L-11.9647 -19.8631L-10.6242 -20.0443L-9.30596 -20.5603L-7.23537 -22.5209L-5.49737 -25.2494L-2.3879 -27.0642L-0.805413 -27.5576L-0.18405 -28.1471L0.322179 -29.0451L0.981295 -29.8621L0.845769 -30.8904L0.175329 -31.7492L-0.621571 -32.168L-2.24181 -32.5816L-3.5891 -33.8913L-3.92206 -35.1712L-3.94433 -36.6037L-3.46037 -37.2918L0.492427 -37.1867L1.1406 -37.3122L1.68873 -39.6098L2.1036 -40.7967L2.66947 -41.7813L3.43504 -42.1199L4.25383 -42.1425L5.05716 -41.8879L6.08924 -40.6144L6.97938 -39.046L8.2357 -38.2791L12.6079 -38.1005L13.7555 -37.47L14.7098 -36.3264L14.1149 -35.0036L12.5679 -32.9677L12.8144 -31.8942L14.6389 -30.4689L15.6732 -28.137L13.7113 -26.4796L13.8978 -24.9681L14.5637 -23.6893L14.2595 -21.4696L13.2942 -19.2457L15.0409 -18.6156L16.6702 -17.3952L17.7223 -15.0783L17.2629 -12.5708L17.0077 -12.0861L16.6615 -11.9618L16.2776 -11.9855L15.9159 -11.7094L15.7717 -10.7952L16.5441 -10.0532L16.8816 -9.22226L17.31 -8.53409L18.1825 -8.36798L19.0435 -8.65462L19.4206 -8.99965L20.0911 -8.43465L20.2776 -7.96118L20.3708 -7.37395L20.5396 -7.16227L20.7815 -7.02177L22.1511 -6.55885L23.6449 -6.47674L25.2628 -5.60023L27.4603 -3.58469L28.2258 -3.18919L29.0205 -3.13382L29.7464 -2.83926L30.3678 -2.06371L31.0624 -1.40868L33.2375 -0.832762L33.9721 -1.16498L35.2217 -2.63361L35.6347 -2.52098L35.9431 -2.30628L36.1096 -1.66105L36.3738 -1.09342L36.78 -0.486603L37.2994 -0.323133L37.6233 -0.514478L37.8298 -0.905088L38.2247 -1.07383L38.6377 -1.11564L39.3836 -0.769482L40.0272 -0.0078613L43.5806 2.9049L44.1688 4.23077L44.9412 4.17013L47.1918 3.22017L47.9532 3.11319L49.9959 4.679Z" stroke="#E6E6E7" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/> +<path d="M79.8856 38.9184L81.071 39.3452L81.7078 40.9577L85.2435 43.1284L85.7429 43.6987L86.1978 44.4222L86.7504 44.8411L89.3495 45.3797L92.3325 44.9025L93.0426 44.4976L93.673 43.6188L94.3476 42.9815L94.9958 43.2041L95.1755 44.3522L95.8191 45.0765L95.9101 45.6442L96.0479 46.1632L97.5171 47.1173L99.1683 47.2601L102.724 48.3727L109.593 46.9448L109.678 47.4043L109.587 47.6051L109.42 47.7493L109.231 47.839L109.078 47.8699V48.103L109.475 48.3968L109.542 49.062L109.384 50.5322L109.36 50.6403L109.304 50.7043L109.249 50.8037L109.224 51.0173L109.271 51.2113L109.371 51.3002L109.471 51.3635L109.517 51.4821L109.557 51.7993L110.103 53.8773L110.212 54.6069L110.281 55.0661L110.305 56.3204L110.13 57.6523L109.977 58.1894L109.724 58.7962L109.396 59.2946L109.012 59.4998L108.448 59.5917L108.08 59.8592L107.465 60.8845L106.444 62.0958L106.293 62.6243L106.182 63.2748L105.911 63.7995L105.252 64.5924L104.857 64.9276L103.481 65.2839L101.428 66.203L101.51 66.3578L101.721 66.8938L101.313 67.3217L100.765 67.6434L100.219 67.7624L99.815 67.5824L98.4967 68.7304L98.4235 68.7564L98.1151 68.7304L98.0309 68.7956L98.0419 68.9451L98.0683 69.1086L98.0419 69.2111L97.8021 69.3881L97.6557 69.3794L97.456 69.2111L97.3405 69.6879L97.0853 69.9181L96.8365 70.045L96.7232 70.222L96.6964 70.5042L96.6187 70.5693L96.5032 70.578L96.3499 70.6917L95.9747 71.2202V71.2756L95.5953 71.3569L95.3842 71.1731L95.1932 70.9234L94.8758 70.7957L94.6628 70.8477L93.7772 71.2752L93.5753 71.4417L93.3756 71.6707L93.1359 71.8737L92.8097 71.9622L91.2163 72.0142L90.9943 72.0975L90.8146 72.2553L90.6036 72.5351L90.4039 72.6496L89.818 72.7069L89.5251 72.9001L89.1921 72.6817L88.9079 72.8655L88.6172 73.1721L88.2642 73.3367L87.4409 72.5536L87.3012 72.7615L87.1657 73.3367L86.7131 73.794L86.6398 73.8354L86.4488 73.8459L86.3601 73.9085L86.2869 74.0731L86.2605 74.429L86.1982 74.6057L85.8984 74.8972L85.2038 75.2313L84.9396 75.6449L84.8554 75.9993L84.2118 76.686L81.3907 76.6092L79.8128 75.6622L79.4066 74.8038L78.4322 73.4324L78.0615 72.6508L77.6999 71.1072L76.7188 69.1662L75.0653 68.063L73.2631 67.4946L72.5395 66.7345L71.6961 66.2821L69.6697 66.2787L69.0683 66.0437L67.6078 65.8245L66.8554 65.4327L67.2862 64.4975L68.7667 63.2496L69.6278 63.1222L68.6089 61.8766L68.0098 60.5428L67.2684 59.9786L65.6505 59.5138L65.0601 58.8109L65.8679 57.2801L67.3394 57.0387L67.4417 56.7709L67.4372 56.3543L67.3571 55.9761L67.0887 55.8288L65.2503 55.471L65.7497 54.6341L66.3711 54.0581L67.1148 53.5575L67.481 52.539L67.3945 51.467L67.41 50.3804L67.6852 49.2831L68.4466 49.146L71.2831 51.223L71.7694 50.6474L71.9404 49.5355L71.7316 48.3965L71.068 47.865L70.0868 46.3783L70.6195 44.3187L71.1454 43.6267L71.8158 43.3815L74.1906 43.7126L74.8807 43.5156L76.3722 42.0982L77.0536 41.766L77.7682 41.6537L78.4806 41.3268L79.2707 39.3776L79.8856 38.9184Z" stroke="#E6E6E7" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/> +</g> +<g clip-path="url(#clip1_1314_36343)"> +<path d="M60 29C56.1 29 53 32.1 53 36C53 37.9 53.7 39.7 55.1 41C55.2 41.1 59.2 44.7 59.3 44.8C59.7 45.1 60.3 45.1 60.6 44.8C60.7 44.7 64.8 41.1 64.8 41C66.2 39.7 66.9 37.9 66.9 36C67 32.1 63.9 29 60 29ZM60 38C58.9 38 58 37.1 58 36C58 34.9 58.9 34 60 34C61.1 34 62 34.9 62 36C62 37.1 61.1 38 60 38Z" fill="#FF5A44"/> +</g> +</g> +<rect x="25.25" y="20.25" width="69.5" height="37.5" rx="4.75" stroke="#E6E6E7" stroke-width="1.5"/> +</g> +<defs> +<filter id="filter0_d_1314_36343" x="0" y="0" width="120" height="80" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB"> +<feFlood flood-opacity="0" result="BackgroundImageFix"/> +<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/> +<feOffset dy="1"/> +<feGaussianBlur stdDeviation="1"/> +<feColorMatrix type="matrix" values="0 0 0 0 0.027451 0 0 0 0 0.0313726 0 0 0 0 0.0627451 0 0 0 0.1 0"/> +<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_1314_36343"/> +<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_1314_36343" result="shape"/> +</filter> +<clipPath id="clip0_1314_36343"> +<rect x="26" y="21" width="68" height="36" rx="4" fill="white"/> +</clipPath> +<clipPath id="clip1_1314_36343"> +<rect width="16" height="16" fill="white" transform="translate(52 29)"/> +</clipPath> +</defs> +</svg> diff --git a/web-frontend/modules/builder/assets/icons/element-menu.svg b/web-frontend/modules/builder/assets/icons/element-menu.svg new file mode 100644 index 000000000..9c21166ad --- /dev/null +++ b/web-frontend/modules/builder/assets/icons/element-menu.svg @@ -0,0 +1,22 @@ +<svg width="120" height="80" viewBox="0 0 120 80" fill="none" xmlns="http://www.w3.org/2000/svg"> +<g filter="url(#filter0_d_2153_91582)"> +<rect x="2" y="1" width="116" height="76" rx="6" fill="#FAFAFA"/> +<rect x="2.5" y="1.5" width="115" height="75" rx="5.5" stroke="#EDEDED"/> +<rect x="39" y="43" width="42" height="4" rx="2" fill="#E6E6E7"/> +<rect x="39" y="55" width="34" height="4" rx="2" fill="#E6E6E7"/> +<path d="M37 18.25C34.3766 18.25 32.25 20.3766 32.25 23V31C32.25 33.6234 34.3766 35.75 37 35.75H83C85.6234 35.75 87.75 33.6234 87.75 31V23C87.75 20.3766 85.6234 18.25 83 18.25H37Z" fill="white"/> +<path d="M37 18.25C34.3766 18.25 32.25 20.3766 32.25 23V31C32.25 33.6234 34.3766 35.75 37 35.75H83C85.6234 35.75 87.75 33.6234 87.75 31V23C87.75 20.3766 85.6234 18.25 83 18.25H37Z" stroke="#E6E6E7" stroke-width="1.5"/> +<rect x="39" y="25" width="42" height="4" rx="2" fill="#E6E6E7"/> +</g> +<defs> +<filter id="filter0_d_2153_91582" x="0" y="0" width="120" height="80" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB"> +<feFlood flood-opacity="0" result="BackgroundImageFix"/> +<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/> +<feOffset dy="1"/> +<feGaussianBlur stdDeviation="1"/> +<feColorMatrix type="matrix" values="0 0 0 0 0.027451 0 0 0 0 0.0313726 0 0 0 0 0.0627451 0 0 0 0.1 0"/> +<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_2153_91582"/> +<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_2153_91582" result="shape"/> +</filter> +</defs> +</svg> diff --git a/web-frontend/modules/builder/assets/icons/element-positioned_container.svg b/web-frontend/modules/builder/assets/icons/element-positioned_container.svg new file mode 100644 index 000000000..f3ac4d847 --- /dev/null +++ b/web-frontend/modules/builder/assets/icons/element-positioned_container.svg @@ -0,0 +1,22 @@ +<svg width="120" height="80" viewBox="0 0 120 80" fill="none" xmlns="http://www.w3.org/2000/svg"> +<g filter="url(#filter0_d_2154_91866)"> +<rect x="2" y="1" width="116" height="76" rx="6" fill="#FAFAFA"/> +<rect x="2.5" y="1.5" width="115" height="75" rx="5.5" stroke="#EDEDED"/> +<rect x="25.25" y="28.25" width="69.5" height="21.5" rx="4.75" fill="white"/> +<rect x="25.25" y="28.25" width="69.5" height="21.5" rx="4.75" stroke="#E6E6E7" stroke-width="1.5"/> +<rect opacity="0.48" x="66" y="37" width="20" height="4" rx="2" fill="#E6E6E7"/> +<rect x="48" y="37" width="14" height="4" rx="2" fill="#E6E6E7"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M39 37.5V35H39.5C39.775 35 40 34.775 40 34.5C40 34.225 39.775 34 39.5 34H34.5C34.225 34 34 34.225 34 34.5C34 34.775 34.225 35 34.5 35H35V37.5C35 38.33 34.33 39 33.5 39V40H36.485V43.5L36.985 44L37.485 43.5V40H40.5V39C39.67 39 39 38.33 39 37.5Z" fill="#D7D8D9"/> +</g> +<defs> +<filter id="filter0_d_2154_91866" x="0" y="0" width="120" height="80" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB"> +<feFlood flood-opacity="0" result="BackgroundImageFix"/> +<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/> +<feOffset dy="1"/> +<feGaussianBlur stdDeviation="1"/> +<feColorMatrix type="matrix" values="0 0 0 0 0.027451 0 0 0 0 0.0313726 0 0 0 0 0.0627451 0 0 0 0.1 0"/> +<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_2154_91866"/> +<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_2154_91866" result="shape"/> +</filter> +</defs> +</svg> diff --git a/web-frontend/modules/builder/assets/icons/element-rating.svg b/web-frontend/modules/builder/assets/icons/element-rating.svg new file mode 100644 index 000000000..cb382e43d --- /dev/null +++ b/web-frontend/modules/builder/assets/icons/element-rating.svg @@ -0,0 +1,25 @@ +<svg width="120" height="80" viewBox="0 0 120 80" fill="none" xmlns="http://www.w3.org/2000/svg"> +<g filter="url(#filter0_d_3351_92289)"> +<rect x="2" y="1" width="116" height="76" rx="6" fill="#FAFAFA"/> +<rect x="2.5" y="1.5" width="115" height="75" rx="5.5" stroke="#EDEDED"/> +<rect x="30.25" y="28.25" width="60.5" height="21.5" rx="4.75" fill="white"/> +<rect x="30.25" y="28.25" width="60.5" height="21.5" rx="4.75" stroke="#E6E6E7" stroke-width="1.5"/> +<path d="M39.2937 36.8109L40.5924 34.1948C40.7592 33.8589 41.2408 33.8589 41.4076 34.1948L42.7063 36.8109L45.6107 37.233C45.9834 37.2871 46.1319 37.7426 45.8621 38.0038L43.7609 40.0388L44.2568 42.9136C44.3205 43.2828 43.9307 43.5643 43.5973 43.3899L41 42.0319L38.4027 43.3899C38.0693 43.5643 37.6795 43.2828 37.7432 42.9136L38.2391 40.0388L36.1379 38.0038C35.8681 37.7426 36.0166 37.2871 36.3893 37.233L39.2937 36.8109Z" fill="#FFC744"/> +<path d="M52.2937 36.8109L53.5924 34.1948C53.7592 33.8589 54.2408 33.8589 54.4076 34.1948L55.7063 36.8109L58.6107 37.233C58.9834 37.2871 59.1319 37.7426 58.8621 38.0038L56.7609 40.0388L57.2568 42.9136C57.3205 43.2828 56.9307 43.5643 56.5973 43.3899L54 42.0319L51.4027 43.3899C51.0693 43.5643 50.6795 43.2828 50.7432 42.9136L51.2391 40.0388L49.1379 38.0038C48.8681 37.7426 49.0166 37.2871 49.3893 37.233L52.2937 36.8109Z" fill="#FFC744"/> +<path d="M65.2937 36.8109L66.5924 34.1948C66.7592 33.8589 67.2408 33.8589 67.4076 34.1948L68.7063 36.8109L71.6107 37.233C71.9834 37.2871 72.1319 37.7426 71.8621 38.0038L69.7609 40.0388L70.2568 42.9136C70.3205 43.2828 69.9307 43.5643 69.5973 43.3899L67 42.0319L64.4027 43.3899C64.0693 43.5643 63.6795 43.2828 63.7432 42.9136L64.2391 40.0388L62.1379 38.0038C61.8681 37.7426 62.0166 37.2871 62.3893 37.233L65.2937 36.8109Z" fill="#FFC744"/> +<g opacity="0.48"> +<path d="M78.2937 36.8109L79.5924 34.1948C79.7592 33.8589 80.2408 33.8589 80.4076 34.1948L81.7063 36.8109L84.6107 37.233C84.9834 37.2871 85.1319 37.7426 84.8621 38.0038L82.7609 40.0388L83.2568 42.9136C83.3205 43.2828 82.9307 43.5643 82.5973 43.3899L80 42.0319L77.4027 43.3899C77.0693 43.5643 76.6795 43.2828 76.7432 42.9136L77.2391 40.0388L75.1379 38.0038C74.8681 37.7426 75.0166 37.2871 75.3893 37.233L78.2937 36.8109Z" fill="#D7D8D9"/> +</g> +</g> +<defs> +<filter id="filter0_d_3351_92289" x="0" y="0" width="120" height="80" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB"> +<feFlood flood-opacity="0" result="BackgroundImageFix"/> +<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/> +<feOffset dy="1"/> +<feGaussianBlur stdDeviation="1"/> +<feColorMatrix type="matrix" values="0 0 0 0 0.027451 0 0 0 0 0.0313726 0 0 0 0 0.0627451 0 0 0 0.1 0"/> +<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_3351_92289"/> +<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_3351_92289" result="shape"/> +</filter> +</defs> +</svg> diff --git a/web-frontend/modules/builder/assets/icons/element-rating_input.svg b/web-frontend/modules/builder/assets/icons/element-rating_input.svg new file mode 100644 index 000000000..618278b6d --- /dev/null +++ b/web-frontend/modules/builder/assets/icons/element-rating_input.svg @@ -0,0 +1,21 @@ +<svg width="120" height="80" viewBox="0 0 120 80" fill="none" xmlns="http://www.w3.org/2000/svg"> +<g filter="url(#filter0_d_3351_92303)"> +<rect x="2" y="1" width="116" height="76" rx="6" fill="#FAFAFA"/> +<rect x="2.5" y="1.5" width="115" height="75" rx="5.5" stroke="#EDEDED"/> +<rect x="25.25" y="28.25" width="69.5" height="21.5" rx="4.75" fill="white"/> +<rect x="25.25" y="28.25" width="69.5" height="21.5" rx="4.75" stroke="#E6E6E7" stroke-width="1.5"/> +<path opacity="0.48" d="M48 39C48 37.8954 48.8954 37 50 37H84C85.1046 37 86 37.8954 86 39C86 40.1046 85.1046 41 84 41H50C48.8954 41 48 40.1046 48 39Z" fill="#E6E6E7"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M34.847 43.4976H39.3914C40.2815 43.4976 41.0644 42.9095 41.3123 42.0547L41.9923 39.7099C42.3634 38.4305 41.4036 37.1528 40.0715 37.1528H38.6482C38.2419 37.1528 37.9531 36.7575 38.0766 36.3704L38.5796 34.7935C38.6838 34.4672 38.6121 34.1102 38.3901 33.8493C37.9578 33.3411 37.1571 33.396 36.7983 33.9585L35.3499 36.2286C35.2148 36.4402 35.0435 36.6211 34.847 36.7653V43.4976ZM33.447 43.4976L33.447 37.1528H32.6C32.2686 37.1528 32 37.4214 32 37.7528V42.8976C32 43.229 32.2686 43.4976 32.6 43.4976H33.447Z" fill="#D7D8D9"/> +</g> +<defs> +<filter id="filter0_d_3351_92303" x="0" y="0" width="120" height="80" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB"> +<feFlood flood-opacity="0" result="BackgroundImageFix"/> +<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/> +<feOffset dy="1"/> +<feGaussianBlur stdDeviation="1"/> +<feColorMatrix type="matrix" values="0 0 0 0 0.027451 0 0 0 0 0.0313726 0 0 0 0 0.0627451 0 0 0 0.1 0"/> +<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_3351_92303"/> +<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_3351_92303" result="shape"/> +</filter> +</defs> +</svg> diff --git a/web-frontend/modules/builder/assets/icons/element-record_selector.svg b/web-frontend/modules/builder/assets/icons/element-record_selector.svg new file mode 100644 index 000000000..7795db7f9 --- /dev/null +++ b/web-frontend/modules/builder/assets/icons/element-record_selector.svg @@ -0,0 +1,24 @@ +<svg width="120" height="80" viewBox="0 0 120 80" fill="none" xmlns="http://www.w3.org/2000/svg"> +<g filter="url(#filter0_d_2153_91635)"> +<rect x="2" y="1" width="116" height="76" rx="6" fill="#FAFAFA"/> +<rect x="2.5" y="1.5" width="115" height="75" rx="5.5" stroke="#EDEDED"/> +<rect x="25.25" y="28.25" width="69.5" height="21.5" rx="4.75" fill="white"/> +<rect x="25.25" y="28.25" width="69.5" height="21.5" rx="4.75" stroke="#E6E6E7" stroke-width="1.5"/> +<rect x="48" y="37" width="24" height="4" rx="2" fill="#E6E6E7"/> +<path d="M85.5 37.75L83 40.25L80.5 37.75" stroke="#D7D8D9" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/> +<path d="M33.5 39V42C33.5 42 33.5 43.5 37 43.5C40.5 43.5 40.5 42 40.5 42V39" stroke="#D7D8D9" stroke-width="1.5"/> +<path d="M33.5 36V39C33.5 39 33.5 40.5 37 40.5C40.5 40.5 40.5 39 40.5 39V36" stroke="#D7D8D9" stroke-width="1.5"/> +<path d="M37 34.5C40.5 34.5 40.5 36 40.5 36C40.5 36 40.5 37.5 37 37.5C33.5 37.5 33.5 36 33.5 36C33.5 36 33.5 34.5 37 34.5Z" stroke="#D7D8D9" stroke-width="1.5"/> +</g> +<defs> +<filter id="filter0_d_2153_91635" x="0" y="0" width="120" height="80" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB"> +<feFlood flood-opacity="0" result="BackgroundImageFix"/> +<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/> +<feOffset dy="1"/> +<feGaussianBlur stdDeviation="1"/> +<feColorMatrix type="matrix" values="0 0 0 0 0.027451 0 0 0 0 0.0313726 0 0 0 0 0.0627451 0 0 0 0.1 0"/> +<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_2153_91635"/> +<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_2153_91635" result="shape"/> +</filter> +</defs> +</svg> diff --git a/web-frontend/modules/builder/assets/icons/element-repeat.svg b/web-frontend/modules/builder/assets/icons/element-repeat.svg new file mode 100644 index 000000000..5026ffc98 --- /dev/null +++ b/web-frontend/modules/builder/assets/icons/element-repeat.svg @@ -0,0 +1,29 @@ +<svg width="120" height="80" viewBox="0 0 120 80" fill="none" xmlns="http://www.w3.org/2000/svg"> +<g filter="url(#filter0_d_2154_91928)"> +<rect x="2" y="1" width="116" height="76" rx="6" fill="#FAFAFA"/> +<rect x="2.5" y="1.5" width="115" height="75" rx="5.5" stroke="#EDEDED"/> +<path d="M42 22.25C39.3766 22.25 37.25 24.3766 37.25 27V34C37.25 36.6234 39.3766 38.75 42 38.75H78C80.6234 38.75 82.75 36.6234 82.75 34V27C82.75 24.3766 80.6234 22.25 78 22.25H42Z" fill="#F7F7F7" stroke="#E6E6E7" stroke-width="1.5"/> +<path d="M36 27.25C33.3766 27.25 31.25 29.3766 31.25 32V39C31.25 41.6234 33.3766 43.75 36 43.75H84C86.6234 43.75 88.75 41.6234 88.75 39V32C88.75 29.3766 86.6234 27.25 84 27.25H36Z" fill="#FAFAFA" stroke="#E6E6E7" stroke-width="1.5"/> +<rect x="25.25" y="32.25" width="69.5" height="21.5" rx="4.75" fill="white"/> +<rect x="25.25" y="32.25" width="69.5" height="21.5" rx="4.75" stroke="#E6E6E7" stroke-width="1.5"/> +<rect opacity="0.48" x="66" y="41" width="20" height="4" rx="2" fill="#E6E6E7"/> +<rect x="48" y="41" width="14" height="4" rx="2" fill="#E6E6E7"/> +<g clip-path="url(#clip0_2154_91928)"> +<path d="M41.8783 38.03C41.8404 38.0142 41.7987 38.01 41.7583 38.0178C41.718 38.0257 41.6809 38.0453 41.6517 38.0742L40.3842 39.3283C39.4656 38.4721 38.2558 37.9973 37 38C36.1477 38 35.3096 38.2179 34.5652 38.6329C33.8208 39.0479 33.1948 39.6464 32.7467 40.3714C32.2987 41.0964 32.0434 41.9238 32.0051 42.7753C31.9667 43.6267 32.1467 44.4738 32.5279 45.2361C32.909 45.9984 33.4787 46.6506 34.1828 47.1308C34.8869 47.611 35.7021 47.9033 36.551 47.9798C37.3998 48.0563 38.2541 47.9146 39.0328 47.5681C39.8115 47.2216 40.4886 46.6818 41 46C41.1326 45.8232 41.1895 45.601 41.1583 45.3822C41.127 45.1634 41.0101 44.966 40.8333 44.8333C40.7458 44.7677 40.6462 44.7199 40.5402 44.6928C40.4341 44.6656 40.3238 44.6596 40.2155 44.6751C39.9967 44.7063 39.7993 44.8232 39.6667 45C39.3258 45.4546 38.8743 45.8144 38.3552 46.0454C37.8361 46.2764 37.2665 46.3709 36.7006 46.3199C36.1348 46.2689 35.5913 46.074 35.1219 45.7539C34.6525 45.4337 34.2727 44.9989 34.0186 44.4907C33.7645 43.9825 33.6445 43.4178 33.67 42.8502C33.6956 42.2826 33.8658 41.7309 34.1645 41.2476C34.4632 40.7642 34.8805 40.3653 35.3768 40.0886C35.8731 39.8119 36.4318 39.6667 37 39.6667C37.8097 39.6651 38.5917 39.9618 39.1967 40.5L37.7842 41.9008C37.7565 41.9285 37.7371 41.9634 37.7282 42.0016C37.7194 42.0398 37.7215 42.0796 37.7342 42.1167C37.747 42.1539 37.7702 42.1868 37.8011 42.2113C37.8319 42.2358 37.8691 42.251 37.9083 42.255L41.775 42.6833H41.7983C41.8258 42.6836 41.8529 42.6783 41.8783 42.6679C41.9037 42.6575 41.9268 42.6422 41.9461 42.6228C41.9655 42.6034 41.9809 42.5804 41.9913 42.555C42.0017 42.5296 42.0069 42.5024 42.0067 42.475V38.2225C42.0066 38.1814 41.9944 38.1411 41.9715 38.1069C41.9487 38.0727 41.9163 38.0459 41.8783 38.03Z" fill="#D7D8D9"/> +</g> +</g> +<defs> +<filter id="filter0_d_2154_91928" x="0" y="0" width="120" height="80" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB"> +<feFlood flood-opacity="0" result="BackgroundImageFix"/> +<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/> +<feOffset dy="1"/> +<feGaussianBlur stdDeviation="1"/> +<feColorMatrix type="matrix" values="0 0 0 0 0.027451 0 0 0 0 0.0313726 0 0 0 0 0.0627451 0 0 0 0.1 0"/> +<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_2154_91928"/> +<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_2154_91928" result="shape"/> +</filter> +<clipPath id="clip0_2154_91928"> +<rect width="10" height="10" fill="white" transform="translate(32 38)"/> +</clipPath> +</defs> +</svg> diff --git a/web-frontend/modules/builder/assets/icons/element-rich_text.svg b/web-frontend/modules/builder/assets/icons/element-rich_text.svg new file mode 100644 index 000000000..32a3d57bd --- /dev/null +++ b/web-frontend/modules/builder/assets/icons/element-rich_text.svg @@ -0,0 +1,25 @@ +<svg width="120" height="80" viewBox="0 0 120 80" fill="none" xmlns="http://www.w3.org/2000/svg"> +<g filter="url(#filter0_d_1314_36302)"> +<rect x="2" y="1" width="116" height="76" rx="6" fill="#F7F7F7"/> +<rect x="2.5" y="1.5" width="115" height="75" rx="5.5" stroke="#D7D8D9"/> +<rect x="25.25" y="26.25" width="69.5" height="25.5" rx="4.75" fill="white"/> +<rect x="25.25" y="26.25" width="69.5" height="25.5" rx="4.75" stroke="#E6E6E7" stroke-width="1.5"/> +<rect x="32" y="33" width="15" height="4" rx="2" fill="#E6E6E7"/> +<rect opacity="0.48" x="32" y="41" width="10" height="4" rx="2" fill="#E6E6E7"/> +<path d="M57.5 38.8194H55.3334M57.5 38.8194C57.5 38.8194 59.3056 38.8194 59.3056 37.0139C59.3056 35.2083 57.5001 35.2083 57.5 35.2083C57.5 35.2083 57.5 35.2083 57.5 35.2083H55.9334C55.602 35.2083 55.3334 35.477 55.3334 35.8083V38.8194M57.5 38.8194C57.5 38.8194 59.6667 38.8194 59.6667 40.8056C59.6667 42.7917 57.5 42.7917 57.5 42.7917C57.5 42.7917 57.5 42.7917 57.5 42.7917H55.9334C55.602 42.7917 55.3334 42.523 55.3334 42.1917V38.8194" stroke="#CDCECF" stroke-width="1.5"/> +<path d="M69.9583 35.2083L71.5833 35.2083M73.2083 35.2083L71.5833 35.2083M71.5833 35.2083L69.4166 42.7917M69.4166 42.7917L67.7916 42.7917M69.4166 42.7917L71.0416 42.7917" stroke="#CDCECF" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/> +<path d="M85.6667 35.2083V38.4583C85.6667 39.6549 84.6967 40.625 83.5 40.625V40.625C82.3034 40.625 81.3334 39.6549 81.3334 38.4583V35.2083" stroke="#CDCECF" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/> +<path d="M80.25 42.7917L86.75 42.7917" stroke="#CDCECF" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/> +</g> +<defs> +<filter id="filter0_d_1314_36302" x="0" y="0" width="120" height="80" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB"> +<feFlood flood-opacity="0" result="BackgroundImageFix"/> +<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/> +<feOffset dy="1"/> +<feGaussianBlur stdDeviation="1"/> +<feColorMatrix type="matrix" values="0 0 0 0 0.027451 0 0 0 0 0.0313726 0 0 0 0 0.0627451 0 0 0 0.1 0"/> +<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_1314_36302"/> +<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_1314_36302" result="shape"/> +</filter> +</defs> +</svg> diff --git a/web-frontend/modules/builder/assets/icons/element-separator.svg b/web-frontend/modules/builder/assets/icons/element-separator.svg new file mode 100644 index 000000000..fca6ce972 --- /dev/null +++ b/web-frontend/modules/builder/assets/icons/element-separator.svg @@ -0,0 +1,20 @@ +<svg width="120" height="80" viewBox="0 0 120 80" fill="none" xmlns="http://www.w3.org/2000/svg"> +<g filter="url(#filter0_d_2043_89914)"> +<rect x="2" y="1" width="116" height="76" rx="6" fill="#FAFAFA"/> +<rect x="2.5" y="1.5" width="115" height="75" rx="5.5" stroke="#EDEDED"/> +<rect x="26.75" y="17.75" width="66.5" height="12.5" rx="3.25" fill="#F5F5F5" stroke="#E6E6E7" stroke-width="1.5" stroke-dasharray="4 4"/> +<rect x="26.75" y="47.75" width="66.5" height="12.5" rx="3.25" fill="#F5F5F5" stroke="#E6E6E7" stroke-width="1.5" stroke-dasharray="4 4"/> +<rect x="34" y="38" width="52" height="2" rx="1" fill="#CDCECF"/> +</g> +<defs> +<filter id="filter0_d_2043_89914" x="0" y="0" width="120" height="80" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB"> +<feFlood flood-opacity="0" result="BackgroundImageFix"/> +<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/> +<feOffset dy="1"/> +<feGaussianBlur stdDeviation="1"/> +<feColorMatrix type="matrix" values="0 0 0 0 0.027451 0 0 0 0 0.0313726 0 0 0 0 0.0627451 0 0 0 0.1 0"/> +<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_2043_89914"/> +<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_2043_89914" result="shape"/> +</filter> +</defs> +</svg> diff --git a/web-frontend/modules/builder/assets/icons/element-simple_container.svg b/web-frontend/modules/builder/assets/icons/element-simple_container.svg new file mode 100644 index 000000000..3a1b1c22d --- /dev/null +++ b/web-frontend/modules/builder/assets/icons/element-simple_container.svg @@ -0,0 +1,5 @@ +<svg width="72" height="48" viewBox="0 0 72 48" fill="none" xmlns="http://www.w3.org/2000/svg"> +<rect x="1.25" y="1.25" width="69.5" height="45.5" rx="4.75" fill="white"/> +<rect x="1.25" y="1.25" width="69.5" height="45.5" rx="4.75" stroke="#E6E6E7" stroke-width="1.5"/> +<rect x="8.75" y="8.75" width="54.5" height="30.5" rx="3.25" fill="#F7F7F7" stroke="#E6E6E7" stroke-width="1.5" stroke-dasharray="4 4"/> +</svg> diff --git a/web-frontend/modules/builder/assets/icons/element-table.svg b/web-frontend/modules/builder/assets/icons/element-table.svg new file mode 100644 index 000000000..f6cc89af9 --- /dev/null +++ b/web-frontend/modules/builder/assets/icons/element-table.svg @@ -0,0 +1,34 @@ +<svg width="120" height="80" viewBox="0 0 120 80" fill="none" xmlns="http://www.w3.org/2000/svg"> +<g filter="url(#filter0_d_1314_36219)"> +<rect x="2" y="1" width="116" height="76" rx="6" fill="#FAFAFA"/> +<rect x="2.5" y="1.5" width="115" height="75" rx="5.5" stroke="#EDEDED"/> +<g clip-path="url(#clip0_1314_36219)"> +<rect x="26" y="17" width="68" height="44" rx="4" fill="white"/> +<rect x="26" y="17" width="68" height="6" fill="#E6E6E7"/> +<rect x="30" y="27" width="14" height="4" rx="2" fill="#E6E6E7"/> +<rect opacity="0.48" x="53" y="27" width="37" height="4" rx="2" fill="#E6E6E7"/> +<rect x="30" y="53" width="14" height="4" rx="2" fill="#E6E6E7"/> +<rect opacity="0.48" x="53" y="53" width="37" height="4" rx="2" fill="#E6E6E7"/> +<rect x="30" y="40" width="14" height="4" rx="2" fill="#E6E6E7"/> +<rect opacity="0.48" x="53" y="40" width="21" height="4" rx="2" fill="#E6E6E7"/> +<rect x="48" y="23" width="1" height="39" fill="#EDEDED"/> +<rect x="26" y="35" width="68" height="1" fill="#EDEDED"/> +<rect x="26" y="48" width="68" height="1" fill="#EDEDED"/> +</g> +<rect x="25.25" y="16.25" width="69.5" height="45.5" rx="4.75" stroke="#E6E6E7" stroke-width="1.5"/> +</g> +<defs> +<filter id="filter0_d_1314_36219" x="0" y="0" width="120" height="80" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB"> +<feFlood flood-opacity="0" result="BackgroundImageFix"/> +<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/> +<feOffset dy="1"/> +<feGaussianBlur stdDeviation="1"/> +<feColorMatrix type="matrix" values="0 0 0 0 0.027451 0 0 0 0 0.0313726 0 0 0 0 0.0627451 0 0 0 0.1 0"/> +<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_1314_36219"/> +<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_1314_36219" result="shape"/> +</filter> +<clipPath id="clip0_1314_36219"> +<rect x="26" y="17" width="68" height="44" rx="4" fill="white"/> +</clipPath> +</defs> +</svg> diff --git a/web-frontend/modules/builder/assets/icons/element-text.svg b/web-frontend/modules/builder/assets/icons/element-text.svg new file mode 100644 index 000000000..8d432502b --- /dev/null +++ b/web-frontend/modules/builder/assets/icons/element-text.svg @@ -0,0 +1,24 @@ +<svg width="120" height="80" viewBox="0 0 120 80" fill="none" xmlns="http://www.w3.org/2000/svg"> +<g filter="url(#filter0_d_1314_36292)"> +<rect x="2" y="1" width="116" height="76" rx="6" fill="#FAFAFA"/> +<rect x="2.5" y="1.5" width="115" height="75" rx="5.5" stroke="#EDEDED"/> +<rect x="25.25" y="26.25" width="69.5" height="25.5" rx="4.75" fill="white"/> +<rect x="25.25" y="26.25" width="69.5" height="25.5" rx="4.75" stroke="#E6E6E7" stroke-width="1.5"/> +<rect x="32" y="33" width="44" height="4" rx="2" fill="#E6E6E7"/> +<rect x="82" y="33" width="6" height="2" rx="1" fill="#D7D8D9"/> +<rect x="84" y="34" width="2" height="10" rx="1" fill="#D7D8D9"/> +<rect x="82" y="43" width="6" height="2" rx="1" fill="#D7D8D9"/> +<rect opacity="0.48" x="32" y="41" width="32" height="4" rx="2" fill="#E6E6E7"/> +</g> +<defs> +<filter id="filter0_d_1314_36292" x="0" y="0" width="120" height="80" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB"> +<feFlood flood-opacity="0" result="BackgroundImageFix"/> +<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/> +<feOffset dy="1"/> +<feGaussianBlur stdDeviation="1"/> +<feColorMatrix type="matrix" values="0 0 0 0 0.027451 0 0 0 0 0.0313726 0 0 0 0 0.0627451 0 0 0 0.1 0"/> +<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_1314_36292"/> +<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_1314_36292" result="shape"/> +</filter> +</defs> +</svg> diff --git a/web-frontend/modules/builder/assets/icons/element-video.svg b/web-frontend/modules/builder/assets/icons/element-video.svg new file mode 100644 index 000000000..822158447 --- /dev/null +++ b/web-frontend/modules/builder/assets/icons/element-video.svg @@ -0,0 +1,25 @@ +<svg width="120" height="80" viewBox="0 0 120 80" fill="none" xmlns="http://www.w3.org/2000/svg"> +<g filter="url(#filter0_d_1314_36336)"> +<rect x="2" y="1" width="116" height="76" rx="6" fill="#FAFAFA"/> +<rect x="2.5" y="1.5" width="115" height="75" rx="5.5" stroke="#EDEDED"/> +<rect x="25.25" y="20.25" width="69.5" height="37.5" rx="4.75" fill="white"/> +<rect x="25.25" y="20.25" width="69.5" height="37.5" rx="4.75" stroke="#E6E6E7" stroke-width="1.5"/> +<g clip-path="url(#clip0_1314_36336)"> +<path d="M60 31C58.4178 31 56.871 31.4692 55.5554 32.3482C54.2398 33.2273 53.2145 34.4767 52.609 35.9385C52.0035 37.4003 51.845 39.0089 52.1537 40.5607C52.4624 42.1126 53.2243 43.538 54.3431 44.6569C55.462 45.7757 56.8874 46.5376 58.4393 46.8463C59.9911 47.155 61.5997 46.9965 63.0615 46.391C64.5233 45.7855 65.7727 44.7602 66.6518 43.4446C67.5308 42.129 68 40.5823 68 39C67.9937 36.8802 67.1488 34.8491 65.6499 33.3501C64.1509 31.8512 62.1198 31.0063 60 31ZM62.765 39.424L58.765 41.924C58.6855 41.9737 58.5937 42 58.5 42C58.3674 42 58.2402 41.9473 58.1465 41.8536C58.0527 41.7598 58 41.6326 58 41.5V36.5C58 36.4107 58.0239 36.3231 58.0692 36.2462C58.1145 36.1693 58.1796 36.1059 58.2576 36.0627C58.3357 36.0194 58.4239 35.9978 58.5131 36.0002C58.6023 36.0025 58.6893 36.0287 58.765 36.076L62.765 38.576C62.8369 38.6209 62.8962 38.6834 62.9373 38.7576C62.9784 38.8318 63 38.9152 63 39C63 39.0848 62.9784 39.1682 62.9373 39.2424C62.8962 39.3166 62.8369 39.3791 62.765 39.424Z" fill="#4E5CFE"/> +</g> +</g> +<defs> +<filter id="filter0_d_1314_36336" x="0" y="0" width="120" height="80" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB"> +<feFlood flood-opacity="0" result="BackgroundImageFix"/> +<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/> +<feOffset dy="1"/> +<feGaussianBlur stdDeviation="1"/> +<feColorMatrix type="matrix" values="0 0 0 0 0.027451 0 0 0 0 0.0313726 0 0 0 0 0.0627451 0 0 0 0.1 0"/> +<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_1314_36336"/> +<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_1314_36336" result="shape"/> +</filter> +<clipPath id="clip0_1314_36336"> +<rect width="16" height="16" fill="white" transform="translate(52 31)"/> +</clipPath> +</defs> +</svg> diff --git a/web-frontend/modules/builder/components/PublicSiteErrorPage.vue b/web-frontend/modules/builder/components/PublicSiteErrorPage.vue index 465bb0a3b..43aa08c86 100644 --- a/web-frontend/modules/builder/components/PublicSiteErrorPage.vue +++ b/web-frontend/modules/builder/components/PublicSiteErrorPage.vue @@ -54,12 +54,20 @@ export default { }, methods: { onHome() { - this.$router.push({ - name: 'application-builder-page', - params: { pathMatch: '/' }, - // We remove the query parameters. Important if we have some with error - query: null, - }) + if ( + this.$route.name === 'application-builder-page' && + this.$route.params.pathMatch === '/' + ) { + // Reload the current page + this.$router.go(0) + } else { + // Navigate to the home route + this.$router.push({ + name: 'application-builder-page', + params: { pathMatch: '/' }, + query: null, // Remove query parameters + }) + } }, }, } diff --git a/web-frontend/modules/builder/components/TextDecorationSelector.vue b/web-frontend/modules/builder/components/TextDecorationSelector.vue new file mode 100644 index 000000000..a65b86406 --- /dev/null +++ b/web-frontend/modules/builder/components/TextDecorationSelector.vue @@ -0,0 +1,49 @@ +<template> + <div class="text-decoration-selector"> + <SwitchButton + :value="value[0]" + :icon="'iconoir-underline'" + :title="$t('textDecorationSelector.underline')" + @input="toggle(0)" + /> + <SwitchButton + :value="value[1]" + :icon="'iconoir-strikethrough'" + :title="$t('textDecorationSelector.stroke')" + @input="toggle(1)" + /> + <SwitchButton + :value="value[2]" + :icon="'iconoir-text'" + :title="$t('textDecorationSelector.uppercase')" + @input="toggle(2)" + /> + <SwitchButton + :value="value[3]" + :icon="'iconoir-italic'" + :title="$t('textDecorationSelector.italic')" + @input="toggle(3)" + /> + </div> +</template> + +<script> +export default { + name: 'TextDecorationSelector', + props: { + value: { + type: Array, + required: false, + default: () => [false, false, false, false], + }, + }, + methods: { + toggle(index) { + this.$emit( + 'input', + this.value.map((v, i) => (i === index ? !v : v)) + ) + }, + }, +} +</script> diff --git a/web-frontend/modules/builder/components/domain/CustomDomainForm.vue b/web-frontend/modules/builder/components/domain/CustomDomainForm.vue index 450a7ea96..742b956d1 100644 --- a/web-frontend/modules/builder/components/domain/CustomDomainForm.vue +++ b/web-frontend/modules/builder/components/domain/CustomDomainForm.vue @@ -7,6 +7,7 @@ :error-message="getFirstErrorMessage('domain_name') || serverErrorMessage" > <FormInput + ref="domainName" v-model="v$.values.domain_name.$model" size="large" @input="handleInput" @@ -45,6 +46,9 @@ export default { : '' }, }, + mounted() { + this.$refs.domainName.focus() + }, methods: { handleInput() { this.serverErrors.domain_name = null diff --git a/web-frontend/modules/builder/components/domain/DomainCard.vue b/web-frontend/modules/builder/components/domain/DomainCard.vue index a5d5e61b9..557f18d92 100644 --- a/web-frontend/modules/builder/components/domain/DomainCard.vue +++ b/web-frontend/modules/builder/components/domain/DomainCard.vue @@ -26,6 +26,13 @@ /> </div> </div> + <Alert + v-if="!domain.last_published" + type="warning" + class="margin-bottom-0" + > + <p>{{ $t('domainCard.unpublishedDomainWarning') }}</p> + </Alert> </template> <component :is="domainType.detailsComponent" diff --git a/web-frontend/modules/builder/components/domain/DomainForm.vue b/web-frontend/modules/builder/components/domain/DomainForm.vue index 2d15118f1..89058994a 100644 --- a/web-frontend/modules/builder/components/domain/DomainForm.vue +++ b/web-frontend/modules/builder/components/domain/DomainForm.vue @@ -105,6 +105,7 @@ export default { }) this.hideError() this.hideForm() + this.$emit('created') } catch (error) { this.handleAnyError(error) } diff --git a/web-frontend/modules/builder/components/elements/AddElementCard.vue b/web-frontend/modules/builder/components/elements/AddElementCard.vue index 5d93fcdcc..fc0e9bd61 100644 --- a/web-frontend/modules/builder/components/elements/AddElementCard.vue +++ b/web-frontend/modules/builder/components/elements/AddElementCard.vue @@ -1,24 +1,19 @@ <template> <div :key="elementType.name" - v-tooltip="disabled ? disabledMessage : null" + v-tooltip="disabled ? disabledMessage : elementType.description" class="add-element-card" :class="{ 'add-element-card--disabled': disabled }" v-on="$listeners" > + <div class="add-element-card__element-type"> + <div + class="add-element-card__element-type-icon" + :class="`add-element-card__element-type-icon-${elementType.getType()}`" + ></div> + </div> <div v-if="loading" class="loading"></div> - <template v-else> - <div class="add-element-card__element-type"> - <i - class="add-element-card__element-type-icon" - :class="elementType.iconClass" - ></i> - <span>{{ elementType.name }}</span> - </div> - <div class="margin-top-1 add-element-card__description"> - {{ elementType.description }} - </div> - </template> + <span v-else class="add-element-card__label">{{ elementType.name }}</span> </div> </template> diff --git a/web-frontend/modules/builder/components/elements/AddElementModal.vue b/web-frontend/modules/builder/components/elements/AddElementModal.vue index 8b8c44921..5b4c35fc4 100644 --- a/web-frontend/modules/builder/components/elements/AddElementModal.vue +++ b/web-frontend/modules/builder/components/elements/AddElementModal.vue @@ -1,24 +1,56 @@ <template> - <Modal> + <Modal class="add-element-modal"> <h2 class="box__title">{{ $t('addElementModal.title') }}</h2> - <FormInput - ref="search" - v-model="search" - size="large" - class="margin-bottom-2" - :placeholder="$t('addElementModal.searchPlaceholder')" - icon-right="iconoir-search" - /> - <div class="add-element-modal__element-cards"> - <AddElementCard - v-for="elementType in elementTypes" - :key="elementType.getType()" - :element-type="elementType" - :loading="addingElementType === elementType.getType()" - :disabled="isElementTypeDisabled(elementType)" - :disabled-message="getElementTypeDisabledMessage(elementType)" - @click="addElement(elementType)" + <div class="add-element-modal__content"> + <FormInput + ref="search" + v-model="search" + size="large" + class="add-element-modal__search" + :placeholder="$t('addElementModal.searchPlaceholder')" + icon-left="iconoir-search" /> + <div class="add-element-modal__element-cards"> + <template v-for="group in elementTypes"> + <div + v-if="group.elementTypes.length > 0" + :key="group.subject" + class="add-element-modal__category" + > + <Expandable + :default-expanded="!initiallyCollapsedCategories[group.subject]" + > + <template #header="{ toggle, expanded }"> + <a class="add-element-modal__category-title" @click="toggle"> + {{ group.label }} + <i + class="add-element-modal__category-arrow" + :class="{ + 'iconoir-nav-arrow-down': expanded, + 'iconoir-nav-arrow-right': !expanded, + }" + /> + </a> + </template> + <template #default> + <div class="add-element-modal__category-content"> + <AddElementCard + v-for="elementType in group.elementTypes" + :key="elementType.getType()" + :element-type="elementType" + :loading="addingElementType === elementType.getType()" + :disabled="isElementTypeDisabled(elementType)" + :disabled-message=" + getElementTypeDisabledMessage(elementType) + " + @click="addElement(elementType)" + /> + </div> + </template> + </Expandable> + </div> + </template> + </div> </div> </Modal> </template> @@ -30,10 +62,11 @@ import { isSubstringOfStrings } from '@baserow/modules/core/utils/string' import { notifyIf } from '@baserow/modules/core/utils/error' import { mapActions } from 'vuex' import { PAGE_PLACES } from '@baserow/modules/builder/enums' +import Expandable from '@baserow/modules/core/components/Expandable' export default { name: 'AddElementModal', - components: { AddElementCard }, + components: { AddElementCard, Expandable }, mixins: [modal], inject: ['builder', 'currentPage'], props: { @@ -50,17 +83,43 @@ export default { parentElementId: null, pagePlace: null, addingElementType: null, + initiallyCollapsedCategories: {}, } }, computed: { elementTypes() { const elementTypesAll = Object.values(this.$registry.getAll('element')) - return elementTypesAll.filter((elementType) => + const filteredTypes = elementTypesAll.filter((elementType) => isSubstringOfStrings( [elementType.name, elementType.description], this.search ) ) + + // Define group categories + const groupsList = ['baseElement', 'layoutElement', 'formElement'] + + // Create group objects with label and empty elementTypes array + const groups = groupsList.map((subject) => ({ + subject, + label: this.$t(`addElementCategory.${subject}`), + elementTypes: [], + })) + + // Fill other groups with filtered element types + filteredTypes.forEach((elementType) => { + const category = elementType.category() || 'baseElement' + + // Add element to its standard category, even if it's already in suggested elements + if (category !== 'suggestedElement') { + const group = groups.find((g) => g.subject === category) + if (group) { + group.elementTypes.push(elementType) + } + } + }) + + return groups }, sharedPage() { return this.$store.getters['page/getSharedPage'](this.builder) diff --git a/web-frontend/modules/builder/components/elements/ElementPreview.vue b/web-frontend/modules/builder/components/elements/ElementPreview.vue index 59c32c59e..b823d3fec 100644 --- a/web-frontend/modules/builder/components/elements/ElementPreview.vue +++ b/web-frontend/modules/builder/components/elements/ElementPreview.vue @@ -38,6 +38,7 @@ :mode="mode" class="element--read-only" :application-context-additions="applicationContextAdditions" + :show-element-id="showElementId" @move="$emit('move', $event)" /> @@ -100,6 +101,11 @@ export default { required: false, default: null, }, + showElementId: { + type: Boolean, + required: false, + default: false, + }, }, data() { return { diff --git a/web-frontend/modules/builder/components/elements/baseComponents/ABLink.vue b/web-frontend/modules/builder/components/elements/baseComponents/ABLink.vue index 6a81d6515..5d7e7bea0 100644 --- a/web-frontend/modules/builder/components/elements/baseComponents/ABLink.vue +++ b/web-frontend/modules/builder/components/elements/baseComponents/ABLink.vue @@ -1,10 +1,13 @@ <template> <a - :class="{ - 'ab-link': variant !== 'button', - 'ab-button ab-button--medium': variant === 'button', - 'ab-button--full-width': variant === 'button' && fullWidth === true, - }" + :class="[ + { + 'ab-link': variant !== 'button', + 'ab-button ab-button--medium': variant === 'button', + 'ab-button--full-width': variant === 'button' && fullWidth === true, + }, + forceActiveClass, + ]" :target="`_${target}`" :href="url" :rel="isExternalLink ? 'noopener noreferrer' : null" @@ -36,7 +39,7 @@ export default { }, }, /** - * @type {string} - Wheter the button should be full width. + * @type {Boolean} - Wheter the button should be full width. */ fullWidth: { type: Boolean, @@ -61,11 +64,22 @@ export default { type: String, required: true, }, + /** + * @type {Boolean} - Whether the active class should be applied to the link. + */ + forceActive: { + type: Boolean, + required: false, + default: false, + }, }, computed: { isExternalLink() { return !this.url.startsWith('/') }, + forceActiveClass() { + return this.forceActive ? `ab-${this.variant}--force-active` : '' + }, }, methods: { handleClick(event) { diff --git a/web-frontend/modules/builder/components/elements/baseComponents/ABTable.vue b/web-frontend/modules/builder/components/elements/baseComponents/ABTable.vue index fdc54e5db..57a01aae4 100644 --- a/web-frontend/modules/builder/components/elements/baseComponents/ABTable.vue +++ b/web-frontend/modules/builder/components/elements/baseComponents/ABTable.vue @@ -39,7 +39,7 @@ </template> <script> -import { TABLE_ORIENTATION } from '@baserow/modules/builder/enums' +import { ORIENTATIONS } from '@baserow/modules/builder/enums' import BaserowTable from '@baserow/modules/builder/components/elements/components/BaserowTable' export default { @@ -57,7 +57,7 @@ export default { orientation: { type: String, required: false, - default: TABLE_ORIENTATION.HORIZONTAL, + default: ORIENTATIONS.HORIZONTAL, }, contentLoading: { type: Boolean, diff --git a/web-frontend/modules/builder/components/elements/components/BaserowTable.vue b/web-frontend/modules/builder/components/elements/components/BaserowTable.vue index 4d57ad968..04ab8d26c 100644 --- a/web-frontend/modules/builder/components/elements/components/BaserowTable.vue +++ b/web-frontend/modules/builder/components/elements/components/BaserowTable.vue @@ -1,7 +1,7 @@ <template> <div class="baserow-table-wrapper"> <table class="baserow-table" :class="`baserow-table--${orientation}`"> - <template v-if="orientation === TABLE_ORIENTATION.HORIZONTAL"> + <template v-if="orientation === ORIENTATIONS.HORIZONTAL"> <thead> <tr class="baserow-table__row"> <template v-for="field in fields"> @@ -84,7 +84,7 @@ </template> <script> -import { TABLE_ORIENTATION } from '@baserow/modules/builder/enums' +import { ORIENTATIONS } from '@baserow/modules/builder/enums' export default { name: 'BaserowTable', @@ -100,12 +100,12 @@ export default { }, orientation: { type: String, - default: TABLE_ORIENTATION.HORIZONTAL, + default: ORIENTATIONS.HORIZONTAL, }, }, computed: { - TABLE_ORIENTATION() { - return TABLE_ORIENTATION + ORIENTATIONS() { + return ORIENTATIONS }, }, } diff --git a/web-frontend/modules/builder/components/elements/components/MenuElement.vue b/web-frontend/modules/builder/components/elements/components/MenuElement.vue new file mode 100644 index 000000000..d8443685b --- /dev/null +++ b/web-frontend/modules/builder/components/elements/components/MenuElement.vue @@ -0,0 +1,274 @@ +<template> + <div + :style="{ + '--alignment': menuAlignment, + }" + :class="[ + 'menu-element__container', + element.orientation === 'horizontal' + ? 'menu-element__container--horizontal' + : 'menu-element__container--vertical', + ]" + > + <div + v-for="item in element.menu_items" + :key="item.id" + :class="`menu-element__menu-item-${item.type}`" + > + <template v-if="item.type === 'link' && !item.parent_menu_item"> + <div v-if="!item.children?.length" :style="getStyleOverride('menu')"> + <ABLink + :variant="item.variant" + :url="getItemUrl(item)" + :target="getMenuItem(item).target" + :force-active="menuItemIsActive(item)" + > + {{ + item.name + ? item.name || + (mode === 'editing' + ? $t('menuElement.emptyLinkValue') + : ' ') + : $t('menuElement.missingLinkValue') + }} + </ABLink> + </div> + <div + v-else + ref="menuSubLinkContainer" + @click="showSubMenu($event, item.id)" + > + <div :style="getStyleOverride('menu')"> + <ABLink + :variant="item.variant" + url="" + :force-active="sublinkIsActive(item)" + > + <div class="menu-element__sub-link-menu--container"> + {{ item.name }} + <div class="menu-element__sub-link-menu-spacer"></div> + <div> + <i + class="menu-element__sub-link--expanded-icon" + :class=" + isExpanded(item.id) + ? 'iconoir-nav-arrow-up' + : 'iconoir-nav-arrow-down' + " + ></i> + </div> + </div> + </ABLink> + </div> + + <Context + :ref="`subLinkContext_${item.id}`" + :hide-on-click-outside="true" + @shown="toggleExpanded(item.id)" + @hidden="toggleExpanded(item.id)" + > + <ThemeProvider> + <div + v-for="child in item.children" + :key="child.id" + class="menu-element__sub-links" + :style="getStyleOverride('menu')" + > + <ABLink + :variant="child.variant" + :url="getItemUrl(child)" + :target="getMenuItem(child).target" + class="menu-element__sub-link" + :force-active="menuItemIsActive(child)" + > + {{ + child.name + ? child.name || + (mode === 'editing' + ? $t('menuElement.emptyLinkValue') + : ' ') + : $t('menuElement.missingLinkValue') + }} + </ABLink> + </div> + </ThemeProvider> + </Context> + </div> + </template> + <template v-else-if="item.type === 'button'"> + <ABButton + :style="getStyleOverride('menu')" + @click="onButtonClick(item)" + > + {{ + item.name + ? item.name || + (mode === 'editing' + ? $t('menuElement.emptyButtonValue') + : ' ') + : $t('menuElement.missingButtonValue') + }} + </ABButton> + </template> + </div> + + <div v-if="!element.menu_items.length" class="element--no-value"> + {{ $t('menuElement.missingValue') }} + </div> + </div> +</template> + +<script> +import { resolveApplicationRoute } from '@baserow/modules/builder/utils/routing' +import element from '@baserow/modules/builder/mixins/element' +import resolveElementUrl from '@baserow/modules/builder/utils/urlResolution' +import ThemeProvider from '@baserow/modules/builder/components/theme/ThemeProvider' +import { HORIZONTAL_ALIGNMENTS } from '@baserow/modules/builder/enums' + +/** + * CSS classes to force a Link variant to appear as active. + */ +const LINK_ACTIVE_CLASSES = { + link: 'ab-link--force-active', + button: 'ab-button--force-active', +} + +/** + * @typedef MenuElement + * @property {Array} menu_items Array of Menu items + */ + +export default { + name: 'MenuElement', + components: { ThemeProvider }, + mixins: [element], + props: { + element: { + type: Object, + required: true, + }, + }, + data() { + return { + expandedItems: {}, + activeItem: {}, + } + }, + computed: { + pages() { + return this.$store.getters['page/getVisiblePages'](this.builder) + }, + menuElementType() { + return this.$registry.get('element', 'menu') + }, + menuAlignment() { + const alignmentsCSS = { + [HORIZONTAL_ALIGNMENTS.LEFT]: 'flex-start', + [HORIZONTAL_ALIGNMENTS.CENTER]: 'center', + [HORIZONTAL_ALIGNMENTS.RIGHT]: 'flex-end', + } + return alignmentsCSS[this.element.alignment] + }, + }, + mounted() { + /** + * If the current page matches a menu item, that menu item is set as the + * active item. This ensures that the active CSS style is applied to the + * correct menu item. + */ + const found = resolveApplicationRoute( + this.pages, + this.$route.params.pathMatch + ) + + if (!found?.length) return + + const currentPageId = found[0].id + + for (const item of this.element.menu_items) { + if (!item.children.length && item.navigate_to_page_id === currentPageId) { + this.activeItem = item + break + } + for (const child of item.children) { + if (child.navigate_to_page_id === currentPageId) { + this.activeItem = child + break + } + } + } + }, + methods: { + showSubMenu(event, itemId) { + const contextRef = this.$refs[`subLinkContext_${itemId}`][0] + if (contextRef?.isOpen()) { + contextRef.hide() + } else { + const containerRef = event.currentTarget + contextRef.show(containerRef, 'bottom', 'left', 0) + } + }, + getItemUrl(item) { + try { + return resolveElementUrl( + this.getMenuItem(item), + this.builder, + this.pages, + this.resolveFormula, + this.mode + ) + } catch (e) { + return '#error' + } + }, + toggleExpanded(itemId) { + this.$set(this.expandedItems, itemId, !this.expandedItems[itemId]) + }, + /** + * Transforms a Menu Item into a valid object that can be passed as a prop + * to the ABLink component. + */ + getMenuItem(item) { + return { + id: this.element.id, + menu_item_id: item?.id, + uid: item?.uid, + target: item.target || 'self', + variant: item?.variant || 'link', + value: item.name, + navigation_type: item.navigation_type, + navigate_to_page_id: item.navigate_to_page_id || null, + page_parameters: item.page_parameters || {}, + query_parameters: item.query_parameters || {}, + navigate_to_url: item.navigate_to_url || '#', + page_id: this.element.page_id, + type: 'menu_item', + } + }, + isExpanded(itemId) { + return !!this.expandedItems[itemId] + }, + onButtonClick(item) { + const eventName = `${item.uid}_click` + this.fireEvent( + this.menuElementType.getEventByName(this.element, eventName) + ) + }, + menuItemIsActive(item) { + return this.activeItem?.uid === item.uid + }, + getActiveParentClass(item) { + if (item.children?.some((child) => child.uid === this.activeItem?.uid)) + return LINK_ACTIVE_CLASSES[item.variant] || '' + + return '' + }, + sublinkIsActive(item) { + if (item.children?.some((child) => child.uid === this.activeItem?.uid)) + return true + + return false + }, + }, +} +</script> diff --git a/web-frontend/modules/builder/components/elements/components/RepeatElement.vue b/web-frontend/modules/builder/components/elements/components/RepeatElement.vue index 4f8e4cce7..c80e1a013 100644 --- a/web-frontend/modules/builder/components/elements/components/RepeatElement.vue +++ b/web-frontend/modules/builder/components/elements/components/RepeatElement.vue @@ -2,6 +2,7 @@ <div class="repeat-element--container"> <CollectionElementHeader :element="element" + :style="getStyleOverride('header_button')" @filters-changed="adhocFilters = $event" @sortings-changed="adhocSortings = $event" @search-changed="adhocSearch = $event" @@ -134,6 +135,7 @@ import PageElement from '@baserow/modules/builder/components/page/PageElement' import { ensureString } from '@baserow/modules/core/utils/validator' import { RepeatElementType } from '@baserow/modules/builder/elementTypes' import CollectionElementHeader from '@baserow/modules/builder/components/elements/components/CollectionElementHeader' +import { ORIENTATIONS } from '@baserow/modules/builder/enums' export default { name: 'RepeatElement', @@ -190,7 +192,7 @@ export default { // `grid-template-columns` rule's `repeat`, it will cause a repaint // following page load when the orientation is horizontal. Initially the // page visitor will see repetitions vertically, then suddenly horizontally. - if (this.element.orientation === 'vertical') { + if (this.element.orientation === ORIENTATIONS.VERTICAL) { return { display: 'flex', 'flex-direction': 'column', diff --git a/web-frontend/modules/builder/components/elements/components/SimpleContainerElement.vue b/web-frontend/modules/builder/components/elements/components/SimpleContainerElement.vue new file mode 100644 index 000000000..8dbec1740 --- /dev/null +++ b/web-frontend/modules/builder/components/elements/components/SimpleContainerElement.vue @@ -0,0 +1,66 @@ +<template> + <div> + <template + v-if=" + mode === 'editing' && + children.length === 0 && + $hasPermission('builder.page.create_element', currentPage, workspace.id) + " + > + <AddElementZone @add-element="showAddElementModal"></AddElementZone> + <AddElementModal + ref="addElementModal" + :page="elementPage" + ></AddElementModal> + </template> + <template v-else> + <template v-for="child in children"> + <ElementPreview + v-if="mode === 'editing'" + :key="child.id" + :element="child" + @move="$emit('move', $event)" + /> + <PageElement + v-else + :key="`${child.id}else`" + :element="child" + :mode="mode" + /> + </template> + </template> + </div> +</template> + +<script> +import AddElementZone from '@baserow/modules/builder/components/elements/AddElementZone' +import containerElement from '@baserow/modules/builder/mixins/containerElement' +import AddElementModal from '@baserow/modules/builder/components/elements/AddElementModal' +import ElementPreview from '@baserow/modules/builder/components/elements/ElementPreview' +import PageElement from '@baserow/modules/builder/components/page/PageElement' + +export default { + name: 'SimpleContainerElement', + components: { + PageElement, + ElementPreview, + AddElementModal, + AddElementZone, + }, + mixins: [containerElement], + props: { + element: { + type: Object, + required: true, + }, + }, + methods: { + showAddElementModal() { + this.$refs.addElementModal.show({ + placeInContainer: null, + parentElementId: this.element.id, + }) + }, + }, +} +</script> diff --git a/web-frontend/modules/builder/components/elements/components/TableElement.vue b/web-frontend/modules/builder/components/elements/components/TableElement.vue index 89279de4a..8ffbe545c 100644 --- a/web-frontend/modules/builder/components/elements/components/TableElement.vue +++ b/web-frontend/modules/builder/components/elements/components/TableElement.vue @@ -2,6 +2,7 @@ <div class="table-element"> <CollectionElementHeader :element="element" + :style="getStyleOverride('header_button')" @filters-changed="adhocFilters = $event" @sortings-changed="adhocSortings = $event" @search-changed="adhocSearch = $event" diff --git a/web-frontend/modules/builder/components/elements/components/forms/general/MenuElementForm.vue b/web-frontend/modules/builder/components/elements/components/forms/general/MenuElementForm.vue new file mode 100644 index 000000000..52186fceb --- /dev/null +++ b/web-frontend/modules/builder/components/elements/components/forms/general/MenuElementForm.vue @@ -0,0 +1,242 @@ +<template> + <form @submit.prevent @keydown.enter.prevent> + <CustomStyle + v-model="values.styles" + style-key="menu" + :config-block-types="['button', 'link']" + :theme="builder.theme" + :extra-args="{ noAlignment: true, noWidth: true }" + /> + <FormGroup + :label="$t('orientations.label')" + small-label + required + class="margin-bottom-2" + > + <RadioGroup + v-model="values.orientation" + :options="orientationOptions" + type="button" + > + </RadioGroup> + </FormGroup> + + <FormGroup + v-if="values.orientation === ORIENTATIONS.HORIZONTAL" + :label="$t('menuElementForm.alignment')" + small-label + required + class="margin-bottom-2" + > + <HorizontalAlignmentsSelector v-model="values.alignment" /> + </FormGroup> + + <div + ref="menuItemAddContainer" + class="menu-element-form__add-item-container" + > + <div> + {{ $t('menuElementForm.menuItemsLabel') }} + </div> + <div> + <ButtonText + type="primary" + icon="iconoir-plus" + size="small" + @click=" + $refs.menuItemAddContext.show( + $refs.menuItemAddContainer, + 'bottom', + 'right' + ) + " + > + {{ $t('menuElementForm.addMenuItemLink') }} + </ButtonText> + </div> + </div> + <p v-if="!values.menu_items.length"> + {{ $t('menuElementForm.noMenuItemsMessage') }} + </p> + <Context ref="menuItemAddContext" :hide-on-click-outside="true"> + <div class="menu-element-form__add-item-context"> + <ButtonText + v-for="(menuItemType, index) in addMenuItemTypes" + :key="index" + type="primary" + :icon="menuItemType.icon" + size="small" + @click="addMenuItem(menuItemType.type)" + > + {{ menuItemType.label }} + </ButtonText> + </div> + </Context> + <div> + <div class="menu-element-form__items"> + <MenuElementItemForm + v-for="(item, index) in values.menu_items" + :key="`${item.uid}-${index}`" + v-sortable="{ + id: item.uid, + update: orderRootItems, + enabled: $hasPermission( + 'builder.page.element.update', + element, + workspace.id + ), + handle: '[data-sortable-handle]', + }" + :default-values="item" + @remove-item="removeMenuItem($event)" + @values-changed="updateMenuItem" + ></MenuElementItemForm> + </div> + </div> + </form> +</template> + +<script> +import elementForm from '@baserow/modules/builder/mixins/elementForm' +import { + HORIZONTAL_ALIGNMENTS, + ORIENTATIONS, +} from '@baserow/modules/builder/enums' +import { + getNextAvailableNameInSequence, + uuid, +} from '@baserow/modules/core/utils/string' +import { mapGetters } from 'vuex' +import MenuElementItemForm from '@baserow/modules/builder/components/elements/components/forms/general/MenuElementItemForm' +import CustomStyle from '@baserow/modules/builder/components/elements/components/forms/style/CustomStyle' +import HorizontalAlignmentsSelector from '@baserow/modules/builder/components/HorizontalAlignmentsSelector' + +export default { + name: 'MenuElementForm', + components: { + MenuElementItemForm, + CustomStyle, + HorizontalAlignmentsSelector, + }, + mixins: [elementForm], + data() { + return { + values: { + value: '', + styles: {}, + orientation: ORIENTATIONS.VERTICAL, + alignment: HORIZONTAL_ALIGNMENTS.LEFT, + menu_items: [], + }, + allowedValues: [ + 'value', + 'styles', + 'menu_items', + 'orientation', + 'alignment', + ], + addMenuItemTypes: [ + { + icon: 'iconoir-link', + label: this.$t('menuElementForm.menuItemAddLink'), + type: 'link', + }, + { + icon: 'iconoir-cursor-pointer', + label: this.$t('menuElementForm.menuItemAddButton'), + type: 'button', + }, + { + icon: 'baserow-icon-separator', + label: this.$t('menuElementForm.menuItemAddSeparator'), + type: 'separator', + }, + { + icon: 'baserow-icon-spacer', + label: this.$t('menuElementForm.menuItemAddSpacer'), + type: 'spacer', + }, + ], + } + }, + computed: { + ...mapGetters({ + getElementSelected: 'element/getSelected', + }), + ORIENTATIONS() { + return ORIENTATIONS + }, + element() { + return this.getElementSelected(this.builder) + }, + orientationOptions() { + return [ + { + label: this.$t('orientations.vertical'), + value: ORIENTATIONS.VERTICAL, + icon: 'iconoir-table-rows', + }, + { + label: this.$t('orientations.horizontal'), + value: ORIENTATIONS.HORIZONTAL, + icon: 'iconoir-view-columns-3', + }, + ] + }, + }, + methods: { + addMenuItem(type) { + const name = getNextAvailableNameInSequence( + this.$t('menuElementForm.menuItemDefaultName'), + this.values.menu_items + .filter((item) => item.parent_menu_item === null) + .map(({ name }) => name) + ) + + this.values.menu_items = [ + ...this.values.menu_items, + { + name, + variant: 'link', + value: '', + type, + uid: uuid(), + children: [], + parent_menu_item: null, // This is the root menu item. + }, + ] + this.$refs.menuItemAddContext.hide() + }, + /** + * When a menu item is removed, this method is responsible for removing it + * from the `MenuElement` itself. + */ + removeMenuItem(uidToRemove) { + this.values.menu_items = this.values.menu_items.filter( + (item) => item.uid !== uidToRemove + ) + }, + /** + * When a menu item is updated, this method is responsible for updating the + * `MenuElement` with the new values. + */ + updateMenuItem(newValues) { + this.values.menu_items = this.values.menu_items.map((item) => { + if (item.uid === newValues.uid) { + return { ...item, ...newValues } + } + return item + }) + }, + /** + * Responsible for sorting the root items of this menu item. + */ + orderRootItems(newOrder) { + const itemsByUid = Object.fromEntries( + this.values.menu_items.map((item) => [item.uid, item]) + ) + this.values.menu_items = newOrder.map((uid) => itemsByUid[uid]) + }, + }, +} +</script> diff --git a/web-frontend/modules/builder/components/elements/components/forms/general/MenuElementItemForm.vue b/web-frontend/modules/builder/components/elements/components/forms/general/MenuElementItemForm.vue new file mode 100644 index 000000000..703436c57 --- /dev/null +++ b/web-frontend/modules/builder/components/elements/components/forms/general/MenuElementItemForm.vue @@ -0,0 +1,292 @@ +<template> + <Expandable> + <template #header="{ toggle, expanded }"> + <div + class="menu-element-form__item-header" + :class="{ + 'menu-element-form__item-header--outline': isStyle, + }" + @click.stop="!isStyle ? toggle() : null" + > + <div class="menu-element-form__item-handle" data-sortable-handle /> + <div class="menu-element-form__item-name"> + <template v-if="values.type === 'separator'"> + {{ $t('menuElement.separator') }} + </template> + <template v-else-if="values.type === 'spacer'"> + {{ $t('menuElement.spacer') }} + </template> + <template v-else> + {{ values.name }} + </template> + </div> + + <template v-if="isStyle"> + <ButtonIcon + size="small" + icon="iconoir-bin" + @click="removeMenuItem(values)" + /> + </template> + <template v-else> + <i + :class=" + expanded ? 'iconoir-nav-arrow-down' : 'iconoir-nav-arrow-right' + " + /> + </template> + </div> + </template> + <template v-if="!isStyle" #default> + <div + class="menu-element-form__item" + :class="{ 'menu-element-form__item-child': preventItemNesting }" + > + <div v-if="values.type === 'button'"> + <FormGroup + small-label + horizontal + required + class="margin-bottom-2" + :label="$t('menuElementForm.menuItemLabelLabel')" + :error="fieldHasErrors('name')" + > + <FormInput + v-model="v$.values.name.$model" + :placeholder="$t('menuElementForm.namePlaceholder')" + :error="fieldHasErrors('name')" + /> + <template #error> + {{ v$.values.name.$errors[0]?.$message }} + </template> + <template #after-input> + <ButtonIcon icon="iconoir-bin" @click="removeMenuItem()" /> + </template> + </FormGroup> + <Alert type="info-neutral"> + <p>{{ $t('menuElementForm.eventDescription') }}</p> + </Alert> + </div> + + <div v-else> + <FormGroup + small-label + horizontal + required + class="margin-bottom-2" + :label="$t('menuElementForm.menuItemLabelLabel')" + :error="fieldHasErrors('name')" + > + <FormInput + v-model="v$.values.name.$model" + :placeholder="$t('menuElementForm.namePlaceholder')" + :error="fieldHasErrors('name')" + /> + <template #error> + {{ v$.values.name.$errors[0]?.$message }} + </template> + <template #after-input> + <ButtonIcon icon="iconoir-bin" @click="removeMenuItem()" /> + </template> + </FormGroup> + + <FormGroup + small-label + horizontal + required + :label="$t('menuElementForm.menuItemVariantLabel')" + class="margin-bottom-2" + > + <Dropdown + :value="values.variant" + :show-search="false" + @input="values.variant = $event" + > + <DropdownItem + v-for="itemVariant in menuItemVariants" + :key="itemVariant.value" + :name="itemVariant.label" + :value="itemVariant.value" + /> + </Dropdown> + </FormGroup> + + <LinkNavigationSelectionForm + v-if="!values.children.length" + :default-values="defaultValues" + @values-changed="values = { ...values, ...$event }" + /> + <div class="menu-element-item-form__children"> + <MenuElementItemForm + v-for="(child, index) in values.children" + :key="`${child.uid}-${index}`" + v-sortable="{ + id: child.uid, + update: orderChildItems, + enabled: $hasPermission( + 'builder.page.element.update', + element, + workspace.id + ), + handle: '[data-sortable-handle]', + }" + prevent-item-nesting + :default-values="child" + @remove-item="removeChildItem($event)" + @values-changed="updateChildItem" + ></MenuElementItemForm> + </div> + + <div + v-if="!preventItemNesting" + class="menu-element-form__add-sub-link-container" + > + <ButtonText + type="primary" + icon="iconoir-plus" + size="small" + @click="addSubLink()" + > + {{ $t('menuElementForm.addSubLink') }} + </ButtonText> + </div> + </div> + </div> + </template> + </Expandable> +</template> + +<script> +import { mapGetters } from 'vuex' +import elementForm from '@baserow/modules/builder/mixins/elementForm' +import LinkNavigationSelectionForm from '@baserow/modules/builder/components/elements/components/forms/general/LinkNavigationSelectionForm' +import { useVuelidate } from '@vuelidate/core' +import { helpers, required } from '@vuelidate/validators' +import { + getNextAvailableNameInSequence, + uuid, +} from '@baserow/modules/core/utils/string' +import { LINK_VARIANTS } from '@baserow/modules/builder/enums' + +export default { + name: 'MenuElementItemForm', + components: { + LinkNavigationSelectionForm, + }, + mixins: [elementForm], + props: { + /** + * Controls whether this menu item can nest other menu items. This is + * allowed by default. Since we only allow one level of nesting for + * sublinks, this should be false when rendering sublinks. + */ + preventItemNesting: { + type: Boolean, + default: false, + }, + }, + setup() { + return { v$: useVuelidate({ $lazy: true }) } + }, + data() { + return { + values: { + uid: '', + name: '', + type: '', + variant: '', + children: [], + }, + allowedValues: ['uid', 'name', 'type', 'variant', 'children'], + } + }, + computed: { + ...mapGetters({ + getElementSelected: 'element/getSelected', + }), + isStyle() { + return ['separator', 'spacer'].includes(this.values.type) + }, + element() { + return this.getElementSelected(this.builder) + }, + menuItemVariants() { + return [ + { + label: this.$t('menuElementForm.menuItemVariantLink'), + value: LINK_VARIANTS.LINK, + }, + { + label: this.$t('menuElementForm.menuItemVariantButton'), + value: LINK_VARIANTS.BUTTON, + }, + ] + }, + }, + methods: { + /** + * Responsible for removing this menu item from the `MenuElement` itself. + */ + removeMenuItem() { + this.$emit('remove-item', this.values.uid) + }, + /** + * Responsible for removing a nested menu item from a parent menu item. + */ + removeChildItem(uidToRemove) { + this.values.children = this.values.children.filter( + (child) => child.uid !== uidToRemove + ) + }, + /** + * When a nested meny item is updated, this method is responsible for updating the + * parent menu item with the new values. + */ + updateChildItem(newValues) { + this.values.children = this.values.children.map((item) => { + if (item.uid === newValues.uid) { + return { ...item, ...newValues } + } + return item + }) + }, + /** + * If this menu item is a parent menu item, this method is responsible for + * adding a child menu item to it. + */ + addSubLink() { + const name = getNextAvailableNameInSequence( + this.$t('menuElementForm.menuItemSubLinkDefaultName'), + this.values.children.map(({ name }) => name) + ) + this.values.children.push({ + name, + variant: LINK_VARIANTS.LINK, + type: 'link', + uid: uuid(), + }) + }, + /** + * Responsible for sorting the child items of this menu item. + */ + orderChildItems(newOrder) { + const itemsByUid = Object.fromEntries( + this.values.children.map((item) => [item.uid, item]) + ) + this.values.children = newOrder.map((uid) => itemsByUid[uid]) + }, + }, + validations() { + return { + values: { + name: { + required: helpers.withMessage( + this.$t('error.requiredField'), + required + ), + }, + }, + } + }, +} +</script> diff --git a/web-frontend/modules/builder/components/elements/components/forms/general/RepeatElementForm.vue b/web-frontend/modules/builder/components/elements/components/forms/general/RepeatElementForm.vue index 694673ea7..60c8d9327 100644 --- a/web-frontend/modules/builder/components/elements/components/forms/general/RepeatElementForm.vue +++ b/web-frontend/modules/builder/components/elements/components/forms/general/RepeatElementForm.vue @@ -75,7 +75,7 @@ /> </FormGroup> <FormGroup - :label="$t('repeatElementForm.orientationLabel')" + :label="$t('orientations.label')" small-label required class="margin-bottom-2" @@ -132,11 +132,19 @@ <Checkbox :checked="isCollapsed" @input="emitToggleRepetitions($event)"> </Checkbox> </FormGroup> + <CustomStyle + v-model="values.styles" + style-key="header_button" + :config-block-types="['button']" + :theme="builder.theme" + :extra-args="{ noAlignment: true, noWidth: true }" + /> <FormGroup v-if="propertyOptionsAvailable" small-label class="margin-bottom-2" :label="$t('collectionElementForm.propertyOptionLabel')" + required > <PropertyOptionForm :default-values="element" @@ -170,6 +178,7 @@ import ServiceSchemaPropertySelector from '@baserow/modules/core/components/serv import DataSourceDropdown from '@baserow/modules/builder/components/dataSource/DataSourceDropdown.vue' import PropertyOptionForm from '@baserow/modules/builder/components/elements/components/forms/general/settings/PropertyOptionForm' import PaddingSelector from '@baserow/modules/builder/components/PaddingSelector' +import { ORIENTATIONS } from '@baserow/modules/builder/enums' const MAX_GAP_PX = 2000 @@ -254,13 +263,13 @@ export default { orientationOptions() { return [ { - label: this.$t('repeatElementForm.orientationVertical'), - value: 'vertical', + label: this.$t('orientations.vertical'), + value: ORIENTATIONS.VERTICAL, icon: 'iconoir-table-rows', }, { - label: this.$t('repeatElementForm.orientationHorizontal'), - value: 'horizontal', + label: this.$t('orientations.horizontal'), + value: ORIENTATIONS.HORIZONTAL, icon: 'iconoir-view-columns-3', }, ] diff --git a/web-frontend/modules/builder/components/elements/components/forms/general/SimpleContainerElementForm.vue b/web-frontend/modules/builder/components/elements/components/forms/general/SimpleContainerElementForm.vue new file mode 100644 index 000000000..9fbfc74dd --- /dev/null +++ b/web-frontend/modules/builder/components/elements/components/forms/general/SimpleContainerElementForm.vue @@ -0,0 +1,22 @@ +<template> + <form @submit.prevent @keydown.enter.prevent> + <p>{{ $t('simpleContainerElementForm.noConfigurationOptions') }}</p> + </form> +</template> + +<script> +import elementForm from '@baserow/modules/builder/mixins/elementForm' + +export default { + name: 'SimpleContainerElementForm', + mixins: [elementForm], + data() { + return { + values: { + styles: {}, + }, + allowedValues: ['styles'], + } + }, +} +</script> diff --git a/web-frontend/modules/builder/components/elements/components/forms/general/TableElementForm.vue b/web-frontend/modules/builder/components/elements/components/forms/general/TableElementForm.vue index c91a71629..10e60379b 100644 --- a/web-frontend/modules/builder/components/elements/components/forms/general/TableElementForm.vue +++ b/web-frontend/modules/builder/components/elements/components/forms/general/TableElementForm.vue @@ -200,7 +200,12 @@ </template> <p v-else>{{ $t('tableElementForm.selectSourceFirst') }}</p> </FormSection> - <FormGroup :label="$t('tableElementForm.orientation')" small-label required> + <FormGroup + :label="$t('orientations.label')" + small-label + required + class="margin-bottom-2" + > <DeviceSelector :device-type-selected="deviceTypeSelected" direction="row" @@ -210,25 +215,34 @@ <RadioButton v-model="values.orientation[deviceType.getType()]" icon="iconoir-view-columns-3" - :value="TABLE_ORIENTATION.HORIZONTAL" + :value="ORIENTATIONS.HORIZONTAL" > - {{ $t('tableElementForm.orientationHorizontal') }} + {{ $t('orientations.horizontal') }} </RadioButton> <RadioButton v-model="values.orientation[deviceType.getType()]" icon="iconoir-table-rows" - :value="TABLE_ORIENTATION.VERTICAL" + :value="ORIENTATIONS.VERTICAL" > - {{ $t('tableElementForm.orientationVertical') }} + {{ $t('orientations.vertical') }} </RadioButton> </template> </DeviceSelector> </FormGroup> + <CustomStyle + v-if="propertyOptionsAvailable" + v-model="values.styles" + style-key="header_button" + :config-block-types="['button']" + :theme="builder.theme" + :extra-args="{ noAlignment: true, noWidth: true }" + /> <FormGroup v-if="propertyOptionsAvailable" small-label - class="margin-top-2 margin-bottom-2" + class="margin-bottom-2" :label="$t('collectionElementForm.propertyOptionLabel')" + required > <PropertyOptionForm :default-values="element" @@ -258,7 +272,7 @@ import { helpers, } from '@vuelidate/validators' import collectionElementForm from '@baserow/modules/builder/mixins/collectionElementForm' -import { TABLE_ORIENTATION } from '@baserow/modules/builder/enums' +import { ORIENTATIONS } from '@baserow/modules/builder/enums' import DeviceSelector from '@baserow/modules/builder/components/page/header/DeviceSelector.vue' import { mapActions, mapGetters } from 'vuex' import CustomStyle from '@baserow/modules/builder/components/elements/components/forms/style/CustomStyle' @@ -304,8 +318,8 @@ export default { }, computed: { ...mapGetters({ deviceTypeSelected: 'page/getDeviceTypeSelected' }), - TABLE_ORIENTATION() { - return TABLE_ORIENTATION + ORIENTATIONS() { + return ORIENTATIONS }, orderedCollectionTypes() { return this.$registry.getOrderedList('collectionField') diff --git a/web-frontend/modules/builder/components/page/PageElement.vue b/web-frontend/modules/builder/components/page/PageElement.vue index 27ad05d0d..6a3309e8e 100644 --- a/web-frontend/modules/builder/components/page/PageElement.vue +++ b/web-frontend/modules/builder/components/page/PageElement.vue @@ -6,6 +6,9 @@ :style="elementStyles" > <div class="element__inner-wrapper"> + <span v-if="showElementId" class="element--element-id">{{ + element.id + }}</span> <component :is="component" :key="element._.uid" @@ -58,6 +61,11 @@ export default { required: false, default: null, }, + showElementId: { + type: Boolean, + required: false, + default: false, + }, }, computed: { BACKGROUND_TYPES: () => BACKGROUND_TYPES, diff --git a/web-frontend/modules/builder/components/page/PagePreview.vue b/web-frontend/modules/builder/components/page/PagePreview.vue index 4629408fc..ead7b01f6 100644 --- a/web-frontend/modules/builder/components/page/PagePreview.vue +++ b/web-frontend/modules/builder/components/page/PagePreview.vue @@ -28,6 +28,7 @@ :is-first-element="index === 0" :is-copying="copyingElementIndex === index" :application-context-additions="contextAdditions" + :show-element-id="showElementId" @move="moveElement($event)" /> </header> @@ -64,6 +65,7 @@ :is-first-element="index === 0 && headerElements.length === 0" :is-copying="copyingElementIndex === index" :application-context-additions="contextAdditions" + :show-element-id="showElementId" @move="moveElement($event)" /> </div> @@ -92,6 +94,7 @@ " :is-copying="copyingElementIndex === index" :application-context-additions="contextAdditions" + :show-element-id="showElementId" @move="moveElement($event)" /> </footer> @@ -129,6 +132,8 @@ export default { // The resize observer to resize the preview when the wrapper size change resizeObserver: null, + + showElementId: false, } }, computed: { @@ -505,6 +510,11 @@ export default { case 'p': this.selectParentElement() break + case 'E': + if (alternateAction && e.shiftKey) { + this.showElementId = !this.showElementId + } + break default: shouldPrevent = false } diff --git a/web-frontend/modules/builder/components/page/header/PublishActionModal.vue b/web-frontend/modules/builder/components/page/header/PublishActionModal.vue index e9a83f1c7..46cbb5cb0 100644 --- a/web-frontend/modules/builder/components/page/header/PublishActionModal.vue +++ b/web-frontend/modules/builder/components/page/header/PublishActionModal.vue @@ -14,11 +14,12 @@ :key="domain.id" class="publish-action-modal__container" > - <Radio v-model="selectedDomain" :value="domain.id"> + <Radio v-model="selectedDomainId" :value="domain.id"> <span class="publish-action-modal__domain-name">{{ domain.domain_name }}</span> <a + v-if="domain.last_published" v-tooltip="$t('action.copyToClipboard')" class="publish-action-modal__copy-domain" tooltip-position="top" @@ -30,6 +31,7 @@ <Copied ref="domainCopied" /> </a> <a + v-if="domain.last_published" v-tooltip="$t('publishActionModal.openInNewTab')" tooltip-position="top" class="publish-action-modal__domain-link" @@ -46,6 +48,7 @@ /> </div> </template> + <div v-else-if="fetchingDomains" class="loading-spinner"></div> <p v-else>{{ $t('publishActionModal.noDomain') }}</p> </template> @@ -54,6 +57,11 @@ $t('publishActionModal.publishSucceedTitle') }}</template> <p>{{ $t('publishActionModal.publishSucceedDescription') }}</p> + <template #actions> + <Button tag="a" :href="getDomainUrl(selectedDomain)" target="_blank">{{ + $t('publishActionModal.publishSucceedLink') + }}</Button> + </template> </Alert> <div class="modal-progress__actions"> @@ -64,13 +72,24 @@ /> <div class="align-right"> <Button + v-if="domains.length" size="large" :loading="jobIsRunning || loading" - :disabled="loading || jobIsRunning || !selectedDomain" + :disabled="loading || jobIsRunning || !selectedDomainId" @click="publishSite()" > {{ $t('publishActionModal.publish') }} </Button> + <template v-else-if="!fetchingDomains"> + <Button tag="a" @click="openDomainSettings"> + {{ $t('publishActionModal.addDomain') }} + </Button> + </template> + <BuilderSettingsModal + ref="domainSettingsModal" + hide-after-create + :builder="builder" + /> </div> </div> </Modal> @@ -85,10 +104,12 @@ import PublishedDomainService from '@baserow/modules/builder/services/publishedB import { notifyIf } from '@baserow/modules/core/utils/error' import { copyToClipboard } from '@baserow/modules/database/utils/clipboard' import LastPublishedDomainDate from '@baserow/modules/builder/components/domain/LastPublishedDomainDate' +import BuilderSettingsModal from '@baserow/modules/builder/components/settings/BuilderSettingsModal' +import { DomainsBuilderSettingsType } from '@baserow/modules/builder/builderSettingTypes' export default { name: 'PublishActionModal', - components: { LastPublishedDomainDate }, + components: { BuilderSettingsModal, LastPublishedDomainDate }, mixins: [modal, error, jobProgress], props: { builder: { @@ -97,15 +118,23 @@ export default { }, }, data() { - return { selectedDomain: null, loading: false } + return { selectedDomainId: null, loading: false, fetchingDomains: false } }, computed: { ...mapGetters({ domains: 'domain/getDomains' }), + selectedDomain() { + return this.domains.find((domain) => domain.id === this.selectedDomainId) + }, }, watch: { - selectedDomain() { + selectedDomainId() { this.job = null }, + domains() { + if (!this.selectedDomainId) { + this.selectedDomainId = this.domains.length ? this.domains[0].id : null + } + }, }, beforeDestroy() { this.stopPollIfRunning() @@ -119,19 +148,22 @@ export default { this.hideError() this.job = null this.loading = false - this.selectedDomain = null + this.selectedDomainId = null + this.fetchingDomains = true try { await this.actionFetchDomains({ builderId: this.builder.id }) this.hideError() } catch (error) { this.handleError(error) + } finally { + this.fetchingDomains = false } }, async publishSite() { this.loading = true this.hideError() const { data: job } = await PublishedDomainService(this.$client).publish({ - id: this.selectedDomain, + id: this.selectedDomainId, }) this.startJobPoller(job) @@ -145,7 +177,7 @@ export default { }, onJobDone() { this.actionForceUpdateDomain({ - domainId: this.selectedDomain, + domainId: this.selectedDomainId, values: { last_published: new Date() }, }) this.loading = false @@ -169,6 +201,15 @@ export default { } return '' }, + openDomainSettings() { + // Open the builder settings modal, which is instructed to select the domain + // settings instance first, and pass `DomainsBuilderSettingsType.getType()` into + // `show` so that the create domain form is immediately presented. + this.$refs.domainSettingsModal.show( + DomainsBuilderSettingsType.getType(), + true + ) + }, }, } </script> diff --git a/web-frontend/modules/builder/components/page/settings/PageSettingsQueryParamsFormElement.vue b/web-frontend/modules/builder/components/page/settings/PageSettingsQueryParamsFormElement.vue index faae03e6d..b527f8b34 100644 --- a/web-frontend/modules/builder/components/page/settings/PageSettingsQueryParamsFormElement.vue +++ b/web-frontend/modules/builder/components/page/settings/PageSettingsQueryParamsFormElement.vue @@ -30,6 +30,7 @@ </Dropdown> </div> <ButtonIcon + tag="a" class="filters__remove page-settings-query-params__remove" icon="iconoir-bin" @click="deleteQueryParam(index)" diff --git a/web-frontend/modules/builder/components/settings/BuilderSettingsModal.vue b/web-frontend/modules/builder/components/settings/BuilderSettingsModal.vue index bd1bfca49..09232bf86 100644 --- a/web-frontend/modules/builder/components/settings/BuilderSettingsModal.vue +++ b/web-frontend/modules/builder/components/settings/BuilderSettingsModal.vue @@ -26,7 +26,14 @@ </ul> </template> <template v-if="settingSelected" #content> - <component :is="settingSelected.component" :builder="builder"></component> + <component + :is="settingSelected.component" + ref="settingSelected" + :builder="builder" + :hide-after-create="hideAfterCreate" + :force-display-form="displaySelectedSettingForm" + @hide-modal="emitCreatedRecord($event)" + ></component> </template> </Modal> </template> @@ -43,10 +50,20 @@ export default { type: Object, required: true, }, + /** + * If you want the selected setting form to hide the builder settings modal + * after a record is created, set this to `true`. + */ + hideAfterCreate: { + type: Boolean, + required: false, + default: false, + }, }, data() { return { settingSelected: null, + displaySelectedSettingForm: false, } }, computed: { @@ -54,12 +71,44 @@ export default { return this.$registry.getOrderedList('builderSettings') }, }, + watch: { + // When the selected setting changes, and we've forcibly displayed + // the selected setting's form, then reset the display flag so that + // the next setting doesn't immediately display its form. + settingSelected(newSetting, oldSetting) { + if ( + oldSetting && + newSetting !== oldSetting && + this.displaySelectedSettingForm + ) { + this.displaySelectedSettingForm = false + } + }, + }, methods: { - show(...args) { + show( + selectSettingType = null, + displaySelectedSettingForm = false, + ...args + ) { + // If we've been instructed to show a specific setting component, + // then ensure it's displayed first. + if (selectSettingType) { + this.settingSelected = this.$registry.get( + 'builderSettings', + selectSettingType + ) + } + + // If no `selectSettingType` was provided then choose the first setting. if (!this.settingSelected) { this.settingSelected = this.registeredSettings[0] } + // If we've been instructed to show the modal, and make the + // selected setting component's form display, then do so. + this.displaySelectedSettingForm = displaySelectedSettingForm + const builderApplicationType = this.$registry.get( 'application', BuilderApplicationType.getType() @@ -68,6 +117,17 @@ export default { return modal.methods.show.call(this, ...args) }, + /** + * If this modal is being used with the `hideAfterCreate` prop set to `true`, + * then once a record has been created, we want to hide the modal, and then + * emit the newly created record ID so that it can be used by the component + * implementing this modal. + * @param createdRecordId - The ID of the newly created record. + */ + emitCreatedRecord(createdRecordId) { + this.hide() + this.$emit('created', createdRecordId) + }, }, } </script> diff --git a/web-frontend/modules/builder/components/settings/DomainsSettings.vue b/web-frontend/modules/builder/components/settings/DomainsSettings.vue index 05c596104..30322b53e 100644 --- a/web-frontend/modules/builder/components/settings/DomainsSettings.vue +++ b/web-frontend/modules/builder/components/settings/DomainsSettings.vue @@ -28,7 +28,12 @@ {{ $t('domainSettings.noDomainMessage') }} </p> </div> - <DomainForm v-else :builder="builder" :hide-form="hideForm" /> + <DomainForm + v-else + :builder="builder" + :hide-form="hideForm" + @created="hideModalIfRequired" + /> </template> <script> @@ -36,22 +41,12 @@ import { mapActions, mapGetters } from 'vuex' import error from '@baserow/modules/core/mixins/error' import DomainCard from '@baserow/modules/builder/components/domain/DomainCard' import DomainForm from '@baserow/modules/builder/components/domain/DomainForm' +import builderSetting from '@baserow/modules/builder/components/settings/mixins/builderSetting' export default { name: 'DomainsSettings', components: { DomainCard, DomainForm }, - mixins: [error], - props: { - builder: { - type: Object, - required: true, - }, - }, - data() { - return { - showForm: false, - } - }, + mixins: [error, builderSetting], async fetch() { try { await this.actionFetchDomains({ builderId: this.builder.id }) diff --git a/web-frontend/modules/builder/components/settings/UserSourcesSettings.vue b/web-frontend/modules/builder/components/settings/UserSourcesSettings.vue index 2b52f543e..9513da378 100644 --- a/web-frontend/modules/builder/components/settings/UserSourcesSettings.vue +++ b/web-frontend/modules/builder/components/settings/UserSourcesSettings.vue @@ -1,13 +1,13 @@ <template> <!-- Show user source list --> <div - v-if="!showCreateForm && editedUserSource === null" + v-if="!showForm && editedUserSource === null" class="user-sources-settings" > <h2 class="box__title">{{ $t('userSourceSettings.titleOverview') }}</h2> <Error :error="error"></Error> <div v-if="!error.visible" class="actions actions--right"> - <Button icon="iconoir-plus" @click="showForm()"> + <Button icon="iconoir-plus" @click="displayForm()"> {{ $t('userSourceSettings.addUserSource') }} </Button> </div> @@ -26,7 +26,7 @@ style="flex: 1" /> <div class="user-source-settings__user-source-actions"> - <ButtonIcon icon="iconoir-edit" @click="showForm(userSource)" /> + <ButtonIcon icon="iconoir-edit" @click="displayForm(userSource)" /> <ButtonIcon icon="iconoir-bin" @click="deleteUserSource(userSource)" /> </div> </div> @@ -116,23 +116,18 @@ import { clone } from '@baserow/modules/core/utils/object' import { notifyIf } from '@baserow/modules/core/utils/error' import CreateUserSourceForm from '@baserow/modules/builder/components/userSource/CreateUserSourceForm' import UpdateUserSourceForm from '@baserow/modules/builder/components/userSource/UpdateUserSourceForm' +import builderSetting from '@baserow/modules/builder/components/settings/mixins/builderSetting' export default { name: 'UserSourceSettings', components: { CreateUserSourceForm, UpdateUserSourceForm }, - mixins: [error], + mixins: [error, builderSetting], provide() { return { builder: this.builder } }, - props: { - builder: { - type: Object, - required: true, - }, - }, data() { return { - showCreateForm: false, + showForm: false, editedUserSource: null, actionInProgress: false, invalidForm: true, @@ -145,9 +140,6 @@ export default { userSources() { return this.$store.getters['userSource/getUserSources'](this.builder) }, - userSourceTypes() { - return this.$registry.getAll('userSource') - }, }, async mounted() { try { @@ -174,17 +166,17 @@ export default { onValueChange() { this.invalidForm = !this.$refs.userSourceForm.isFormValid() }, - async showForm(userSourceToEdit) { + async displayForm(userSourceToEdit) { if (userSourceToEdit) { this.editedUserSource = userSourceToEdit } else { - this.showCreateForm = true + this.showForm = true } await this.$nextTick() this.onValueChange() }, hideForm() { - this.showCreateForm = false + this.showForm = false this.editedUserSource = null this.hideError() this.invalidForm = true @@ -219,6 +211,11 @@ export default { userSourceId: this.editedUserSource.id, values: clone(newValues), }) + // If the builder settings modal is set to hide after create, normally + // we would have hidden the modal and shared the record ID after the user + // source was created, but in this settings component we'll share the ID + // after the update, when there's a better change of having a configure source. + this.hideModalIfRequired(this.editedUserSource.id) this.hideForm() } catch (error) { // Restore the previously saved values from the store diff --git a/web-frontend/modules/builder/components/settings/mixins/builderSetting.js b/web-frontend/modules/builder/components/settings/mixins/builderSetting.js new file mode 100644 index 000000000..f686b87d8 --- /dev/null +++ b/web-frontend/modules/builder/components/settings/mixins/builderSetting.js @@ -0,0 +1,41 @@ +/** + * A mixin for the builder setting components which have forms. This mixin makes + * it easier to make them immediately display their "create" form from the parent + * builder settings modal. When `force-display-form` is set, the end-user doesn't + * have to click a "New" button. + */ +export default { + props: { + builder: { + type: Object, + required: true, + }, + forceDisplayForm: { + type: Boolean, + required: false, + default: false, + }, + hideAfterCreate: { + type: Boolean, + required: false, + default: false, + }, + }, + data() { + return { + showForm: false, + } + }, + mounted() { + if (this.forceDisplayForm) { + this.showForm = true + } + }, + methods: { + hideModalIfRequired(createdRecordId) { + if (this.hideAfterCreate) { + this.$emit('hide-modal', createdRecordId) + } + }, + }, +} diff --git a/web-frontend/modules/builder/components/theme/ButtonThemeConfigBlock.vue b/web-frontend/modules/builder/components/theme/ButtonThemeConfigBlock.vue index 425a05294..0d8955044 100644 --- a/web-frontend/modules/builder/components/theme/ButtonThemeConfigBlock.vue +++ b/web-frontend/modules/builder/components/theme/ButtonThemeConfigBlock.vue @@ -3,6 +3,7 @@ <ThemeConfigBlockSection> <template #default> <FormGroup + v-if="!extraArgs?.noWidth" horizontal-narrow small-label required @@ -37,7 +38,9 @@ </template> </FormGroup> <FormGroup - v-if="v$.values.button_width.$model === 'full'" + v-if=" + v$.values.button_width.$model === 'full' && !extraArgs?.noAlignment + " horizontal-narrow small-label required @@ -75,7 +78,7 @@ :label="$t('buttonThemeConfigBlock.weight')" > <FontWeightSelector - v-model="values.button_font_weight" + v-model="v$.values.button_font_weight.$model" :font="values.button_font_family" /> <template #after-input> @@ -226,14 +229,14 @@ :label="$t('buttonThemeConfigBlock.borderColor')" > <ColorInput - v-model="values.button_border_color" + v-model="v$.values.button_border_color.$model" :color-variables="colorVariables" :default-value="theme?.button_border_color" small /> <template #after-input> <ResetButton - v-model="values.button_border_color" + v-model="v$.values.button_border_color.$model" :default-value="theme?.button_border_color" /> </template> @@ -310,6 +313,73 @@ </ABButton> </template> </ThemeConfigBlockSection> + <ThemeConfigBlockSection :title="$t('buttonThemeConfigBlock.activeState')"> + <template #default> + <FormGroup + horizontal-narrow + small-label + required + class="margin-bottom-2" + :label="$t('buttonThemeConfigBlock.backgroundColor')" + > + <ColorInput + v-model="v$.values.button_active_background_color.$model" + :color-variables="colorVariables" + :default-value="theme?.button_active_background_color" + small + /> + <template #after-input> + <ResetButton + v-model="v$.values.button_active_background_color.$model" + :default-value="theme?.button_active_background_color" + /> + </template> + </FormGroup> + <FormGroup + horizontal-narrow + small-label + class="margin-bottom-2" + :label="$t('buttonThemeConfigBlock.textColor')" + > + <ColorInput + v-model="v$.values.button_active_text_color.$model" + :color-variables="colorVariables" + :default-value="theme?.button_active_text_color" + small + /> + <template #after-input> + <ResetButton + v-model="v$.values.button_active_text_color.$model" + :default-value="theme?.button_active_text_color" + /> + </template> + </FormGroup> + <FormGroup + horizontal-narrow + small-label + class="margin-bottom-2" + :label="$t('buttonThemeConfigBlock.borderColor')" + > + <ColorInput + v-model="v$.values.button_active_border_color.$model" + :color-variables="colorVariables" + :default-value="theme?.button_active_border_color" + small + /> + <template #after-input> + <ResetButton + v-model="v$.values.button_active_border_color.$model" + :default-value="theme?.button_active_border_color" + /> + </template> + </FormGroup> + </template> + <template #preview> + <ABButton class="ab-button--force-active"> + {{ $t('buttonThemeConfigBlock.button') }} + </ABButton> + </template> + </ThemeConfigBlockSection> </div> </template> @@ -386,9 +456,11 @@ export default { button_font_size: this.theme?.button_font_size, button_border_size: this.theme?.button_border_size, button_border_radius: this.theme?.button_border_radius, + button_border_color: this.theme?.button_border_color, button_horizontal_padding: this.theme?.button_horizontal_padding, button_vertical_padding: this.theme?.button_vertical_padding, button_font_family: this.theme?.button_font_family, + button_font_weight: this.theme?.button_font_weight, button_text_alignment: this.theme?.button_text_alignment, button_alignment: this.theme?.button_alignment, button_text_color: this.theme?.button_text_color, @@ -398,6 +470,10 @@ export default { this.theme?.button_hover_background_color, button_hover_text_color: this.theme?.button_hover_text_color, button_hover_border_color: this.theme?.button_hover_border_color, + button_active_background_color: + this.theme?.button_active_background_color, + button_active_text_color: this.theme?.button_active_text_color, + button_active_border_color: this.theme?.button_active_border_color, }, } }, @@ -551,8 +627,13 @@ export default { button_background_color: {}, button_hover_background_color: {}, button_hover_text_color: {}, + button_border_color: {}, button_hover_border_color: {}, + button_active_background_color: {}, + button_active_text_color: {}, + button_active_border_color: {}, button_font_family: {}, + button_font_weight: {}, button_text_color: {}, button_text_alignment: {}, button_alignment: {}, diff --git a/web-frontend/modules/builder/components/theme/ColorThemeConfigBlock.vue b/web-frontend/modules/builder/components/theme/ColorThemeConfigBlock.vue index 242c2db82..4f73878eb 100644 --- a/web-frontend/modules/builder/components/theme/ColorThemeConfigBlock.vue +++ b/web-frontend/modules/builder/components/theme/ColorThemeConfigBlock.vue @@ -51,6 +51,44 @@ <ColorInput v-model="v$.values.main_error_color.$model" small /> </FormGroup> </template> + <template #preview> + <div + class="color-theme-config-block__color-preview margin-bottom-1" + :style="{ + '--preview-color': 'var(--main-primary-color)', + }" + /> + <div + class="color-theme-config-block__color-preview margin-bottom-1" + :style="{ + '--preview-color': 'var(--main-secondary-color)', + }" + /> + <div + class="color-theme-config-block__color-preview margin-bottom-1" + :style="{ + '--preview-color': 'var(--main-border-color)', + }" + /> + <div + class="color-theme-config-block__color-preview margin-bottom-1" + :style="{ + '--preview-color': 'var(--main-success-color)', + }" + /> + <div + class="color-theme-config-block__color-preview margin-bottom-1" + :style="{ + '--preview-color': 'var(--main-warning-color)', + }" + /> + <div + class="color-theme-config-block__color-preview margin-bottom-1" + :style="{ + '--preview-color': 'var(--main-error-color)', + }" + /> + </template> </ThemeConfigBlockSection> <ThemeConfigBlockSection :title="$t('colorThemeConfigBlock.customColors')"> @@ -74,6 +112,16 @@ </ButtonText> </div> </template> + <template #preview> + <div + v-for="customColor in values.custom_colors" + :key="customColor.value" + class="color-theme-config-block__color-preview margin-bottom-1" + :style="{ + '--preview-color': customColor.color, + }" + /> + </template> </ThemeConfigBlockSection> </div> </template> @@ -136,7 +184,6 @@ export default { * doesn't duplicate the name of an existing custom color. */ addCustomColor() { - console.log('addCustomColor') // To avoid duplicating names, newColorId is incremented until an unused // value is found. const existingNames = this.values.custom_colors.map((color) => color.name) diff --git a/web-frontend/modules/builder/components/theme/LinkThemeConfigBlock.vue b/web-frontend/modules/builder/components/theme/LinkThemeConfigBlock.vue index 3865049b2..d3faf71c0 100644 --- a/web-frontend/modules/builder/components/theme/LinkThemeConfigBlock.vue +++ b/web-frontend/modules/builder/components/theme/LinkThemeConfigBlock.vue @@ -99,6 +99,22 @@ /> </template> </FormGroup> + <FormGroup + horizontal-narrow + small-label + class="margin-bottom-2" + :label="$t('linkThemeConfigBlock.decoration')" + > + <TextDecorationSelector + v-model="values.link_default_text_decoration" + /> + <template #after-input> + <ResetButton + v-model="values.link_default_text_decoration" + :default-value="theme?.link_default_text_decoration" + /> + </template> + </FormGroup> </template> <template #preview> <ABLink url="">{{ $t('linkThemeConfigBlock.link') }}</ABLink> @@ -126,6 +142,20 @@ /> </template> </FormGroup> + <FormGroup + horizontal-narrow + small-label + class="margin-bottom-2" + :label="$t('linkThemeConfigBlock.decoration')" + > + <TextDecorationSelector v-model="values.link_hover_text_decoration" /> + <template #after-input> + <ResetButton + v-model="values.link_hover_text_decoration" + :default-value="theme?.link_hover_text_decoration" + /> + </template> + </FormGroup> </template> <template #preview> <ABLink url="" class="ab-link--force-hover"> @@ -133,6 +163,51 @@ </ABLink> </template> </ThemeConfigBlockSection> + <ThemeConfigBlockSection :title="$t('linkThemeConfigBlock.activeState')"> + <template #default> + <FormGroup + horizontal-narrow + small-label + required + class="margin-bottom-2" + :label="$t('linkThemeConfigBlock.color')" + > + <ColorInput + v-model="v$.values.link_active_text_color.$model" + :color-variables="colorVariables" + :default-value="theme?.link_active_text_color" + small + /> + <template #after-input> + <ResetButton + v-model="v$.values.link_active_text_color.$model" + :default-value="theme?.link_active_text_color" + /> + </template> + </FormGroup> + <FormGroup + horizontal-narrow + small-label + class="margin-bottom-2" + :label="$t('linkThemeConfigBlock.decoration')" + > + <TextDecorationSelector + v-model="values.link_active_text_decoration" + /> + <template #after-input> + <ResetButton + v-model="values.link_active_text_decoration" + :default-value="theme?.link_active_text_decoration" + /> + </template> + </FormGroup> + </template> + <template #preview> + <ABLink url="" class="ab-link--force-active"> + {{ $t('linkThemeConfigBlock.link') }} + </ABLink> + </template> + </ThemeConfigBlockSection> </form> </template> @@ -145,6 +220,7 @@ import HorizontalAlignmentsSelector from '@baserow/modules/builder/components/Ho import FontFamilySelector from '@baserow/modules/builder/components/FontFamilySelector' import FontWeightSelector from '@baserow/modules/builder/components/FontWeightSelector' import PixelValueSelector from '@baserow/modules/builder/components/PixelValueSelector' +import TextDecorationSelector from '@baserow/modules/builder/components/TextDecorationSelector' import { required, integer, @@ -170,6 +246,7 @@ export default { FontFamilySelector, FontWeightSelector, PixelValueSelector, + TextDecorationSelector, }, mixins: [themeConfigBlock], setup() { @@ -193,9 +270,13 @@ export default { link_text_color: this.theme?.link_text_color, link_text_alignment: this.theme?.link_text_alignment, link_hover_text_color: this.theme?.link_hover_text_color, + link_active_text_color: this.theme?.link_active_text_color, link_font_family: this.theme?.link_font_family, link_font_weight: this.theme?.link_font_weight, link_font_size: this.theme?.link_font_size, + link_default_text_decoration: this.theme?.link_default_text_decoration, + link_hover_text_decoration: this.theme?.link_hover_text_decoration, + link_active_text_decoration: this.theme?.link_active_text_decoration, }, } }, @@ -234,8 +315,12 @@ export default { link_text_color: {}, link_text_alignment: {}, link_hover_text_color: {}, + link_active_text_color: {}, link_font_family: {}, link_font_weight: {}, + link_default_text_decoration: {}, + link_hover_text_decoration: {}, + link_active_text_decoration: {}, }, } }, diff --git a/web-frontend/modules/builder/components/theme/ThemeConfigBlockSection.vue b/web-frontend/modules/builder/components/theme/ThemeConfigBlockSection.vue index 95cd03e77..6f4f727f9 100644 --- a/web-frontend/modules/builder/components/theme/ThemeConfigBlockSection.vue +++ b/web-frontend/modules/builder/components/theme/ThemeConfigBlockSection.vue @@ -17,7 +17,7 @@ <div class="theme-config-block-section__properties"> <slot></slot> </div> - <div class="theme-config-block-section__preview"> + <div v-if="hasSlotPreview" class="theme-config-block-section__preview"> <slot name="preview"></slot> </div> </div> @@ -35,5 +35,10 @@ export default { default: null, }, }, + computed: { + hasSlotPreview() { + return !!this.$slots.preview + }, + }, } </script> diff --git a/web-frontend/modules/builder/components/theme/TypographyThemeConfigBlock.vue b/web-frontend/modules/builder/components/theme/TypographyThemeConfigBlock.vue index bbb1c657b..939e030f9 100644 --- a/web-frontend/modules/builder/components/theme/TypographyThemeConfigBlock.vue +++ b/web-frontend/modules/builder/components/theme/TypographyThemeConfigBlock.vue @@ -11,10 +11,10 @@ class="margin-bottom-2" :label="$t('typographyThemeConfigBlock.fontFamily')" > - <FontFamilySelector v-model="values.body_font_family" /> + <FontFamilySelector v-model="v$.values.body_font_family.$model" /> <template #after-input> <ResetButton - v-model="values.body_font_family" + v-model="v$.values.body_font_family.$model" :default-value="theme?.body_font_family" /> </template> @@ -26,13 +26,13 @@ :label="$t('typographyThemeConfigBlock.weight')" > <FontWeightSelector - v-model="values.body_font_weight" - :font="values.body_font_family" + v-model="v$.values.body_font_weight.$model" + :font="v$.values.body_font_family.$model" /> <template #after-input> <ResetButton v-if="values.body_font_family === theme?.body_font_family" - v-model="values.body_font_weight" + v-model="v$.values.body_font_weight.$model" :default-value="theme?.body_font_weight" /> </template> @@ -72,20 +72,6 @@ /> </template> </FormGroup> - <FormGroup - horizontal-narrow - small-label - class="margin-bottom-2" - :label="$t('typographyThemeConfigBlock.textAlignment')" - > - <HorizontalAlignmentsSelector v-model="values.body_text_alignment" /> - <template #after-input> - <ResetButton - v-model="values.body_text_alignment" - :default-value="theme?.body_text_alignment" - /> - </template> - </FormGroup> <FormGroup horizontal-narrow small-label @@ -218,6 +204,20 @@ /> </template> </FormGroup> + <FormGroup + horizontal-narrow + small-label + class="margin-bottom-2" + :label="$t('typographyThemeConfigBlock.decoration')" + > + <TextDecorationSelector + v-model="values[`heading_${level}_text_decoration`]" /> + <template #after-input> + <ResetButton + v-model="values[`heading_${level}_text_decoration`]" + :default-value="theme?.[`heading_${level}_text_decoration`]" + /> </template + ></FormGroup> </template> <template #preview> <ABHeading @@ -248,6 +248,7 @@ import HorizontalAlignmentsSelector from '@baserow/modules/builder/components/Ho import FontFamilySelector from '@baserow/modules/builder/components/FontFamilySelector' import FontWeightSelector from '@baserow/modules/builder/components/FontWeightSelector' import PixelValueSelector from '@baserow/modules/builder/components/PixelValueSelector' +import TextDecorationSelector from '@baserow/modules/builder/components/TextDecorationSelector' import { DEFAULT_FONT_SIZE_PX } from '@baserow/modules/builder/defaultStyles' const fontSizeMin = 1 @@ -264,6 +265,7 @@ export default { FontFamilySelector, FontWeightSelector, PixelValueSelector, + TextDecorationSelector, }, mixins: [themeConfigBlock], setup() { @@ -274,13 +276,16 @@ export default { values: { body_font_size: 0, body_text_color: '', + body_font_weight: '', body_font_family: '', body_text_alignment: '', ...headings.reduce((o, i) => { o[`heading_${i}_font_size`] = 0 o[`heading_${i}_text_color`] = '' o[`heading_${i}_font_family`] = '' + o[`heading_${i}_font_weight`] = '' o[`heading_${i}_text_alignment`] = '' + o[`heading_${i}_text_decoration`] = [false, false, false] return o }, {}), }, @@ -363,6 +368,8 @@ export default { maxValue(bodyFontSizeMax) ), }, + body_font_family: {}, + body_font_weight: {}, }, } }, diff --git a/web-frontend/modules/builder/components/userSource/UpdateUserSourceForm.vue b/web-frontend/modules/builder/components/userSource/UpdateUserSourceForm.vue index 93255ea75..2eb0cad00 100644 --- a/web-frontend/modules/builder/components/userSource/UpdateUserSourceForm.vue +++ b/web-frontend/modules/builder/components/userSource/UpdateUserSourceForm.vue @@ -147,7 +147,9 @@ export default { ) }, appAuthProviderTypes() { - return this.$registry.getOrderedList('appAuthProvider') + return this.$registry + .getOrderedList('appAuthProvider') + .filter((type) => !type.isDeactivated(this.builder.workspace.id)) }, appAuthProviderPerTypes() { return Object.fromEntries( diff --git a/web-frontend/modules/builder/components/userSource/UserSourceDropdown.vue b/web-frontend/modules/builder/components/userSource/UserSourceDropdown.vue new file mode 100644 index 000000000..16f31253e --- /dev/null +++ b/web-frontend/modules/builder/components/userSource/UserSourceDropdown.vue @@ -0,0 +1,68 @@ +<template> + <div> + <Dropdown + :value="value" + fixed-items + show-footer + :show-search="false" + @input="$emit('input', $event)" + > + <DropdownItem + v-for="userSource in userSources" + :key="userSource.id" + :name="userSource.name" + :value="userSource.id" + /> + <template #emptyState> + <slot name="emptyState"> + {{ $t('userSourceDropdown.noUserSources') }} + </slot> + </template> + <template #footer> + <a class="select__footer-button" @click="openUserSettings"> + <i class="iconoir-plus"></i> + {{ $t('userSourceDropdown.addUserSource') }} + </a> + <BuilderSettingsModal + ref="userSourcesSettingsModal" + hide-after-create + :builder="builder" + @created="$emit('input', $event)" + /> + </template> + </Dropdown> + </div> +</template> + +<script> +import BuilderSettingsModal from '@baserow/modules/builder/components/settings/BuilderSettingsModal' +import { UserSourcesBuilderSettingsType } from '@baserow/modules/builder/builderSettingTypes' + +export default { + name: 'UserSourceDropdown', + components: { BuilderSettingsModal }, + props: { + value: { + type: Number, + required: false, + default: null, + }, + builder: { + type: Object, + required: true, + }, + userSources: { + type: Array, + required: true, + }, + }, + methods: { + openUserSettings() { + this.$refs.userSourcesSettingsModal.show( + UserSourcesBuilderSettingsType.getType(), + true + ) + }, + }, +} +</script> diff --git a/web-frontend/modules/builder/dataProviderTypes.js b/web-frontend/modules/builder/dataProviderTypes.js index 6840709f8..7cea464d4 100644 --- a/web-frontend/modules/builder/dataProviderTypes.js +++ b/web-frontend/modules/builder/dataProviderTypes.js @@ -313,10 +313,18 @@ export class PageParameterDataProviderType extends DataProviderType { const validators = queryParamNames.includes(name) ? QUERY_PARAM_TYPE_VALIDATION_FUNCTIONS : PAGE_PARAM_TYPE_VALIDATION_FUNCTIONS + let value + try { + value = validators[type](pageParamsValue[name]) + } catch { + // Skip setting the parameter if the user-provided value + // doesn't pass our parameter `type` validation. + return null + } return this.app.store.dispatch('pageParameter/setParameter', { page, name, - value: validators[type](pageParamsValue[name]), + value, }) }) ) diff --git a/web-frontend/modules/builder/elementTypes.js b/web-frontend/modules/builder/elementTypes.js index 7365a9b06..6a831fb53 100644 --- a/web-frontend/modules/builder/elementTypes.js +++ b/web-frontend/modules/builder/elementTypes.js @@ -37,6 +37,8 @@ import RuntimeFormulaContext from '@baserow/modules/core/runtimeFormulaContext' import { resolveFormula } from '@baserow/modules/core/formula' import FormContainerElement from '@baserow/modules/builder/components/elements/components/FormContainerElement.vue' import FormContainerElementForm from '@baserow/modules/builder/components/elements/components/forms/general/FormContainerElementForm.vue' +import SimpleContainerElement from '@baserow/modules/builder/components/elements/components/SimpleContainerElement.vue' +import SimpleContainerElementForm from '@baserow/modules/builder/components/elements/components/forms/general/SimpleContainerElementForm.vue' import ChoiceElement from '@baserow/modules/builder/components/elements/components/ChoiceElement.vue' import ChoiceElementForm from '@baserow/modules/builder/components/elements/components/forms/general/ChoiceElementForm.vue' import CheckboxElement from '@baserow/modules/builder/components/elements/components/CheckboxElement.vue' @@ -51,6 +53,8 @@ import MultiPageContainerElementForm from '@baserow/modules/builder/components/e import MultiPageContainerElement from '@baserow/modules/builder/components/elements/components/MultiPageContainerElement' import DateTimePickerElement from '@baserow/modules/builder/components/elements/components/DateTimePickerElement' import DateTimePickerElementForm from '@baserow/modules/builder/components/elements/components/forms/general/DateTimePickerElementForm' +import MenuElement from '@baserow/modules/builder/components/elements/components/MenuElement' +import MenuElementForm from '@baserow/modules/builder/components/elements/components/forms/general/MenuElementForm' import { pathParametersInError } from '@baserow/modules/builder/utils/params' import { ContainerElementTypeMixin, @@ -65,6 +69,10 @@ export class ElementType extends Registerable { return null } + category() { + return 'baseElement' + } + get description() { return null } @@ -695,6 +703,10 @@ export class FormContainerElementType extends ContainerElementTypeMixin( return 'form_container' } + category() { + return 'formElement' + } + get name() { return this.app.i18n.t('elementType.formContainer') } @@ -777,6 +789,10 @@ export class ColumnElementType extends ContainerElementTypeMixin(ElementType) { return 'column' } + category() { + return 'layoutElement' + } + get name() { return this.app.i18n.t('elementType.column') } @@ -842,11 +858,67 @@ export class ColumnElementType extends ContainerElementTypeMixin(ElementType) { } } +export class SimpleContainerElementType extends ContainerElementTypeMixin( + ElementType +) { + static getType() { + return 'simple_container' + } + + category() { + return 'layoutElement' + } + + get name() { + return this.app.i18n.t('elementType.simpleContainer') + } + + get description() { + return this.app.i18n.t('elementType.simpleContainerDescription') + } + + get iconClass() { + return 'iconoir-square' + } + + get component() { + return SimpleContainerElement + } + + get generalFormComponent() { + return SimpleContainerElementForm + } + + getDefaultValues(page, values) { + const superValues = super.getDefaultValues(page, values) + return { + ...superValues, + style_padding_left: 0, + style_padding_right: 0, + style_padding_top: 0, + style_padding_bottom: 0, + } + } + + getDefaultChildValues(page, values) { + // Unlike other container we don't want to affect the child padding. + return {} + } + + getElementPlaces(element) { + return [null] + } +} + export class TableElementType extends CollectionElementTypeMixin(ElementType) { static getType() { return 'table' } + category() { + return 'layoutElement' + } + get name() { return this.app.i18n.t('elementType.table') } @@ -915,6 +987,10 @@ export class RepeatElementType extends CollectionElementTypeMixin( return 'repeat' } + category() { + return 'layoutElement' + } + get name() { return this.app.i18n.t('elementType.repeat') } @@ -961,6 +1037,10 @@ export class FormElementType extends ElementType { return null } + category() { + return 'formElement' + } + /** * Given a form element, and a form data value, is responsible for validating * this form element type against that value. Returns whether the value is valid. @@ -1815,6 +1895,10 @@ export class HeaderElementType extends MultiPageElementTypeMixin( return 'header' } + category() { + return 'layoutElement' + } + get name() { return this.app.i18n.t('elementType.header') } @@ -1897,6 +1981,10 @@ export class FooterElementType extends HeaderElementType { return 'footer' } + category() { + return 'layoutElement' + } + getPagePlace() { return PAGE_PLACES.FOOTER } @@ -1957,3 +2045,108 @@ export class FooterElementType extends HeaderElementType { return null } } + +export class MenuElementType extends ElementType { + static getType() { + return 'menu' + } + + get name() { + return this.app.i18n.t('elementType.menu') + } + + get description() { + return this.app.i18n.t('elementType.menuDescription') + } + + get iconClass() { + return 'iconoir-menu' + } + + get component() { + return MenuElement + } + + get generalFormComponent() { + return MenuElementForm + } + + getEventByName(element, name) { + return this.getEvents(element).find((event) => event.name === name) + } + + getEvents(element) { + return (element.menu_items || []) + .map((item) => { + const { type: menuItemType, name, uid } = item + if (menuItemType === 'button') { + return [ + new ClickEvent({ + ...this.app, + namePrefix: uid, + labelSuffix: `- ${name}`, + applicationContextAdditions: { allowSameElement: true }, + }), + ] + } + return [] + }) + .flat() + } + + isInError({ page, element, builder }) { + // There must be at least one menu item + if (!element.menu_items?.length) { + return true + } + + const workflowActions = this.app.store.getters[ + 'workflowAction/getElementWorkflowActions' + ](page, element.id) + + const hasInvalidMenuItem = element.menu_items.some((menuItem) => { + if (menuItem.children?.length) { + return menuItem.children.some((child) => { + return this.menuItemIsInError(child, builder, workflowActions) + }) + } else { + return this.menuItemIsInError(menuItem, builder, workflowActions) + } + }) + + return hasInvalidMenuItem || super.isInError({ page, element, builder }) + } + + menuItemIsInError(element, builder, workflowActions) { + if (['separator', 'spacer'].includes(element.type)) { + return false + } else if (element.type === 'button') { + // For button variants, there must be at least one workflow action + return !element.name || !workflowActions.length + } else if (element.type === 'link') { + if (!element.name) { + return true + } + + if (!element.children?.length) { + if (element.navigation_type === 'page') { + if (!element.navigate_to_page_id) { + return true + } + return pathParametersInError( + element, + this.app.store.getters['page/getVisiblePages'](builder) + ) + } else if (element.navigation_type === 'custom') { + return !element.navigate_to_url + } + } + } + + return false + } + + getDisplayName(element, applicationContext) { + return this.name + } +} diff --git a/web-frontend/modules/builder/enums.js b/web-frontend/modules/builder/enums.js index c5a9fb4bc..2becef7dc 100644 --- a/web-frontend/modules/builder/enums.js +++ b/web-frontend/modules/builder/enums.js @@ -162,7 +162,7 @@ export const ELEMENT_EVENTS = { DATA_SOURCE_AFTER_UPDATE: 'DATA_SOURCE_AFTER_UPDATE', } -export const TABLE_ORIENTATION = { +export const ORIENTATIONS = { HORIZONTAL: 'horizontal', VERTICAL: 'vertical', } diff --git a/web-frontend/modules/builder/jobTypes.js b/web-frontend/modules/builder/jobTypes.js index ab1b5cebd..8fa1c5401 100644 --- a/web-frontend/modules/builder/jobTypes.js +++ b/web-frontend/modules/builder/jobTypes.js @@ -56,3 +56,13 @@ export class DuplicatePageJobType extends JobType { store.dispatch('job/forceDelete', job) } } + +export class PublishBuilderJobType extends JobType { + static getType() { + return 'publish_domain' + } + + getName() { + return 'publishDomain' + } +} diff --git a/web-frontend/modules/builder/locales/de.json b/web-frontend/modules/builder/locales/de.json index 792efadc8..c6b2b52ee 100644 --- a/web-frontend/modules/builder/locales/de.json +++ b/web-frontend/modules/builder/locales/de.json @@ -27,7 +27,13 @@ "pathParamsTitle": "Pfad-Parameter", "nameTitle": "Name", "pathParamsSubtitle": "Werden durch :parameter im Pfad definiert", - "pathParamsSubtitleTutorial": "Pfad-Parameter können verwendet werden, um Daten dynamisch zu laden, abhängig von dem angegebenen Parameter. Fügen Sie :parameter zum Pfad hinzu, um einen hinzuzufügen." + "pathParamsSubtitleTutorial": "Pfad-Parameter können verwendet werden, um Daten dynamisch zu laden, abhängig von dem angegebenen Parameter. Fügen Sie :parameter zum Pfad hinzu, um einen hinzuzufügen.", + "namePlaceholder": "Geben Sie einen Namen ein...", + "addAnotherParameter": "Einen weiteren Abfrageparameter hinzufügen", + "addParameter": "Einen Abfrageparameter hinzufügen", + "queryParamsSubtitleTutorial": "Abfrageparameter können verwendet werden, um Daten abhängig von dem angegebenen Parameter dynamisch zu laden.", + "pathPlaceholder": "Geben Sie einen Pfad ein...", + "queryParamsTitle": "Abfrageparameter" }, "builderSettingTypes": { "integrationsName": "Integrationen", @@ -68,7 +74,20 @@ "recordSelector": "Datensatz-Auswahl", "recordSelectorDescription": "Eine Bezugs-Datensatz-Auswahl", "choice": "Auswahl", - "choiceDescription": "Für die Auswahl einzelner/mehrerer Werte" + "choiceDescription": "Für die Auswahl einzelner/mehrerer Werte", + "dateTimePicker": "Datums- und Zeitauswahl", + "footerDescription": "Ein seitenübergreifend geteilter Container", + "headerDescription": "Ein seitenübergreifend geteilter Container", + "notAllowedUnlessTop": "Dieses Element ist nur im oberen Bereich der Seite erlaubt", + "notAllowedUnlessBottom": "Dieses Element ist nur im unteren Bereich der Seite erlaubt", + "footer": "Mehrseitiger Fussbereich", + "notAllowedUnlessFooter": "Dieses Element ist nur im Fussbereich der Seite erlaubt", + "notAllowedLocation": "Dieses Element ist an dieser Stelle nicht erlaubt", + "notAllowedInsideContainer": "Dieses Element ist nur außerhalb eines Containers erlaubt", + "notAllowedInsideSameType": "Dieses Element ist nicht in einem Container der gleichen Art erlaubt", + "dateTimePickerDescription": "Ein Eingabefeld für Datum und Zeit", + "header": "Mehrseitiger Kopfbereich", + "notAllowedUnlessHeader": "Dieses Element ist nur im Kopfbereich der Seite erlaubt" }, "addElementButton": { "label": "Element" @@ -85,12 +104,14 @@ }, "elementsContext": { "searchPlaceholder": "Elemente suchen", - "noElements": "Keine Elemente gefunden" + "noElements": "Keine Elemente gefunden", + "noPageElements": "Für diese Seite wurden keine Elemente gefunden" }, "addElementModal": { "title": "Neues Element hinzufügen", "searchPlaceholder": "Elemente suchen", - "disabledElementTooltip": "Innerhalb dieses Elements nicht verfügbar" + "disabledElementTooltip": "Innerhalb dieses Elements nicht verfügbar", + "elementInProgress": "Element wird hinzugefügt..." }, "elementMenu": { "moveUp": "Nach oben verschieben", @@ -104,13 +125,16 @@ "style": "Style", "visibility": "Sichtbarkeit", "events": "Ereignisse", - "eventsTabDeactivatedNoEvents": "Dieses Element unterstützt keinerlei Ereignisse" + "eventsTabDeactivatedNoEvents": "Dieses Element unterstützt keinerlei Ereignisse", + "eventsTabInError": "Eine oder mehrere Aktionen sind falsch konfiguriert." }, "emptySidePanelState": { "message": "Klicken Sie auf eines der Elemente, um weitere Details zu sehen" }, "headingElement": { - "noValue": "Kein Titel..." + "noValue": "Kein Titel...", + "missingValue": "Titel fehlt...", + "emptyValue": "Leerer Titel..." }, "headingElementForm": { "levelTitle": "Ebene", @@ -120,7 +144,9 @@ "textPlaceholder": "Text eingeben..." }, "textElement": { - "noValue": "Leerer Absatz..." + "noValue": "Leerer Absatz...", + "missingValue": "Fehlender Text...", + "emptyValue": "Leerer Text..." }, "textElementForm": { "textTitle": "Text", @@ -144,7 +170,8 @@ "errorUniquePathParams": "Pfad-Parameter müssen eindeutig sein.", "errorPathNotUnique": "Es existiert bereits ein Pfad mit diesem Namen", "errorValidPathCharacters": "Der Pfad enthält ungültige Zeichen", - "errorNameNotUnique": "Es existiert bereits eine Seite mit diesem Namen" + "errorNameNotUnique": "Es existiert bereits eine Seite mit diesem Namen", + "errorUniqueValidQueryParams": "Die Namen der Abfrageparameter müssen eindeutig und gültig sein." }, "publishActionModal": { "title": "Veröffentlichen", @@ -244,15 +271,24 @@ "namePlaceholder": "Quellenname", "servicePlaceholder": "Wählen Sie einen Dienst aus", "integrationPlaceholder": "Wählen Sie eine Integration aus", - "errorUniqueName": "Der Name der Datenquelle muss eindeutig sein." + "errorUniqueName": "Der Name der Datenquelle muss eindeutig sein.", + "nameLabel": "Name", + "actionLabel": "Aktion", + "integrationLabel": "Integration" }, "dataSourceContext": { "addDataSource": "Neue Datenquelle hinzufügen", - "noDataSourceTitle": "Diese Seite hat keine Datenquellen.", - "noDataSourceMessage": "Datenquellen können verwendet werden, um Daten aus internen oder externen Quellen abzurufen und auf der Seite anzuzeigen." + "noDataSourceTitle": "Sie haben noch keine Datenquellen hinzugefügt.", + "noDataSourceMessage": "Datenquellen können verwendet werden, um Daten aus internen oder externen Quellen abzurufen und auf der Seite anzuzeigen.", + "pageDataSourceTitle": "Für diese Seite", + "pageDataSourceDescription": "Wird abgerufen, wenn der Benutzer auf diese Seite navigiert.", + "sharedDataSourceTitle": "Zwischen Seiten geteilt", + "sharedDataSourceDescription": "Ist auf jeder Seite verfügbar und wird einmalig beim ersten Laden der Seite abgerufen." }, "imageElement": { - "emptyState": "Kein alternativer Text festgelegt..." + "emptyState": "Kein alternativer Text festgelegt...", + "emptyValue": "Leerer Alternativ-Text...", + "missingValue": "Fehlender Alternativ-Text..." }, "imageElementForm": { "fileSourceTypeURL": "URL", @@ -335,7 +371,11 @@ }, "publicPage": { "siteNotFound": "Seite nicht gefunden", - "pageNotFound": "Seite nicht gefunden" + "pageNotFound": "Seite nicht gefunden", + "loginToastTitle": "Authentifizierung erfolgreich", + "loginToastMessage": "Sie wurden erfolgreich eingeloggt.", + "authorizedToastTitle": "Authentifizierung erforderlich", + "authorizedToastMessage": "Sie müssen angemeldet sein, um auf diese Seite zugreifen zu können. Bitte loggen Sie sich ein, um fortzufahren." }, "defaultStyleForm": { "backgroundLabel": "Hintergrund", @@ -372,9 +412,15 @@ "addField": "Feld hinzufügen", "fieldType": "Typ", "itemsPerPagePlaceholder": "Wert eingeben...", - "selectSourceFirst": "Wählen Sie eine Listen-Datenquelle, um mit der Konfiguration Ihrer Felder zu beginnen.", + "selectSourceFirst": "Wählen Sie eine Datenquelle und/oder Eigenschaft, um mit der Konfiguration Ihrer Felder zu beginnen.", "buttonColor": "Buttonfarbe", - "refreshFieldsFromDataSource": "Felder aus der Datenquelle aktualisieren" + "refreshFieldsFromDataSource": "Felder aus der Datenquelle aktualisieren", + "orientation": "Ausrichtung", + "name": "Name", + "propertySelectorMissingArrays": "Keine Felder mit mehreren Werten gefunden, die als Zeilen verwendet werden können.", + "orientationHorizontal": "Horizontal", + "orientationVertical": "Vertikal", + "buttonLoadMoreLabel": "Mehr anzeigen-Beschriftung" }, "tableElement": { "empty": "Es wurden keine Elemente gefunden.", @@ -455,7 +501,9 @@ "embedPlaceholder": "Reiner HTML-Inhalt, der eingebettet werden soll", "heightLabel": "Höhe (px)", "heightPlaceholder": "Höhe in Pixeln", - "urlLabel": "URL" + "urlLabel": "URL", + "missingValue": "Fehlende IFrame-Quelle...", + "emptyValue": "Leere IFrame-Quelle..." }, "linkNavigationSelection": { "navigateToCustom": "Benutzerdefinierte URL", @@ -475,7 +523,9 @@ "integrationMessage": "Sie können neue Integrationen erstellen, indem Sie Datenquellen, Aktionen oder Benutzerauthentifizierungen hinzufügen." }, "pagePreview": { - "emptyMessage": "Anklicken, um das erste Element zu erstellen" + "emptyMessage": "Anklicken, um ein Element zu erstellen", + "footer": "FUSSBEREICH", + "header": "KOPFBEREICH" }, "inputTextElementForm": { "multilineTitle": "Mehrzeilig", @@ -495,10 +545,12 @@ "buttonElementForm": { "valuePlaceholder": "Text eingeben...", "buttonColor": "Buttonfarbe", - "valueLabel": "Text" + "valueLabel": "Button-Text" }, "buttonElement": { - "noValue": "Unbenannt..." + "noValue": "Unbenannt...", + "missingValue": "Fehlender Button-Text...", + "emptyValue": "Leerer Button-Text..." }, "eventTypes": { "clickLabel": "Bei Klick", @@ -543,7 +595,9 @@ "repeatElement": { "showMore": "Mehr anzeigen", "missingDataSourceTooltip": "Wählen Sie eine Datenquelle, um mit dem Hinzufügen von Elementen zu beginnen.", - "empty": "Es wurden keine Elemente gefunden." + "empty": "Es wurden keine Elemente gefunden.", + "emptyState": "Keine Einträge gefunden.", + "missingSchemaPropertyTooltip": "Wählen Sie eine Eigenschaft, um mit dem Hinzufügen von Elementen zu beginnen." }, "repeatElementForm": { "dataSource": "Datenquelle", @@ -620,7 +674,7 @@ "colorThemeConfigBlockType": { "primary": "Primär", "secondary": "Sekundär", - "border": "Umrandung", + "border": "Rahmen", "transparent": "Transparent", "warning": "Warnung", "success": "Erfolgreich", @@ -631,15 +685,170 @@ "secondaryColor": "Sekundär", "primaryColor": "Primär", "warningColor": "Warnung", - "borderColor": "Umrandung", + "borderColor": "Rahmen", "successColor": "Erfolgreich", - "errorColor": "Fehler" + "errorColor": "Fehler", + "customColors": "Benutzerdefinierte Farben", + "addCustomColor": "Benutzerdefinierte Farbe hinzufügen", + "customColorPrefix": "Benutzerdefiniert" }, "typographyThemeConfigBlock": { "headingValue": "Überschrift <h{i}>", "size": "Größe", "headingLabel": "Überschrift {i} (h{i})", "color": "Farbe", - "textAlignment": "Ausrichtung" + "textAlignment": "Ausrichtung", + "weight": "Gewicht", + "bodyLabel": "Body", + "fontFamily": "Schriftart" + }, + "common": { + "timeFormatTitle": "Zeitformat", + "dateFormatTitle": "Datumsformat", + "dateFormatEU": "Europäisch", + "dateFormatUS": "US-amerikanisch", + "dateFormatISO": "ISO-Format", + "timeFormat24Hour": "24-Stunden", + "timeFormat12Hour": "12 Stunden" + }, + "dateTimePickerElementForm": { + "includeTime": "Zeit einbeziehen", + "invalidDateError": "Ungültiges Datum. Bitte stellen Sie sicher, dass das eingegebene Datum dem angegebenen Format entspricht." + }, + "choiceElementForm": { + "multiple": "Mehrere Werte zulassen", + "checkbox": "Kontrollfeld", + "radio": "Option", + "display": "Anzeige", + "dropdown": "Drop-Down" + }, + "dataSourceItem": { + "notConfigured": "Nicht konfiguriert" + }, + "dataSourceCreateEditModal": { + "createTitle": "Datenquelle erstellen", + "sharedWarning": "Diese Datenquelle wird gemeinsam genutzt, so dass sich Ihre Änderungen auf mehrere Seiten auswirken können.", + "editTitle": "Datenquelle bearbeiten" + }, + "buttonThemeConfigBlock": { + "borderRadius": "Rahmen-Radius", + "size": "Schriftgröße", + "padding": "Innenabstand", + "weight": "Schriftgewicht", + "textColor": "Textfarbe", + "borderColor": "Rahmenfarbe", + "borderSize": "Rahmengröße", + "fontFamily": "Schriftart", + "backgroundColor": "Hintergrundfarbe", + "alignment": "Ausrichtung", + "width": "Breite", + "button": "Button", + "defaultState": "Standard-Zustand", + "hoverState": "Hover-Zustand", + "textAlignment": "Textausrichtung" + }, + "linkThemeConfigBlock": { + "color": "Farbe", + "link": "Link", + "hoverState": "Hover-Zustand", + "alignment": "Ausrichtung", + "fontFamily": "Schriftart", + "defaultState": "Standard-Zustand", + "size": "Schriftgröße", + "weight": "Schriftgewicht" + }, + "inputThemeConfigBlock": { + "input": "Eingabe", + "backgroundColor": "Hintergrundfarbe", + "label": "Beschriftung", + "borderSize": "Rahmengröße", + "borderRadius": "Rahmen-Radius", + "borderColor": "Rahmenfarbe", + "textColor": "Textfarbe", + "padding": "Innenabstand", + "weight": "Schriftgewicht", + "fontFamily": "Schriftart", + "size": "Schriftgröße" + }, + "tableThemeConfigBlock": { + "fontSize": "Schriftgröße", + "table": "Tabelle", + "horizontalSeparatorSize": "Horizontale Größe", + "separators": "Trennelemente", + "verticalSeparatorColor": "Vertikale Farbe", + "backgroundAlternateColor": "Gerade Zeilenfarbe", + "padding": "Innenabstand", + "backgroundColor": "Hintergrundfarbe", + "header": "Kopfbereich", + "alignment": "Ausrichtung", + "cells": "Zellen", + "fontFamily": "Schriftart", + "size": "Größe", + "verticalSeparatorSize": "Vertikale Größe", + "horizontalSeparatorColor": "Horizontale Farbe", + "borderSize": "Rahmengröße", + "borderRadius": "Rahmen-Radius", + "fontWeight": "Schriftgewicht", + "borderColor": "Rahmenfarbe", + "textColor": "Textfarbe" + }, + "abTable": { + "loading": "Wird geladen...", + "empty": "Es wurden keine Elemente gefunden." + }, + "collectionElementForm": { + "noSchemaPropertyMessage": "Wählen Sie eine Eigenschaft in der Datenquelle, die Sie als Listendaten für Ihr Element verwenden möchten.", + "noDataSourceMessage": "Wählen Sie eine Datenquelle mit mehreren Zeilen, um alle Ergebnisse aufzulisten, oder eine einzeilige Datenquelle, um eine Eigenschaft innerhalb dieser Zeile auszuwählen." + }, + "dropdown": { + "empty": "Keine Optionen verfügbar" + }, + "pageVisibilitySettings": { + "allVisitors": "Alle Besucher", + "loggedInVisitors": "Eingeloggte Besucher", + "description": "Wer darf diese Seite sehen" + }, + "queryParamTypes": { + "textName": "Text", + "numericName": "Numerisch" + }, + "pageEditor": { + "pageNotFound": "Seite nicht gefunden" + }, + "dataSourceItemContext": { + "shareBetweenPages": "Teilen zwischen Seiten", + "unshareBetweenPages": "Freigabe auf anderen Seiten aufheben" + }, + "radiusStyleForm": { + "cornerRadiusLabel": "Eckradius", + "backgroundRadiusLabel": "Hintergrund", + "borderRadiusLabel": "Rahmen" + }, + "fontWeightType": { + "light": "Leicht", + "thin": "Dünn", + "extraLight": "Extra-leicht", + "regular": "Regulär", + "medium": "Mittel", + "semiBold": "Semi-Bold", + "bold": "Fett", + "extraBold": "Extra-Bold", + "black": "Black", + "extraBlack": "Extra-Black" + }, + "imageThemeConfigBlock": { + "imageBorderRadiusLabel": "Randradius", + "imageBorderRadiusPlaceholder": "Geben Sie den Bildrand-Radius ein.", + "maxWidthLabel": "Maximale Breite", + "maxHeightLabel": "Maximale Höhe", + "maxHeightPlaceholder": "Geben Sie die maximale Höhe ein", + "maxWidthPlaceholder": "Geben Sie die maximale Breite ein", + "alignment": "Ausrichtung", + "imageConstraintCoverDisabled": "Nicht verfügbar bei leerer maximaler Höhe.", + "imageConstraintContain": "Contain", + "imageConstraintsLabel": "Beschränkungen", + "imageConstraintFullWidth": "Auf maximale Breite ausweiten", + "imageConstraintCover": "Cover", + "imageConstraintContainDisabled": "Nicht verfügbar mit maximaler Höhe." } } diff --git a/web-frontend/modules/builder/locales/en.json b/web-frontend/modules/builder/locales/en.json index 5397d1e9c..8b3a4c30c 100644 --- a/web-frontend/modules/builder/locales/en.json +++ b/web-frontend/modules/builder/locales/en.json @@ -65,11 +65,13 @@ "publish": "Publish", "publishSucceedTitle": "Site published", "publishSucceedDescription": "The site has been successfully published.", + "publishSucceedLink": "View site", "publishFailedTitle": "Site publishing failed", "publishFailedDescription": "The site publishing has failed. Please try again later.", "openInNewTab": "Open in a new tab", "importingState": "Importing", - "noDomain": "You need to have at least one domain in order to publish your application." + "noDomain": "You need to have at least one domain in order to publish your application.", + "addDomain": "Add domain" }, "lastPublishedDomainDate": { "neverPublished": "never", @@ -123,7 +125,11 @@ "notAllowedUnlessFooter": "This element is allowed only inside the page footer", "notAllowedInsideContainer": "This element is not allowed inside a container", "notAllowedInsideSameType": "This element is not allowed in a container of the same type", - "notAllowedLocation": "This element is not allowed at this location" + "notAllowedLocation": "This element is not allowed at this location", + "menu": "Menu", + "menuDescription": "Menu element", + "simpleContainer": "Container", + "simpleContainerDescription": "A container for other elements" }, "addElementButton": { "label": "Element" @@ -133,6 +139,12 @@ "searchPlaceholder": "Search elements", "elementInProgress": "Adding element..." }, + "addElementCategory": { + "suggestedElement": "Suggested elements", + "baseElement": "Base elements", + "layoutElement": "Layout elements", + "formElement": "Form elements" + }, "elementMenu": { "moveUp": "Move up", "moveDown": "Move down", @@ -188,6 +200,44 @@ "textFormatTypePlain": "Plain text", "textFormatTypeMarkdown": "Markdown" }, + "orientations": { + "label": "Orientation", + "horizontal": "Horizontal", + "vertical": "Vertical" + }, + "menuElement": { + "missingValue": "Missing menu item", + "separator": "Separator", + "spacer": "Spacer", + "missingLinkValue": "Missing link name...", + "emptyLinkValue": "Empty link name...", + "missingButtonValue": "Missing button name...", + "emptyButtonValue": "Empty button name..." + }, + "menuElementForm": { + "menuItemsLabel": "Menu items", + "addMenuItemLink": "Add...", + "alignment": "Alignment", + "menuItemDefaultName": "Page", + "menuItemLabelLabel": "Label", + "menuItemTypeLabel": "Type", + "menuItemTypeSeparator": "Separator", + "menuItemVariantLabel": "Variant", + "menuItemVariantLink": "Link", + "menuItemVariantButton": "Button", + "namePlaceholder": "Page", + "addSubLink": "Add sublink", + "menuItemSubLinkDefaultName": "Sublink", + "menuItemAddLink": "Link", + "menuItemAddButton": "Button", + "menuItemAddSeparator": "Separator", + "menuItemAddSpacer": "Spacer", + "eventDescription": "To configure actions for this button, open the Events tab of this element.", + "noMenuItemsMessage": "Click 'Add' to add your first menu item." + }, + "simpleContainerElementForm": { + "noConfigurationOptions": "The container element does not have any configuration options." + }, "imageElement": { "missingValue": "Missing alt text...", "emptyValue": "Empty alt text..." @@ -297,7 +347,8 @@ }, "domainCard": { "refresh": "Refresh settings", - "detailLabel": "Show details" + "detailLabel": "Show details", + "unpublishedDomainWarning": "Please publish the application to make it available on this domain." }, "domainTypes": { "customName": "Custom domain", @@ -511,6 +562,7 @@ "weight": "Weight", "textAlignment": "Alignment", "bodyLabel": "Body", + "decoration": "Text decoration", "fontFamily": "Font" }, "fontWeightType": { @@ -530,6 +582,7 @@ "button": "Button", "defaultState": "Default state", "hoverState": "Hover state", + "activeState": "Active state", "textAlignment": "Text alignment", "alignment": "Alignment", "width": "Width", @@ -542,15 +595,21 @@ "size": "Font size", "weight": "Font weight" }, + "linkDecorations": { + "normal": "Normal", + "plain": "Plain" + }, "linkThemeConfigBlock": { "color": "Color", "link": "Link", "defaultState": "Default state", "hoverState": "Hover state", + "activeState": "Active state", "alignment": "Alignment", "fontFamily": "Font", "size": "Font size", - "weight": "Font weight" + "weight": "Font weight", + "decoration": "Text decoration" }, "inputThemeConfigBlock": { "label": "Label", @@ -645,9 +704,6 @@ "selectSourceFirst": "Choose a data source and/or property to begin configuring your fields.", "buttonColor": "Button color", "refreshFieldsFromDataSource": "refresh fields from data source", - "orientation": "Orientation", - "orientationHorizontal": "Horizontal", - "orientationVertical": "Vertical", "buttonLoadMoreLabel": "Show more label", "propertySelectorMissingArrays": "No multiple valued fields found to use as rows." }, @@ -677,7 +733,7 @@ "searchHeading": "Search", "optionUnavailable": "Unavailable", "noPropertiesAvailable": "No fields available.", - "formDescription": "Choose which properties within this element's data source external users can filter, sort and search upon." + "formDescription": "Choose which properties within this element's data source page visitors can filter, sort and search upon." }, "repeatElementForm": { "dataSource": "Data source", @@ -685,9 +741,6 @@ "itemsPerPagePlaceholder": "Enter value...", "itemsPerRowLabel": "Items per row", "itemsPerRowDescription": "Number of columns per row and device type.", - "orientationLabel": "Orientation", - "orientationVertical": "Vertical", - "orientationHorizontal": "Horizontal", "buttonLoadMoreLabel": "Show more label", "toggleEditorRepetitionsLabel": "Temporarily disable repetitions", "propertySelectorMissingArrays": "No multiple valued fields found to repeat with.", @@ -902,6 +955,11 @@ "label": "Property", "noProperties": "No properties available" }, + "userSourceDropdown": { + "label": "User source", + "addUserSource": "Add new user source", + "noUserSources": "No user sources available" + }, "dataSourceDropdown": { "label": "Data source", "noDataSources": "No data sources available", @@ -924,5 +982,11 @@ "authProviderWithModal": { "authProviderInError": "Please edit this provider to fix the error.", "title": "Edit provider: {name}" + }, + "textDecorationSelector": { + "underline": "Underline", + "stroke": "Stroke", + "italic": "Italic", + "uppercase": "Uppercase" } } diff --git a/web-frontend/modules/builder/locales/fr.json b/web-frontend/modules/builder/locales/fr.json index 2197b19ba..42c68cf27 100644 --- a/web-frontend/modules/builder/locales/fr.json +++ b/web-frontend/modules/builder/locales/fr.json @@ -62,8 +62,8 @@ "linkDescription": "Un lien vers une page/URL", "image": "Image", "imageDescription": "Affiche une image", - "inputText": "Saisie de texte", - "inputTextDescription": "Un champ de saisie de texte", + "inputText": "Champ de saisie", + "inputTextDescription": "Un champ de saisie", "columnDescription": "Conteneur multi-colonnes", "column": "Colonnes", "table": "Table", @@ -98,7 +98,11 @@ "notAllowedInsideSameType": "Cet élément n'est pas autorisé dans un conteneur du même type", "header": "En-tête multi-pages", "notAllowedInsideContainer": "Cet élément n'est pas autorisé à l'intérieur d'un conteneur", - "notAllowedLocation": "Cet élément n'est pas autorisé à cet endroit" + "notAllowedLocation": "Cet élément n'est pas autorisé à cet endroit", + "menu": "Menu", + "simpleContainerDescription": "Un conteneur pour grouper des éléments", + "simpleContainer": "Conteneur", + "menuDescription": "Un élément de menu" }, "elementMenu": { "moveDown": "Descendre", @@ -174,7 +178,9 @@ "title": "Publication", "noDomain": "Vous devez disposer d’au moins un domaine pour publier votre application.", "description": "Mettez votre application en ligne en publiant sur l’un des domaines. Notez que votre application peut avoir plusieurs domaines, chacun avec une version différente de l’application.", - "importingState": "Import en cours…" + "importingState": "Import en cours…", + "addDomain": "Ajouter un domaine", + "publishSucceedLink": "Voir le site" }, "pageActionTypes": { "preview": "Aperçu", @@ -233,7 +239,8 @@ }, "domainCard": { "refresh": "Actualiser les paramètres", - "detailLabel": "Afficher les détails" + "detailLabel": "Afficher les détails", + "unpublishedDomainWarning": "Veuillez publier l'application pour la rendre disponible sur ce domaine." }, "domainTypes": { "customName": "Domaine personnalisé", @@ -646,8 +653,8 @@ "allVisitors": "Tous les visiteurs", "loggedInVisitors": "Visiteurs connectés", "notLoggedInVisitors": "Visiteurs déconnectés", - "warningTitle": "Nous améliorons constamment la sécurité", - "warningMessage": "Pour l'instant, la visibilité d'une information n'est appliquée que dans l'interface utilisateur, les données sous-jacentes restant accessibles à partir de l'API. Veuillez consulter la <a href='https://baserow.io/user-docs/application-builder-element-visibility#note-accessing-hidden-data-via-api' target='_blank'>documentation</a> pour plus d'informations sur la sécurité des données.", + "warningTitle": "C'est un dispositif de sécurité", + "warningMessage": "Veuillez consulter la <a href='https://baserow.io/user-docs/application-builder-element-visibility#note-accessing-hidden-data-via-api' target='_blank'>documentation</a> pour plus d'informations sur la sécurité des données.", "excludedRolesLabel": "tous les rôles sauf", "switchAllowLabel": "Autoriser", "switchDisallowLabel": "Interdir", @@ -781,7 +788,8 @@ "textColor": "Couleur du texte", "button": "Bouton", "borderColor": "Couleur de la bordure", - "weight": "Graisse de la police" + "weight": "Graisse de la police", + "activeState": "État actif" }, "linkThemeConfigBlock": { "color": "Couleur", @@ -791,7 +799,8 @@ "alignment": "Alignement", "fontFamily": "Police", "size": "Taille de la police", - "weight": "Graisse de la police" + "weight": "Graisse de la police", + "activeState": "État actif" }, "imageThemeConfigBlock": { "alignment": "Alignement", @@ -944,7 +953,7 @@ "searchHeading": "Chercher", "optionUnavailable": "Non disponible", "noPropertiesAvailable": "Aucun champ disponible.", - "formDescription": "Choisissez les propriétés de la source de données que les utilisateurs externes peuvent filtrer, trier et rechercher." + "formDescription": "Choisissez les propriétés de la source de données que les utilisateurs de l'application peuvent filtrer, trier et rechercher." }, "dataSourceItem": { "notConfigured": "Non configurée" @@ -1026,5 +1035,50 @@ "queryParamTypes": { "textName": "Texte", "numericName": "Numérique" + }, + "addElementCategory": { + "suggestedElement": "Éléments suggérés", + "baseElement": "Éléments basiques", + "formElement": "Éléments de formulaire", + "layoutElement": "Éléments de mise en page" + }, + "orientations": { + "horizontal": "Horizontale", + "vertical": "Verticale", + "label": "Orientation" + }, + "menuElement": { + "spacer": "Espacement", + "missingLinkValue": "Nom du lien manquant...", + "emptyLinkValue": "Nom du lien vide...", + "missingButtonValue": "Nom du bouton manquant...", + "missingValue": "Aucune entrée de menu", + "emptyButtonValue": "Nom du bouton vide...", + "separator": "Séparateur" + }, + "menuElementForm": { + "menuItemsLabel": "Entrées du menu", + "addMenuItemLink": "Ajouter...", + "menuItemTypeItem": "Item", + "menuItemAddSeparator": "Séparateur", + "menuItemVariantLink": "Lien", + "menuItemVariantLabel": "Variante", + "namePlaceholder": "Page", + "noMenuItemsMessage": "Cliquez sur \"Ajouter\" pour ajouter votre première entrée de menu.", + "menuItemAddLink": "Lien", + "alignment": "Alignement", + "menuItemAddButton": "Bouton", + "menuItemDefaultName": "Page", + "menuItemTypeLabel": "Type", + "menuItemSubLinkDefaultName": "Lien enfant", + "menuItemLabelLabel": "Label", + "menuItemAddSpacer": "Espacement", + "menuItemTypeSeparator": "Séparateur", + "menuItemVariantButton": "Bouton", + "addSubLink": "Ajouter un lien enfant", + "eventDescription": "Pour configurer les actions de ce bouton, ouvrez l'onglet « Événements » de l'élément courant." + }, + "simpleContainerElementForm": { + "noConfigurationOptions": "L'élément conteneur n'a pas de configuration." } } diff --git a/web-frontend/modules/builder/locales/nl.json b/web-frontend/modules/builder/locales/nl.json index c6b64b908..a85b78d2d 100644 --- a/web-frontend/modules/builder/locales/nl.json +++ b/web-frontend/modules/builder/locales/nl.json @@ -105,7 +105,11 @@ "notAllowedInsideSameType": "Dit element is niet toegestaan in een container van hetzelfde type", "notAllowedLocation": "Dit element is niet toegestaan op deze locatie", "dateTimePicker": "Datum tijd kiezer", - "dateTimePickerDescription": "Een invoerveld voor datum en tijd" + "dateTimePickerDescription": "Een invoerveld voor datum en tijd", + "simpleContainer": "Container", + "menu": "Menu", + "menuDescription": "Menu element", + "simpleContainerDescription": "Een container voor andere elementen" }, "addElementButton": { "label": "Element" @@ -178,7 +182,9 @@ "publishFailedDescription": "Het publiceren van de site is mislukt. Probeer het later opnieuw.", "openInNewTab": "Openen in nieuw tabblad", "noDomain": "Je moet ten minste één domein hebben om uw applicatie te kunnen publiceren.", - "importingState": "importeren" + "importingState": "importeren", + "addDomain": "Domein toevoegen", + "publishSucceedLink": "Bekijk site" }, "lastPublishedDomainDate": { "neverPublished": "nooit", @@ -212,7 +218,8 @@ }, "domainCard": { "refresh": "Instellingen vernieuwen", - "detailLabel": "Toon details" + "detailLabel": "Toon details", + "unpublishedDomainWarning": "Publiceer de applicatie om deze beschikbaar te maken op dit domein." }, "domainTypes": { "customName": "Aangepast domein", @@ -743,7 +750,8 @@ "size": "Lettergrootte", "backgroundColor": "Achtergrond kleur", "button": "Knop", - "weight": "Lettertype gewicht" + "weight": "Lettertype gewicht", + "activeState": "Actieve status" }, "linkThemeConfigBlock": { "color": "Kleur", @@ -753,7 +761,8 @@ "alignment": "Uitlijning", "fontFamily": "Lettertype", "size": "Lettergrootte", - "weight": "Lettertype gewicht" + "weight": "Lettertype gewicht", + "activeState": "Actieve status" }, "imageThemeConfigBlock": { "alignment": "Uitlijning", @@ -1024,5 +1033,50 @@ "cornerRadiusLabel": "Hoekradius", "backgroundRadiusLabel": "Achtergrond", "borderRadiusLabel": "Rand" + }, + "addElementCategory": { + "suggestedElement": "Voorgestelde elementen", + "baseElement": "Basis elementen", + "layoutElement": "Layout elementen", + "formElement": "Formulier elementen" + }, + "menuElement": { + "spacer": "Spacer", + "missingLinkValue": "Ontbrekende linknaam...", + "missingButtonValue": "Ontbrekende knopnaam...", + "emptyLinkValue": "Lege linknaam...", + "missingValue": "Ontbrekend menu-item", + "separator": "Scheider", + "emptyButtonValue": "Lege knopnaam..." + }, + "menuElementForm": { + "menuItemsLabel": "Menu items", + "addMenuItemLink": "Toevoegen...", + "alignment": "Uitlijning", + "menuItemDefaultName": "Pagina", + "menuItemLabelLabel": "Label", + "menuItemTypeLabel": "Type", + "menuItemTypeItem": "Item", + "menuItemTypeSeparator": "Scheider", + "menuItemVariantLabel": "Variant", + "menuItemAddButton": "Knop", + "eventDescription": "Om acties te configureren voor deze knop, open de events van dit element.", + "noMenuItemsMessage": "Klik 'Toevoegen' om je eerste menu item toe te voegen.", + "menuItemVariantLink": "Link", + "menuItemAddSeparator": "Scheider", + "menuItemSubLinkDefaultName": "Sublink", + "addSubLink": "Sublink toevoegen", + "menuItemVariantButton": "Knop", + "namePlaceholder": "Pagina", + "menuItemAddSpacer": "Spacer", + "menuItemAddLink": "Link" + }, + "simpleContainerElementForm": { + "noConfigurationOptions": "Het container element heeft geen configuratieopties." + }, + "orientations": { + "vertical": "Vertical", + "horizontal": "Horizontaal", + "label": "Oriëntatie" } } diff --git a/web-frontend/modules/builder/pages/pageEditor.vue b/web-frontend/modules/builder/pages/pageEditor.vue index 433f3eeaa..ea46973f1 100644 --- a/web-frontend/modules/builder/pages/pageEditor.vue +++ b/web-frontend/modules/builder/pages/pageEditor.vue @@ -80,13 +80,12 @@ export default { parseInt(from.params.builderId) ) - // Unselect previously selected element - this.$store.dispatch('element/select', { - builder, - element: null, - }) - if (builder) { + // Unselect previously selected element + this.$store.dispatch('element/select', { + builder, + element: null, + }) // We want to reload once only data for this builder next time this.$store.dispatch('application/forceUpdate', { application: builder, diff --git a/web-frontend/modules/builder/pages/publicPage.vue b/web-frontend/modules/builder/pages/publicPage.vue index 2dc862d1e..b0ac087d3 100644 --- a/web-frontend/modules/builder/pages/publicPage.vue +++ b/web-frontend/modules/builder/pages/publicPage.vue @@ -27,6 +27,7 @@ import { userSourceCookieTokenName, setToken, } from '@baserow/modules/core/utils/auth' +import { QUERY_PARAM_TYPE_VALIDATION_FUNCTIONS } from '@baserow/modules/builder/enums' const logOffAndReturnToLogin = async ({ builder, store, redirect }) => { await store.dispatch('userSourceUser/logoff', { @@ -341,6 +342,34 @@ export default { }, }, watch: { + '$route.query': { + immediate: true, + deep: true, + handler(newQuery) { + // when query string changed due to user action, + // update the page's query parameters in the store + Promise.all( + this.currentPage.query_params.map(({ name, type }) => { + if (!newQuery[name]) return null + let value + try { + value = QUERY_PARAM_TYPE_VALIDATION_FUNCTIONS[type]( + newQuery[name] + ) + } catch { + // Skip setting the parameter if the user-provided value + // doesn't pass our parameter `type` validation. + return null + } + return this.$store.dispatch('pageParameter/setParameter', { + page: this.currentPage, + name, + value, + }) + }) + ) + }, + }, dispatchContext: { deep: true, /** diff --git a/web-frontend/modules/builder/plugin.js b/web-frontend/modules/builder/plugin.js index 40a94eac9..3b6eb6398 100644 --- a/web-frontend/modules/builder/plugin.js +++ b/web-frontend/modules/builder/plugin.js @@ -25,7 +25,6 @@ import elementContentStore from '@baserow/modules/builder/store/elementContent' import themeStore from '@baserow/modules/builder/store/theme' import workflowActionStore from '@baserow/modules/builder/store/workflowAction' import formDataStore from '@baserow/modules/builder/store/formData' - import { registerRealtimeEvents } from '@baserow/modules/builder/realtime' import { HeadingElementType, @@ -45,13 +44,18 @@ import { RecordSelectorElementType, HeaderElementType, FooterElementType, + MenuElementType, + SimpleContainerElementType, } from '@baserow/modules/builder/elementTypes' import { DesktopDeviceType, SmartphoneDeviceType, TabletDeviceType, } from '@baserow/modules/builder/deviceTypes' -import { DuplicatePageJobType } from '@baserow/modules/builder/jobTypes' +import { + DuplicatePageJobType, + PublishBuilderJobType, +} from '@baserow/modules/builder/jobTypes' import { BuilderApplicationType } from '@baserow/modules/builder/applicationTypes' import { PublicSiteErrorPageType } from '@baserow/modules/builder/errorPageTypes' import { @@ -182,6 +186,7 @@ export default (context) => { app.$registry.register('application', new BuilderApplicationType(context)) app.$registry.register('job', new DuplicatePageJobType(context)) + app.$registry.register('job', new PublishBuilderJobType(context)) app.$registry.register( 'builderSettings', @@ -214,6 +219,7 @@ export default (context) => { app.$registry.register('element', new LinkElementType(context)) app.$registry.register('element', new ButtonElementType(context)) app.$registry.register('element', new TableElementType(context)) + app.$registry.register('element', new SimpleContainerElementType(context)) app.$registry.register('element', new ColumnElementType(context)) app.$registry.register('element', new HeaderElementType(context)) app.$registry.register('element', new FooterElementType(context)) @@ -224,6 +230,7 @@ export default (context) => { app.$registry.register('element', new DateTimePickerElementType(context)) app.$registry.register('element', new RecordSelectorElementType(context)) app.$registry.register('element', new RepeatElementType(context)) + app.$registry.register('element', new MenuElementType(context)) app.$registry.register('device', new DesktopDeviceType(context)) app.$registry.register('device', new TabletDeviceType(context)) diff --git a/web-frontend/modules/builder/realtime.js b/web-frontend/modules/builder/realtime.js index 0c3497c02..2a4583608 100644 --- a/web-frontend/modules/builder/realtime.js +++ b/web-frontend/modules/builder/realtime.js @@ -78,7 +78,6 @@ export const registerRealtimeEvents = (realtime) => { realtime.registerEvent('element_updated', ({ store }, { element }) => { const selectedPage = store.getters['page/getSelected'] if (selectedPage.id === element.page_id) { - console.log('it is') const builder = store.getters['application/get'](selectedPage.builder_id) store.dispatch('element/forceUpdate', { builder, diff --git a/web-frontend/modules/builder/themeConfigBlockTypes.js b/web-frontend/modules/builder/themeConfigBlockTypes.js index f857b5b5a..377405f30 100644 --- a/web-frontend/modules/builder/themeConfigBlockTypes.js +++ b/web-frontend/modules/builder/themeConfigBlockTypes.js @@ -289,6 +289,36 @@ export class TypographyThemeConfigBlockType extends ThemeConfigBlockType { `heading_${level}_font_weight`, `--heading-h${level}-font-weight` ) + style.addIfExists( + theme, + `heading_${level}_text_decoration`, + `--heading-h${level}-text-decoration`, + (v) => { + const value = [] + if (v[0]) { + value.push('underline') + } + if (v[1]) { + value.push('line-through') + } + if (value.length === 0) { + return 'none' + } + return value.join(' ') + } + ) + style.addIfExists( + theme, + `heading_${level}_text_decoration`, + `--heading-h${level}-text-transform`, + (v) => (v[2] ? 'uppercase' : 'none') + ) + style.addIfExists( + theme, + `heading_${level}_text_decoration`, + `--heading-h${level}-font-style`, + (v) => (v[3] ? 'italic' : 'none') + ) }) style.addPixelValueIfExists(theme, `body_font_size`) style.addColorIfExists(theme, `body_text_color`) @@ -328,6 +358,10 @@ export class ButtonThemeConfigBlockType extends ThemeConfigBlockType { style.addColorIfExists(theme, 'button_hover_text_color') style.addColorIfExists(theme, 'button_border_color') style.addColorIfExists(theme, 'button_hover_border_color') + style.addColorIfExists(theme, 'button_active_background_color') + style.addColorIfExists(theme, 'button_active_text_color') + style.addColorIfExists(theme, 'button_active_border_color') + style.addIfExists(theme, 'button_width', null, (v) => v === WIDTHS_NEW.FULL ? '100%' : 'auto' ) @@ -378,6 +412,7 @@ export class LinkThemeConfigBlockType extends ThemeConfigBlockType { }) style.addColorIfExists(theme, 'link_text_color') style.addColorIfExists(theme, 'link_hover_text_color') + style.addColorIfExists(theme, 'link_active_text_color') style.addIfExists( theme, 'link_text_alignment', @@ -393,6 +428,96 @@ export class LinkThemeConfigBlockType extends ThemeConfigBlockType { const fontFamilyType = this.app.$registry.get('fontFamily', v) return `"${fontFamilyType.name}","${fontFamilyType.safeFont}"` }) + style.addIfExists( + theme, + 'link_default_text_decoration', + '--link-default-text-decoration', + (v) => { + const value = [] + if (v[0]) { + value.push('underline') + } + if (v[1]) { + value.push('line-through') + } + if (value.length === 0) { + return 'none' + } + return value.join(' ') + } + ) + style.addIfExists( + theme, + 'link_default_text_decoration', + '--link-default-text-transform', + (v) => (v[2] ? 'uppercase' : 'none') + ) + style.addIfExists( + theme, + 'link_default_text_decoration', + '--link-default-font-style', + (v) => (v[3] ? 'italic' : 'none') + ) + style.addIfExists( + theme, + 'link_hover_text_decoration', + '--link-hover-text-decoration', + (v) => { + const value = [] + if (v[0]) { + value.push('underline') + } + if (v[1]) { + value.push('line-through') + } + if (value.length === 0) { + return 'none' + } + return value.join(' ') + } + ) + style.addIfExists( + theme, + 'link_hover_text_decoration', + '--link-hover-text-transform', + (v) => (v[2] ? 'uppercase' : 'none') + ) + style.addIfExists( + theme, + 'link_hover_text_decoration', + '--link-hover-font-style', + (v) => (v[3] ? 'italic' : 'none') + ) + style.addIfExists( + theme, + 'link_active_text_decoration', + '--link-active-text-decoration', + (v) => { + const value = [] + if (v[0]) { + value.push('underline') + } + if (v[1]) { + value.push('line-through') + } + if (value.length === 0) { + return 'none' + } + return value.join(' ') + } + ) + style.addIfExists( + theme, + 'link_active_text_decoration', + '--link-active-text-transform', + (v) => (v[2] ? 'uppercase' : 'none') + ) + style.addIfExists( + theme, + 'link_active_text_decoration', + '--link-active-font-style', + (v) => (v[3] ? 'italic' : 'none') + ) style.addPixelValueIfExists(theme, `link_font_size`) style.addFontWeightIfExists(theme, `link_font_weight`) return style.toObject() diff --git a/web-frontend/modules/core/appAuthProviderTypes.js b/web-frontend/modules/core/appAuthProviderTypes.js index c21b8e7e6..adeeaa3a9 100644 --- a/web-frontend/modules/core/appAuthProviderTypes.js +++ b/web-frontend/modules/core/appAuthProviderTypes.js @@ -41,4 +41,13 @@ export class AppAuthProviderType extends BaseAuthProviderType { handleError(userSource, authProvider, route) { return null } + + /** + * Returns whether the provider is enabled or not. + * @param {Number} workspaceId The workspace id. + * @returns {Boolean} True if the provider is disabled, false otherwise. + */ + isDeactivated(workspaceId) { + return false + } } diff --git a/web-frontend/modules/core/assets/icons/separator.svg b/web-frontend/modules/core/assets/icons/separator.svg new file mode 100644 index 000000000..42c160ebc --- /dev/null +++ b/web-frontend/modules/core/assets/icons/separator.svg @@ -0,0 +1,8 @@ +<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> +<path d="M3.5625 3V5.11538C3.5625 5.69923 4.0665 6.17307 4.6875 6.17307H19.3125C19.9335 6.17307 20.4375 5.69923 20.4375 5.11538V3" stroke="black" stroke-width="1.4" stroke-linecap="round" stroke-linejoin="round"/> +<path d="M3.5625 20.9999V18.8845C3.5625 18.3006 4.0665 17.8268 4.6875 17.8268H19.3125C19.9335 17.8268 20.4375 18.3006 20.4375 18.8845V20.9999" stroke="black" stroke-width="1.4" stroke-linecap="round" stroke-linejoin="round"/> +<path d="M4.125 12.8655C4.74632 12.8655 5.25 12.392 5.25 11.8078C5.25 11.2237 4.74632 10.7501 4.125 10.7501C3.50368 10.7501 3 11.2237 3 11.8078C3 12.392 3.50368 12.8655 4.125 12.8655Z" fill="black"/> +<path d="M14.625 12.8655C15.2463 12.8655 15.75 12.392 15.75 11.8078C15.75 11.2237 15.2463 10.7501 14.625 10.7501C14.0037 10.7501 13.5 11.2237 13.5 11.8078C13.5 12.392 14.0037 12.8655 14.625 12.8655Z" fill="black"/> +<path d="M9.375 12.8655C9.99632 12.8655 10.5 12.392 10.5 11.8078C10.5 11.2237 9.99632 10.7501 9.375 10.7501C8.75368 10.7501 8.25 11.2237 8.25 11.8078C8.25 12.392 8.75368 12.8655 9.375 12.8655Z" fill="black"/> +<path d="M19.875 12.8655C20.4963 12.8655 21 12.392 21 11.8078C21 11.2237 20.4963 10.7501 19.875 10.7501C19.2537 10.7501 18.75 11.2237 18.75 11.8078C18.75 12.392 19.2537 12.8655 19.875 12.8655Z" fill="black"/> +</svg> diff --git a/web-frontend/modules/core/assets/icons/spacer.svg b/web-frontend/modules/core/assets/icons/spacer.svg new file mode 100644 index 000000000..639ee5f81 --- /dev/null +++ b/web-frontend/modules/core/assets/icons/spacer.svg @@ -0,0 +1,10 @@ +<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> +<path d="M7 4H4V7" stroke="black" stroke-width="1.4" stroke-linecap="round" stroke-linejoin="round"/> +<path d="M4 11V13" stroke="black" stroke-width="1.4" stroke-linecap="round" stroke-linejoin="round"/> +<path d="M11 4H13" stroke="black" stroke-width="1.4" stroke-linecap="round" stroke-linejoin="round"/> +<path d="M11 20H13" stroke="black" stroke-width="1.4" stroke-linecap="round" stroke-linejoin="round"/> +<path d="M20 11V13" stroke="black" stroke-width="1.4" stroke-linecap="round" stroke-linejoin="round"/> +<path d="M17 4H20V7" stroke="black" stroke-width="1.4" stroke-linecap="round" stroke-linejoin="round"/> +<path d="M7 20H4V17" stroke="black" stroke-width="1.4" stroke-linecap="round" stroke-linejoin="round"/> +<path d="M17 20H20V17" stroke="black" stroke-width="1.4" stroke-linecap="round" stroke-linejoin="round"/> +</svg> diff --git a/web-frontend/modules/core/assets/scss/components/builder/add_element_card.scss b/web-frontend/modules/core/assets/scss/components/builder/add_element_card.scss index 5e7924d12..f4c22b1b6 100644 --- a/web-frontend/modules/core/assets/scss/components/builder/add_element_card.scss +++ b/web-frontend/modules/core/assets/scss/components/builder/add_element_card.scss @@ -1,32 +1,56 @@ +// Main Component .add-element-card { - border: solid $color-neutral-400 1px; - padding: 10px 15px; - width: 133px; + display: flex; + flex-direction: column; + align-items: center; + width: 125px; cursor: pointer; @include rounded($rounded-md); &:hover { - background-color: $color-neutral-100; text-decoration: none; } &--disabled { opacity: 0.3; cursor: not-allowed; - background-color: $color-neutral-100; + } + + // Nested elements + &__description { + font-size: 11px; + color: $color-neutral-400; + } + + &__element-type { + display: flex; + flex-wrap: wrap; + justify-content: center; + + @include flex-align-items(4px); + } + + &__element-type-icon { + display: inline-block; + width: 116px; + height: 110px; + background-repeat: no-repeat; + background-position: center; + background-size: contain; + font-size: 16px; + + &:hover { + filter: contrast(0.95); + } + } + + &__label { + display: block; + color: #202128; + font-size: 13px; + font-weight: 500; + width: 90px; + text-align: center; } } - -.add-element-card__description { - font-size: 11px; - color: $color-neutral-400; -} - -.add-element-card__element-type { - @include flex-align-items(4px); -} - -.add-element-card__element-type-icon { - font-size: 16px; -} diff --git a/web-frontend/modules/core/assets/scss/components/builder/add_element_icons.scss b/web-frontend/modules/core/assets/scss/components/builder/add_element_icons.scss new file mode 100644 index 000000000..c3dc3c942 --- /dev/null +++ b/web-frontend/modules/core/assets/scss/components/builder/add_element_icons.scss @@ -0,0 +1,45 @@ +// Icon list +$baserow-builder-icons: ( + 'auth_form', + 'button', + 'checkbox', + 'choice', + 'column', + 'container', + 'datetime_picker', + 'fields', + 'footer', + 'form_container', + 'header', + 'heading', + 'iframe', + 'simple_container', + 'positioned_container', + 'menu', + 'image', + 'input_text', + 'link', + 'map', + 'rating', + 'rating_input', + 'record_selector', + 'repeat', + 'rich_text', + 'separator', + 'table', + 'text', + 'video' +); + +@mixin baserow-builder-icon($name) { + background-image: url('@baserow/modules/builder/assets/icons/element-' + $name + '.svg'); +} + +$baserow-builder-icon-prefix: 'add-element-card__element-type-icon-'; + +// Generate builder icon classes +@each $icon in $baserow-builder-icons { + .#{$baserow-builder-icon-prefix}#{$icon} { + @include baserow-builder-icon($icon); + } +} diff --git a/web-frontend/modules/core/assets/scss/components/builder/add_element_modal.scss b/web-frontend/modules/core/assets/scss/components/builder/add_element_modal.scss index aedde8087..20fd0ddf5 100644 --- a/web-frontend/modules/core/assets/scss/components/builder/add_element_modal.scss +++ b/web-frontend/modules/core/assets/scss/components/builder/add_element_modal.scss @@ -1,5 +1,74 @@ -.add-element-modal__element-cards { - display: flex; - flex-flow: wrap; - gap: 15px; +// Main modal container +.add-element-modal { + div.modal__box { + max-height: 90vh; + overflow-y: auto; + padding: 2.5em; + max-width: 560px; + } + + &__element-cards { + display: flex; + flex-flow: wrap; + gap: 15px; + flex-direction: column; + margin-left: -11px; + width: 500px; + } + + .expandable__header { + display: flex; + justify-content: space-between; + align-items: center; + border-top: 1px solid #ededed; + cursor: pointer; + user-select: none; + padding-top: 20px; + margin-left: 5px; + width: 490px; + } + + &__category-arrow { + font-size: 14px; + color: $color-neutral-500; + cursor: pointer; + display: flex; + flex-direction: row-reverse; + margin-top: -14px; + } + + &__category-title { + font-size: 12px; + font-weight: 400; + color: #6a6b70; + width: 100%; + display: inline-block; + + &:hover { + text-decoration: none; + } + } + + &__category-content { + display: flex; + flex-wrap: wrap; + } + + &__category { + padding-bottom: 24px; + } + + &__category:first-of-type { + .expandable__header { + border-top: none; + } + } + + &__search { + margin-bottom: 24px; + } + + &__search-magnifier { + margin-top: 5px; + } } diff --git a/web-frontend/modules/core/assets/scss/components/builder/all.scss b/web-frontend/modules/core/assets/scss/components/builder/all.scss index 891bf1bd7..03279d049 100644 --- a/web-frontend/modules/core/assets/scss/components/builder/all.scss +++ b/web-frontend/modules/core/assets/scss/components/builder/all.scss @@ -2,6 +2,7 @@ @import 'theme/all'; @import 'page_builder'; @import 'elements_context'; +@import 'add_element_icons'; @import 'add_element_card'; @import 'add_element_modal'; @import 'page_preview'; @@ -40,3 +41,4 @@ @import 'auth_provider_with_modal'; @import 'side_bar'; @import 'custom_color_input'; +@import 'text_decoration_selector'; diff --git a/web-frontend/modules/core/assets/scss/components/builder/element.scss b/web-frontend/modules/core/assets/scss/components/builder/element.scss index 9330bfd2f..d2cb9cc02 100644 --- a/web-frontend/modules/core/assets/scss/components/builder/element.scss +++ b/web-frontend/modules/core/assets/scss/components/builder/element.scss @@ -83,3 +83,8 @@ user-select: none; } } + +.element--element-id { + font-size: 12px; + color: rgb(87, 86, 86); +} diff --git a/web-frontend/modules/core/assets/scss/components/builder/elements/ab_components/ab_button.scss b/web-frontend/modules/core/assets/scss/components/builder/elements/ab_components/ab_button.scss index a6c6f83cd..b0ef47b3b 100644 --- a/web-frontend/modules/core/assets/scss/components/builder/elements/ab_components/ab_button.scss +++ b/web-frontend/modules/core/assets/scss/components/builder/elements/ab_components/ab_button.scss @@ -25,6 +25,13 @@ text-decoration: none; } + &:not(.loading-spinner).ab-button--force-active { + background-color: var(--button-active-background-color, $black); + border-color: var(--button-active-border-color, $white); + color: var(--button-active-text-color, $white); + text-decoration: none; + } + &[disabled], &[disabled]:hover { cursor: not-allowed; diff --git a/web-frontend/modules/core/assets/scss/components/builder/elements/ab_components/ab_checkbox.scss b/web-frontend/modules/core/assets/scss/components/builder/elements/ab_components/ab_checkbox.scss index 2a1f8da71..94b2e8ad8 100644 --- a/web-frontend/modules/core/assets/scss/components/builder/elements/ab_components/ab_checkbox.scss +++ b/web-frontend/modules/core/assets/scss/components/builder/elements/ab_components/ab_checkbox.scss @@ -3,6 +3,7 @@ align-items: center; font-size: var(--input-font-size, 13px); font-family: var(--input-font-family, Inter); + font-weight: var(--input-font-weight, 400); color: var(--input-text-color, $color-neutral-900); gap: calc(var(--input-font-size, 13px) / 2); diff --git a/web-frontend/modules/core/assets/scss/components/builder/elements/ab_components/ab_dropdown.scss b/web-frontend/modules/core/assets/scss/components/builder/elements/ab_components/ab_dropdown.scss index b7ff411fc..2c16f3f6a 100644 --- a/web-frontend/modules/core/assets/scss/components/builder/elements/ab_components/ab_dropdown.scss +++ b/web-frontend/modules/core/assets/scss/components/builder/elements/ab_components/ab_dropdown.scss @@ -1,6 +1,5 @@ .ab-dropdown { position: relative; - background-color: $white; } .ab-dropdown__selected { @@ -11,6 +10,7 @@ font-size: var(--input-font-size, 13px); color: var(--input-text-color, $color-neutral-900); font-family: var(--input-font-family, Inter); + font-weight: var(--input-font-weight, 400); background-color: var(--input-background-color, $white); padding: var(--input-vertical-padding, 8px) var(--input-horizontal-padding, 12px); @@ -64,6 +64,7 @@ border-radius: var(--input-border-radius, 0); background-color: var(--input-background-color, $white); font-size: var(--input-font-size, 13px); + font-weight: var(--input-font-weight, 400); z-index: 1; @include absolute(0, 0, auto, 0); diff --git a/web-frontend/modules/core/assets/scss/components/builder/elements/ab_components/ab_dropdownitem.scss b/web-frontend/modules/core/assets/scss/components/builder/elements/ab_components/ab_dropdownitem.scss index c018e2e47..b72b17af1 100644 --- a/web-frontend/modules/core/assets/scss/components/builder/elements/ab_components/ab_dropdownitem.scss +++ b/web-frontend/modules/core/assets/scss/components/builder/elements/ab_components/ab_dropdownitem.scss @@ -52,6 +52,7 @@ .ab-dropdownitem__item-active-icon { text-align: center; font-size: var(--input-font-size, 13px); + font-weight: var(--input-font-weight, 400); color: var(--input-text-color, $color-neutral-900); position: absolute; top: calc(50% - var(--input-font-size, 13px) / 2); @@ -70,6 +71,7 @@ user-select: none; border-radius: var(--input-border-radius, 0); font-family: var(--input-font-family, Inter); + font-weight: var(--input-font-weight, 400); &:last-child { margin-bottom: 0; diff --git a/web-frontend/modules/core/assets/scss/components/builder/elements/ab_components/ab_heading.scss b/web-frontend/modules/core/assets/scss/components/builder/elements/ab_components/ab_heading.scss index b50df3c31..7aae7bf73 100644 --- a/web-frontend/modules/core/assets/scss/components/builder/elements/ab_components/ab_heading.scss +++ b/web-frontend/modules/core/assets/scss/components/builder/elements/ab_components/ab_heading.scss @@ -8,6 +8,9 @@ font-weight: var(--heading-h1-font-weight, 700); text-align: var(--heading-h1-text-alignment, left); font-family: var(--heading-h1-font-family, Inter); + text-decoration: var(--heading-h1-text-decoration, none); + text-transform: var(--heading-h1-text-transform, none); + font-style: var(--heading-h1-font-style, none); } .ab-heading--h2 { @@ -16,6 +19,9 @@ font-weight: var(--heading-h2-font-weight, 600); text-align: var(--heading-h2-text-alignment, left); font-family: var(--heading-h2-font-family, Inter); + text-decoration: var(--heading-h2-text-decoration, none); + text-transform: var(--heading-h2-text-transform, none); + font-style: var(--heading-h2-font-style, none); } .ab-heading--h3 { @@ -24,6 +30,9 @@ font-weight: var(--heading-h3-font-weight, 500); text-align: var(--heading-h3-text-alignment, left); font-family: var(--heading-h3-font-family, Inter); + text-decoration: var(--heading-h3-text-decoration, none); + text-transform: var(--heading-h3-text-transform, none); + font-style: var(--heading-h3-font-style, none); } .ab-heading--h4 { @@ -32,6 +41,9 @@ font-weight: var(--heading-h4-font-weight, 500); text-align: var(--heading-h4-text-alignment, left); font-family: var(--heading-h4-font-family, Inter); + text-decoration: var(--heading-h4-text-decoration, none); + text-transform: var(--heading-h4-text-transform, none); + font-style: var(--heading-h4-font-style, none); } .ab-heading--h5 { @@ -40,6 +52,9 @@ font-weight: var(--heading-h5-font-weight, 400); text-align: var(--heading-h5-text-alignment, left); font-family: var(--heading-h5-font-family, Inter); + text-decoration: var(--heading-h5-text-decoration, none); + text-transform: var(--heading-h5-text-transform, none); + font-style: var(--heading-h5-font-style, none); } .ab-heading--h6 { @@ -48,5 +63,7 @@ font-weight: var(--heading-h6-font-weight, 400); text-align: var(--heading-h6-text-alignment, left); font-family: var(--heading-h6-font-family, Inter); - font-style: italic; + text-decoration: var(--heading-h6-text-decoration, underline); + text-transform: var(--heading-h6-text-transform, none); + font-style: var(--heading-h6-font-style, italic); } diff --git a/web-frontend/modules/core/assets/scss/components/builder/elements/ab_components/ab_link.scss b/web-frontend/modules/core/assets/scss/components/builder/elements/ab_components/ab_link.scss index 1affc8872..c9c1e4471 100644 --- a/web-frontend/modules/core/assets/scss/components/builder/elements/ab_components/ab_link.scss +++ b/web-frontend/modules/core/assets/scss/components/builder/elements/ab_components/ab_link.scss @@ -1,7 +1,9 @@ .ab-link { font-size: var(--link-font-size, 14px); font-weight: var(--link-font-weight, 400); - text-decoration: var(--link-text-decoration, underline); + text-decoration: var(--link-default-text-decoration, underline); + text-transform: var(--link-default-text-transform, none); + font-style: var(--link-default-font-style, none); color: var(--link-text-color, $black); align-self: var(--force-self-alignment, var(--link-text-alignment, initial)); font-family: var(--link-font-family, Inter); @@ -10,5 +12,14 @@ &--force-hover { color: var(--link-hover-text-color, $black); text-decoration: var(--link-hover-text-decoration, underline); + text-transform: var(--link-hover-text-transform, none); + font-style: var(--link-hover-font-style, none); + } + + &--force-active { + color: var(--link-active-text-color, $black); + text-decoration: var(--link-active-text-decoration, underline); + text-transform: var(--link-active-text-transform, none); + font-style: var(--link-active-font-style, none); } } diff --git a/web-frontend/modules/core/assets/scss/components/builder/elements/ab_components/ab_radio.scss b/web-frontend/modules/core/assets/scss/components/builder/elements/ab_components/ab_radio.scss index 16f04807a..69095d67e 100644 --- a/web-frontend/modules/core/assets/scss/components/builder/elements/ab_components/ab_radio.scss +++ b/web-frontend/modules/core/assets/scss/components/builder/elements/ab_components/ab_radio.scss @@ -3,6 +3,7 @@ align-items: center; font-size: var(--input-font-size, 13px); font-family: var(--input-font-family, Inter); + font-weight: var(--input-font-weight, 400); color: var(--input-text-color, $color-neutral-900); gap: calc(var(--input-font-size, 13px) / 2); diff --git a/web-frontend/modules/core/assets/scss/components/builder/elements/all.scss b/web-frontend/modules/core/assets/scss/components/builder/elements/all.scss index f3b3b70a0..6bffc231e 100644 --- a/web-frontend/modules/core/assets/scss/components/builder/elements/all.scss +++ b/web-frontend/modules/core/assets/scss/components/builder/elements/all.scss @@ -12,3 +12,4 @@ @import 'repeat_element'; @import 'tag_field'; @import 'image_field'; +@import 'menu_element'; diff --git a/web-frontend/modules/core/assets/scss/components/builder/elements/forms/all.scss b/web-frontend/modules/core/assets/scss/components/builder/elements/forms/all.scss index c7f9436b3..4a9b1e701 100644 --- a/web-frontend/modules/core/assets/scss/components/builder/elements/forms/all.scss +++ b/web-frontend/modules/core/assets/scss/components/builder/elements/forms/all.scss @@ -5,3 +5,4 @@ @import 'visibility_form'; @import 'property_option_form'; @import 'multi_page_container_element_form'; +@import 'menu_element_form'; diff --git a/web-frontend/modules/core/assets/scss/components/builder/elements/forms/menu_element_form.scss b/web-frontend/modules/core/assets/scss/components/builder/elements/forms/menu_element_form.scss new file mode 100644 index 000000000..329e8fae0 --- /dev/null +++ b/web-frontend/modules/core/assets/scss/components/builder/elements/forms/menu_element_form.scss @@ -0,0 +1,84 @@ +/** + Menu Element Form styles. + */ + +.menu-element-form__add-item-container { + display: flex; + align-items: center; + justify-content: space-between; +} + +.menu-element-form__add-item-context { + display: flex; + flex-direction: column; + width: 100%; + gap: 10px; + padding: 10px; +} + +%menu-element-form-expandable-item { + display: flex; + align-items: center; + margin: 5px 0; + user-select: none; + cursor: pointer; +} + +.menu-element-form__item-header { + @extend %menu-element-form-expandable-item; + + background-color: $palette-neutral-100; +} + +.menu-element-form__item-error { + font-size: 20px; + color: #ffbdb4; + pointer-events: none; + padding-right: 3px; +} + +.menu-element-form__item-name { + flex: 1; + padding-right: 5px; + + @extend %ellipsis; +} + +.menu-element-form__item-handle { + width: 8px; + height: 36px; + background-image: radial-gradient($color-neutral-200 40%, transparent 40%); + background-size: 4px 4px; + background-repeat: repeat; + margin: 2px; + margin-right: 12px; + cursor: grab; + visibility: hidden; + + .menu-element-form__item-header:hover & { + visibility: visible; + } +} + +.menu-element-form__item-header--outline { + @extend %menu-element-form-expandable-item; + + background-color: $color-neutral-10; + border: 1px dashed $color-neutral-200; +} + +.menu-element-form__item { + margin: 5px 10px; + width: 100%; +} + +.menu-element-form__item-child { + margin-right: -10px; + width: calc(100% - 10px); +} + +.menu-element-form__add-sub-link-container { + display: flex; + justify-content: flex-end; + margin-left: 15px; +} diff --git a/web-frontend/modules/core/assets/scss/components/builder/elements/link_element.scss b/web-frontend/modules/core/assets/scss/components/builder/elements/link_element.scss index 1f086bce7..5b4e23bcd 100644 --- a/web-frontend/modules/core/assets/scss/components/builder/elements/link_element.scss +++ b/web-frontend/modules/core/assets/scss/components/builder/elements/link_element.scss @@ -3,6 +3,14 @@ flex-direction: column; } +/** + Disable pointer events when in Page Editor. + */ +.element--read-only .ab-link { + pointer-events: none; + user-select: none; +} + .link-element__link { font-size: 14px; color: $black; diff --git a/web-frontend/modules/core/assets/scss/components/builder/elements/menu_element.scss b/web-frontend/modules/core/assets/scss/components/builder/elements/menu_element.scss new file mode 100644 index 000000000..f87bc60b8 --- /dev/null +++ b/web-frontend/modules/core/assets/scss/components/builder/elements/menu_element.scss @@ -0,0 +1,75 @@ +.menu-element__container { + display: flex; + justify-content: var(--alignment); +} + +/** + Disable pointer events when in Page Editor. + */ +.element--read-only .menu-element__container { + pointer-events: none; + user-select: none; +} + +.menu-element__container--vertical { + flex-direction: column; + gap: 20px; + width: 100%; + + .menu-element__menu-item-separator { + width: 100%; + height: 1px; + background-color: $palette-neutral-500; + margin: 0 5px; + } +} + +.menu-element__menu-item-spacer { + flex: 1; +} + +.menu-element__sub-link-menu-spacer { + flex: 1; +} + +.menu-element__container--horizontal { + flex-direction: row; + align-items: center; + gap: 20px; + + .menu-element__menu-item-separator { + width: 1px; + height: 20px; + background-color: $palette-neutral-500; + } + + .menu-element__sub-link-menu--expanded-icon { + margin-left: 5px; + } +} + +.menu-element__sub-link-menu--container { + display: flex; + flex-direction: row; + align-items: center; + gap: 5px; +} + +.menu-element__sub-links { + display: flex; + flex-direction: column; + width: 100%; + gap: 10px; + padding: 5px; +} + +.menu-element__sub-link { + width: 100%; + display: block; + padding: 10px; + text-decoration: none; +} + +.menu-element__sub-link:hover { + background: $palette-neutral-100; +} diff --git a/web-frontend/modules/core/assets/scss/components/builder/text_decoration_selector.scss b/web-frontend/modules/core/assets/scss/components/builder/text_decoration_selector.scss new file mode 100644 index 000000000..78479d296 --- /dev/null +++ b/web-frontend/modules/core/assets/scss/components/builder/text_decoration_selector.scss @@ -0,0 +1,4 @@ +.text-decoration-selector { + display: flex; + gap: 2px; +} diff --git a/web-frontend/modules/core/assets/scss/components/builder/theme/color_theme_config_block.scss b/web-frontend/modules/core/assets/scss/components/builder/theme/color_theme_config_block.scss index 2ab09add1..ee77f1f46 100644 --- a/web-frontend/modules/core/assets/scss/components/builder/theme/color_theme_config_block.scss +++ b/web-frontend/modules/core/assets/scss/components/builder/theme/color_theme_config_block.scss @@ -2,3 +2,32 @@ display: flex; justify-content: flex-end; } + +.color-theme-config-block__color-preview { + display: block; + width: 16px; + height: 16px; + border-radius: 2px; + position: relative; + border: 1px solid $palette-neutral-400; +} + +.color-theme-config-block__color-preview::before { + content: ''; + position: absolute; + inset: 0; + background-size: 14px 14px; + background-image: conic-gradient( + $white 90deg, + $color-neutral-400 90deg 180deg, + $white 180deg 270deg, + $color-neutral-400 270deg + ); +} + +.color-theme-config-block__color-preview::after { + content: ''; + position: absolute; + inset: 0; + background-color: var(--preview-color, black); +} diff --git a/web-frontend/modules/core/assets/scss/components/builder/theme/theme_config_block.scss b/web-frontend/modules/core/assets/scss/components/builder/theme/theme_config_block.scss index 2a7b71427..39aaf7f9e 100644 --- a/web-frontend/modules/core/assets/scss/components/builder/theme/theme_config_block.scss +++ b/web-frontend/modules/core/assets/scss/components/builder/theme/theme_config_block.scss @@ -5,7 +5,7 @@ display: flex; place-content: center space-between; margin-bottom: 15px; - width: 60%; + width: calc(60% - 10px); padding: 0; user-select: none; @@ -25,10 +25,18 @@ .theme-config-block { position: relative; + &:not(.theme-config-block--no-preview) { + background: linear-gradient( + 90deg, + transparent calc(60% + 14px), + var(--page-background-color, transparent) calc(40% - 14px) + ); + } + &:not(.theme-config-block--no-preview)::after { @include absolute(0, calc(40% - 14px), 0, auto); content: ''; - border-right: 1px solid $color-neutral-100; + border-right: 1px solid $color-neutral-200; } } diff --git a/web-frontend/modules/core/assets/scss/components/builder/theme/theme_config_block_section.scss b/web-frontend/modules/core/assets/scss/components/builder/theme/theme_config_block_section.scss index e93b03267..acd275b00 100644 --- a/web-frontend/modules/core/assets/scss/components/builder/theme/theme_config_block_section.scss +++ b/web-frontend/modules/core/assets/scss/components/builder/theme/theme_config_block_section.scss @@ -1,13 +1,13 @@ .theme-config-block-section { display: flex; width: 100%; - gap: 28px; + gap: 34px; margin-bottom: 15px; } .theme-config-block-section__properties { - max-width: 60%; - flex: 60% 0 0; + max-width: calc(60% - 10px); + flex: calc(60% - 10px) 0 0; .theme-config-block--no-preview & { max-width: 100%; @@ -17,11 +17,12 @@ .theme-config-block-section__preview { flex: 1; + max-width: calc(40% - 14px); + overflow: hidden; + padding-right: 14px; + padding-top: 4px; display: flex; flex-direction: column; - justify-content: flex-start; - max-width: calc(40% - 15px); - overflow: hidden; .theme-config-block--no-preview & { display: none; diff --git a/web-frontend/modules/core/assets/scss/components/dashboard/all.scss b/web-frontend/modules/core/assets/scss/components/dashboard/all.scss index c19a721f5..773991c1a 100644 --- a/web-frontend/modules/core/assets/scss/components/dashboard/all.scss +++ b/web-frontend/modules/core/assets/scss/components/dashboard/all.scss @@ -7,6 +7,6 @@ @import 'dashboard_widget'; @import 'dashboard_summary_widget'; @import 'create_widget_button'; -@import 'widget_header'; +@import 'widget'; @import 'widget_settings_base_form'; @import 'create_widget_modal'; diff --git a/web-frontend/modules/core/assets/scss/components/dashboard/dashboard_summary_widget.scss b/web-frontend/modules/core/assets/scss/components/dashboard/dashboard_summary_widget.scss index 20283267c..591f1c3f1 100644 --- a/web-frontend/modules/core/assets/scss/components/dashboard/dashboard_summary_widget.scss +++ b/web-frontend/modules/core/assets/scss/components/dashboard/dashboard_summary_widget.scss @@ -1,5 +1,5 @@ .dashboard-summary-widget { - padding: 0 24px 24px; + // nothing } .dashboard-summary-widget__summary { @@ -7,7 +7,6 @@ font-size: 40px; font-weight: 600; line-height: 40px; - margin-top: 16px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; @@ -16,3 +15,11 @@ .dashboard-summary-widget__summary--misconfigured { color: #cdcecf; } + +.dashboard-summary-widget__loading { + height: 120px; + + .dashboard-summary-widget--with-header-description & { + height: 141.8px; + } +} diff --git a/web-frontend/modules/core/assets/scss/components/dashboard/widget.scss b/web-frontend/modules/core/assets/scss/components/dashboard/widget.scss new file mode 100644 index 000000000..91730655c --- /dev/null +++ b/web-frontend/modules/core/assets/scss/components/dashboard/widget.scss @@ -0,0 +1,62 @@ +.widget__header { + display: flex; + flex-direction: row; + align-items: start; + gap: 7px; + padding: 20px 24px; + border-bottom: 1px solid $palette-neutral-200; + position: relative; + height: auto; + + &--no-border { + border-bottom: none; + padding-bottom: 0; + } + + &--edit-mode { + padding: 20px 55px 20px 24px; + } +} + +.widget__header-main { + display: flex; + flex-direction: column; + min-width: 0; +} + +.widget__header-context-menu { + margin-left: auto; + width: 46px; + position: absolute; + right: 0; + top: 8px; +} + +.widget__header-title-wrapper { + display: flex; + align-items: center; + gap: 14px; + height: 20px; +} + +.widget__header-title { + color: $palette-neutral-1200; + font-size: 16px; + font-weight: 500; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +.widget__header-description { + @extend %ellipsis; + + color: #6a6b70; + font-size: 12px; + font-weight: 400; + margin-top: 8px; +} + +.widget__content { + padding: 20px; +} diff --git a/web-frontend/modules/core/assets/scss/components/dashboard/widget_header.scss b/web-frontend/modules/core/assets/scss/components/dashboard/widget_header.scss deleted file mode 100644 index f8b2d55ae..000000000 --- a/web-frontend/modules/core/assets/scss/components/dashboard/widget_header.scss +++ /dev/null @@ -1,57 +0,0 @@ -.widget-header { - display: flex; - flex-direction: row; - align-items: start; - gap: 7px; -} - -.widget-header__main { - padding-top: 24px; - overflow: hidden; -} - -.widget-header__context-menu { - flex-grow: 1; - text-align: right; - margin: 6px -14px 0 7px; - width: 46px; -} - -.widget-header__title-wrapper { - display: flex; - gap: 7px; -} - -.widget-header__title { - color: $palette-neutral-1200; - font-size: 16px; - font-weight: 500; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; -} - -.widget-header__description { - color: #6a6b70; - font-size: 12px; - font-weight: 400; - margin-top: 8px; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; -} - -.widget-header__fix-configuration { - display: flex; - align-items: center; - gap: 6px; - color: #b23f30; - font-size: 10px; - font-weight: 500; - line-height: 12px; - letter-spacing: 0.2px; - padding: 4px 8px; - border-radius: 80px; - background: #fff2f0; - white-space: nowrap; -} diff --git a/web-frontend/modules/core/assets/scss/components/integrations/local_baserow/local_baserow_adhoc_header.scss b/web-frontend/modules/core/assets/scss/components/integrations/local_baserow/local_baserow_adhoc_header.scss index 9429fb3b6..0975c572e 100644 --- a/web-frontend/modules/core/assets/scss/components/integrations/local_baserow/local_baserow_adhoc_header.scss +++ b/web-frontend/modules/core/assets/scss/components/integrations/local_baserow/local_baserow_adhoc_header.scss @@ -1,10 +1,40 @@ -.local-baserow-adhoc-header__container { - .header__filter-item { - margin-left: 0; +.local-baserow-adhoc-header { + gap: 5px; + display: flex; +} - &.header__filter-item--right { - margin-left: auto; - margin-right: 0; +.local-baserow-adhoc-header__item { + .header__search { + .header__search-icon { + font-size: inherit; + color: inherit; } } + + .header__filter-link { + // We use the button style for these links + color: var(--button-text-color, $white); + background-color: var(--button-background-color, $black); + font-size: var(--button-font-size, 12px); + font-weight: var(--button-font-weight, 400); + border: var(--button-border-size, 0) solid var(--button-border-color, black); + border-radius: var(--button-border-radius, 4px); + font-family: var(--button-font-family, Inter); + padding: var(--button-vertical-padding, 4px) + var(--button-horizontal-padding, 12px); + height: auto; + line-height: 1em; + + &:hover { + background-color: var(--button-hover-background-color, $black); + border-color: var(--button-hover-border-color, $white); + color: var(--button-hover-text-color, $white); + text-decoration: none; + } + } + + .header__filter-icon { + font-size: inherit; + color: inherit; + } } diff --git a/web-frontend/modules/core/assets/scss/components/segment_control.scss b/web-frontend/modules/core/assets/scss/components/segment_control.scss index 677cc8ec4..93ac2345d 100644 --- a/web-frontend/modules/core/assets/scss/components/segment_control.scss +++ b/web-frontend/modules/core/assets/scss/components/segment_control.scss @@ -7,6 +7,10 @@ @include rounded($rounded-md); } +.segment-control--rounded { + border-radius: 80px; +} + .segment-control--small:not(.segment-control--icons-only) { padding: 0; } @@ -42,6 +46,10 @@ @include flex-align-items(5px); @include rounded($rounded); + .segment-control--rounded & { + border-radius: 80px; + } + &:hover { background: $palette-neutral-200; color: $palette-neutral-1200; @@ -51,6 +59,11 @@ height: 36px; } + .segment-control--large & { + height: 52px; + font-size: 14px; + } + .segment-control--icons-only & { width: 36px; height: 36px; diff --git a/web-frontend/modules/core/assets/scss/components/sortings.scss b/web-frontend/modules/core/assets/scss/components/sortings.scss index e0a686d3e..54951de90 100644 --- a/web-frontend/modules/core/assets/scss/components/sortings.scss +++ b/web-frontend/modules/core/assets/scss/components/sortings.scss @@ -102,6 +102,10 @@ display: flex; } +.sortings__order-dropdown { + width: 170px; +} + .sortings__order-item { justify-content: center; flex-wrap: nowrap; diff --git a/web-frontend/modules/core/assets/scss/components/webhook.scss b/web-frontend/modules/core/assets/scss/components/webhook.scss index f3ed8a593..c300c7a0d 100644 --- a/web-frontend/modules/core/assets/scss/components/webhook.scss +++ b/web-frontend/modules/core/assets/scss/components/webhook.scss @@ -117,6 +117,7 @@ width: 262px; display: flex; align-items: center; + z-index: 2; } .webhook__type-dropdown { diff --git a/web-frontend/modules/core/assets/scss/variables.scss b/web-frontend/modules/core/assets/scss/variables.scss index 981f2b8c3..31a91fc05 100644 --- a/web-frontend/modules/core/assets/scss/variables.scss +++ b/web-frontend/modules/core/assets/scss/variables.scss @@ -80,7 +80,7 @@ $baserow-icons: 'circle-empty', 'circle-checked', 'check-square', 'formula', 'calendar', 'smile', 'smartphone', 'plus', 'heading-1', 'heading-2', 'heading-3', 'paragraph', 'ordered-list', 'enlarge', 'share', 'settings', 'up-down-arrows', 'application', 'groups', 'timeline', 'dashboard', 'jira', - 'postgresql', 'hubspot'; + 'postgresql', 'hubspot', 'separator', 'spacer'; $grid-view-row-height-small: 33px; $grid-view-row-height-medium: 55px; diff --git a/web-frontend/modules/core/components/SegmentControl.vue b/web-frontend/modules/core/components/SegmentControl.vue index c514c9eeb..b79df8f15 100644 --- a/web-frontend/modules/core/components/SegmentControl.vue +++ b/web-frontend/modules/core/components/SegmentControl.vue @@ -5,6 +5,8 @@ 'segment-control--transparent': transparent, 'segment-control--icons-only': iconsOnly, 'segment-control--small': size === 'small', + 'segment-control--large': size === 'large', + 'segment-control--rounded': type === 'rounded', }" > <button @@ -68,7 +70,15 @@ export default { required: false, default: 'regular', validator: function (value) { - return ['regular', 'small'].includes(value) + return ['regular', 'small', 'large'].includes(value) + }, + }, + type: { + type: String, + required: false, + default: 'regular', + validator: function (value) { + return ['regular', 'rounded'].includes(value) }, }, }, @@ -82,6 +92,9 @@ export default { this.activeIndex = index this.$emit('update:activeIndex', index) }, + reset() { + this.activeIndex = this.initialActiveIndex + }, }, } </script> diff --git a/web-frontend/modules/core/components/SwitchButton.vue b/web-frontend/modules/core/components/SwitchButton.vue new file mode 100644 index 000000000..290803711 --- /dev/null +++ b/web-frontend/modules/core/components/SwitchButton.vue @@ -0,0 +1,65 @@ +<template> + <ButtonIcon + type="secondary" + v-bind="restProps" + :loading="loading" + :disabled="disabled" + :icon="icon" + :title="title" + :active="value" + @click.prevent="select()" + > + <slot></slot> + </ButtonIcon> +</template> + +<script> +export default { + name: 'SwitchButton', + model: { + prop: 'modelValue', + event: 'input', + }, + props: { + value: { + type: Boolean, + required: true, + default: false, + }, + loading: { + type: Boolean, + required: false, + default: false, + }, + disabled: { + type: Boolean, + required: false, + default: false, + }, + icon: { + type: String, + required: false, + default: '', + }, + title: { + type: String, + required: false, + default: '', + }, + }, + computed: { + restProps() { + const { value, modelValue, ...rest } = this.$attrs + return rest + }, + }, + methods: { + select() { + if (this.disabled) { + return + } + this.$emit('input', !this.value) + }, + }, +} +</script> diff --git a/web-frontend/modules/core/components/admin/users/forms/ChangePasswordForm.vue b/web-frontend/modules/core/components/admin/users/forms/ChangePasswordForm.vue index 187464959..e7859052e 100644 --- a/web-frontend/modules/core/components/admin/users/forms/ChangePasswordForm.vue +++ b/web-frontend/modules/core/components/admin/users/forms/ChangePasswordForm.vue @@ -6,7 +6,6 @@ :label="$t('changePasswordForm.newPassword')" class="margin-bottom-2" > - {{ v$.values }} <PasswordInput v-model="values.password" :validation-state="v$.values.password" diff --git a/web-frontend/modules/core/components/admin/users/forms/UserForm.vue b/web-frontend/modules/core/components/admin/users/forms/UserForm.vue index 2c8a7ed22..461d8de98 100644 --- a/web-frontend/modules/core/components/admin/users/forms/UserForm.vue +++ b/web-frontend/modules/core/components/admin/users/forms/UserForm.vue @@ -12,6 +12,7 @@ v-model="v$.values.name.$model" size="large" :error="fieldHasErrors('name')" + @blur="v$.values.name.$touch" > </FormInput> @@ -40,6 +41,7 @@ v-model="v$.values.username.$model" size="large" :error="fieldHasErrors('username')" + @blur="v$.values.username.$touch" > </FormInput> diff --git a/web-frontend/modules/core/components/editor/RichTextEditor.vue b/web-frontend/modules/core/components/editor/RichTextEditor.vue index 6bde0f3bb..1bc410aa3 100644 --- a/web-frontend/modules/core/components/editor/RichTextEditor.vue +++ b/web-frontend/modules/core/components/editor/RichTextEditor.vue @@ -110,6 +110,8 @@ const richTextEditorExtensions = ({ Markdown.configure({ html: false, breaks: true, + transformPastedText: true, + transformCopiedText: true, }), History, ] @@ -287,6 +289,15 @@ export default { return true } }, + handlePaste: (view, event) => { + const plainText = event.clipboardData.getData('text/plain') + if (plainText.startsWith('"') && plainText.endsWith('"')) { + const cleanText = plainText.slice(1, -1) + this.editor.commands.insertContent(cleanText) + return true + } + return false + }, }, extensions, onUpdate: () => { @@ -337,7 +348,6 @@ export default { this.registerResizeObserver() this.registerAutoCollapseFloatingMenuHandler() this.registerAutoHideBubbleMenuHandler() - this.registerOnPasteHandler() } else { this.unregisterResizeObserver() } @@ -368,12 +378,6 @@ export default { elem.removeEventListener('scroll', handler) }) }, - registerOnPasteHandler() { - document.addEventListener('paste', this.onPaste) - this.$once('hook:unmounted', () => { - document.removeEventListener('paste', this.onPaste) - }) - }, renderHTMLMention() { const loggedUserId = this.loggedUserId const isUserInWorkspace = (userId) => @@ -476,22 +480,6 @@ export default { this.dragTarget = null } }, - onPaste(event) { - if ( - !event.clipboardData.types.includes('text/plain') || - event.clipboardData.getData('text/plain').startsWith('file:///') - ) { - const { items } = event.clipboardData - for (const item of items) { - if (item.type.includes('image')) { - const file = item.getAsFile() - this.uploadFiles([file]) - return true - } - } - } - return false - }, }, } </script> diff --git a/web-frontend/modules/core/components/export/ExportWorkspaceModal.vue b/web-frontend/modules/core/components/export/ExportWorkspaceModal.vue index c7fb2417b..05574f270 100644 --- a/web-frontend/modules/core/components/export/ExportWorkspaceModal.vue +++ b/web-frontend/modules/core/components/export/ExportWorkspaceModal.vue @@ -122,7 +122,6 @@ export default { const { data: job } = await ExportWorkspaceService( this.$client ).exportApplications(this.workspace.id, values) - this.job = job await this.createAndMonitorJob(job) } catch (error) { this.createLoading = false @@ -187,9 +186,6 @@ export default { }, getCustomHumanReadableJobState(jobState) { - if (jobState === EXPORT_SERIALIZED_EXPORTING) { - return this.$t('exportWorkspaceModal.exportingState') - } if (jobState.startsWith(EXPORT_SERIALIZED_EXPORTING_TABLE)) { return this.$t('exportWorkspaceModal.exportingTableState', { table: jobState.replace(EXPORT_SERIALIZED_EXPORTING_TABLE, ''), @@ -198,6 +194,9 @@ export default { if (jobState === EXPORT_WORKSPACE_CREATE_ARCHIVE) { return this.$t('exportWorkspaceModal.exportingCreateArchiveState') } + if (jobState === EXPORT_SERIALIZED_EXPORTING) { + return this.$t('exportWorkspaceModal.exportingState') + } return '' }, }, diff --git a/web-frontend/modules/core/components/files/UploadViaURLUserFileUpload.vue b/web-frontend/modules/core/components/files/UploadViaURLUserFileUpload.vue index a53c08f32..d037414e8 100644 --- a/web-frontend/modules/core/components/files/UploadViaURLUserFileUpload.vue +++ b/web-frontend/modules/core/components/files/UploadViaURLUserFileUpload.vue @@ -13,6 +13,7 @@ v-model="v$.values.url.$model" size="large" :error="v$.values.url.$error" + @blur="v$.values.url.$touch()" > </FormInput> diff --git a/web-frontend/modules/core/components/health/EmailTester.vue b/web-frontend/modules/core/components/health/EmailTester.vue index e53cdff1b..bab726947 100644 --- a/web-frontend/modules/core/components/health/EmailTester.vue +++ b/web-frontend/modules/core/components/health/EmailTester.vue @@ -36,6 +36,7 @@ v-model="v$.values.targetEmail.$model" :error="fieldHasErrors('targetEmail')" :disabled="loading" + @blur="v$.values.targetEmail.$touch" ></FormInput> <template #error> diff --git a/web-frontend/modules/core/components/import/ImportWorkspaceModal.vue b/web-frontend/modules/core/components/import/ImportWorkspaceModal.vue index 8b3e49487..6bb2c451c 100644 --- a/web-frontend/modules/core/components/import/ImportWorkspaceModal.vue +++ b/web-frontend/modules/core/components/import/ImportWorkspaceModal.vue @@ -111,7 +111,11 @@ import ImportWorkspaceForm from '@baserow/modules/core/components/import/ImportW import { notifyIf } from '@baserow/modules/core/utils/error' import { ImportApplicationsJobType } from '@baserow/modules/core/jobTypes' import { ResponseErrorMessage } from '@baserow/modules/core/plugins/clientHandler' -import { IMPORT_SERIALIZED_IMPORTING } from '@baserow/modules/core/constants' +import { + IMPORT_SERIALIZED_IMPORTING, + IMPORT_SERIALIZED_IMPORTING_TABLE_STRUCTURE, + IMPORT_SERIALIZED_IMPORTING_TABLE_DATA, +} from '@baserow/modules/core/constants' const STAGES = { UPLOAD: 'upload', @@ -284,7 +288,6 @@ export default { const { data: job } = await ImportWorkspaceService( this.$client ).triggerImport(this.workspace.id, this.resourceId) - this.job = job await this.createAndMonitorJob(job) } catch (error) { this.importing = false @@ -293,6 +296,19 @@ export default { }, getCustomHumanReadableJobState(jobState) { + if (jobState.startsWith(IMPORT_SERIALIZED_IMPORTING_TABLE_STRUCTURE)) { + return this.$t('importWorkspaceModal.importingTableStructure', { + table: jobState.replace( + IMPORT_SERIALIZED_IMPORTING_TABLE_STRUCTURE, + '' + ), + }) + } + if (jobState.startsWith(IMPORT_SERIALIZED_IMPORTING_TABLE_DATA)) { + return this.$t('importWorkspaceModal.importingTableData', { + table: jobState.replace(IMPORT_SERIALIZED_IMPORTING_TABLE_DATA, ''), + }) + } if (jobState.startsWith(IMPORT_SERIALIZED_IMPORTING)) { return this.$t('importWorkspaceModal.importingState') } diff --git a/web-frontend/modules/core/components/onboarding/WorkspaceStep.vue b/web-frontend/modules/core/components/onboarding/WorkspaceStep.vue index c1cca6036..3c034793f 100644 --- a/web-frontend/modules/core/components/onboarding/WorkspaceStep.vue +++ b/web-frontend/modules/core/components/onboarding/WorkspaceStep.vue @@ -10,6 +10,7 @@ size="large" :error="v$.name.$error" @input="updateValue" + @blur="v$.name.$touch" /> <template #error> {{ v$.name.$errors[0]?.$message }} </template> </FormGroup> diff --git a/web-frontend/modules/core/components/settings/AccountForm.vue b/web-frontend/modules/core/components/settings/AccountForm.vue index a53aef252..8ff13438a 100644 --- a/web-frontend/modules/core/components/settings/AccountForm.vue +++ b/web-frontend/modules/core/components/settings/AccountForm.vue @@ -12,6 +12,7 @@ v-model="v$.values.first_name.$model" size="large" :error="fieldHasErrors('first_name')" + @blur="v$.values.first_name.$touch" ></FormInput> <template #error> diff --git a/web-frontend/modules/core/components/snapshots/CreateSnapshotForm.vue b/web-frontend/modules/core/components/snapshots/CreateSnapshotForm.vue index 5982c68d1..ab9ad64c7 100644 --- a/web-frontend/modules/core/components/snapshots/CreateSnapshotForm.vue +++ b/web-frontend/modules/core/components/snapshots/CreateSnapshotForm.vue @@ -13,6 +13,7 @@ size="large" :error="fieldHasErrors('name')" class="snapshots-modal__name-input" + @blur="v$.values.name.$touch" /> </slot> diff --git a/web-frontend/modules/core/components/snapshots/SnapshotsModal.vue b/web-frontend/modules/core/components/snapshots/SnapshotsModal.vue index ded55a47d..cd92911a2 100644 --- a/web-frontend/modules/core/components/snapshots/SnapshotsModal.vue +++ b/web-frontend/modules/core/components/snapshots/SnapshotsModal.vue @@ -151,7 +151,6 @@ export default { this.application.id, values ) - this.job = job await this.createAndMonitorJob(job) } catch (error) { this.createLoading = false @@ -167,6 +166,7 @@ export default { ) { this.snapshots.unshift(this.job.snapshot) } + this.$refs.form.v$.$reset() }, onJobFailed() { this.createLoading = false diff --git a/web-frontend/modules/core/components/template/TemplatePreview.vue b/web-frontend/modules/core/components/template/TemplatePreview.vue index 1fae1076a..095b5fc48 100644 --- a/web-frontend/modules/core/components/template/TemplatePreview.vue +++ b/web-frontend/modules/core/components/template/TemplatePreview.vue @@ -102,20 +102,22 @@ export default { populateApplication(application, this.$registry) ) - // Check if there is an application that can give us an initial page. The - // database application type would for example return the first table as page. - for (let i = 0; i < this.applications.length; i++) { - const application = this.applications[i] - const pageValue = this.$registry - .get('application', application.type) - .getTemplatePage(application) - if (pageValue !== null) { - application._.selected = true - this.selectPage({ - application: application.type, - value: pageValue, - }) - break + // A template can optionally have a preferred application that must be opened + // first in the preview. Try to select that one, and if that's not possible, + // then try to select the first application of the template. + const openApplication = this.applications.find( + (a) => a.id === this.template.open_application + ) + if (openApplication) { + this.selectApplication(openApplication) + } else { + // Check if there is an application that can give us an initial page. The + // database application type would for example return the first table as page. + for (let i = 0; i < this.applications.length; i++) { + const application = this.applications[i] + if (this.selectApplication(application)) { + break + } } } } catch (error) { @@ -125,6 +127,20 @@ export default { this.loading = false } }, + selectApplication(application) { + const pageValue = this.$registry + .get('application', application.type) + .getTemplatePage(application) + if (pageValue !== null) { + application._.selected = true + this.selectPage({ + application: application.type, + value: pageValue, + }) + return true + } + return false + }, selectPage({ application, value }) { this.page = { application, diff --git a/web-frontend/modules/core/components/workspace/WorkspaceForm.vue b/web-frontend/modules/core/components/workspace/WorkspaceForm.vue index dd9c2c130..4bb8f6094 100644 --- a/web-frontend/modules/core/components/workspace/WorkspaceForm.vue +++ b/web-frontend/modules/core/components/workspace/WorkspaceForm.vue @@ -12,6 +12,7 @@ :error="fieldHasErrors('name')" size="large" @focus.once="$event.target.select()" + @blur="v$.values.name.$touch" ></FormInput> <template #error>{{ $t('error.requiredField') }}</template> diff --git a/web-frontend/modules/core/constants.js b/web-frontend/modules/core/constants.js index f755d21d7..8da2f035c 100644 --- a/web-frontend/modules/core/constants.js +++ b/web-frontend/modules/core/constants.js @@ -1,4 +1,7 @@ export const IMPORT_SERIALIZED_IMPORTING = 'importing' +export const IMPORT_SERIALIZED_IMPORTING_TABLE_STRUCTURE = + 'importing-table-structure-' +export const IMPORT_SERIALIZED_IMPORTING_TABLE_DATA = 'importing-table-data-' export const EXPORT_SERIALIZED_EXPORTING = 'exporting' export const EXPORT_SERIALIZED_EXPORTING_TABLE = 'exporting-table-' export const EXPORT_WORKSPACE_CREATE_ARCHIVE = 'create-archive' diff --git a/web-frontend/modules/core/locales/de.json b/web-frontend/modules/core/locales/de.json index 2031ec2e6..8e943f531 100644 --- a/web-frontend/modules/core/locales/de.json +++ b/web-frontend/modules/core/locales/de.json @@ -129,7 +129,9 @@ "leaveWorkspace": "Arbeitsbereich verlassen", "deleteWorkspace": "Arbeitsbereich löschen", "auditLog": "Audit-Log", - "settings": "Einstellungen" + "settings": "Einstellungen", + "importWorkspace": "Daten importieren", + "exportWorkspace": "Daten exportieren" }, "createWorkspaceModal": { "createNew": "Neuen Arbeitsbereich erstellen", @@ -260,9 +262,9 @@ "knowledgeBaseMessage": "Finden Sie Antworten auf all Ihre Fragen" }, "login": { - "title": "Anmeldung", - "forgotPassword": "Passwort vergessen?", - "signUpText": "Sie haben noch kein Konto?", + "title": "Willkommen zurück", + "forgotPassword": "Vergessen?", + "signUpText": "Neu bei Baserow?", "emailPlaceholder": "Geben Sie Ihre E-Mail Adresse ein.", "passwordPlaceholder": "Geben Sie Ihr Passwort ein..", "signUp": "Anmelden", @@ -280,10 +282,11 @@ "errorLinkExpiredTitle": "Link abgelaufen", "errorLinkExpiredMessage": "Der Link zum Zurücksetzen des Passworts ist abgelaufen. Bitte fordern Sie ein neues an.", "disabled": "Passwort-Zurücksetzung ist deaktiviert", - "disabledMessage": "Es ist nicht möglich, ein Passwort zurückzusetzen, da es deaktiviert wurde." + "disabledMessage": "Es ist nicht möglich, ein Passwort zurückzusetzen, da es deaktiviert wurde.", + "message": "Sie können sich jetzt mit Ihrem neuen Passwort bei Baserow anmelden." }, "signup": { - "headTitle": "Neues Konto erstellen", + "headTitle": "Konto erstellen", "title": "Registrieren Sie sich", "disabled": "Registrierung ist deaktiviert", "disabledMessage": "Es ist nicht möglich, ein Konto zu erstellen, da es deaktiviert wurde.", @@ -294,16 +297,21 @@ "passwordPlaceholder": "Geben Sie Ihr Passwort ein.", "loginText": "Sie haben bereits ein Konto?", "passwordRepeatPlaceholder": "Bestätigen Sie Ihr Passwort..", - "login": "Einloggen" + "login": "Einloggen", + "privacyPolicy": "Datenschutzerklärung", + "terms": "Nutzungsbedingungen", + "agreeTerms": "Mit der Erstellung eines Kontos erklären Sie sich einverstanden mit {0} {1} {2}" }, "forgotPassword": { "title": "Passwort vergessen", - "message": "Bitte geben Sie Ihre E-Mail-Adresse in das Formular ein. Wenn wir ein Konto finden, senden wir Ihnen eine E-Mail mit einem Link zum Zurücksetzen Ihres Passworts.", + "message": "Geben Sie Ihre E-Mail-Adresse ein, damit wir Ihnen einen Link zum Zurücksetzen Ihres Passworts zusenden können.", "submit": "Link senden", - "confirmation": "Wenn Ihre E-Mail-Adresse in unserer Datenbank vorhanden ist, erhalten Sie in wenigen Minuten einen Link zum Zurücksetzen des Passworts an Ihre E-Mail-Adresse.", + "confirmation": "Wir haben eine E-Mail an {email} gesendet, die einen Link zum Zurücksetzen Ihres Baserow-Passworts enthält.", "disabled": "Passwort-Zurücksetzung ist deaktiviert", "disabledMessage": "Es ist nicht möglich, ein Passwort zurückzusetzen, da es deaktiviert wurde.", - "loginText": "Sie haben bereits ein Konto und ein Passwort?" + "loginText": "Sie haben bereits ein Konto und ein Passwort?", + "confirmationTitle": "Rufen Sie Ihre E-Mails ab", + "goBack": "Zurück" }, "settings": { "settingsTitle": "Administrator-Einstellungen", @@ -333,7 +341,11 @@ "emailVerification": "E-Mail-Verifizierung", "emailVerificationDescription": "Gibt an, ob E-Mailadressen bestätigt werden müssen.", "emailVerificationRecommended": "Empfohlen", - "emailVerificationEnforced": "Erzwungen" + "emailVerificationEnforced": "Erzwungen", + "settingsVerifyImportSignatureDescription": "Wenn diese Funktion aktiviert ist, wird die Signatur der importierten Daten überprüft um sicherzustellen, dass die Daten nicht manipuliert wurden.", + "baserowVersion": "Baserow-Version", + "settingsVerifyImportSignature": "Import-Signatur prüfen", + "baserowVersionDescription": "Die Versionsnummer dieser Instanz." }, "undoRedoNotification": { "redoingText": "Deine Aktion wird wieder hergestellt", @@ -462,7 +474,9 @@ "stateFinished": "Abgeschlossen", "stateFailed": "Gescheitert", "errorJobAlreadyRunningTitle": "Wird bereits ausgeführt", - "errorJobAlreadyRunningDescription": "Es läuft bereits ein anderer Importauftrag. Sie müssen warten, bis dieser beendet ist, bevor Sie einen weiteren Auftrag starten." + "errorJobAlreadyRunningDescription": "Es läuft bereits ein anderer Importauftrag. Sie müssen warten, bis dieser beendet ist, bevor Sie einen weiteren Auftrag starten.", + "errorJobCannotBeCancelledDescription": "Es ist nicht möglich, den Auftrag abzubrechen, da er bereits abgeschlossen ist.\nBitte löschen Sie den ersten Snapshot in der untenstehenden Liste, um ihn zu entfernen.", + "errorJobCannotBeCancelledTitle": "Abbrechen nicht möglich" }, "datetime": { "daysAgo": "vor 0 Tagen | vor 1 Tag | vor {n} Tagen", @@ -470,7 +484,9 @@ "yearsAgo": "vor 0 Jahren | vor 1 Jahr | vor {n} Jahren", "hoursAgo": "vor 0 Stunden | vor 1 Stunde | vor {n} Stunden", "secondsAgo": "Gerade eben | vor 1 Sekunde | {n} Sekunden zuvor", - "minutesAgo": "vor 0 Minuten | vor 1 Minute | vor {n} Minuten" + "minutesAgo": "vor 0 Minuten | vor 1 Minute | vor {n} Minuten", + "lessThanMinuteAgo": "vor weniger als einer Minute", + "justNow": "gerade eben" }, "duplicateApplicationJobType": { "duplicating": "Duplizieren", @@ -591,7 +607,7 @@ "title": "Sitzung abgelaufen" }, "restoreToast": { - "restore": "Gelöschten {type} wiederherstellen" + "restore": "{type} (gelöscht) wiederherstellen" }, "copyingToast": { "title": "Kopieren...", @@ -728,7 +744,22 @@ "ollamaHostDescription": "Geben Sie den Hostnamen Ihres [Ollama](https://ollama.com/)-Servers an. Dieser läuft normalerweise lokal auf Ihrem eigenen Gerät.", "ollamaModelsLabel": "Aktivierte Modelle", "ollama": "Ollama", - "ollamaHostLabel": "Host" + "ollamaHostLabel": "Host", + "anthropic": "Anthropic", + "anthropicApiKeyLabel": "API-Schlüssel", + "anthropicModelsLabel": "Aktivierte Modelle", + "mistral": "Mistral", + "mistralApiKeyLabel": "API-Schlüssel", + "anthropicApiKeyDescription": "Geben Sie einen Anthropic-API-Schlüssel an, wenn Sie die Integration aktivieren möchten. [Anweisungen zum Erhalt eines API-Schlüssels](https://docs.anthropic.com/en/api/getting-started).", + "anthropicModelsDescription": "Geben Sie eine durch Kommata getrennte Liste von [Anthropic-Modellen](https://docs.anthropic.com/en/docs/about-claude/models) an, die in Baserow verwendet werden können. (z.B. `claude-3-5-sonnet-20241022,claude-3-opus-20240229`)", + "mistralApiKeyDescription": "Geben Sie einen Mistral-API-Schlüssel an, wenn Sie die Integration aktivieren möchten. [Anleitung zum Erhalt eines API-Schlüssels](https://docs.mistral.ai/getting-started/quickstart/).", + "mistralModelsLabel": "Aktivierte Modelle", + "mistralModelsDescription": "Geben Sie eine durch Kommata getrennte Liste von [Mistral-Modellen](https://docs.mistral.ai/getting-started/models/models_overview/) an, die in Baserow verwendet werden können. (z.B. `mistral-large-latest, mistral-small-latest`)", + "openRouterApiKeyDescription": "Geben Sie einen OpenRouter-API-Schlüssel an, wenn Sie die Integration aktivieren möchten. [Einen API-Schlüssel erhalten](https://openrouter.ai/settings/keys).", + "openRouter": "OpenRouter", + "openRouterApiKeyLabel": "API-Schlüssel", + "openRouterOrganization": "Organisation (optional)", + "openRouterModelsLabel": "Aktivierte Modelle" }, "emailNotVerified": { "title": "Bestätigung der E-Mailadresse notwendig", @@ -918,5 +949,49 @@ "activeUsers7days": "Aktive Benutzer in den letzten 7 Tagen", "activeUsers30days": "Aktive Benutzer in den letzten 30 Tagen", "viewAll": "Alle anzeigen" + }, + "exportWorkspaceModal": { + "title": "Exportieren", + "description": "Ihre Daten werden als ZIP-Datei exportiert, die in andere Baserow-Instanzen importiert werden kann.", + "exportSettings": "Einstellungen exportieren", + "export": "Daten exportieren", + "reset": "Von vorne beginnen", + "cancel": "Abbrechen", + "download": "Herunterladen", + "noExports": "Für diesen Arbeitsbereich gibt es noch keine Exporte.", + "created": "erstellt", + "exportingState": "Exportiere", + "exportingTableState": "Exportiere Tabelle: {table}", + "exportingCreateArchiveState": "Erstelle Archiv" + }, + "exportWorkspaceForm": { + "onlyStructureLabel": "Nur die Struktur exportieren", + "onlyStructureDescription": "Wenn diese Option aktiviert ist, wird nur die Struktur der Anwendungen exportiert. Die Daten werden nicht enthalten sein.", + "exportSettingsLabel": "Einstellungen exportieren" + }, + "importWorkspaceModal": { + "databases": "Datenbanken", + "untrustedPublicKeyMessage": "Die bereitgestellte Datei wurde mit einem nicht vertrauenswürdigen öffentlichen Schlüssel signiert. Bitten Sie Ihren Administrator, den öffentlichen Schlüssel zur Liste der vertrauenswürdigen Schlüssel hinzuzufügen oder die Signaturprüfung zu deaktivieren, um diese Datei importieren zu können.", + "retry": "Wiederholen", + "description": "Sie können bestehende Baserow-Daten importieren, indem Sie die .zip-Datei einer anderen Baserow-Instanz hochladen.", + "import": "Daten importieren", + "upload": "Hochladen", + "cancel": "Abbrechen", + "done": "Abgeschlossen", + "close": "Schließen", + "uploading": "Hochladen...", + "chooseFile": "Datei auswählen", + "selectApplications": "Zu importierende Daten auswählen", + "deselectAll": "Alle abwählen", + "selectAll": "Alle auswählen", + "applications": "Anwendungen", + "successTitle": "Baserow-Daten erfolgreich importiert", + "successMessage": "{count} Anwendungen importiert", + "signatureVerificationNote": "Es ist nicht möglich, eine ZIP-Datei aus einer nicht vertrauenswürdigen Quelle zu importieren.", + "invalidResourceTitle": "Ungültige Ressource", + "invalidResourceMessage": "Die bereitgestellte Datei ist kein gültiger Baserow-Export.", + "untrustedPublicKeyTitle": "Nicht vertrauenswürdige Signatur", + "importingState": "Importiere", + "title": "Baserow-Daten importieren" } } diff --git a/web-frontend/modules/core/locales/en.json b/web-frontend/modules/core/locales/en.json index d225947dd..7c2227552 100644 --- a/web-frontend/modules/core/locales/en.json +++ b/web-frontend/modules/core/locales/en.json @@ -135,8 +135,8 @@ "reset": "Start new", "cancel": "Cancel", "download": "Download", - "exportingState": "Exporting", - "exportingTableState": "Exporting table: {table}", + "exportingState": "Exporting...", + "exportingTableState": "Exporting: {table}", "exportingCreateArchiveState": "Creating archive", "noExports": "No exports for this workspace yet.", "created": "created" @@ -169,7 +169,9 @@ "invalidResourceMessage": "The provided file is not a valid Baserow export.", "untrustedPublicKeyTitle": "Untrusted signature", "untrustedPublicKeyMessage": "The provided file is signed with an untrusted public key. Ask your administrator to add the public key to the list of trusted keys or disable the signature verification to be able to import this file.", - "importingState": "Importing" + "importingState": "Importing...", + "importingTableStructure": "Creating: {table}", + "importingTableData": "Importing data: {table}" }, "dashboardWorkspace": { "createApplication": "Create new" @@ -475,10 +477,7 @@ "passwordPlaceholder": "Enter your password..", "passwordRepeatPlaceholder": "Confirm your password..", "loginText": "Already have an account?", - "login": "Login", - "agreeTerms": "By creating an account, you agree to the {0} {1} {2}", - "terms": "Terms of Service", - "privacyPolicy": "Privacy Policy" + "login": "Login" }, "forgotPassword": { "title": "Forgot password", diff --git a/web-frontend/modules/core/locales/fr.json b/web-frontend/modules/core/locales/fr.json index c4b22dcf7..3105333e9 100644 --- a/web-frontend/modules/core/locales/fr.json +++ b/web-frontend/modules/core/locales/fr.json @@ -875,8 +875,8 @@ "noExports": "Il n'y a pas d'export pour ce projet.", "created": "Créé le", "importingState": "Import en cours", - "exportingState": "Export en cours", - "exportingTableState": "Export de la table :{table}", + "exportingState": "Export en cours...", + "exportingTableState": "Export en cours : {table}", "exportingCreateArchiveState": "Création de l'archive" }, "exportWorkspaceForm": { @@ -907,7 +907,9 @@ "import": "Importer", "done": "Valider", "databases": "Bases de données", - "importingState": "Import en cours" + "importingState": "Import en cours...", + "importingTableStructure": "Création en cours : {table}", + "importingTableData": "Import en cours : {table}" }, "user": { "isStaff": "Est collaborateur", diff --git a/web-frontend/modules/core/locales/ko.json b/web-frontend/modules/core/locales/ko.json index 4dc3dbe66..ba1f69911 100644 --- a/web-frontend/modules/core/locales/ko.json +++ b/web-frontend/modules/core/locales/ko.json @@ -24,7 +24,7 @@ "sidebar": { "createWorkspace": "작업공간 생성", "addNewWorkspace": "새 작업공간 추가", - "inviteOthers": "다른 사람 초대", + "inviteOthers": "초대", "members": "멤버", "logoff": "로그아웃", "errorNoWorkspace": "작업공간이 없습니다.", diff --git a/web-frontend/modules/core/locales/nl.json b/web-frontend/modules/core/locales/nl.json index e0d22fb40..d89c0f7af 100644 --- a/web-frontend/modules/core/locales/nl.json +++ b/web-frontend/modules/core/locales/nl.json @@ -907,7 +907,9 @@ "invalidResourceMessage": "Het geleverde bestand is geen geldige Baserow export.", "untrustedPublicKeyTitle": "Onbetrouwbare handtekening", "untrustedPublicKeyMessage": "Het geleverde bestand is ondertekend met een onbetrouwbare openbare sleutel. Vraag je beheerder om de openbare sleutel toe te voegen aan de lijst van vertrouwde sleutels of de handtekeningverificatie uit te schakelen om dit bestand te kunnen importeren.", - "importingState": "Importeren" + "importingState": "Importeren", + "importingTableStructure": "Aanmaken: {table}", + "importingTableData": "Gegevens importeren: {tabel}" }, "user": { "isStaff": "Is personeel", diff --git a/web-frontend/modules/core/middleware/authentication.js b/web-frontend/modules/core/middleware/authentication.js index ad74e7f0d..bec03ca74 100644 --- a/web-frontend/modules/core/middleware/authentication.js +++ b/web-frontend/modules/core/middleware/authentication.js @@ -1,12 +1,18 @@ import { getTokenIfEnoughTimeLeft, setToken, + setUserSessionCookie, } from '@baserow/modules/core/utils/auth' export default function ({ store, req, app, route, redirect }) { // If nuxt generate or already authenticated, pass this middleware if ((process.server && !req) || store.getters['auth/isAuthenticated']) return + const userSession = route.query.user_session + if (userSession) { + setUserSessionCookie(app, userSession) + } + // token can be in the query string (SSO) or in the cookies (previous session) let refreshToken = route.query.token if (refreshToken) { diff --git a/web-frontend/modules/core/mixins/form.js b/web-frontend/modules/core/mixins/form.js index 68431bbe6..43bf24c90 100644 --- a/web-frontend/modules/core/mixins/form.js +++ b/web-frontend/modules/core/mixins/form.js @@ -23,11 +23,15 @@ export default { return { // A list of values that the form allows. If null all values are allowed. allowedValues: null, - // By setting emitValuesOnReset to false in the form's component - // the values changed event won't be sent right after resetting the - // form - emitValuesOnReset: true, - isAfterReset: true, + // Setting to false make it possible to temporarily + // prevent emitting values when they change. + // Use setEmitValues(value) method to include children + // forms. + emitValues: true, + // Setting to true makes it possible to not + // emit values the first time values are set in + // the form. + skipFirstValuesEmit: false, } }, mounted() { @@ -38,7 +42,13 @@ export default { watch: { values: { handler(newValues) { - this.emitChange(newValues) + if (this.skipFirstValuesEmit) { + this.skipFirstValuesEmit = false + return + } + if (this.emitValues) { + this.emitChange(newValues) + } }, deep: true, }, @@ -200,6 +210,12 @@ export default { }) ) }, + isDirty() { + for (const [key, value] of Object.entries(this.getDefaultValues())) { + if (this.values[key] !== value) return true + } + return false + }, /** * Resets the form and the child forms to its original state. * @@ -207,8 +223,6 @@ export default { * first level of children. */ async reset(deep = false) { - this.isAfterReset = true - for (const [key, value] of Object.entries(this.getDefaultValues())) { this.values[key] = value } @@ -224,6 +238,15 @@ export default { child.reset() ) }, + /** + * Sets emitValues property also to child forms. + */ + setEmitValues(value) { + this.emitValues = value + this.getChildForms((child) => 'setEmitValues' in child, true).forEach( + (child) => child.setEmitValues(value) + ) + }, /** * Returns if a child form has indicated it handled the error, false otherwise. */ @@ -241,13 +264,7 @@ export default { return childHandledIt }, emitChange(newValues) { - if (this.emitValuesOnReset === true || this.isAfterReset === false) { - this.$emit('values-changed', newValues) - } - - if (this.isAfterReset) { - this.isAfterReset = false - } + this.$emit('values-changed', newValues) }, }, } diff --git a/web-frontend/modules/core/mixins/job.js b/web-frontend/modules/core/mixins/job.js index f361ddcb0..f08e9bbcc 100644 --- a/web-frontend/modules/core/mixins/job.js +++ b/web-frontend/modules/core/mixins/job.js @@ -91,8 +91,7 @@ export default { * @returns {Promise<void>} */ async createAndMonitorJob(job) { - await this.$store.dispatch('job/create', job) - this.job = job + this.job = await this.$store.dispatch('job/create', job) }, /** * Called from a component to cancel any job currently running. diff --git a/web-frontend/modules/core/pages/admin/health.vue b/web-frontend/modules/core/pages/admin/health.vue index a8339b262..9dc78a443 100644 --- a/web-frontend/modules/core/pages/admin/health.vue +++ b/web-frontend/modules/core/pages/admin/health.vue @@ -11,7 +11,7 @@ <div> <div v-for="(status, checkName) in healthChecks" - :key="status" + :key="checkName" class="admin-health__check-item" > <div class="admin-health__check-item-label"> diff --git a/web-frontend/modules/core/pages/resetPassword.vue b/web-frontend/modules/core/pages/resetPassword.vue index 94e0d76fc..77e4e05a2 100644 --- a/web-frontend/modules/core/pages/resetPassword.vue +++ b/web-frontend/modules/core/pages/resetPassword.vue @@ -167,7 +167,7 @@ export default { const token = this.$route.params.token await AuthService(this.$client).resetPassword( token, - this.state.password + this.account.password ) this.success = true this.loading = false diff --git a/web-frontend/modules/core/pages/signup.vue b/web-frontend/modules/core/pages/signup.vue index 4d97bc2be..c8e474005 100644 --- a/web-frontend/modules/core/pages/signup.vue +++ b/web-frontend/modules/core/pages/signup.vue @@ -36,11 +36,7 @@ </template> <template v-else> <template v-if="loginButtons.length"> - <LoginButtons - :invitation="invitation" - :original="original" - :hide-if-no-buttons="true" - /> + <LoginButtons :invitation="invitation" :hide-if-no-buttons="true" /> <div class="auth__separator"> {{ $t('common.or') }} @@ -57,25 +53,7 @@ <LoginActions v-if="!shouldShowAdminSignupPage" :invitation="invitation" - > - <!-- <li class="auth__action-link"> - <i18n path="signup.agreeTerms" tag="span"> - <a - href="https://baserow.io/terms-and-conditions" - target="_blank" - @click.stop - >{{ $t('signup.terms') }} - </a> - {{ $t('common.and') }} - <a - href="https://baserow.io/privacy-policy" - target="_blank" - @click.stop - >{{ $t('signup.privacyPolicy') }} - </a> - </i18n> - </li> --> - </LoginActions> + ></LoginActions> </template> </template> </div> @@ -135,11 +113,6 @@ export default { loginButtons: 'authProvider/getAllLoginButtons', passwordLoginEnabled: 'authProvider/getPasswordLoginEnabled', }), - termsofServiceURL() { - return this.$nuxt.$router.resolve({ - name: 'terms', - }).href - }, }, methods: { next(params) { diff --git a/web-frontend/modules/core/pages/workspace.vue b/web-frontend/modules/core/pages/workspace.vue index 91139edcc..1c3eb0b7d 100644 --- a/web-frontend/modules/core/pages/workspace.vue +++ b/web-frontend/modules/core/pages/workspace.vue @@ -272,7 +272,11 @@ export default { // here. const plugins = Object.values(app.$registry.getAll('plugin')) for (let i = 0; i < plugins.length; i++) { - asyncData = await plugins[i].fetchAsyncDashboardData(context, asyncData) + asyncData = await plugins[i].fetchAsyncDashboardData( + context, + asyncData, + workspace.id + ) } return asyncData } catch (e) { diff --git a/web-frontend/modules/core/plugins/featureFlags.js b/web-frontend/modules/core/plugins/featureFlags.js index 670410a5a..9622f2880 100644 --- a/web-frontend/modules/core/plugins/featureFlags.js +++ b/web-frontend/modules/core/plugins/featureFlags.js @@ -1,6 +1,4 @@ const FF_ENABLE_ALL = '*' -export const FF_DASHBOARDS = 'dashboards' -export const FF_AB_SSO = 'ab_sso' /** * A comma separated list of feature flags used to enable in-progress or not ready diff --git a/web-frontend/modules/core/plugins/global.js b/web-frontend/modules/core/plugins/global.js index 543a800ba..c85fd6eb5 100644 --- a/web-frontend/modules/core/plugins/global.js +++ b/web-frontend/modules/core/plugins/global.js @@ -61,6 +61,7 @@ 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 SelectSearch from '@baserow/modules/core/components/SelectSearch' +import SwitchButton from '@baserow/modules/core/components/SwitchButton' function setupVue(Vue) { Vue.component('Context', Context) @@ -111,6 +112,7 @@ function setupVue(Vue) { Vue.component('ReadOnlyForm', ReadOnlyForm) Vue.component('FormSection', FormSection) Vue.component('SegmentControl', SegmentControl) + Vue.component('SwitchButton', SwitchButton) Vue.filter('lowercase', lowercase) Vue.filter('uppercase', uppercase) diff --git a/web-frontend/modules/core/plugins/realTimeHandler.js b/web-frontend/modules/core/plugins/realTimeHandler.js index e642242f6..4808adcfb 100644 --- a/web-frontend/modules/core/plugins/realTimeHandler.js +++ b/web-frontend/modules/core/plugins/realTimeHandler.js @@ -413,7 +413,19 @@ export class RealTimeHandler { }) this.registerEvent('job_started', ({ store }, data) => { - store.dispatch('job/create', data.job) + try { + store.dispatch('job/create', data.job) + } catch (err) { + // TODO: some job types have no frontend handlers (JobType subclasses) + // registered. This will cause an error during creation. The proper fix + // would be to add missing JobTypes. + if ( + err.message !== + `The type ${data.job.type} is not found under namespace job in the registry.` + ) { + throw err + } + } }) } } diff --git a/web-frontend/modules/core/store/job.js b/web-frontend/modules/core/store/job.js index 1d905e965..410607264 100644 --- a/web-frontend/modules/core/store/job.js +++ b/web-frontend/modules/core/store/job.js @@ -5,6 +5,14 @@ const FINISHED_STATES = ['finished', 'failed', 'cancelled'] const STARTING_TIMEOUT_MS = 200 const MAX_POLLING_ATTEMPTS = 100 +/** + * Calls job-type specific routine to enhance job object with any job-type specific + * properties. This may return `null` if job type is not registered. + * + * @param job + * @param registry + * @returns {*|null} + */ export function populateJob(job, registry) { const type = registry.get('job', job.type) return type.populate(job) @@ -31,8 +39,17 @@ export const mutations = { SET_ITEMS(state, items) { state.items = items }, + /** + * Adds new job to the store. + * Adding job might be triggered from various places i.e. backend POST response + * or from websocket message. In those cases we want to make sure we don't add + * the same job multiple times. + */ ADD_ITEM(state, item) { - state.items.push(item) + const existingJobIndex = state.items.findIndex((job) => job.id === item.id) + if (existingJobIndex === -1) { + state.items.push(item) + } }, UPDATE_ITEM(state, { id, values }) { const index = state.items.findIndex((item) => item.id === id) @@ -180,6 +197,7 @@ export const actions = { create({ dispatch }, job) { dispatch('forceCreate', job) dispatch('tryScheduleNextUpdate') + return this.getters['job/get'](job.id) }, /** diff --git a/web-frontend/modules/dashboard/components/data_source/AggregateRowsDataSourceForm.vue b/web-frontend/modules/dashboard/components/data_source/AggregateRowsDataSourceForm.vue index 71f548e5f..43e61484d 100644 --- a/web-frontend/modules/dashboard/components/data_source/AggregateRowsDataSourceForm.vue +++ b/web-frontend/modules/dashboard/components/data_source/AggregateRowsDataSourceForm.vue @@ -110,6 +110,9 @@ :key="viewAggregation.getType()" :name="viewAggregation.getName()" :value="viewAggregation.getType()" + :disabled=" + unsupportedAggregationTypes.includes(viewAggregation.getType()) + " > </DropdownItem> </Dropdown> @@ -170,7 +173,7 @@ export default { }, tableLoading: false, databaseSelectedId: null, - emitValuesOnReset: false, + skipFirstValuesEmit: true, } }, computed: { @@ -224,16 +227,23 @@ export default { aggregationTypeNames() { return this.viewAggregationTypes.map((aggType) => aggType.getType()) }, + unsupportedAggregationTypes() { + return this.$registry.get('service', 'local_baserow_aggregate_rows') + .unsupportedAggregationTypes + }, }, watch: { dataSource: { - handler(values) { + async handler(values) { + this.setEmitValues(false) // Reset the form to set default values // again after a different widget is selected - this.reset(true) + await this.reset(true) // Run form validation so that // problems are highlighted immediately - this.v$.$validate() + this.v$.$touch() + await this.$nextTick() + this.setEmitValues(true) }, deep: true, }, diff --git a/web-frontend/modules/dashboard/components/widget/DashboardWidget.vue b/web-frontend/modules/dashboard/components/widget/DashboardWidget.vue index f0bd7d66b..ab305bab3 100644 --- a/web-frontend/modules/dashboard/components/widget/DashboardWidget.vue +++ b/web-frontend/modules/dashboard/components/widget/DashboardWidget.vue @@ -12,14 +12,12 @@ </div> <component :is="widgetComponent(widget.type)" - v-if="isLoading === false" :dashboard="dashboard" :widget="widget" :store-prefix="storePrefix" + :loading="isLoading" + :edit-mode="isEditMode" /> - <div v-else> - <div class="dashboard-widget__loading"></div> - </div> </div> </template> diff --git a/web-frontend/modules/dashboard/components/widget/SummaryWidget.vue b/web-frontend/modules/dashboard/components/widget/SummaryWidget.vue index 3ff83e494..9d17efbc9 100644 --- a/web-frontend/modules/dashboard/components/widget/SummaryWidget.vue +++ b/web-frontend/modules/dashboard/components/widget/SummaryWidget.vue @@ -1,45 +1,46 @@ <template> - <div class="dashboard-summary-widget"> - <div class="widget-header"> - <div class="widget-header__main"> - <div class="widget-header__title-wrapper"> - <div class="widget-header__title">{{ widget.title }}</div> - <div - v-if="dataSourceMisconfigured" - class="widget-header__fix-configuration" - > - <svg - width="5" - height="6" - viewBox="0 0 5 6" - fill="none" - xmlns="http://www.w3.org/2000/svg" + <div + class="dashboard-summary-widget" + :class="{ + 'dashboard-summary-widget--with-header-description': widget.description, + }" + > + <template v-if="!loading"> + <div class="widget__header widget__header--no-border"> + <div class="widget__header-main"> + <div class="widget__header-title-wrapper"> + <div class="widget__header-title">{{ widget.title }}</div> + + <Badge + v-if="dataSourceMisconfigured" + color="red" + indicator + rounded + >{{ $t('widget.fixConfiguration') }}</Badge > - <circle cx="2.5" cy="3" r="2.5" fill="#FF5A44" /> - </svg> - {{ $t('widget.fixConfiguration') }} + </div> + <div v-if="widget.description" class="widget__header-description"> + {{ widget.description }} </div> </div> - <div v-if="widget.description" class="widget-header__description"> - {{ widget.description }} - </div> + <WidgetContextMenu + v-if="isEditMode" + :widget="widget" + :dashboard="dashboard" + @delete-widget="$emit('delete-widget', $event)" + ></WidgetContextMenu> </div> - <WidgetContextMenu - v-if="isEditMode" - :widget="widget" - :dashboard="dashboard" - @delete-widget="$emit('delete-widget', $event)" - ></WidgetContextMenu> - </div> - <div - class="dashboard-summary-widget__summary" - :class="{ - 'dashboard-summary-widget__summary--misconfigured': - dataSourceMisconfigured, - }" - > - {{ result }} - </div> + <div + class="widget__content dashboard-summary-widget__summary" + :class="{ + 'dashboard-summary-widget__summary--misconfigured': + dataSourceMisconfigured, + }" + > + {{ result }} + </div> + </template> + <div v-else class="dashboard-summary-widget__loading loading-spinner"></div> </div> </template> @@ -63,6 +64,11 @@ export default { required: false, default: '', }, + loading: { + type: Boolean, + required: false, + default: false, + }, }, computed: { dataSource() { diff --git a/web-frontend/modules/dashboard/components/widget/WidgetContextMenu.vue b/web-frontend/modules/dashboard/components/widget/WidgetContextMenu.vue index a465ed5e3..38b191d1c 100644 --- a/web-frontend/modules/dashboard/components/widget/WidgetContextMenu.vue +++ b/web-frontend/modules/dashboard/components/widget/WidgetContextMenu.vue @@ -1,11 +1,11 @@ <template> - <div ref="contextButton" class="widget-header__context-menu"> + <div ref="contextButton" class="widget__header-context-menu"> <ButtonIcon icon="iconoir-more-vert" type="secondary" size="regular" @click.stop=" - $refs.context.toggle($refs.contextButton, 'bottom', 'right', 8, 0) + $refs.context.toggle($refs.contextButton, 'bottom', 'right', 8, -8) " ></ButtonIcon> <WidgetContext diff --git a/web-frontend/modules/dashboard/components/widget/WidgetSettingsBaseForm.vue b/web-frontend/modules/dashboard/components/widget/WidgetSettingsBaseForm.vue index 18c96d4df..c5d91d740 100644 --- a/web-frontend/modules/dashboard/components/widget/WidgetSettingsBaseForm.vue +++ b/web-frontend/modules/dashboard/components/widget/WidgetSettingsBaseForm.vue @@ -71,7 +71,7 @@ export default { title: '', description: '', }, - emitValuesOnReset: false, + skipFirstValuesEmit: true, } }, validations() { @@ -98,8 +98,16 @@ export default { }, watch: { widget: { - handler(value) { - this.reset(true) + async handler(value) { + this.setEmitValues(false) + // Reset the form to set default values + // again after a different widget is selected + await this.reset(true) + // Run form validation so that + // problems are highlighted immediately + this.v$.$touch() + await this.$nextTick() + this.setEmitValues(true) }, deep: true, }, diff --git a/web-frontend/modules/dashboard/plugin.js b/web-frontend/modules/dashboard/plugin.js index d21f8b1b4..8c4834691 100644 --- a/web-frontend/modules/dashboard/plugin.js +++ b/web-frontend/modules/dashboard/plugin.js @@ -11,7 +11,6 @@ import { registerRealtimeEvents } from '@baserow/modules/dashboard/realtime' import { DashboardApplicationType } from '@baserow/modules/dashboard/applicationTypes' import { SummaryWidgetType } from '@baserow/modules/dashboard/widgetTypes' import dashboardApplicationStore from '@baserow/modules/dashboard/store/dashboardApplication' -import { FF_DASHBOARDS } from '@baserow/modules/core/plugins/featureFlags' export default (context) => { const { app, isDev, store } = context @@ -37,8 +36,6 @@ export default (context) => { dashboardApplicationStore ) - if (app.$featureFlagIsEnabled(FF_DASHBOARDS)) { - app.$registry.register('application', new DashboardApplicationType(context)) - app.$registry.register('dashboardWidget', new SummaryWidgetType(context)) - } + app.$registry.register('application', new DashboardApplicationType(context)) + app.$registry.register('dashboardWidget', new SummaryWidgetType(context)) } diff --git a/web-frontend/modules/dashboard/store/dashboardApplication.js b/web-frontend/modules/dashboard/store/dashboardApplication.js index 20ecb364d..af4294519 100644 --- a/web-frontend/modules/dashboard/store/dashboardApplication.js +++ b/web-frontend/modules/dashboard/store/dashboardApplication.js @@ -174,19 +174,32 @@ export const actions = { } }) }, - async createWidget({ dispatch }, { dashboard, widget }) { - const { data } = await WidgetService(this.$client).create( - dashboard.id, - widget - ) + async createWidget({ commit, dispatch }, { dashboard, widget }) { + const tempId = Date.now() + commit('ADD_WIDGET', { id: tempId, ...widget }) + let widgetData + try { + const { data } = await WidgetService(this.$client).create( + dashboard.id, + widget + ) + widgetData = data + } catch (error) { + commit('DELETE_WIDGET', tempId) + throw error + } return await dispatch('handleNewWidgetCreated', { - ...data, + tempWidgetId: tempId, + createdWidget: widgetData, }) }, - async handleNewWidgetCreated({ commit, dispatch }, createdWidget) { - commit('ADD_WIDGET', createdWidget) - await dispatch('fetchNewDataSources', createdWidget.dashboard_id) + async handleNewWidgetCreated( + { commit, dispatch }, + { tempWidgetId, createdWidget } + ) { + commit('UPDATE_WIDGET', { widgetId: tempWidgetId, values: createdWidget }) dispatch('selectWidget', createdWidget.id) + await dispatch('fetchNewDataSources', createdWidget.dashboard_id) }, async dispatchDataSource({ commit }, dataSourceId) { commit('UPDATE_DATA', { dataSourceId, values: null }) diff --git a/web-frontend/modules/database/components/dataSync/ConfigureDataSyncModal.vue b/web-frontend/modules/database/components/dataSync/ConfigureDataSyncModal.vue index 8087d52ec..36ab5c903 100644 --- a/web-frontend/modules/database/components/dataSync/ConfigureDataSyncModal.vue +++ b/web-frontend/modules/database/components/dataSync/ConfigureDataSyncModal.vue @@ -1,5 +1,9 @@ <template> - <Modal :left-sidebar="true" :left-sidebar-scrollable="true"> + <Modal + :left-sidebar="true" + :left-sidebar-scrollable="true" + @hidden="$emit('hidden')" + > <template #sidebar> <div class="modal-sidebar__head"> <div class="modal-sidebar__head-name"> @@ -64,6 +68,15 @@ export default { }, }, methods: { + show(selectedPage, ...args) { + if ( + selectedPage && + this.$registry.exists('configureDataSync', selectedPage) + ) { + this.selectedPage = selectedPage + } + modal.methods.show.bind(this)(...args) + }, setPage(page) { this.selectedPage = page }, diff --git a/web-frontend/modules/database/components/dataSync/ConfigureDataSyncSettings.vue b/web-frontend/modules/database/components/dataSync/ConfigureDataSyncSettings.vue index af171fd66..d77a69662 100644 --- a/web-frontend/modules/database/components/dataSync/ConfigureDataSyncSettings.vue +++ b/web-frontend/modules/database/components/dataSync/ConfigureDataSyncSettings.vue @@ -118,7 +118,13 @@ export default { } }, async submitted(values) { - await this.update(this.table, values, this.syncTableValue) + // Remove the `undefined` values, because those contain not updated secrets that + // are only meant to be included in the update request if they've changed + // because they're not exposed by the backend. + const valuesWithoutUndefined = Object.fromEntries( + Object.entries(values).filter(([_, v]) => v !== undefined) + ) + await this.update(this.table, valuesWithoutUndefined, this.syncTableValue) if (!this.syncTableValue) { this.completed = true } diff --git a/web-frontend/modules/database/components/dataSync/PostgreSQLDataSync.vue b/web-frontend/modules/database/components/dataSync/PostgreSQLDataSync.vue index b2c52a7b9..ee58db7a0 100644 --- a/web-frontend/modules/database/components/dataSync/PostgreSQLDataSync.vue +++ b/web-frontend/modules/database/components/dataSync/PostgreSQLDataSync.vue @@ -35,13 +35,8 @@ small-label :protected-edit="update && field.protectedEdit" class="margin-bottom-2" - @enabled-protected-edit="allowedValues.push(field.name)" - @disable-protected-edit=" - ;[ - allowedValues.splice(allowedValues.indexOf(field.name), 1), - delete values[field.name], - ] - " + @enabled-protected-edit="values.postgresql_password = ''" + @disable-protected-edit="values.postgresql_password = undefined" > <template #label>{{ $t(`postgreSQLDataSync.${field.translationPrefix}`) @@ -52,6 +47,7 @@ :type="field.type" :error="fieldHasErrors(field.name)" :disabled="disabled" + @blur="v$.values[field.name].$touch()" > </FormInput> <template #error> @@ -72,6 +68,7 @@ size="large" :error="fieldHasErrors('postgresql_port')" :disabled="disabled" + @blur="v$.values.postgresql_port.$touch" > </FormInput> <template #error> @@ -129,13 +126,11 @@ export default { 'postgresql_username', 'postgresql_port', 'postgresql_database', + 'postgresql_password', 'postgresql_schema', 'postgresql_table', 'postgresql_sslmode', ] - if (!this.update) { - allowedValues.push('postgresql_password') - } return { allowedValues, values: { @@ -143,6 +138,9 @@ export default { postgresql_username: '', postgresql_port: '5432', postgresql_database: '', + // If `undefined`, it's not included in the patch update request, and will then + // not be changed. + postgresql_password: this.update ? undefined : '', postgresql_schema: 'public', postgresql_table: '', postgresql_sslmode: 'prefer', @@ -176,7 +174,7 @@ export default { required: helpers.withMessage( this.$t('error.requiredField'), requiredIf(() => { - return this.allowedValues.includes('postgresql_password') + return this.values.postgresql_password !== undefined }) ), }, diff --git a/web-frontend/modules/database/components/field/CreateFieldContext.vue b/web-frontend/modules/database/components/field/CreateFieldContext.vue index 44f9dc1a0..f0eef019f 100644 --- a/web-frontend/modules/database/components/field/CreateFieldContext.vue +++ b/web-frontend/modules/database/components/field/CreateFieldContext.vue @@ -15,6 +15,7 @@ :view="view" :forced-type="forcedType" :all-fields-in-table="allFieldsInTable" + :default-values="defaultValues" :database="database" @submitted="submit" @keydown-enter="$refs.submitButton.focus()" @@ -88,6 +89,11 @@ export default { return { loading: false, showDescription: false, + defaultValues: { + name: '', + type: this.forcedType || '', + description: null, + }, } }, methods: { diff --git a/web-frontend/modules/database/components/field/FieldDateSubForm.vue b/web-frontend/modules/database/components/field/FieldDateSubForm.vue index 72f8b46f0..f391de3b4 100644 --- a/web-frontend/modules/database/components/field/FieldDateSubForm.vue +++ b/web-frontend/modules/database/components/field/FieldDateSubForm.vue @@ -75,7 +75,8 @@ :add-empty-item="false" :initial-display-name="defaultValues.date_force_timezone" :fetch-on-open="true" - :debounce-time="100" + :debounce-time="20" + :page-size="pageSize" :fixed-items="true" @input="(timezone) => (values.date_force_timezone = timezone)" ></PaginatedDropdown> @@ -141,6 +142,7 @@ export default { date_force_timezone: null, date_force_timezone_offset: null, }, + pageSize: 100, } }, computed: { @@ -187,7 +189,7 @@ export default { }, methods: { fetchTimezonePage(page, search) { - const pageSize = 20 + const pageSize = this.pageSize const start = (page - 1) * pageSize const results = this.filterTimezones(search || '') // The paginate dropdown expects a HTTP response-like object with these properties diff --git a/web-frontend/modules/database/components/field/FieldForm.vue b/web-frontend/modules/database/components/field/FieldForm.vue index 186a20c1e..1db00544d 100644 --- a/web-frontend/modules/database/components/field/FieldForm.vue +++ b/web-frontend/modules/database/components/field/FieldForm.vue @@ -7,6 +7,7 @@ v-model="v$.values.name.$model" :error="fieldHasErrors('name')" :placeholder="$t('fieldForm.name')" + @blur="v$.values.name.$touch()" @input="isPrefilledWithSuggestedFieldName = false" @keydown.enter="handleKeydownEnter($event)" ></FormInput> @@ -157,9 +158,9 @@ export default { return { allowedValues: ['name', 'type', 'description'], values: { - name: '', - type: this.forcedType || '', - description: null, + name: this.defaultValues.name, + type: this.forcedType || this.defaultValues.type, + description: this.defaultValues.description, }, isPrefilledWithSuggestedFieldName: false, oldValueType: null, @@ -222,7 +223,7 @@ export default { required ), maxLength: helpers.withMessage( - this.$t('error.nameTooLong'), + this.$t('fieldForm.nameTooLong'), maxLength(MAX_FIELD_NAME_LENGTH) ), mustHaveUniqueFieldName: helpers.withMessage( @@ -230,7 +231,7 @@ export default { this.mustHaveUniqueFieldName ), mustNotClashWithReservedName: helpers.withMessage( - this.$t('error.nameNotAllowed'), + this.$t('fieldForm.nameNotAllowed'), this.mustNotClashWithReservedName ), }, diff --git a/web-frontend/modules/database/components/field/FieldLookupSubForm.vue b/web-frontend/modules/database/components/field/FieldLookupSubForm.vue index fc1e0a68c..f656cc686 100644 --- a/web-frontend/modules/database/components/field/FieldLookupSubForm.vue +++ b/web-frontend/modules/database/components/field/FieldLookupSubForm.vue @@ -16,6 +16,7 @@ ></FieldSelectTargetFieldSubForm> <template v-if="selectedTargetField"> <FormulaTypeSubForms + ref="subForm" :default-values="subFormDefaultValues" :formula-type="targetFieldFormulaType" :table="table" @@ -31,6 +32,7 @@ <script> import form from '@baserow/modules/core/mixins/form' import fieldSubForm from '@baserow/modules/database/mixins/fieldSubForm' +import lookupFieldSubForm from '@baserow/modules/database/mixins/lookupFieldSubForm' import FormulaTypeSubForms from '@baserow/modules/database/components/formula/FormulaTypeSubForms' import FieldSelectThroughFieldSubForm from '@baserow/modules/database/components/field/FieldSelectThroughFieldSubForm' import FieldSelectTargetFieldSubForm from '@baserow/modules/database/components/field/FieldSelectTargetFieldSubForm' @@ -42,77 +44,6 @@ export default { FieldSelectTargetFieldSubForm, FormulaTypeSubForms, }, - mixins: [form, fieldSubForm], - data() { - return { - selectedThroughField: null, - selectedTargetField: null, - allowedValues: [], - values: {}, - errorFromServer: null, - subFormDefaultValues: {}, - } - }, - computed: { - targetFieldFormulaType() { - if (this.selectedTargetField) { - return this.getFormulaType(this.selectedTargetField) - } - return 'unknown' - }, - }, - watch: { - defaultValues: { - handler(newDefaultValues) { - this.subFormDefaultValues = { ...newDefaultValues } - }, - immediate: true, - }, - selectedTargetField: { - handler(newTargetField) { - if (!newTargetField) { - return - } - const fieldType = this.$registry.get('field', newTargetField.type) - const formulaType = fieldType.toBaserowFormulaType(newTargetField) - - const formulaTypeChanged = - formulaType && this.getFormulaType(this.defaultValues) !== formulaType - - // New field or different type, use the relevant settings from the target field - const fieldValues = this.defaultValues - if (!fieldValues.id || formulaTypeChanged) { - for (const key in this.selectedTargetField) { - if (key.startsWith(formulaType)) { - this.subFormDefaultValues[key] = this.selectedTargetField[key] - } - } - } - }, - }, - }, - methods: { - getFormulaType(field) { - return field.array_formula_type || field.formula_type || field.type - }, - handleErrorByForm(error) { - if ( - [ - 'ERROR_WITH_FORMULA', - 'ERROR_FIELD_SELF_REFERENCE', - 'ERROR_FIELD_CIRCULAR_REFERENCE', - ].includes(error.handler.code) - ) { - this.errorFromServer = error.handler.detail - return true - } else { - return false - } - }, - reset() { - form.methods.reset.call(this) - this.errorFromServer = null - }, - }, + mixins: [form, fieldSubForm, lookupFieldSubForm], } </script> diff --git a/web-frontend/modules/database/components/field/FieldRollupSubForm.vue b/web-frontend/modules/database/components/field/FieldRollupSubForm.vue index 8d7dca4ca..914947125 100644 --- a/web-frontend/modules/database/components/field/FieldRollupSubForm.vue +++ b/web-frontend/modules/database/components/field/FieldRollupSubForm.vue @@ -39,7 +39,8 @@ </FormGroup> <FormulaTypeSubForms - :default-values="defaultValues" + ref="subForm" + :default-values="subFormDefaultValues" :formula-type="targetFieldFormulaType" :table="table" :view="view" @@ -60,6 +61,7 @@ import { required } from '@vuelidate/validators' import form from '@baserow/modules/core/mixins/form' import fieldSubForm from '@baserow/modules/database/mixins/fieldSubForm' +import lookupFieldSubForm from '@baserow/modules/database/mixins/lookupFieldSubForm' import FormulaTypeSubForms from '@baserow/modules/database/components/formula/FormulaTypeSubForms' import FieldSelectThroughFieldSubForm from '@baserow/modules/database/components/field/FieldSelectThroughFieldSubForm' import FieldSelectTargetFieldSubForm from '@baserow/modules/database/components/field/FieldSelectTargetFieldSubForm' @@ -71,58 +73,25 @@ export default { FieldSelectTargetFieldSubForm, FormulaTypeSubForms, }, - mixins: [form, fieldSubForm], + mixins: [form, fieldSubForm, lookupFieldSubForm], setup() { return { v$: useVuelidate({ $lazy: true }) } }, data() { return { - selectedThroughField: null, - selectedTargetField: null, allowedValues: ['rollup_function'], values: { rollup_function: null, }, - errorFromServer: null, } }, computed: { - targetFieldFormulaType() { - if (this.selectedTargetField) { - return ( - this.selectedTargetField.array_formula_type || - this.selectedTargetField.type - ) - } - return 'unknown' - }, rollupFunctions() { return Object.values(this.$registry.getAll('formula_function')).filter( (f) => f.isRollupCompatible(this.targetFieldFormulaType) ) }, }, - - methods: { - handleErrorByForm(error) { - if ( - [ - 'ERROR_WITH_FORMULA', - 'ERROR_FIELD_SELF_REFERENCE', - 'ERROR_FIELD_CIRCULAR_REFERENCE', - ].includes(error.handler.code) - ) { - this.errorFromServer = error.handler.detail - return true - } else { - return false - } - }, - reset() { - form.methods.reset.call(this) - this.errorFromServer = null - }, - }, validations() { return { values: { diff --git a/web-frontend/modules/database/components/field/FieldSelectOptions.vue b/web-frontend/modules/database/components/field/FieldSelectOptions.vue index d7b386b75..be82362cb 100644 --- a/web-frontend/modules/database/components/field/FieldSelectOptions.vue +++ b/web-frontend/modules/database/components/field/FieldSelectOptions.vue @@ -6,7 +6,7 @@ class="select-options select-options--scrollable" > <div - v-for="(item, index) in values.value" + v-for="(item, index) in options" :key="item.id" v-sortable="{ id: item.id, @@ -27,9 +27,9 @@ <FormInput ref="inputs" v-model="item.value" - :error="v$.values.value.$each.$response?.$data[index].value.$error" + :error="v$.options.$each.$response?.$data[index].value.$error" @input="$emit('input', value)" - @blur="v$.values.value.$touch" + @blur="v$.options.$touch" /> <ButtonIcon tag="a" @@ -70,36 +70,37 @@ export default { return { colorContextSelected: -1, lastSeenId: -1, - values: { - value: [], - }, + options: [], } }, computed: { usedColors() { const colors = new Set() - this.values.value.forEach((option) => colors.add(option.color)) + this.options.forEach((option) => colors.add(option.color)) return Array.from(colors) }, }, - mounted() { - this.$nextTick(() => { - this.values.value = this.value - }) + watch: { + value: { + immediate: true, + handler(newVal) { + this.options = newVal + }, + }, }, methods: { remove(index) { this.$refs.colorContext.hide() - this.values.value.splice(index, 1) - this.$emit('input', this.values.value) + this.options.splice(index, 1) + this.$emit('input', this.options) }, add(optionValue = '') { - this.values.value.push({ + this.options.push({ value: optionValue, color: randomColor(this.usedColors), id: this.lastSeenId, }) - this.$emit('input', this.values.value) + this.$emit('input', this.options) this.lastSeenId -= 1 this.$nextTick(() => { this.$refs.options.scrollTop = this.$refs.options.scrollHeight @@ -110,7 +111,7 @@ export default { }, openColor(index) { this.colorContextSelected = index - this.$refs.colorContext.setActive(this.values.value[index].color) + this.$refs.colorContext.setActive(this.options[index].color) this.$refs.colorContext.toggle( this.$refs['color-select-' + index][0], 'bottom', @@ -119,11 +120,11 @@ export default { ) }, updateColor(index, color) { - this.values.value[index].color = color + this.options[index].color = color this.$emit('input', this.value) }, order(newOrder, oldOrder) { - const sortedValue = this.value + const sortedValue = this.options .slice() .sort( (a, b) => @@ -135,12 +136,10 @@ export default { }, validations() { return { - values: { - value: { - $each: helpers.forEach({ - value: { required }, - }), - }, + options: { + $each: helpers.forEach({ + value: { required }, + }), }, } }, diff --git a/web-frontend/modules/database/components/form/BlankDatabaseForm.vue b/web-frontend/modules/database/components/form/BlankDatabaseForm.vue index daa396cb1..983765e12 100644 --- a/web-frontend/modules/database/components/form/BlankDatabaseForm.vue +++ b/web-frontend/modules/database/components/form/BlankDatabaseForm.vue @@ -14,6 +14,7 @@ size="large" :placeholder="$t('applicationForm.namePlaceholder')" @focus.once="$event.target.select()" + @blur="v$.values.name.$touch" ></FormInput> <template #error> diff --git a/web-frontend/modules/database/components/formula/FormulaTypeSubForms.vue b/web-frontend/modules/database/components/formula/FormulaTypeSubForms.vue index 6dec9b97c..cb39b9e5b 100644 --- a/web-frontend/modules/database/components/formula/FormulaTypeSubForms.vue +++ b/web-frontend/modules/database/components/formula/FormulaTypeSubForms.vue @@ -1,6 +1,7 @@ <template> <FieldNumberSubForm v-if="formulaType === 'number'" + ref="subForm" :default-values="defaultValues" :table="table" :view="view" @@ -12,6 +13,7 @@ </FieldNumberSubForm> <FieldDateSubForm v-else-if="['date', 'last_modified', 'created_on'].includes(formulaType)" + ref="subForm" :default-values="defaultValues" :table="table" :view="view" @@ -22,6 +24,7 @@ </FieldDateSubForm> <FieldDurationSubForm v-else-if="formulaType === 'duration'" + ref="subForm" :default-values="defaultValues" :table="table" :view="view" @@ -67,5 +70,10 @@ export default { values: {}, } }, + methods: { + isDirty() { + return this.$refs.subForm?.isDirty() + }, + }, } </script> diff --git a/web-frontend/modules/database/components/notifications/WebhookDeactivatedNotification.vue b/web-frontend/modules/database/components/notifications/WebhookDeactivatedNotification.vue new file mode 100644 index 000000000..7ec787bcd --- /dev/null +++ b/web-frontend/modules/database/components/notifications/WebhookDeactivatedNotification.vue @@ -0,0 +1,29 @@ +<template> + <nuxt-link + class="notification-panel__notification-link" + :to="route" + @click.native="markAsReadAndHandleClick" + > + <div class="notification-panel__notification-content-title"> + <i18n path="webhookDeactivatedNotification.body" tag="span"> + <template #name> + <strong>{{ notification.data.webhook_name }}</strong> + </template> + </i18n> + </div> + </nuxt-link> +</template> + +<script> +import notificationContent from '@baserow/modules/core/mixins/notificationContent' + +export default { + name: 'WebhookDeactivatedNotification', + mixins: [notificationContent], + methods: { + handleClick() { + this.$emit('close-panel') + }, + }, +} +</script> diff --git a/web-frontend/modules/database/components/notifications/WebhookPayloadTooLargeNotification.vue b/web-frontend/modules/database/components/notifications/WebhookPayloadTooLargeNotification.vue new file mode 100644 index 000000000..5c2b5ce94 --- /dev/null +++ b/web-frontend/modules/database/components/notifications/WebhookPayloadTooLargeNotification.vue @@ -0,0 +1,35 @@ +<template> + <nuxt-link + class="notification-panel__notification-link" + :to="route" + @click.native="markAsReadAndHandleClick" + > + <div class="notification-panel__notification-content-title"> + <i18n path="webhookPayloadTooLargeNotification.body" tag="span"> + <template #name> + <strong>{{ notification.data.webhook_name }}</strong> + </template> + <template #event_id> + <strong>{{ notification.data.event_id }}</strong> + </template> + <template #batch_limit> + <strong>{{ notification.data.batch_limit }}</strong> + </template> + </i18n> + </div> + </nuxt-link> +</template> + +<script> +import notificationContent from '@baserow/modules/core/mixins/notificationContent' + +export default { + name: 'WebhookPayloadTooLargeNotification', + mixins: [notificationContent], + methods: { + handleClick() { + this.$emit('close-panel') + }, + }, +} +</script> diff --git a/web-frontend/modules/database/components/settings/APITokenForm.vue b/web-frontend/modules/database/components/settings/APITokenForm.vue index 5d20124d2..8916188cd 100644 --- a/web-frontend/modules/database/components/settings/APITokenForm.vue +++ b/web-frontend/modules/database/components/settings/APITokenForm.vue @@ -12,6 +12,7 @@ v-model="v$.values.name.$model" size="large" :error="fieldHasErrors('name')" + @blur="v$.values.name.$touch()" > </FormInput> diff --git a/web-frontend/modules/database/components/table/ImportFileModal.vue b/web-frontend/modules/database/components/table/ImportFileModal.vue index c23d3efdd..115fb90ed 100644 --- a/web-frontend/modules/database/components/table/ImportFileModal.vue +++ b/web-frontend/modules/database/components/table/ImportFileModal.vue @@ -55,7 +55,39 @@ @header="onHeader($event)" @data="onData($event)" @getData="onGetData($event)" - /> + > + <template #upsertMapping> + <div class="control margin-top-1"> + <label class="control__label control__label--small"> + {{ $t('importFileModal.useUpsertField') }} + <HelpIcon + :icon="'info-empty'" + :tooltip="$t('importFileModal.upsertTooltip')" + /> + </label> + <div class="control__elements"> + <Checkbox + v-model="useUpsertField" + :disabled="!mappingNotEmpty" + >{{ $t('common.yes') }}</Checkbox + > + </div> + + <Dropdown + v-model="upsertField" + :disabled="!useUpsertField" + class="margin-top-1" + > + <DropdownItem + v-for="item in availableUpsertFields" + :key="item.id" + :name="item.name" + :value="item.id" + /> + </Dropdown> + </div> + </template> + </component> </div> <ImportErrorReport :job="job" :error="error"></ImportErrorReport> @@ -204,6 +236,8 @@ export default { getData: null, previewData: [], dataLoaded: false, + useUpsertField: false, + upsertField: undefined, } }, computed: { @@ -213,12 +247,19 @@ export default { } return this.database.tables.some(({ id }) => id === this.job.table_id) }, + mappingNotEmpty() { + return Object.values(this.mapping).some( + (value) => this.fieldIndexMap[value] !== undefined + ) + }, canBeSubmitted() { return ( this.importer && Object.values(this.mapping).some( (value) => this.fieldIndexMap[value] !== undefined - ) + ) && + (!this.useUpsertField || + Object.values(this.mapping).includes(this.upsertField)) ) }, fieldTypes() { @@ -307,6 +348,14 @@ export default { selectedFields() { return Object.values(this.mapping) }, + availableUpsertFields() { + const selected = Object.values(this.mapping) + return this.fields.filter((field) => { + return ( + selected.includes(field.id) && this.fieldTypes[field.type].canUpsert() + ) + }) + }, progressPercentage() { switch (this.state) { case null: @@ -417,6 +466,14 @@ export default { this.showProgressBar = false this.reset(false) let data = null + const importConfiguration = {} + + if (this.upsertField) { + // at the moment we use only one field, but the key may be composed of several + // fields. + importConfiguration.upsert_fields = [this.upsertField] + importConfiguration.upsert_values = [] + } if (typeof this.getData === 'function') { try { @@ -425,6 +482,18 @@ export default { await this.$ensureRender() data = await this.getData() + const upsertFields = importConfiguration.upsert_fields || [] + const upsertValues = importConfiguration.upsert_values || [] + const upsertFieldIndexes = [] + + Object.entries(this.mapping).forEach( + ([importIndex, targetFieldId]) => { + if (upsertFields.includes(targetFieldId)) { + upsertFieldIndexes.push(importIndex) + } + } + ) + const fieldMapping = Object.entries(this.mapping) .filter( ([, targetFieldId]) => @@ -456,22 +525,41 @@ export default { // Processes the data by chunk to avoid UI freezes const result = [] + for (const chunk of _.chunk(data, 1000)) { result.push( chunk.map((row) => { const newRow = clone(defaultRow) + const upsertRow = [] fieldMapping.forEach(([importIndex, targetIndex]) => { newRow[targetIndex] = prepareValueByField[targetIndex]( row[importIndex] ) + if (upsertFieldIndexes.includes(importIndex)) { + upsertRow.push(newRow[targetIndex]) + } }) + if (upsertFields.length > 0 && upsertRow.length > 0) { + if (upsertFields.length !== upsertRow.length) { + throw new Error( + "upsert row length doesn't match required fields" + ) + } + upsertValues.push(upsertRow) + } return newRow }) ) await this.$ensureRender() } data = result.flat() + if (upsertFields.length > 0) { + if (upsertValues.length !== data.length) { + throw new Error('upsert values lenght mismatch') + } + importConfiguration.upsert_values = upsertValues + } } catch (error) { this.reset() this.handleError(error, 'application') @@ -493,7 +581,8 @@ export default { data, { onUploadProgress, - } + }, + importConfiguration.upsert_fields ? importConfiguration : null ) this.startJobPoller(job) } catch (error) { diff --git a/web-frontend/modules/database/components/table/Table.vue b/web-frontend/modules/database/components/table/Table.vue index e82da0345..b0ccfd3b4 100644 --- a/web-frontend/modules/database/components/table/Table.vue +++ b/web-frontend/modules/database/components/table/Table.vue @@ -76,6 +76,7 @@ :database="database" :view="view" :table="table" + :views="views" @enable-rename="$refs.rename.edit()" > </ViewContext> @@ -210,9 +211,10 @@ /> </header> <div class="layout__col-2-2 content"> + <DefaultErrorPage v-if="viewError" :error="viewError" /> <component :is="getViewComponent(view)" - v-if="hasSelectedView && !tableLoading" + v-if="hasSelectedView && !tableLoading && !viewError" ref="view" :database="database" :table="table" @@ -252,7 +254,8 @@ import ViewSearch from '@baserow/modules/database/components/view/ViewSearch' import EditableViewName from '@baserow/modules/database/components/view/EditableViewName' import ShareViewLink from '@baserow/modules/database/components/view/ShareViewLink' import ExternalLinkBaserowLogo from '@baserow/modules/core/components/ExternalLinkBaserowLogo' -import ViewGroupBy from '@baserow/modules/database/components/view/ViewGroupBy.vue' +import ViewGroupBy from '@baserow/modules/database/components/view/ViewGroupBy' +import DefaultErrorPage from '@baserow/modules/core/components/DefaultErrorPage' /** * This page component is the skeleton for a table. Depending on the selected view it @@ -260,6 +263,7 @@ import ViewGroupBy from '@baserow/modules/database/components/view/ViewGroupBy.v */ export default { components: { + DefaultErrorPage, ViewGroupBy, ExternalLinkBaserowLogo, ShareViewLink, @@ -300,6 +304,14 @@ export default { required: true, validator: (prop) => typeof prop === 'object' || prop === undefined, }, + viewError: { + required: false, + validator: (prop) => + typeof prop === 'object' || + typeof prop === 'function' || + prop === undefined, + default: null, + }, tableLoading: { type: Boolean, required: true, diff --git a/web-frontend/modules/database/components/table/TableCSVImporter.vue b/web-frontend/modules/database/components/table/TableCSVImporter.vue index 652144fae..7f38393a9 100644 --- a/web-frontend/modules/database/components/table/TableCSVImporter.vue +++ b/web-frontend/modules/database/components/table/TableCSVImporter.vue @@ -106,6 +106,9 @@ </div> </div> </div> + <div v-if="values.filename !== ''" class="row"> + <div class="col col-8 margin-top-1"><slot name="upsertMapping" /></div> + </div> <Alert v-if="error !== ''" type="error"> <template #title> {{ $t('common.wrong') }} </template> {{ error }} @@ -228,7 +231,10 @@ export default { * when the CSV doesn't have any entries the appropriate error will be shown. */ async reload() { + const fileName = this.values.filename this.resetImporterState() + this.values.filename = fileName + this.state = 'parsing' await this.$ensureRender() diff --git a/web-frontend/modules/database/components/table/TableJSONImporter.vue b/web-frontend/modules/database/components/table/TableJSONImporter.vue index 6e6cfaa7b..8a7cd8cab 100644 --- a/web-frontend/modules/database/components/table/TableJSONImporter.vue +++ b/web-frontend/modules/database/components/table/TableJSONImporter.vue @@ -75,6 +75,11 @@ ></CharsetDropdown> </div> </div> + + <div v-if="values.filename !== ''" class="control margin-top-2"> + <slot name="upsertMapping" /> + </div> + <Alert v-if="error !== ''" type="error"> <template #title> {{ $t('common.wrong') }} </template> {{ error }} @@ -167,7 +172,9 @@ export default { }, async reload() { let json + const fileName = this.values.filename this.resetImporterState() + this.values.filename = fileName try { const decoder = new TextDecoder(this.encoding) diff --git a/web-frontend/modules/database/components/table/TablePasteImporter.vue b/web-frontend/modules/database/components/table/TablePasteImporter.vue index 1e7deaff5..c1e97807c 100644 --- a/web-frontend/modules/database/components/table/TablePasteImporter.vue +++ b/web-frontend/modules/database/components/table/TablePasteImporter.vue @@ -28,6 +28,10 @@ </Checkbox> </FormGroup> + <div v-if="values.filename !== ''" class="control margin-top-0"> + <slot name="upsertMapping" /> + </div> + <Alert v-if="error !== ''" type="error"> <template #title> {{ $t('common.wrong') }} </template> {{ error }} diff --git a/web-frontend/modules/database/components/table/TableXMLImporter.vue b/web-frontend/modules/database/components/table/TableXMLImporter.vue index 94ef355f4..a01562cf4 100644 --- a/web-frontend/modules/database/components/table/TableXMLImporter.vue +++ b/web-frontend/modules/database/components/table/TableXMLImporter.vue @@ -27,7 +27,7 @@ </div> </template> <div class="control__elements"> - <div class="file-upload"> + <div class="file-upload margin-top-1"> <input v-show="false" ref="file" @@ -61,6 +61,10 @@ <div v-if="v$.values.filename.$error" class="error"> {{ v$.values.filename.$errors[0]?.$message }} </div> + + <div v-if="values.filename !== ''" class="control margin-top-1"> + <slot name="upsertMapping" /> + </div> </div> </div> <Alert v-if="error !== ''" type="error"> @@ -148,7 +152,9 @@ export default { } }, async reload() { + const fileName = this.values.filename this.resetImporterState() + this.values.filename = fileName this.state = 'parsing' await this.$ensureRender() diff --git a/web-frontend/modules/database/components/view/ViewContext.vue b/web-frontend/modules/database/components/view/ViewContext.vue index a7cf1be05..b4739b2c2 100644 --- a/web-frontend/modules/database/components/view/ViewContext.vue +++ b/web-frontend/modules/database/components/view/ViewContext.vue @@ -126,12 +126,7 @@ :table="table" :fields="fields" /> - <WebhookModal - ref="webhookModal" - :database="database" - :table="table" - :fields="fields" - /> + <WebhookModal ref="webhookModal" :database="database" :table="table" /> </Context> </template> diff --git a/web-frontend/modules/database/components/view/ViewGroupByContext.vue b/web-frontend/modules/database/components/view/ViewGroupByContext.vue index b12b62b2a..fedc62623 100644 --- a/web-frontend/modules/database/components/view/ViewGroupByContext.vue +++ b/web-frontend/modules/database/components/view/ViewGroupByContext.vue @@ -63,58 +63,15 @@ </DropdownItem> </Dropdown> </div> - <div - class="group-bys__order" - :class="{ 'group-bys__order--disabled': disableGroupBy }" - > - <a - class="group-bys__order-item" - :class="{ active: groupBy.order === 'ASC' }" - @click="updateGroupBy(groupBy, { order: 'ASC' })" - > - <template v-if="getGroupByIndicator(field, 0) === 'text'">{{ - getGroupByIndicator(field, 1) - }}</template> - <i - v-if="getGroupByIndicator(field, 0) === 'icon'" - :class="getGroupByIndicator(field, 1)" - ></i> - - <i class="iconoir-arrow-right"></i> - - <template v-if="getGroupByIndicator(field, 0) === 'text'">{{ - getGroupByIndicator(field, 2) - }}</template> - <i - v-if="getGroupByIndicator(field, 0) === 'icon'" - class="fa" - :class="getGroupByIndicator(field, 2)" - ></i> - </a> - <a - class="group-bys__order-item" - :class="{ active: groupBy.order === 'DESC' }" - @click="updateGroupBy(groupBy, { order: 'DESC' })" - > - <template v-if="getGroupByIndicator(field, 0) === 'text'">{{ - getGroupByIndicator(field, 2) - }}</template> - <i - v-if="getGroupByIndicator(field, 0) === 'icon'" - :class="getGroupByIndicator(field, 2)" - ></i> - - <i class="iconoir-arrow-right"></i> - - <template v-if="getGroupByIndicator(field, 0) === 'text'">{{ - getGroupByIndicator(field, 1) - }}</template> - <i - v-if="getGroupByIndicator(field, 0) === 'icon'" - :class="getGroupByIndicator(field, 1)" - ></i> - </a> - </div> + <ViewSortOrder + :disabled="disableGroupBy" + :sort-types="getSortTypes(field)" + :type="groupBy.type" + :order="groupBy.order" + @update-order=" + updateGroupBy(groupBy, { order: $event.order, type: $event.type }) + " + ></ViewSortOrder> </div> </div> <div @@ -152,9 +109,12 @@ <script> import { notifyIf } from '@baserow/modules/core/utils/error' import context from '@baserow/modules/core/mixins/context' +import { DEFAULT_SORT_TYPE_KEY } from '@baserow/modules/database/constants' +import ViewSortOrder from '@baserow/modules/database/components/view/ViewSortOrder.vue' export default { name: 'ViewGroupByContext', + components: { ViewSortOrder }, mixins: [context], props: { fields: { @@ -213,6 +173,7 @@ export default { values: { field: fieldId, value: 'ASC', + type: DEFAULT_SORT_TYPE_KEY, }, readOnly: this.readOnly, }) @@ -238,6 +199,18 @@ export default { return } + // If the field has changed, the type might not be compatible anymore. If so, + // then we're falling back on the default sort type. + if (values.field) { + const sortType = values.type || groupBy.type + const field = this.getField(values.field) + const fieldType = this.getFieldType(field) + const sortTypes = fieldType.getSortTypes(field) + if (!Object.prototype.hasOwnProperty.call(sortTypes, sortType)) { + values.type = DEFAULT_SORT_TYPE_KEY + } + } + try { await this.$store.dispatch('view/updateGroupBy', { groupBy, @@ -249,10 +222,8 @@ export default { notifyIf(error, 'view') } }, - getGroupByIndicator(field, index) { - return this.$registry - .get('field', field.type) - .getGroupByIndicator(field, this.$registry)[index] + getSortTypes(field) { + return this.getFieldType(field).getSortTypes(field) }, }, } diff --git a/web-frontend/modules/database/components/view/ViewSortContext.vue b/web-frontend/modules/database/components/view/ViewSortContext.vue index a20c9cca5..d7b9bc131 100644 --- a/web-frontend/modules/database/components/view/ViewSortContext.vue +++ b/web-frontend/modules/database/components/view/ViewSortContext.vue @@ -60,57 +60,15 @@ ></DropdownItem> </Dropdown> </div> - <div - class="sortings__order" - :class="{ 'sortings__order--disabled': disableSort }" - > - <a - class="sortings__order-item" - :class="{ active: sort.order === 'ASC' }" - @click="updateSort(sort, { order: 'ASC' })" - > - <template v-if="getSortIndicator(field, 0) === 'text'" - >{{ getSortIndicator(field, 1) }} - </template> - <i - v-if="getSortIndicator(field, 0) === 'icon'" - :class="getSortIndicator(field, 1)" - ></i> - - <i class="iconoir-arrow-right"></i> - - <template v-if="getSortIndicator(field, 0) === 'text'" - >{{ getSortIndicator(field, 2) }} - </template> - <i - v-if="getSortIndicator(field, 0) === 'icon'" - :class="getSortIndicator(field, 2)" - ></i> - </a> - <a - class="sortings__order-item" - :class="{ active: sort.order === 'DESC' }" - @click="updateSort(sort, { order: 'DESC' })" - > - <template v-if="getSortIndicator(field, 0) === 'text'" - >{{ getSortIndicator(field, 2) }} - </template> - <i - v-if="getSortIndicator(field, 0) === 'icon'" - :class="getSortIndicator(field, 2)" - ></i> - - <i class="iconoir-arrow-right"></i> - - <template v-if="getSortIndicator(field, 0) === 'text'" - >{{ getSortIndicator(field, 1) }} - </template> - <i - v-if="getSortIndicator(field, 0) === 'icon'" - :class="getSortIndicator(field, 1)" - ></i> - </a> - </div> + <ViewSortOrder + :disabled="disableSort" + :sort-types="getSortTypes(field)" + :type="sort.type" + :order="sort.order" + @update-order=" + updateSort(sort, { order: $event.order, type: $event.type }) + " + ></ViewSortOrder> </div> </div> <div @@ -148,9 +106,12 @@ <script> import { notifyIf } from '@baserow/modules/core/utils/error' import context from '@baserow/modules/core/mixins/context' +import ViewSortOrder from '@baserow/modules/database/components/view/ViewSortOrder' +import { DEFAULT_SORT_TYPE_KEY } from '@baserow/modules/database/constants' export default { name: 'ViewSortContext', + components: { ViewSortOrder }, mixins: [context], props: { fields: { @@ -206,6 +167,7 @@ export default { values: { field: fieldId, value: 'ASC', + type: DEFAULT_SORT_TYPE_KEY, }, readOnly: this.readOnly, }) @@ -231,6 +193,18 @@ export default { return } + // If the field has changed, the type might not be compatible anymore. If so, + // then we're falling back on the default sort type. + if (values.field) { + const sortType = values.type || sort.type + const field = this.getField(values.field) + const fieldType = this.getFieldType(field) + const sortTypes = fieldType.getSortTypes(field) + if (!Object.prototype.hasOwnProperty.call(sortTypes, sortType)) { + values.type = DEFAULT_SORT_TYPE_KEY + } + } + try { await this.$store.dispatch('view/updateSort', { sort, @@ -242,10 +216,8 @@ export default { notifyIf(error, 'view') } }, - getSortIndicator(field, index) { - return this.getFieldType(field).getSortIndicator(field, this.$registry)[ - index - ] + getSortTypes(field) { + return this.getFieldType(field).getSortTypes(field) }, }, } diff --git a/web-frontend/modules/database/components/view/ViewSortOrder.vue b/web-frontend/modules/database/components/view/ViewSortOrder.vue new file mode 100644 index 000000000..d950d948e --- /dev/null +++ b/web-frontend/modules/database/components/view/ViewSortOrder.vue @@ -0,0 +1,109 @@ +<template> + <div + class="sortings__order" + :class="{ 'sortings__order--disabled': disabled }" + > + <template v-if="Object.keys(sortTypes).length === 1"> + <a + class="sortings__order-item" + :class="{ active: order === 'ASC' }" + @click="$emit('update-order', { order: 'ASC', type })" + > + <template v-if="sortIndicator[0] === 'text'" + >{{ sortIndicator[1] }} + </template> + <i v-if="sortIndicator[0] === 'icon'" :class="sortIndicator[1]"></i> + + <i class="iconoir-arrow-right"></i> + + <template v-if="sortIndicator[0] === 'text'" + >{{ sortIndicator[2] }} + </template> + <i v-if="sortIndicator[0] === 'icon'" :class="sortIndicator[2]"></i> + </a> + <a + class="sortings__order-item" + :class="{ active: order === 'DESC' }" + @click="$emit('update-order', { order: 'DESC', type })" + > + <template v-if="sortIndicator[0] === 'text'" + >{{ sortIndicator[2] }} + </template> + <i v-if="sortIndicator[0] === 'icon'" :class="sortIndicator[2]"></i> + + <i class="iconoir-arrow-right"></i> + + <template v-if="sortIndicator[0] === 'text'" + >{{ sortIndicator[1] }} + </template> + <i v-if="sortIndicator[0] === 'icon'" :class="sortIndicator[1]"></i> + </a> + </template> + <template v-else> + <Dropdown + :value="`${type}-${order}`" + :fixed-items="true" + class="sortings__order-dropdown" + @input="dropdownItemChange" + > + <DropdownItem + v-for="item in dropdownItems" + :key="item.value" + :name="item.name" + :value="item.value" + ></DropdownItem> + </Dropdown> + </template> + </div> +</template> + +<script> +export default { + name: 'ViewSortOrder', + props: { + disabled: { + type: Boolean, + required: false, + default: false, + }, + sortTypes: { + type: Object, + required: true, + }, + type: { + type: String, + required: true, + }, + order: { + type: String, + required: true, + }, + }, + computed: { + sortIndicator() { + return this.sortTypes[this.type].indicator + }, + dropdownItems() { + const items = [] + Object.entries(this.sortTypes).forEach(([type, sortObject]) => { + const indicator = sortObject.indicator + items.push({ + name: `${indicator[1]} -> ${indicator[2]}`, + value: `${type}-ASC`, + }) + items.push({ + name: `${indicator[2]} -> ${indicator[1]}`, + value: `${type}-DESC`, + }) + }) + return items + }, + }, + methods: { + dropdownItemChange(value) { + const [type, order] = value.split('-') + this.$emit('update-order', { order, type }) + }, + }, +} +</script> diff --git a/web-frontend/modules/database/components/view/grid/GridViewFieldType.vue b/web-frontend/modules/database/components/view/grid/GridViewFieldType.vue index cbee5f2da..259426d31 100644 --- a/web-frontend/modules/database/components/view/grid/GridViewFieldType.vue +++ b/web-frontend/modules/database/components/view/grid/GridViewFieldType.vue @@ -281,6 +281,7 @@ import InsertFieldContext from '@baserow/modules/database/components/field/Inser import DuplicateFieldModal from '@baserow/modules/database/components/field/DuplicateFieldModal' import HorizontalResize from '@baserow/modules/core/components/HorizontalResize' import gridViewHelpers from '@baserow/modules/database/mixins/gridViewHelpers' +import { DEFAULT_SORT_TYPE_KEY } from '@baserow/modules/database/constants' export default { name: 'GridViewFieldType', @@ -455,7 +456,7 @@ export default { await this.$store.dispatch('view/createSort', { view, field, - values, + values: { ...values, type: DEFAULT_SORT_TYPE_KEY }, }) } else { await this.$store.dispatch('view/updateSort', { @@ -492,9 +493,9 @@ export default { this.$emit('dragging', { field, event }) }, getSortIndicator(field, index) { - return this.$registry - .get('field', field.type) - .getSortIndicator(field, this.$registry)[index] + return this.$registry.get('field', field.type).getSortIndicator(field)[ + index + ] }, getCanSortInView(field) { return this.$registry.get('field', field.type).getCanSortInView(field) diff --git a/web-frontend/modules/database/components/webhook/CreateWebhook.vue b/web-frontend/modules/database/components/webhook/CreateWebhook.vue index f627b1447..dbb7325b6 100644 --- a/web-frontend/modules/database/components/webhook/CreateWebhook.vue +++ b/web-frontend/modules/database/components/webhook/CreateWebhook.vue @@ -6,6 +6,7 @@ :database="database" :table="table" :fields="fields" + :views="views" @submitted="submit" > <div class="actions"> @@ -42,6 +43,10 @@ export default { type: Array, required: true, }, + views: { + type: Array, + required: true, + }, }, data() { return { diff --git a/web-frontend/modules/database/components/webhook/UpdateWebhook.vue b/web-frontend/modules/database/components/webhook/UpdateWebhook.vue index 6a7965d1f..f2fe863c8 100644 --- a/web-frontend/modules/database/components/webhook/UpdateWebhook.vue +++ b/web-frontend/modules/database/components/webhook/UpdateWebhook.vue @@ -6,6 +6,7 @@ :database="database" :table="table" :fields="fields" + :views="views" :default-values="webhook" @submitted="submit" @formchange="handleFormChange" @@ -66,6 +67,10 @@ export default { type: Array, required: true, }, + views: { + type: Array, + required: true, + }, webhook: { type: Object, required: true, diff --git a/web-frontend/modules/database/components/webhook/Webhook.vue b/web-frontend/modules/database/components/webhook/Webhook.vue index d09d82d28..5781e68a3 100644 --- a/web-frontend/modules/database/components/webhook/Webhook.vue +++ b/web-frontend/modules/database/components/webhook/Webhook.vue @@ -52,6 +52,7 @@ :database="database" :table="table" :fields="fields" + :views="views" @updated="$emit('updated', $event)" @deleted="$emit('deleted', $event)" /> @@ -94,6 +95,10 @@ export default { type: Array, required: true, }, + views: { + type: Array, + required: true, + }, }, data() { return { diff --git a/web-frontend/modules/database/components/webhook/WebhookForm.vue b/web-frontend/modules/database/components/webhook/WebhookForm.vue index edadc90d9..951e38aa4 100644 --- a/web-frontend/modules/database/components/webhook/WebhookForm.vue +++ b/web-frontend/modules/database/components/webhook/WebhookForm.vue @@ -113,20 +113,35 @@ <div v-for="webhookEvent in webhookEventTypes" :key="webhookEvent.type" + v-tooltip=" + webhookEvent.isDeactivated(database.workspace.id) + ? webhookEvent.getDeactivatedText() + : null + " class="webhook__type" + tooltip-position="bottom-cursor" + @mousedown=" + webhookEvent.isDeactivated(database.workspace.id) && + !values.events.includes(webhookEvent.type) && + $refs[`${webhookEvent.getName()}DeactivatedClickModal`][0].show() + " > <Checkbox :checked="values.events.includes(webhookEvent.type)" - @input=" - $event - ? values.events.push(webhookEvent.type) - : values.events.splice( - values.events.indexOf(webhookEvent.type), - 1 - ) + :disabled=" + !values.events.includes(webhookEvent.type) && + webhookEvent.isDeactivated(database.workspace.id) " - >{{ webhookEvent.getName() }}</Checkbox + @input="toggleEventType(webhookEvent, $event)" > + {{ webhookEvent.getName() }} + <div + v-if="webhookEvent.isDeactivated(database.workspace.id)" + class="deactivated-label" + > + <i class="iconoir-lock"></i> + </div> + </Checkbox> <div v-if="webhookEvent.getHasRelatedFields()" class="webhook__type-dropdown-container" @@ -157,6 +172,42 @@ :tooltip="webhookEvent.getRelatedFieldsHelpText()" /> </div> + <div + v-if="webhookEvent.getHasRelatedView()" + class="webhook__type-dropdown-container" + > + <Dropdown + :value=" + values.events.includes(webhookEvent.type) + ? getEventView(webhookEvent) + : null + " + :placeholder="webhookEvent.getRelatedViewPlaceholder()" + :disabled="!values.events.includes(webhookEvent.type)" + class="dropdown--tiny webhook__type-dropdown" + @input="setEventView(webhookEvent, $event)" + > + <DropdownItem + v-for="view in filterableViews" + :key="view.id" + :name="view.name" + :value="view.id" + > + </DropdownItem> + </Dropdown> + <HelpIcon + v-if="webhookEvent.getRelatedViewHelpText()" + class="margin-left-1" + :tooltip="webhookEvent.getRelatedViewHelpText()" + /> + </div> + <component + :is="webhookEvent.getDeactivatedClickModal()" + v-if="webhookEvent.isDeactivated(database.workspace.id)" + :ref="`${webhookEvent.getName()}DeactivatedClickModal`" + :workspace="database.workspace" + :name="webhookEvent.getFeatureName()" + ></component> </div> </div> @@ -275,6 +326,10 @@ export default { type: Array, required: true, }, + views: { + type: Array, + required: true, + }, }, setup() { const values = reactive({ @@ -351,6 +406,11 @@ export default { webhookEventTypes() { return this.$registry.getAll('webhookEvent') }, + filterableViews() { + return this.views.filter( + (view) => this.$registry.get('view', view.type).canFilter + ) + }, /** * Generates an example payload of the webhook event based on the chosen webhook * event type. @@ -424,6 +484,45 @@ export default { eventConfig.fields = fields }, + getEventView(event) { + const eventConfig = this.values.event_config.find( + (e) => e.event_type === event.type + ) + if (eventConfig === undefined) { + return null + } + const viewId = eventConfig.views?.[0] + const view = + viewId && this.filterableViews.find((view) => view.id === viewId) + return view?.id || null + }, + setEventView(event, view) { + const eventConfig = this.values.event_config.find( + (e) => e.event_type === event.type + ) + if (eventConfig === undefined) { + this.values.event_config.push({ + event_type: event.type, + views: [], + }) + return this.setEventView(event, view) + } + this.$set(eventConfig, 'views', [view]) + }, + toggleEventType(webhookEvent, event) { + if (event) { + this.values.events.push(webhookEvent.type) + } else { + this.values.events.splice( + this.values.events.indexOf(webhookEvent.type), + 1 + ) + this.values.event_config.splice( + this.values.event_config.indexOf((e) => e.event_type === event.type), + 1 + ) + } + }, prepareHeaders(headers) { const preparedHeaders = {} headers.forEach((header) => { diff --git a/web-frontend/modules/database/components/webhook/WebhookList.vue b/web-frontend/modules/database/components/webhook/WebhookList.vue index 771f31b03..659c521b1 100644 --- a/web-frontend/modules/database/components/webhook/WebhookList.vue +++ b/web-frontend/modules/database/components/webhook/WebhookList.vue @@ -10,6 +10,7 @@ :database="database" :table="table" :fields="fields" + :views="views" @updated="$emit('updated', $event)" @deleted="$emit('deleted', $event)" /> @@ -37,6 +38,10 @@ export default { type: Array, required: true, }, + views: { + type: Array, + required: true, + }, webhooks: { type: Array, required: true, diff --git a/web-frontend/modules/database/components/webhook/WebhookModal.vue b/web-frontend/modules/database/components/webhook/WebhookModal.vue index edeefa357..5bc4f74ab 100644 --- a/web-frontend/modules/database/components/webhook/WebhookModal.vue +++ b/web-frontend/modules/database/components/webhook/WebhookModal.vue @@ -1,5 +1,5 @@ <template> - <Modal> + <Modal @hidden="$emit('hidden')"> <h2 class="box__title"> {{ $t('webhookModal.title', { name: table.name }) }} </h2> @@ -21,6 +21,7 @@ :database="database" :table="table" :fields="tableFields" + :views="tableViews" :webhooks="webhooks" @updated="updated" @deleted="deleted" @@ -30,6 +31,7 @@ :database="database" :table="table" :fields="tableFields" + :views="tableViews" @created="created" /> </template> @@ -43,6 +45,7 @@ import WebhookList from '@baserow/modules/database/components/webhook/WebhookLis import CreateWebhook from '@baserow/modules/database/components/webhook/CreateWebhook' import WebhookService from '@baserow/modules/database/services/webhook' import FieldService from '@baserow/modules/database/services/field' +import ViewService from '@baserow/modules/database/services/view' export default { name: 'WebhookModal', @@ -65,6 +68,11 @@ export default { required: false, default: null, }, + views: { + type: [Array, null], + required: false, + default: null, + }, }, data() { return { @@ -72,6 +80,7 @@ export default { state: 'list', webhooks: [], tableFields: [], + tableViews: [], } }, methods: { @@ -92,21 +101,35 @@ export default { this.handleError(e) } + const selectedTableId = this.$store.getters['table/getSelected']?.id + const isSelectedTable = + selectedTableId && selectedTableId === this.table.id // The parent component can provide the fields, but if it doesn't we need to // fetch them ourselves. If the table is the selected one, we can use the // store, otherwise we need to fetch them. if (Array.isArray(this.fields)) { this.tableFields = this.fields + } else if (isSelectedTable) { + this.tableFields = this.$store.getters['field/getAll'] } else { - const selectedTable = this.$store.getters['table/getSelected'] - if (selectedTable && selectedTable.id === this.table.id) { - this.tableFields = this.$store.getters['field/getAll'] - } else { - const { data: fields } = await FieldService(this.$client).fetchAll( - this.table.id - ) - this.tableFields = fields - } + const { data: fields } = await FieldService(this.$client).fetchAll( + this.table.id + ) + this.tableFields = fields + } + + // The parent component can provide the views, but if it doesn't we need to + // fetch them ourselves. If the table is the selected one, we can use the + // store, otherwise we need to fetch them. + if (Array.isArray(this.views)) { + this.tableViews = this.views + } else if (isSelectedTable) { + this.tableViews = this.$store.getters['view/getAll'] + } else { + const { data: views } = await ViewService(this.$client).fetchAll( + this.table.id + ) + this.tableViews = views } this.loading = false diff --git a/web-frontend/modules/database/constants.js b/web-frontend/modules/database/constants.js index 4d8ff25e7..710eb4832 100644 --- a/web-frontend/modules/database/constants.js +++ b/web-frontend/modules/database/constants.js @@ -1,6 +1,9 @@ -// Must be the same as `src/baserow/contrib/database/constants.py`. +// Must be the same as `src/baserow/contrib/database/views/models.py`. export const DEFAULT_FORM_VIEW_FIELD_COMPONENT_KEY = 'default' +// Must be the same as `src/baserow/contrib/database/views/models.py`. +export const DEFAULT_SORT_TYPE_KEY = 'default' + export const GRID_VIEW_SIZE_TO_ROW_HEIGHT_MAPPING = { small: 33, medium: 55, diff --git a/web-frontend/modules/database/fieldTypes.js b/web-frontend/modules/database/fieldTypes.js index 576d4cd08..e5643cc91 100644 --- a/web-frontend/modules/database/fieldTypes.js +++ b/web-frontend/modules/database/fieldTypes.js @@ -158,7 +158,10 @@ import FieldLookupSubForm from '@baserow/modules/database/components/field/Field import FieldCountSubForm from '@baserow/modules/database/components/field/FieldCountSubForm' import FieldRollupSubForm from '@baserow/modules/database/components/field/FieldRollupSubForm' import RowEditFieldFormula from '@baserow/modules/database/components/row/RowEditFieldFormula' -import { DEFAULT_FORM_VIEW_FIELD_COMPONENT_KEY } from '@baserow/modules/database/constants' +import { + DEFAULT_FORM_VIEW_FIELD_COMPONENT_KEY, + DEFAULT_SORT_TYPE_KEY, +} from '@baserow/modules/database/constants' import ViewService from '@baserow/modules/database/services/view' import FormService from '@baserow/modules/database/services/view/form' import { UploadFileUserFileUploadType } from '@baserow/modules/core/userFileUploadTypes' @@ -382,10 +385,6 @@ export class FieldType extends Registerable { return false } - getGroupByIndicator(field, registry) { - return this.getSortIndicator(field, registry) - } - /** * In some cases, the group by value can not be directly compared to a row value * because the format is different for technical reasons in the backend. This @@ -524,6 +523,28 @@ export class FieldType extends Registerable { return ['text', 'A', 'Z'] } + /** + * Should return a mapping containing all the available sort types for this field + * type. It always returns the default type, which uses the `getSort` and + * `getSortIndicator` by default. + */ + getSortTypes(field) { + return { + [DEFAULT_SORT_TYPE_KEY]: { + function: this.getSort, + indicator: this.getSortIndicator(field), + }, + } + } + + /** + * Can a field of this type be used to perform an update during import on rows that + * contain the same value as imported one. + */ + canUpsert() { + return false + } + /** * This hook is called before the field's value is copied to the clipboard. * Optionally formatting can be done here. By default the value is always @@ -969,6 +990,10 @@ export class TextFieldType extends FieldType { return field.text_default } + canUpsert() { + return true + } + getSort(name, order) { return (a, b) => { const stringA = a[name] === null ? '' : '' + a[name] @@ -1080,6 +1105,10 @@ export class LongTextFieldType extends FieldType { return '' } + canUpsert() { + return true + } + getSort(name, order) { return (a, b) => { const stringA = a[name] === null ? '' : '' + a[name] @@ -1529,6 +1558,10 @@ export class NumberFieldType extends FieldType { return ['text', '1', '9'] } + canUpsert() { + return true + } + /** * When searching a cell's value, this should return the value to match the user's * search term against. We can't use `toHumanReadableString` here as it needs to be @@ -1743,6 +1776,10 @@ export class RatingFieldType extends FieldType { return 0 } + canUpsert() { + return true + } + getSort(name, order) { return (a, b) => { if (a[name] === b[name]) { @@ -1877,6 +1914,10 @@ export class BooleanFieldType extends FieldType { return ['icon', 'baserow-icon-circle-empty', 'baserow-icon-circle-checked'] } + canUpsert() { + return true + } + getSort(name, order) { return (a, b) => { const intA = +a[name] @@ -2230,6 +2271,10 @@ export class DateFieldType extends BaseDateFieldType { return true } + canUpsert() { + return true + } + parseQueryParameter(field, value) { return this.formatValue( field.field, @@ -2696,6 +2741,10 @@ export class DurationFieldType extends FieldType { return this.formatValue(field, value) } + canUpsert() { + return true + } + getSort(name, order) { return (a, b) => { const aValue = a[name] @@ -2843,6 +2892,10 @@ export class URLFieldType extends FieldType { return isValidURL(value) ? value : '' } + canUpsert() { + return true + } + getSort(name, order) { return (a, b) => { const stringA = a[name] === null ? '' : '' + a[name] @@ -2942,6 +2995,10 @@ export class EmailFieldType extends FieldType { return isValidEmail(value) ? value : '' } + canUpsert() { + return true + } + getSort(name, order) { return (a, b) => { const stringA = a[name] === null ? '' : '' + a[name] @@ -3266,6 +3323,40 @@ export class SingleSelectFieldType extends SelectOptionBaseFieldType { } } + getSortByOptionOrder(name, order, field) { + const getOrder = function (row, name, field) { + let id = null + + try { + id = row[name].id || null + } catch (e) { + return -1 + } + + return field.select_options.findIndex((o) => o.id === id) || -1 + } + + return (a, b) => { + const aOrder = getOrder(a, name, field) + const bOrder = getOrder(b, name, field) + + if (order === 'ASC') { + return aOrder - bOrder + } else if (order === 'DESC') { + return bOrder - aOrder + } + } + } + + getSortTypes(field) { + const defaultTypes = super.getSortTypes(field) + defaultTypes.order = { + function: this.getSortByOptionOrder, + indicator: ['text', 'First', 'Last'], + } + return defaultTypes + } + parseFromLinkedRowItemValue(field, value) { return value ? { value } : null } @@ -3754,6 +3845,10 @@ export class PhoneNumberFieldType extends FieldType { return isSimplePhoneNumber(value) ? value : '' } + canUpsert() { + return true + } + getSort(name, order) { return (a, b) => { const stringA = a[name] === null ? '' : '' + a[name] @@ -3912,6 +4007,10 @@ export class FormulaFieldType extends mix( return this.getFormulaType(field)?.getSort(name, order, field) } + getSortTypes(field) { + return this.getFormulaType(field)?.getSortTypes(field) + } + getEmptyValue(field) { return null } @@ -4335,6 +4434,27 @@ export class MultipleCollaboratorsFieldType extends FieldType { canBeReferencedByFormulaField() { return true } + + getCanGroupByInView(field) { + return true + } + + getRowValueFromGroupValue(field, value) { + return value.map((optId) => { + return { id: optId } + }) + } + + getGroupValueFromRowValue(field, value) { + return value && value.map((o) => o.id) + } + + isEqual(field, value1, value2) { + const value1Ids = value1.map((v) => v.id) + const value2Ids = value2.map((v) => v.id) + + return _.isEqual(value1Ids, value2Ids) + } } export class UUIDFieldType extends FieldType { @@ -4379,6 +4499,10 @@ export class UUIDFieldType extends FieldType { return RowCardFieldUUID } + canUpsert() { + return true + } + getSort(name, order) { return (a, b) => { const stringA = a[name] === null ? '' : '' + a[name] @@ -4458,6 +4582,10 @@ export class AutonumberFieldType extends FieldType { return RowCardFieldAutonumber } + canUpsert() { + return true + } + getSort(name, order) { return (a, b) => { if (a[name] === b[name]) { diff --git a/web-frontend/modules/database/formula/formulaTypes.js b/web-frontend/modules/database/formula/formulaTypes.js index 15aaf9379..22db41440 100644 --- a/web-frontend/modules/database/formula/formulaTypes.js +++ b/web-frontend/modules/database/formula/formulaTypes.js @@ -73,6 +73,7 @@ import { } from '@baserow/modules/database/utils/fieldFilters' import ViewFilterTypeDuration from '@baserow/modules/database/components/view/ViewFilterTypeDuration.vue' import ViewFilterTypeMultipleSelectOptions from '@baserow/modules/database/components/view/ViewFilterTypeMultipleSelectOptions.vue' +import { DEFAULT_SORT_TYPE_KEY } from '@baserow/modules/database/constants' export class BaserowFormulaTypeDefinition extends Registerable { getIconClass() { @@ -196,6 +197,19 @@ export class BaserowFormulaTypeDefinition extends Registerable { return underlyingFieldType.getSort(name, order, field) } + getSortTypes(field) { + const underlyingFieldType = this.app.$registry.get( + 'field', + this.getFieldType() + ) + const fieldSortTypes = underlyingFieldType.getSortTypes(field) + // Only the default sort type is supported for formulas at the moment because + // there is no way to configure different types in the backend. + return { + [DEFAULT_SORT_TYPE_KEY]: fieldSortTypes[DEFAULT_SORT_TYPE_KEY], + } + } + _mapFormulaTypeToFieldType(formulaType) { return this.app.$registry.get('formula_type', formulaType).getFieldType() } @@ -261,6 +275,14 @@ export class BaserowFormulaTypeDefinition extends Registerable { toBaserowFormulaType(field) { return this.getType() } + + parseFromLinkedRowItemValue(field, value) { + const underlyingFieldType = this.app.$registry.get( + 'field', + this._mapFormulaTypeToFieldType(field.formula_type) + ) + return underlyingFieldType.parseFromLinkedRowItemValue(field, value) + } } export class BaserowFormulaTextType extends mix( @@ -753,8 +775,10 @@ export class BaserowFormulaArrayType extends mix( const innerSortFunction = subType.getSort(name, order, field) return (a, b) => { - const valuesA = a[name].map(subType.mapToSortableArray.bind(subType)) - const valuesB = b[name].map(subType.mapToSortableArray.bind(subType)) + const valA = Array.isArray(a[name]) ? a[name] : [a[name]] + const valB = Array.isArray(b[name]) ? b[name] : [b[name]] + const valuesA = valA.map(subType.mapToSortableArray.bind(subType)) + const valuesB = valB.map(subType.mapToSortableArray.bind(subType)) for (let i = 0; i < Math.max(valuesA.length, valuesB.length); i++) { let compared = 0 @@ -825,6 +849,11 @@ export class BaserowFormulaArrayType extends mix( toBaserowFormulaType(field) { return this.getSubType(field)?.toBaserowFormulaType(field) } + + parseFromLinkedRowItemValue(field, value) { + const subType = this.getSubType(field) + return subType.parseFromLinkedRowItemValue(field, value) + } } export class BaserowFormulaFileType extends BaserowFormulaTypeDefinition { diff --git a/web-frontend/modules/database/locales/de.json b/web-frontend/modules/database/locales/de.json index 107e5259a..438a5d454 100644 --- a/web-frontend/modules/database/locales/de.json +++ b/web-frontend/modules/database/locales/de.json @@ -72,7 +72,8 @@ "webhooks": "Webhooks", "lastSynced": "Zuletzt synchronisiert", "notSynced": "nicht sychnronisiert", - "sync": "Tabelle synchronisieren" + "sync": "Tabelle synchronisieren", + "updateSyncConfig": "Sync-Konfiguration aktualisieren" }, "apiToken": { "create": "erstellen", @@ -243,7 +244,16 @@ "integer": "Integer", "decimal": "Dezimal", "decimalPlacesLabel": "Dezimalstellen", - "allowNegative": "Negativ zulassen" + "allowNegative": "Negativ zulassen", + "separatorLabel": "Tausender- und Dezimaltrennzeichen", + "prefixPlaceholder": "Präfix", + "suffixPlaceholder": "Suffix", + "prefixAndSuffixLabel": "Präfix / Suffix", + "spaceComma": "Leerzeichen, Komma (1 000 000,00)", + "spacePeriod": "Leerzeichen, Punkt (1 000 000.00)", + "commaPeriod": "Komma, Leerzeichen (1,000,000.00)", + "periodComma": "Punkt, Komma (1.000.000,00)", + "noFormatting": "Keine Formatierung" }, "fieldContext": { "editField": "Feld bearbeiten", @@ -425,16 +435,19 @@ "add": "Hinzufügen {view}" }, "shareViewLink": { - "shareView": "Teilen {viewTypeSharingLinkName}", - "shareViewTitle": "Erstellen Sie einen privaten, gemeinsam nutzbaren Link zum {ViewTypeSharingLinkName}", + "shareView": "{viewTypeSharingLinkName} teilen", + "shareViewTitle": "Sie haben die Ansicht noch nicht geteilt", "sharedViewTitle": "Dieser {ViewTypeSharingLinkName} ist derzeit über einen privaten Link freigegeben", "sharedViewDescription": "Personen, die den Link haben, können den {ViewTypeSharingLinkName} sehen.", - "disableLink": "freigegebenen Link deaktivieren", + "disableLink": "Freigegebenen Link deaktivieren", "generateNewUrl": "neue Url generieren", "copyURL": "URL kopieren", "DisablePassword": "Zugriff ist passwortgeschützt", "EnablePassword": "Beschränken Sie den Zugriff mit einem Passwort", - "ChangePassword": "Ändern" + "ChangePassword": "Ändern", + "createPrivateLink": "Einen privaten Link erstellen", + "shareViewText": "Ein privater, gemeinsam nutzbarer Link erlaubt es jedem, die Daten in dieser Ansicht zu sehen.", + "notSharedYetText": "Erlauben Sie jedem, die Daten in dieser Ansicht zu sehen, oder synchronisieren Sie Ereignisse mit Ihrem externen Kalender." }, "viewSortContext": { "noSortTitle": "Sie haben noch keine Sortierungen erstellt", @@ -452,9 +465,9 @@ "generateNewURL": "Neue URL generieren" }, "viewFieldsContext": { - "coverField": "Deckungsfeld", - "noCover": "Keine Deckung", - "search": "Suchfelder", + "coverField": "Coverfeld", + "noCover": "Kein Cover", + "search": "Felder durchsuchen", "hideAll": "Alle ausblenden", "showAll": "Alle anzeigen" }, @@ -462,7 +475,16 @@ "selected": "Ausgewählte" }, "viewFilter": { - "filter": "Filter | 1 Filter | {count} Filters" + "filter": "Filter | 1 Filter | {count} Filters", + "hasAllValuesEqual": "hat alle Werte gleich", + "hasValueHigherThanOrEqual": "hat einen Wert größer oder gleich", + "hasValueLowerThan": "hat einen Wert kleiner als", + "hasValueLowerThanOrEqual": "hat einen Wert kleiner oder gleich", + "hasNotValueHigherThan": "hat keinen Wert größer als", + "hasValueHigherThan": "hat einen Wert größer als", + "hasNotValueHigherThanOrEqual": "hat keinen Wert größer oder gleich", + "hasNotValueLowerThan": "hat keinen Wert kleiner als", + "hasNotValueLowerThanOrEqual": "hat keinen Wert kleiner oder gleich" }, "viewContext": { "exportView": "Ansicht exportieren", @@ -495,7 +517,8 @@ "hideField": "Feld ausblenden", "insertLeft": "Links einfügen", "insertRight": "Rechts einfügen", - "duplicate": "Feld duplizieren" + "duplicate": "Feld duplizieren", + "dataSyncField": "Das Feld ist schreibgeschützt und Teil des Datenabgleichs der Tabelle." }, "gridViewRow": { "rowNotMatchingFilters": "Zeile entspricht nicht den Filtern", @@ -521,7 +544,8 @@ "tooManyItemsTitle": "Zu viele Elemente", "AIValuesGenerationErrorTitle": "Werterstellung mittels KI fehlgeschlagen", "AIValuesGenerationErrorMessage": "Bitte überprüfen Sie Ihren API_KEY und das ausgewählte Modell.", - "generateCellsValues": "Mit KI Werte generieren" + "generateCellsValues": "Mit KI Werte generieren", + "copyCellsWithHeader": "Zellen mit Kopfbereich kopieren" }, "gridViewFieldLinkRow": { "unnamed": "unbenannte Zeile {value}" @@ -537,7 +561,8 @@ "failedTitle": "Export fehlgeschlagen", "failedDescription": "Der Export ist aufgrund eines Serverfehlers fehlgeschlagen.", "cancelledTitle": "Export abgebrochen", - "cancelledDescription": "Die Exportaktion wurde abgebrochen." + "cancelledDescription": "Die Exportaktion wurde abgebrochen.", + "title": "{name} exportieren" }, "exporterTypeChoices": { "formatLabel": "In welches Format möchten Sie exportieren?" @@ -558,7 +583,8 @@ "recordSeparator": "Datensatz-Trennzeichen", "unitSeparator": "Teilgruppentrennzeichen", "encodingLabel": "Kodierung", - "firstRowIsHeaderLabel": "Erste Zeile ist Kopfzeile" + "firstRowIsHeaderLabel": "Erste Zeile ist Kopfzeile", + "includeHeader": "Feldnamen als Überschrift einfügen" }, "apiDocsDatabase": { "pageTitle": "{name} Datenbank-API-Dokumentation", @@ -591,10 +617,11 @@ "variance": "Varianz", "average": "Durchschnitt", "stdDevShort": "Std Abw", - "emptyCount": "Leer", + "emptyCount": "(Leer)", "notEmptyCount": "Gefüllt", "emptyPercentage": "Prozent leer", - "notEmptyPercentage": "Prozent gefüllt" + "notEmptyPercentage": "Prozent gefüllt", + "count": "Anzahl" }, "databaseForm": { "importLabel": "Möchten Sie vorhandene Daten importieren?", @@ -838,7 +865,8 @@ "durationFormatLabel": "Format der Dauer" }, "viewFieldConditionsForm": { - "addCondition": "Bedingung hinzufügen" + "addCondition": "Bedingung hinzufügen", + "addConditionGroup": "Bedingungsgruppe hinzufügen" }, "fieldCollaboratorSubForm": { "notifyUserWhenAdded": "Benutzer beim Hinzufügen benachrichtigen" @@ -933,5 +961,15 @@ "reportTitleSuccess": "Import war erfolgreich, allerdings...", "reportMessage": "Die folgenden Zeilenindizes konnten nicht importiert werden:", "reportTitleFailure": "Fehlgeschlagene Zeilen" + }, + "formViewMetaControls": { + "showMessage": "Eine Nachricht anzeigen", + "theMessage": "Die Nachricht", + "theURL": "Die URL", + "whenSubmittedLabel": "Wenn das Formular abgeschickt wurde", + "urlRedirect": "Weiterleiten zu einer URL" + }, + "createViewLink": { + "inCompatibleWithDataSync": "Dieser Ansichtstyp ist nicht mit einer Datenabgleichs-Tabelle kompatibel." } } diff --git a/web-frontend/modules/database/locales/en.json b/web-frontend/modules/database/locales/en.json index 65fb0d147..13dd1e292 100644 --- a/web-frontend/modules/database/locales/en.json +++ b/web-frontend/modules/database/locales/en.json @@ -441,7 +441,9 @@ "fieldMappingDescription": "We have automatically mapped the columns of the Baserow fields in your table. You can change them below. Any incompatible cell will remain empty after the import.", "selectImportMessage": "Please select data to import.", "filePreview": "File content preview", - "importPreview": "Import preview" + "importPreview": "Import preview", + "useUpsertField": "Update rows if they already exist", + "upsertTooltip": "Match existing rows using a unique field to overwrite data with imported values." }, "formulaAdvancedEditContext": { "textAreaFormulaInputPlaceholder": "Click to edit the formula", @@ -757,12 +759,12 @@ "databaseForm": { "importLabel": "Would you like to import existing data?", "emptyLabel": "Start from scratch", - "airtableLabel": "Import from Airtable (beta)" + "airtableLabel": "Import from Airtable" }, "importFromAirtable": { "airtableShareLinkTitle": "Share a link to your Base", - "airtableShareLinkDescription": "To import your Airtable base, you need to have a shared link to your entire base. In Airtable, click on the share button in the top right corner after opening your base. After that you must choose the \"Access to base\" option. In the share modal you can click on the \"Create a shared link to the whole base\" button and then on “Private read-only link”. Copy the public link and paste it in the input below.", - "airtableShareLinkBeta": "Note that this feature is in beta, your tables, fields (except formula, lookup and count) and data will be imported. Your views will not be imported.", + "airtableShareLinkDescription": "To import your Airtable base, you need to have a shared link to your entire base. In Airtable, click on the share button in the top right corner after opening your base. After that you must choose the \"Share via link\" option. In the share modal you can click on the \"Share publicly\" tab and then on “Enabl;e shared base link”. Copy the public link and paste it in the input below.", + "airtableShareLinkBeta": "This functionality will import most of the data, but there are incompatibilities. A table named \"Airtable import report\" will therefore be added containing a list of things that were not or partially imported.", "airtableShareLinkPaste": "Paste the link here", "importButtonLabel": "Import from Airtable", "openButtonLabel": "Open imported database", @@ -830,7 +832,8 @@ "snapshot": "Snapshot", "importingState": "Creating", "reset": "Create another", - "noSnapshots": "No snapshots for this application yet." + "noSnapshots": "No snapshots for this application yet.", + "nameAlreadyExists": "A snapshot with this name already exists." }, "deleteSnapshotModal": { "title": "Delete snapshot", @@ -1054,5 +1057,11 @@ "configureDataSyncSettings": { "title": "Change data sync", "syncTable": "Sync when save" + }, + "webhookDeactivatedNotification": { + "body": "{name} webhook has been deactivated because it failed too many times consecutively." + }, + "webhookPayloadTooLargeNotification": { + "body": "The payload for the {name} webhook with event ID {event_id} was too large. The content has been split into multiple batches, but data above the batch limit of {batch_limit} was discarded." } } diff --git a/web-frontend/modules/database/locales/fr.json b/web-frontend/modules/database/locales/fr.json index d4cfdde27..b47f08ce5 100644 --- a/web-frontend/modules/database/locales/fr.json +++ b/web-frontend/modules/database/locales/fr.json @@ -621,19 +621,21 @@ "variance": "Variance", "notEmptyPercentage": "Pourcentage de renseignées", "notEmptyCount": "Renseignées", - "emptyCount": "Vides", + "emptyCount": "(Vides)", "emptyPercentage": "Pourcentage de vides", - "count": "Compter" + "count": "Compter", + "distribution": "Distribution", + "othersCount": "Autres" }, "databaseForm": { "importLabel": "Souhaitez-vous importer des données existantes ?", - "airtableLabel": "Importer à partir d'Airtable (beta)", + "airtableLabel": "Importer à partir d'Airtable", "emptyLabel": "Base de donnée vierge" }, "importFromAirtable": { "airtableShareLinkTitle": "Partager un lien vers votre Base", - "airtableShareLinkDescription": "Pour importer une base Airtable, vous devez au préalable créer un lien de partage de la base que vous souhaitez copier. Dans Airtable cliquez sur le bouton « share » dans le coin en haut à droite après avoir ouvert votre base. Ensuite, vous devez choisir l'option « Access to base ». Dans la fenêtre modale qui s'ouvre puis cliquez sur le bouton « Create a shared link to the whole base » et enfin cliquez sur « Private read-only link ». Copiez alors le lien publique généré et collez-le dans le champ suivant.", - "airtableShareLinkBeta": "Attention : cette fonctionnalité est encore en version beta, vos tables, champs (sauf les formules, les champs rapportés et les calculs) et les données seront importés. En revanche, les vues ne le seront pas.", + "airtableShareLinkDescription": "Pour importer une base Airtable, vous devez au préalable créer un lien de partage de la base que vous souhaitez copier. Dans Airtable cliquez sur le bouton « share » dans le coin en haut à droite après avoir ouvert votre base. Ensuite, vous devez choisir l'option « Share via link ». Dans la fenêtre modale qui s'ouvre puis cliquez sur le bouton « Share publicly » et enfin cliquez sur « Enable shared base link ». Copiez alors le lien publique généré et collez-le dans le champ suivant.", + "airtableShareLinkBeta": "Cette fonctionnalité importera la plupart des données, mais il existe des incompatibilités. Un tableau nommé \"Rapport d'importation Airtable\" sera donc créé et contiendra la liste des éléments qui n'ont pas été importés ou qui ont été partiellement importés.", "airtableShareLinkPaste": "Collez le lien ici", "importButtonLabel": "Importer à partir de Airtable", "openButtonLabel": "Ouvrir la base importée", @@ -719,7 +721,8 @@ "showFieldAs": "Afficher le champ comme", "includeAllSelectOptionsHelper": "Choisissez les options qui doivent être incluses dans le formulaire à l'aide de cette liste déroulante", "noSelectOptions": "Il n'y a pas d'options disponibles.", - "includeAllSelectOptions": "inclure toutes les options sélectionnées" + "includeAllSelectOptions": "inclure toutes les options sélectionnées", + "noCollaboratorsAvailable": "Il n'y a pas de collaborateurs disponibles." }, "duplicateFieldContext": { "duplicate": "Dupliquer le champ", @@ -742,7 +745,8 @@ "snapshotRestoredErrorTitle": "Une erreur s'est produite", "reset": "Créer une autre", "cancel": "Annuler", - "noSnapshots": "Il n'y a pas encore de sauvegarde pour cette application." + "noSnapshots": "Il n'y a pas encore de sauvegarde pour cette application.", + "nameAlreadyExists": "Une sauvegarde portant ce nom existe déjà." }, "deleteSnapshotModal": { "content": "Êtes-vous sûr·e de vouloir supprimer définitivement la sauvegarde {nom} ?", @@ -1087,5 +1091,14 @@ "title": "Modifier les champs synchronisés", "fields": "Champs synchronisés", "syncTable": "Synchroniser lors de l'enregistrement" + }, + "viewFieldConditionItem": { + "filterMisconfigured": "Le champ auquel ce filtre est associé a été supprimé." + }, + "webhookPayloadTooLargeNotification": { + "body": "La charge utile pour le webhook {name} avec l'ID d'événement {event_id} était trop importante. Le contenu a été divisé en plusieurs lots, mais les données dépassant la limite de {batch_limit} ont été rejetées." + }, + "webhookDeactivatedNotification": { + "body": "Le webhook {name} a été désactivé car il a échoué trop de fois consécutivement." } } diff --git a/web-frontend/modules/database/locales/ko.json b/web-frontend/modules/database/locales/ko.json index 08b568d4a..add8af9c1 100644 --- a/web-frontend/modules/database/locales/ko.json +++ b/web-frontend/modules/database/locales/ko.json @@ -726,7 +726,7 @@ "back": "대시보드로 돌아가기" }, "viewAggregationType": { - "emptyCount": "(비어 있음)", + "emptyCount": "빈 값", "notEmptyCount": "채워짐", "emptyPercentage": "비어 있는 비율", "notEmptyPercentage": "채워진 비율", diff --git a/web-frontend/modules/database/locales/nl.json b/web-frontend/modules/database/locales/nl.json index f92438938..a248eb7bc 100644 --- a/web-frontend/modules/database/locales/nl.json +++ b/web-frontend/modules/database/locales/nl.json @@ -718,7 +718,8 @@ "showFieldAs": "Toon veld als", "includeAllSelectOptionsHelper": "Kies de keuzes die in het formulier moeten worden opgenomen met behulp van deze dropdown", "noSelectOptions": "Er zijn geen keuzes beschikbaar.", - "includeAllSelectOptions": "inclusief alle keuzes" + "includeAllSelectOptions": "inclusief alle keuzes", + "noCollaboratorsAvailable": "Er zijn geen medewerkers beschikbaar." }, "duplicateFieldContext": { "duplicate": "Dupliceer veld", @@ -744,7 +745,8 @@ "snapshotDeletedErrorTitle": "Fout opgetreden", "importingState": "Maken", "cancel": "Annuleren", - "noSnapshots": "Er zijn nog geen snapshots voor deze applicatie." + "noSnapshots": "Er zijn nog geen snapshots voor deze applicatie.", + "nameAlreadyExists": "Er bestaat al een snapshot met deze naam." }, "deleteSnapshotModal": { "title": "Snapshot verwijderen", @@ -1089,5 +1091,14 @@ "configureDataSyncSettings": { "title": "Verander data sync", "syncTable": "Sync bij opslaan" + }, + "webhookPayloadTooLargeNotification": { + "body": "De payload voor de {name} webhook met event ID {event_id} was te groot. De inhoud is opgesplitst in meerdere batches, maar gegevens boven de batchnorm van {batch_limit} zijn weggegooid." + }, + "viewFieldConditionItem": { + "filterMisconfigured": "Het veld waaraan deze filter is gekoppeld, is weggegooid." + }, + "webhookDeactivatedNotification": { + "body": "{name} webhook is gedeactiveerd omdat het te vaak achter elkaar faalde." } } diff --git a/web-frontend/modules/database/mixins/copyPasteHelper.js b/web-frontend/modules/database/mixins/copyPasteHelper.js index dddc32cfb..00f8ef3fd 100644 --- a/web-frontend/modules/database/mixins/copyPasteHelper.js +++ b/web-frontend/modules/database/mixins/copyPasteHelper.js @@ -40,6 +40,13 @@ export default { prepareHTMLData(textData, firstRowIsHeader) { const table = document.createElement('table') const tbody = document.createElement('tbody') + + // For single cells we don't need html clipboard data as it's + // conflicting with tiptap + if (textData.length === 1 && textData[0].length === 1) { + return + } + textData.forEach((row, index) => { const tr = document.createElement('tr') row.forEach((cell) => { @@ -63,7 +70,6 @@ export default { // The HTML table renders a structured table when pasted into an email or rich // text document. const htmlData = this.prepareHTMLData(textData, includeHeader) - try { localStorage.setItem( LOCAL_STORAGE_CLIPBOARD_KEY, @@ -78,19 +84,24 @@ export default { // need to check if it is available. Safari instead, needs the // ClipboardItem type to save async data to the clipboard. if (typeof ClipboardItem !== 'undefined') { - navigator.clipboard.write([ - new ClipboardItem({ - 'text/plain': new Blob([tsvData], { type: 'text/plain' }), - 'text/html': new Blob([htmlData], { type: 'text/html' }), - }), - ]) + const clipboardConfig = { + 'text/plain': new Blob([tsvData], { type: 'text/plain' }), + } + if (htmlData) { + clipboardConfig['text/html'] = new Blob([htmlData], { + type: 'text/html', + }) + } + + navigator.clipboard.write([new ClipboardItem(clipboardConfig)]) } else if (typeof navigator.clipboard?.writeText !== 'undefined') { navigator.clipboard.writeText(tsvData) } else { - setRichClipboard({ - 'text/plain': tsvData, - 'text/html': htmlData, - }) + const richClipboardConfig = { 'text/plain': tsvData } + if (htmlData) { + richClipboardConfig['text/html'] = htmlData + } + setRichClipboard(richClipboardConfig) } }, async extractClipboardData(event) { diff --git a/web-frontend/modules/database/mixins/filterTypeInput.js b/web-frontend/modules/database/mixins/filterTypeInput.js index 3495d5c0d..919921f8c 100644 --- a/web-frontend/modules/database/mixins/filterTypeInput.js +++ b/web-frontend/modules/database/mixins/filterTypeInput.js @@ -43,8 +43,10 @@ export default { clearTimeout(delayTimeout) }, }, - mounted() { + created() { this.copy = this.prepareCopy(this.filter.value) + }, + mounted() { if (this.copy) { this.v$.$touch() } diff --git a/web-frontend/modules/database/mixins/importer.js b/web-frontend/modules/database/mixins/importer.js index 25b90984e..dc64e7c2d 100644 --- a/web-frontend/modules/database/mixins/importer.js +++ b/web-frontend/modules/database/mixins/importer.js @@ -9,6 +9,16 @@ import { const IMPORT_PREVIEW_MAX_ROW_COUNT = 6 export default { + props: { + mapping: { + type: Object, + required: false, + default: () => { + return {} + }, + }, + }, + data() { return { fileLoadingProgress: 0, diff --git a/web-frontend/modules/database/mixins/lookupFieldSubForm.js b/web-frontend/modules/database/mixins/lookupFieldSubForm.js new file mode 100644 index 000000000..3cd23e87f --- /dev/null +++ b/web-frontend/modules/database/mixins/lookupFieldSubForm.js @@ -0,0 +1,106 @@ +import form from '@baserow/modules/core/mixins/form' + +export default { + data() { + return { + selectedThroughField: null, + selectedTargetField: null, + allowedValues: [], + values: {}, + errorFromServer: null, + subFormDefaultValues: {}, + } + }, + computed: { + targetFieldFormulaType() { + if (this.selectedTargetField) { + return this.getFormulaType(this.selectedTargetField) + } + return 'unknown' + }, + }, + watch: { + defaultValues: { + handler(newDefaultValues) { + this.subFormDefaultValues = { ...newDefaultValues } + }, + immediate: true, + }, + selectedTargetField: { + /** + * Updates sub form defaults based on the selected target field. + * For new fields with untouched forms, always suggest target field settings. + * For existing fields, suggest settings only if the formula type changes. + */ + handler(newTargetField, oldTargetField) { + if (!newTargetField) { + return + } + const fieldId = this.defaultValues.id + const newField = !fieldId + const cleanForm = !this.$refs.subForm?.isDirty() + + const newFieldCleanFormAndNewTarget = + newField && cleanForm && newTargetField?.id !== oldTargetField?.id + + const existingFieldButDifferentType = + !newField && !this.matchTargetFieldType(newTargetField) + + const shouldSuggestDefaults = + newFieldCleanFormAndNewTarget || existingFieldButDifferentType + + const fieldType = this.$registry.get('field', newTargetField.type) + const formulaType = fieldType.toBaserowFormulaType(newTargetField) + + // New field or different type, use the relevant settings from the target field + if (shouldSuggestDefaults) { + const defaults = {} + for (const key in this.selectedTargetField) { + if (key.startsWith(formulaType)) { + defaults[key] = this.selectedTargetField[key] + } + } + this.subFormDefaultValues = { + ...this.subFormDefaultValues, + ...defaults, + } + this.$nextTick(() => this.$refs.subForm.reset()) + } + }, + }, + }, + methods: { + /** + * Verify if the final formula type match the target field type. + */ + matchTargetFieldType(targetField) { + const field = this.defaultValues + return ( + field?.type === this.fieldType && + (field?.formula_type === targetField?.type || + field?.array_formula_type === targetField?.type) + ) + }, + getFormulaType(field) { + return field.array_formula_type || field.formula_type || field.type + }, + handleErrorByForm(error) { + if ( + [ + 'ERROR_WITH_FORMULA', + 'ERROR_FIELD_SELF_REFERENCE', + 'ERROR_FIELD_CIRCULAR_REFERENCE', + ].includes(error.handler.code) + ) { + this.errorFromServer = error.handler.detail + return true + } else { + return false + } + }, + reset() { + form.methods.reset.call(this) + this.errorFromServer = null + }, + }, +} diff --git a/web-frontend/modules/database/notificationTypes.js b/web-frontend/modules/database/notificationTypes.js index 17090201a..ca2bf162f 100644 --- a/web-frontend/modules/database/notificationTypes.js +++ b/web-frontend/modules/database/notificationTypes.js @@ -3,6 +3,8 @@ import NotificationSenderInitialsIcon from '@baserow/modules/core/components/not import CollaboratorAddedToRowNotification from '@baserow/modules/database/components/notifications/CollaboratorAddedToRowNotification' import UserMentionInRichTextFieldNotification from '@baserow/modules/database/components/notifications/UserMentionInRichTextFieldNotification' import FormSubmittedNotification from '@baserow/modules/database/components/notifications/FormSubmittedNotification' +import WebhookDeactivatedNotification from '@baserow/modules/database/components/notifications/WebhookDeactivatedNotification' +import WebhookPayloadTooLargeNotification from '@baserow/modules/database/components/notifications/WebhookPayloadTooLargeNotification' export class CollaboratorAddedToRowNotificationType extends NotificationType { static getType() { @@ -78,3 +80,51 @@ export class UserMentionInRichTextFieldNotificationType extends NotificationType } } } + +export class WebhookDeactivatedNotificationType extends NotificationType { + static getType() { + return 'webhook_deactivated' + } + + getIconComponent() { + return null + } + + getContentComponent() { + return WebhookDeactivatedNotification + } + + getRoute(notificationData) { + return { + name: 'database-table-open-webhooks', + params: { + databaseId: notificationData.database_id, + tableId: notificationData.table_id, + }, + } + } +} + +export class WebhookPayloadTooLargedNotificationType extends NotificationType { + static getType() { + return 'webhook_payload_too_large' + } + + getIconComponent() { + return null + } + + getContentComponent() { + return WebhookPayloadTooLargeNotification + } + + getRoute(notificationData) { + return { + name: 'database-table-open-webhooks', + params: { + databaseId: notificationData.database_id, + tableId: notificationData.table_id, + }, + } + } +} diff --git a/web-frontend/modules/database/pages/table.vue b/web-frontend/modules/database/pages/table.vue index 5fd1c56dc..faa509e86 100644 --- a/web-frontend/modules/database/pages/table.vue +++ b/web-frontend/modules/database/pages/table.vue @@ -1,11 +1,14 @@ <template> <div> + <DefaultErrorPage v-if="error && !view" :error="error" /> <Table + v-else :database="database" :table="table" :fields="fields" :views="views" :view="view" + :view-error="error" :table-loading="tableLoading" store-prefix="page/" @selected-view="selectedView" @@ -17,6 +20,7 @@ (row, activeSearchTerm) => setAdjacentRow(false, row, activeSearchTerm) " ></Table> + <NuxtChild :database="database" :table="table" :fields="fields" /> </div> </template> @@ -26,13 +30,15 @@ import { mapState } from 'vuex' import Table from '@baserow/modules/database/components/table/Table' import { StoreItemLookupError } from '@baserow/modules/core/errors' import { getDefaultView } from '@baserow/modules/database/utils/view' +import DefaultErrorPage from '@baserow/modules/core/components/DefaultErrorPage' +import { normalizeError } from '@baserow/modules/database/utils/errors' /** * This page component is the skeleton for a table. Depending on the selected view it * will load the correct components into the header and body. */ export default { - components: { Table }, + components: { DefaultErrorPage, Table }, /** * When the user leaves to another page we want to unselect the selected table. This * way it will not be highlighted the left sidebar. @@ -55,6 +61,7 @@ export default { function parseIntOrNull(x) { return x != null ? parseInt(x) : null } + const currentRowId = parseIntOrNull(to.params?.rowId) const currentTableId = parseIntOrNull(to.params.tableId) @@ -115,37 +122,44 @@ export default { * Prepares all the table, field and view data for the provided database, table and * view id. */ - async asyncData({ store, params, error, app, redirect, route }) { + async asyncData({ store, params, query, error, app, redirect, route }) { // @TODO figure out why the id's aren't converted to an int in the route. const databaseId = parseInt(params.databaseId) const tableId = parseInt(params.tableId) const viewId = params.viewId ? parseInt(params.viewId) : null - const data = {} - + // let's use undefined for view, as it's explicitly checked in components + const data = { error: null, view: undefined, fields: null } // Try to find the table in the already fetched applications by the // workspacesAndApplications middleware and select that one. By selecting the table, the // fields and views are also going to be fetched. try { - const { database, table } = await store.dispatch('table/selectById', { - databaseId, - tableId, - }) + const { database, table, error } = await store.dispatch( + 'table/selectById', + { + databaseId, + tableId, + } + ) await store.dispatch('workspace/selectById', database.workspace.id) data.database = database data.table = table + + if (error) { + data.error = normalizeError(error) + return data + } } catch (e) { // In case of a network error we want to fail hard. if (e.response === undefined && !(e instanceof StoreItemLookupError)) { throw e } - - return error({ statusCode: 404, message: 'Table not found.' }) + data.error = normalizeError(e) + return data } // After selecting the table the fields become available which need to be added to // the data. data.fields = store.getters['field/getAll'] - data.view = undefined // Without a viewId, redirect the user to the default or the first available view. if (viewId === null) { @@ -154,14 +168,11 @@ export default { const viewToUse = getDefaultView(app, store, workspaceId, rowId !== null) if (viewToUse !== undefined) { + params.viewId = viewToUse.id return redirect({ name: route.name, - params: { - databaseId, - tableId, - viewId: viewToUse.id, - rowId: params.rowId, - }, + params, + query, }) } } @@ -194,18 +205,17 @@ export default { if (e.response === undefined && !(e instanceof StoreItemLookupError)) { throw e } + data.error = normalizeError(e) - return error({ statusCode: 404, message: 'View not found.' }) + return data } } - if (params.rowId) { await store.dispatch('rowModalNavigation/fetchRow', { tableId, rowId: params.rowId, }) } - return data }, head() { diff --git a/web-frontend/modules/database/pages/table/configureDataSync.vue b/web-frontend/modules/database/pages/table/configureDataSync.vue new file mode 100644 index 000000000..c9544c590 --- /dev/null +++ b/web-frontend/modules/database/pages/table/configureDataSync.vue @@ -0,0 +1,49 @@ +<template> + <div> + <ConfigureDataSyncModal + ref="configureDataSyncModal" + :database="database" + :table="table" + @hidden="back" + ></ConfigureDataSyncModal> + </div> +</template> + +<script> +import ConfigureDataSyncModal from '@baserow/modules/database/components/dataSync/ConfigureDataSyncModal' + +export default { + components: { ConfigureDataSyncModal }, + props: { + database: { + type: Object, + required: true, + }, + table: { + type: Object, + required: true, + }, + fields: { + type: Array, + required: true, + }, + }, + mounted() { + if (this.table.data_sync === null) { + return this.back() + } + + this.$nextTick(() => { + this.$refs.configureDataSyncModal.show( + this.$route.params.selectedPage || undefined + ) + }) + }, + methods: { + back() { + delete this.$route.params.selectedPage + this.$router.push({ name: 'database-table', params: this.$route.params }) + }, + }, +} +</script> diff --git a/web-frontend/modules/database/pages/table/webhooks.vue b/web-frontend/modules/database/pages/table/webhooks.vue new file mode 100644 index 000000000..2beca9afc --- /dev/null +++ b/web-frontend/modules/database/pages/table/webhooks.vue @@ -0,0 +1,37 @@ +<template> + <div> + <WebhookModal + ref="webhookModal" + :database="database" + :table="table" + :fields="fields" + @hidden="$router.push({ name: 'database-table', params: $route.params })" + /> + </div> +</template> +<script> +import WebhookModal from '@baserow/modules/database/components/webhook/WebhookModal' + +export default { + components: { WebhookModal }, + props: { + database: { + type: Object, + required: true, + }, + table: { + type: Object, + required: true, + }, + fields: { + type: Array, + required: true, + }, + }, + mounted() { + this.$nextTick(() => { + this.$refs.webhookModal.show() + }) + }, +} +</script> diff --git a/web-frontend/modules/database/plugin.js b/web-frontend/modules/database/plugin.js index 81080b112..431fec47a 100644 --- a/web-frontend/modules/database/plugin.js +++ b/web-frontend/modules/database/plugin.js @@ -319,6 +319,8 @@ import { CollaboratorAddedToRowNotificationType, FormSubmittedNotificationType, UserMentionInRichTextFieldNotificationType, + WebhookDeactivatedNotificationType, + WebhookPayloadTooLargedNotificationType, } from '@baserow/modules/database/notificationTypes' import { HistoryRowModalSidebarType } from '@baserow/modules/database/rowModalSidebarTypes' import { FieldsDataProviderType } from '@baserow/modules/database/dataProviderTypes' @@ -1019,6 +1021,14 @@ export default (context) => { 'notification', new UserMentionInRichTextFieldNotificationType(context) ) + app.$registry.register( + 'notification', + new WebhookDeactivatedNotificationType(context) + ) + app.$registry.register( + 'notification', + new WebhookPayloadTooLargedNotificationType(context) + ) app.$registry.register( 'rowModalSidebar', diff --git a/web-frontend/modules/database/routes.js b/web-frontend/modules/database/routes.js index f256948da..74ae47315 100644 --- a/web-frontend/modules/database/routes.js +++ b/web-frontend/modules/database/routes.js @@ -23,6 +23,16 @@ export const routes = [ path: 'row/:rowId', name: 'database-table-row', }, + { + path: 'webhooks', + name: 'database-table-open-webhooks', + component: path.resolve(__dirname, 'pages/table/webhooks.vue'), + }, + { + path: 'configure-data-sync/:selectedPage?', + name: 'database-table-open-configure-data-sync', + component: path.resolve(__dirname, 'pages/table/configureDataSync.vue'), + }, ], }, // These redirect exist because the original api docs path was `/api/docs`, but diff --git a/web-frontend/modules/database/services/table.js b/web-frontend/modules/database/services/table.js index 918680d9f..4053ba8d1 100644 --- a/web-frontend/modules/database/services/table.js +++ b/web-frontend/modules/database/services/table.js @@ -29,10 +29,15 @@ export default (client) => { return client.post(`/database/tables/database/${databaseId}/`, values) }, - importData(tableId, data, config = null) { + importData(tableId, data, config = null, importConfiguration = null) { + const payload = { data } + if (importConfiguration) { + payload.configuration = importConfiguration + } + return client.post( `/database/tables/${tableId}/import/async/`, - { data }, + payload, config ) }, diff --git a/web-frontend/modules/database/store/table.js b/web-frontend/modules/database/store/table.js index b10ab1c88..5dfed2c3c 100644 --- a/web-frontend/modules/database/store/table.js +++ b/web-frontend/modules/database/store/table.js @@ -211,14 +211,18 @@ export const actions = { if (getters.getSelectedId === table.id) { return { database, table } } - - await axios.all([ - dispatch('view/fetchAll', table, { root: true }), - dispatch('field/fetchAll', table, { root: true }), - ]) + let error = null + await axios + .all([ + dispatch('view/fetchAll', table, { root: true }), + dispatch('field/fetchAll', table, { root: true }), + ]) + .catch((err) => { + error = err + }) await dispatch('application/clearChildrenSelected', null, { root: true }) await dispatch('forceSelect', { database, table }) - return { database, table } + return { database, table, error } }, forceSelect({ commit, dispatch }, { database, table }) { dispatch( @@ -259,7 +263,7 @@ export const actions = { } const table = database.tables[index] - return dispatch('select', { database, table }) + return await dispatch('select', { database, table }) }, /** * Unselect the selected table. diff --git a/web-frontend/modules/database/store/view.js b/web-frontend/modules/database/store/view.js index 54f8377da..a4f63145f 100644 --- a/web-frontend/modules/database/store/view.js +++ b/web-frontend/modules/database/store/view.js @@ -1353,8 +1353,8 @@ export const actions = { * to the delete field. */ fieldUpdated({ dispatch, commit, getters }, { field, fieldType }) { - // Remove all filters are not compatible anymore. getters.getAll.forEach((view) => { + // Remove all filters are not compatible anymore. view.filters .filter((filter) => filter.field === field.id) .forEach((filter) => { @@ -1364,19 +1364,33 @@ export const actions = { commit('DELETE_FILTER', { view, id: filter.id }) } }) + + // Remove all sorts are not compatible anymore. + view.sortings + .filter((sort) => sort.field === field.id) + .forEach((sort) => { + const sortTypes = fieldType.getSortTypes(field) + const compatible = + fieldType.getCanSortInView(field) && + Object.prototype.hasOwnProperty.call(sortTypes, sort.type) + if (!compatible) { + dispatch('deleteFieldSortings', { field }) + } + }) + + // Remove all sorts are not compatible anymore. + view.group_bys + .filter((groupBy) => groupBy.field === field.id) + .forEach((groupBy) => { + const sortTypes = fieldType.getSortTypes(field) + const compatible = + fieldType.getCanSortInView(field) && + Object.prototype.hasOwnProperty.call(sortTypes, groupBy.type) + if (!compatible) { + dispatch('deleteFieldGroupBys', { field }) + } + }) }) - - // Remove all the field sortings because the new field does not support sortings - // at all. - if (!fieldType.getCanSortInView(field)) { - dispatch('deleteFieldSortings', { field }) - } - - // Remove all the field group bys because the new field does not support group bys - // at all. - if (!fieldType.getCanGroupByInView(field)) { - dispatch('deleteFieldGroupBys', { field }) - } }, /** * Is called when a field is deleted. It will remove all filters and sortings diff --git a/web-frontend/modules/database/utils/errors.js b/web-frontend/modules/database/utils/errors.js new file mode 100644 index 000000000..e98d20d2e --- /dev/null +++ b/web-frontend/modules/database/utils/errors.js @@ -0,0 +1,23 @@ +/** + * Returns most expected error structure. + * + * When an error is thrown, it can be of any type. This function tries to return + * the most useful error data from the error. It tries to return any first of the + * following: + * + * * http response body, if it's a DRF error structure + * * http response object + * * the error as-is in any other case + * + * @param err + * @param errorMap + * @returns {*} + */ +export function normalizeError(err) { + err = err.response?.data?.message ? err.response.data : err.response || err + return { + message: err.message, + content: err.detail, + statusCode: err.statusCode, + } +} diff --git a/web-frontend/modules/database/utils/view.js b/web-frontend/modules/database/utils/view.js index 889c61aee..7f49ee2e5 100644 --- a/web-frontend/modules/database/utils/view.js +++ b/web-frontend/modules/database/utils/view.js @@ -4,6 +4,7 @@ import { maxPossibleOrderValue } from '@baserow/modules/database/viewTypes' import { escapeRegExp, isSecureURL } from '@baserow/modules/core/utils/string' import { SearchModes } from '@baserow/modules/database/utils/search' import { convertStringToMatchBackendTsvectorData } from '@baserow/modules/database/search/regexes' +import { DEFAULT_SORT_TYPE_KEY } from '@baserow/modules/database/constants' export const DEFAULT_VIEW_ID_COOKIE_NAME = 'defaultViewId' @@ -20,7 +21,12 @@ export function getRowSortFunction($registry, sortings, fields, groupBys = []) { if (field !== undefined) { const fieldName = `field_${field.id}` const fieldType = $registry.get('field', field.type) - const fieldSortFunction = fieldType.getSort(fieldName, sort.order, field) + const sortTypes = fieldType.getSortTypes(field) + const fieldSortFunction = sortTypes[sort.type].function( + fieldName, + sort.order, + field + ) sortFunction = sortFunction.thenBy(fieldSortFunction) } }) @@ -457,7 +463,13 @@ export function getGroupBy(rootGetters, viewId) { const view = rootGetters['view/get'](viewId) return view.group_bys .map((groupBy) => { - return `${groupBy.order === 'DESC' ? '-' : ''}field_${groupBy.field}` + let serialized = `${groupBy.order === 'DESC' ? '-' : ''}field_${ + groupBy.field + }` + if (groupBy.type !== DEFAULT_SORT_TYPE_KEY) { + serialized += `[${groupBy.type}]` + } + return serialized }) .join(',') } else { @@ -517,7 +529,11 @@ export function canRowsBeOptimisticallyUpdatedInView( export function getOrderBy(view, adhocSorting) { if (adhocSorting) { const serializeSort = (sort) => { - return `${sort.order === 'DESC' ? '-' : ''}field_${sort.field}` + let serialized = `${sort.order === 'DESC' ? '-' : ''}field_${sort.field}` + if (sort.type !== DEFAULT_SORT_TYPE_KEY) { + serialized += `[${sort.type}]` + } + return serialized } // Group bys first, then sorts to ensure that the order is correct. const groupBys = view.group_bys ? view.group_bys.map(serializeSort) : [] diff --git a/web-frontend/modules/database/webhookEventTypes.js b/web-frontend/modules/database/webhookEventTypes.js index bfa244b5d..2719e9343 100644 --- a/web-frontend/modules/database/webhookEventTypes.js +++ b/web-frontend/modules/database/webhookEventTypes.js @@ -49,6 +49,39 @@ export class WebhookEventType extends Registerable { getRelatedFieldsHelpText() { return null } + + /** + * If `true`, then a dropdown will be shown next to the webhook type allowing the user + * to choose related views. This can for example for an event that's restricted to + * certain view updates. + */ + getHasRelatedView() { + return false + } + + getRelatedViewPlaceholder() { + return null + } + + getRelatedViewHelpText() { + return null + } + + getDeactivatedText() { + return '' + } + + getDeactivatedClickModal() { + return null + } + + isDeactivated(workspaceId) { + return false + } + + getFeatureName() { + return '' + } } export class RowsCreatedWebhookEventType extends WebhookEventType { @@ -183,13 +216,18 @@ export class FieldDeletedWebhookEventType extends WebhookEventType { // Unfortunately, we don't have an example of the field object in the web-frontend, so // we would need to hardcode it here. -const viewExample = { +export const viewExample = { id: 0, table_id: 0, name: 'View', order: 1, type: 'grid', - table: null, + table: { + id: 0, + order: 1, + name: 'Table', + database_id: 0, + }, filter_type: 'AND', filters_disabled: false, public_view_has_password: false, diff --git a/web-frontend/modules/integrations/localBaserow/components/integrations/LocalBaserowAdhocHeader.vue b/web-frontend/modules/integrations/localBaserow/components/integrations/LocalBaserowAdhocHeader.vue index 634105dda..c916d8915 100644 --- a/web-frontend/modules/integrations/localBaserow/components/integrations/LocalBaserowAdhocHeader.vue +++ b/web-frontend/modules/integrations/localBaserow/components/integrations/LocalBaserowAdhocHeader.vue @@ -1,7 +1,7 @@ <template> <div class="local-baserow-adhoc-header__container"> - <ul class="header__filter"> - <li class="header__filter-item"> + <div class="local-baserow-adhoc-header"> + <div class="local-baserow-adhoc-header__item"> <ViewFilter v-if="filterableFields.length" read-only @@ -10,8 +10,8 @@ :disable-filter="false" @changed="handleFiltersChange" ></ViewFilter> - </li> - <li class="header__filter-item"> + </div> + <div class="local-baserow-adhoc-header__item"> <ViewSort v-if="sortableFields.length" read-only @@ -19,8 +19,9 @@ :fields="sortableFields" @changed="handleSortingsChange" ></ViewSort> - </li> - <li class="header__filter-item header__filter-item--right"> + </div> + <div class="flex-grow-1" /> + <div class="local-baserow-adhoc-header__item"> <ViewSearch v-if="searchableFields.length" read-only @@ -29,8 +30,8 @@ :fields="searchableFields" @refresh="handleSearchChange" ></ViewSearch> - </li> - </ul> + </div> + </div> </div> </template> diff --git a/web-frontend/modules/integrations/localBaserow/components/services/LocalBaserowAggregateRowsForm.vue b/web-frontend/modules/integrations/localBaserow/components/services/LocalBaserowAggregateRowsForm.vue index 8391bdb62..3b1b81d21 100644 --- a/web-frontend/modules/integrations/localBaserow/components/services/LocalBaserowAggregateRowsForm.vue +++ b/web-frontend/modules/integrations/localBaserow/components/services/LocalBaserowAggregateRowsForm.vue @@ -45,6 +45,9 @@ :key="viewAggregation.getType()" :name="viewAggregation.getName()" :value="viewAggregation.getType()" + :disabled=" + unsupportedAggregationTypes.includes(viewAggregation.getType()) + " > </DropdownItem> </Dropdown> @@ -127,6 +130,10 @@ export default { } }, computed: { + unsupportedAggregationTypes() { + return this.$registry.get('service', 'local_baserow_aggregate_rows') + .unsupportedAggregationTypes + }, viewAggregationTypes() { const selectedField = this.tableFields.find( (field) => field.id === this.values.field_id diff --git a/web-frontend/modules/integrations/localBaserow/components/services/LocalBaserowTableServiceSortForm.vue b/web-frontend/modules/integrations/localBaserow/components/services/LocalBaserowTableServiceSortForm.vue index 43f9175ad..6a6bb33de 100644 --- a/web-frontend/modules/integrations/localBaserow/components/services/LocalBaserowTableServiceSortForm.vue +++ b/web-frontend/modules/integrations/localBaserow/components/services/LocalBaserowTableServiceSortForm.vue @@ -237,9 +237,7 @@ export default { this.$emit('input', newSortings) }, getSortIndicator(field, index) { - return this.getFieldType(field).getSortIndicator(field, this.$registry)[ - index - ] + return this.getFieldType(field).getSortIndicator(field)[index] }, }, } diff --git a/web-frontend/modules/integrations/locales/de.json b/web-frontend/modules/integrations/locales/de.json index 4d427853d..d6ff241b7 100644 --- a/web-frontend/modules/integrations/locales/de.json +++ b/web-frontend/modules/integrations/locales/de.json @@ -47,7 +47,8 @@ }, "serviceType": { "localBaserowGetRow": "Einzelne Zeile abfragen", - "localBaserowListRows": "{multipleRows} auflisten" + "localBaserowListRows": "Mehrere Zeilen auflisten", + "localBaserowAggregateRows": "Feld zusammenfassen" }, "userSourceType": { "localBaserow": "Baserow-Tabellen-Authentifizierung" @@ -72,5 +73,13 @@ "integrationsCommon": { "singleRow": "Einzelne Zeile", "multipleRows": "Mehrere Zeilen" + }, + "localBaserowAggregateRowsForm": { + "filterTabTitle": "Filter", + "searchTabTitle": "Suche", + "aggregationFieldLabel": "Feld", + "aggregationTypeLabel": "Aggregierung", + "searchFieldPlaceHolder": "Geben Sie einen Suchbegriff ein...", + "noTableChosenForFiltering": "Wählen Sie eine Tabelle, um mit der Verwendung von Datenquellenfiltern zu beginnen." } } diff --git a/web-frontend/modules/integrations/locales/fr.json b/web-frontend/modules/integrations/locales/fr.json index 21603dc29..0c2dbe9b5 100644 --- a/web-frontend/modules/integrations/locales/fr.json +++ b/web-frontend/modules/integrations/locales/fr.json @@ -7,7 +7,9 @@ "serviceType": { "localBaserowGetRow": "Obtenir une ligne", "localBaserowListRows": "Lister plusieurs lignes", - "localBaserowAggregateRows": "Résumer une colonne" + "localBaserowAggregateRows": "Résumer une colonne", + "trashedField": "Champ supprimé", + "misconfigured": "Configuration incorrecte" }, "localBaserowForm": { "user": "Utilisateur", @@ -50,7 +52,8 @@ "sortBy": "Trier par", "addSort": "Ajouter un tri", "thenBy": "Puis par", - "noTableChosenForSorting": "Sélectionnez une table pour pouvoir ordonner les lignes de la sources de données." + "noTableChosenForSorting": "Sélectionnez une table pour pouvoir ordonner les lignes de la sources de données.", + "sortMisconfigured": "Le champ auquel ce tri est associé à été supprimé." }, "dataProviderType": { "dataSource": "Source de données", diff --git a/web-frontend/modules/integrations/locales/nl.json b/web-frontend/modules/integrations/locales/nl.json index 3aafdc9b5..7cf8b8638 100644 --- a/web-frontend/modules/integrations/locales/nl.json +++ b/web-frontend/modules/integrations/locales/nl.json @@ -44,7 +44,9 @@ "serviceType": { "localBaserowGetRow": "Rij ophalen", "localBaserowListRows": "Rijen ophalen", - "localBaserowAggregateRows": "Veld samenvatten" + "localBaserowAggregateRows": "Veld samenvatten", + "misconfigured": "Verkeerd geconfigureerd", + "trashedField": "In prullenbak gestopt veld" }, "userSourceType": { "localBaserow": "Baserow tabel authenticatie" @@ -59,7 +61,8 @@ "sortBy": "Sorteer op", "thenBy": "Dan op", "addSort": "Extra sortering toevoegen", - "noTableChosenForSorting": "Kies een tabel om te beginnen met het sorteren van gegevensbronnen." + "noTableChosenForSorting": "Kies een tabel om te beginnen met het sorteren van gegevensbronnen.", + "sortMisconfigured": "Het veld waar deze sortering aan gekoppeld is, is weggegooid." }, "dataProviderType": { "dataSource": "Gegevensbron", diff --git a/web-frontend/modules/integrations/serviceTypes.js b/web-frontend/modules/integrations/serviceTypes.js index ba72332b4..f72d7ea27 100644 --- a/web-frontend/modules/integrations/serviceTypes.js +++ b/web-frontend/modules/integrations/serviceTypes.js @@ -5,6 +5,7 @@ import LocalBaserowListRowsForm from '@baserow/modules/integrations/localBaserow import LocalBaserowAggregateRowsForm from '@baserow/modules/integrations/localBaserow/components/services/LocalBaserowAggregateRowsForm' import { uuid } from '@baserow/modules/core/utils/string' import LocalBaserowAdhocHeader from '@baserow/modules/integrations/localBaserow/components/integrations/LocalBaserowAdhocHeader' +import { DistributionViewAggregationType } from '@baserow/modules/database/viewAggregationTypes' export class LocalBaserowTableServiceType extends ServiceType { get integrationType() { @@ -239,6 +240,14 @@ export class LocalBaserowAggregateRowsServiceType extends LocalBaserowTableServi return LocalBaserowAggregateRowsForm } + /** + * Local Baserow aggregate rows does not currently support the distribution + * aggregation type, this will be resolved in a future release. + */ + get unsupportedAggregationTypes() { + return [DistributionViewAggregationType.getType()] + } + getResult(service, data) { if (data && data.result !== undefined && service !== undefined) { const field = service.context_data.field diff --git a/web-frontend/package.json b/web-frontend/package.json index d62002f78..e54c3a92e 100644 --- a/web-frontend/package.json +++ b/web-frontend/package.json @@ -1,6 +1,6 @@ { "name": "baserow", - "version": "1.31.1", + "version": "1.32.0", "private": true, "description": "Baserow: open source no-code database web frontend.", "author": "Bram Wiepjes (Baserow)", diff --git a/web-frontend/stories/SegmentControl.stories.mdx b/web-frontend/stories/SegmentControl.stories.mdx index a7fca904a..38b69cb5a 100644 --- a/web-frontend/stories/SegmentControl.stories.mdx +++ b/web-frontend/stories/SegmentControl.stories.mdx @@ -43,7 +43,14 @@ import SegmentControl from '@baserow/modules/core/components/SegmentControl' size: { control: { type: 'select', - options: ['regular', 'small'], + options: ['regular', 'small', 'large'], + }, + defaultValue: 'regular', + }, + type: { + control: { + type: 'select', + options: ['regular', 'rounded'], }, defaultValue: 'regular', }, diff --git a/web-frontend/test/helpers/components.js b/web-frontend/test/helpers/components.js index e5b8c6617..150f169f4 100644 --- a/web-frontend/test/helpers/components.js +++ b/web-frontend/test/helpers/components.js @@ -39,6 +39,7 @@ export const bootstrapVueContext = (configureContext) => { jest.isolateModules(() => { context.vueTestUtils = require('@vue/test-utils') context.vueTestUtils.config.stubs.nuxt = { template: '<div />' } + context.vueTestUtils.config.stubs.NuxtChild = { template: '<div />' } context.vueTestUtils.config.stubs['nuxt-link'] = { template: '<a><slot /></a>', } diff --git a/web-frontend/test/unit/builder/elementTypes.spec.js b/web-frontend/test/unit/builder/elementTypes.spec.js index 7a6dcf351..e3296be78 100644 --- a/web-frontend/test/unit/builder/elementTypes.spec.js +++ b/web-frontend/test/unit/builder/elementTypes.spec.js @@ -898,6 +898,89 @@ describe('elementTypes tests', () => { }) }) + describe('MenuElementType isInError tests', () => { + test('Returns true if Menu Element has errors, false otherwise', () => { + const elementType = testApp.getRegistry().get('element', 'menu') + + const page = { + id: 1, + shared: false, + name: 'Foo Page', + workflowActions: [], + } + const element = { + id: 50, + page_id: page.id, + menu_items: [], + } + const builder = { + id: 1, + pages: [page], + } + + // Menu element with zero Menu items is invalid. + expect(elementType.isInError({ page: {}, element, builder })).toBe(true) + + const menuItem = { + type: 'button', + name: 'foo button', + } + element.menu_items = [menuItem] + + // Button Menu item without workflow actions is invalid. + expect(elementType.isInError({ page, element, builder })).toBe(true) + + page.workflowActions = [{ element_id: 50, type: 'open_page' }] + element.menu_items[0].name = '' + + // Button Menu item with empty name is invalid. + expect(elementType.isInError({ page, element, builder })).toBe(true) + + element.menu_items[0].type = 'link' + element.menu_items[0].name = '' + + // Link Menu item with empty name is invalid. + expect(elementType.isInError({ page, element, builder })).toBe(true) + + element.menu_items[0].name = 'sub link' + element.menu_items[0].navigation_type = 'page' + element.menu_items[0].navigate_to_page_id = '' + + // Link Menu item - sublink with Page navigation but no page ID is invalid. + expect(elementType.isInError({ page, element, builder })).toBe(true) + + element.menu_items[0].name = 'sub link' + element.menu_items[0].navigation_type = 'custom' + element.menu_items[0].navigate_to_url = '' + + // Link Menu item - sublink with custom navigation but no URL is invalid. + expect(elementType.isInError({ page, element, builder })).toBe(true) + + // Valid Button Menu item + element.menu_items[0].type = 'button' + element.menu_items[0].name = 'foo button' + page.workflowActions = [{ element_id: 50, type: 'open_page' }] + + expect(elementType.isInError({ page, element, builder })).toBe(false) + + // Valid Link Menu item - page + element.menu_items[0].type = 'link' + element.menu_items[0].name = 'foo link' + element.menu_items[0].navigation_type = 'page' + element.menu_items[0].navigate_to_page_id = 10 + + expect(elementType.isInError({ page, element, builder })).toBe(false) + + // Valid Link Menu item - custom + element.menu_items[0].type = 'link' + element.menu_items[0].name = 'foo link' + element.menu_items[0].navigation_type = 'custom' + element.menu_items[0].navigate_to_url = 'https://www.baserow.io' + + expect(elementType.isInError({ page, element, builder })).toBe(false) + }) + }) + describe('elementType elementAround tests', () => { let page, sharedPage, builder beforeEach(async () => { diff --git a/web-frontend/test/unit/database/__snapshots__/publicView.spec.js.snap b/web-frontend/test/unit/database/__snapshots__/publicView.spec.js.snap index ba6e01a66..555f5b2b8 100644 --- a/web-frontend/test/unit/database/__snapshots__/publicView.spec.js.snap +++ b/web-frontend/test/unit/database/__snapshots__/publicView.spec.js.snap @@ -354,6 +354,8 @@ exports[`Public View Page Tests Can see a publicly shared grid view 1`] = ` <div class="layout__col-2-2 content" > + <!----> + <div class="grid-view grid-view--row-height-undefined" > diff --git a/web-frontend/test/unit/database/store/view/bufferedRows.spec.js b/web-frontend/test/unit/database/store/view/bufferedRows.spec.js index f46b0336e..7cbb34183 100644 --- a/web-frontend/test/unit/database/store/view/bufferedRows.spec.js +++ b/web-frontend/test/unit/database/store/view/bufferedRows.spec.js @@ -1502,6 +1502,7 @@ describe('Buffered rows view store helper', () => { view: 1, field: 1, order: 'ASC', + type: 'default', }, ], } @@ -1669,6 +1670,7 @@ describe('Buffered rows view store helper', () => { view: 1, field: 1, order: 'ASC', + type: 'default', }, ], } diff --git a/web-frontend/test/unit/database/view.spec.js b/web-frontend/test/unit/database/view.spec.js index e4d265ea1..dee817808 100644 --- a/web-frontend/test/unit/database/view.spec.js +++ b/web-frontend/test/unit/database/view.spec.js @@ -361,6 +361,114 @@ describe('View Tests', () => { expect(updatedCookieValue.length).toBeLessThan(originalDataLength) }) + test('Unknown error during views loading is displayed correctly - no view toolbar', async () => { + const viewsError = { statusCode: 500, data: 'some backend error' } + + // no list of views + const { application, table } = await givenATableWithError({ + viewsError, + }) + const tableComponent = await testApp.mount(Table, { + asyncDataParams: { + databaseId: application.id, + tableId: table.id, + viewId: '123', + }, + }) + + expect(tableComponent.vm.views).toEqual([]) + + expect(tableComponent.vm.error).toBeTruthy() + + // no table header (view selection, filters, sorting, grouping...) + expect(tableComponent.find('header .header__filter-link').exists()).toBe( + false + ) + + expect(tableComponent.find('.placeholder__title').exists()).toBe(true) + // error message will be processed and replaced + expect(tableComponent.find('.placeholder__title').text()).toBe( + 'errorLayout.wrong' + ) + expect(tableComponent.find('.placeholder__content').exists()).toBe(true) + + expect(tableComponent.find('.placeholder__content').text()).toBe( + 'errorLayout.error' + ) + }) + + test('API error during views loading is displayed correctly', async () => { + const viewsError = { + statusCode: 400, + data: { + message: "The view filter type INVALID doesn't exist.", + }, + } + + // no list of views + const { application, table } = await givenATableWithError({ + viewsError, + }) + const tableComponent = await testApp.mount(Table, { + asyncDataParams: { + databaseId: application.id, + tableId: table.id, + viewId: '123', + }, + }) + + expect(tableComponent.vm.views).toEqual([]) + expect(tableComponent.vm.error).toBeTruthy() + + expect(tableComponent.find('header .header__filter-link').exists()).toBe( + false + ) + expect(tableComponent.find('.placeholder__title').exists()).toBe(true) + expect(tableComponent.find('.placeholder__title').text()).toEqual( + viewsError.data.message + ) + expect(tableComponent.find('.placeholder__content').exists()).toBe(true) + + expect(tableComponent.find('.placeholder__content').text()).toEqual( + 'errorLayout.error' + ) + }) + + test('API error during view rows loading', async () => { + const rowsError = { statusCode: 500, data: { message: 'Unknown error' } } + + // views list readable, fields readable, rows not readable + const { application, table, view } = await givenATableWithError({ + rowsError, + }) + + // + const tableComponent = await testApp.mount(Table, { + asyncDataParams: { + databaseId: application.id, + tableId: table.id, + viewId: view.id, + }, + }) + + expect(tableComponent.vm.views).toMatchObject([view]) + + // we're past views api call, so the table (with the error) and toolbar should be present + expect(tableComponent.find('.header__filter-link').exists()).toBe(true) + + expect(tableComponent.vm.error).toBeTruthy() + + expect(tableComponent.find('.placeholder__title').exists()).toBe(true) + expect(tableComponent.find('.placeholder__title').text()).toEqual( + rowsError.data.message + ) + expect(tableComponent.find('.placeholder__content').exists()).toBe(true) + + expect(tableComponent.find('.placeholder__content').text()).toEqual( + 'errorLayout.error' + ) + }) + async function givenATableInTheServerWithMultipleViews() { const table = mockServer.createTable() const { application } = await mockServer.createAppAndWorkspace(table) @@ -494,4 +602,83 @@ describe('View Tests', () => { tables.push(secondTable) return { application, tables, views } } + + async function givenATableWithError({ viewsError, fieldsError, rowsError }) { + const table = mockServer.createTable() + // we expect some endpoints to return errors + testApp.dontFailOnErrorResponses() + const { application } = + await mockServer.createAppAndWorkspaceWithMultipleTables([table]) + const viewId = 1 + + const rawGridView = { + id: viewId, + table_id: table.id, + name: `mock_view_${viewId}`, + order: 0, + type: 'grid', + table: { + id: table.id, + name: table.name, + order: 0, + database_id: application.id, + }, + filter_type: 'AND', + filters_disabled: false, + public: null, + row_identifier_type: 'id', + row_height_size: 'small', + filters: [], + sortings: [], + group_bys: [], + decorations: [], + } + + const rawFields = [ + { + name: 'Name', + type: 'text', + primary: true, + }, + { + name: 'Last name', + type: 'text', + }, + { + name: 'Notes', + type: 'long_text', + }, + { + name: 'Active', + type: 'boolean', + }, + ] + const rawRows = [ + { + id: 1, + order: 0, + field_1: 'name', + field_2: 'last_name', + field_3: 'notes', + field_4: false, + }, + ] + + mockServer.mock + .onGet(`/database/views/table/${table.id}/`) + .replyOnce( + viewsError?.statusCode || 200, + viewsError?.data || [rawGridView] + ) + + mockServer.mock + .onGet(`/database/fields/table/${table.id}/`) + .replyOnce(fieldsError?.statusCode || 200, fieldsError?.data || rawFields) + + mockServer.mock + .onGet(`database/views/grid/${rawGridView.id}/`) + .replyOnce(rowsError?.statusCode || 200, rowsError?.data || rawRows) + + return { application, table, view: rawGridView } + } }) diff --git a/web-frontend/test/unit/database/webhooks/webhookForm.spec.js b/web-frontend/test/unit/database/webhooks/webhookForm.spec.js index 3db5ebdf3..82b0f70ad 100644 --- a/web-frontend/test/unit/database/webhooks/webhookForm.spec.js +++ b/web-frontend/test/unit/database/webhooks/webhookForm.spec.js @@ -18,6 +18,7 @@ describe('Webhook form Input Tests', () => { table: { id: 1 }, database: { id: 2, workspace: { id: 3 } }, fields: [{ id: 1, name: 'Name', type: 'text' }], + views: [], }, }) }