284 lines
10 KiB
HTML
284 lines
10 KiB
HTML
{% extends "base.html" %}
|
|
{% block title_row %}{% endblock %}
|
|
{% block title_ruler %}{% endblock %}
|
|
{% block title %} {{_('Chat Box')}} {% endblock %}
|
|
{% block js_media %}
|
|
|
|
<script type="text/javascript">
|
|
// change ws to wss if using HTTPS
|
|
var chatSocket = new WebSocket( "{{ws_address}}" );
|
|
</script>
|
|
<script type="text/javascript" src="{{ static('mathjax_config.js') }}"></script>
|
|
<script type="text/javascript"
|
|
src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/MathJax.js?config=TeX-AMS_HTML"></script>
|
|
<script type="text/javascript">
|
|
$(function() {
|
|
let currentPage = 1;
|
|
|
|
$('#loader').hide();
|
|
|
|
chatSocket.onmessage = function(e) {
|
|
let data = JSON.parse(e.data);
|
|
data = data['message'];
|
|
loadMessage(data['body'],
|
|
data['author'],
|
|
data['time'],
|
|
data['id'],
|
|
data['image'],
|
|
data['css_class'],
|
|
true);
|
|
// console.log(data);
|
|
$('#chat-box').scrollTop($('#chat-box')[0].scrollHeight);
|
|
};
|
|
|
|
function encodeHTML(content) {
|
|
return content.replace(/[\u00A0-\u9999<>\&]/gim, function(i) {
|
|
return '&#'+i.charCodeAt(0)+';';
|
|
});
|
|
}
|
|
const datesAreOnSameDay = (first, second) =>
|
|
first.getFullYear() === second.getFullYear() &&
|
|
first.getMonth() === second.getMonth() &&
|
|
first.getDate() === second.getDate();
|
|
|
|
function loadMessage(content, user, time, messid, image, css_class, isNew) {
|
|
// if (isNew) content = encodeHTML(content)
|
|
time = new Date(time);
|
|
if (datesAreOnSameDay(time, new Date())) {
|
|
time = moment(time).format("HH:mm");
|
|
}
|
|
else {
|
|
time = moment(time).format("HH:mm DD-MM-YYYY");
|
|
}
|
|
content = encodeHTML(content);
|
|
li = `<li class="message">
|
|
<img src="${image}" class="profile-pic">
|
|
<div class="body-message">
|
|
<div class="user-time">
|
|
<span class="${css_class}">
|
|
<a href="{{ url('user_page') }}/${user}">
|
|
${user}
|
|
</a>
|
|
</span>
|
|
<span class="time">${time}</span>
|
|
{% if request.user.is_staff %}
|
|
<a class="chatbtn_remove_mess" style="color:red; cursor: pointer;" data-messtime="${time}" data-author="${user}" data-messid="${messid}">Delete</a>
|
|
{% endif %}
|
|
</div>
|
|
<span class="content-message">${content} </span>
|
|
</div>
|
|
<div class="clear"></div>
|
|
</li>`
|
|
ul = $('#chat-log')
|
|
if (isNew) {
|
|
ul.append(li)
|
|
}
|
|
else {
|
|
ul.prepend(li)
|
|
}
|
|
MathJax.Hub.Queue(["Typeset",MathJax.Hub]);
|
|
}
|
|
|
|
(function init_chatlog() {
|
|
ul = $('#chat-log')
|
|
{% autoescape on %}
|
|
{% for msg in message %}
|
|
loadMessage("{{msg.body|safe|escapejs}}", `{{msg.author}}`, `{{msg.time}}`, `{{msg.id}}`, `{{gravatar(msg.author, 32)}}`,`{{msg.author.css_class}}`);
|
|
{% endfor %}
|
|
{% endautoescape %}
|
|
$('#chat-box').scrollTop($('#chat-box')[0].scrollHeight);
|
|
})()
|
|
|
|
function scrollTopOfBottom(container) {
|
|
return container[0].scrollHeight - container.innerHeight()
|
|
}
|
|
|
|
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.id, msg.image, msg.css_class)
|
|
}
|
|
|
|
loader.hide()
|
|
|
|
// scroll to last msg
|
|
container.scrollTop(
|
|
scrollTopOfBottom(container) - lastMsgPos
|
|
)
|
|
}, 500)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
})}
|
|
|
|
scrollContainer($('#chat-box'), $('#loader'))
|
|
|
|
{% if request.user.is_staff %}
|
|
$(document).on("click", ".chatbtn_remove_mess", function() {
|
|
var elt = $(this);
|
|
$.ajax({
|
|
url: 'delete/',
|
|
type: 'post',
|
|
data: elt.data(),
|
|
dataType: 'json',
|
|
success: function(data){
|
|
console.log('delete ajax call success!');
|
|
location.reload();
|
|
}
|
|
});
|
|
});
|
|
{% endif %}
|
|
|
|
$("#chat-submit").click(function() {
|
|
if ($("#chat-input").val().trim()) {
|
|
let body = $('#chat-input').val().trim();
|
|
let img = '{{ gravatar(request.user, 32) }}'
|
|
|
|
message = {
|
|
'body': body,
|
|
}
|
|
|
|
chatSocket.send(JSON.stringify({
|
|
'message': message
|
|
}));
|
|
|
|
$('#chat-input').val('').focus();
|
|
}
|
|
});
|
|
|
|
chatSocket.onclose = function(e) {
|
|
console.error('Chat socket closed unexpectedly');
|
|
};
|
|
|
|
$("#chat-log").change(function() {
|
|
$('#chat-log').scrollTop($('#chat-log')[0].scrollHeight);
|
|
});
|
|
|
|
$('#chat-input').focus();
|
|
|
|
$('#chat-input').keydown(function(e) {
|
|
if (e.keyCode === 13) {
|
|
if (e.ctrlKey || e.shiftKey) {
|
|
var val = this.value;
|
|
if (typeof this.selectionStart == "number" && typeof this.selectionEnd == "number") {
|
|
var start = this.selectionStart;
|
|
this.value = val.slice(0, start) + "\n" + val.slice(this.selectionEnd);
|
|
this.selectionStart = this.selectionEnd = start + 1;
|
|
} else if (document.selection && document.selection.createRange) {
|
|
this.focus();
|
|
var range = document.selection.createRange();
|
|
range.text = "\r\n";
|
|
range.collapse(false);
|
|
range.select();
|
|
}
|
|
}
|
|
else {
|
|
e.preventDefault();
|
|
$('#chat-submit').click();
|
|
}
|
|
return false
|
|
}
|
|
return true
|
|
});
|
|
|
|
});
|
|
|
|
$(document).ready(function () {
|
|
$('.chat-right-panel').hide();
|
|
$('#chat-tab').find('a').click(function (e) {
|
|
e.preventDefault();
|
|
$('#chat-tab').addClass('active');
|
|
$('#online-tab').removeClass('active');
|
|
$('.chat-left-panel').show();
|
|
$('.chat-right-panel').hide();
|
|
});
|
|
$('#online-tab').find('a').click(function (e) {
|
|
e.preventDefault();
|
|
$('#online-tab').addClass('active');
|
|
$('#chat-tab').removeClass('active');
|
|
$('.chat-left-panel').hide();
|
|
$('.chat-right-panel').show();
|
|
});
|
|
});
|
|
</script>
|
|
|
|
{% endblock js_media %}
|
|
|
|
{% block media %}
|
|
<style>
|
|
#content {
|
|
margin-top: -0.5em;
|
|
}
|
|
</style>
|
|
{% endblock media %}
|
|
|
|
{% block body %}
|
|
{% csrf_token %}
|
|
{% block before_posts %}{% endblock %}
|
|
<div id="mobile" class="tabs">
|
|
<ul>
|
|
<li id="chat-tab" class="tab active"><a href="#">
|
|
<i class="tab-icon fa fa-comments"></i> {{ _('Chat') }}
|
|
</a></li>
|
|
<li id="online-tab" class="tab"><a href="#"><i class="tab-icon fa fa-wifi"></i> {{ _('Online Users') }}</a></li>
|
|
</ul>
|
|
</div>
|
|
|
|
<div id="chat-container">
|
|
<div id="chat-area" class="chat-left-panel">
|
|
<div id="chat-box">
|
|
<img src="http://opengraphicdesign.com/wp-content/uploads/2009/01/loader64.gif" id="loader">
|
|
<ul id="chat-log">
|
|
</ul>
|
|
</div>
|
|
<textarea id="chat-input" placeholder="{{_('Enter your message')}}"></textarea>
|
|
</div>
|
|
<button id="chat-submit" style="display:none;"> Send </button>
|
|
<div id="chat-online" class="chat-right-panel sidebox">
|
|
<h3>
|
|
{{_('Online Users')}}
|
|
<i class="fa fa-wifi"></i>
|
|
</h3>
|
|
<ul id="chat-online-content">
|
|
<h4>{{_('Admins')}}: </h4>
|
|
<hr/>
|
|
{% for user in admin_status %}
|
|
<li style="padding-left: 1em">
|
|
{% if user.is_online %}
|
|
<span class="green-dot"></span>
|
|
{% else %}
|
|
<span class="red-dot"></span>
|
|
{% endif %}
|
|
<span style="padding-left:0.25em">
|
|
{{ link_user(user.user) }}
|
|
</span>
|
|
</li>
|
|
{% endfor %}
|
|
<h4 style="margin-top:1em;">{{_('Users')}}: </h4>
|
|
<hr/>
|
|
{% for user in online_users %}
|
|
<li style="padding-left: 1em">
|
|
<span class="green-dot"></span>
|
|
<span style="padding-left:0.25em">
|
|
{{ link_user(user.user) }}
|
|
</span>
|
|
</li>
|
|
{% endfor %}
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
|
|
{% endblock body %}
|