Commit 6e9986a811e8d615a687ea49cd30d4831fedb9f3
1 parent
6c50648e
Exists in
master
and in
3 other branches
Adding mural notifications
Showing
6 changed files
with
61 additions
and
11 deletions
Show diff stats
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
@@ -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 |