almost chatbox

This commit is contained in:
cuom1999 2020-03-20 22:48:04 -06:00
parent dd34f474a5
commit 92d94af520
7 changed files with 107 additions and 40 deletions

View file

@ -2,6 +2,9 @@ import json
from channels.generic.websocket import AsyncWebsocketConsumer from channels.generic.websocket import AsyncWebsocketConsumer
from .models import Message from .models import Message
from .views import format_time from .views import format_time
from django.urls import reverse
from django.http import HttpResponse, HttpResponseRedirect
from judge.models.profile import Profile from judge.models.profile import Profile
@ -14,7 +17,7 @@ class ChatConsumer(AsyncWebsocketConsumer):
# Join room group # Join room group
await self.channel_layer.group_add( await self.channel_layer.group_add(
self.room_group_name, self.room_group_name,
self.channel_name self.channel_name,
) )
await self.accept() await self.accept()
@ -23,7 +26,7 @@ class ChatConsumer(AsyncWebsocketConsumer):
# Leave room group # Leave room group
await self.channel_layer.group_discard( await self.channel_layer.group_discard(
self.room_group_name, self.room_group_name,
self.channel_name self.channel_name,
) )
# Receive message from WebSocket # Receive message from WebSocket
@ -58,6 +61,5 @@ def save_data_and_get_time(message):
.get(id=message['author_id']), .get(id=message['author_id']),
) )
new_message.save() new_message.save()
HttpResponseRedirect(reverse('chat'))
return new_message.time return new_message.time

View file

@ -1,25 +1,50 @@
from django.utils.translation import gettext as _ from django.utils.translation import gettext as _
from django.views.generic import ListView from django.views.generic import ListView
from django.http import HttpResponse, HttpResponseRedirect
from django.shortcuts import render
from django.core.paginator import Paginator
from django.urls import reverse
from judge.jinja2.gravatar import gravatar
from .models import Message from .models import Message
import json
def format_time(time): def format_time(time):
return time.strftime('%H:%M %p %d-%m-%Y') return time.strftime('%H:%M %p %d-%m-%Y')
def format_messages(messages):
msg_list = [{
'time': format_time(msg.time),
'author': str(msg.author),
'body': msg.body,
'image': gravatar(msg.author, 32),
} for msg in messages]
return json.dumps(msg_list)
class ChatView(ListView): class ChatView(ListView):
model = Message model = Message
context_object_name = 'message' context_object_name = 'message'
template_name = 'chat/chat.html' template_name = 'chat/chat.html'
title = _('Chat Box') title = _('Chat Box')
paginate_by = 50 paginate_by = 50
paginator = Paginator(Message.objects.all(), paginate_by)
def get(self, request, *args, **kwargs):
page = request.GET.get('page')
if (page == None):
return super().get(request, *args, **kwargs)
cur_page = self.paginator.get_page(page)
return HttpResponse(format_messages(cur_page.object_list))
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs) context = super().get_context_data(**kwargs)
context['title'] = self.title context['title'] = self.title
for msg in context['message']: for msg in context['message']:
msg.time = format_time(msg.time) msg.time = format_time(msg.time)
return context return context

View file

@ -4,7 +4,7 @@ from django.conf.urls import include, url
from django.contrib import admin from django.contrib import admin
from django.contrib.auth import views as auth_views from django.contrib.auth import views as auth_views
from django.contrib.sitemaps.views import sitemap from django.contrib.sitemaps.views import sitemap
from django.http import Http404, HttpResponsePermanentRedirect from django.http import Http404, HttpResponsePermanentRedirect, HttpResponseRedirect
from django.templatetags.static import static from django.templatetags.static import static
from django.urls import reverse from django.urls import reverse
from django.utils.functional import lazystr from django.utils.functional import lazystr
@ -369,7 +369,9 @@ urlpatterns = [
url(r'^custom_checker_sample/', about.custom_checker_sample, name='custom_checker_sample'), url(r'^custom_checker_sample/', about.custom_checker_sample, name='custom_checker_sample'),
url(r'^chat/', include([ url(r'^chat/', include([
url(r'^$', login_required(ChatView.as_view()), name='chat'), url(r'^$',
login_required(ChatView.as_view()),
name='chat'),
])), ])),
] ]

View file

@ -219,11 +219,11 @@ header {
#nav-shadow { #nav-shadow {
height: 2px; height: 2px;
background: linear-gradient(#63c8f9, transparent); background: linear-gradient(#7dc7ff, transparent);
} }
#nav-container { #nav-container {
background: linear-gradient(#c1e9fd, #63c8f9); background: #7dc7ff;
// opacity: 0.77; // opacity: 0.77;
// filter: alpha(opacity=77) // filter: alpha(opacity=77)

View file

@ -7,6 +7,7 @@
overflow-wrap: break-word; overflow-wrap: break-word;
overflow-y: scroll; overflow-y: scroll;
} }
#loader { #loader {
display: block; display: block;
margin-left: auto; margin-left: auto;
@ -16,6 +17,7 @@
#chat-log { #chat-log {
padding: 0; padding: 0;
padding-top: 2em;
width: 100%; width: 100%;
} }
@ -61,8 +63,9 @@
.clear { .clear {
clear: both; clear: both;
} }
.message { .content-message {
word-wrap: break-word; word-wrap: break-word;
white-space: pre-line;
} }

