ФУНКЦИИ - МЕЖПРОЕКТНАЯ КОММУНИКАЦИЯ: единый realtime слой Tasker
Добавлен NODE.DC realtime event stream для workspace/project/member/invite/profile событий. Обновлены frontend stores и live controller. Доработаны settings modal, member dropdown и confirm remove под NODE.DC UX.
This commit is contained in:
@@ -9,6 +9,8 @@ from django.db.models import Min
|
||||
|
||||
# Module imports
|
||||
from .base import BaseViewSet, BaseAPIView
|
||||
from plane.app.realtime.issue_events import publish_assignee_cleanup_issue_events_on_commit
|
||||
from plane.app.realtime.nodedc_events import publish_nodedc_workspace_event_on_commit
|
||||
from plane.authentication.nodedc_workspace_policy import (
|
||||
is_nodedc_launcher_managed_workspace,
|
||||
nodedc_launcher_managed_workspace_response,
|
||||
@@ -176,6 +178,18 @@ class ProjectMemberViewSet(BaseViewSet):
|
||||
],
|
||||
batch_size=10,
|
||||
)
|
||||
for project_member in project_members:
|
||||
publish_nodedc_workspace_event_on_commit(
|
||||
project_member.workspace,
|
||||
"project_member.created",
|
||||
payload={
|
||||
"project_id": str(project_member.project_id),
|
||||
"member_id": str(project_member.member_id),
|
||||
"role": project_member.role,
|
||||
"source": "tasker",
|
||||
},
|
||||
extra_user_ids=[project_member.member_id],
|
||||
)
|
||||
# Send emails to notify the users
|
||||
[
|
||||
project_add_user_email.delay(
|
||||
@@ -301,6 +315,17 @@ class ProjectMemberViewSet(BaseViewSet):
|
||||
|
||||
if serializer.is_valid():
|
||||
serializer.save()
|
||||
publish_nodedc_workspace_event_on_commit(
|
||||
project_member.workspace,
|
||||
"project_member.updated",
|
||||
payload={
|
||||
"project_id": str(project_member.project_id),
|
||||
"member_id": str(project_member.member_id),
|
||||
"role": project_member.role,
|
||||
"source": "tasker",
|
||||
},
|
||||
extra_user_ids=[project_member.member_id],
|
||||
)
|
||||
return Response(serializer.data, status=status.HTTP_200_OK)
|
||||
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
|
||||
|
||||
@@ -336,9 +361,24 @@ class ProjectMemberViewSet(BaseViewSet):
|
||||
status=status.HTTP_400_BAD_REQUEST,
|
||||
)
|
||||
|
||||
publish_assignee_cleanup_issue_events_on_commit(
|
||||
project_id=project_id,
|
||||
assignee_id=project_member.member_id,
|
||||
actor_id=request.user.id,
|
||||
)
|
||||
project_member.is_active = False
|
||||
project_member.save()
|
||||
IssueAssignee.objects.filter(project_id=project_id, assignee_id=project_member.member_id).delete()
|
||||
publish_nodedc_workspace_event_on_commit(
|
||||
project_member.workspace,
|
||||
"project_member.deleted",
|
||||
payload={
|
||||
"project_id": str(project_member.project_id),
|
||||
"member_id": str(project_member.member_id),
|
||||
"source": "tasker",
|
||||
},
|
||||
extra_user_ids=[project_member.member_id],
|
||||
)
|
||||
return Response(status=status.HTTP_204_NO_CONTENT)
|
||||
|
||||
@allow_permission([ROLE.ADMIN, ROLE.MEMBER, ROLE.GUEST])
|
||||
@@ -367,10 +407,25 @@ class ProjectMemberViewSet(BaseViewSet):
|
||||
},
|
||||
status=status.HTTP_400_BAD_REQUEST,
|
||||
)
|
||||
publish_assignee_cleanup_issue_events_on_commit(
|
||||
project_id=project_id,
|
||||
assignee_id=project_member.member_id,
|
||||
actor_id=request.user.id,
|
||||
)
|
||||
# Deactivate the user
|
||||
project_member.is_active = False
|
||||
project_member.save()
|
||||
IssueAssignee.objects.filter(project_id=project_id, assignee_id=project_member.member_id).delete()
|
||||
publish_nodedc_workspace_event_on_commit(
|
||||
project_member.workspace,
|
||||
"project_member.deleted",
|
||||
payload={
|
||||
"project_id": str(project_member.project_id),
|
||||
"member_id": str(project_member.member_id),
|
||||
"source": "tasker",
|
||||
},
|
||||
extra_user_ids=[project_member.member_id],
|
||||
)
|
||||
return Response(status=status.HTTP_204_NO_CONTENT)
|
||||
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@ from rest_framework.response import Response
|
||||
|
||||
# Module imports
|
||||
from plane.app.permissions import WorkSpaceAdminPermission
|
||||
from plane.app.realtime.nodedc_events import publish_nodedc_workspace_event_on_commit
|
||||
from plane.authentication.nodedc_workspace_policy import (
|
||||
get_nodedc_workspace_creation_policy,
|
||||
is_nodedc_launcher_managed_workspace,
|
||||
@@ -159,6 +160,18 @@ class WorkspaceInvitationsViewset(BaseViewSet):
|
||||
invitation.nodedc_approval_request_id = approval_request_id
|
||||
invitation.save(update_fields=["nodedc_approval_request_id", "updated_at"])
|
||||
approved_requests.append(approval_request_id)
|
||||
invited_user = User.objects.filter(email__iexact=invitation.email, is_bot=False).first()
|
||||
publish_nodedc_workspace_event_on_commit(
|
||||
workspace,
|
||||
"workspace_invite.created",
|
||||
payload={
|
||||
"invite_id": str(invitation.id),
|
||||
"email": invitation.email,
|
||||
"status": invitation.nodedc_approval_status,
|
||||
"source": "tasker",
|
||||
},
|
||||
extra_user_ids=[request.user.id, getattr(invited_user, "id", None)],
|
||||
)
|
||||
except Exception:
|
||||
WorkspaceMemberInvite.objects.filter(id__in=[invitation.id for invitation in workspace_invitations]).delete()
|
||||
return Response(
|
||||
@@ -197,6 +210,18 @@ class WorkspaceInvitationsViewset(BaseViewSet):
|
||||
"invitee_email": invitation.email,
|
||||
},
|
||||
)
|
||||
invited_user = User.objects.filter(email__iexact=invitation.email, is_bot=False).first()
|
||||
publish_nodedc_workspace_event_on_commit(
|
||||
workspace,
|
||||
"workspace_invite.created",
|
||||
payload={
|
||||
"invite_id": str(invitation.id),
|
||||
"email": invitation.email,
|
||||
"status": invitation.nodedc_approval_status,
|
||||
"source": "tasker",
|
||||
},
|
||||
extra_user_ids=[request.user.id, getattr(invited_user, "id", None)],
|
||||
)
|
||||
|
||||
return Response({"message": "Emails sent successfully"}, status=status.HTTP_200_OK)
|
||||
|
||||
@@ -214,7 +239,23 @@ class WorkspaceInvitationsViewset(BaseViewSet):
|
||||
status=status.HTTP_502_BAD_GATEWAY,
|
||||
)
|
||||
|
||||
invited_user = User.objects.filter(email__iexact=workspace_member_invite.email, is_bot=False).first()
|
||||
workspace = workspace_member_invite.workspace
|
||||
invite_payload = {
|
||||
"invite_id": str(workspace_member_invite.id),
|
||||
"email": workspace_member_invite.email,
|
||||
"status": workspace_member_invite.nodedc_approval_status,
|
||||
"source": "tasker",
|
||||
}
|
||||
extra_user_ids = [workspace_member_invite.created_by_id, getattr(invited_user, "id", None)]
|
||||
|
||||
workspace_member_invite.delete()
|
||||
publish_nodedc_workspace_event_on_commit(
|
||||
workspace,
|
||||
"workspace_invite.deleted",
|
||||
payload=invite_payload,
|
||||
extra_user_ids=extra_user_ids,
|
||||
)
|
||||
return Response(status=status.HTTP_204_NO_CONTENT)
|
||||
|
||||
|
||||
@@ -340,6 +381,17 @@ class WorkspaceJoinEndpoint(BaseAPIView):
|
||||
},
|
||||
)
|
||||
|
||||
publish_nodedc_workspace_event_on_commit(
|
||||
workspace_invite.workspace,
|
||||
"workspace_member.created",
|
||||
payload={
|
||||
"member_id": str(user.id),
|
||||
"role": workspace_invite.role,
|
||||
"source": "tasker",
|
||||
},
|
||||
extra_user_ids=[user.id, workspace_invite.created_by_id],
|
||||
)
|
||||
|
||||
# Delete the invitation
|
||||
workspace_invite.delete()
|
||||
|
||||
@@ -447,6 +499,16 @@ class UserWorkspaceInvitationsViewSet(BaseViewSet):
|
||||
},
|
||||
)
|
||||
)
|
||||
publish_nodedc_workspace_event_on_commit(
|
||||
invitation.workspace,
|
||||
"workspace_member.created",
|
||||
payload={
|
||||
"member_id": str(request.user.id),
|
||||
"role": invitation.role,
|
||||
"source": "tasker",
|
||||
},
|
||||
extra_user_ids=[request.user.id, invitation.created_by_id],
|
||||
)
|
||||
|
||||
# Bulk create the user for all the workspaces
|
||||
WorkspaceMember.objects.bulk_create(
|
||||
|
||||
@@ -12,6 +12,8 @@ from rest_framework import status
|
||||
from rest_framework.response import Response
|
||||
|
||||
from plane.app.permissions import WorkspaceEntityPermission, allow_permission, ROLE
|
||||
from plane.app.realtime.issue_events import publish_assignee_cleanup_issue_events_on_commit
|
||||
from plane.app.realtime.nodedc_events import publish_nodedc_workspace_event_on_commit
|
||||
from plane.authentication.nodedc_workspace_policy import (
|
||||
get_nodedc_workspace_creation_policy,
|
||||
is_nodedc_launcher_managed_workspace,
|
||||
@@ -54,7 +56,7 @@ class WorkSpaceMemberViewSet(BaseViewSet):
|
||||
workspace_member = WorkspaceMember.objects.get(member=request.user, workspace__slug=slug, is_active=True)
|
||||
|
||||
# Get all active workspace members
|
||||
workspace_members = self.get_queryset()
|
||||
workspace_members = self.get_queryset().filter(is_active=True)
|
||||
if workspace_member.role > 5:
|
||||
serializer = WorkspaceMemberAdminSerializer(workspace_members, fields=("id", "member", "role"), many=True)
|
||||
else:
|
||||
@@ -102,6 +104,16 @@ class WorkSpaceMemberViewSet(BaseViewSet):
|
||||
|
||||
if serializer.is_valid():
|
||||
serializer.save()
|
||||
publish_nodedc_workspace_event_on_commit(
|
||||
workspace_member.workspace,
|
||||
"workspace_member.updated",
|
||||
payload={
|
||||
"member_id": str(workspace_member.member_id),
|
||||
"role": workspace_member.role,
|
||||
"source": "tasker",
|
||||
},
|
||||
extra_user_ids=[workspace_member.member_id],
|
||||
)
|
||||
return Response(serializer.data, status=status.HTTP_200_OK)
|
||||
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
|
||||
|
||||
@@ -166,6 +178,20 @@ class WorkSpaceMemberViewSet(BaseViewSet):
|
||||
status=status.HTTP_502_BAD_GATEWAY,
|
||||
)
|
||||
|
||||
project_ids = list(
|
||||
ProjectMember.objects.filter(
|
||||
workspace__slug=slug,
|
||||
member_id=workspace_member.member_id,
|
||||
is_active=True,
|
||||
).values_list("project_id", flat=True)
|
||||
)
|
||||
|
||||
publish_assignee_cleanup_issue_events_on_commit(
|
||||
workspace_id=workspace_member.workspace_id,
|
||||
assignee_id=workspace_member.member_id,
|
||||
actor_id=request.user.id,
|
||||
)
|
||||
|
||||
# Deactivate the users from the projects where the user is part of
|
||||
_ = ProjectMember.objects.filter(
|
||||
workspace__slug=slug, member_id=workspace_member.member_id, is_active=True
|
||||
@@ -174,6 +200,16 @@ class WorkSpaceMemberViewSet(BaseViewSet):
|
||||
|
||||
workspace_member.is_active = False
|
||||
workspace_member.save()
|
||||
publish_nodedc_workspace_event_on_commit(
|
||||
workspace_member.workspace,
|
||||
"workspace_member.deleted",
|
||||
payload={
|
||||
"member_id": str(workspace_member.member_id),
|
||||
"project_ids": [str(project_id) for project_id in project_ids],
|
||||
"source": "tasker",
|
||||
},
|
||||
extra_user_ids=[workspace_member.member_id],
|
||||
)
|
||||
return Response(status=status.HTTP_204_NO_CONTENT)
|
||||
|
||||
@invalidate_cache(
|
||||
@@ -224,6 +260,20 @@ class WorkSpaceMemberViewSet(BaseViewSet):
|
||||
status=status.HTTP_400_BAD_REQUEST,
|
||||
)
|
||||
|
||||
project_ids = list(
|
||||
ProjectMember.objects.filter(
|
||||
workspace__slug=slug,
|
||||
member_id=workspace_member.member_id,
|
||||
is_active=True,
|
||||
).values_list("project_id", flat=True)
|
||||
)
|
||||
|
||||
publish_assignee_cleanup_issue_events_on_commit(
|
||||
workspace_id=workspace_member.workspace_id,
|
||||
assignee_id=workspace_member.member_id,
|
||||
actor_id=request.user.id,
|
||||
)
|
||||
|
||||
# # Deactivate the users from the projects where the user is part of
|
||||
_ = ProjectMember.objects.filter(
|
||||
workspace__slug=slug, member_id=workspace_member.member_id, is_active=True
|
||||
@@ -233,6 +283,16 @@ class WorkSpaceMemberViewSet(BaseViewSet):
|
||||
# # Deactivate the user
|
||||
workspace_member.is_active = False
|
||||
workspace_member.save()
|
||||
publish_nodedc_workspace_event_on_commit(
|
||||
workspace_member.workspace,
|
||||
"workspace_member.deleted",
|
||||
payload={
|
||||
"member_id": str(workspace_member.member_id),
|
||||
"project_ids": [str(project_id) for project_id in project_ids],
|
||||
"source": "tasker",
|
||||
},
|
||||
extra_user_ids=[workspace_member.member_id],
|
||||
)
|
||||
return Response(status=status.HTTP_204_NO_CONTENT)
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user