This commit is contained in:
Andros Fenollosa 2021-11-23 21:41:52 +01:00
parent 2b30e08381
commit 33d0a75775
8 changed files with 189 additions and 22 deletions

View File

@ -1,7 +1,8 @@
import json import json
from channels.generic.websocket import AsyncWebsocketConsumer from channels.generic.websocket import AsyncWebsocketConsumer
from asgiref.sync import sync_to_async 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): class WebsiteConsumer(AsyncWebsocketConsumer):
@ -62,14 +63,6 @@ class WebsiteConsumer(AsyncWebsocketConsumer):
self.room_group_name, {"type": "send_page_profiles"} 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 # About
if data["value"] == "about": if data["value"] == "about":
await self.channel_layer.group_send( await self.channel_layer.group_send(
@ -112,14 +105,6 @@ class WebsiteConsumer(AsyncWebsocketConsumer):
html = await sync_to_async(self._get_profiles)() html = await sync_to_async(self._get_profiles)()
await self.send(text_data=html) 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): def _get_about(self):
return page_about() return page_about()
@ -138,3 +123,69 @@ class WebsiteConsumer(AsyncWebsocketConsumer):
else: else:
html = await sync_to_async(self._get_talks)() html = await sync_to_async(self._get_talks)()
await self.send(text_data=html) 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)

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

View File

@ -75,3 +75,18 @@ class Talk(models.Model):
def __str__(self): def __str__(self):
return self.title 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] + "..."

View File

@ -4,4 +4,5 @@ from . import consumers
websocket_urlpatterns = [ websocket_urlpatterns = [
re_path(r"ws/pages/(?P<room_id>\w+)/$", consumers.WebsiteConsumer), re_path(r"ws/pages/(?P<room_id>\w+)/$", consumers.WebsiteConsumer),
re_path(r"ws/chat/$", consumers.ChatConsumer),
] ]

View File

@ -38,7 +38,7 @@
</li> </li>
<li> <li>
{# To page Chat #} {# 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>
<li> <li>
{# To page About #} {# To page About #}
@ -49,5 +49,8 @@
</header> </header>
<main id="main"></main> <main id="main"></main>
</div> </div>
<section hx-ws="connect:ws:{{ DOMAIN }}/ws/chat/">
<div id="chat" class="hidden"></div>
</section>
</body> </body>
</html> </html>

View File

@ -1,3 +1,63 @@
<main id="main" data-scroll-to-top="true"> {% load slippers %}
soy el chat <div id="chat" data-scroll-to-top="false">
</main> <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>

View File

@ -11,6 +11,7 @@
id="search" id="search"
type="search" type="search"
name="search" name="search"
autocomplete="off"
hx-ws="send" hx-ws="send"
hx-trigger="keyup changed delay:1s" hx-trigger="keyup changed delay:1s"
value="{{ search }}" value="{{ search }}"

View File

@ -2,7 +2,7 @@ from django.shortcuts import render
from django.template.loader import render_to_string from django.template.loader import render_to_string
from random import randint from random import randint
from django.conf import settings from django.conf import settings
from .models import Talk, Profile from .models import Talk, Profile, Message
from asgiref.sync import sync_to_async from asgiref.sync import sync_to_async
@ -67,3 +67,12 @@ def page_results(search):
"search": search, "search": search,
}, },
) )
def page_chat():
return render_to_string(
"pages/chat.html",
{
"messages": Message.objects.order_by("created_at").all(),
},
)