Merge pull request #302 from makeplane/feat/issue_sorting_grouping

feat: updated issue grouping and filtering
This commit is contained in:
pablohashescobar 2023-02-21 23:52:08 +05:30 committed by GitHub
commit a904c4a7de
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 86 additions and 48 deletions

View File

@ -1,8 +1,9 @@
# All the python scripts that are used for back migrations # All the python scripts that are used for back migrations
import uuid import uuid
import random
from django.contrib.auth.hashers import make_password
from plane.db.models import ProjectIdentifier from plane.db.models import ProjectIdentifier
from plane.db.models import Issue, IssueComment, User from plane.db.models import Issue, IssueComment, User
from django.contrib.auth.hashers import make_password
# Update description and description html values for old descriptions # Update description and description html values for old descriptions
@ -79,3 +80,19 @@ def update_user_empty_password():
except Exception as e: except Exception as e:
print(e) print(e)
print("Failed") print("Failed")
def updated_issue_sort_order():
try:
issues = Issue.objects.all()
updated_issues = []
for issue in issues:
issue.sort_order = issue.sequence_id * random.randint(100, 500)
updated_issues.append(issue)
Issue.objects.bulk_update(updated_issues, ["sort_order"], batch_size=100)
print("Success")
except Exception as e:
print(e)
print("Failed")

View File

@ -42,6 +42,7 @@ from plane.db.models import (
IssueLink, IssueLink,
) )
from plane.bgtasks.issue_activites_task import issue_activity from plane.bgtasks.issue_activites_task import issue_activity
from plane.utils.grouper import group_results
class IssueViewSet(BaseViewSet): class IssueViewSet(BaseViewSet):
@ -145,51 +146,33 @@ class IssueViewSet(BaseViewSet):
) )
) )
def grouper(self, issue, group_by):
group_by = issue.get(group_by, "")
if isinstance(group_by, list):
if len(group_by):
return group_by[0]
else:
return ""
else:
return group_by
def list(self, request, slug, project_id): def list(self, request, slug, project_id):
try: try:
issue_queryset = self.get_queryset() # Issue State groups
type = request.GET.get("type", "all")
group = ["backlog", "unstarted", "started", "completed", "cancelled"]
if type == "backlog":
group = ["backlog"]
if type == "active":
group = ["unstarted", "started"]
## Grouping the results issue_queryset = (
group_by = request.GET.get("group_by", False) self.get_queryset()
# TODO: Move this group by from ittertools to ORM for better performance - nk .order_by(request.GET.get("order_by", "created_at"))
if group_by: .filter(state__group__in=group)
issue_dict = dict() )
issues = IssueSerializer(issue_queryset, many=True).data issues = IssueSerializer(issue_queryset, many=True).data
for key, value in groupby( ## Grouping the results
issues, lambda issue: self.grouper(issue, group_by) group_by = request.GET.get("group_by", False)
): if group_by:
issue_dict[str(key)] = list(value)
return Response(issue_dict, status=status.HTTP_200_OK)
return Response( return Response(
{ group_results(issues, group_by), status=status.HTTP_200_OK
"next_cursor": str(0),
"prev_cursor": str(0),
"next_page_results": False,
"prev_page_results": False,
"count": issue_queryset.count(),
"total_pages": 1,
"extra_stats": {},
"results": IssueSerializer(issue_queryset, many=True).data,
},
status=status.HTTP_200_OK,
) )
return Response(issues, status=status.HTTP_200_OK)
except Exception as e: except Exception as e:
print(e) print(e)
capture_exception(e) capture_exception(e)

View File

@ -69,16 +69,6 @@ class Issue(ProjectBaseModel):
def save(self, *args, **kwargs): def save(self, *args, **kwargs):
# This means that the model isn't saved to the database yet # This means that the model isn't saved to the database yet
if self._state.adding:
# Get the maximum display_id value from the database
last_id = IssueSequence.objects.filter(project=self.project).aggregate(
largest=models.Max("sequence")
)["largest"]
# aggregate can return None! Check it first.
# If it isn't none, just use the last ID specified (which should be the greatest) and add one to it
if last_id is not None:
self.sequence_id = last_id + 1
if self.state is None: if self.state is None:
try: try:
from plane.db.models import State from plane.db.models import State
@ -109,6 +99,23 @@ class Issue(ProjectBaseModel):
except ImportError: except ImportError:
pass pass
if self._state.adding:
# Get the maximum display_id value from the database
last_id = IssueSequence.objects.filter(project=self.project).aggregate(
largest=models.Max("sequence")
)["largest"]
# aggregate can return None! Check it first.
# If it isn't none, just use the last ID specified (which should be the greatest) and add one to it
if last_id is not None:
self.sequence_id = last_id + 1
largest_sort_order = Issue.objects.filter(
project=self.project, state=self.state
).aggregate(largest=models.Max("sort_order"))["largest"]
if largest_sort_order is not None:
self.sort_order = largest_sort_order + 10000
# Strip the html tags using html parser # Strip the html tags using html parser
self.description_stripped = ( self.description_stripped = (
None None

View File

@ -0,0 +1,31 @@
def group_results(results_data, group_by):
"""
Utility function to group data into a given attribute.
Function can group attributes of string and list type.
"""
response_dict = dict()
for value in results_data:
group_attribute = value.get(group_by, None)
if isinstance(group_attribute, list):
if len(group_attribute):
for attrib in group_attribute:
if str(attrib) in response_dict:
response_dict[str(attrib)].append(value)
else:
response_dict[str(attrib)] = []
response_dict[str(attrib)].append(value)
else:
if str(None) in response_dict:
response_dict[str(None)].append(value)
else:
response_dict[str(None)] = []
response_dict[str(None)].append(value)
else:
if str(group_attribute) in response_dict:
response_dict[str(group_attribute)].append(value)
else:
response_dict[str(group_attribute)] = []
response_dict[str(group_attribute)].append(value)
return response_dict