From 1a0368bed16071fcb85d6eeb41a0fccdc5da04ea Mon Sep 17 00:00:00 2001 From: Peter Evans <peter@baserow.io> Date: Wed, 5 Mar 2025 09:00:44 +0000 Subject: [PATCH] Prevent aggregate rows services from using the new distribution aggregation type. --- .../local_baserow/service_types.py | 26 ++++++++++++++----- .../test_aggregate_rows_service_type.py | 26 +++++++++++++++++++ .../AggregateRowsDataSourceForm.vue | 7 +++++ .../LocalBaserowAggregateRowsForm.vue | 7 +++++ .../modules/integrations/serviceTypes.js | 9 +++++++ 5 files changed, 69 insertions(+), 6 deletions(-) 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 45ce90bde..931bdacfe 100644 --- a/backend/src/baserow/contrib/integrations/local_baserow/service_types.py +++ b/backend/src/baserow/contrib/integrations/local_baserow/service_types.py @@ -62,6 +62,9 @@ from baserow.contrib.database.views.exceptions import ( ViewDoesNotExist, ) 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, ) @@ -1240,6 +1243,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 @@ -1378,6 +1385,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 ( @@ -1407,12 +1427,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/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/web-frontend/modules/dashboard/components/data_source/AggregateRowsDataSourceForm.vue b/web-frontend/modules/dashboard/components/data_source/AggregateRowsDataSourceForm.vue index a94b6d1f3..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> @@ -224,6 +227,10 @@ export default { aggregationTypeNames() { return this.viewAggregationTypes.map((aggType) => aggType.getType()) }, + unsupportedAggregationTypes() { + return this.$registry.get('service', 'local_baserow_aggregate_rows') + .unsupportedAggregationTypes + }, }, watch: { dataSource: { 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/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