diff --git a/baseapp-chats/baseapp_chats/admin.py b/baseapp-chats/baseapp_chats/admin.py index 175b7f57..1d31373e 100644 --- a/baseapp-chats/baseapp_chats/admin.py +++ b/baseapp-chats/baseapp_chats/admin.py @@ -4,6 +4,7 @@ ChatRoom = swapper.load_model("baseapp_chats", "ChatRoom") ChatRoomParticipant = swapper.load_model("baseapp_chats", "ChatRoomParticipant") Message = swapper.load_model("baseapp_chats", "Message") +MessageStatus = swapper.load_model("baseapp_chats", "MessageStatus") class ChatRoomParticipantInline(admin.TabularInline): @@ -18,11 +19,17 @@ class ChatRoomParticipantAdmin(admin.ModelAdmin): search_fields = ["profile", "room"] +class MessageStatusInline(admin.TabularInline): + model = MessageStatus + extra = 0 + + @admin.register(Message) class MessageAdmin(admin.ModelAdmin): list_display = ("profile", "verb", "action_object", "room", "timesince") list_filter = ["verb"] search_fields = ["content", "profile", "action_object", "room"] + inlines = [MessageStatusInline] @admin.register(ChatRoom) diff --git a/baseapp-chats/baseapp_chats/base.py b/baseapp-chats/baseapp_chats/base.py index 0d89c412..8d360b9d 100644 --- a/baseapp-chats/baseapp_chats/base.py +++ b/baseapp-chats/baseapp_chats/base.py @@ -188,6 +188,7 @@ def get_graphql_object_type(cls): class AbstractUnreadMessageCount(RelayModel): room = models.ForeignKey( swapper.get_model_name("baseapp_chats", "ChatRoom"), + related_name="unread_messages", on_delete=models.CASCADE, ) profile = models.ForeignKey( diff --git a/baseapp-chats/baseapp_chats/graphql/filters.py b/baseapp-chats/baseapp_chats/graphql/filters.py index 63a0986b..1dce6d29 100644 --- a/baseapp-chats/baseapp_chats/graphql/filters.py +++ b/baseapp-chats/baseapp_chats/graphql/filters.py @@ -9,6 +9,7 @@ class ChatRoomFilter(django_filters.FilterSet): q = django_filters.CharFilter(method="filter_q") profile_id = django_filters.CharFilter(method="filter_profile_id") + unread_messages = django_filters.BooleanFilter(method="filter_unread_messages") order_by = django_filters.OrderingFilter(fields=(("created", "created"),)) @@ -19,8 +20,31 @@ class Meta: def filter_q(self, queryset, name, value): return queryset.filter( Q(title__icontains=value) | Q(participants__profile__name__icontains=value) - ) + ).distinct() def filter_profile_id(self, queryset, name, value): pk = get_pk_from_relay_id(value) return queryset.filter(participants__profile_id=pk) + + def filter_unread_messages(self, queryset, name, value): + if value: + profile_id = self.data.get("profile_id", None) + try: + user_profile = self.request.user.profile + except AttributeError: + return queryset.none() + + unread_messages_profile_pk = ( + get_pk_from_relay_id(profile_id) if profile_id else user_profile.pk + ) + + return ( + queryset.prefetch_related("unread_messages") + .filter( + unread_messages__profile_id=unread_messages_profile_pk, + unread_messages__count__gt=0, + ) + .distinct() + ) + + return queryset diff --git a/baseapp-chats/baseapp_chats/graphql/object_types.py b/baseapp-chats/baseapp_chats/graphql/object_types.py index a59c6ce3..fd6af152 100644 --- a/baseapp-chats/baseapp_chats/graphql/object_types.py +++ b/baseapp-chats/baseapp_chats/graphql/object_types.py @@ -2,6 +2,7 @@ import swapper from baseapp_core.graphql import ( DjangoObjectType, + ThumbnailField, get_object_type_for_model, get_pk_from_relay_id, ) @@ -38,6 +39,7 @@ class BaseMessageObjectType: action_object = graphene.Field(relay.Node) verb = graphene.Field(VerbsEnum) content = graphene.String(required=False) + is_read = graphene.Boolean(profile_id=graphene.ID(required=False)) class Meta: interfaces = (relay.Node,) @@ -53,6 +55,7 @@ class Meta: "action_object", "extra_data", "in_reply_to", + "is_read", ) filter_fields = ("verb",) @@ -66,6 +69,19 @@ def get_node(cls, info, id): except cls._meta.model.DoesNotExist: return None + def resolve_is_read(self, info, profile_id=None, **kwargs): + if profile_id: + profile_pk = get_pk_from_relay_id(profile_id) + profile = Profile.objects.get_if_member(pk=profile_pk, user=info.context.user) + if not profile: + return None + else: + profile_pk = info.context.user.current_profile.pk + + message_status = self.statuses.filter(profile_id=profile_pk).first() + + return message_status and message_status.is_read + class MessageObjectType(BaseMessageObjectType, DjangoObjectType): class Meta(BaseMessageObjectType.Meta): @@ -76,6 +92,7 @@ class BaseChatRoomObjectType: all_messages = DjangoFilterConnectionField(get_object_type_for_model(Message)) participants = DjangoConnectionField(get_object_type_for_model(ChatRoomParticipant)) unread_messages_count = graphene.Int(profile_id=graphene.ID(required=False)) + image = ThumbnailField(required=False) def resolve_all_messages(self, info, **kwargs): return self.messages.all().order_by("-created") @@ -110,7 +127,7 @@ def resolve_unread_messages_count(self, info, profile_id=None, **kwargs): class Meta: interfaces = (relay.Node,) model = ChatRoom - fields = ("id", "last_message_time", "last_message", "participants", "name", "image") + fields = ("id", "last_message_time", "last_message", "participants", "title", "image") filterset_class = ChatRoomFilter diff --git a/baseapp-chats/baseapp_chats/migrations/0003_alter_unreadmessagecount_room.py b/baseapp-chats/baseapp_chats/migrations/0003_alter_unreadmessagecount_room.py new file mode 100644 index 00000000..d7e07e77 --- /dev/null +++ b/baseapp-chats/baseapp_chats/migrations/0003_alter_unreadmessagecount_room.py @@ -0,0 +1,25 @@ +# Generated by Django 5.0.9 on 2024-11-13 23:31 + +import django.db.models.deletion +from django.conf import settings +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("baseapp_chats", "0002_message_set_last_message_and_more"), + migrations.swappable_dependency(settings.BASEAPP_CHATS_CHATROOM_MODEL), + ] + + operations = [ + migrations.AlterField( + model_name="unreadmessagecount", + name="room", + field=models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + related_name="unread_messages", + to=settings.BASEAPP_CHATS_CHATROOM_MODEL, + ), + ), + ] diff --git a/baseapp-chats/setup.cfg b/baseapp-chats/setup.cfg index 43fd7c67..c8020f0f 100644 --- a/baseapp-chats/setup.cfg +++ b/baseapp-chats/setup.cfg @@ -1,6 +1,6 @@ [metadata] name = baseapp_chats -version = 0.0.2 +version = 0.0.3 description = BaseApp Chats long_description = file: README.md url = https://github.com/silverlogic/baseapp-backend