]> git.parisson.com Git - teleforma.git/commitdiff
Uncommited changes from Yoan
authorGael Le Mignot <gael@pilotsystems.net>
Thu, 16 Jun 2022 08:08:37 +0000 (10:08 +0200)
committerGael Le Mignot <gael@pilotsystems.net>
Thu, 16 Jun 2022 08:08:37 +0000 (10:08 +0200)
teleforma/models/chat.py
teleforma/models/notification.py [new file with mode: 0644]
teleforma/src/js/components/Notification.vue [new file with mode: 0644]
teleforma/src/js/main.ts
teleforma/templates/teleforma/base.html
teleforma/ws/notification.py [new file with mode: 0644]
teleforma/ws/routing.py

index 53c804b451dfaaf5afcc28116a0e89bb1b0459b9..ac52266bbd1a831437daf096204217aea3c7f24e 100644 (file)
@@ -65,8 +65,6 @@ class ChatMessage(models.Model):
             'content': self.message,
             'senderId': self.user and self.user.id or "system",
             'username': self.user and self.user.username or "Système",
-            'date': '13 November',
-            'timestamp': '10:20',
             'date': self.created.strftime('%d/%m/%Y'),
             'timestamp': self.created.strftime('%H:%M'),
             'system': self.system
diff --git a/teleforma/models/notification.py b/teleforma/models/notification.py
new file mode 100644 (file)
index 0000000..126382f
--- /dev/null
@@ -0,0 +1,56 @@
+
+from datetime import datetime, timedelta
+from django.contrib.auth.models import User
+from django.contrib.sites.models import Site
+from django.db import models
+from django.urls.base import reverse
+from django.utils.translation import ugettext_lazy as _
+
+from ..models import MetaCore
+from ..models.core import app_label
+from channels.layers import get_channel_layer
+from asgiref.sync import async_to_sync
+
+def in_one_week():
+    return datetime.utcnow() + timedelta(days=1)
+
+class Notification(models.Model):
+    """A notification message"""
+
+    message = models.CharField('Message', max_length=255)
+    url = models.CharField('Url', max_length=255)
+    user = models.ForeignKey(
+        User, related_name='notifications', verbose_name=_('user'), on_delete=models.CASCADE)
+    created = models.DateTimeField('Creation date', auto_now_add=True)
+    expired = models.DateTimeField("Date d'expiration", default=in_one_week)
+
+    class Meta(MetaCore):
+        db_table = app_label + '_' + 'notifications'
+
+    def __str__(self):
+        return f"{str(self.user)} - {self.message[:20]}"
+
+    @classmethod
+    def create(cls, user, room_name, message, system=False):
+        notification = Notification(user=user, message=message,
+                              room_name=room_name, system=system)
+        notification.save()
+        return notification.to_dict()
+    
+    def broadcast(self):
+        """
+        broadcast a notification to socket
+        """
+        channel_layer = get_channel_layer()
+        async_to_sync(channel_layer.send)(f"usernotification_{self.user.id}", {
+            'type': 'notification',
+            'message': self.to_dict()
+        })
+
+    def to_dict(self):
+        return {
+            '_id': self.id,
+            'content': self.message,
+            'url': self.url,
+            'date': self.created.strftime('%d/%m/%Y'),
+        }
diff --git a/teleforma/src/js/components/Notification.vue b/teleforma/src/js/components/Notification.vue
new file mode 100644 (file)
index 0000000..7fda57e
--- /dev/null
@@ -0,0 +1,56 @@
+<template>
+  Notification
+</template>
+
+<script lang="ts">
+import { Component, Vue } from "vue-property-decorator"
+
+@Component({
+})
+export default class Notification extends Vue {
+  socket: WebSocket | null = null
+  messagesLoaded = false
+  messages: Messages = []
+  currentUserId: number | null = null
+
+  created() {
+    // get room info
+    const userId = document.getElementById("user_id")
+    this.connect(roomInfo.room_name)
+    this.currentUserId = userId
+  }
+
+  connect(roomName: string) {
+    // connect to socket
+    let protocol = "wss"
+    if (window.location.protocol != "https:") protocol = "ws"
+    this.socket = new WebSocket(protocol + "://" + window.location.host + "/ws/notification/" + this.currentUserId + "/")
+    this.fetchMessages()
+
+    this.socket.onclose = () => {
+      console.log("Chat socket closed")
+    }
+  }
+
+  async fetchMessages() {
+    this.socket!.onmessage = (e) => {
+      const data = JSON.parse(e.data)
+      const type = data.type
+      // do not load messages in case of socket reconnect
+      if (type == "initial" && this.messagesLoaded) return
+      const newMessages = data.messages as Message[]
+      this.messages = [...this.messages, ...newMessages]
+      if (type == "initial") this.messagesLoaded = true
+    }
+  }
+}
+</script>
+
+<style>
+.vac-message-wrapper .vac-offset-current {
+  margin-left: 15%;
+}
+.vac-message-wrapper .vac-message-box {
+  max-width: 80%;
+}
+</style>
index 2fbd41647abcd8a6c03691075db631e835ff6d98..d75b08b57161261c7ac4714daa2858e273f205e9 100644 (file)
@@ -1,6 +1,7 @@
 import "./compatibility"
 import Vue from "vue"
 import Chat from "./components/Chat.vue"
