Skip to content

Commit f177020

Browse files
lunikaAntoLC
authored andcommitted
fixup! adapt back with blocknote interface
1 parent 5fc9777 commit f177020

13 files changed

+2147
-696
lines changed

src/backend/core/api/serializers.py

Lines changed: 81 additions & 148 deletions
Original file line numberDiff line numberDiff line change
@@ -879,134 +879,127 @@ class MoveDocumentSerializer(serializers.Serializer):
879879
)
880880

881881

882-
class ThreadSerializer(serializers.ModelSerializer):
883-
"""Serialize threads in a backward compatible shape for current frontend.
882+
class ReactionSerializer(serializers.ModelSerializer):
883+
"""Serialize reactions."""
884+
885+
users = UserLightSerializer(many=True, read_only=True)
886+
887+
class Meta:
888+
model = models.Reaction
889+
fields = [
890+
"id",
891+
"emoji",
892+
"created_at",
893+
"updated_at",
894+
"users",
895+
]
896+
read_only_fields = ["id", "created_at", "updated_at"]
884897

885-
We expose a flatten representation where ``content`` maps to the first
886-
comment's body. Creating a thread requires a ``content`` field which is
887-
stored as the first comment.
888-
"""
898+
899+
class CommentSerializer(serializers.ModelSerializer):
900+
"""Serialize comments (nested under a thread) with reactions and abilities."""
889901

890902
user = UserLightSerializer(read_only=True)
891-
abilities = serializers.SerializerMethodField(read_only=True)
892-
content = serializers.JSONField(write_only=True, required=True)
893-
document = serializers.PrimaryKeyRelatedField(read_only=True)
903+
abilities = serializers.SerializerMethodField()
904+
reactions = ReactionSerializer(many=True, read_only=True)
894905

895906
class Meta:
896-
model = models.Thread
907+
model = models.Comment
897908
fields = [
898909
"id",
899-
"content", # write: body of initial comment; read: not returned (we override to_representation)
910+
"user",
911+
"body",
900912
"created_at",
901913
"updated_at",
902-
"user",
903-
"document",
914+
"reactions",
904915
"abilities",
905916
]
906917
read_only_fields = [
907918
"id",
919+
"user",
908920
"created_at",
909921
"updated_at",
910-
"user",
911-
"document",
922+
"reactions",
912923
"abilities",
913924
]
914925

915-
def to_representation(self, instance):
916-
rep = super().to_representation(instance)
917-
# Provide first comment body as ``content`` to match previous API.
918-
first_comment = instance.first_comment
919-
rep["content"] = first_comment.body if first_comment else None
920-
return rep
926+
def validate(self, attrs):
927+
"""Validate comment data."""
928+
929+
request = self.context.get("request")
930+
user = getattr(request, "user", None)
921931

922-
def get_abilities(self, thread) -> dict: # type: ignore[override]
932+
attrs["thread_id"] = self.context["thread_id"]
933+
attrs["user_id"] = user.id if user else None
934+
return attrs
935+
936+
def get_abilities(self, obj):
937+
"""Return comment's abilities."""
923938
request = self.context.get("request")
924939
if request:
925-
return thread.get_abilities(request.user)
940+
return obj.get_abilities(request.user)
926941
return {}
927942

928-
def create(self, validated_data):
929-
request = self.context.get("request")
930-
document_id = self.context.get("resource_id")
931-
content = validated_data.pop("content")
932-
document = models.Document.objects.get(pk=document_id)
933-
user = request.user if request else None
934-
thread = models.Thread.objects.create(document=document, user=user)
935-
models.Comment.objects.create(thread=thread, user=user, body=content)
936-
return thread
937-
938-
def update(self, instance, validated_data): # pragma: no cover - not used yet
939-
# Allow updating first comment body for backward compatibility.
940-
content = validated_data.get("content")
941-
if content is not None:
942-
first = instance.first_comment
943-
if first:
944-
first.body = content
945-
first.save(update_fields=["body", "updated_at"])
946-
return instance
947-
948-
949-
class CommentInThreadSerializer(serializers.ModelSerializer):
950-
"""Serialize comments (nested under a thread) with reactions and abilities."""
951943

952-
user = UserLightSerializer(read_only=True)
953-
reactions = serializers.SerializerMethodField()
954-
abilities = serializers.SerializerMethodField()
944+
class ThreadSerializer(serializers.ModelSerializer):
945+
"""Serialize threads in a backward compatible shape for current frontend.
946+
947+
We expose a flatten representation where ``content`` maps to the first
948+
comment's body. Creating a thread requires a ``content`` field which is
949+
stored as the first comment.
950+
"""
951+
952+
creator = UserLightSerializer(read_only=True)
953+
abilities = serializers.SerializerMethodField(read_only=True)
954+
body = serializers.JSONField(write_only=True, required=True)
955+
document = serializers.PrimaryKeyRelatedField(read_only=True)
956+
comments = CommentSerializer(many=True, read_only=True)
955957

