Skip to content

Commit bda3677

Browse files
authored
Merge pull request #208 from mapswipe/feat/delete-assets-bulk
2 parents 47ff5e5 + b593148 commit bda3677

File tree

5 files changed

+86
-9
lines changed

5 files changed

+86
-9
lines changed

apps/project/graphql/mutations.py

Lines changed: 46 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
import strawberry
22
import strawberry_django
3+
from django.utils.translation import gettext
34
from strawberry_django.permissions import IsAuthenticated
45

5-
from apps.project.models import Organization, Project
6+
from apps.common.models import AssetTypeEnum
7+
from apps.project.models import Organization, Project, ProjectAsset, ProjectAssetInputTypeEnum
68
from apps.project.serializers import (
79
OrganizationSerializer,
810
ProcessedProjectUpdateSerializer,
@@ -13,7 +15,7 @@
1315
)
1416
from main.graphql.context import Info
1517
from utils.graphql.mutations import ModelMutation
16-
from utils.graphql.types import MutationResponseType
18+
from utils.graphql.types import CustomErrorType, MutationResponseType
1719

1820
from .inputs.inputs import (
1921
OrganizationCreateInput,
@@ -24,7 +26,7 @@
2426
ProjectStatusUpdateInput,
2527
ProjectUpdateInput,
2628
)
27-
from .types.types import OrganizationType, ProjectAssetType, ProjectType
29+
from .types.types import OrganizationType, ProjectAssetsDeleteType, ProjectAssetType, ProjectType
2830

2931

3032
@strawberry.type
@@ -90,3 +92,44 @@ async def update_project_status(
9092
) -> MutationResponseType[ProjectType]:
9193
project = await Project.objects.aget(pk=pk)
9294
return await ModelMutation(ProjectStatusUpdateSerializer).handle_update_mutation(data, info, project)
95+
96+
@strawberry_django.mutation(extensions=[IsAuthenticated()])
97+
async def delete_project_assets(
98+
self,
99+
info: Info,
100+
project_id: strawberry.ID,
101+
asset_input_type: list[ProjectAssetInputTypeEnum],
102+
) -> MutationResponseType[ProjectAssetsDeleteType]:
103+
project = await Project.objects.aget(pk=project_id)
104+
105+
if project.status_enum not in [Project.Status.DRAFT, Project.Status.PROCESSING_FAILED]:
106+
return MutationResponseType(
107+
ok=False,
108+
errors=CustomErrorType(
109+
{
110+
"array_errors": None,
111+
"client_id": project.client_id,
112+
"field": "nonFieldErrors",
113+
"messages": gettext("Cannot delete assets of project with status %s") % project.status_enum.label,
114+
},
115+
),
116+
result=None,
117+
)
118+
119+
deleted_count = await (
120+
ProjectAsset.usable_objects()
121+
.filter(
122+
project_id=project_id,
123+
type=AssetTypeEnum.INPUT,
124+
input_type__in=asset_input_type,
125+
)
126+
.aupdate(marked_as_deleted=True)
127+
)
128+
129+
return MutationResponseType(
130+
ok=True,
131+
errors=None,
132+
result=ProjectAssetsDeleteType(
133+
count=deleted_count,
134+
),
135+
)

apps/project/graphql/queries.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
from apps.project.custom_options import get_custom_options
99
from apps.project.graphql.inputs.inputs import ProjectNameInput
10-
from apps.project.models import Organization, Project, ProjectTypeEnum
10+
from apps.project.models import Organization, Project, ProjectAsset, ProjectTypeEnum
1111
from utils.geo.raster_tile_server.config import RasterConfig, RasterTileServerNameEnum, RasterTileServerNameEnumWithoutCustom
1212
from utils.geo.vector_tile_server.config import VectorConfig, VectorTileServerNameEnum, VectorTileServerNameEnumWithoutCustom
1313

