From 2505417dbd9932532276d3c13773562a734e1937 Mon Sep 17 00:00:00 2001 From: pablohashescobar Date: Sat, 18 Feb 2023 12:22:17 +0530 Subject: [PATCH 1/5] feat: updated issue grouping and filtering --- apiserver/plane/api/views/issue.py | 53 ++++++++++++------------------ 1 file changed, 21 insertions(+), 32 deletions(-) diff --git a/apiserver/plane/api/views/issue.py b/apiserver/plane/api/views/issue.py index 4f7e7473b..3c621319b 100644 --- a/apiserver/plane/api/views/issue.py +++ b/apiserver/plane/api/views/issue.py @@ -143,50 +143,39 @@ 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): 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"] + issue_queryset = ( + self.get_queryset() + .order_by(request.GET.get("order_by", "created_at")) + .filter(state__group__in=group) + ) + + issues = IssueSerializer(issue_queryset, many=True).data ## Grouping the results group_by = request.GET.get("group_by", False) - # TODO: Move this group by from ittertools to ORM for better performance - nk + if group_by: issue_dict = dict() - - issues = IssueSerializer(issue_queryset, many=True).data - for key, value in groupby( - issues, lambda issue: self.grouper(issue, group_by) + sorted( + issues, + key=lambda issue: str(issue.get(group_by)), + ), + key=lambda issue: str(issue.get(group_by)), ): issue_dict[str(key)] = list(value) - return Response(issue_dict, status=status.HTTP_200_OK) - return Response( - { - "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: print(e) From eba0f02aebba873de15a09baf3fc5b1bbb311360 Mon Sep 17 00:00:00 2001 From: pablohashescobar Date: Sat, 18 Feb 2023 12:29:46 +0530 Subject: [PATCH 2/5] feat: back migration script to populate random sort_order values --- apiserver/back_migration.py | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/apiserver/back_migration.py b/apiserver/back_migration.py index 9613412a3..f716ea29f 100644 --- a/apiserver/back_migration.py +++ b/apiserver/back_migration.py @@ -1,8 +1,9 @@ # All the python scripts that are used for back migrations import uuid +import random +from django.contrib.auth.hashers import make_password from plane.db.models import ProjectIdentifier 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 @@ -79,3 +80,19 @@ def update_user_empty_password(): except Exception as e: print(e) 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") From 236c660cc7792dcecddee052bf37bccca213588f Mon Sep 17 00:00:00 2001 From: pablohashescobar Date: Sat, 18 Feb 2023 12:35:42 +0530 Subject: [PATCH 3/5] feat: sort order during create --- apiserver/plane/db/models/issue.py | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/apiserver/plane/db/models/issue.py b/apiserver/plane/db/models/issue.py index d212f7565..56ddbfb45 100644 --- a/apiserver/plane/db/models/issue.py +++ b/apiserver/plane/db/models/issue.py @@ -69,16 +69,6 @@ class Issue(ProjectBaseModel): def save(self, *args, **kwargs): # 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: try: from plane.db.models import State @@ -109,6 +99,23 @@ class Issue(ProjectBaseModel): except ImportError: 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(larget=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 self.description_stripped = ( None From 495ac0ca0079a72aefbbe0e3f2edc4c07f3320be Mon Sep 17 00:00:00 2001 From: pablohashescobar Date: Sat, 18 Feb 2023 15:43:47 +0530 Subject: [PATCH 4/5] feat: improved grouper with grouping function --- apiserver/plane/api/views/issue.py | 16 +++++---------- apiserver/plane/utils/grouper.py | 31 ++++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 11 deletions(-) create mode 100644 apiserver/plane/utils/grouper.py diff --git a/apiserver/plane/api/views/issue.py b/apiserver/plane/api/views/issue.py index 3c621319b..9f35aeb69 100644 --- a/apiserver/plane/api/views/issue.py +++ b/apiserver/plane/api/views/issue.py @@ -42,6 +42,7 @@ from plane.db.models import ( IssueLink, ) from plane.bgtasks.issue_activites_task import issue_activity +from plane.utils.grouper import group_results class IssueViewSet(BaseViewSet): @@ -160,20 +161,13 @@ class IssueViewSet(BaseViewSet): ) issues = IssueSerializer(issue_queryset, many=True).data + ## Grouping the results group_by = request.GET.get("group_by", False) - if group_by: - issue_dict = dict() - for key, value in groupby( - sorted( - issues, - key=lambda issue: str(issue.get(group_by)), - ), - key=lambda issue: str(issue.get(group_by)), - ): - issue_dict[str(key)] = list(value) - return Response(issue_dict, status=status.HTTP_200_OK) + return Response( + group_results(issues, group_by), status=status.HTTP_200_OK + ) return Response(issues, status=status.HTTP_200_OK) diff --git a/apiserver/plane/utils/grouper.py b/apiserver/plane/utils/grouper.py new file mode 100644 index 000000000..51c1f61c2 --- /dev/null +++ b/apiserver/plane/utils/grouper.py @@ -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 \ No newline at end of file From d50cc1497238164d99cbd1e42442378671a0e18d Mon Sep 17 00:00:00 2001 From: pablohashescobar Date: Sat, 18 Feb 2023 18:21:42 +0530 Subject: [PATCH 5/5] fix: typo in model aggregation key --- apiserver/plane/db/models/issue.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apiserver/plane/db/models/issue.py b/apiserver/plane/db/models/issue.py index 56ddbfb45..2979362dc 100644 --- a/apiserver/plane/db/models/issue.py +++ b/apiserver/plane/db/models/issue.py @@ -112,7 +112,7 @@ class Issue(ProjectBaseModel): largest_sort_order = Issue.objects.filter( project=self.project, state=self.state - ).aggregate(larget=models.Max("sort_order"))["largest"] + ).aggregate(largest=models.Max("sort_order"))["largest"] if largest_sort_order is not None: self.sort_order = largest_sort_order + 10000