Commit 4dc3a1374e717e3fe9be7be890befe52bf3c055f
1 parent
82d4a01e
Exists in
master
and in
5 other branches
modified header to accept notifications and created notification system, stil ha…
…s bugs from Python 2.7 implementation on inheritance, had to duplicate code
Showing
8 changed files
with
185 additions
and
23 deletions
Show diff stats
amadeus/settings.py
@@ -88,8 +88,8 @@ DATABASES = { | @@ -88,8 +88,8 @@ DATABASES = { | ||
88 | 'default': { | 88 | 'default': { |
89 | 'ENGINE': 'django.db.backends.postgresql', | 89 | 'ENGINE': 'django.db.backends.postgresql', |
90 | 'NAME': 'amadeus', | 90 | 'NAME': 'amadeus', |
91 | - 'USER': 'amadeus_admin', | ||
92 | - 'PASSWORD': 'amadeus', | 91 | + 'USER': 'postgres', |
92 | + 'PASSWORD': 'felipe', | ||
93 | 'HOST': '127.0.0.1', | 93 | 'HOST': '127.0.0.1', |
94 | 'PORT': '5432', | 94 | 'PORT': '5432', |
95 | } | 95 | } |
app/views.py
@@ -2,17 +2,21 @@ from django.shortcuts import render | @@ -2,17 +2,21 @@ from django.shortcuts import render | ||
2 | from django.views.generic import TemplateView | 2 | from django.views.generic import TemplateView |
3 | from django.contrib.auth.mixins import LoginRequiredMixin | 3 | from django.contrib.auth.mixins import LoginRequiredMixin |
4 | from django.core.urlresolvers import reverse_lazy | 4 | from django.core.urlresolvers import reverse_lazy |
5 | -from core.mixins import LogMixin | ||
6 | - | 5 | +from core.mixins import LogMixin, NotificationMixin |
6 | +from core.models import Notification, Action, Resource, Action_Resource | ||
7 | +from users.models import User | ||
7 | from courses.models import Course | 8 | from courses.models import Course |
8 | 9 | ||
9 | -class AppIndex(LoginRequiredMixin, LogMixin, TemplateView): | 10 | +class AppIndex(LoginRequiredMixin, LogMixin, TemplateView, NotificationMixin): |
10 | log_action = "Acessar" | 11 | log_action = "Acessar" |
11 | log_resource = "Home" | 12 | log_resource = "Home" |
12 | login_url = reverse_lazy("core:home") | 13 | login_url = reverse_lazy("core:home") |
13 | redirect_field_name = 'next' | 14 | redirect_field_name = 'next' |
14 | template_name = "home_professor.html" | 15 | template_name = "home_professor.html" |
15 | 16 | ||
17 | + not_action = "Acessar" | ||
18 | + not_resource = "home" | ||
19 | + | ||
16 | def render_to_response(self, context, **response_kwargs): | 20 | def render_to_response(self, context, **response_kwargs): |
17 | context = {} | 21 | context = {} |
18 | 22 | ||
@@ -24,5 +28,40 @@ class AppIndex(LoginRequiredMixin, LogMixin, TemplateView): | @@ -24,5 +28,40 @@ class AppIndex(LoginRequiredMixin, LogMixin, TemplateView): | ||
24 | context['courses'] = Course.objects.filter(user = self.request.user) | 28 | context['courses'] = Course.objects.filter(user = self.request.user) |
25 | 29 | ||
26 | context['title'] = 'Amadeus' | 30 | context['title'] = 'Amadeus' |
31 | + self.createNotification("teste") | ||
32 | + notifications = Notification.objects.filter(user= self.request.user, read=False) | ||
33 | + | ||
34 | + context['notifications'] = notifications | ||
35 | + print(notifications) | ||
36 | + | ||
37 | + return self.response_class(request = self.request, template = template, context = context, using = self.template_engine, **response_kwargs) | ||
38 | + | ||
39 | + def createNotification(self, mensagem='', actor=None, users = User.objects.all(), not_action = '', not_resource=''): #the default will be a broadcast | ||
40 | + action = Action.objects.filter(name = not_action) | ||
41 | + resource = Resource.objects.filter(name = self.not_resource) | ||
42 | + print(action) | ||
43 | + if not action: | ||
44 | + action = Action(name = self.not_action) | ||
45 | + action.save() | ||
46 | + else: | ||
47 | + action = action[0] | ||
48 | + | ||
49 | + if not resource: | ||
50 | + resource = Resource(name = self.not_resource) | ||
51 | + resource.save() | ||
52 | + else: | ||
53 | + resource = resource[0] | ||
54 | + | ||
55 | + action_resource = Action_Resource.objects.filter(action = action, resource = resource) | ||
56 | + | ||
57 | + if not action_resource: | ||
58 | + action_resource = Action_Resource(action = action, resource = resource) | ||
59 | + action_resource.save() | ||
60 | + else: | ||
61 | + action_resource = action_resource[0] | ||
62 | + | ||
63 | + for user in users: | ||
64 | + print(user) | ||
65 | + notification = Notification(user=user, actor= actor, message=mensagem, action_resource= action_resource) | ||
66 | + notification.save() | ||
27 | 67 | ||
28 | - return self.response_class(request = self.request, template = template, context = context, using = self.template_engine, **response_kwargs) | ||
29 | \ No newline at end of file | 68 | \ No newline at end of file |
core/decorators.py
1 | from django.conf import settings | 1 | from django.conf import settings |
2 | from functools import wraps | 2 | from functools import wraps |
3 | -from .models import Action, Resource, Action_Resource, Log | 3 | +from .models import Action, Resource, Action_Resource, Log, Notification |
4 | 4 | ||
5 | def log_decorator(log_action = '', log_resource = ''): | 5 | def log_decorator(log_action = '', log_resource = ''): |
6 | 6 | ||
@@ -45,3 +45,48 @@ def log_decorator(log_action = '', log_resource = ''): | @@ -45,3 +45,48 @@ def log_decorator(log_action = '', log_resource = ''): | ||
45 | return wraps(view_function)(_decorator) | 45 | return wraps(view_function)(_decorator) |
46 | 46 | ||
47 | return _log_decorator | 47 | return _log_decorator |
48 | + | ||
49 | + | ||
50 | +def notification_decorator(read = False, message = '', actor = None, users = [], not_action='', not_resource=''): | ||
51 | + | ||
52 | + def _notification_decorator(view_function): | ||
53 | + | ||
54 | + def _decorator(request, *args, **kwargs): | ||
55 | + #Do something before the call | ||
56 | + | ||
57 | + response = view_function(request, *args, **kwargs) | ||
58 | + action = Action.objects.filter(name = not_action) | ||
59 | + resource = Resource.objects.filter(name = not_resource) | ||
60 | + | ||
61 | + if not action: | ||
62 | + action = Action(name = not_action) | ||
63 | + action.save() | ||
64 | + else: | ||
65 | + action = action[0] | ||
66 | + | ||
67 | + if not resource: | ||
68 | + resource = Resource(name = not_resource) | ||
69 | + resource.save() | ||
70 | + else: | ||
71 | + resource = resource[0] | ||
72 | + | ||
73 | + action_resource = Action_Resource.objects.filter(action = action, resource = resource) | ||
74 | + | ||
75 | + if not action_resource: | ||
76 | + action_resource = Action_Resource(action = action, resource = resource) | ||
77 | + action_resource.save() | ||
78 | + else: | ||
79 | + action_resource = action_resource[0] | ||
80 | + | ||
81 | + if request.user.is_authenticated: #the user was authenticated by the view | ||
82 | + notification = Notification(actor = request.user, message= message, | ||
83 | + action_resource = action_resource, user = request.user) | ||
84 | + | ||
85 | + | ||
86 | + | ||
87 | + #Do something after the call | ||
88 | + return response | ||
89 | + | ||
90 | + return wraps(view_function)(_decorator) | ||
91 | + | ||
92 | + return _notification_decorator | ||
48 | \ No newline at end of file | 93 | \ No newline at end of file |
core/mixins.py
1 | from django.conf import settings | 1 | from django.conf import settings |
2 | from .models import Action, Resource, Action_Resource, Log, Notification | 2 | from .models import Action, Resource, Action_Resource, Log, Notification |
3 | +from users.models import User | ||
3 | 4 | ||
4 | class LogMixin(object): | 5 | class LogMixin(object): |
5 | log_action = "" | 6 | log_action = "" |
@@ -40,16 +41,38 @@ class LogMixin(object): | @@ -40,16 +41,38 @@ class LogMixin(object): | ||
40 | class NotificationMixin(object): | 41 | class NotificationMixin(object): |
41 | message = "" | 42 | message = "" |
42 | read = False | 43 | read = False |
44 | + not_action = '' | ||
45 | + not_resource = '' | ||
43 | 46 | ||
44 | - def dispatch(self, request, *args, **kwargs): | ||
45 | - action = Action.objects.filter(name = self.log_action) | ||
46 | - resource = Resource.objects.filter(name = self.log_resource) | 47 | + def createNotification(message='', actor=None, users = User.objects.all(), not_action = '', not_resource=''): #the default will be a broadcast |
48 | + action = Action.objects.filter(name = self.not_action) | ||
49 | + resource = Resource.objects.filter(name = self.not_resource) | ||
50 | + | ||
51 | + if not action: | ||
52 | + action = Action(name = self.not_action) | ||
53 | + action.save() | ||
54 | + else: | ||
55 | + action = action[0] | ||
56 | + | ||
57 | + if not resource: | ||
58 | + resource = Resource(name = self.not_resource) | ||
59 | + resource.save() | ||
60 | + else: | ||
61 | + resource = resource[0] | ||
62 | + | ||
63 | + action_resource = Action_Resource.objects.filter(action = action, resource = resource) | ||
64 | + | ||
65 | + if not action_resource: | ||
66 | + action_resource = Action_Resource(action = action, resource = resource) | ||
67 | + action_resource.save() | ||
68 | + else: | ||
69 | + action_resource = action_resource[0] | ||
47 | 70 | ||
48 | - action_resource = Action_Resource.objects.filter(action = action, resource = resource)[0] | 71 | + for user in users: |
72 | + notification = Notification(user=user, actor= actor, message=message, action_resource= action_resource) | ||
49 | 73 | ||
50 | - notification = Notification() | ||
51 | - notification.action_resource = action_resource | ||
52 | - notification.user = request.user #We still have to handle the notification to be sent to an amount of Users | ||
53 | 74 | ||
54 | - notification.read = read | ||
55 | - notification.message = "" | 75 | + def dispatch(self, request, *args, **kwargs): |
76 | + """ | ||
77 | + Not quite sure how to do about it""" | ||
78 | + return super(NotificationMixin, self).dispatch(request, *args, **kwargs) | ||
56 | \ No newline at end of file | 79 | \ No newline at end of file |
core/static/css/base/header.css
@@ -13,10 +13,19 @@ | @@ -13,10 +13,19 @@ | ||
13 | margin-left: 30%; | 13 | margin-left: 30%; |
14 | } | 14 | } |
15 | 15 | ||
16 | -/* ID */ | 16 | +.link{ |
17 | + transition-duration: 0.5s; /*Slow down the transformation*/ | ||
18 | +} | ||
19 | + | ||
20 | +.link:hover{ | ||
21 | + transform:scale(1.1); | ||
22 | +} | ||
17 | 23 | ||
18 | .notifications{ | 24 | .notifications{ |
19 | font-size: 20px; | 25 | font-size: 20px; |
20 | 26 | ||
21 | } | 27 | } |
22 | 28 | ||
29 | +/* ID */ | ||
30 | + | ||
31 | + |
core/templates/base.html
@@ -30,6 +30,7 @@ | @@ -30,6 +30,7 @@ | ||
30 | <script> | 30 | <script> |
31 | $.material.init(); | 31 | $.material.init(); |
32 | </script> | 32 | </script> |
33 | + <script src="{% static 'js/base/header.js'%}"></script> | ||
33 | <!--Javascript block for specific-app ones --> | 34 | <!--Javascript block for specific-app ones --> |
34 | {% block javascript %} | 35 | {% block javascript %} |
35 | 36 | ||
@@ -51,16 +52,55 @@ | @@ -51,16 +52,55 @@ | ||
51 | </div> | 52 | </div> |
52 | <div class="navbar-collapse collapse navbar-responsive-collapse"> | 53 | <div class="navbar-collapse collapse navbar-responsive-collapse"> |
53 | <ul class="nav navbar-nav navbar-right notifications"> | 54 | <ul class="nav navbar-nav navbar-right notifications"> |
54 | - <li> <a href="#"><i class="fa fa-bell-o" aria-hidden="true"></i></a> </li> | ||
55 | - <li> <a href="#"><i class="fa fa-comments" aria-hidden="true"></i></a> </li> | ||
56 | - <li> <a href="{% url 'users:profile' %}">{{ user }}</a></li> | ||
57 | - <li> <a href="{% url 'core:logout' %}">{% trans 'Log out' %}</a></li> | 55 | + <li class="" data-toggle="tooltip" data-placement="bottom" title data-original-title="notifications"> |
56 | + <a href="../user/profile_user.html" class="dropdown-toggle" data-toggle="dropdown"><i class="fa fa-bell-o" aria-hidden="true"></i></a> | ||
57 | + <ul class="dropdown-menu"> | ||
58 | + <li class="dropdown-header">Notifications</li> | ||
59 | + {% for notification in notifications %} | ||
60 | + {% if notification.actor %} <!-- if the notification has a user--> | ||
61 | + <li> | ||
62 | + <a><div class="list-group-item"> | ||
63 | + <div class="row-picture"> | ||
64 | + <img class="circle" src="http://lorempixel.com/56/56/people/1" alt="icon"> | ||
65 | + <div class="least-content pull-right">{{ notification.datetime }}</div> | ||
66 | + </div> | ||
67 | + <div class="row-content"> | ||
68 | + <p class="list-group-item-text">{{ notification.message }}</p> | ||
69 | + </div> | ||
70 | + </div> | ||
71 | + </a> | ||
72 | + </li> | ||
73 | + {% else %} | ||
74 | + <li> | ||
75 | + <a> | ||
76 | + <div class="list-group-item"> | ||
77 | + <div class="row-action-primary"> | ||
78 | + <i class="material-icons">folder</i> | ||
79 | + </div> | ||
80 | + <div class="row-content"> | ||
81 | + | ||
82 | + <div class="least-content pull-right">{{ notification.datetime }}</div> | ||
83 | + | ||
84 | + <p class="list-group-item-text">{{ notification.message }}</p> | ||
85 | + </div> | ||
86 | + </a> | ||
87 | + </li> | ||
88 | + {% endif %} | ||
89 | + {% endfor %} | ||
90 | + | ||
91 | + <div> <p>See more</p> </div> | ||
92 | + </ul> | ||
93 | + </li> | ||
94 | + | ||
95 | + <li class="link" data-toggle="tooltip" data-placement="bottom" title data-original-title="messages"> <a href="#"><i class="fa fa-comments" aria-hidden="true"></i></a> </li> | ||
96 | + <li class="link"> <a href="{% url 'users:profile' %}">{{ user }}</a></li> | ||
97 | + <li class="link"> <a href="{% url 'core:logout' %}">{% trans 'Log out' %}</a></li> | ||
58 | </ul> | 98 | </ul> |
59 | </div> | 99 | </div> |
60 | </div> | 100 | </div> |
61 | </div> | 101 | </div> |
62 | </div> | 102 | </div> |
63 | - </div> | 103 | + </div> |
64 | {% endblock %} | 104 | {% endblock %} |
65 | 105 | ||
66 | <div class="container-fluid"> | 106 | <div class="container-fluid"> |
core/views.py
@@ -13,16 +13,18 @@ from django.conf import settings | @@ -13,16 +13,18 @@ from django.conf import settings | ||
13 | from rolepermissions.shortcuts import assign_role | 13 | from rolepermissions.shortcuts import assign_role |
14 | 14 | ||
15 | from .forms import RegisterUserForm | 15 | from .forms import RegisterUserForm |
16 | -from .decorators import log_decorator | 16 | +from .decorators import log_decorator, notification_decorator |
17 | 17 | ||
18 | from users.models import User | 18 | from users.models import User |
19 | 19 | ||
20 | + | ||
20 | def index(request): | 21 | def index(request): |
21 | context = { | 22 | context = { |
22 | 'subscribed_courses': 'testando' | 23 | 'subscribed_courses': 'testando' |
23 | } | 24 | } |
24 | return render(request, "index.html", context) | 25 | return render(request, "index.html", context) |
25 | 26 | ||
27 | + | ||
26 | class RegisterUser(CreateView): | 28 | class RegisterUser(CreateView): |
27 | model = User | 29 | model = User |
28 | form_class = RegisterUserForm | 30 | form_class = RegisterUserForm |
@@ -64,6 +66,7 @@ def remember_password(request): | @@ -64,6 +66,7 @@ def remember_password(request): | ||
64 | context['danger'] = 'E-mail does not send' | 66 | context['danger'] = 'E-mail does not send' |
65 | return render(request, "remember_password.html",context) | 67 | return render(request, "remember_password.html",context) |
66 | 68 | ||
69 | +@notification_decorator(message='just connected') | ||
67 | @log_decorator('Acessar', 'Sistema') | 70 | @log_decorator('Acessar', 'Sistema') |
68 | def login(request): | 71 | def login(request): |
69 | context = {} | 72 | context = {} |