Skip to content

Commit 48d2254

Browse files
committed
add usecase dashboard related model and schema
1 parent c149d66 commit 48d2254

File tree

5 files changed

+251
-0
lines changed

5 files changed

+251
-0
lines changed

api/models/UseCaseDashboard.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
from django.db import models
2+
3+
4+
class UseCaseDashboard(models.Model):
5+
"""
6+
Model to store dashboard information for usecases.
7+
Each usecase can have multiple dashboards with names and links.
8+
"""
9+
10+
id = models.AutoField(primary_key=True)
11+
name = models.CharField(max_length=200, blank=False, null=False)
12+
link = models.URLField(blank=False, null=False)
13+
created = models.DateTimeField(auto_now_add=True)
14+
modified = models.DateTimeField(auto_now=True)
15+
usecase = models.ForeignKey(
16+
"api.UseCase", on_delete=models.CASCADE, related_name="dashboards"
17+
)
18+
19+
class Meta:
20+
db_table = "usecase_dashboard"
21+
ordering = ["created"]
22+
23+
def __str__(self):
24+
return f"{self.name} - {self.usecase.title if self.usecase else 'No Usecase'}"

api/models/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,5 +19,6 @@
1919
from api.models.Sector import Sector
2020
from api.models.SerializableJSONField import SerializableJSONField
2121
from api.models.UseCase import UseCase
22+
from api.models.UseCaseDashboard import UseCaseDashboard
2223
from api.models.UseCaseMetadata import UseCaseMetadata
2324
from api.models.UseCaseOrganizationRelationship import UseCaseOrganizationRelationship

