feat: add comments feature with nested replies and recursive rendering
All checks were successful
ci/woodpecker/pr/pipeline Pipeline was successful
All checks were successful
ci/woodpecker/pr/pipeline Pipeline was successful
Implement full comments system: domain entities (Comment, CommentLike), value objects (CommentContent), use cases (CRUD, like toggle), SQLAlchemy repository, API v1 endpoints, web UI with comment form and nested replies, i18n translations (EN/RU/FR/DE), and E2E tests. Fix nested reply (reply-to-reply) not displaying — the flat reply_comments dict was only queried for top-level comment IDs, so deeply nested replies were saved to DB (incrementing comment count) but never rendered. Switch to a recursive Jinja2 macro that renders any nesting depth.
This commit is contained in:
63
app/application/use_cases/list_comments.py
Normal file
63
app/application/use_cases/list_comments.py
Normal file
@@ -0,0 +1,63 @@
|
||||
"""List comments use case.
|
||||
|
||||
This module implements the use case for listing comments on a blog post.
|
||||
"""
|
||||
|
||||
from uuid import UUID
|
||||
|
||||
from app.application.dtos.comment import CommentResponseDTO
|
||||
from app.domain.entities.comment import Comment
|
||||
from app.domain.repositories import CommentRepository
|
||||
|
||||
|
||||
class ListCommentsUseCase:
|
||||
"""Use case for listing comments on a blog post.
|
||||
|
||||
Retrieves all comments for a given post ordered by creation time.
|
||||
|
||||
Attributes:
|
||||
_comment_repo: Repository for comment data access.
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
comment_repo: CommentRepository,
|
||||
) -> None:
|
||||
"""Initialize use case with dependencies.
|
||||
|
||||
Args:
|
||||
comment_repo: Repository for comment operations.
|
||||
"""
|
||||
self._comment_repo = comment_repo
|
||||
|
||||
async def execute(self, post_id: UUID) -> list[CommentResponseDTO]:
|
||||
"""List all comments for a post.
|
||||
|
||||
Args:
|
||||
post_id: UUID of the post.
|
||||
|
||||
Returns:
|
||||
List of CommentResponseDTO for the post.
|
||||
"""
|
||||
comments = await self._comment_repo.get_by_post(post_id)
|
||||
return [self._map_to_dto(c) for c in comments]
|
||||
|
||||
def _map_to_dto(self, comment: Comment) -> CommentResponseDTO:
|
||||
"""Map domain entity to response DTO.
|
||||
|
||||
Args:
|
||||
comment: Domain Comment entity.
|
||||
|
||||
Returns:
|
||||
CommentResponseDTO with all comment attributes.
|
||||
"""
|
||||
return CommentResponseDTO(
|
||||
id=comment.id,
|
||||
post_id=comment.post_id,
|
||||
author_id=comment.author_id,
|
||||
content=comment.content.value,
|
||||
parent_id=comment.parent_id,
|
||||
like_count=comment.like_count,
|
||||
created_at=comment.created_at,
|
||||
updated_at=comment.updated_at,
|
||||
)
|
||||
Reference in New Issue
Block a user