Commit 2c02d7ee6dd357c98c4517bbe0d8fb07667584bf

Authored by Zambom
1 parent a7d5f7a6

User status change propagation via notification

amadeus/static/js/socket.js
... ... @@ -21,6 +21,8 @@ socket.onmessage = function(e) {
21 21 }
22 22 } else if (content.type == "chat") {
23 23 messageReceived(content);
  24 + } else if (content.type == "user_status") {
  25 + changeUserStatus(content);
24 26 }
25 27 }
26 28 // Call onopen directly if socket is already open
... ... @@ -297,4 +299,18 @@ function messageReceived(content) {
297 299 setTimeout(notification.close.bind(notification), 3000);
298 300 }
299 301 }
  302 +}
  303 +
  304 +function changeUserStatus(content) {
  305 + var elem = $(".user_" + content.user_id + "_status");
  306 +
  307 + elem.removeClass(content.remove_class);
  308 +
  309 + if (content.status_class == "") {
  310 + elem.removeClass('active');
  311 + } else {
  312 + elem.addClass(content.status_class);
  313 + }
  314 +
  315 + elem.attr('data-original-title', content.status);
300 316 }
301 317 \ No newline at end of file
... ...
chat/templates/chat/_profile.html
... ... @@ -14,7 +14,7 @@
14 14 <img src="{{ participant.image_url }}" />
15 15 </span>
16 16 <h4>
17   - <a class="status {{ status }}" title="{{ status|status_text }}"></a>
  17 + <a class="user_{{ participant.id }}_status status {{ status }}" title="{{ status|status_text }}"></a>
18 18 <b>{{ participant }}</b>
19 19 </h4>
20 20 <a href="#" onclick="getModalInfo($(this), '{{ space }}', '{{ space_type }}'); return false;" data-url='{% url "chat:talk" participant.email %}' class="btn btn-raised btn-success btn-block">{% trans 'Send Message' %}</a>
... ...
chat/templates/chat/_view.html
... ... @@ -9,7 +9,7 @@
9 9 <img src="{{ talking_to.image_url }}" class="img-responsive" />
10 10 </div>
11 11 <div class="col-md-6 user-info">
12   - <h4 class='talking-header'><a class="status {{ status }}" data-toggle="tooltip" title="{{ status|status_text }}"></a> {{ talking_to }} (<span class="chat_notify">{{ chat|notifies:request.user }}</span>)</h4>
  12 + <h4 class='talking-header'><a class="user_{{ talking_to.id }}_status status {{ status }}" data-toggle="tooltip" title="{{ status|status_text }}"></a> {{ talking_to }} (<span class="chat_notify">{{ chat|notifies:request.user }}</span>)</h4>
13 13 <p class="talk-last_msg">{% trans 'Last message in' %} {{ chat|last_message }}</p>
14 14 </div>
15 15 <div class="col-md-4 buttons pull-right text-center">
... ...
chat/templates/chat/_view_participant.html
... ... @@ -7,7 +7,7 @@
7 7 <img src="{{ participant.image_url }}" class="img-responsive" />
8 8 </div>
9 9 <div class="col-md-6 user-info">
10   - <h4><a class="status {{ status }}" data-toggle="tooltip" title="{{ status|status_text }}"></a> {{ participant }}</h4>
  10 + <h4><a class="user_{{ participant.id }}_status status {{ status }}" data-toggle="tooltip" title="{{ status|status_text }}"></a> {{ participant }}</h4>
11 11 </div>
12 12 <div class="col-md-4 buttons pull-right text-center">
13 13 <a href="#" onclick="getModalInfo($(this), '{{ space }}', '{{ space_type }}'); return false;" data-url='{% url "chat:profile" participant.email %}' class="btn btn-raised btn-default">{% trans 'See Profile' %}</a>
... ...
chat/templates/chat/talk.html
... ... @@ -11,7 +11,7 @@
11 11 <img src="{{ participant.image_url }}" />
12 12 </span>
13 13 <h4 class="pull-left" data-breadcrumb="{% trans 'Talk with ' %}{{ participant }}">
14   - <a class="status {{ status }}" title="{{ status|status_text }}"></a>
  14 + <a class="user_{{ participant.id }}_status status {{ status }}" title="{{ status|status_text }}"></a>