api/schema/schema.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import api.schema.sector_schema
2020
import api.schema.stats_schema
2121
import api.schema.tags_schema
22+
import api.schema.usecase_dashboard_schema
2223
import api.schema.usecase_schema
2324
import api.schema.user_schema
2425
from api.models import Resource, Tag
@@ -53,6 +54,7 @@ def tags(self, info: Info) -> List[TypeTag]:
5354
"Query",
5455
(
5556
DefaultQuery,
57+
api.schema.usecase_dashboard_schema.Query,
5658
api.schema.dataset_schema.Query,
5759
api.schema.resource_schema.Query,
5860
api.schema.access_model_schema.Query,
@@ -72,6 +74,7 @@ def tags(self, info: Info) -> List[TypeTag]:
7274
Mutation = merge_types(
7375
"Mutation",
7476
(
77+
api.schema.usecase_dashboard_schema.Mutation,
7578
api.schema.dataset_schema.Mutation,
7679
api.schema.resource_schema.Mutation,
7780
api.schema.access_model_schema.Mutation,
Lines changed: 183 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
1+
"""Schema definitions for usecase dashboards."""
2+
3+
from typing import List, Optional
4+
5+
import strawberry
6+
import strawberry_django
7+
from strawberry.types import Info
8+
from strawberry_django.pagination import OffsetPaginationInput
9+
10+
from api.models import UseCase, UseCaseDashboard
11+
from api.schema.base_mutation import BaseMutation
12+
from api.types.type_usecase_dashboard import (
13+
TypeUseCaseDashboard,
14+
UseCaseDashboardFilter,
15+
UseCaseDashboardOrder,
16+
)
17+
from api.utils.graphql_telemetry import trace_resolver
18+
from authorization.permissions import IsAuthenticated
19+
20+
21+
@strawberry.input
22+
class UseCaseDashboardInput:
23+
"""Input type for usecase dashboard creation."""
24+
25+
name: str
26+
link: str
27+
28+
29+
@strawberry.input
30+
class AddUseCaseDashboardsInput:
31+
"""Input for adding multiple dashboards to a usecase."""
32+
33+
usecase_id: int
34+
dashboards: List[UseCaseDashboardInput]
35+
36+
37+
@strawberry.type
38+
class UseCaseDashboardMutationResponse:
39+
"""Response type for usecase dashboard mutations."""
40+
41+
dashboards: Optional[List[TypeUseCaseDashboard]] = None
42+
success: bool = False
43+
message: str = ""
44+
45+
46+
class Mutation:
47+
"""UseCaseDashboard mutations."""
48+
49+
@BaseMutation.mutation(
50+
permission_classes=[IsAuthenticated],
51+
trace_name="add_usecase_dashboards",
52+
trace_attributes={"component": "usecase_dashboard"},
53+
track_activity={
54+
"verb": "created",
55+
"get_data": lambda result, **kwargs: {
56+
"usecase_id": str(kwargs.get("input").usecase_id),
57+
"dashboard_count": len(result),
58+
},
59+
},
60+
)
61+
def add_usecase_dashboards(
62+
self, info: Info, input: AddUseCaseDashboardsInput
63+
) -> UseCaseDashboardMutationResponse:
64+
"""Add multiple dashboards to a usecase."""
65+
try:
66+
# Check if usecase exists
67+
usecase = UseCase.objects.get(id=input.usecase_id)
68+
69+
# Create dashboards
70+
created_dashboards = []
71+
for dashboard_input in input.dashboards:
72+
dashboard = UseCaseDashboard.objects.create(
73+
name=dashboard_input.name,
74+
link=dashboard_input.link,
75+
usecase=usecase,
76+
)
77+
created_dashboards.append(dashboard)
78+
79+
return UseCaseDashboardMutationResponse(
80+
dashboards=[
81+
TypeUseCaseDashboard.from_django(d) for d in created_dashboards
82+
],
83+
success=True,
84+
message=f"Added {len(created_dashboards)} dashboards to usecase",
85+
)
86+
except UseCase.DoesNotExist:
87+
raise Exception(f"Usecase with ID {input.usecase_id} does not exist")
88+
except Exception as e:
89+
raise Exception(f"Failed to add dashboards: {str(e)}")
90+
91+
@BaseMutation.mutation(
92+
permission_classes=[IsAuthenticated],
93+
trace_name="delete_usecase_dashboard",
94+
trace_attributes={"component": "usecase_dashboard"},
95+
track_activity={
96+
"verb": "deleted",
97+
"get_data": lambda result, **kwargs: {
98+
"dashboard_id": str(kwargs.get("id")),
99+
},
100+
},
101+
)
102+
def delete_usecase_dashboard(
103+
self, info: Info, id: int
104+
) -> UseCaseDashboardMutationResponse:
105+
"""Delete a usecase dashboard."""
106+
try:
107+
dashboard = UseCaseDashboard.objects.get(id=id)
108+
dashboard.delete()
109+
return UseCaseDashboardMutationResponse(
110+
success=True,
111+
message=f"Dashboard with ID {id} deleted successfully",
112+
)
113+
except UseCaseDashboard.DoesNotExist:
114+
raise Exception(f"Dashboard with ID {id} does not exist")
115+
except Exception as e:
116+
raise Exception(f"Failed to delete dashboard: {str(e)}")
117+
118+
119+
class Query:
120+
"""UseCaseDashboard queries."""
121+
122+
@strawberry_django.field(
123+
filters=UseCaseDashboardFilter,
124+
pagination=True,
125+
order=UseCaseDashboardOrder,
126+
)
127+
@trace_resolver(
128+
name="get_usecase_dashboards_all", attributes={"component": "usecase_dashboard"}
129+
)
130+
def usecase_dashboards_all(
131+
self,
132+
info: Info,
133+
filters: UseCaseDashboardFilter = strawberry.UNSET,
134+
pagination: OffsetPaginationInput = strawberry.UNSET,
135+
order: UseCaseDashboardOrder = strawberry.UNSET,
136+
) -> list[TypeUseCaseDashboard]:
137+
"""Get all usecase dashboards."""
138+
queryset = UseCaseDashboard.objects.all()
139+
140+
if filters is not strawberry.UNSET:
141+
queryset = strawberry_django.filters.apply(filters, queryset, info)
142+
143+
if order is not strawberry.UNSET:
144+
queryset = strawberry_django.ordering.apply(order, queryset, info)
145+
146+
dashboard_instances = list(queryset)
147+
148+
if pagination is not strawberry.UNSET:
149+
offset = pagination.offset if pagination.offset is not None else 0
150+
limit = pagination.limit
151+
152+
if limit is not None:
153+
dashboard_instances = dashboard_instances[offset : offset + limit]
154+
else:
155+
dashboard_instances = dashboard_instances[offset:]
156+
157+
return [
158+
TypeUseCaseDashboard.from_django(instance)
159+
for instance in dashboard_instances
160+
]
161+
162+
@strawberry_django.field
163+
@trace_resolver(
164+
name="get_usecase_dashboards", attributes={"component": "usecase_dashboard"}
165+
)
166+
def usecase_dashboards(
167+
self, info: Info, usecase_id: int
168+
) -> list[TypeUseCaseDashboard]:
169+
"""Get dashboards for a specific usecase."""
170+
try:
171+
# Check if usecase exists
172+
usecase = UseCase.objects.get(id=usecase_id)
173+
174+
# Get dashboards for the usecase
175+
dashboards = UseCaseDashboard.objects.filter(usecase=usecase)
176+
177+
return [
178+
TypeUseCaseDashboard.from_django(dashboard) for dashboard in dashboards
179+
]
180+
except UseCase.DoesNotExist:
181+
raise Exception(f"Usecase with ID {usecase_id} does not exist")
182+
except Exception as e:
183+
raise Exception(f"Failed to get usecase dashboards: {str(e)}")
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
"""Type definitions for UseCaseDashboard model."""
2+
3+
from typing import Optional
4+
5+
import strawberry
6+
import strawberry_django
7+
from strawberry import auto
8+
from strawberry_django.filters import FilterLookup
9+
10+
from api.models import UseCaseDashboard
11+
from api.types.base_type import BaseType
12+
13+
14+
@strawberry_django.type(UseCaseDashboard)
15+
class TypeUseCaseDashboard(BaseType):
16+
"""Type for UseCaseDashboard model."""
17+
18+
id: auto
19+
name: auto
20+
link: auto
21+
created: auto
22+
modified: auto
23+
usecase_id: auto
24+
25+
26+
@strawberry.input
27+
class UseCaseDashboardFilter:
28+
"""Filter for UseCaseDashboard queries."""
29+
30+
id: Optional[FilterLookup[int]] = strawberry.UNSET
31+
name: Optional[FilterLookup[str]] = strawberry.UNSET
32+
usecase_id: Optional[FilterLookup[int]] = strawberry.UNSET
33+
34+
35+
@strawberry.input
36+
class UseCaseDashboardOrder:
37+
"""Order for UseCaseDashboard queries."""
38+
39+
name: Optional[str] = strawberry.UNSET
40+
created: Optional[str] = strawberry.UNSET

0 commit comments

Comments
 (0)