Commit 07193e64de2ee9ab1e2642c6ff8b01ebbc0c5d60

Authored by Zambom
1 parent 85fe3d3f

Adding subject notifications view page

amadeus/static/css/base/amadeus.css
@@ -142,6 +142,10 @@ a:focus { @@ -142,6 +142,10 @@ a:focus {
142 font-size: 15px; 142 font-size: 15px;
143 } 143 }
144 144
  145 +.pendencies-content {
  146 + padding: 10px;
  147 +}
  148 +
145 .category-panel-content { 149 .category-panel-content {
146 padding:10px; 150 padding:10px;
147 } 151 }
@@ -834,4 +838,54 @@ li.item .notify_badge { @@ -834,4 +838,54 @@ li.item .notify_badge {
834 font-size: 0.9rem; 838 font-size: 0.9rem;
835 border-radius: 50%; 839 border-radius: 50%;
836 padding: 0px; 840 padding: 0px;
  841 +}
  842 +
  843 +.pendency {
  844 + border: 1px solid;
  845 + padding-left: 10px;
  846 + padding-top: 7px;
  847 + margin-bottom: 15px;
  848 +}
  849 +
  850 +.pendency .breadcrumb {
  851 + padding-left: 0px;
  852 + margin-bottom: 0px;
  853 +}
  854 +
  855 +.pendency h4 {
  856 + margin: 0px;
  857 + font-size: 22px;
  858 + font-weight: 700;
  859 +}
  860 +
  861 +.pendency p {
  862 + margin-bottom: 3px;
  863 +}
  864 +
  865 +.pendency .alert {
  866 + padding-top: 5px;
  867 + padding-bottom: 5px;
  868 + font-weight: 700;
  869 +}
  870 +
  871 +.pendency .alert span {
  872 + position: relative;
  873 + top: -7px;
  874 + padding-left: 10px;
  875 +}
  876 +
  877 +.pendency .alert i {
  878 + font-size: 35px;
  879 +}
  880 +
  881 +.alert-low {
  882 + opacity: 0.5;
  883 +}
  884 +
  885 +.no_button {
  886 + cursor: initial;
  887 +}
  888 +
  889 +.no_button:focus, .no_button:active:focus, .no_button.active:focus, .no_button.focus, .no_button:active.focus, .no_button.active.focus {
  890 + outline: none;
837 } 891 }
838 \ No newline at end of file 892 \ No newline at end of file
amadeus/static/css/themes/green.css
@@ -85,6 +85,14 @@ a, a:focus, a:hover { @@ -85,6 +85,14 @@ a, a:focus, a:hover {
85 color: #F5F5F5; 85 color: #F5F5F5;
86 } 86 }
87 87
  88 +.pendencies-content {
  89 + background: #FFFFFF;
  90 +}
  91 +
  92 +.pendencies-content .core-subjects-options li {
  93 + background: #F5F5F5;
  94 +}
  95 +
88 .category-header i { 96 .category-header i {
89 color: white; 97 color: white;
90 } 98 }
@@ -426,6 +434,27 @@ a.add-row { @@ -426,6 +434,27 @@ a.add-row {
426 color: #F5F5F5 !important; 434 color: #F5F5F5 !important;
427 } 435 }
428 436
  437 +.pendency {
  438 + border-color: #CCCCCC;
  439 +}
  440 +
  441 +.pendency .breadcrumb {
  442 + background-color: #FFFFFF;
  443 +}
  444 +
  445 +.pendency .meta {
  446 + color: #FF0000;
  447 +}
  448 +
  449 +.alert-low, .alert-medium {
  450 + background-color: #FFA500;
  451 + color: #FFFFFF;
  452 +}
  453 +
  454 +.no_button:hover, .no_button:focus, .no_button:active {
  455 + background-color: initial !important;
  456 +}
  457 +
