Commit 6e9986a811e8d615a687ea49cd30d4831fedb9f3

Authored by Zambom
1 parent 6c50648e

Adding mural notifications

amadeus/routing.py
1 from channels.routing import route 1 from channels.routing import route
2 -from mural.consumers import ws_message 2 +from mural.consumers import ws_add, ws_message
3 3
4 channel_routing = [ 4 channel_routing = [
  5 + route("websocket.connect", ws_add),
5 route("websocket.receive", ws_message), 6 route("websocket.receive", ws_message),
6 ] 7 ]
7 \ No newline at end of file 8 \ No newline at end of file
amadeus/settings.py
@@ -54,7 +54,7 @@ INSTALLED_APPS = [ @@ -54,7 +54,7 @@ INSTALLED_APPS = [
54 'session_security', 54 'session_security',
55 'django_crontab', 55 'django_crontab',
56 'django_cron', 56 'django_cron',
57 - #'channels', 57 + 'channels',
58 58
59 'amadeus', 59 'amadeus',
60 'users', 60 'users',
amadeus/static/js/socket.js 0 → 100644
@@ -0,0 +1,37 @@ @@ -0,0 +1,37 @@
  1 +socket = new WebSocket("ws://" + window.location.host + "/");
  2 +
  3 +socket.onmessage = function(e) {
  4 + content = JSON.parse(e.data);
  5 +
  6 + if (content.type == "mural") {
  7 + if (window.location.pathname == content.pathname) {
  8 + $('.posts').prepend(content.complete);
  9 +
  10 + $('.no-subjects').attr('style', 'display:none');
  11 + }
  12 +
  13 + if (("Notification" in window)) {
  14 + var options = {
  15 + icon: content.user_icon,
  16 + body: content.simple
  17 + }
  18 +
  19 + if (Notification.permission === "granted") {
  20 + var notification = new Notification("", options);
  21 +
  22 + setTimeout(notification.close.bind(notification), 3000);
  23 + } else if (Notification.permission !== 'denied') {
  24 + Notification.requestPermission(function (permission) {
  25 + // If the user accepts, let's create a notification
  26 + if (permission === "granted") {
  27 + var notification = new Notification("", options);
  28 +
  29 + setTimeout(notification.close.bind(notification), 3000);
  30 + }
  31 + });
  32 + }
  33 + }
  34 + }
  35 +}
  36 +// Call onopen directly if socket is already open
  37 +if (socket.readyState == WebSocket.OPEN) socket.onopen();
0 \ No newline at end of file 38 \ No newline at end of file
amadeus/templates/base.html
@@ -260,6 +260,7 @@ @@ -260,6 +260,7 @@
260 <!-- Init material Bootstrap --> 260 <!-- Init material Bootstrap -->
261 <script type="text/javascript">$.material.init()</script> 261 <script type="text/javascript">$.material.init()</script>
262 <script src="{% static 'js/main.js' %}"></script> 262 <script src="{% static 'js/main.js' %}"></script>
  263 + <script src="{% static 'js/socket.js' %}"></script>
263 </body> 264 </body>
264 265
265 </html> 266 </html>
266 \ No newline at end of file 267 \ No newline at end of file
mural/consumers.py
1 from channels import Group 1 from channels import Group
2 from channels.sessions import channel_session 2 from channels.sessions import channel_session
3 -from django.http import HttpResponse  
4 -from channels.handler import AsgiHandler 3 +from channels.auth import channel_session_user, channel_session_user_from_http
  4 +
  5 +# Connected to websocket.connect
  6 +@channel_session_user_from_http
  7 +def ws_add(message):
  8 + # Accept connection
  9 + message.reply_channel.send({"accept": True})
  10 + # Add them to the right group
  11 + Group("user-%s" % message.user.id).add(message.reply_channel)
5 12
6 -def http_consumer(message):  
7 - # Make standard HTTP response - access ASGI path attribute directly  
8 - response = HttpResponse("Hello world! You asked for %s" % message.content['path'])  
9 - # Encode that response into message format (ASGI)  
10 - for chunk in AsgiHandler.encode_response(response):  
11 - message.reply_channel.send(chunk)  
12 13
13 def ws_message(message): 14 def ws_message(message):
14 # ASGI WebSocket packet-received and send-packet message types 15 # ASGI WebSocket packet-received and send-packet message types
mural/views.py
@@ -8,6 +8,9 @@ from django.utils.translation import ugettext_lazy as _ @@ -8,6 +8,9 @@ from django.utils.translation import ugettext_lazy as _
8 from django.contrib.auth.mixins import LoginRequiredMixin 8 from django.contrib.auth.mixins import LoginRequiredMixin
9 from django.db.models import Q, Count 9 from django.db.models import Q, Count
10 10
  11 +from channels import Group
  12 +import json
  13 +
11 from users.models import User 14 from users.models import User
12 15
13 from .models import GeneralPost, CategoryPost, SubjectPost, MuralVisualizations 16 from .models import GeneralPost, CategoryPost, SubjectPost, MuralVisualizations
@@ -67,8 +70,15 @@ class GeneralCreate(LoginRequiredMixin, generic.edit.CreateView): @@ -67,8 +70,15 @@ class GeneralCreate(LoginRequiredMixin, generic.edit.CreateView):
67 users = User.objects.all().exclude(id = self.request.user.id) 70 users = User.objects.all().exclude(id = self.request.user.id)
68 entries = [] 71 entries = []
69 72
  73 + notify_type = "mural"
  74 + user_icon = self.object.user.image_url
  75 + _view = render_to_string("mural/_view.html", {"post": self.object}, self.request)
  76 + simple_notify = _("%s has made a post in General")%(str(self.object.user))
  77 + pathname = reverse("mural:manage_general")
  78 +
70 for user in users: 79 for user in users:
71 - entries.append(MuralVisualizations(viewed = False, user = user, post = self.object)) 80 + entries.append(MuralVisualizations(viewed = False, user = user, post = self.object))
  81 + Group("user-%s" % user.id).send({'text': json.dumps({"type": notify_type, "user_icon": user_icon, "pathname": pathname, "simple": simple_notify, "complete": _view})})
72 82
73 MuralVisualizations.objects.bulk_create(entries) 83 MuralVisualizations.objects.bulk_create(entries)
74 84