Commit 85e518275a0ac14a570fe92fef14254aeb37ec5d

Authored by Jailson Dias
2 parents d473db92 1e152bf2

Merge branch 'refactoring' of https://github.com/amadeusproject/amadeuslms into refactoring

amadeus/static/js/goals_reports.js
@@ -4,8 +4,7 @@ $(function () { @@ -4,8 +4,7 @@ $(function () {
4 4
5 function getAnswered() { 5 function getAnswered() {
6 var container = $("#reports"), 6 var container = $("#reports"),
7 - list = container.find('.answered_data'),  
8 - holder = list.parent().find('.holder'); 7 + list = container.find('.answered_data');
9 8
10 if (list.children().length == 0) { 9 if (list.children().length == 0) {
11 var url = list.parent().data('url'); 10 var url = list.parent().data('url');
@@ -15,13 +14,6 @@ function getAnswered() { @@ -15,13 +14,6 @@ function getAnswered() {
15 success: function (data) { 14 success: function (data) {
16 list.html(data); 15 list.html(data);
17 16
18 - // var form = list.find('.form_search');  
19 -  
20 - // form.submit(function () {  
21 - // searchHistory(panel_id);  
22 -  
23 - // return false;  
24 - // });  
25 $('#answered_table').DataTable({ 17 $('#answered_table').DataTable({
26 "dom": "Bfrtip", 18 "dom": "Bfrtip",
27 "language": dataTablei18n, 19 "language": dataTablei18n,
@@ -44,35 +36,138 @@ function getAnswered() { @@ -44,35 +36,138 @@ function getAnswered() {
44 ] 36 ]
45 } 37 }
46 }); 38 });
47 - // var items = $("#answered_table").children(":visible").length;  
48 -  
49 - // if (items > 10) {  
50 - // holder.jPages({  
51 - // containerID : "answered_table",  
52 - // perPage: 10,  
53 - // previous: "«",  
54 - // next: "»",  
55 - // midRange: 5  
56 - // });  
57 - // }  
58 } 39 }
59 }); 40 });
60 - } else {  
61 - $('#answered_table').DataTable();  
62 - // var items = $("#answered_table").children(":visible").length;  
63 -  
64 - // if (items > 10) {  
65 - // holder.jPages({  
66 - // containerID : "answered_table",  
67 - // perPage: 10,  
68 - // previous: "«",  
69 - // next: "»",  
70 - // midRange: 5  
71 - // });  
72 - // }  
73 } 41 }
74 42
75 container.find('.answered_link').addClass('active'); 43 container.find('.answered_link').addClass('active');
  44 + container.find('.answered').show();
  45 +
  46 + container.find('.unanswered_link').removeClass('active');
  47 + container.find('.unanswered').hide();
  48 +
  49 + container.find('.history_link').removeClass('active');
  50 + container.find('.history').hide();
  51 +
  52 + setBreadcrumb(answeredBread);
  53 +}
  54 +
  55 +function getUnanswered() {
  56 + var container = $("#reports"),
  57 + list = container.find('.unanswered_data');
  58 +
  59 + if (list.children().length == 0) {
  60 + var url = list.parent().data('url');
  61 +
  62 + $.ajax({
  63 + url: url,
  64 + success: function (data) {
  65 + list.html(data);
  66 +
  67 + $('#unanswered_table').DataTable({
  68 + "dom": "Bfrtip",
  69 + "language": dataTablei18n,
  70 + buttons: {
  71 + dom: {
  72 + container: {
  73 + className: 'col-md-3'
  74 + },
  75 + buttonContainer: {
  76 + tag: 'h4',
  77 + className: 'history-header'
  78 + },
  79 + },
  80 + buttons: [
  81 + {
  82 + extend: 'csv',
  83 + text: csvBtnLabeli18n,
  84 + filename: 'report-unanswered'
  85 + }
  86 + ],
  87 + },
  88 + "columns": [
  89 + null,
  90 + null,
  91 + { "orderable": false },
  92 + ]
  93 + });
  94 +
  95 + $("#check_all_rows").click(function () {
  96 + var checked = this.checked;
  97 +
  98 + $('#unanswered_table').find('input[type="checkbox"]').each(function() {
  99 + this.checked = checked;
  100 + });
  101 + });
  102 + }
  103 + });
  104 + }
  105 +
  106 + container.find('.answered_link').removeClass('active');
  107 + container.find('.answered').hide();
  108 +
  109 + container.find('.unanswered_link').addClass('active');
  110 + container.find('.unanswered').show();
  111 +
  112 + container.find('.history_link').removeClass('active');
  113 + container.find('.history').hide();
  114 +
  115 + setBreadcrumb(unansweredBread);
  116 +}
  117 +
  118 +function getHistory() {
  119 + var container = $("#reports"),
  120 + list = container.find('.history_data');
  121 +
  122 + if (list.children().length == 0) {
  123 + var url = list.parent().data('url');
  124 +
  125 + $.ajax({
  126 + url: url,
  127 + success: function (data) {
  128 + list.html(data);
  129 +
  130 + $('#history_table').DataTable({
  131 + "dom": "Bfrtip",
  132 + "language": dataTablei18n,
  133 + buttons: {
  134 + dom: {
  135 + container: {
  136 + className: 'col-md-3'
  137 + },
  138 + buttonContainer: {
  139 + tag: 'h4',
  140 + className: 'history-header'
  141 + },
  142 + },
  143 + buttons: [
  144 + {
  145 + extend: 'csv',
  146 + text: csvBtnLabeli18n,
  147 + filename: 'report-history'
  148 + }
  149 + ],
  150 + },
  151 + });
  152 + }
  153 + });
  154 + }
  155 +
  156 + container.find('.answered_link').removeClass('active');
  157 + container.find('.answered').hide();
  158 +
  159 + container.find('.unanswered_link').removeClass('active');
  160 + container.find('.unanswered').hide();
  161 +
  162 + container.find('.history_link').addClass('active');
  163 + container.find('.history').show();
  164 +
  165 + setBreadcrumb(historyBread);
  166 +}
76 167
77 - container.find('.answered').attr('style', 'display: block'); 168 +function setBreadcrumb(text) {
  169 + var breadcrumb = $(".breadcrumb")[0],
  170 + li = $(breadcrumb).find('li:last-child');
  171 +
  172 + $(li).html(text);
78 } 173 }
79 \ No newline at end of file 174 \ No newline at end of file
goals/templates/goals/_history.html 0 → 100644
@@ -0,0 +1,40 @@ @@ -0,0 +1,40 @@
  1 +{% load i18n goals_filters %}
  2 +
  3 +<div class="row">
  4 + <div class="col-md-12">
  5 + <table id="history_table" class="table table-striped table-bordered">
  6 + <thead>
  7 + <th>
  8 + {% trans 'Date/Hour' %}
  9 + </th>
  10 + <th>
  11 + {% trans 'Student' %}
  12 + </th>
  13 + <th>
  14 + {% trans 'Group' %}
  15 + </th>
  16 + <th>
  17 + {% trans 'Action' %}
  18 + </th>
  19 + <th>
  20 + {% trans 'Object' %}
  21 + </th>
  22 + <th>
  23 + {% trans 'Resource' %}
  24 + </th>
  25 + </thead>
  26 + <tbody>
  27 + {% for row in records %}
  28 + <tr>
  29 + <td>{{ row.datetime }}</td>
  30 + <td>{{ row.user }}</td>
  31 + <td>{{ row.user_id|log_groups }}</td>
  32 + <td>{{ row.action|log_action }}</td>
  33 + <td>{{ row|log_object }}</td>
  34 + <td>{{ row.context.goals_name }}</td>
  35 + </tr>
  36 + {% endfor %}
  37 + </tbody>
  38 + </table>
  39 + </div>
  40 +</div>
