apply languages

This commit is contained in:
Egor Matveev 2022-02-20 12:33:19 +03:00
parent a422ab9ad3
commit cdb5157471
18 changed files with 233 additions and 1 deletions

7
Main/views/ChatsView.py Normal file
View File

@ -0,0 +1,7 @@
from SprintLib.BaseView import BaseView
class ChatsView(BaseView):
view_file = "chats.html"
required_login = True
endpoint = "chats"

View File

@ -17,3 +17,4 @@ from Main.views.SolutionsView import SolutionsView
from Main.views.SetView import SetView from Main.views.SetView import SetView
from Main.views.GroupView import GroupView from Main.views.GroupView import GroupView
from Main.views.CheckersView import CheckersView from Main.views.CheckersView import CheckersView
from Main.views.ChatsView import ChatsView

0
Messaging/__init__.py Normal file
View File

8
Messaging/admin.py Normal file
View File

@ -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)

6
Messaging/apps.py Normal file
View File

@ -0,0 +1,6 @@
from django.apps import AppConfig
class MessagingConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'Messaging'

View File

@ -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'),
),
]

View File

@ -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'),
),
]

View File

@ -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',
),
]

View File

@ -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'),
),
]

View File

22
Messaging/models.py Normal file
View File

@ -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)

3
Messaging/tests.py Normal file
View File

@ -0,0 +1,3 @@
from django.test import TestCase
# Create your tests here.

7
Messaging/urls.py Normal file
View File

@ -0,0 +1,7 @@
from django.urls import path
from Messaging import views
urlpatterns = [
path("chat_window", views.chat_window),
]

26
Messaging/views.py Normal file
View File

@ -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,
})

View File

@ -44,6 +44,7 @@ INSTALLED_APPS = [
"django.contrib.staticfiles", "django.contrib.staticfiles",
"Main.apps.MainConfig", "Main.apps.MainConfig",
"Checker.apps.CheckerConfig", "Checker.apps.CheckerConfig",
"Messaging.apps.MessagingConfig",
] ]
MIDDLEWARE = [ MIDDLEWARE = [

View File

@ -6,7 +6,8 @@ from Main.views import *
urlpatterns = [ urlpatterns = [
path("checker/", include("Checker.urls")) path("checker/", include("Checker.urls")),
path("messaging/", include("Messaging.urls")),
] ]
for v in dir(Main.views): for v in dir(Main.views):

View File

@ -0,0 +1,20 @@
<div class="row" style="bottom: 0; height: 90%; position: absolute; top: 5%; left: 10%; right: 10%;">
<div class="col-3" style="overflow-y: scroll;">
<h3>Чаты</h3>
{% for membership in memberships %}
<div {% if membership.chat == current_chat %}style="background-color: #DDDDDD;"{% endif %}>
<hr>
<h4>{{ membership.chat.name }}</h4>
<b>{{ membership.chat.last_message.sender.username }}</b>: {{ membership.chat.last_message.text }} {% if not membership.chat.last_message.is_read %}<i class="fa fa-circle"></i>{% endif %}
<hr>
</div>
{% endfor %}
</div>
<div class="col-9" style="position: relative; align-content: end;">
<div style="position: absolute; bottom: 0; right: 0; left: 0;">
{% for message in messages %}
<b>{{ message.sender.username }}</b>: {{ message.text }}<br>
{% endfor %}
</div>
</div>
</div>

25
templates/chats.html Normal file
View File

@ -0,0 +1,25 @@
{% extends 'base_main.html' %}
{% block scripts %}
var chat_id = 1;
var page = 1;
function doPoll() {
jQuery.get('/messaging/chat_window?chat_id=' + chat_id.toString() + '&page=' + page.toString(), function(data) {
var e = document.getElementById('chats');
e.innerHTML = data;
setTimeout(function() {doPoll()}, 1000);
})
}
{% endblock %}
{% block onload %}doPoll(){% endblock %}
{% block main %}
<div id="chats"></div>
<div class="row">
<div class="col-3"></div>
<div class="col-9" style="position: absolute; bottom: 0;">
<textarea name="text" style="width: 100%; height: 80px; resize: none;"></textarea>
</div>
</div>
{% endblock %}