15 15 <b>{{ participant }}</b>
16 16 </h4>
17 17 </div>
... ...
subjects/templates/subjects/view.html
... ... @@ -93,7 +93,7 @@
93 93  
94 94 <div class="participants-container">
95 95 <div class="col-md-12 sub-user" data-toggle="popover" data-container="body" data-placement="left">
96   - <h4><a class="status {{ status }}" data-placement="right" data-toggle="tooltip" title="{{ status|status_text }}"></a> {{ participant }}</h4>
  96 + <h4><a class="user_{{ participant.id }}_status status {{ status }}" data-placement="right" data-toggle="tooltip" title="{{ status|status_text }}"></a> {{ participant }}</h4>
97 97 </div>
98 98  
99 99 <div class="popover">
... ...
users/middleware.py
... ... @@ -9,6 +9,11 @@ from session_security.utils import get_last_activity, set_last_activity
9 9  
10 10 from log.models import Log
11 11  
  12 +from .models import User
  13 +from django.utils.translation import ugettext as _u
  14 +from channels import Group
  15 +import json
  16 +
12 17 class SessionExpireMiddleware(object):
13 18  
14 19 def process_request(self, request):
... ... @@ -33,4 +38,19 @@ class SessionExpireMiddleware(object):
33 38 log.action = "logout"
34 39 log.resource = "system"
35 40  
36   - log.save()
37 41 \ No newline at end of file
  42 + log.save()
  43 +
  44 + users = User.objects.all().exclude(email = request.user.email)
  45 +
  46 + notification = {
  47 + "type": "user_status",
  48 + "user_id": str(request.user.id),
  49 + "status": _u("Offline"),
  50 + "status_class": "",
  51 + "remove_class": "away"
  52 + }
  53 +
  54 + notification = json.dumps(notification)
  55 +
  56 + for u in users:
  57 + Group("user-%s" % u.id).send({'text': notification})
38 58 \ No newline at end of file
... ...
users/views.py
... ... @@ -5,6 +5,7 @@ from django.contrib.auth import authenticate, login as login_user, logout as log
5 5 from django.contrib.auth.mixins import LoginRequiredMixin
6 6 from django.core.urlresolvers import reverse, reverse_lazy
7 7 from django.utils.translation import ugettext_lazy as _
  8 +from django.utils.translation import ugettext as _u
8 9 from django.db.models import Q, Count
9 10  
10 11 from braces import views as braces_mixins
... ... @@ -19,6 +20,10 @@ from .models import User
19 20 from .utils import has_dependencies
20 21 from .forms import RegisterUserForm, ProfileForm, UserForm, ChangePassForm, PassResetRequest, SetPasswordForm
21 22  
  23 +#USER STATUS NOTIFICATION
  24 +from channels import Group
  25 +import json
  26 +
22 27 #RECOVER PASS IMPORTS
23 28 from django.contrib.auth.tokens import default_token_generator
24 29 from django.core.mail import send_mail
... ... @@ -501,6 +506,21 @@ def login(request):
501 506 if not security.maintence or user.is_staff:
502 507 login_user(request, user)
503 508  
  509 + users = User.objects.all().exclude(email = username)
  510 +
  511 + notification = {
  512 + "type": "user_status",
  513 + "user_id": str(user.id),
  514 + "status": _u("Online"),
  515 + "status_class": "active",
  516 + "remove_class": "away"
  517 + }
  518 +
  519 + notification = json.dumps(notification)
  520 +
  521 + for u in users:
  522 + Group("user-%s" % u.id).send({'text': notification})
  523 +
504 524 next_url = request.GET.get('next', None)
505 525  
506 526 if next_url:
... ... @@ -519,8 +539,25 @@ def login(request):
519 539  
520 540 @log_decorator('user', 'logout', 'system')
521 541 def logout(request, next_page = None):
  542 + user = request.user
  543 +
522 544 logout_user(request)
523 545  
  546 + users = User.objects.all().exclude(email = user.email)
  547 +
  548 + notification = {
  549 + "type": "user_status",
  550 + "user_id": str(user.id),
  551 + "status": _u("Offline"),
  552 + "status_class": "",
  553 + "remove_class": "away"
  554 + }
  555 +
  556 + notification = json.dumps(notification)
  557 +
  558 + for u in users:
  559 + Group("user-%s" % u.id).send({'text': notification})
  560 +
524 561 if next_page:
525 562 return redirect(next_page)
526 563  
... ...