0 \ No newline at end of file 41 \ No newline at end of file
goals/templates/goals/_unanswered.html 0 → 100644
@@ -0,0 +1,28 @@ @@ -0,0 +1,28 @@
  1 +{% load i18n goals_filters %}
  2 +
  3 +<div class="row">
  4 + <div class="col-md-12">
  5 + <table id="unanswered_table" class="table table-striped table-bordered">
  6 + <thead>
  7 + <th>
  8 + {% trans 'Student' %}
  9 + </th>
  10 + <th>
  11 + {% trans 'Group' %}
  12 + </th>
  13 + <th>
  14 + <input type="checkbox" id="check_all_rows" /> {% trans 'Select All' %}
  15 + </th>
  16 + </thead>
  17 + <tbody>
  18 + {% for student in students %}
  19 + <tr>
  20 + <td>{{ student }}</td>
  21 + <td>{{ student|groups }}</td>
  22 + <td class="text-center"><input type="checkbox" /></td>
  23 + </tr>
  24 + {% endfor %}
  25 + </tbody>
  26 + </table>
  27 + </div>
  28 +</div>
0 \ No newline at end of file 29 \ No newline at end of file
goals/templates/goals/reports.html
@@ -54,17 +54,22 @@ @@ -54,17 +54,22 @@
54 <div id="reports" class="panel-collapse in collapse category-panel-content"> 54 <div id="reports" class="panel-collapse in collapse category-panel-content">
55 <div id="core-subjects-options-div"> 55 <div id="core-subjects-options-div">
56 <ul class="core-subjects-options"> 56 <ul class="core-subjects-options">
57 - <a href=""><li class="answered_link active">{% trans "Answered" %} ({{ totals.answered }})</li></a>  
58 - <a href=""><li class="">{% trans "Unanswered" %} ({{ totals.unanswered }})</li></a>  
59 - <a href=""><li class="">{% trans "Resource History" %}</li></a> 57 + <a href="javascript:getAnswered()"><li class="answered_link active">{% trans "Answered" %} ({{ totals.answered }})</li></a>
  58 + <a href="javascript:getUnanswered()"><li class="unanswered_link">{% trans "Unanswered" %} ({{ totals.unanswered }})</li></a>
  59 + <a href="javascript:getHistory()"><li class="history_link">{% trans "Resource History" %}</li></a>
