fix(customers): Filter dashboards by tag (#38400)

This commit is contained in:
Arthur Moreira de Deus
2025-09-23 05:28:15 -07:00
committed by GitHub
parent 4687d1f392
commit dae7d925c4
4 changed files with 52 additions and 19 deletions

View File

@@ -4,7 +4,7 @@ from contextlib import nullcontext
from typing import Any, Optional, cast
from django.conf import settings
from django.db.models import Prefetch
from django.db.models import Prefetch, QuerySet
from django.dispatch import receiver
from django.http import StreamingHttpResponse
from django.utils.timezone import now
@@ -605,6 +605,14 @@ class DashboardsViewSet(
def get_serializer_class(self) -> type[BaseSerializer]:
return DashboardBasicSerializer if self.action == "list" else DashboardSerializer
def filter_queryset(self, queryset: QuerySet) -> QuerySet:
queryset = super().filter_queryset(queryset)
tags = self.request.query_params.getlist("tags")
if not tags:
return queryset
return queryset.filter(tagged_items__tag__name__in=tags).distinct()
@tracer.start_as_current_span("DashboardViewSet.dangerously_get_queryset")
def dangerously_get_queryset(self):
# Dashboards are retrieved under /environments/ because they include team-specific query results,

View File

@@ -95,15 +95,16 @@ class TaggedItemViewSetMixin(viewsets.GenericViewSet):
return is_licensed_for_tagged_items(self.request.user) # type: ignore
def prefetch_tagged_items_if_available(self, queryset: QuerySet) -> QuerySet:
if self.is_licensed():
return queryset.prefetch_related(
Prefetch(
"tagged_items",
queryset=TaggedItem.objects.select_related("tag"),
to_attr="prefetched_tags",
)
if not self.is_licensed():
return queryset
return queryset.prefetch_related(
Prefetch(
"tagged_items",
queryset=TaggedItem.objects.select_related("tag"),
to_attr="prefetched_tags",
)
return queryset
)
def filter_queryset(self, queryset: QuerySet) -> QuerySet:
queryset = super().filter_queryset(queryset)

View File

@@ -80,7 +80,8 @@ class TestDashboard(APIBaseTest, QueryMatchingTest):
for dashboard_name in dashboard_names:
self.dashboard_api.create_dashboard({"name": dashboard_name})
response_data = self.dashboard_api.list_dashboards()
with self.assertNumQueries(14):
response_data = self.dashboard_api.list_dashboards()
self.assertEqual(
[dashboard["name"] for dashboard in response_data["results"]],
dashboard_names,
@@ -113,6 +114,34 @@ class TestDashboard(APIBaseTest, QueryMatchingTest):
{dashboard_a_id, dashboard_b_id},
)
def test_list_filter_by_tag(self):
self.dashboard_api.create_dashboard({"name": "tagged", "tags": ["tag"]})
self.dashboard_api.create_dashboard({"name": "also tagged", "tags": ["tag2"]})
self.dashboard_api.create_dashboard({"name": "not tagged"})
with self.assertNumQueries(14):
response = self.dashboard_api.list_dashboards(
expected_status=status.HTTP_200_OK, query_params={"tags": ["tag"]}
)
assert response["count"] == 1
assert response["results"][0]["name"] == "tagged"
def test_list_filter_by_multiple_tags(self):
self.dashboard_api.create_dashboard({"name": "tagged", "tags": ["tag"]})
self.dashboard_api.create_dashboard({"name": "also tagged", "tags": ["tag2"]})
self.dashboard_api.create_dashboard({"name": "not tagged"})
self.dashboard_api.create_dashboard({"name": "not with the right tag", "tags": ["wrong-tag"]})
with self.assertNumQueries(14):
response = self.dashboard_api.list_dashboards(
expected_status=status.HTTP_200_OK, query_params={"tags": ["tag", "tag2"]}
)
assert response["count"] == 2
dashboard_names = {dashboard["name"] for dashboard in response["results"]}
assert dashboard_names == {"tagged", "also tagged"}
@snapshot_postgres_queries
def test_retrieve_dashboard(self):
dashboard = Dashboard.objects.create(team=self.team, name="private dashboard", created_by=self.user)

View File

@@ -42,17 +42,12 @@ export const customerAnalyticsSceneLogic = kea<customerAnalyticsSceneLogicType>(
[] as CustomerDashboard[],
{
loadCustomerDashboards: async () => {
// Fetch all dashboards and filter for those tagged with "customer-analytics"
const response = await api.get(`api/environments/${values.currentTeamId}/dashboards/`)
const response = await api.get(
`api/environments/${values.currentTeamId}/dashboards/?tags=customer-analytics`
)
const allDashboards: DashboardType[] = response.results || []
// Filter dashboards that have "customer-analytics" tag
const customerDashboards = allDashboards.filter(
(dashboard) => dashboard.tags && dashboard.tags.includes('customer-analytics')
)
// Convert to CustomerDashboard format
return customerDashboards.map((dashboard) => ({
return allDashboards.map((dashboard) => ({
id: dashboard.id,
name: dashboard.name,
description: dashboard.description || '',