Skip to content
Merged

Dev #116

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 21 additions & 1 deletion chats/admin.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
from django.contrib import admin

from chats.models import ProjectChat, DirectChat, ProjectChatMessage, DirectChatMessage
from chats.models import (
ProjectChat,
DirectChat,
ProjectChatMessage,
DirectChatMessage,
FileToMessage,
)


@admin.display(description="Пользователи чата")
Expand Down Expand Up @@ -38,3 +44,17 @@ class ProjectChatMessageAdmin(admin.ModelAdmin):
class DirectChatMessageAdmin(admin.ModelAdmin):
list_display = ("id", "author", "chat", "created_at")
list_display_links = ("id", "author", "chat")


@admin.register(FileToMessage)
class FileToMessageAdmin(admin.ModelAdmin):
list_display = (
"file",
"direct_message",
"project_message",
)
list_display_links = (
"file",
"direct_message",
"project_message",
)
8 changes: 8 additions & 0 deletions chats/consumers/event_types/DirectEvent.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
get_user_channel_cache_key,
create_message,
get_chat_and_user_ids_from_content,
match_files_and_messages,
)
from chats.serializers import DirectChatMessageListSerializer

Expand Down Expand Up @@ -47,9 +48,16 @@ async def process_new_message_event(self, event: Event, room_name: str):
reply_to=reply_to_message,
)

messages = {
"direct_message": msg,
"project_message": None,
}
await match_files_and_messages(event.content["file_urls"], messages)

message_data = await sync_to_async(
lambda: (DirectChatMessageListSerializer(msg)).data
)()

content = {
"chat_id": chat_id,
"message": message_data,
Expand Down
12 changes: 9 additions & 3 deletions chats/consumers/event_types/ProjectEvent.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
from asgiref.sync import sync_to_async
from chats.models import ProjectChat, ProjectChatMessage
from chats.utils import create_message
from chats.utils import create_message, match_files_and_messages
from chats.websockets_settings import Event, EventType
from chats.exceptions import (
WrongChatIdException,
UserNotInChatException,
UserNotMessageAuthorException,
)

from chats.serializers import (
ProjectChatMessageListSerializer,
DirectChatMessageListSerializer,
)


Expand Down Expand Up @@ -45,8 +45,14 @@ async def process_new_message_event(self, event: Event, room_name: str):
reply_to=reply_to_message,
)

messages = {
"direct_message": None,
"project_message": msg,
}
await match_files_and_messages(event.content["file_urls"], messages)

message_data = await sync_to_async(
lambda: (DirectChatMessageListSerializer(msg)).data
lambda: (ProjectChatMessageListSerializer(msg)).data
)()
content = {
"chat_id": chat_id,
Expand Down
3 changes: 0 additions & 3 deletions chats/migrations/0005_chatattachment.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,6 @@ class Migration(migrations.Migration):
to="files.userfile",
),
),
("name", models.CharField(default="file", max_length=512)),
("extension", models.CharField(blank=True, default="", max_length=32)),
("size", models.PositiveBigIntegerField(default=1)),
],
bases=("files.userfile",),
),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Generated by Django 4.1.3 on 2023-03-27 18:48

from django.db import migrations


class Migration(migrations.Migration):

dependencies = [
("chats", "0007_remove_directchatmessage_file_url_and_more"),
]

operations = [
migrations.RemoveField(
model_name="directchatmessage",
name="file_url",
),
migrations.RemoveField(
model_name="projectchatmessage",
name="file_url",
),
]
52 changes: 52 additions & 0 deletions chats/migrations/0009_filetomessage.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# Generated by Django 4.1.3 on 2023-03-28 14:05

from django.db import migrations, models
import django.db.models.deletion


class Migration(migrations.Migration):

dependencies = [
("files", "0003_userfile_extension_userfile_name_userfile_size"),
("chats", "0008_remove_directchatmessage_file_url_and_more"),
]

operations = [
migrations.CreateModel(
name="FileToMessage",
fields=[
(
"file",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
primary_key=True,
related_name="file_to_message",
serialize=False,
to="files.userfile",
),
),
(
"direct_message",
models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.CASCADE,
related_name="file_to_direct_message",
to="chats.directchatmessage",
),
),
(
"project_message",
models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.CASCADE,
related_name="file_to_direct_message",
to="chats.projectchatmessage",
),
),
],
options={
"verbose_name": "Связка файла и сообщения",
"verbose_name_plural": "Связки файлов и сообщений",
},
),
]
26 changes: 26 additions & 0 deletions chats/migrations/0010_alter_filetomessage_file.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Generated by Django 4.1.3 on 2023-03-28 14:07

from django.db import migrations, models
import django.db.models.deletion


class Migration(migrations.Migration):

dependencies = [
("files", "0003_userfile_extension_userfile_name_userfile_size"),
("chats", "0009_filetomessage"),
]

