From 9339138c0e3997450431032a4422cbcaa9e4c516 Mon Sep 17 00:00:00 2001 From: pablohashescobar <118773738+pablohashescobar@users.noreply.github.com> Date: Wed, 22 Mar 2023 01:33:44 +0530 Subject: [PATCH] feat: user workspace dashboard endpoint (#461) * dev: initiate new dashboard endpoint * fix: updated issue week for this count and pending issues * dev: add try catch block * dev: add exception * dev: issue state distribution endpoint * dev: move from state name to state group * dev: add overdue issues and upcoming issues --- apiserver/plane/api/urls.py | 6 ++ apiserver/plane/api/views/__init__.py | 1 + apiserver/plane/api/views/workspace.py | 103 ++++++++++++++++++++++++- 3 files changed, 109 insertions(+), 1 deletion(-) diff --git a/apiserver/plane/api/urls.py b/apiserver/plane/api/urls.py index febe3f2c0..2050106b9 100644 --- a/apiserver/plane/api/urls.py +++ b/apiserver/plane/api/urls.py @@ -40,6 +40,7 @@ from plane.api.views import ( UserWorkspaceInvitationEndpoint, UserActivityGraphEndpoint, UserIssueCompletedGraphEndpoint, + UserWorkspaceDashboardEndpoint, ## End Workspaces # File Assets FileAssetEndpoint, @@ -200,6 +201,11 @@ urlpatterns = [ UserIssueCompletedGraphEndpoint.as_view(), name="completed-graph", ), + path( + "users/me/workspaces//dashboard/", + UserWorkspaceDashboardEndpoint.as_view(), + name="user-workspace-dashboard", + ), ## User Graph path( "users/me/invitations/workspaces///join/", diff --git a/apiserver/plane/api/views/__init__.py b/apiserver/plane/api/views/__init__.py index 1943511d3..fe9cdb96a 100644 --- a/apiserver/plane/api/views/__init__.py +++ b/apiserver/plane/api/views/__init__.py @@ -38,6 +38,7 @@ from .workspace import ( WorkspaceMemberUserViewsEndpoint, UserActivityGraphEndpoint, UserIssueCompletedGraphEndpoint, + UserWorkspaceDashboardEndpoint, ) from .state import StateViewSet from .shortcut import ShortCutViewSet diff --git a/apiserver/plane/api/views/workspace.py b/apiserver/plane/api/views/workspace.py index 116f4b2c9..89d8fb58d 100644 --- a/apiserver/plane/api/views/workspace.py +++ b/apiserver/plane/api/views/workspace.py @@ -629,7 +629,108 @@ class UserIssueCompletedGraphEndpoint(BaseAPIView): return Response(issues, status=status.HTTP_200_OK) except Exception as e: - print(e) + capture_exception(e) + return Response( + {"error": "Something went wrong please try again later"}, + status=status.HTTP_400_BAD_REQUEST, + ) + + +class UserWorkspaceDashboardEndpoint(BaseAPIView): + def get(self, request, slug): + try: + issue_activities = ( + IssueActivity.objects.filter( + actor=request.user, + workspace__slug=slug, + created_at__date__gte=date.today() + relativedelta(months=-3), + ) + .annotate(created_date=Cast("created_at", DateField())) + .values("created_date") + .annotate(activity_count=Count("created_date")) + .order_by("created_date") + ) + + month = request.GET.get("month", 1) + completed_issues = ( + Issue.objects.filter( + assignees__in=[request.user], + workspace__slug=slug, + completed_at__month=month, + completed_at__isnull=False, + ) + .annotate(completed_week=ExtractWeek("completed_at")) + .annotate(week=F("completed_week") % 4) + .values("week") + .annotate(completed_count=Count("completed_week")) + .order_by("week") + ) + + assigned_issues = Issue.objects.filter( + workspace__slug=slug, assignees__in=[request.user] + ).count() + + pending_issues = Issue.objects.filter( + ~Q(state__group__in=["completed", "cancelled"]), + workspace__slug=slug, + assignees__in=[request.user], + ).count() + + completed_issues_count = Issue.objects.filter( + workspace__slug=slug, + assignees__in=[request.user], + state__group="completed", + ).count() + + issues_due_week = ( + Issue.objects.filter( + workspace__slug=slug, + assignees__in=[request.user], + ) + .annotate(target_week=ExtractWeek("target_date")) + .filter(target_week=timezone.now().date().isocalendar()[1]) + .count() + ) + + state_distribution = ( + Issue.objects.filter(workspace__slug=slug, assignees__in=[request.user]) + .annotate(state_group=F("state__group")) + .values("state_group") + .annotate(state_count=Count("state_group")) + .order_by("state_group") + ) + + overdue_issues = Issue.objects.filter( + workspace__slug=slug, + assignees__in=[request.user], + target_date__lt=timezone.now(), + completed_at__isnull=False, + ).values("id", "name", "workspace__slug", "project_id", "target_date") + + upcoming_issues = Issue.objects.filter( + workspace__slug=slug, + assignees__in=[request.user], + target_date__gte=timezone.now(), + completed_at__isnull=False, + ).values("id", "name", "workspace__slug", "project_id", "target_date") + + return Response( + { + "issue_activities": issue_activities, + "completed_issues": completed_issues, + "assigned_issues_count": assigned_issues, + "pending_issues_count": pending_issues, + "completed_issues_count": completed_issues_count, + "issues_due_week_count": issues_due_week, + "state_distribution": state_distribution, + "overdue_issues": overdue_issues, + "upcoming_issues": upcoming_issues, + }, + status=status.HTTP_200_OK, + ) + + except Exception as e: + capture_exception(e) return Response( {"error": "Something went wrong please try again later"}, status=status.HTTP_400_BAD_REQUEST,