diff --git a/Main/views/ChatsView.py b/Main/views/ChatsView.py new file mode 100644 index 0000000..d4eac46 --- /dev/null +++ b/Main/views/ChatsView.py @@ -0,0 +1,7 @@ +from SprintLib.BaseView import BaseView + + +class ChatsView(BaseView): + view_file = "chats.html" + required_login = True + endpoint = "chats" diff --git a/Main/views/__init__.py b/Main/views/__init__.py index 2f72fde..8f40c4e 100644 --- a/Main/views/__init__.py +++ b/Main/views/__init__.py @@ -17,3 +17,4 @@ from Main.views.SolutionsView import SolutionsView from Main.views.SetView import SetView from Main.views.GroupView import GroupView from Main.views.CheckersView import CheckersView +from Main.views.ChatsView import ChatsView diff --git a/Messaging/__init__.py b/Messaging/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/Messaging/admin.py b/Messaging/admin.py new file mode 100644 index 0000000..50b753d --- /dev/null +++ b/Messaging/admin.py @@ -0,0 +1,8 @@ +from django.contrib import admin +from Messaging.models import * + +# Register your models here. + +admin.site.register(Message) +admin.site.register(Chat) +admin.site.register(Membership) diff --git a/Messaging/apps.py b/Messaging/apps.py new file mode 100644 index 0000000..afdbd63 --- /dev/null +++ b/Messaging/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class MessagingConfig(AppConfig): + default_auto_field = 'django.db.models.BigAutoField' + name = 'Messaging' diff --git a/Messaging/migrations/0001_initial.py b/Messaging/migrations/0001_initial.py new file mode 100644 index 0000000..ad5dd07 --- /dev/null +++ b/Messaging/migrations/0001_initial.py @@ -0,0 +1,50 @@ +# Generated by Django 3.2.4 on 2022-02-17 19:53 + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import django.utils.timezone + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ] + + operations = [ + migrations.CreateModel( + name='Chat', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.TextField()), + ('is_group', models.BooleanField()), + ], + ), + migrations.CreateModel( + name='Message', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('text', models.TextField()), + ('time_sent', models.DateTimeField(default=django.utils.timezone.now)), + ('is_read', models.BooleanField(default=False)), + ('chat', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='Messaging.chat')), + ('sender', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL)), + ], + ), + migrations.CreateModel( + name='Membership', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('chat', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='Messaging.chat')), + ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), + ], + ), + migrations.AddField( + model_name='chat', + name='last_message', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='+', to='Messaging.message'), + ), + ] diff --git a/Messaging/migrations/0002_alter_chat_last_message.py b/Messaging/migrations/0002_alter_chat_last_message.py new file mode 100644 index 0000000..f6679ac --- /dev/null +++ b/Messaging/migrations/0002_alter_chat_last_message.py @@ -0,0 +1,19 @@ +# Generated by Django 3.2.4 on 2022-02-17 20:20 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('Messaging', '0001_initial'), + ] + + operations = [ + migrations.AlterField( + model_name='chat', + name='last_message', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='+', to='Messaging.message'), + ), + ] diff --git a/Messaging/migrations/0003_remove_chat_last_message.py b/Messaging/migrations/0003_remove_chat_last_message.py new file mode 100644 index 0000000..faf83a1 --- /dev/null +++ b/Messaging/migrations/0003_remove_chat_last_message.py @@ -0,0 +1,17 @@ +# Generated by Django 3.2.4 on 2022-02-18 08:37 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('Messaging', '0002_alter_chat_last_message'), + ] + + operations = [ + migrations.RemoveField( + model_name='chat', + name='last_message', + ), + ] diff --git a/Messaging/migrations/0004_chat_last_message.py b/Messaging/migrations/0004_chat_last_message.py new file mode 100644 index 0000000..1827fbd --- /dev/null +++ b/Messaging/migrations/0004_chat_last_message.py @@ -0,0 +1,19 @@ +# Generated by Django 3.2.4 on 2022-02-18 08:43 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('Messaging', '0003_remove_chat_last_message'), + ] + + operations = [ + migrations.AddField( + model_name='chat', + name='last_message', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='Messaging.message'), + ), + ] diff --git a/Messaging/migrations/__init__.py b/Messaging/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/Messaging/models.py b/Messaging/models.py new file mode 100644 index 0000000..44a75ad --- /dev/null +++ b/Messaging/models.py @@ -0,0 +1,22 @@ +from django.contrib.auth.models import User +from django.db import models +from django.utils import timezone + + +class Chat(models.Model): + name = models.TextField() + is_group = models.BooleanField() + last_message = models.ForeignKey("Message", null=True, on_delete=models.SET_NULL, related_name='+') + + +class Membership(models.Model): + user = models.ForeignKey(User, on_delete=models.CASCADE) + chat = models.ForeignKey(Chat, on_delete=models.CASCADE) + + +class Message(models.Model): + chat = models.ForeignKey(Chat, on_delete=models.CASCADE) + sender = models.ForeignKey(User, null=True, on_delete=models.SET_NULL) + text = models.TextField() + time_sent = models.DateTimeField(default=timezone.now) + is_read = models.BooleanField(default=False) diff --git a/Messaging/tests.py b/Messaging/tests.py new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/Messaging/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/Messaging/urls.py b/Messaging/urls.py new file mode 100644 index 0000000..fdbcbdb --- /dev/null +++ b/Messaging/urls.py @@ -0,0 +1,7 @@ +from django.urls import path + +from Messaging import views + +urlpatterns = [ + path("chat_window", views.chat_window), +] diff --git a/Messaging/views.py b/Messaging/views.py new file mode 100644 index 0000000..af1d1b2 --- /dev/null +++ b/Messaging/views.py @@ -0,0 +1,26 @@ +from django.shortcuts import render + +from Messaging.models import Chat, Message, Membership +from SprintLib.BaseView import AccessError + +page_size = 20 + + +def chat_window(request): + chat = None if request.GET['chat_id'] == '-1' else Chat.objects.get(id=request.GET['chat_id']) + if chat is not None: + if Membership.objects.filter(user=request.user, chat=chat).first() is None: + raise AccessError() + page = None if request.GET['page'] == '-1' else int(request.GET['page']) + memberships = Membership.objects.filter(user=request.user).order_by('-chat__last_message__time_sent') + messages = [] + if chat is not None: + offset = page_size * (page - 1) + limit = page_size + Message.objects.filter(chat=chat, is_read=False).update(is_read=True) + messages = Message.objects.filter(chat=chat).order_by('-time_sent')[offset:offset + limit] + return render(request, "chat_window.html", context={ + "memberships": memberships, + "messages": messages, + "current_chat": chat, + }) diff --git a/Sprint/settings.py b/Sprint/settings.py index 2e3f2c9..2f977b5 100644 --- a/Sprint/settings.py +++ b/Sprint/settings.py @@ -44,6 +44,7 @@ INSTALLED_APPS = [ "django.contrib.staticfiles", "Main.apps.MainConfig", "Checker.apps.CheckerConfig", + "Messaging.apps.MessagingConfig", ] MIDDLEWARE = [ diff --git a/Sprint/urls.py b/Sprint/urls.py index b26f9b7..5c6ebe5 100644 --- a/Sprint/urls.py +++ b/Sprint/urls.py @@ -6,7 +6,8 @@ from Main.views import * urlpatterns = [ - path("checker/", include("Checker.urls")) + path("checker/", include("Checker.urls")), + path("messaging/", include("Messaging.urls")), ] for v in dir(Main.views): diff --git a/templates/chat_window.html b/templates/chat_window.html new file mode 100644 index 0000000..cf93e04 --- /dev/null +++ b/templates/chat_window.html @@ -0,0 +1,20 @@ +