Add chat
This commit is contained in:
parent
2b30e08381
commit
33d0a75775
@ -1,7 +1,8 @@
|
||||
import json
|
||||
from channels.generic.websocket import AsyncWebsocketConsumer
|
||||
from asgiref.sync import sync_to_async
|
||||
from .views import page_talks, page_about, page_single_talk, page_results, page_profiles
|
||||
from .views import page_talks, page_about, page_single_talk, page_results, page_profiles, page_chat
|
||||
from .models import Message
|
||||
|
||||
|
||||
class WebsiteConsumer(AsyncWebsocketConsumer):
|
||||
@ -62,14 +63,6 @@ class WebsiteConsumer(AsyncWebsocketConsumer):
|
||||
self.room_group_name, {"type": "send_page_profiles"}
|
||||
)
|
||||
|
||||
# Chat
|
||||
if data["value"] == "chat":
|
||||
await self.channel_layer.group_send(
|
||||
self.room_group_name, {
|
||||
"type": "send_page_chat",
|
||||
}
|
||||
)
|
||||
|
||||
# About
|
||||
if data["value"] == "about":
|
||||
await self.channel_layer.group_send(
|
||||
@ -112,14 +105,6 @@ class WebsiteConsumer(AsyncWebsocketConsumer):
|
||||
html = await sync_to_async(self._get_profiles)()
|
||||
await self.send(text_data=html)
|
||||
|
||||
def _get_chat(self):
|
||||
return page_chat()
|
||||
|
||||
async def send_page_chat(self, event):
|
||||
"""Send Chat page"""
|
||||
html = await sync_to_async(self._get_chat)()
|
||||
await self.send(text_data=html)
|
||||
|
||||
def _get_about(self):
|
||||
return page_about()
|
||||
|
||||
@ -138,3 +123,69 @@ class WebsiteConsumer(AsyncWebsocketConsumer):
|
||||
else:
|
||||
html = await sync_to_async(self._get_talks)()
|
||||
await self.send(text_data=html)
|
||||
|
||||
|
||||
class ChatConsumer(AsyncWebsocketConsumer):
|
||||
|
||||
async def connect(self):
|
||||
|
||||
# Room
|
||||
self.room_name = "general"
|
||||
# Group for Redis
|
||||
self.room_group_name = f"chat_{self.room_name}"
|
||||
|
||||
# Join room group
|
||||
await self.channel_layer.group_add(self.room_group_name, self.channel_name)
|
||||
|
||||
await self.accept()
|
||||
|
||||
# Send chat page
|
||||
await self.channel_layer.group_send(
|
||||
self.room_group_name,
|
||||
{
|
||||
"type": "send_page_chat",
|
||||
},
|
||||
)
|
||||
|
||||
async def disconnect(self, close_code):
|
||||
# Leave room group
|
||||
await self.channel_layer.group_discard(self.room_group_name, self.channel_name)
|
||||
|
||||
# Receive message from WebSocket
|
||||
async def receive(self, text_data):
|
||||
|
||||
# Get data
|
||||
text_data_json = json.loads(text_data)
|
||||
new_username = text_data_json["new-username"]
|
||||
new_text = text_data_json["new-text"]
|
||||
|
||||
# Save message
|
||||
await self.save_message(new_username, new_text)
|
||||
|
||||
# Send new HTML
|
||||
await self.channel_layer.group_send(
|
||||
self.room_group_name,
|
||||
{
|
||||
"type": "send_page_chat",
|
||||
},
|
||||
)
|
||||
|
||||
@sync_to_async
|
||||
def instance_message(self, username, text):
|
||||
return Message.objects.create(
|
||||
username=username,
|
||||
text=text,
|
||||
)
|
||||
|
||||
async def save_message(self, username, text):
|
||||
return await self.instance_message(username, text)
|
||||
|
||||
# Pages
|
||||
|
||||
def _get_chat(self):
|
||||
return page_chat()
|
||||
|
||||
async def send_page_chat(self, event):
|
||||
"""Send Home page"""
|
||||
html = await sync_to_async(self._get_chat)()
|
||||
await self.send(text_data=html)
|
27
app/website/migrations/0006_message.py
Normal file
27
app/website/migrations/0006_message.py
Normal file
@ -0,0 +1,27 @@
|
||||
# Generated by Django 3.2.9 on 2021-11-23 18:31
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('website', '0005_auto_20211121_0757'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='Message',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('username', models.CharField(default='', max_length=100, verbose_name='Alias')),
|
||||
('text', models.TextField(max_length=500)),
|
||||
('created_at', models.DateTimeField(auto_now_add=True)),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'Message',
|
||||
'verbose_name_plural': 'Messages',
|
||||
'ordering': ('-created_at',),
|
||||
},
|
||||
),
|
||||
]
|
@ -75,3 +75,18 @@ class Talk(models.Model):
|
||||
|
||||
def __str__(self):
|
||||
return self.title
|
||||
|
||||
|
||||
class Message(models.Model):
|
||||
|
||||
username = models.CharField(max_length=100, verbose_name="Alias", default="")
|
||||
text = models.TextField(max_length=500)
|
||||
created_at = models.DateTimeField(auto_now_add=True)
|
||||
|
||||
class Meta:
|
||||
ordering = ("-created_at",)
|
||||
verbose_name = "Message"
|
||||
verbose_name_plural = "Messages"
|
||||
|
||||
def __str__(self):
|
||||
return self.text[:10] + "..."
|
@ -4,4 +4,5 @@ from . import consumers
|
||||
|
||||
websocket_urlpatterns = [
|
||||
re_path(r"ws/pages/(?P<room_id>\w+)/$", consumers.WebsiteConsumer),
|
||||
re_path(r"ws/chat/$", consumers.ChatConsumer),
|
||||
]
|
||||
|
@ -38,7 +38,7 @@
|
||||
</li>
|
||||
<li>
|
||||
{# To page Chat #}
|
||||
{% #link action="page" value="chat" scroll-up="true" %}Chat{% /link %}
|
||||
<a href="#" onclick="document.querySelector('#chat').classList.toggle('hidden')">Chat</a>
|
||||
</li>
|
||||
<li>
|
||||
{# To page About #}
|
||||
@ -49,5 +49,8 @@
|
||||
</header>
|
||||
<main id="main"></main>
|
||||
</div>
|
||||
<section hx-ws="connect:ws:{{ DOMAIN }}/ws/chat/">
|
||||
<div id="chat" class="hidden"></div>
|
||||
</section>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -1,3 +1,63 @@
|
||||
<main id="main" data-scroll-to-top="true">
|
||||
soy el chat
|
||||
</main>
|
||||
{% load slippers %}
|
||||
<div id="chat" data-scroll-to-top="false">
|
||||
<style>
|
||||
#chat {
|
||||
position: fixed;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
width: 17rem;
|
||||
height: 35rem;
|
||||
border: 1px solid;
|
||||
padding: 1rem;
|
||||
background-color: var(--background-color);
|
||||
margin: 0;
|
||||
transition: .5s
|
||||
}
|
||||
|
||||
.hidden {
|
||||
left: -17rem !important;
|
||||
}
|
||||
|
||||
.messages {
|
||||
height: 10rem;
|
||||
overflow-y: scroll;
|
||||
border: 1px solid;
|
||||
}
|
||||
|
||||
</style>
|
||||
<h1>Chat</h1>
|
||||
<div class="messages" data-scroll-to-bottom="true">
|
||||
<table>
|
||||
<tbody>
|
||||
{% for message in messages %}
|
||||
<tr>
|
||||
<th>{{ message.username }}</th>
|
||||
<td>{{ message.text }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<form>
|
||||
<input type="hidden" name="action" value="new-message">
|
||||
<label>
|
||||
<span>Username:</span>
|
||||
<input
|
||||
id="new-username"
|
||||
type="text"
|
||||
name="new-username"
|
||||
value=""
|
||||
>
|
||||
</label>
|
||||
<label>
|
||||
<span>Message:</span>
|
||||
<input
|
||||
id="new-text"
|
||||
type="text"
|
||||
name="new-text"
|
||||
value=""
|
||||
>
|
||||
</label>
|
||||
<input type="button" hx-ws="send" hx-trigger="click" value="Send">
|
||||
</form>
|
||||
</div>
|
||||
|
@ -11,6 +11,7 @@
|
||||
id="search"
|
||||
type="search"
|
||||
name="search"
|
||||
autocomplete="off"
|
||||
hx-ws="send"
|
||||
hx-trigger="keyup changed delay:1s"
|
||||
value="{{ search }}"
|
||||
|
@ -2,7 +2,7 @@ from django.shortcuts import render
|
||||
from django.template.loader import render_to_string
|
||||
from random import randint
|
||||
from django.conf import settings
|
||||
from .models import Talk, Profile
|
||||
from .models import Talk, Profile, Message
|
||||
from asgiref.sync import sync_to_async
|
||||
|
||||
|
||||
@ -67,3 +67,12 @@ def page_results(search):
|
||||
"search": search,
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
def page_chat():
|
||||
return render_to_string(
|
||||
"pages/chat.html",
|
||||
{
|
||||
"messages": Message.objects.order_by("created_at").all(),
|
||||
},
|
||||
)
|
Loading…
Reference in New Issue
Block a user