@@ -88,11 +88,19 @@ def default_custom_options(self, project_type: ProjectTypeEnum) -> list[CustomOp
8888
project_asset: ProjectAssetType = strawberry_django.field(extensions=[IsAuthenticated()])
8989

9090
# --- Paginated
91-
project_assets: OffsetPaginated[ProjectAssetType] = strawberry_django.offset_paginated(
91+
@strawberry_django.offset_paginated(
92+
OffsetPaginated[ProjectAssetType],
9293
order=ProjectAssetOrder,
9394
filters=ProjectAssetFilter,
9495
extensions=[IsAuthenticated()],
9596
)
97+
def project_assets(
98+
self,
99+
include_all: bool = False,
100+
) -> QuerySet[ProjectAsset]:
101+
if include_all:
102+
return ProjectAsset.objects.all()
103+
return ProjectAsset.usable_objects()
96104

97105
organization: OrganizationType = strawberry_django.field(extensions=[IsAuthenticated()])
98106
public_organization: OrganizationType = strawberry_django.field()

apps/project/graphql/types/types.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,11 @@ async def export_moderate_to_high_agreement_yes_maybe_geometries(
142142
return await info.context.dl.project.export.moderate_to_high_agreement_yes_maybe_geometries.load(project.pk)
143143

144144

145+
@strawberry.type
146+
class ProjectAssetsDeleteType:
147+
count: int
148+
149+
145150
@strawberry_django.type(Project)
146151
class ProjectType(UserResourceTypeMixin, ProjectExportAssetTypeMixin, FirebasePushResourceTypeMixin):
147152
id: strawberry.ID

apps/tutorial/graphql/queries.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
from strawberry_django.pagination import OffsetPaginated
55
from strawberry_django.permissions import IsAuthenticated
66

7-
from apps.tutorial.models import Tutorial
7+
from apps.tutorial.models import Tutorial, TutorialAsset
88

99
from .filters import TutorialAssetFilter, TutorialFilter
1010
from .orders import TutorialAssetOrder, TutorialOrder
@@ -35,8 +35,16 @@ def tutorials(
3535
tutorial_asset: TutorialAssetType = strawberry_django.field(extensions=[IsAuthenticated()])
3636

3737
# --- Paginated
38-
tutorial_assets: OffsetPaginated[TutorialAssetType] = strawberry_django.offset_paginated(
38+
@strawberry_django.offset_paginated(
39+
OffsetPaginated[TutorialAssetType],
3940
order=TutorialAssetOrder,
4041
filters=TutorialAssetFilter,
4142
extensions=[IsAuthenticated()],
4243
)
44+
def tutorial_assets(
45+
self,
46+
include_all: bool = False,
47+
) -> QuerySet[TutorialAsset]:
48+
if include_all:
49+
return TutorialAsset.objects.all()
50+
return TutorialAsset.usable_objects()

schema.graphql

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -771,6 +771,8 @@ input DeleteInput {
771771
id: ID!
772772
}
773773

774+
union DeleteProjectAssetsPayload = OperationInfo | ProjectAssetsDeleteTypeMutationResponseType
775+
774776
union DeleteProjectPayload = OperationInfo | ProjectType
775777

776778
union DeleteTutorialPayload = OperationInfo | TutorialType
@@ -958,6 +960,7 @@ type Mutation {
958960
createTutorial(data: TutorialCreateInput!): CreateTutorialPayload! @isAuthenticated
959961
createTutorialAsset(data: TutorialAssetCreateInput!): CreateTutorialAssetPayload! @isAuthenticated
960962
deleteProject: DeleteProjectPayload! @isAuthenticated
963+
deleteProjectAssets(projectId: ID!, assetInputType: [ProjectAssetInputTypeEnum!]!): DeleteProjectAssetsPayload! @isAuthenticated
961964
deleteTutorial: DeleteTutorialPayload! @isAuthenticated
962965
login(username: String!, password: String!): UserMeType!
963966
logout: Boolean!
@@ -1388,6 +1391,16 @@ type ProjectAssetTypeOffsetPaginated {
13881391
totalCount: Int!
13891392
}
13901393

1394+
type ProjectAssetsDeleteType {
1395+
count: Int!
1396+
}
1397+
1398+
type ProjectAssetsDeleteTypeMutationResponseType {
1399+
errors: CustomErrorType
1400+
ok: Boolean!
1401+
result: ProjectAssetsDeleteType
1402+
}
1403+
13911404
"""Model representing the project."""
13921405
input ProjectCreateInput {
13931406
"""
@@ -2033,7 +2046,7 @@ type Query {
20332046
organizations(includeAll: Boolean! = false, filters: OrganizationFilter, order: OrganizationOrder, pagination: OffsetPaginationInput): OrganizationTypeOffsetPaginated! @isAuthenticated
20342047
project(id: ID!): ProjectType! @isAuthenticated
20352048
projectAsset(id: ID!): ProjectAssetType! @isAuthenticated
2036-
projectAssets(pagination: OffsetPaginationInput, filters: ProjectAssetFilter, order: ProjectAssetOrder): ProjectAssetTypeOffsetPaginated! @isAuthenticated
2049+
projectAssets(includeAll: Boolean! = false, filters: ProjectAssetFilter, order: ProjectAssetOrder, pagination: OffsetPaginationInput): ProjectAssetTypeOffsetPaginated! @isAuthenticated
20372050
projectName(params: ProjectNameInput): String!
20382051
projects(includeAll: Boolean! = false, filters: ProjectFilter, order: ProjectOrder, pagination: OffsetPaginationInput): ProjectTypeOffsetPaginated! @isAuthenticated
20392052
publicOrganization(id: ID!): OrganizationType!
@@ -2043,7 +2056,7 @@ type Query {
20432056
tileServers: RasterTileServersType! @isAuthenticated
20442057
tutorial(id: ID!): TutorialType! @isAuthenticated
20452058
tutorialAsset(id: ID!): TutorialAssetType! @isAuthenticated
2046-
tutorialAssets(pagination: OffsetPaginationInput, filters: TutorialAssetFilter, order: TutorialAssetOrder): TutorialAssetTypeOffsetPaginated! @isAuthenticated
2059+
tutorialAssets(includeAll: Boolean! = false, filters: TutorialAssetFilter, order: TutorialAssetOrder, pagination: OffsetPaginationInput): TutorialAssetTypeOffsetPaginated! @isAuthenticated
20472060
tutorials(includeAll: Boolean! = false, filters: TutorialFilter, order: TutorialOrder, pagination: OffsetPaginationInput): TutorialTypeOffsetPaginated! @isAuthenticated
20482061
users(filters: UserFilter, order: UserOrder, pagination: OffsetPaginationInput): UserTypeOffsetPaginated! @isAuthenticated
20492062
}

0 commit comments

Comments
 (0)