429 @media(max-width: 768px) { 458 @media(max-width: 768px) {
430 .navbar .navbar-nav .dropdown .dropdown-menu li > a { 459 .navbar .navbar-nav .dropdown .dropdown-menu li > a {
431 color: #333333 !important; 460 color: #333333 !important;
amadeus/templates/pagination.html
1 {% if paginator.count > 0 %} 1 {% if paginator.count > 0 %}
2 - <div class="row-fluid"> 2 + <div class="row">
3 <div class="col-md-12 col-lg-12 col-sm-12 col-xs-12 text-center"> 3 <div class="col-md-12 col-lg-12 col-sm-12 col-xs-12 text-center">
4 <ul class="pagination"> 4 <ul class="pagination">
5 {% if page_obj.has_previous %} 5 {% if page_obj.has_previous %}
amadeus/urls.py
@@ -34,6 +34,7 @@ urlpatterns = [ @@ -34,6 +34,7 @@ urlpatterns = [
34 url(r'^mailsender/', include('mailsender.urls', namespace = 'mailsender')), 34 url(r'^mailsender/', include('mailsender.urls', namespace = 'mailsender')),
35 url(r'^security/', include('security.urls', namespace = 'security')), 35 url(r'^security/', include('security.urls', namespace = 'security')),
36 url(r'^themes/', include('themes.urls', namespace = 'themes')), 36 url(r'^themes/', include('themes.urls', namespace = 'themes')),
  37 + url(r'^notifications/', include('notifications.urls', namespace = 'notifications')),
37 #API 38 #API
38 url(r'^o/', include('oauth2_provider.urls', namespace='oauth2_provider')), 39 url(r'^o/', include('oauth2_provider.urls', namespace='oauth2_provider')),
39 #S3Direct 40 #S3Direct
notifications/models.py
@@ -11,3 +11,6 @@ class Notification(models.Model): @@ -11,3 +11,6 @@ class Notification(models.Model):
11 level = models.IntegerField(_('Type'), choices = ((1, _('Type 1-A')), (2, _('Type 1-B')), (3, _('Type 2')), (4, _('Type 3')))) 11 level = models.IntegerField(_('Type'), choices = ((1, _('Type 1-A')), (2, _('Type 1-B')), (3, _('Type 2')), (4, _('Type 3'))))
12 viewed = models.BooleanField(_('Visualized'), default = False) 12 viewed = models.BooleanField(_('Visualized'), default = False)
13 creation_date = models.DateField(_('Creation Date'), auto_now_add = True) 13 creation_date = models.DateField(_('Creation Date'), auto_now_add = True)
  14 +
  15 + def __str__(self):
  16 + return self.task.get_action_display() + " " + str(self.task.resource)
notifications/templates/notifications/_view.html 0 → 100644
@@ -0,0 +1,65 @@ @@ -0,0 +1,65 @@
  1 +{% load i18n notification_filters %}
  2 +
  3 +<div class="row">
  4 + <div class="col-md-12">
  5 + <div class="pendency">
  6 + <ul class="breadcrumb">
  7 + <li>
  8 + <a href="">{% trans 'Home' %}</a>
  9 + </li>
  10 + <li>
  11 + <a href="">{{ notification.task.resource.topic.subject.category }}</a>
  12 + </li>
  13 + <li>
  14 + <a href="">{{ notification.task.resource.topic.subject }}</a>
  15 + </li>
  16 + <li>
  17 + <a href="">{{ notification.task.resource.topic }}</a>
  18 + </li>
  19 + <li>
  20 + <a href="">{{ notification.task.resource }}</a>
  21 + </li>
  22 + </ul>
  23 + <div class="row">
  24 + <div class="col-md-6">
  25 + <h4>{{ notification }}</h4>
  26 + <p>{% trans 'Final Date/Time' %}: {{ notification.task.end_date|default:_('Not Informed') }}</p>
  27 +
  28 + {% if notification.level == 2 %}
  29 + <p class="meta">{% trans 'Your goal was to realize this in' %}: {{ notification.meta }}</p>
  30 + {% elif notification.level == 4 %}
  31 + <p class="meta">{% trans 'Task finished in' %}: {{ notification.task.limit_date }}</p>
  32 + {% endif %}
  33 +
  34 + <b>{{ notification|done_percent }}%</b> {% trans 'of the participants already realized this task.' %}
  35 + </div>
  36 + <div class="col-md-6">
  37 + <div class="alert {{ notification.level|warning_class }}">
  38 + <i class="fa fa-exclamation-triangle"></i>
  39 + <span>{{ notification.level|warning_msg }}</span>
  40 + </div>
  41 + </div>
  42 + </div>
  43 + <div class="row text-center">
  44 + <a href="" class="btn btn-success btn-raised">
  45 + {% if notification.level == 4 %}
  46 + {% trans 'Access the task' %}
  47 + {% else %}
  48 + {% trans 'Realize the task' %}
  49 + {% endif %}
  50 + </a>
  51 +
  52 + {% if notification.level < 3 %}
  53 + <button class="btn btn-default no_button">{% trans 'or' %}</button>
  54 + <a href="" class="btn btn-default btn-raised">
  55 + {% if notification.level == 1 %}
  56 + {% trans 'Define goal to realization' %}
  57 + {% else %}
  58 + {% trans 'Define new goal' %}
  59 + {% endif %}
  60 + </a>
  61 + {% endif %}
  62 + </div>
  63 + </div>
  64 + </div>
  65 +</div>
0 \ No newline at end of file 66 \ No newline at end of file
notifications/templates/notifications/subject.html 0 → 100644
@@ -0,0 +1,50 @@ @@ -0,0 +1,50 @@
  1 +{% extends 'subjects/view.html' %}
  2 +
  3 +{% load static i18n pagination permissions_tags subject_counter %}
  4 +{% load django_bootstrap_breadcrumbs %}
  5 +
  6 +{% block breadcrumbs %}
  7 + {{ block.super }}
  8 +
  9 + {% breadcrumb 'Pendencies' 'notifications:view' subject.slug %}
  10 +{% endblock %}
  11 +
  12 +{% block content %}
  13 + {% if subject.visible %}
  14 + <div class="panel panel-info subject-panel">
  15 + <div class="panel-heading">
  16 + {% else %}
  17 + <div class="panel panel-info subject-panel-invisible">
  18 + <div class="panel-heading panel-invisible">
  19 + {% endif %}
  20 + <div class="row">
  21 + <div class="col-md-12 category-header">
  22 + <h4 class="panel-title" style="margin-top: 10px; margin-bottom: 8px">
  23 + <span>{% trans 'Pendencies' %}</span>
  24 + </h4>
  25 + </div>
  26 + </div>
  27 + </div>
  28 + <div id="{{subject.slug}}" class="panel-collapse in collapse pendencies-content">
  29 + <div id="core-subjects-options-div">
  30 + <ul class="core-subjects-options">
  31 + <a href="{% url 'notifications:view' subject.slug %}"><li class="active">{% trans "Actual Pendencies" %} ({{ notifications.count }})</li></a>
  32 + <a href="" ><li>{% trans "Notifications History" %}</li></a>
  33 + </ul>
  34 + </div>
  35 +
  36 + {% if notifications.count > 0 %}
  37 + {% for notification in notifications %}
  38 + {% include 'notifications/_view.html' %}
  39 + {% endfor %}
  40 +
  41 + {% pagination request paginator page_obj %}
  42 + {% else %}
  43 + <div class="text-center no-subjects">
  44 + <i class="fa fa-exclamation-triangle"></i>
  45 + <h4>{% trans 'You do not posses any pendency in this subject' %}</h4>
  46 + </div>
  47 + {% endif %}
  48 + </div>
  49 + </div>
  50 +{% endblock %}
0 \ No newline at end of file 51 \ No newline at end of file
notifications/templatetags/__init__.py 0 → 100644
notifications/templatetags/notification_filters.py 0 → 100644
@@ -0,0 +1,45 @@ @@ -0,0 +1,45 @@
  1 +from django import template
  2 +from datetime import datetime
  3 +from django.utils.translation import ugettext_lazy as _
  4 +
  5 +from notifications.utils import get_resource_users
  6 +from notifications.models import Notification
  7 +
  8 +register = template.Library()
  9 +
  10 +@register.filter(name = 'warning_class')
  11 +def warning_class(level):
  12 + if level == 1:
  13 + class_name = "alert-low"
  14 + elif level == 2:
  15 + class_name = "alert-low"
  16 + elif level == 3:
  17 + class_name = "alert-medium"
  18 + else:
  19 + class_name = "alert-danger"
  20 +
  21 + return class_name
  22 +
  23 +@register.filter(name = 'warning_msg')
  24 +def warning_msg(level):
  25 + if level == 1:
  26 + msg = _('You still did not realize this task')
  27 + elif level == 2:
  28 + msg = _('You still did not realize this task')
  29 + elif level == 3:
  30 + msg = _('This task is late')
  31 + else:
  32 + msg = _('You miss this task')
  33 +
  34 + return msg
  35 +
  36 +@register.filter(name = 'done_percent')
  37 +def done_percent(notification):
  38 + users = get_resource_users(notification.task.resource)
  39 + notified = Notification.objects.filter(user__in = users.values_list('id', flat = True), creation_date = datetime.now(), task = notification.task).count()
  40 +
  41 + number_users = users.count()
  42 +
  43 + not_done = (notified * 100) / number_users
  44 +
  45 + return 100 - not_done
0 \ No newline at end of file 46 \ No newline at end of file
notifications/urls.py 0 → 100644
@@ -0,0 +1,6 @@ @@ -0,0 +1,6 @@
  1 +from django.conf.urls import url
  2 +from . import views
  3 +
  4 +urlpatterns = [
  5 + url(r'^(?P<slug>[\w_-]+)/$', views.SubjectNotifications.as_view(), name='view'),
  6 +]
0 \ No newline at end of file 7 \ No newline at end of file
notifications/views.py
1 -from django.shortcuts import render 1 +from django.shortcuts import get_object_or_404, redirect, render
  2 +from django.views import generic
  3 +from django.contrib import messages
  4 +from django.core.urlresolvers import reverse, reverse_lazy
  5 +from django.utils.translation import ugettext_lazy as _
  6 +from django.contrib.auth.mixins import LoginRequiredMixin
2 7
3 -# Create your views here. 8 +from datetime import datetime
  9 +
  10 +from amadeus.permissions import has_subject_view_permissions
  11 +
  12 +from subjects.models import Subject
  13 +
  14 +from .models import Notification
  15 +
  16 +class SubjectNotifications(LoginRequiredMixin, generic.ListView):
  17 + login_url = reverse_lazy("users:login")
  18 + redirect_field_name = 'next'
  19 +
  20 + context_object_name = 'notifications'
  21 + template_name = 'notifications/subject.html'
  22 + paginate_by = 10
  23 +
  24 + def dispatch(self, request, *args, **kwargs):
  25 + slug = self.kwargs.get('slug', '')
  26 + subject = get_object_or_404(Subject, slug = slug)
  27 +
  28 + if not has_subject_view_permissions(request.user, subject):
  29 + return redirect(reverse_lazy('subjects:home'))
  30 +
  31 + return super(SubjectNotifications, self).dispatch(request, *args, **kwargs)
  32 +
  33 + def get_queryset(self):
  34 + slug = self.kwargs.get('slug', '')
  35 + subject = get_object_or_404(Subject, slug = slug)
  36 +
  37 + notifications = Notification.objects.filter(user = self.request.user, task__resource__topic__subject = subject, creation_date = datetime.now())
  38 +
  39 + return notifications
  40 +
  41 + def get_context_data(self, **kwargs):
  42 + context = super(SubjectNotifications, self).get_context_data(**kwargs)
  43 +
  44 + slug = self.kwargs.get('slug', '')
  45 + subject = get_object_or_404(Subject, slug = slug)
  46 +
  47 + context['title'] = _('%s - Pendencies')%(subject.name)
  48 + context['subject'] = subject
  49 +
  50 + return context
subjects/templates/subjects/subject_card.html
@@ -37,7 +37,7 @@ @@ -37,7 +37,7 @@
37 37
38 38
39 <a href="" class="pull-right action_icon"><i class="fa fa-bar-chart" aria-hidden="true"></i></a> 39 <a href="" class="pull-right action_icon"><i class="fa fa-bar-chart" aria-hidden="true"></i></a>
40 - <a href="" class="pull-right action_icon"> 40 + <a href="{% url 'notifications:view' subject.slug %}" class="pull-right action_icon">
41 <i class="fa fa-exclamation-triangle" aria-hidden="true"></i> 41 <i class="fa fa-exclamation-triangle" aria-hidden="true"></i>
42 {% notifies_number subject request.user %} 42 {% notifies_number subject request.user %}
43 </a> 43 </a>
subjects/templates/subjects/view.html
@@ -56,7 +56,7 @@ @@ -56,7 +56,7 @@
56 </ul> 56 </ul>
57 {% endif %} 57 {% endif %}
58 <a href="" class="pull-right action_icon"><i class="fa fa-bar-chart" aria-hidden="true"></i></a> 58 <a href="" class="pull-right action_icon"><i class="fa fa-bar-chart" aria-hidden="true"></i></a>
59 - <a href="" class="pull-right action_icon"> 59 + <a href="{% url 'notifications:view' subject.slug %}" class="pull-right action_icon">
60 <i class="fa fa-exclamation-triangle" aria-hidden="true"></i> 60 <i class="fa fa-exclamation-triangle" aria-hidden="true"></i>
61 {% notifies_number subject request.user %} 61 {% notifies_number subject request.user %}
62 </a> 62 </a>
subjects/views.py
@@ -46,7 +46,7 @@ class HomeView(LoginRequiredMixin, ListView): @@ -46,7 +46,7 @@ class HomeView(LoginRequiredMixin, ListView):
46 46
47 subjects = Subject.objects.filter(Q(students__pk=pk) | Q(professor__pk=pk) | Q(category__coordinators__pk=pk)).distinct() 47 subjects = Subject.objects.filter(Q(students__pk=pk) | Q(professor__pk=pk) | Q(category__coordinators__pk=pk)).distinct()
48 48
49 - self.total = len(subjects) 49 + self.total = subjects.count()
50 50
51 return subjects 51 return subjects
52 52
topics/templates/topics/list.html
@@ -34,7 +34,7 @@ @@ -34,7 +34,7 @@
34 </div> 34 </div>
35 </div> 35 </div>
36 </div> 36 </div>
37 - <div id="{{topic.slug}}" class="panel-collapse collapse category-panel-content topic-panel"> 37 + <div id="{{topic.slug}}" class="panel-collapse collapse category-panel-content">
38 <input type="hidden" class="id_inp" name="id" value="{{ topic.id }}" /> 38 <input type="hidden" class="id_inp" name="id" value="{{ topic.id }}" />
39 <input type="hidden" class="order_inp" name="order" value="{{ topic.order }}" /> 39 <input type="hidden" class="order_inp" name="order" value="{{ topic.order }}" />
40 40