mirror of
https://github.com/BillyOutlast/posthog.git
synced 2026-02-04 03:01:23 +01:00
fix(customers): Filter dashboards by tag (#38400)
This commit is contained in:
committed by
GitHub
parent
4687d1f392
commit
dae7d925c4
@@ -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,
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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 || '',
|
||||
|
||||
Reference in New Issue
Block a user