Skip to content
Merged
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
3 changes: 2 additions & 1 deletion apiserver/.env.example
Original file line number Diff line number Diff line change
Expand Up @@ -57,5 +57,6 @@ ADMIN_BASE_URL=
SPACE_BASE_URL=
APP_BASE_URL=


# Hard delete files after days
HARD_DELETE_AFTER_DAYS=60
HARD_DELETE_AFTER_DAYS=60
4 changes: 2 additions & 2 deletions apiserver/plane/api/serializers/issue.py
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,7 @@ def update(self, instance, validated_data):
updated_by_id = instance.updated_by_id

if assignees is not None:
IssueAssignee.objects.filter(issue=instance).delete(soft=False)
IssueAssignee.objects.filter(issue=instance).delete()
IssueAssignee.objects.bulk_create(
[
IssueAssignee(
Expand All @@ -229,7 +229,7 @@ def update(self, instance, validated_data):
)

if labels is not None:
IssueLabel.objects.filter(issue=instance).delete(soft=False)
IssueLabel.objects.filter(issue=instance).delete()
IssueLabel.objects.bulk_create(
[
IssueLabel(
Expand Down
2 changes: 1 addition & 1 deletion apiserver/plane/api/views/cycle.py
Original file line number Diff line number Diff line change
Expand Up @@ -404,7 +404,7 @@ def delete(self, request, slug, project_id, pk):
epoch=int(timezone.now().timestamp()),
)
# Delete the cycle
cycle.delete(soft=False)
cycle.delete()
# Delete the user favorite cycle
UserFavorite.objects.filter(
entity_type="cycle",
Expand Down
11 changes: 9 additions & 2 deletions apiserver/plane/api/views/inbox.py
Original file line number Diff line number Diff line change
Expand Up @@ -227,15 +227,22 @@ def patch(self, request, slug, project_id, issue_id):
ArrayAgg(
"labels__id",
distinct=True,
filter=~Q(labels__id__isnull=True),
filter=Q(
~Q(labels__id__isnull=True)
& Q(label_issue__deleted_at__isnull=True),
),
),
Value([], output_field=ArrayField(UUIDField())),
),
assignee_ids=Coalesce(
ArrayAgg(
"assignees__id",
distinct=True,
filter=~Q(assignees__id__isnull=True),
filter=Q(
~Q(assignees__id__isnull=True)
& Q(assignees__member_project__is_active=True)
& Q(issue_assignee__deleted_at__isnull=True)
),
),
Value([], output_field=ArrayField(UUIDField())),
),
Expand Down
2 changes: 1 addition & 1 deletion apiserver/plane/api/views/issue.py
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@ def get(self, request, slug, project_id, pk=None):
.annotate(
cycle_id=Case(
When(
Q(issue_cycle__cycle__deleted_at__isnull=True),
Q(issue_cycle__deleted_at__isnull=True),
then=F("issue_cycle__cycle_id"),
),
default=None,
Expand Down
10 changes: 3 additions & 7 deletions apiserver/plane/app/serializers/draft.py
Original file line number Diff line number Diff line change
Expand Up @@ -169,9 +169,7 @@ def update(self, instance, validated_data):
updated_by_id = instance.updated_by_id

if assignees is not None:
DraftIssueAssignee.objects.filter(draft_issue=instance).delete(
soft=False
)
DraftIssueAssignee.objects.filter(draft_issue=instance).delete()
DraftIssueAssignee.objects.bulk_create(
[
DraftIssueAssignee(
Expand All @@ -188,9 +186,7 @@ def update(self, instance, validated_data):
)

if labels is not None:
DraftIssueLabel.objects.filter(draft_issue=instance).delete(
soft=False
)
DraftIssueLabel.objects.filter(draft_issue=instance).delete()
DraftIssueLabel.objects.bulk_create(
[
DraftIssueLabel(
Expand All @@ -208,7 +204,7 @@ def update(self, instance, validated_data):

if cycle_id != "not_provided":
DraftIssueCycle.objects.filter(draft_issue=instance).delete()
if cycle_id is not None:
if cycle_id:
DraftIssueCycle.objects.create(
cycle_id=cycle_id,
draft_issue=instance,
Expand Down
4 changes: 2 additions & 2 deletions apiserver/plane/app/serializers/issue.py
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,7 @@ def update(self, instance, validated_data):
updated_by_id = instance.updated_by_id

if assignees is not None:
IssueAssignee.objects.filter(issue=instance).delete(soft=False)
IssueAssignee.objects.filter(issue=instance).delete()
IssueAssignee.objects.bulk_create(
[
IssueAssignee(
Expand All @@ -218,7 +218,7 @@ def update(self, instance, validated_data):
)

if labels is not None:
IssueLabel.objects.filter(issue=instance).delete(soft=False)
IssueLabel.objects.filter(issue=instance).delete()
IssueLabel.objects.bulk_create(
[
IssueLabel(
Expand Down
5 changes: 4 additions & 1 deletion apiserver/plane/app/views/analytic/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,10 @@ def get(self, request, slug):
if x_axis in ["labels__id"] or segment in ["labels__id"]:
label_details = (
Issue.objects.filter(
workspace__slug=slug, **filters, labels__id__isnull=False
workspace__slug=slug,
**filters,
labels__id__isnull=False
& Q(label_issue__deleted_at__isnull=True),
)
.distinct("labels__id")
.order_by("labels__id")
Expand Down
7 changes: 6 additions & 1 deletion apiserver/plane/app/views/cycle/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,11 @@ def get_queryset(self):
distinct=True,
filter=~Q(
issue_cycle__issue__assignees__id__isnull=True
)
& (
Q(
issue_cycle__issue__issue_assignee__deleted_at__isnull=True
)
),
),
Value([], output_field=ArrayField(UUIDField())),
Expand Down Expand Up @@ -491,7 +496,7 @@ def destroy(self, request, slug, project_id, pk):
origin=request.META.get("HTTP_ORIGIN"),
)
# TODO: Soft delete the cycle break the onetoone relationship with cycle issue
cycle.delete(soft=False)
cycle.delete()
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Hard deletion of cycles may lead to data loss; consider addressing soft delete issues

Changing to cycle.delete() now performs a hard delete of the cycle, which may result in permanent data loss. The existing TODO comment indicates that soft deletion breaks the one-to-one relationship with CycleIssue. It would be better to resolve the soft deletion issue rather than switching to a hard delete as a workaround.

Would you like assistance in resolving the soft deletion issue? I can help investigate why soft deletion is causing issues with the one-to-one relationship and propose a solution.


# Delete the user favorite cycle
UserFavorite.objects.filter(
Expand Down
2 changes: 1 addition & 1 deletion apiserver/plane/app/views/cycle/issue.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ def list(self, request, slug, project_id, cycle_id):
.annotate(
cycle_id=Case(
When(
issue_cycle__cycle__deleted_at__isnull=True,
issue_cycle__deleted_at__isnull=True,
then=F("issue_cycle__cycle_id"),
),
default=None,
Expand Down
38 changes: 24 additions & 14 deletions apiserver/plane/app/views/dashboard/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -218,9 +218,9 @@ def dashboard_assigned_issues(self, request, slug):
ArrayAgg(
"labels__id",
distinct=True,
filter=(
filter=Q(
~Q(labels__id__isnull=True)
& Q(labels__deleted_at__isnull=True)
& Q(label_issue__deleted_at__isnull=True),
),
),
Value([], output_field=ArrayField(UUIDField())),
Expand All @@ -229,18 +229,23 @@ def dashboard_assigned_issues(self, request, slug):
ArrayAgg(
"assignees__id",
distinct=True,
filter=~Q(assignees__id__isnull=True)
& Q(assignees__member_project__is_active=True),
filter=Q(
~Q(assignees__id__isnull=True)
& Q(assignees__member_project__is_active=True)
& Q(issue_assignee__deleted_at__isnull=True)
),
),
Value([], output_field=ArrayField(UUIDField())),
),
module_ids=Coalesce(
ArrayAgg(
"issue_module__module_id",
distinct=True,
filter=~Q(issue_module__module_id__isnull=True)
& Q(issue_module__module__archived_at__isnull=True)
& Q(issue_module__module__deleted_at__isnull=True),
filter=Q(
~Q(issue_module__module_id__isnull=True)
& Q(issue_module__module__archived_at__isnull=True)
& Q(issue_module__deleted_at__isnull=True)
),
),
Value([], output_field=ArrayField(UUIDField())),
),
Expand Down Expand Up @@ -387,9 +392,9 @@ def dashboard_created_issues(self, request, slug):
ArrayAgg(
"labels__id",
distinct=True,
filter=(
filter=Q(
~Q(labels__id__isnull=True)
& Q(labels__deleted_at__isnull=True)
& Q(label_issue__deleted_at__isnull=True),
),
),
Value([], output_field=ArrayField(UUIDField())),
Expand All @@ -398,18 +403,23 @@ def dashboard_created_issues(self, request, slug):
ArrayAgg(
"assignees__id",
distinct=True,
filter=~Q(assignees__id__isnull=True)
& Q(assignees__member_project__is_active=True),
filter=Q(
~Q(assignees__id__isnull=True)
& Q(assignees__member_project__is_active=True)
& Q(issue_assignee__deleted_at__isnull=True)
),
),
Value([], output_field=ArrayField(UUIDField())),
),
module_ids=Coalesce(
ArrayAgg(
"issue_module__module_id",
distinct=True,
filter=~Q(issue_module__module_id__isnull=True)
& Q(issue_module__module__archived_at__isnull=True)
& Q(issue_module__module__deleted_at__isnull=True),
filter=Q(
~Q(issue_module__module_id__isnull=True)
& Q(issue_module__module__archived_at__isnull=True)
& Q(issue_module__deleted_at__isnull=True)
),
),
Value([], output_field=ArrayField(UUIDField())),
),
Expand Down
55 changes: 36 additions & 19 deletions apiserver/plane/app/views/inbox/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ def get_queryset(self):
.annotate(
cycle_id=Case(
When(
issue_cycle__cycle__deleted_at__isnull=True,
issue_cycle__deleted_at__isnull=True,
then=F("issue_cycle__cycle_id"),
),
default=None,
Expand Down Expand Up @@ -149,9 +149,9 @@ def get_queryset(self):
ArrayAgg(
"labels__id",
distinct=True,
filter=(
filter=Q(
~Q(labels__id__isnull=True)
& Q(labels__deleted_at__isnull=True)
& Q(label_issue__deleted_at__isnull=True),
),
),
Value([], output_field=ArrayField(UUIDField())),
Expand All @@ -160,18 +160,23 @@ def get_queryset(self):
ArrayAgg(
"assignees__id",
distinct=True,
filter=~Q(assignees__id__isnull=True)
& Q(assignees__member_project__is_active=True),
filter=Q(
~Q(assignees__id__isnull=True)
& Q(assignees__member_project__is_active=True)
& Q(issue_assignee__deleted_at__isnull=True)
),
),
Value([], output_field=ArrayField(UUIDField())),
),
module_ids=Coalesce(
ArrayAgg(
"issue_module__module_id",
distinct=True,
filter=~Q(issue_module__module_id__isnull=True)
& Q(issue_module__module__archived_at__isnull=True)
& Q(issue_module__module__deleted_at__isnull=True),
filter=Q(
~Q(issue_module__module_id__isnull=True)
& Q(issue_module__module__archived_at__isnull=True)
& Q(issue_module__deleted_at__isnull=True)
),
),
Value([], output_field=ArrayField(UUIDField())),
),
Expand All @@ -198,8 +203,8 @@ def list(self, request, slug, project_id):
ArrayAgg(
"issue__labels__id",
distinct=True,
filter=~Q(issue__labels__id__isnull=True)
& Q(issue__labels__deleted_at__isnull=True),
filter=Q(~Q(issue__labels__id__isnull=True)
& Q(issue__label_issue__deleted_at__isnull=True)),
),
Value([], output_field=ArrayField(UUIDField())),
)
Expand Down Expand Up @@ -311,9 +316,11 @@ def create(self, request, slug, project_id):
ArrayAgg(
"issue__labels__id",
distinct=True,
filter=(
filter=Q(
~Q(issue__labels__id__isnull=True)
& Q(issue__labels__deleted_at__isnull=True)
& Q(
issue__label_issue__deleted_at__isnull=True
)
),
),
Value([], output_field=ArrayField(UUIDField())),
Expand All @@ -323,7 +330,9 @@ def create(self, request, slug, project_id):
"issue__assignees__id",
distinct=True,
filter=~Q(issue__assignees__id__isnull=True)
& Q(issue__assignees__member_project__is_active=True),
& Q(
issue__assignees__member_project__is_active=True
),
),
Value([], output_field=ArrayField(UUIDField())),
),
Expand Down Expand Up @@ -376,15 +385,17 @@ def partial_update(self, request, slug, project_id, pk):
ArrayAgg(
"labels__id",
distinct=True,
filter=~Q(labels__id__isnull=True),
filter=Q(~Q(labels__id__isnull=True)
& Q(label_issue__deleted_at__isnull=True)),
),
Value([], output_field=ArrayField(UUIDField())),
),
assignee_ids=Coalesce(
ArrayAgg(
"assignees__id",
distinct=True,
filter=~Q(assignees__id__isnull=True),
filter=Q(~Q(assignees__id__isnull=True)
& Q(issue_assignee__deleted_at__isnull=True)),
),
Value([], output_field=ArrayField(UUIDField())),
),
Expand Down Expand Up @@ -507,15 +518,19 @@ def partial_update(self, request, slug, project_id, pk):
ArrayAgg(
"issue__labels__id",
distinct=True,
filter=~Q(issue__labels__id__isnull=True),
filter=Q(~Q(issue__labels__id__isnull=True)
& Q(
issue__label_issue__deleted_at__isnull=True
)),
),
Value([], output_field=ArrayField(UUIDField())),
),
assignee_ids=Coalesce(
ArrayAgg(
"issue__assignees__id",
distinct=True,
filter=~Q(issue__assignees__id__isnull=True),
filter=Q(~Q(issue__assignees__id__isnull=True)
& Q(issue__issue_assignee__deleted_at__isnull=True)),
),
Value([], output_field=ArrayField(UUIDField())),
),
Expand Down Expand Up @@ -560,15 +575,17 @@ def retrieve(self, request, slug, project_id, pk):
ArrayAgg(
"issue__labels__id",
distinct=True,
filter=~Q(issue__labels__id__isnull=True),
filter=Q(~Q(issue__labels__id__isnull=True)
& Q(issue__label_issue__deleted_at__isnull=True)),
),
Value([], output_field=ArrayField(UUIDField())),
),
assignee_ids=Coalesce(
ArrayAgg(
"issue__assignees__id",
distinct=True,
filter=~Q(issue__assignees__id__isnull=True),
filter=Q(~Q(issue__assignees__id__isnull=True)
& Q(issue__issue_assignee__deleted_at__isnull=True)),
),
Value([], output_field=ArrayField(UUIDField())),
),
Expand Down
2 changes: 1 addition & 1 deletion apiserver/plane/app/views/issue/archive.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ def get_queryset(self):
.annotate(
cycle_id=Case(
When(
issue_cycle__cycle__deleted_at__isnull=True,
issue_cycle__deleted_at__isnull=True,
then=F("issue_cycle__cycle_id"),
),
default=None,
Expand Down
Loading