From 462f4a37769e2df16749f724b06951afab6c9bf9 Mon Sep 17 00:00:00 2001 From: gh-pedrotpo Date: Mon, 4 Nov 2024 13:02:49 -0500 Subject: [PATCH 1/3] feat: change profile filter to add name and urlpath query --- baseapp-profiles/baseapp_profiles/tests/test_get_queries.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/baseapp-profiles/baseapp_profiles/tests/test_get_queries.py b/baseapp-profiles/baseapp_profiles/tests/test_get_queries.py index 1559a77e..e874e55d 100644 --- a/baseapp-profiles/baseapp_profiles/tests/test_get_queries.py +++ b/baseapp-profiles/baseapp_profiles/tests/test_get_queries.py @@ -4,6 +4,8 @@ from django.contrib.contenttypes.models import ContentType from .factories import ProfileFactory +from baseapp_pages.tests.factories import URLPathFactory +from django.contrib.contenttypes.models import ContentType pytestmark = pytest.mark.django_db From cfc4975c3336259958755b9b5f1de6f3c7806513 Mon Sep 17 00:00:00 2001 From: Ronan-Fernandes Date: Thu, 7 Nov 2024 16:05:32 -0300 Subject: [PATCH 2/3] Update room title field query and image query --- baseapp-chats/.coveragerc | 7 +++++++ baseapp-chats/baseapp_chats/graphql/object_types.py | 4 +++- baseapp-chats/setup.cfg | 2 +- .../baseapp_profiles/tests/test_get_queries.py | 3 +-- 4 files changed, 12 insertions(+), 4 deletions(-) create mode 100644 baseapp-chats/.coveragerc diff --git a/baseapp-chats/.coveragerc b/baseapp-chats/.coveragerc new file mode 100644 index 00000000..2c1ba620 --- /dev/null +++ b/baseapp-chats/.coveragerc @@ -0,0 +1,7 @@ +[run] +omit = + ./testproject/* + **/tests/* + +[report] +fail_under = 80 diff --git a/baseapp-chats/baseapp_chats/graphql/object_types.py b/baseapp-chats/baseapp_chats/graphql/object_types.py index a59c6ce3..b29f06d3 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, ) @@ -76,6 +77,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 +112,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/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 diff --git a/baseapp-profiles/baseapp_profiles/tests/test_get_queries.py b/baseapp-profiles/baseapp_profiles/tests/test_get_queries.py index e874e55d..fc00644c 100644 --- a/baseapp-profiles/baseapp_profiles/tests/test_get_queries.py +++ b/baseapp-profiles/baseapp_profiles/tests/test_get_queries.py @@ -4,8 +4,7 @@ from django.contrib.contenttypes.models import ContentType from .factories import ProfileFactory -from baseapp_pages.tests.factories import URLPathFactory -from django.contrib.contenttypes.models import ContentType + pytestmark = pytest.mark.django_db From 2d4e31409f09a4f0e08b29718656c72693787df1 Mon Sep 17 00:00:00 2001 From: Ronan <62265281+Ronan-Fernandes@users.noreply.github.com> Date: Wed, 27 Nov 2024 09:07:02 -0300 Subject: [PATCH 3/3] Unread Messages Filters (#183) --- baseapp-chats/.coveragerc | 7 ----- baseapp-chats/baseapp_chats/admin.py | 7 +++++ baseapp-chats/baseapp_chats/base.py | 1 + .../baseapp_chats/graphql/filters.py | 26 ++++++++++++++++++- .../baseapp_chats/graphql/object_types.py | 15 +++++++++++ .../0003_alter_unreadmessagecount_room.py | 25 ++++++++++++++++++ .../tests/test_get_queries.py | 1 - 7 files changed, 73 insertions(+), 9 deletions(-) delete mode 100644 baseapp-chats/.coveragerc create mode 100644 baseapp-chats/baseapp_chats/migrations/0003_alter_unreadmessagecount_room.py diff --git a/baseapp-chats/.coveragerc b/baseapp-chats/.coveragerc deleted file mode 100644 index 2c1ba620..00000000 --- a/baseapp-chats/.coveragerc +++ /dev/null @@ -1,7 +0,0 @@ -[run] -omit = - ./testproject/* - **/tests/* - -[report] -fail_under = 80 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 b29f06d3..fd6af152 100644 --- a/baseapp-chats/baseapp_chats/graphql/object_types.py +++ b/baseapp-chats/baseapp_chats/graphql/object_types.py @@ -39,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,) @@ -54,6 +55,7 @@ class Meta: "action_object", "extra_data", "in_reply_to", + "is_read", ) filter_fields = ("verb",) @@ -67,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): 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-profiles/baseapp_profiles/tests/test_get_queries.py b/baseapp-profiles/baseapp_profiles/tests/test_get_queries.py index fc00644c..1559a77e 100644 --- a/baseapp-profiles/baseapp_profiles/tests/test_get_queries.py +++ b/baseapp-profiles/baseapp_profiles/tests/test_get_queries.py @@ -5,7 +5,6 @@ from .factories import ProfileFactory - pytestmark = pytest.mark.django_db Profile = swapper.load_model("baseapp_profiles", "Profile")