Skip to content

Commit 10b36b6

Browse files
[WEB-3189] fix: listing deleted projects in initiatives (#2281)
* fix: deleted projects epic showing on initiatives * fix: deleted project epics listing on search
1 parent 153b2e3 commit 10b36b6

File tree

2 files changed

+126
-98
lines changed

2 files changed

+126
-98
lines changed

apiserver/plane/ee/views/app/epic/base.py

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -565,8 +565,14 @@ class WorkspaceEpicEndpoint(BaseAPIView):
565565
def get(self, request, slug):
566566
initiative_id = request.query_params.get("initiative_id", None)
567567

568-
epics_query = Issue.objects.filter(workspace__slug=slug).filter(
569-
Q(type__isnull=False) & Q(type__is_epic=True)
568+
epics_query = Issue.objects.filter(
569+
workspace__slug=slug,
570+
project__project_projectmember__member=self.request.user,
571+
project__project_projectmember__is_active=True,
572+
).filter(
573+
Q(type__isnull=False)
574+
& Q(type__is_epic=True)
575+
& Q(project__deleted_at__isnull=True)
570576
)
571577

572578
if initiative_id:
@@ -605,10 +611,7 @@ def get(self, request, slug, project_id):
605611
)
606612

607613
# fetch all the issues in which user is part of
608-
issues = Issue.objects.filter(
609-
workspace__slug=slug,
610-
project_id=project_id,
611-
)
614+
issues = Issue.objects.filter(workspace__slug=slug, project_id=project_id)
612615

613616
result = []
614617
for epic_id in epics:

apiserver/plane/ee/views/app/initiative/epic.py

Lines changed: 117 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,17 @@
22
from django.db import models
33
from django.contrib.postgres.aggregates import ArrayAgg
44
from django.contrib.postgres.fields import ArrayField
5-
from django.db.models import OuterRef, Subquery, Q, Count, Prefetch, Func, F, UUIDField, Value
5+
from django.db.models import (
6+
OuterRef,
7+
Subquery,
8+
Q,
9+
Count,
10+
Prefetch,
11+
Func,
12+
F,
13+
UUIDField,
14+
Value,
15+
)
616
from django.db.models.functions import Coalesce
717

818
# Third party imports
@@ -25,16 +35,16 @@ class InitiativeEpicViewSet(BaseViewSet):
2535
model = InitiativeEpic
2636

2737
@check_feature_flag(FeatureFlag.INITIATIVES)
28-
@allow_permission([ROLE.ADMIN, ROLE.MEMBER,], level="WORKSPACE")
38+
@allow_permission([ROLE.ADMIN, ROLE.MEMBER], level="WORKSPACE")
2939
def create(self, request, slug, initiative_id):
3040
# Get the epic_ids from the request
3141
epic_ids = request.data.get("epic_ids", [])
3242

3343
# Get the workspace
3444
workspace = Workspace.objects.get(slug=slug)
35-
largest_sort_order = InitiativeEpic.objects.filter(workspace=workspace, initiative_id=initiative_id).aggregate(
36-
largest=models.Max("sort_order")
37-
)["largest"]
45+
largest_sort_order = InitiativeEpic.objects.filter(
46+
workspace=workspace, initiative_id=initiative_id
47+
).aggregate(largest=models.Max("sort_order"))["largest"]
3848

3949
# If largest_sort_order is None, set it to 10000
4050
if largest_sort_order is None:
@@ -45,59 +55,66 @@ def create(self, request, slug, initiative_id):
4555
# Create the initiative_epics
4656
initiative_epics = []
4757
for epic_id in epic_ids:
48-
initiative_epics.append(InitiativeEpic(
49-
workspace=workspace,
50-
initiative_id=initiative_id,
51-
epic_id=epic_id,
52-
sort_order=largest_sort_order,
53-
))
58+
initiative_epics.append(
59+
InitiativeEpic(
60+
workspace=workspace,
61+
initiative_id=initiative_id,
62+
epic_id=epic_id,
63+
sort_order=largest_sort_order,
64+
)
65+
)
5466
largest_sort_order += 1000
5567

5668
# Bulk create the initiative_epics
57-
initiative_epics = InitiativeEpic.objects.bulk_create(initiative_epics, batch_size=1000)
69+
initiative_epics = InitiativeEpic.objects.bulk_create(
70+
initiative_epics, batch_size=1000
71+
)
5872

59-
epics = Issue.objects.filter(
60-
workspace__slug=slug, id__in=epic_ids
61-
).filter(Q(type__isnull=False) & Q(type__is_epic=True)).annotate(
62-
label_ids=Coalesce(
63-
ArrayAgg(
64-
"labels__id",
65-
distinct=True,
66-
filter=Q(
67-
~Q(labels__id__isnull=True)
68-
& Q(label_issue__deleted_at__isnull=True)
73+
epics = (
74+
Issue.objects.filter(workspace__slug=slug, id__in=epic_ids)
75+
.filter(Q(type__isnull=False) & Q(type__is_epic=True))
76+
.annotate(
77+
label_ids=Coalesce(
78+
ArrayAgg(
79+
"labels__id",
80+
distinct=True,
81+
filter=Q(
82+
~Q(labels__id__isnull=True)
83+
& Q(label_issue__deleted_at__isnull=True)
84+
),
6985
),
86+
Value([], output_field=ArrayField(UUIDField())),
7087
),
71-
Value([], output_field=ArrayField(UUIDField())),
72-
),
73-
assignee_ids=Coalesce(
74-
ArrayAgg(
75-
"assignees__id",
76-
distinct=True,
77-
filter=Q(
78-
~Q(assignees__id__isnull=True)
79-
& Q(assignees__member_project__is_active=True)
80-
& Q(issue_assignee__deleted_at__isnull=True)
88+
assignee_ids=Coalesce(
89+
ArrayAgg(
90+
"assignees__id",
91+
distinct=True,
92+
filter=Q(
93+
~Q(assignees__id__isnull=True)
94+
& Q(assignees__member_project__is_active=True)
95+
& Q(issue_assignee__deleted_at__isnull=True)
96+
),
8197
),
98+
Value([], output_field=ArrayField(UUIDField())),
8299
),
83-
Value([], output_field=ArrayField(UUIDField())),
84-
),
85-
).values(
86-
"id",
87-
"name",
88-
"state_id",
89-
"sort_order",
90-
"estimate_point",
91-
"priority",
92-
"start_date",
93-
"target_date",
94-
"sequence_id",
95-
"project_id",
96-
"archived_at",
97-
"state__group",
98-
"label_ids",
99-
"assignee_ids",
100-
"type_id",
100+
)
101+
.values(
102+
"id",
103+
"name",
104+
"state_id",
105+
"sort_order",
106+
"estimate_point",
107+
"priority",
108+
"start_date",
109+
"target_date",
110+
"sequence_id",
111+
"project_id",
112+
"archived_at",
113+
"state__group",
114+
"label_ids",
115+
"assignee_ids",
116+
"type_id",
117+
)
101118
)
102119

103120
return Response(epics, status=status.HTTP_200_OK)
@@ -108,57 +125,65 @@ def list(self, request, slug, initiative_id):
108125
workspace__slug=slug, initiative_id=initiative_id
109126
).values_list("epic_id", flat=True)
110127

111-
epics = Issue.objects.filter(
112-
workspace__slug=slug, id__in=initiative_epics
113-
).filter(Q(type__isnull=False) & Q(type__is_epic=True)).annotate(
114-
label_ids=Coalesce(
115-
ArrayAgg(
116-
"labels__id",
117-
distinct=True,
118-
filter=Q(
119-
~Q(labels__id__isnull=True)
120-
& Q(label_issue__deleted_at__isnull=True)
128+
epics = (
129+
Issue.objects.filter(
130+
workspace__slug=slug,
131+
id__in=initiative_epics,
132+
project__project_projectmember__member=self.request.user,
133+
project__project_projectmember__is_active=True,
134+
)
135+
.filter(Q(project__deleted_at__isnull=True))
136+
.filter(Q(type__isnull=False) & Q(type__is_epic=True))
137+
.annotate(
138+
label_ids=Coalesce(
139+
ArrayAgg(
140+
"labels__id",
141+
distinct=True,
142+
filter=Q(
143+
~Q(labels__id__isnull=True)
144+
& Q(label_issue__deleted_at__isnull=True)
145+
),
121146
),
147+
Value([], output_field=ArrayField(UUIDField())),
122148
),
123-
Value([], output_field=ArrayField(UUIDField())),
124-
),
125-
assignee_ids=Coalesce(
126-
ArrayAgg(
127-
"assignees__id",
128-
distinct=True,
129-
filter=Q(
130-
~Q(assignees__id__isnull=True)
131-
& Q(assignees__member_project__is_active=True)
132-
& Q(issue_assignee__deleted_at__isnull=True)
149+
assignee_ids=Coalesce(
150+
ArrayAgg(
151+
"assignees__id",
152+
distinct=True,
153+
filter=Q(
154+
~Q(assignees__id__isnull=True)
155+
& Q(assignees__member_project__is_active=True)
156+
& Q(issue_assignee__deleted_at__isnull=True)
157+
),
133158
),
159+
Value([], output_field=ArrayField(UUIDField())),
134160
),
135-
Value([], output_field=ArrayField(UUIDField())),
136-
),
137-
).values(
138-
"id",
139-
"name",
140-
"state_id",
141-
"sort_order",
142-
"estimate_point",
143-
"priority",
144-
"start_date",
145-
"target_date",
146-
"sequence_id",
147-
"project_id",
148-
"archived_at",
149-
"state__group",
150-
"label_ids",
151-
"assignee_ids",
152-
"type_id",
161+
)
162+
.values(
163+
"id",
164+
"name",
165+
"state_id",
166+
"sort_order",
167+
"estimate_point",
168+
"priority",
169+
"start_date",
170+
"target_date",
171+
"sequence_id",
172+
"project_id",
173+
"archived_at",
174+
"state__group",
175+
"label_ids",
176+
"assignee_ids",
177+
"type_id",
178+
)
153179
)
180+
154181
return Response(epics, status=status.HTTP_200_OK)
155182

156-
@allow_permission([ROLE.ADMIN, ROLE.MEMBER,], level="WORKSPACE")
183+
@allow_permission([ROLE.ADMIN, ROLE.MEMBER], level="WORKSPACE")
157184
def destroy(self, request, slug, initiative_id, epic_id):
158185
initiative_epics = InitiativeEpic.objects.filter(
159-
workspace__slug=slug,
160-
epic_id=epic_id,
161-
initiative_id=initiative_id
186+
workspace__slug=slug, epic_id=epic_id, initiative_id=initiative_id
162187
)
163188
initiative_epics.delete()
164189
return Response(status=status.HTTP_204_NO_CONTENT)

0 commit comments

Comments
 (0)