60 </ul> 60 </ul>
61 </div> 61 </div>
62 62
63 <div class="answered" data-url="{% url 'goals:answered_report' goal.slug %}"> 63 <div class="answered" data-url="{% url 'goals:answered_report' goal.slug %}">
64 <div class="answered_data"></div> 64 <div class="answered_data"></div>
65 - <div class="text-center">  
66 - <div class="holder"></div>  
67 - </div> 65 + </div>
  66 +
  67 + <div class="unanswered" data-url="{% url 'goals:unanswered_report' goal.slug %}">
  68 + <div class="unanswered_data"></div>
  69 + </div>
  70 +
  71 + <div class="history" data-url="{% url 'goals:history_report' goal.slug %}">
  72 + <div class="history_data"></div>
68 </div> 73 </div>
69 </div> 74 </div>
70 </div> 75 </div>
@@ -95,7 +100,10 @@ @@ -95,7 +100,10 @@
95 } 100 }
96 }; 101 };
97 102
98 - var csvBtnLabeli18n = "<i class='fa fa-download'></i> {% trans 'Download .csv file' %}"; 103 + var csvBtnLabeli18n = "<i class='fa fa-download'></i> {% trans 'Download .csv file' %}",
  104 + answeredBread = "{% trans 'Reports: Answered' %}",
  105 + unansweredBread = "{% trans 'Reports: Unanswered' %}",
  106 + historyBread = "{% trans 'Reports: History' %}";
99 </script> 107 </script>
100 <script type="text/javascript" src="{% static 'js/goals_reports.js' %}"></script> 108 <script type="text/javascript" src="{% static 'js/goals_reports.js' %}"></script>
101 {% endblock %} 109 {% endblock %}
102 \ No newline at end of file 110 \ No newline at end of file
goals/templatetags/goals_filters.py
@@ -3,6 +3,7 @@ from django.utils.translation import ugettext_lazy as _ @@ -3,6 +3,7 @@ from django.utils.translation import ugettext_lazy as _
3 3
4 from goals.models import MyGoals 4 from goals.models import MyGoals
5 from log.models import Log 5 from log.models import Log
  6 +from students_group.models import StudentsGroup
