diff --git a/plane-src/apps/api/plane/authentication/views/nodedc_agent_adapter.py b/plane-src/apps/api/plane/authentication/views/nodedc_agent_adapter.py index f46aaa6..abc274b 100644 --- a/plane-src/apps/api/plane/authentication/views/nodedc_agent_adapter.py +++ b/plane-src/apps/api/plane/authentication/views/nodedc_agent_adapter.py @@ -128,6 +128,8 @@ def serialize_comment(comment): "body": comment.comment_html, "actor_id": str(comment.actor_id) if comment.actor_id else None, "created_at": comment.created_at.isoformat(), + "updated_at": comment.updated_at.isoformat(), + "edited_at": comment.edited_at.isoformat() if comment.edited_at else None, } @@ -986,6 +988,53 @@ class NodeDCAgentIssueCommentEndpoint(View): comment.save(created_by_id=actor.id) return JsonResponse({"ok": True, "comment": serialize_comment(comment)}, status=201) + def patch(self, request, issue_id, comment_id): + error_response = validate_internal_request(request) + if error_response is not None: + return error_response + + payload = parse_json_body(request) + if payload is None: + return invalid_json_response() + + project, issue = resolve_issue(payload.get("project_id"), issue_id, payload.get("workspace_slug")) + if project is None: + return validation_error("project_not_found", status=404) + if issue is None: + return validation_error("issue_not_found", status=404) + + project_access_error = validate_agent_project_access(request, project) + if project_access_error is not None: + return project_access_error + + body = payload.get("body") + if not isinstance(body, str) or not body.strip(): + return validation_error("body_required") + + actor = ensure_agent_actor(request, project.workspace, project, payload) + if actor is None: + return validation_error("missing_agent_headers") + + comment = IssueComment.objects.filter( + id=comment_id, + issue=issue, + project=project, + actor=actor, + deleted_at__isnull=True, + ).first() + if comment is None: + return validation_error("comment_not_found_or_not_owned", status=404) + + comment.comment_html = html_from_text(body) + comment.comment_json = {} + comment.edited_at = timezone.now() + comment.updated_by = actor + comment.save( + update_fields=["comment_html", "comment_json", "edited_at", "updated_by", "updated_at"], + disable_auto_set_user=True, + ) + return JsonResponse({"ok": True, "comment": serialize_comment(comment)}) + @method_decorator(csrf_exempt, name="dispatch") class NodeDCAgentIssueLabelsEndpoint(View): diff --git a/plane-src/apps/api/plane/urls.py b/plane-src/apps/api/plane/urls.py index 96d2b2b..5603140 100644 --- a/plane-src/apps/api/plane/urls.py +++ b/plane-src/apps/api/plane/urls.py @@ -120,6 +120,11 @@ urlpatterns = [ NodeDCAgentIssueCommentEndpoint.as_view(), name="nodedc-agent-issue-comment", ), + path( + "api/internal/nodedc/agent/issues//comments/", + NodeDCAgentIssueCommentEndpoint.as_view(), + name="nodedc-agent-issue-comment-detail", + ), path( "api/internal/nodedc/agent/issues//labels", NodeDCAgentIssueLabelsEndpoint.as_view(),