+import Notification from "./components/Notification.vue"
 
 Vue.config.productionTip = false
 
@@ -9,3 +10,10 @@ if (document.getElementById("chat")) {
     render: (h) => h(Chat)
   }).$mount("#chat")
 }
+
+
+if (document.getElementById("notification")) {
+  new Vue({
+    render: (h) => h(Notification)
+  }).$mount("#notification")
+}
index 80dd0aae6da2f9c5270c40b23a4b3f08fad8ee85..8e0381f07c605ffc897bf0fd250bbfd4332fa1b1 100644 (file)
         </ul>
         {% endblock menu %}
       </div>
+
+
+      <div id="notifications"></div>
     </div>
 
     {% endblock header %}
diff --git a/teleforma/ws/notification.py b/teleforma/ws/notification.py
new file mode 100644 (file)
index 0000000..006cd1d
--- /dev/null
@@ -0,0 +1,28 @@
+from teleforma.ws.logger import log_consumer_exceptions
+from teleforma.models.notification import Notification
+from django.conf import settings
+from channels.generic.websocket import AsyncJsonWebsocketConsumer
+from channels.db import database_sync_to_async
+
+
+@log_consumer_exceptions
+class NotificationConsumer(AsyncJsonWebsocketConsumer):
+
+    async def connect(self):
+        await self.accept()
+
+        # send initial messages
+        data = await self.get_notifications_list()
+        await self.send_json(content={'type': 'initial', 'messages': data})
+
+    @database_sync_to_async
+    def get_notifications_list(self):
+        messages = [message.to_dict() for message in Notification.objects.filter(
+            user=self.user).order_by('-created')]
+        return messages
+
+    # Receive message from channel
+    async def notification_message(self, event):
+        message = event['message']
+        # Send message to WebSocket
+        await self.send_json(content={'type': 'new', 'messages': [message]})
index 649baec33ae959170a14215e005705419263652a..3f3b109880eb03c1d1d4f58269b9c4da2d5f9f97 100644 (file)
@@ -4,7 +4,9 @@ from channels.auth import AuthMiddlewareStack
 from channels.routing import ProtocolTypeRouter, URLRouter
 from django.core.asgi import get_asgi_application
 from django.urls import re_path
+
 from . import chat
+from . import notification
 
 os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'teleforma.settings')
 sys.path.append(os.path.dirname('.'))
@@ -12,6 +14,7 @@ sys.path.append(os.path.dirname('.'))
 
 websocket_urlpatterns = [
     re_path(r'ws/chat/(?P<room_name>\w+)/$', chat.ChatConsumer.as_asgi()),
+    re_path(r'ws/notification/(?P<user_id>\w+)/$', notification.NotificationConsumer.as_asgi()),
 ]