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

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):
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 = [
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>
{# 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>

View File

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

View File

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

View File

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