956958
class Meta:
957-
model = models.Comment
959+
model = models.Thread
958960
fields = [
959961
"id",
960-
"user",
961962
"body",
962963
"created_at",
963964
"updated_at",
964-
"reactions",
965+
"creator",
966+
"document",
965967
"abilities",
968+
"comments",
966969
]
967-
read_only_fields = fields
968-
969-
def get_reactions(self, obj):
970-
# Collect all users for reactions in a single query
971-
from django.contrib.auth import get_user_model
972-
User = get_user_model()
973-
reactions = list(obj.reactions.all())
974-
user_ids = set()
975-
for r in reactions:
976-
user_ids.update(r.user_ids or [])
977-
users_by_id = {
978-
u.id: u
979-
for u in User.objects.filter(id__in=user_ids).only(
980-
"id", "email", "full_name", "short_name", "language"
981-
)
982-
}
983-
# Serialize users with UserLightSerializer semantics (full_name/short_name logic)
984-
user_serializer = UserLightSerializer
985-
return [
986-
{
987-
"emoji": r.emoji,
988-
"created_at": r.created_at,
989-
"users": [
990-
user_serializer(users_by_id[uid]).data
991-
for uid in r.user_ids
992-
if uid in users_by_id
993-
],
994-
}
995-
for r in reactions
970+
read_only_fields = [
971+
"id",
972+
"created_at",
973+
"updated_at",
974+
"creator",
975+
"document",
976+
"abilities",
977+
"comments",
996978
]
997979

998-
def get_abilities(self, obj):
980+
def validate(self, attrs):
981+
"""Validate thread data."""
982+
request = self.context.get("request")
983+
user = getattr(request, "user", None)
984+
985+
attrs["document_id"] = self.context["resource_id"]
986+
attrs["creator_id"] = user.id if user else None
987+
988+
return attrs
989+
990+
def get_abilities(self, thread):
991+
"""Return thread's abilities."""
999992
request = self.context.get("request")
1000993
if request:
1001-
return obj.get_abilities(request.user)
994+
return thread.get_abilities(request.user)
1002995
return {}
1003996

1004997

1005998
class ThreadFullSerializer(serializers.ModelSerializer):
1006999
"""Full thread representation with nested comments."""
10071000

1008-
user = UserLightSerializer(read_only=True)
1009-
comments = serializers.SerializerMethodField()
1001+
creator = UserLightSerializer(read_only=True)
1002+
comments = CommentSerializer(many=True, read_only=True)
10101003
abilities = serializers.SerializerMethodField()
10111004

10121005
class Meta:
@@ -1015,79 +1008,19 @@ class Meta:
10151008
"id",
10161009
"created_at",
10171010
"updated_at",
1018-
"user",
1011+
"creator",
10191012
"resolved",
1020-
"resolved_updated_at",
1013+
"resolved_at",
10211014
"resolved_by",
10221015
"metadata",
10231016
"comments",
10241017
"abilities",
10251018
]
10261019
read_only_fields = fields
10271020

1028-
def get_comments(self, instance):
1029-
qs = instance.comments.select_related("user").prefetch_related("reactions")
1030-
return CommentInThreadSerializer(qs, many=True, context=self.context).data
1031-
10321021
def get_abilities(self, instance):
1022+
"""Return thread's abilities."""
10331023
request = self.context.get("request")
10341024
if request:
10351025
return instance.get_abilities(request.user)
10361026
return {}
1037-
1038-
1039-
class CreateThreadSerializer(serializers.Serializer):
1040-
body = serializers.JSONField(required=True)
1041-
metadata = serializers.JSONField(required=False)
1042-
1043-
def create(self, validated_data):
1044-
request = self.context.get("request")
1045-
document = self.context.get("document")
1046-
thread = models.Thread.objects.create(
1047-
document=document,
1048-
user=request.user if request else None,
1049-
metadata=validated_data.get("metadata", {}),
1050-
)
1051-
models.Comment.objects.create(
1052-
thread=thread,
1053-
user=request.user if request else None,
1054-
body=validated_data["body"],
1055-
metadata=validated_data.get("metadata", {}),
1056-
)
1057-
return thread
1058-
1059-
1060-
class CreateCommentSerializer(serializers.Serializer):
1061-
body = serializers.JSONField(required=True)
1062-
metadata = serializers.JSONField(required=False)
1063-
1064-
def create(self, validated_data):
1065-
request = self.context.get("request")
1066-
thread = self.context.get("thread")
1067-
return models.Comment.objects.create(
1068-
thread=thread,
1069-
user=request.user if request else None,
1070-
body=validated_data["body"],
1071-
metadata=validated_data.get("metadata", {}),
1072-
)
1073-
1074-
1075-
class UpdateCommentSerializer(serializers.ModelSerializer):
1076-
class Meta:
1077-
model = models.Comment
1078-
fields = ["body"]
1079-
1080-
1081-
class ReactionCreateSerializer(serializers.Serializer):
1082-
emoji = serializers.CharField(max_length=32)
1083-
1084-
def save(self, **kwargs): # pylint: disable=unused-argument
1085-
request = self.context.get("request")
1086-
comment = self.context.get("comment")
1087-
emoji = self.validated_data["emoji"]
1088-
reaction, _created = models.Reaction.objects.get_or_create(
1089-
comment=comment, emoji=emoji
1090-
)
1091-
if request and request.user:
1092-
reaction.add_user(request.user)
1093-
return reaction

0 commit comments

Comments
 (0)