mirror of
https://gitlab.com/animath/si/plateforme.git
synced 2025-06-22 21:18:23 +02:00
@ -4,6 +4,9 @@
|
||||
await Notification.requestPermission()
|
||||
})()
|
||||
|
||||
let channels = {}
|
||||
let selected_channel_id = null
|
||||
|
||||
/**
|
||||
* Display a new notification with the given title and the given body.
|
||||
* @param title The title of the notification
|
||||
@ -18,6 +21,33 @@ function showNotification(title, body, timeout = 5000) {
|
||||
return notif
|
||||
}
|
||||
|
||||
function selectChannel(channel_id) {
|
||||
let channel = channels[channel_id]
|
||||
if (!channel) {
|
||||
console.error('Channel not found:', channel_id)
|
||||
return
|
||||
}
|
||||
|
||||
selected_channel_id = channel_id
|
||||
|
||||
let channelTitle = document.getElementById('channel-title')
|
||||
channelTitle.innerText = channel['name']
|
||||
|
||||
let messageInput = document.getElementById('input-message')
|
||||
messageInput.disabled = !channel['write_access']
|
||||
}
|
||||
|
||||
function setChannels(new_channels) {
|
||||
channels = {}
|
||||
for (let channel of new_channels) {
|
||||
channels[channel['id']] = channel
|
||||
}
|
||||
|
||||
if (new_channels && (!selected_channel_id || !channels[selected_channel_id])) {
|
||||
selectChannel(Object.keys(channels)[0])
|
||||
}
|
||||
}
|
||||
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
/**
|
||||
* Process the received data from the server.
|
||||
@ -25,7 +55,15 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
*/
|
||||
function processMessage(data) {
|
||||
// TODO Implement chat protocol
|
||||
console.log(data)
|
||||
switch (data['type']) {
|
||||
case 'fetch_channels':
|
||||
setChannels(data['channels'])
|
||||
break
|
||||
default:
|
||||
console.log(data)
|
||||
console.error('Unknown message type:', data['type'])
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
function setupSocket(nextDelay = 1000) {
|
||||
|
@ -4,6 +4,64 @@
|
||||
{% load i18n %}
|
||||
|
||||
{% block content %}
|
||||
<noscript>
|
||||
{% trans "JavaScript must be enabled on your browser to access chat." %}
|
||||
</noscript>
|
||||
<div class="offcanvas offcanvas-start" tabindex="-1" id="channelSelector" aria-labelledby="offcanvasExampleLabel">
|
||||
<div class="offcanvas-header">
|
||||
<h4 class="offcanvas-title" id="offcanvasExampleLabel">{% trans "Chat channels" %}</h4>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="offcanvas" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="offcanvas-body">
|
||||
<ul class="list-group list-group-flush" id="nav-channels-tab">
|
||||
{% for channel in channels %}
|
||||
<li class="list-group-item" id="tab-channel-{{ channel.id }}" data-bs-dismiss="offcanvas"
|
||||
onclick="selectChannel({{ channel.id }})">
|
||||
<button class="nav-link">{{ channel.name }}</button>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card tab-content w-100 mh-100" style="height: 95vh" id="nav-channels-content">
|
||||
<div class="card-header">
|
||||
<h3>
|
||||
<button class="navbar-toggler" type="button" data-bs-toggle="offcanvas" data-bs-target="#channelSelector"
|
||||
aria-controls="channelSelector" aria-expanded="false" aria-label="Toggle channel selector">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
<span id="channel-title"></span>
|
||||
</h3>
|
||||
</div>
|
||||
<div class="card-body overflow-y-scroll mw-100 h-100 flex-grow-0" id="chat-messages">
|
||||
<ul class="list-group list-group-flush">
|
||||
<li class="list-group-item">
|
||||
<div class="fw-bold">Emmy D'Anello (CNO)</div>
|
||||
Message 1
|
||||
</li>
|
||||
<li class="list-group-item">
|
||||
<div class="fw-bold">Emmy D'Anello (CNO)</div>
|
||||
Message 2
|
||||
</li>
|
||||
<li class="list-group-item">
|
||||
<div class="fw-bold">Emmy D'Anello (CNO)</div>
|
||||
Message 3
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="card-footer mt-auto">
|
||||
<div class="input-group">
|
||||
<label for="input-message" class="input-group-text">
|
||||
<i class="fas fa-comment"></i>
|
||||
</label>
|
||||
<input type="text" class="form-control" id="input-message" placeholder="{% trans "Send message…" %}" autocomplete="off">
|
||||
<button class="input-group-text btn btn-success">
|
||||
<i class="fas fa-paper-plane"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block extrajavascript %}
|
||||
|
@ -4,6 +4,8 @@
|
||||
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||
from django.views.generic import TemplateView
|
||||
|
||||
from chat.models import Channel
|
||||
|
||||
|
||||
class ChatView(LoginRequiredMixin, TemplateView):
|
||||
"""
|
||||
@ -11,3 +13,9 @@ class ChatView(LoginRequiredMixin, TemplateView):
|
||||
with Javascript and websockets.
|
||||
"""
|
||||
template_name = "chat/chat.html"
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
from asgiref.sync import async_to_sync
|
||||
context['channels'] = async_to_sync(Channel.get_accessible_channels)(self.request.user, 'read')
|
||||
return context
|
||||
|
Reference in New Issue
Block a user