1
0
Fork 0
mirror of https://gitlab.com/bramw/baserow.git synced 2025-04-14 00:59:06 +00:00

Multiple collaborators field group by support

This commit is contained in:
Bram Wiepjes 2025-03-10 17:04:02 +00:00
parent 922a77d88f
commit cc2d50072a
5 changed files with 206 additions and 2 deletions
backend
src/baserow/contrib/database/fields
tests/baserow/contrib/database
changelog/entries/unreleased/feature
web-frontend/modules/database

View file

@ -6008,7 +6008,10 @@ class LookupFieldType(FormulaFieldType):
class MultipleCollaboratorsFieldType( class MultipleCollaboratorsFieldType(
CollationSortMixin, ManyToManyFieldTypeSerializeToInputValueMixin, FieldType CollationSortMixin,
ManyToManyFieldTypeSerializeToInputValueMixin,
ManyToManyGroupByMixin,
FieldType,
): ):
type = "multiple_collaborators" type = "multiple_collaborators"
model_class = MultipleCollaboratorsField model_class = MultipleCollaboratorsField
@ -6024,6 +6027,7 @@ class MultipleCollaboratorsFieldType(
"notify_user_when_added": serializers.BooleanField(required=False), "notify_user_when_added": serializers.BooleanField(required=False),
} }
is_many_to_many_field = True is_many_to_many_field = True
_can_group_by = True
def get_serializer_field(self, instance, **kwargs): def get_serializer_field(self, instance, **kwargs):
required = kwargs.pop("required", False) required = kwargs.pop("required", False)

View file

@ -65,7 +65,8 @@ def test_serialize_group_by_metadata(api_client, data_fixture):
@pytest.mark.django_db @pytest.mark.django_db
def test_serialize_group_by_metadata_on_all_fields_in_interesting_table(data_fixture): 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() model = table.get_model()
queryset = model.objects.all() queryset = model.objects.all()
rows = list(queryset) rows = list(queryset)
@ -284,6 +285,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": [], "count": 1},
{"field_decimal_link_row": [1, 2, 3], "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(): for key, actual_value in actual_result_per_field_name.items():
expected_value = expected_result.get(key, None) expected_value = expected_result.get(key, None)

View file

@ -5,9 +5,11 @@ from django.apps.registry import apps
from django.contrib.auth import get_user_model from django.contrib.auth import get_user_model
from django.db import connection from django.db import connection
from django.test.utils import CaptureQueriesContext from django.test.utils import CaptureQueriesContext
from django.urls import reverse
import pytest import pytest
from faker import Faker from faker import Faker
from pytest_unordered import unordered
from baserow.contrib.database.fields.field_types import MultipleCollaboratorsFieldType from baserow.contrib.database.fields.field_types import MultipleCollaboratorsFieldType
from baserow.contrib.database.fields.handler import FieldHandler from baserow.contrib.database.fields.handler import FieldHandler
@ -937,3 +939,164 @@ def test_multiple_collaborators_formula_field_cache_users_query(data_fixture):
export_row(row) export_row(row)
assert len(queries_for_all_others.captured_queries) == 0 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,
},
]
),
}

View file

@ -0,0 +1,7 @@
{
"type": "feature",
"message": "Multiple collaborator field group by support.",
"issue_number": 3447,
"bullet_points": [],
"created_at": "2025-02-25"
}

View file

@ -4335,6 +4335,27 @@ export class MultipleCollaboratorsFieldType extends FieldType {
canBeReferencedByFormulaField() { canBeReferencedByFormulaField() {
return true 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 { export class UUIDFieldType extends FieldType {