6 7
7 register = template.Library() 8 register = template.Library()
8 9
@@ -17,6 +18,17 @@ def groups(user): @@ -17,6 +18,17 @@ def groups(user):
17 else: 18 else:
18 return "---" 19 return "---"
19 20
  21 +@register.filter(name = 'log_groups')
  22 +def log_groups(user_id):
  23 + groups = StudentsGroup.objects.filter(participants__id = user_id).values_list('name', flat = True)
  24 +
  25 + if groups.count() > 0:
  26 + groups = list(groups)
  27 +
  28 + return ", ".join(groups)
  29 + else:
  30 + return "---"
  31 +
20 @register.filter(name = 'creation_date') 32 @register.filter(name = 'creation_date')
21 def creation_date(user, goal): 33 def creation_date(user, goal):
22 log = Log.objects.filter(user_id = user.id, action = 'submit', resource = 'goals', context__contains = {"goals_id": goal.id}) 34 log = Log.objects.filter(user_id = user.id, action = 'submit', resource = 'goals', context__contains = {"goals_id": goal.id})
@@ -39,4 +51,26 @@ def update_date(user, goal): @@ -39,4 +51,26 @@ def update_date(user, goal):
39 def my_goals(user, goal): 51 def my_goals(user, goal):
40 mine = list(MyGoals.objects.filter(user = user, item__goal = goal).values_list('value', flat = True)) 52 mine = list(MyGoals.objects.filter(user = user, item__goal = goal).values_list('value', flat = True))
41 53
42 - return ', '.join(str(x) for x in mine)  
43 \ No newline at end of file 54 \ No newline at end of file
  55 + return ', '.join(str(x) for x in mine)
  56 +
  57 +@register.filter(name = 'log_action')
  58 +def log_action(action):
  59 + if action == 'view':
  60 + return _('Visualized')
  61 + elif action == 'create':
  62 + return _('Added')
  63 + elif action == 'update':
  64 + return _('Updated')
  65 + elif action == 'submit':
  66 + return _('Submitted')
  67 +
  68 + return '---'
  69 +
  70 +@register.filter(name = 'log_object')
  71 +def log_object(log):
  72 + if log.resource == 'my_goals':
  73 + return _('My Goals')
  74 +
  75 + name = log.context['goals_name']
  76 +
  77 + return _("%s Instance")%(name)
