ФУНКЦИИ - МЕЖПРОЕКТНАЯ КОММУНИКАЦИЯ: зеркалирование комментариев, вложений и активности внешнего контура

This commit is contained in:
DCCONSTRUCTIONS
2026-04-19 08:53:41 +03:00
parent 8195c3fc80
commit 61a8625a5c
16 changed files with 525 additions and 13 deletions
@@ -225,6 +225,7 @@ from .notification.base import (
from .exporter.base import ExportIssuesEndpoint
from .external_contours import (
ExternalContourAttachmentDownloadEndpoint,
ExternalContourListCreateEndpoint,
ExternalContourDetailEndpoint,
ExternalContourDecisionEndpoint,
@@ -2,6 +2,7 @@
# SPDX-License-Identifier: AGPL-3.0-only
# See the LICENSE file for details.
from django.http import HttpResponseRedirect
from django.shortcuts import get_object_or_404
from django.utils import timezone
from rest_framework import status
@@ -17,8 +18,9 @@ from plane.api.serializers import (
from plane.api.serializers.issue import IssueSerializer as IssueCreateSerializer
from plane.app.permissions import ProjectLitePermission
from plane.app.views.base import BaseAPIView
from plane.db.models import Intake, IntakeIssue, Label, Project, ProjectMember, State, StateGroup
from plane.db.models import FileAsset, Intake, IntakeIssue, Label, Project, ProjectMember, State, StateGroup
from plane.db.models.intake import IntakeIssueStatus, SourceType
from plane.settings.storage import S3Storage
class ExternalContourListCreateEndpoint(BaseAPIView):
@@ -269,7 +271,14 @@ class ExternalContourDetailEndpoint(BaseAPIView):
def get(self, request, slug, project_id, request_id):
contour_request = get_object_or_404(self.get_queryset())
serializer = ExternalContourRequestSerializer(contour_request)
serializer = ExternalContourRequestSerializer(
contour_request,
context={
"include_mirror_data": True,
"workspace_slug": slug,
"source_project_id": str(project_id),
},
)
return Response(serializer.data, status=status.HTTP_200_OK)
@@ -349,6 +358,42 @@ class ExternalContourDecisionEndpoint(BaseAPIView):
"issue__created_by",
)
.prefetch_related("issue__issue_assignee__assignee", "issue__label_issue__label")
.get(pk=contour_request.id)
.get(pk=contour_request.id),
context={
"include_mirror_data": True,
"workspace_slug": slug,
"source_project_id": str(project_id),
},
)
return Response(serializer.data, status=status.HTTP_200_OK)
class ExternalContourAttachmentDownloadEndpoint(BaseAPIView):
permission_classes = [ProjectLitePermission]
def get_queryset(self):
return IntakeIssue.objects.filter(
workspace__slug=self.kwargs.get("slug"),
extra__bridge="external-contours",
extra__source_project_id=str(self.kwargs.get("project_id")),
pk=self.kwargs.get("request_id"),
).select_related("issue", "issue__project", "workspace")
def get(self, request, slug, project_id, request_id, attachment_id):
contour_request = get_object_or_404(self.get_queryset())
attachment = get_object_or_404(
FileAsset,
pk=attachment_id,
issue_id=contour_request.issue_id,
entity_type=FileAsset.EntityTypeContext.ISSUE_ATTACHMENT,
is_uploaded=True,
is_deleted=False,
)
storage = S3Storage(request=request)
presigned_url = storage.generate_presigned_url(
object_name=attachment.asset.name,
disposition="attachment",
filename=attachment.attributes.get("name"),
)
return HttpResponseRedirect(presigned_url)