diff --git a/apps/dashboards/graphql/types.py b/apps/dashboards/graphql/types.py index 0cd2736..2857fbd 100644 --- a/apps/dashboards/graphql/types.py +++ b/apps/dashboards/graphql/types.py @@ -1,5 +1,6 @@ import strawberry import strawberry_django +from asgiref.sync import sync_to_async from apps.dashboards.models import CapacityAndResource, DashboardPage, ExternalDashboard @@ -37,6 +38,7 @@ class CapacityAndResourceType: created_by_id: strawberry.ID @strawberry.field + @sync_to_async def dashboards_count(self) -> int: return self.dashboards.count() # type: ignore[reportAttributeAccessIssue] diff --git a/apps/dashboards/serializers.py b/apps/dashboards/serializers.py index 5a1a838..b80607f 100644 --- a/apps/dashboards/serializers.py +++ b/apps/dashboards/serializers.py @@ -36,11 +36,22 @@ class Meta: @typing.override def validate(self, data: dict) -> dict: # type: ignore[reportIncompatibleMethodOverride] + instance = self.instance + is_active = data.get("is_active", instance.is_active if instance else True) + show_on_home = data.get("show_on_home", instance.show_on_home if instance else False) + + if show_on_home and not is_active: + raise serializers.ValidationError( + { + "non_field_errors": "A dashboard must be active to be shown on the home page.", + }, + ) + # Home dashboard limit validation - if data.get("show_on_home"): + if show_on_home: qs = ExternalDashboard.objects.filter(show_on_home=True) - if self.instance: - qs = qs.exclude(pk=self.instance.pk) + if instance: + qs = qs.exclude(pk=instance.pk) if qs.count() >= self.HOME_DASHBOARD_LIMIT: raise serializers.ValidationError( { @@ -51,7 +62,6 @@ def validate(self, data: dict) -> dict: # type: ignore[reportIncompatibleMethod ) # Capacity & Resource validation - instance = self.instance capacity_and_resource = data.get( "capacity_and_resource", getattr(instance, "capacity_and_resource", None), @@ -66,6 +76,7 @@ def validate(self, data: dict) -> dict: # type: ignore[reportIncompatibleMethod ), }, ) + return data @typing.override diff --git a/apps/dashboards/tests/mutations_test.py b/apps/dashboards/tests/mutations_test.py index d6d9cd9..cbca88e 100644 --- a/apps/dashboards/tests/mutations_test.py +++ b/apps/dashboards/tests/mutations_test.py @@ -171,6 +171,35 @@ def test_update_dashboard_wrong_page_for_capacity(self): assert resp["ok"] is False assert resp["errors"] is not None + def test_create_dashboard_show_on_home_requires_active(self): + self.force_login(self.staff) + content = self.query_check( + self.Mutation.CREATE_DASHBOARD, + variables={ + "data": { + "title": "Inactive Home Dashboard", + "url": "https://app.powerbi.com/embed/inactive", + "page": ExternalDashboard.Page.HOME.name, + "showOnHome": True, + "isActive": False, + }, + }, + ) + resp = content["data"]["createExternalDashboard"] + assert resp["ok"] is False + assert resp["errors"] is not None + + def test_update_dashboard_deactivate_while_show_on_home(self): + self.force_login(self.staff) + dashboard = ExternalDashboardFactory.create(is_active=True, show_on_home=True, created_by=self.staff) + content = self.query_check( + self.Mutation.UPDATE_DASHBOARD, + variables={"id": str(dashboard.pk), "data": {"isActive": False}}, + ) + resp = content["data"]["updateExternalDashboard"] + assert resp["ok"] is False + assert resp["errors"] is not None + def test_viewer_cannot_create(self): self.force_login(self.viewer) content = self.query_check(