operations = [
migrations.AlterField(
model_name="filetomessage",
name="file",
field=models.OneToOneField(
on_delete=django.db.models.deletion.CASCADE,
primary_key=True,
related_name="file_to_message",
serialize=False,
to="files.userfile",
),
),
]
30 changes: 30 additions & 0 deletions chats/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from django.core.exceptions import ValidationError
from django.db import models

from files.models import UserFile
from projects.models import Project

User = get_user_model()
Expand Down Expand Up @@ -283,3 +284,32 @@ def __str__(self):
class Meta:
verbose_name = "Сообщение в личном чате"
verbose_name_plural = "Сообщения в личных чатах"


class FileToMessage(models.Model):
file = models.OneToOneField(
UserFile,
on_delete=models.CASCADE,
related_name="file_to_message",
primary_key=True,
null=False,
)
direct_message = models.ForeignKey(
DirectChatMessage,
on_delete=models.CASCADE,
related_name="file_to_direct_message",
null=True,
)
project_message = models.ForeignKey(
ProjectChatMessage,
on_delete=models.CASCADE,
related_name="file_to_direct_message",
null=True,
)

def __str__(self):
return f"FileToMessage<{self.file}>"

class Meta:
verbose_name = "Связка файла и сообщения"
verbose_name_plural = "Связки файлов и сообщений"
28 changes: 27 additions & 1 deletion chats/serializers.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
from rest_framework import serializers

from chats.models import DirectChat, ProjectChat, DirectChatMessage, ProjectChatMessage
from chats.models import (
DirectChat,
ProjectChat,
DirectChatMessage,
ProjectChatMessage,
)
from files.serializers import UserFileSerializer
from users.serializers import UserListSerializer, UserDetailSerializer


Expand Down Expand Up @@ -105,6 +111,15 @@ class Meta:
class DirectChatMessageListSerializer(serializers.ModelSerializer):
author = UserDetailSerializer()
reply_to = DirectChatMessageSerializer(allow_null=True)
files = serializers.SerializerMethodField()

@classmethod
def get_files(cls, message: DirectChatMessage):
data = []
for file_to_message in message.file_to_direct_message.all():
file_data = UserFileSerializer(file_to_message.file).data
data.append(file_data)
return data

class Meta:
model = DirectChatMessage
Expand All @@ -113,6 +128,7 @@ class Meta:
"author",
"text",
"reply_to",
"files",
"is_edited",
"is_read",
"is_deleted",
Expand Down Expand Up @@ -144,13 +160,23 @@ class Meta:
class ProjectChatMessageListSerializer(serializers.ModelSerializer):
author = UserDetailSerializer()
reply_to = ProjectChatMessageSerializer(allow_null=True)
files = serializers.SerializerMethodField()

@classmethod
def get_files(cls, message: DirectChatMessage):
data = []
for file_to_message in message.file_to_direct_message.all():
file_data = UserFileSerializer(file_to_message.file).data
data.append(file_data)
return data

class Meta:
model = ProjectChatMessage
fields = [
"id",
"author",
"text",
"files",
"reply_to",
"is_edited",
"is_read",
Expand Down
2 changes: 0 additions & 2 deletions chats/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,12 @@
ProjectChatMessageList,
ProjectChatDetail,
DirectChatDetail,
# ChatAttachmentView,
)

app_name = "chats"

urlpatterns = [
path("directs/", DirectChatList.as_view(), name="direct-chat-list"),
# path("attachments/", ChatAttachmentView.as_view(), name="chat-attachments"),
path("directs/<slug:pk>/", DirectChatDetail.as_view(), name="direct-chat-detail"),
path("projects/", ProjectChatList.as_view(), name="project-chat-list"),
path("projects/<int:pk>/", ProjectChatDetail.as_view(), name="project-chat-detail"),
Expand Down
24 changes: 23 additions & 1 deletion chats/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@
WrongChatIdException,
NonMatchingDirectChatIdException,
)
from chats.models import DirectChatMessage, ProjectChatMessage
from chats.models import DirectChatMessage, ProjectChatMessage, FileToMessage
from files.models import UserFile

User = get_user_model()

Expand Down Expand Up @@ -93,3 +94,24 @@ async def get_chat_and_user_ids_from_content(content, current_user) -> tuple[str
f"User {current_user.id} is not a member of chat {chat_id}"
)
return chat_id, other_user


async def create_file_to_message(
direct_message: Union[str, None, DirectChatMessage],
project_message: Union[str, None, ProjectChatMessage],
file: str,
) -> FileToMessage:
return await sync_to_async(FileToMessage.objects.create)(
direct_message=direct_message, project_message=project_message, file=file
)


async def match_files_and_messages(file_urls, messages):
for url in file_urls:
file = await sync_to_async(UserFile.objects.get)(pk=url)
# implicitly matches a file and a message
await create_file_to_message(
direct_message=messages["direct_message"],
project_message=messages["project_message"],
file=file,
)
Loading