44 \ No newline at end of file 78 \ No newline at end of file
@@ -13,4 +13,6 @@ urlpatterns = [ @@ -13,4 +13,6 @@ urlpatterns = [
13 url(r'^update_submit/(?P<slug>[\w_-]+)/$', views.UpdateSubmit.as_view(), name = 'update_submit'), 13 url(r'^update_submit/(?P<slug>[\w_-]+)/$', views.UpdateSubmit.as_view(), name = 'update_submit'),
14 url(r'^reports/(?P<slug>[\w_-]+)/$', views.Reports.as_view(), name = 'reports'), 14 url(r'^reports/(?P<slug>[\w_-]+)/$', views.Reports.as_view(), name = 'reports'),
15 url(r'^answered_report/(?P<slug>[\w_-]+)/$', views.AnsweredReport.as_view(), name = 'answered_report'), 15 url(r'^answered_report/(?P<slug>[\w_-]+)/$', views.AnsweredReport.as_view(), name = 'answered_report'),
  16 + url(r'^unanswered_report/(?P<slug>[\w_-]+)/$', views.UnansweredReport.as_view(), name = 'unanswered_report'),
  17 + url(r'^history_report/(?P<slug>[\w_-]+)/$', views.HistoryReport.as_view(), name = 'history_report'),
16 ] 18 ]
goals/views.py
@@ -71,7 +71,6 @@ class AnsweredReport(LoginRequiredMixin, generic.ListView): @@ -71,7 +71,6 @@ class AnsweredReport(LoginRequiredMixin, generic.ListView):
71 redirect_field_name = 'next' 71 redirect_field_name = 'next'
72 72
73 template_name = 'goals/_answered.html' 73 template_name = 'goals/_answered.html'
74 - model = MyGoals  
75 context_object_name = 'students' 74 context_object_name = 'students'
76 75
77 def get_queryset(self): 76 def get_queryset(self):
@@ -105,6 +104,80 @@ class AnsweredReport(LoginRequiredMixin, generic.ListView): @@ -105,6 +104,80 @@ class AnsweredReport(LoginRequiredMixin, generic.ListView):
105 104
106 return context 105 return context
107 106
  107 +class UnansweredReport(LoginRequiredMixin, generic.ListView):
  108 + login_url = reverse_lazy("users:login")
  109 + redirect_field_name = 'next'
  110 +
  111 + template_name = 'goals/_unanswered.html'
  112 + context_object_name = 'students'
  113 +
  114 + def get_queryset(self):
  115 + slug = self.kwargs.get('slug', '')
  116 + goal = get_object_or_404(Goals, slug = slug)
  117 +
  118 + users = goal.topic.subject.students.values_list('id', flat = True)
  119 +
  120 + submited = Log.objects.filter(user_id__in = users, action = 'submit', resource = 'goals', context__contains = {"goals_id": goal.id}).values_list('user_id', flat = True)
  121 +
  122 + users = [i for i in users if i not in submited]
  123 +
  124 + submited_users = User.objects.filter(id__in = users)
  125 +
  126 + return submited_users
  127 +
  128 + def dispatch(self, request, *args, **kwargs):
  129 + slug = self.kwargs.get('slug', '')
  130 + goals = get_object_or_404(Goals, slug = slug)
  131 +
  132 + if not has_resource_permissions(request.user, goals):
  133 + return redirect(reverse_lazy('subjects:home'))
  134 +
  135 + return super(UnansweredReport, self).dispatch(request, *args, **kwargs)
  136 +
  137 + def get_context_data(self, **kwargs):
  138 + context = super(UnansweredReport, self).get_context_data(**kwargs)
  139 +
  140 + slug = self.kwargs.get('slug', '')
  141 + goals = get_object_or_404(Goals, slug = slug)
  142 +
  143 + context['goal'] = goals
  144 +
  145 + return context
  146 +
  147 +class HistoryReport(LoginRequiredMixin, generic.ListView):
  148 + login_url = reverse_lazy("users:login")
  149 + redirect_field_name = 'next'
  150 +
  151 + template_name = 'goals/_history.html'
  152 + context_object_name = 'records'
  153 +
  154 + def get_queryset(self):
  155 + slug = self.kwargs.get('slug', '')
  156 + goal = get_object_or_404(Goals, slug = slug)
  157 +
  158 + rows = Log.objects.filter(context__contains = {"goals_id": goal.id})
  159 +
  160 + return rows
  161 +
  162 + def dispatch(self, request, *args, **kwargs):
  163 + slug = self.kwargs.get('slug', '')
  164 + goals = get_object_or_404(Goals, slug = slug)
  165 +
  166 + if not has_resource_permissions(request.user, goals):
  167 + return redirect(reverse_lazy('subjects:home'))
  168 +
  169 + return super(HistoryReport, self).dispatch(request, *args, **kwargs)
  170 +
  171 + def get_context_data(self, **kwargs):
  172 + context = super(HistoryReport, self).get_context_data(**kwargs)
  173 +
  174 + slug = self.kwargs.get('slug', '')
  175 + goals = get_object_or_404(Goals, slug = slug)
  176 +
  177 + context['goal'] = goals
  178 +
  179 + return context
  180 +
108 class InsideView(LoginRequiredMixin, LogMixin, generic.ListView): 181 class InsideView(LoginRequiredMixin, LogMixin, generic.ListView):
109 log_component = "resources" 182 log_component = "resources"
110 log_action = "view" 183 log_action = "view"