View file

@ -305,8 +305,8 @@ ul.pagination {
.active-page > { .active-page > {
a { a {
z-index: 2; z-index: 2;
color: #FFF; color: black;
background-color: $highlight_blue; background-color: #7dc7ff;
border-color: transparent; border-color: transparent;
cursor: default; cursor: default;
} }

View file

@ -7,6 +7,8 @@
</script> </script>
<script type="text/javascript"> <script type="text/javascript">
$(function() { $(function() {
let currentPage = 1;
$('#loader').hide(); $('#loader').hide();
chatSocket.onmessage = function(e) { chatSocket.onmessage = function(e) {
@ -15,53 +17,87 @@
loadMessage(data['body'], loadMessage(data['body'],
data['author'], data['author'],
data['time'], data['time'],
data['image']) data['image'],
true)
$('#chat-box').scrollTop($('#chat-box')[0].scrollHeight);
}; };
function encodeHTML(content) {
return content.replace(/[\u00A0-\u9999<>\&]/gim, function(i) {
return '&#'+i.charCodeAt(0)+';';
});
}
function loadMessage(content, user, time, image) { function loadMessage(content, user, time, image, isNew) {
li = `<li class="infinite-item"> if (isNew) content = encodeHTML(content)
li = `<li class="message">
<img src="${image}" class="profile-pic"> <img src="${image}" class="profile-pic">
<div class="body-message"> <div class="body-message">
<div class="user-time"> <div class="user-time">
<a href="#" class="user"> <a href="{{ url('user_page') }}/${user}" class="user">
${user} ${user}
</a> </a>
<span class="time">${time}</span> <span class="time">${time}</span>
</div> </div>
<span class="message"> <span class="content-message">${content} </span>
<span>${content}</span>
</span>
</div> </div>
<div class="clear"></div> <div class="clear"></div>
</li>` </li>`
ul = $('#chat-log') ul = $('#chat-log')
ul.append(li) if (isNew) {
$('#chat-box').scrollTop($('#chat-box')[0].scrollHeight); ul.append(li)
}
else {
ul.prepend(li)
}
} }
(function init_chatlog() { (function init_chatlog() {
ul = $('#chat-log') ul = $('#chat-log')
{% for msg in message|reverse %} {% for msg in message %}
loadMessage('{{msg.body}}', '{{msg.author}}', '{{msg.time}}', '{{gravatar(msg.author, 32)}}') loadMessage(`{{msg.body}}`, `{{msg.author}}`, `{{msg.time}}`, `{{gravatar(msg.author, 32)}}`)
{% endfor %} {% endfor %}
$('#chat-box').scrollTop($('#chat-box')[0].scrollHeight);
})() })()
$('#chat-box').scroll(function() { function scrollTopOfBottom(container) {
if ($('#chat-box').scrollTop() == 0) { return container[0].scrollHeight - container.innerHeight()
console.log('Hi') }
$('#loader').show()
}
})
// var infinite = new Waypoint.Infinite({
// element: $('.infinite-container')[0],
// onBeforePageLoad: function () {
// $('.loading').show();
// },
// onAfterPageLoad: function ($items) {
// $('.loading').hide();
// }
// });
function scrollContainer(container, loader) {
container.scroll(function() {
if (container.scrollTop() == 0) {
if (currentPage < {{paginator.num_pages}}) {
currentPage++;
loader.show();
$.ajax({
url: `{{request.path}}?page=${currentPage}`,
success: function(data) {
let lastMsg = $('.message:first')
let lastMsgPos = scrollTopOfBottom(container)
data = JSON.parse(data)
setTimeout( () => {
for (msg of data) {
loadMessage(msg.body, msg.author, msg.time, msg.image)
}
loader.hide()
// scroll to last msg
container.scrollTop(
scrollTopOfBottom(container) - lastMsgPos
)
}, 500)
}
})
}
}
})}
scrollContainer($('#chat-box'), $('#loader'))
$("#chat-submit").click(function() { $("#chat-submit").click(function() {
if ($("#chat-input").val().trim()) { if ($("#chat-input").val().trim()) {
let body = $('#chat-input').val().trim(); let body = $('#chat-input').val().trim();
@ -74,7 +110,6 @@
'author_id': {{request.profile.id}}, 'author_id': {{request.profile.id}},
} }
// $.post("send/", message)
chatSocket.send(JSON.stringify({ chatSocket.send(JSON.stringify({
'message': message 'message': message
})); }));
@ -126,7 +161,7 @@
<div id="chat-area"> <div id="chat-area">
<div id="chat-box"> <div id="chat-box">
<img src="http://opengraphicdesign.com/wp-content/uploads/2009/01/loader64.gif" id="loader"> <img src="http://opengraphicdesign.com/wp-content/uploads/2009/01/loader64.gif" id="loader">
<ul id="chat-log" class="infinite-container waypoint"> <ul id="chat-log">
</ul> </ul>
</div> </div>
{{_('Your message')}} {{_('Your message')}}