Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions apps/dashboards/graphql/inputs.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,12 @@ class ExternalDashboardCreateInput:
is_active: bool = True


@strawberry.input
class ExternalDashboardOrderInput:
id: strawberry.ID
order: int


@strawberry.input
class ExternalDashboardUpdateInput:
title: str | None = strawberry.UNSET
Expand Down
32 changes: 31 additions & 1 deletion apps/dashboards/graphql/mutations.py
Original file line number Diff line number Diff line change
@@ -1,23 +1,41 @@
import strawberry
import strawberry_django
from asgiref.sync import sync_to_async
from django.db import transaction

from apps.dashboards.models import CapacityAndResource, ExternalDashboard
from apps.dashboards.serializers import CapacityAndResourceSerializer, ExternalDashboardSerializer
from main.graphql.context import Info
from main.graphql.permissions import IsStaffOrAbove
from utils.graphql.drf import MutationCustomErrorType
from utils.graphql.mutations import ModelMutation
from utils.graphql.types import MutationResponseType
from utils.graphql.types import CustomErrorType, MutationResponseType

from .inputs import (
CapacityAndResourceCreateInput,
CapacityAndResourceUpdateInput,
ExternalDashboardCreateInput,
ExternalDashboardOrderInput,
ExternalDashboardUpdateInput,
)
from .types import CapacityAndResourceType, ExternalDashboardType


@sync_to_async
def _bulk_update_external_dashboard_order(
order_by_id: dict[str, int],
) -> tuple[CustomErrorType | None, list[ExternalDashboard] | None]:
with transaction.atomic():
dashboards = list(ExternalDashboard.objects.filter(id__in=order_by_id))
if len(dashboards) != len(order_by_id):
return MutationCustomErrorType.generate_message("One or more dashboards were not found."), None
for dashboard in dashboards:
dashboard.order = order_by_id[str(dashboard.pk)]
ExternalDashboard.objects.bulk_update(dashboards, ["order"])
dashboards.sort(key=lambda dashboard: (dashboard.page, dashboard.order))
return None, dashboards
Comment on lines +35 to +36

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
dashboards.sort(key=lambda dashboard: (dashboard.page, dashboard.order))
return None, dashboards
return None, sorted(
dashboards,
key=lambda d: (d.page_id, d.order),
)



@strawberry.type
class Mutation:
@strawberry_django.mutation(permission_classes=[IsStaffOrAbove])
Expand Down Expand Up @@ -56,6 +74,18 @@ async def update_capacity_and_resource(
instance = await CapacityAndResource.objects.aget(id=id)
return await ModelMutation(CapacityAndResourceSerializer).handle_update_mutation(data, info, instance)

@strawberry_django.mutation(permission_classes=[IsStaffOrAbove])
async def bulk_update_external_dashboards(
self,
info: Info,
data: list[ExternalDashboardOrderInput],
) -> MutationResponseType[list[ExternalDashboardType]]:
order_by_id = {str(item.id): item.order for item in data}
errors, dashboards = await _bulk_update_external_dashboard_order(order_by_id)
if errors:
return MutationResponseType(ok=False, errors=errors)
return MutationResponseType(result=dashboards)

@strawberry_django.mutation(permission_classes=[IsStaffOrAbove])
async def add_dashboard_to_home(
self,
Expand Down
14 changes: 14 additions & 0 deletions schema.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,8 @@ type AppEnumCollectionUserRole {
label: String!
}

union BulkUpdateExternalDashboardsPayload = ExternalDashboardTypeListMutationResponseType | OperationInfo

"""A Capacity & Resources entry that groups multiple ExternalDashboards."""
input CapacityAndResourceCreateInput {
title: String!
Expand Down Expand Up @@ -408,6 +410,11 @@ input ExternalDashboardOrder @oneOf {
title: Ordering
}

input ExternalDashboardOrderInput {
id: ID!
order: Int!
}

"""Power BI / iframe dashboards embedded across site pages via CMS."""
type ExternalDashboardType {
id: ID!
Expand All @@ -428,6 +435,12 @@ type ExternalDashboardType {
pageDisplay: String!
}

type ExternalDashboardTypeListMutationResponseType {
ok: Boolean!
errors: CustomErrorType
result: [ExternalDashboardType!]
}

type ExternalDashboardTypeMutationResponseType {
ok: Boolean!
errors: CustomErrorType
Expand Down Expand Up @@ -714,6 +727,7 @@ type Mutation {
updateExternalDashboard(id: ID!, data: ExternalDashboardUpdateInput!): UpdateExternalDashboardPayload!
createCapacityAndResource(data: CapacityAndResourceCreateInput!): CreateCapacityAndResourcePayload!
updateCapacityAndResource(id: ID!, data: CapacityAndResourceUpdateInput!): UpdateCapacityAndResourcePayload!
bulkUpdateExternalDashboards(data: [ExternalDashboardOrderInput!]!): BulkUpdateExternalDashboardsPayload!
addDashboardToHome(id: ID!): AddDashboardToHomePayload!
removeDashboardFromHome(id: ID!): RemoveDashboardFromHomePayload!
deleteExternalDashboard(id: ID!): DeleteExternalDashboardPayload!
Expand Down
Loading