mirror of
https://gitlab.com/bramw/baserow.git
synced 2025-04-07 14:25:37 +00:00
Sort by sort reference in grouped aggregate service
This commit is contained in:
parent
d664710948
commit
1ba677a437
9 changed files with 470 additions and 196 deletions
enterprise
backend
src/baserow_enterprise
api/integrations/local_baserow
integrations/local_baserow
migrations
services
tests/baserow_enterprise_tests
api/dashboard
integrations/local_baserow/service_types
web-frontend/modules/baserow_enterprise/dashboard/components/data_source
|
@ -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")
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
from typing import TYPE_CHECKING, Type
|
||||
|
||||
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
|
||||
|
||||
|
@ -12,23 +10,20 @@ from baserow.contrib.integrations.local_baserow.integration_types import (
|
|||
)
|
||||
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,
|
||||
|
@ -37,20 +32,18 @@ from baserow_enterprise.integrations.registries import grouped_aggregation_regis
|
|||
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 +55,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 +70,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 +88,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 +112,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,
|
||||
|
@ -224,48 +218,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 +279,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 +319,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)
|
||||
|
@ -382,16 +375,6 @@ class LocalBaserowGroupedAggregateRowsUserServiceType(
|
|||
**kwargs,
|
||||
)
|
||||
|
||||
def get_dispatch_sorts(
|
||||
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
|
||||
|
||||
def dispatch_data(
|
||||
self,
|
||||
service: LocalBaserowGroupedAggregateRows,
|
||||
|
@ -412,24 +395,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:
|
||||
|
@ -482,6 +447,54 @@ 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,
|
||||
)
|
||||
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 +508,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)
|
||||
|
|
|
@ -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"),
|
||||
},
|
||||
),
|
||||
]
|
|
@ -8,3 +8,9 @@ class ServiceAggregationSeriesDict(TypedDict):
|
|||
|
||||
class ServiceAggregationGroupByDict(TypedDict):
|
||||
field_id: int
|
||||
|
||||
|
||||
class ServiceAggregationSortByDict(TypedDict):
|
||||
sort_on: str
|
||||
reference: str
|
||||
direction: str
|
||||
|
|
|
@ -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,
|
||||
|
@ -74,13 +79,12 @@ def test_grouped_aggregate_rows_get_dashboard_data_sources(
|
|||
"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 +142,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 +174,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 +221,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(
|
||||
|
|
|
@ -18,6 +18,7 @@ from baserow_enterprise.integrations.local_baserow.models import (
|
|||
LocalBaserowGroupedAggregateRows,
|
||||
LocalBaserowTableServiceAggregationGroupBy,
|
||||
LocalBaserowTableServiceAggregationSeries,
|
||||
LocalBaserowTableServiceAggregationSortBy,
|
||||
)
|
||||
|
||||
|
||||
|
@ -317,8 +318,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 +331,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 +359,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 +372,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 +398,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 +411,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)
|
||||
|
||||
|
@ -765,8 +778,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 +791,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 +825,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 +838,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 +870,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 +883,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 +912,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 +940,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
|
||||
|
@ -1548,11 +1577,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 +1719,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(
|
||||
|
@ -1875,8 +1920,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 +2046,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 +2148,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 +2187,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 +2229,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 +2403,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 +2494,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,8 +2585,12 @@ 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(
|
||||
|
|
|
@ -4,30 +4,30 @@
|
|||
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"
|
||||
:active-index="orderDirectionIndex"
|
||||
:segments="orderDirectionOptions"
|
||||
:initial-active-index="orderDirectionIndex"
|
||||
@update:activeIndex="orderByChangedByUser"
|
||||
></SegmentControl>
|
||||
</FormSection>
|
||||
|
@ -46,7 +46,7 @@ const includesIfSet = (array) => (value) => {
|
|||
export default {
|
||||
name: 'AggregationSortByForm',
|
||||
props: {
|
||||
allowedSortFields: {
|
||||
allowedSortReferences: {
|
||||
type: Array,
|
||||
required: true,
|
||||
},
|
||||
|
@ -60,12 +60,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 +76,13 @@ 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
|
||||
)
|
||||
} else {
|
||||
this.sortByField = null
|
||||
this.orderByIndex = 0
|
||||
this.sortReference = null
|
||||
this.orderDirectionIndex = 0
|
||||
}
|
||||
},
|
||||
immediate: true,
|
||||
|
@ -94,27 +94,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) {
|
||||
|
|
|
@ -101,8 +101,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,14 +161,14 @@ 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,
|
||||
|
@ -201,6 +201,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,17 +217,35 @@ 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)
|
||||
.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.map(
|
||||
(item) => {
|
||||
const field =
|
||||
item.field_id === null
|
||||
? this.primaryTableField
|
||||
: this.getTableFieldById(item.field_id)
|
||||
return {
|
||||
sort_on: 'GROUP_BY',
|
||||
reference: `field_${field.id}`,
|
||||
field,
|
||||
name: field.name,
|
||||
}
|
||||
}
|
||||
)
|
||||
const groupByFieldIds = this.values.aggregation_group_bys.map(
|
||||
(item) => item.field_id
|
||||
)
|
||||
const allowedFieldIds = seriesFieldIds.concat(groupByFieldIds)
|
||||
return this.tableFields.filter((item) => {
|
||||
return allowedFieldIds.includes(item.id)
|
||||
})
|
||||
return seriesSortReferences.concat(groupBySortReferences)
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
|
@ -280,22 +301,44 @@ export default {
|
|||
}
|
||||
},
|
||||
methods: {
|
||||
getTableFieldById(fieldId) {
|
||||
return this.tableFields.find((tableField) => {
|
||||
return tableField.id === fieldId
|
||||
})
|
||||
},
|
||||
getAggregationName(aggregationType) {
|
||||
const aggType = this.$registry.get('groupedAggregation', aggregationType)
|
||||
return aggType.getName()
|
||||
},
|
||||
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.values.aggregation_sorts = []
|
||||
this.v$.values.table_id.$touch()
|
||||
},
|
||||
addSeries() {
|
||||
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) {
|
||||
this.values.aggregation_series.splice(index, 1)
|
||||
async deleteSeries(index) {
|
||||
this.setEmitValues(false)
|
||||
const updatedAggregationSeries = this.values.aggregation_series
|
||||
updatedAggregationSeries.splice(index, 1)
|
||||
this.$emit('values-changed', {
|
||||
aggregation_series: updatedAggregationSeries,
|
||||
})
|
||||
await this.$nextTick()
|
||||
this.setEmitValues(true)
|
||||
},
|
||||
onAggregationSeriesUpdated(index, aggregationSeriesValues) {
|
||||
const updatedAggregationSeries = this.values.aggregation_series
|
||||
|
@ -315,10 +358,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,
|
||||
})
|
||||
},
|
||||
},
|
||||
|
|
Loading…
Add table
Reference in a new issue