diff --git a/apiserver/plane/app/serializers/user.py b/apiserver/plane/app/serializers/user.py index 5381995fd..ca1547e37 100644 --- a/apiserver/plane/app/serializers/user.py +++ b/apiserver/plane/app/serializers/user.py @@ -80,9 +80,18 @@ class UserMeSettingsSerializer(BaseSerializer): workspace_invites = WorkspaceMemberInvite.objects.filter( email=obj.email ).count() - if obj.last_workspace_id is not None: + if ( + obj.last_workspace_id is not None + and Workspace.objects.filter( + pk=obj.last_workspace_id, + workspace_member__member=obj.id, + workspace_member__is_active=True, + ).exists() + ): workspace = Workspace.objects.filter( - pk=obj.last_workspace_id, workspace_member__member=obj.id + pk=obj.last_workspace_id, + workspace_member__member=obj.id, + workspace_member__is_active=True, ).first() return { "last_workspace_id": obj.last_workspace_id, @@ -95,7 +104,9 @@ class UserMeSettingsSerializer(BaseSerializer): } else: fallback_workspace = ( - Workspace.objects.filter(workspace_member__member_id=obj.id) + Workspace.objects.filter( + workspace_member__member_id=obj.id, workspace_member__is_active=True + ) .order_by("created_at") .first() ) @@ -159,10 +170,14 @@ class ChangePasswordSerializer(serializers.Serializer): def validate(self, data): if data.get("old_password") == data.get("new_password"): - raise serializers.ValidationError({"error": "New password cannot be same as old password."}) + raise serializers.ValidationError( + {"error": "New password cannot be same as old password."} + ) if data.get("new_password") != data.get("confirm_password"): - raise serializers.ValidationError({"error": "Confirm password should be same as the new password."}) + raise serializers.ValidationError( + {"error": "Confirm password should be same as the new password."} + ) return data diff --git a/apiserver/plane/app/views/issue.py b/apiserver/plane/app/views/issue.py index e7605bf14..a819d56f0 100644 --- a/apiserver/plane/app/views/issue.py +++ b/apiserver/plane/app/views/issue.py @@ -4,6 +4,7 @@ import random from itertools import chain # Django imports +from django.db import models from django.utils import timezone from django.db.models import ( Prefetch, @@ -367,6 +368,8 @@ class IssueListGroupedEndpoint(BaseAPIView): def get(self, request, slug, project_id): filters = issue_filters(request.query_params, "GET") + archive = request.GET.get("archived", False) + draft = request.GET.get("draft", False) fields = [field for field in request.GET.get("fields", "").split(",") if field] issue_queryset = ( @@ -384,6 +387,14 @@ class IssueListGroupedEndpoint(BaseAPIView): ) ) .filter(**filters) + .filter(is_draft=bool(draft)) + .filter(~Q(archived_at__isnull=bool(archive))) + .filter( + models.Q(issue_inbox__status=1) + | models.Q(issue_inbox__status=-1) + | models.Q(issue_inbox__status=2) + | models.Q(issue_inbox__isnull=True) + ) .annotate(cycle_id=F("issue_cycle__cycle_id")) .annotate(module_id=F("issue_module__module_id")) .annotate( diff --git a/apiserver/plane/app/views/user.py b/apiserver/plane/app/views/user.py index 0e6bba944..e25434bec 100644 --- a/apiserver/plane/app/views/user.py +++ b/apiserver/plane/app/views/user.py @@ -113,6 +113,15 @@ class UserEndpoint(BaseViewSet): # Deactivate the user user.is_active = False + user.last_workspace_id = None + user.is_tour_completed = False + user.is_onboarded = False + user.onboarding_step = { + "workspace_join": False, + "profile_complete": False, + "workspace_create": False, + "workspace_invite": False, + } user.save() return Response(status=status.HTTP_204_NO_CONTENT) @@ -135,9 +144,9 @@ class UpdateUserTourCompletedEndpoint(BaseAPIView): class UserActivityEndpoint(BaseAPIView, BasePaginator): def get(self, request): - queryset = IssueActivity.objects.filter( - actor=request.user - ).select_related("actor", "workspace", "issue", "project") + queryset = IssueActivity.objects.filter(actor=request.user).select_related( + "actor", "workspace", "issue", "project" + ) return self.paginate( request=request, diff --git a/apiserver/plane/app/views/workspace.py b/apiserver/plane/app/views/workspace.py index 3dc478609..5c5d0751c 100644 --- a/apiserver/plane/app/views/workspace.py +++ b/apiserver/plane/app/views/workspace.py @@ -113,7 +113,10 @@ class WorkSpaceViewSet(BaseViewSet): return ( self.filter_queryset(super().get_queryset().select_related("owner")) .order_by("name") - .filter(workspace_member__member=self.request.user) + .filter( + workspace_member__member=self.request.user, + workspace_member__is_active=True, + ) .annotate(total_members=member_count) .annotate(total_issues=issue_count) .select_related("owner") @@ -189,17 +192,21 @@ class UserWorkSpacesEndpoint(BaseAPIView): ) workspace = ( - ( - Workspace.objects.prefetch_related( - Prefetch("workspace_member", queryset=WorkspaceMember.objects.all()) + Workspace.objects.prefetch_related( + Prefetch( + "workspace_member", + queryset=WorkspaceMember.objects.filter( + member=request.user, is_active=True + ), ) - .filter( - workspace_member__member=request.user, - ) - .select_related("owner") ) + .select_related("owner") .annotate(total_members=member_count) .annotate(total_issues=issue_count) + .filter( + workspace_member__member=request.user, workspace_member__is_active=True + ) + .distinct() ) serializer = WorkSpaceSerializer(self.filter_queryset(workspace), many=True) @@ -319,7 +326,7 @@ class WorkspaceInvitationsViewset(BaseViewSet): workspace_invitations, batch_size=10, ignore_conflicts=True ) - current_site = request.META.get('HTTP_ORIGIN') + current_site = request.META.get("HTTP_ORIGIN") # Send invitations for invitation in workspace_invitations: @@ -418,7 +425,9 @@ class WorkspaceJoinEndpoint(BaseAPIView): ) def get(self, request, slug, pk): - workspace_invitation = WorkspaceMemberInvite.objects.get(workspace__slug=slug, pk=pk) + workspace_invitation = WorkspaceMemberInvite.objects.get( + workspace__slug=slug, pk=pk + ) serializer = WorkSpaceMemberInviteSerializer(workspace_invitation) return Response(serializer.data, status=status.HTTP_200_OK) @@ -1313,9 +1322,7 @@ class WorkspaceUserProfileIssuesEndpoint(BaseAPIView): return Response(issues, status=status.HTTP_200_OK) - class WorkspaceUserProfileIssuesGroupedEndpoint(BaseAPIView): - permission_classes = [ WorkspaceViewerPermission, ] @@ -1362,13 +1369,16 @@ class WorkspaceUserProfileIssuesGroupedEndpoint(BaseAPIView): ) ).distinct() - issues = IssueLiteSerializer(issue_queryset, many=True, fields=fields if fields else None).data + issues = IssueLiteSerializer( + issue_queryset, many=True, fields=fields if fields else None + ).data issue_dict = {str(issue["id"]): issue for issue in issues} return Response( issue_dict, status=status.HTTP_200_OK, ) + class WorkspaceLabelsEndpoint(BaseAPIView): permission_classes = [ WorkspaceViewerPermission,