Commit 8ea129f2b12465d37c3bb9435b21a8684555a67a

Authored by Jailson Dias
2 parents ca2bad40 bdf7d172

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

api/templates/api/report.html
... ... @@ -1,31 +0,0 @@
1   -{% extends 'base.html' %}
2   -
3   -{% load static i18n pagination %}
4   -{% load django_bootstrap_breadcrumbs %}
5   -
6   -{% block breadcrumbs %}
7   - {{ block.super }}
8   -
9   - {% trans 'Mural: General' as general %}
10   -
11   - {% breadcrumb general 'mural:manage_general' %}
12   -{% endblock %}
13   -
14   -{% block content %}
15   -
16   -
17   - {% for user, datum in data.items %}
18   -
19   -
20   - <p>
21   - <ul>
22   -
23   - {{user}} :
24   - {% for key, value in datum.items %}
25   - <li>{{key}}: {{value}}</li>
26   - {% endfor %}
27   - </ul>
28   -
29   - </p>
30   - {% endfor %}
31   -{% endblock content %}
32 0 \ No newline at end of file
api/urls.py
... ... @@ -14,7 +14,6 @@ router.register(r&#39;usersapi&#39;, UserViewSet)
14 14  
15 15 urlpatterns = [
16 16 #API REST
17   - url(r'^report/$', views.ReportView.as_view(), name='report'),
18 17  
19 18 url(r'^', include(router.urls)),
20 19 ]
21 20 \ No newline at end of file
... ...
api/views.py
1 1 from django.shortcuts import render
2   -from django.http import HttpResponse, JsonResponse
3   -
4   -
5   -import django.views.generic as generic
6   -from mural.models import SubjectPost, Comment, MuralVisualizations
7   -from django.db.models import Q
8   -from django.contrib.auth.mixins import LoginRequiredMixin
9   -from datetime import datetime, date
10   -from subjects.models import Subject
11   -
12   -from log.models import Log
13   -
14   -class ReportView(LoginRequiredMixin, generic.TemplateView):
15   - template_name = "api/report.html"
16   -
17   - def get_context_data(self, **kwargs):
18   - context = {}
19   - params = self.request.GET
20   -
21   - if params['subject_id'] and params['init_date'] and params['end_date']:
22   - subject_id = params['subject_id']
23   - subject = Subject.objects.get(id=subject_id)
24   - data = {}
25   - students = subject.students.all()
26   - formats = ["%d/%m/%Y", "%m/%d/%Y"] #so it accepts english and portuguese date formats
27   - for fmt in formats:
28   - try:
29   - init_date = datetime.strptime(params['init_date'], fmt)
30   - end_date = datetime.strptime(params['end_date'], fmt)
31   - except ValueError:
32   - pass
33   -
34   - for student in students:
35   - interactions = {}
36   - #first columns
37   - interactions['subject_name'] = subject.name
38   - interactions['username'] = student.social_name
39   - interactions['init_date'] = init_date
40   - interactions['end_date'] = end_date
41   -
42   - help_posts_made_by_user = SubjectPost.objects.filter(action="help",space__id=subject.id, user=student,
43   - create_date__range=(init_date, end_date))
44   -
45   - #number of help posts created by the student
46   - interactions['doubts_count'] = help_posts_made_by_user.count()
47   -
48   - help_posts = SubjectPost.objects.filter(action="help", create_date__range=(init_date, end_date),
49   - space__id=subject_id)
50   -
51   - #comments count on help posts created by the student
52   - interactions['comments_count'] = Comment.objects.filter(post__in = help_posts.filter(user=student),
53   - create_date__range=(init_date, end_date)).count()
54   -
55   -
56   - #count the amount of comments made by the student on posts made by one of the professors
57   - interactions['comments_professor_count'] = Comment.objects.filter(post__in = help_posts.filter(user__in= subject.professor.all()), create_date__range=(init_date, end_date),
58   - user=student).count()
59   -
60   - #comments made by the user on other users posts
61   - interactions['comments_on_others_count'] = Comment.objects.filter(post__in = help_posts.exclude(user=student),
62   - create_date__range=(init_date, end_date),
63   - user= student).count()
64   -
65   -
66   -
67   - comments_by_teacher = Comment.objects.filter(user__in=subject.professor.all())
68   - help_posts_ids = []
69   - for comment in comments_by_teacher:
70   - help_posts_ids.append(comment.post.id)
71   - #number of help posts created by the user that the teacher commented on
72   - interactions['help_posts_commented_by_teacher'] = help_posts.filter(user=student, id__in = help_posts_ids).count()
73   -
74   -
75   - comments_by_others = Comment.objects.filter(user__in=subject.students.exclude(id = student.id))
76   - help_posts_ids = []
77   - for comment in comments_by_teacher:
78   - help_posts_ids.append(comment.post.id)
79   - #number of help posts created by the user others students commented on
80   - interactions['help_posts_commented_by_others'] = help_posts.filter(user=student, id__in = help_posts_ids).count()
81   -
82   - #Number of student visualizations on the mural of the subject
83   - interactions['mural_visualizations_count'] = MuralVisualizations.objects.filter(post__in = SubjectPost.objects.filter(space__id=subject.id),
84   - user = student).count()
85   -
86   -
87   - #VAR20 - number of access to mural between 6 a.m to 12a.m.
88   - interactions['access_subject_between_6_to_12_am'] = Log.objects.filter(action="access", resource="subject",
89   - user_id= student.id, context__contains = {'subject_id' : subject.id}, datetime__hour__range = (5, 11)).count()
90   -
91   - #VAR21 - number of access to mural between 6 a.m to 12a.m.
92   - interactions['access_subject_between_0_to_6_pm'] = Log.objects.filter(action="access", resource="subject",
93   - user_id= student.id, context__contains = {'subject_id' : subject.id}, datetime__hour__range = (11, 17)).count()
94   - #VAR22
95   - interactions['access_subject_between_6_to_12_pm'] = Log.objects.filter(action="access", resource="subject",
96   - user_id= student.id, context__contains = {'subject_id' : subject.id}, datetime__hour__range = (17, 23)).count()
97   -
98   - #VAR23
99   - interactions['access_subject_between_0_to_6_am'] = Log.objects.filter(action="access", resource="subject",
100   - user_id= student.id, context__contains = {'subject_id' : subject.id}, datetime__hour__range = (23, 5)).count()
101   -
102   - #VAR24 through 30
103   - day_numbers = [0, 1, 2, 3, 4, 5, 6]
104   - day_names = ["sunday", "monday", "tuesday", "wednesday", "thursday", "friday", "saturday"]
105   - for day_num in day_numbers:
106   - interactions['access_subject_'+day_names[day_num]] = Log.objects.filter(action="access", resource="subject",
107   - user_id= student.id, context__contains = {'subject_id' : subject.id}, datetime__week_day = day_num).count()
108   -
109   - data[student] = interactions
110   -
111   - context["data"] = data
112   -
113   -
114   - return context
115   -
116 2  
... ...
goals/templates/goals/_form_submit.html
... ... @@ -8,8 +8,10 @@
8 8 {{ my_goals_formset.non_form_errors }}
9 9  
10 10 {% for form, item in my_goals_formset|zip:goals.item_goal.all %}
11   - {% render_field form.id %}
12   - {% render_field form.item %}
  11 + {% for hidden in form.hidden_fields %}
  12 + {{ hidden }}
  13 + {% endfor %}
  14 +
13 15 {{ form.errors }}
14 16  
15 17 {% if form.instance.pk %}{{ form.DELETE }}{% endif %}
... ...
goals/templates/goals/reports.html 0 → 100644
... ... @@ -0,0 +1,58 @@
  1 +{% extends 'subjects/view.html' %}
  2 +
  3 +{% load static i18n pagination permissions_tags subject_counter %}
  4 +{% load django_bootstrap_breadcrumbs %}
  5 +
  6 +{% block style %}
  7 + {{block.super}}
  8 +{% endblock %}
  9 +
  10 +{% block javascript%}
  11 + {{ block.super }}
  12 +{% endblock%}
  13 +
  14 +{% block breadcrumbs %}
  15 + {{ block.super }}
  16 + {% breadcrumb topic 'subjects:topic_view' subject.slug topic.slug %}
  17 + {% breadcrumb goal 'goals:submit' goal.slug %}
  18 +
  19 + {% trans 'Reports: Answered' as bread %}
  20 + {% breadcrumb bread 'goals:answered_reports' goal.slug %}
  21 +{% endblock %}
  22 +
  23 +{% block content %}
  24 + {% resource_permissions request.user goal as has_resource_permissions %}
  25 +
  26 + {% if goal.visible %}
  27 + <div class="panel panel-info topic-panel">
  28 + <div class="panel-heading">
  29 + {% elif has_resource_permissions %}
  30 + <div class="panel panel-info topic-panel-invisible">
  31 + <div class="panel-heading panel-invisible">
  32 + {% endif %}
  33 + <div class="row">
  34 + <div class="col-md-12 category-header">
  35 + <h4 class="panel-title" style="margin-top: 10px; margin-bottom: 8px">
  36 + <span>{{ goal }}</span>
  37 + </h4>
  38 +
  39 + <div class="col-md-5 pull-right category-card-items">
  40 + <a href="{% url 'mural:resource_view' goal.slug %}" class="pull-right action_icon">
  41 + <i class="fa fa-list" aria-hidden="true"></i>
  42 + {% resource_mural_number goal request.user %}
  43 + </a>
  44 + </div>
  45 + </div>
  46 + </div>
  47 + </div>
  48 + <div id="{{subject.slug}}" class="panel-collapse in collapse category-panel-content">
  49 + <div id="core-subjects-options-div">
  50 + <ul class="core-subjects-options">
  51 + <a href=""><li class="active">{% trans "Answered" %}</li></a>
  52 + <a href=""><li class="">{% trans "Unanswered" %}</li></a>
  53 + <a href=""><li class="">{% trans "Resource History" %}</li></a>
  54 + </ul>
  55 + </div>
  56 + </div>
  57 + </div>
  58 +{% endblock %}
0 59 \ No newline at end of file
... ...
goals/urls.py
... ... @@ -11,4 +11,5 @@ urlpatterns = [
11 11 url(r'^view/(?P<slug>[\w_-]+)/$', views.InsideView.as_view(), name = 'view'),
12 12 url(r'^submit/(?P<slug>[\w_-]+)/$', views.SubmitView.as_view(), name = 'submit'),
13 13 url(r'^update_submit/(?P<slug>[\w_-]+)/$', views.UpdateSubmit.as_view(), name = 'update_submit'),
  14 + url(r'^answered_reports/(?P<slug>[\w_-]+)/$', views.AnsweredReport.as_view(), name = 'answered_reports'),
14 15 ]
... ...
goals/views.py
... ... @@ -6,6 +6,11 @@ from django.utils.translation import ugettext_lazy as _
6 6 from django.contrib.auth.mixins import LoginRequiredMixin
7 7 from django.forms import formset_factory, modelformset_factory
8 8  
  9 +from log.models import Log
  10 +from log.mixins import LogMixin
  11 +from log.decorators import log_decorator, log_decorator_ajax
  12 +import time
  13 +
9 14 from amadeus.permissions import has_subject_permissions, has_resource_permissions
10 15  
11 16 from topics.models import Topic
... ... @@ -13,7 +18,51 @@ from topics.models import Topic
13 18 from .forms import GoalsForm, MyGoalsForm, InlinePendenciesFormset, InlineGoalItemFormset
14 19 from .models import Goals, MyGoals
15 20  
16   -class InsideView(LoginRequiredMixin, generic.ListView):
  21 +class AnsweredReport(LoginRequiredMixin, generic.ListView):
  22 + login_url = reverse_lazy("users:login")
  23 + redirect_field_name = 'next'
  24 +
  25 + template_name = 'goals/reports.html'
  26 + model = MyGoals
  27 + context_object_name = 'answered'
  28 +
  29 + def get_queryset(self):
  30 + slug = self.kwargs.get('slug', '')
  31 + goal = get_object_or_404(Goals, slug = slug)
  32 +
  33 + goals = MyGoals.objects.filter(item__goal = goal)
  34 +
  35 + return goals
  36 +
  37 + def dispatch(self, request, *args, **kwargs):
  38 + slug = self.kwargs.get('slug', '')
  39 + goals = get_object_or_404(Goals, slug = slug)
  40 +
  41 + if not has_resource_permissions(request.user, goals):
  42 + return redirect(reverse_lazy('subjects:home'))
  43 +
  44 + return super(AnsweredReport, self).dispatch(request, *args, **kwargs)
  45 +
  46 + def get_context_data(self, **kwargs):
  47 + context = super(AnsweredReport, self).get_context_data(**kwargs)
  48 +
  49 + slug = self.kwargs.get('slug', '')
  50 + goals = get_object_or_404(Goals, slug = slug)
  51 +
  52 + context['title'] = _("Reports: Answered")
  53 +
  54 + context['goal'] = goals
  55 + context['topic'] = goals.topic
  56 + context['subject'] = goals.topic.subject
  57 +
  58 + return context
  59 +
  60 +class InsideView(LoginRequiredMixin, LogMixin, generic.ListView):
  61 + log_component = "resources"
  62 + log_action = "view"
  63 + log_resource = "my_goals"
  64 + log_context = {}
  65 +
17 66 login_url = reverse_lazy("users:login")
18 67 redirect_field_name = 'next'
19 68  
... ... @@ -50,9 +99,32 @@ class InsideView(LoginRequiredMixin, generic.ListView):
50 99 context['topic'] = goals.topic
51 100 context['subject'] = goals.topic.subject
52 101  
  102 + self.log_context['category_id'] = goals.topic.subject.category.id
  103 + self.log_context['category_name'] = goals.topic.subject.category.name
  104 + self.log_context['category_slug'] = goals.topic.subject.category.slug
  105 + self.log_context['subject_id'] = goals.topic.subject.id
  106 + self.log_context['subject_name'] = goals.topic.subject.name
  107 + self.log_context['subject_slug'] = goals.topic.subject.slug
  108 + self.log_context['topic_id'] = goals.topic.id
  109 + self.log_context['topic_name'] = goals.topic.name
  110 + self.log_context['topic_slug'] = goals.topic.slug
  111 + self.log_context['goals_id'] = goals.id
  112 + self.log_context['goals_name'] = goals.name
  113 + self.log_context['goals_slug'] = goals.slug
  114 + self.log_context['timestamp_start'] = str(int(time.time()))
  115 +
  116 + super(InsideView, self).createLog(self.request.user, self.log_component, self.log_action, self.log_resource, self.log_context)
  117 +
  118 + self.request.session['log_id'] = Log.objects.latest('id').id
  119 +
53 120 return context
54 121  
55   -class NewWindowSubmit(LoginRequiredMixin, generic.edit.CreateView):
  122 +class NewWindowSubmit(LoginRequiredMixin, LogMixin, generic.edit.CreateView):
  123 + log_component = "resources"
  124 + log_action = "submit"
  125 + log_resource = "goals"
  126 + log_context = {}
  127 +
56 128 login_url = reverse_lazy("users:login")
57 129 redirect_field_name = 'next'
58 130  
... ... @@ -82,6 +154,28 @@ class NewWindowSubmit(LoginRequiredMixin, generic.edit.CreateView):
82 154  
83 155 MyGoalsFormset = formset_factory(MyGoalsForm, extra = 0)
84 156 my_goals_formset = MyGoalsFormset(initial = [{'item': x.id, 'value': x.ref_value} for x in goals.item_goal.all()])
  157 +
  158 + self.log_action = "view"
  159 +
  160 + self.log_context['category_id'] = goals.topic.subject.category.id
  161 + self.log_context['category_name'] = goals.topic.subject.category.name
  162 + self.log_context['category_slug'] = goals.topic.subject.category.slug
  163 + self.log_context['subject_id'] = goals.topic.subject.id
  164 + self.log_context['subject_name'] = goals.topic.subject.name
  165 + self.log_context['subject_slug'] = goals.topic.subject.slug
  166 + self.log_context['topic_id'] = goals.topic.id
  167 + self.log_context['topic_name'] = goals.topic.name
  168 + self.log_context['topic_slug'] = goals.topic.slug
  169 + self.log_context['goals_id'] = goals.id
  170 + self.log_context['goals_name'] = goals.name
  171 + self.log_context['goals_slug'] = goals.slug
  172 + self.log_context['timestamp_start'] = str(int(time.time()))
  173 +
  174 + super(NewWindowSubmit, self).createLog(self.request.user, self.log_component, self.log_action, self.log_resource, self.log_context)
  175 +
  176 + self.request.session['log_id'] = Log.objects.latest('id').id
  177 +
  178 + self.log_context = {}
85 179  
86 180 return self.render_to_response(self.get_context_data(my_goals_formset = my_goals_formset))
87 181  
... ... @@ -134,9 +228,29 @@ class NewWindowSubmit(LoginRequiredMixin, generic.edit.CreateView):
134 228  
135 229 success_url = reverse_lazy('goals:view', kwargs = {'slug': slug})
136 230  
  231 + self.log_context['category_id'] = goals.topic.subject.category.id
  232 + self.log_context['category_name'] = goals.topic.subject.category.name
  233 + self.log_context['category_slug'] = goals.topic.subject.category.slug
  234 + self.log_context['subject_id'] = goals.topic.subject.id
  235 + self.log_context['subject_name'] = goals.topic.subject.name
  236 + self.log_context['subject_slug'] = goals.topic.subject.slug
  237 + self.log_context['topic_id'] = goals.topic.id
  238 + self.log_context['topic_name'] = goals.topic.name
  239 + self.log_context['topic_slug'] = goals.topic.slug
  240 + self.log_context['goals_id'] = goals.id
  241 + self.log_context['goals_name'] = goals.name
  242 + self.log_context['goals_slug'] = goals.slug
  243 +
  244 + super(NewWindowSubmit, self).createLog(self.request.user, self.log_component, self.log_action, self.log_resource, self.log_context)
  245 +
137 246 return success_url
138 247  
139   -class SubmitView(LoginRequiredMixin, generic.edit.CreateView):
  248 +class SubmitView(LoginRequiredMixin, LogMixin, generic.edit.CreateView):
  249 + log_component = "resources"
  250 + log_action = "submit"
  251 + log_resource = "goals"
  252 + log_context = {}
  253 +
140 254 login_url = reverse_lazy("users:login")
141 255 redirect_field_name = 'next'
142 256  
... ... @@ -166,6 +280,28 @@ class SubmitView(LoginRequiredMixin, generic.edit.CreateView):
166 280  
167 281 MyGoalsFormset = formset_factory(MyGoalsForm, extra = 0)
168 282 my_goals_formset = MyGoalsFormset(initial = [{'item': x.id, 'value': x.ref_value} for x in goals.item_goal.all()])
  283 +
  284 + self.log_action = "view"
  285 +
  286 + self.log_context['category_id'] = goals.topic.subject.category.id
  287 + self.log_context['category_name'] = goals.topic.subject.category.name
  288 + self.log_context['category_slug'] = goals.topic.subject.category.slug
  289 + self.log_context['subject_id'] = goals.topic.subject.id
  290 + self.log_context['subject_name'] = goals.topic.subject.name
  291 + self.log_context['subject_slug'] = goals.topic.subject.slug
  292 + self.log_context['topic_id'] = goals.topic.id
  293 + self.log_context['topic_name'] = goals.topic.name
  294 + self.log_context['topic_slug'] = goals.topic.slug
  295 + self.log_context['goals_id'] = goals.id
  296 + self.log_context['goals_name'] = goals.name
  297 + self.log_context['goals_slug'] = goals.slug
  298 + self.log_context['timestamp_start'] = str(int(time.time()))
  299 +
  300 + super(SubmitView, self).createLog(self.request.user, self.log_component, self.log_action, self.log_resource, self.log_context)
  301 +
  302 + self.request.session['log_id'] = Log.objects.latest('id').id
  303 +
  304 + self.log_context = {}
169 305  
170 306 return self.render_to_response(self.get_context_data(my_goals_formset = my_goals_formset))
171 307  
... ... @@ -220,9 +356,29 @@ class SubmitView(LoginRequiredMixin, generic.edit.CreateView):
220 356  
221 357 success_url = reverse_lazy('goals:view', kwargs = {'slug': slug})
222 358  
  359 + self.log_context['category_id'] = goals.topic.subject.category.id
  360 + self.log_context['category_name'] = goals.topic.subject.category.name
  361 + self.log_context['category_slug'] = goals.topic.subject.category.slug
  362 + self.log_context['subject_id'] = goals.topic.subject.id
  363 + self.log_context['subject_name'] = goals.topic.subject.name
  364 + self.log_context['subject_slug'] = goals.topic.subject.slug
  365 + self.log_context['topic_id'] = goals.topic.id
  366 + self.log_context['topic_name'] = goals.topic.name
  367 + self.log_context['topic_slug'] = goals.topic.slug
  368 + self.log_context['goals_id'] = goals.id
  369 + self.log_context['goals_name'] = goals.name
  370 + self.log_context['goals_slug'] = goals.slug
  371 +
  372 + super(SubmitView, self).createLog(self.request.user, self.log_component, self.log_action, self.log_resource, self.log_context)
  373 +
223 374 return success_url
224 375  
225   -class UpdateSubmit(LoginRequiredMixin, generic.UpdateView):
  376 +class UpdateSubmit(LoginRequiredMixin, LogMixin, generic.UpdateView):
  377 + log_component = "resources"
  378 + log_action = "update"
  379 + log_resource = "my_goals"
  380 + log_context = {}
  381 +
226 382 login_url = reverse_lazy("users:login")
227 383 redirect_field_name = 'next'
228 384  
... ... @@ -254,7 +410,7 @@ class UpdateSubmit(LoginRequiredMixin, generic.UpdateView):
254 410 goals = get_object_or_404(Goals, slug = slug)
255 411  
256 412 MyGoalsFormset = modelformset_factory(MyGoals, form = MyGoalsForm, extra = 0)
257   - my_goals_formset = MyGoalsFormset()
  413 + my_goals_formset = MyGoalsFormset(queryset = MyGoals.objects.filter(user = request.user, item__goal = goals))
258 414  
259 415 return self.render_to_response(self.get_context_data(my_goals_formset = my_goals_formset))
260 416  
... ... @@ -268,7 +424,7 @@ class UpdateSubmit(LoginRequiredMixin, generic.UpdateView):
268 424 goals = get_object_or_404(Goals, slug = slug)
269 425  
270 426 MyGoalsFormset = modelformset_factory(MyGoals, form = MyGoalsForm, extra = 0)
271   - my_goals_formset = MyGoalsFormset(self.request.POST)
  427 + my_goals_formset = MyGoalsFormset(self.request.POST, queryset = MyGoals.objects.filter(user = request.user, item__goal = goals))
272 428  
273 429 if (my_goals_formset.is_valid()):
274 430 return self.form_valid(my_goals_formset)
... ... @@ -308,9 +464,29 @@ class UpdateSubmit(LoginRequiredMixin, generic.UpdateView):
308 464  
309 465 success_url = reverse_lazy('goals:view', kwargs = {'slug': slug})
310 466  
  467 + self.log_context['category_id'] = goals.topic.subject.category.id
  468 + self.log_context['category_name'] = goals.topic.subject.category.name
  469 + self.log_context['category_slug'] = goals.topic.subject.category.slug
  470 + self.log_context['subject_id'] = goals.topic.subject.id
  471 + self.log_context['subject_name'] = goals.topic.subject.name
  472 + self.log_context['subject_slug'] = goals.topic.subject.slug
  473 + self.log_context['topic_id'] = goals.topic.id
  474 + self.log_context['topic_name'] = goals.topic.name
  475 + self.log_context['topic_slug'] = goals.topic.slug
  476 + self.log_context['goals_id'] = goals.id
  477 + self.log_context['goals_name'] = goals.name
  478 + self.log_context['goals_slug'] = goals.slug
  479 +
  480 + super(UpdateSubmit, self).createLog(self.request.user, self.log_component, self.log_action, self.log_resource, self.log_context)
  481 +
311 482 return success_url
312 483  
313   -class CreateView(LoginRequiredMixin, generic.edit.CreateView):
  484 +class CreateView(LoginRequiredMixin, LogMixin, generic.edit.CreateView):
  485 + log_component = "resources"
  486 + log_action = "create"
  487 + log_resource = "goals"
  488 + log_context = {}
  489 +
314 490 login_url = reverse_lazy("users:login")
315 491 redirect_field_name = 'next'
316 492  
... ... @@ -413,6 +589,21 @@ class CreateView(LoginRequiredMixin, generic.edit.CreateView):
413 589  
414 590 g_order += 1
415 591  
  592 + self.log_context['category_id'] = self.object.topic.subject.category.id
  593 + self.log_context['category_name'] = self.object.topic.subject.category.name
  594 + self.log_context['category_slug'] = self.object.topic.subject.category.slug
  595 + self.log_context['subject_id'] = self.object.topic.subject.id
  596 + self.log_context['subject_name'] = self.object.topic.subject.name
  597 + self.log_context['subject_slug'] = self.object.topic.subject.slug
  598 + self.log_context['topic_id'] = self.object.topic.id
  599 + self.log_context['topic_name'] = self.object.topic.name
  600 + self.log_context['topic_slug'] = self.object.topic.slug
  601 + self.log_context['goals_id'] = self.object.id
  602 + self.log_context['goals_name'] = self.object.name
  603 + self.log_context['goals_slug'] = self.object.slug
  604 +
  605 + super(CreateView, self).createLog(self.request.user, self.log_component, self.log_action, self.log_resource, self.log_context)
  606 +
416 607 return redirect(self.get_success_url())
417 608  
418 609 def get_context_data(self, **kwargs):
... ... @@ -442,7 +633,12 @@ class CreateView(LoginRequiredMixin, generic.edit.CreateView):
442 633  
443 634 return success_url
444 635  
445   -class UpdateView(LoginRequiredMixin, generic.UpdateView):
  636 +class UpdateView(LoginRequiredMixin, LogMixin, generic.UpdateView):
  637 + log_component = "resources"
  638 + log_action = "update"
  639 + log_resource = "goals"
  640 + log_context = {}
  641 +
446 642 login_url = reverse_lazy("users:login")
447 643 redirect_field_name = 'next'
448 644  
... ... @@ -528,6 +724,21 @@ class UpdateView(LoginRequiredMixin, generic.UpdateView):
528 724  
529 725 g_order += 1
530 726  
  727 + self.log_context['category_id'] = self.object.topic.subject.category.id
  728 + self.log_context['category_name'] = self.object.topic.subject.category.name
  729 + self.log_context['category_slug'] = self.object.topic.subject.category.slug
  730 + self.log_context['subject_id'] = self.object.topic.subject.id
  731 + self.log_context['subject_name'] = self.object.topic.subject.name
  732 + self.log_context['subject_slug'] = self.object.topic.subject.slug
  733 + self.log_context['topic_id'] = self.object.topic.id
  734 + self.log_context['topic_name'] = self.object.topic.name
  735 + self.log_context['topic_slug'] = self.object.topic.slug
  736 + self.log_context['goals_id'] = self.object.id
  737 + self.log_context['goals_name'] = self.object.name
  738 + self.log_context['goals_slug'] = self.object.slug
  739 +
  740 + super(UpdateView, self).createLog(self.request.user, self.log_component, self.log_action, self.log_resource, self.log_context)
  741 +
531 742 return redirect(self.get_success_url())
532 743  
533 744 def get_context_data(self, **kwargs):
... ... @@ -557,7 +768,12 @@ class UpdateView(LoginRequiredMixin, generic.UpdateView):
557 768  
558 769 return success_url
559 770  
560   -class DeleteView(LoginRequiredMixin, generic.DeleteView):
  771 +class DeleteView(LoginRequiredMixin, LogMixin, generic.DeleteView):
  772 + log_component = "resources"
  773 + log_action = "delete"
  774 + log_resource = "goals"
  775 + log_context = {}
  776 +
561 777 login_url = reverse_lazy("users:login")
562 778 redirect_field_name = 'next'
563 779  
... ... @@ -577,4 +793,19 @@ class DeleteView(LoginRequiredMixin, generic.DeleteView):
577 793 def get_success_url(self):
578 794 messages.success(self.request, _('The Goals specification of the thopic %s was removed successfully!')%(self.object.topic.name))
579 795  
  796 + self.log_context['category_id'] = self.object.topic.subject.category.id
  797 + self.log_context['category_name'] = self.object.topic.subject.category.name
  798 + self.log_context['category_slug'] = self.object.topic.subject.category.slug
  799 + self.log_context['subject_id'] = self.object.topic.subject.id
  800 + self.log_context['subject_name'] = self.object.topic.subject.name
  801 + self.log_context['subject_slug'] = self.object.topic.subject.slug
  802 + self.log_context['topic_id'] = self.object.topic.id
  803 + self.log_context['topic_name'] = self.object.topic.name
  804 + self.log_context['topic_slug'] = self.object.topic.slug
  805 + self.log_context['goals_id'] = self.object.id
  806 + self.log_context['goals_name'] = self.object.name
  807 + self.log_context['goals_slug'] = self.object.slug
  808 +
  809 + super(DeleteView, self).createLog(self.request.user, self.log_component, self.log_action, self.log_resource, self.log_context)
  810 +
580 811 return reverse_lazy('subjects:view', kwargs = {'slug': self.object.topic.subject.slug})
581 812 \ No newline at end of file
... ...
reports/__init__.py 0 → 100644
reports/admin.py 0 → 100644
... ... @@ -0,0 +1,3 @@
  1 +from django.contrib import admin
  2 +
  3 +# Register your models here.
... ...
reports/apps.py 0 → 100644
... ... @@ -0,0 +1,5 @@
  1 +from django.apps import AppConfig
  2 +
  3 +
  4 +class ReportsConfig(AppConfig):
  5 + name = 'reports'
... ...
reports/migrations/__init__.py 0 → 100644
reports/models.py 0 → 100644
... ... @@ -0,0 +1,3 @@
  1 +from django.db import models
  2 +
  3 +# Create your models here.
... ...
reports/templates/reports/report.html 0 → 100644
... ... @@ -0,0 +1,31 @@
  1 +{% extends 'base.html' %}
  2 +
  3 +{% load static i18n pagination %}
  4 +{% load django_bootstrap_breadcrumbs %}
  5 +
  6 +{% block breadcrumbs %}
  7 + {{ block.super }}
  8 +
  9 + {% trans 'Mural: General' as general %}
  10 +
  11 + {% breadcrumb general 'mural:manage_general' %}
  12 +{% endblock %}
  13 +
  14 +{% block content %}
  15 +
  16 +
  17 + {% for user, datum in data.items %}
  18 +
  19 +
  20 + <p>
  21 + <ul>
  22 +
  23 + {{user}} :
  24 + {% for key, value in datum.items %}
  25 + <li>{{key}}: {{value}}</li>
  26 + {% endfor %}
  27 + </ul>
  28 +
  29 + </p>
  30 + {% endfor %}
  31 +{% endblock content %}
0 32 \ No newline at end of file
... ...
reports/tests.py 0 → 100644
... ... @@ -0,0 +1,3 @@
  1 +from django.test import TestCase
  2 +
  3 +# Create your tests here.
... ...
reports/urls.py 0 → 100644
... ... @@ -0,0 +1,7 @@
  1 +from django.conf.urls import url, include
  2 +from . import views
  3 +
  4 +
  5 +urlpatterns = [
  6 + url(r'^report/$', views.ReportView.as_view(), name='report'),
  7 +]
0 8 \ No newline at end of file
... ...
reports/views.py 0 → 100644
... ... @@ -0,0 +1,116 @@
  1 +from django.shortcuts import render
  2 +from django.http import HttpResponse, JsonResponse
  3 +
  4 +
  5 +import django.views.generic as generic
  6 +from mural.models import SubjectPost, Comment, MuralVisualizations
  7 +from django.db.models import Q
  8 +from django.contrib.auth.mixins import LoginRequiredMixin
  9 +from datetime import datetime, date
  10 +from subjects.models import Subject
  11 +
  12 +from log.models import Log
  13 +
  14 +class ReportView(LoginRequiredMixin, generic.TemplateView):
  15 + template_name = "api/report.html"
  16 +
  17 + def get_context_data(self, **kwargs):
  18 + context = {}
  19 + params = self.request.GET
  20 +
  21 + if params['subject_id'] and params['init_date'] and params['end_date']:
  22 + subject_id = params['subject_id']
  23 + subject = Subject.objects.get(id=subject_id)
  24 + data = {}
  25 + students = subject.students.all()
  26 + formats = ["%d/%m/%Y", "%m/%d/%Y"] #so it accepts english and portuguese date formats
  27 + for fmt in formats:
  28 + try:
  29 + init_date = datetime.strptime(params['init_date'], fmt)
  30 + end_date = datetime.strptime(params['end_date'], fmt)
  31 + except ValueError:
  32 + pass
  33 +
  34 + for student in students:
  35 + interactions = {}
  36 + #first columns
  37 + interactions['subject_name'] = subject.name
  38 + interactions['username'] = student.social_name
  39 + interactions['init_date'] = init_date
  40 + interactions['end_date'] = end_date
  41 +
  42 + help_posts_made_by_user = SubjectPost.objects.filter(action="help",space__id=subject.id, user=student,
  43 + create_date__range=(init_date, end_date))
  44 +
  45 + #number of help posts created by the student
  46 + interactions['doubts_count'] = help_posts_made_by_user.count()
  47 +
  48 + help_posts = SubjectPost.objects.filter(action="help", create_date__range=(init_date, end_date),
  49 + space__id=subject_id)
  50 +
  51 + #comments count on help posts created by the student
  52 + interactions['comments_count'] = Comment.objects.filter(post__in = help_posts.filter(user=student),
  53 + create_date__range=(init_date, end_date)).count()
  54 +
  55 +
  56 + #count the amount of comments made by the student on posts made by one of the professors
  57 + interactions['comments_professor_count'] = Comment.objects.filter(post__in = help_posts.filter(user__in= subject.professor.all()), create_date__range=(init_date, end_date),
  58 + user=student).count()
  59 +
  60 + #comments made by the user on other users posts
  61 + interactions['comments_on_others_count'] = Comment.objects.filter(post__in = help_posts.exclude(user=student),
  62 + create_date__range=(init_date, end_date),
  63 + user= student).count()
  64 +
  65 +
  66 +
  67 + comments_by_teacher = Comment.objects.filter(user__in=subject.professor.all())
  68 + help_posts_ids = []
  69 + for comment in comments_by_teacher:
  70 + help_posts_ids.append(comment.post.id)
  71 + #number of help posts created by the user that the teacher commented on
  72 + interactions['help_posts_commented_by_teacher'] = help_posts.filter(user=student, id__in = help_posts_ids).count()
  73 +
  74 +
  75 + comments_by_others = Comment.objects.filter(user__in=subject.students.exclude(id = student.id))
  76 + help_posts_ids = []
  77 + for comment in comments_by_teacher:
  78 + help_posts_ids.append(comment.post.id)
  79 + #number of help posts created by the user others students commented on
  80 + interactions['help_posts_commented_by_others'] = help_posts.filter(user=student, id__in = help_posts_ids).count()
  81 +
  82 + #Number of student visualizations on the mural of the subject
  83 + interactions['mural_visualizations_count'] = MuralVisualizations.objects.filter(post__in = SubjectPost.objects.filter(space__id=subject.id),
  84 + user = student).count()
  85 +
  86 +
  87 + #VAR20 - number of access to mural between 6 a.m to 12a.m.
  88 + interactions['access_subject_between_6_to_12_am'] = Log.objects.filter(action="access", resource="subject",
  89 + user_id= student.id, context__contains = {'subject_id' : subject.id}, datetime__hour__range = (5, 11)).count()
  90 +
  91 + #VAR21 - number of access to mural between 6 a.m to 12a.m.
  92 + interactions['access_subject_between_0_to_6_pm'] = Log.objects.filter(action="access", resource="subject",
  93 + user_id= student.id, context__contains = {'subject_id' : subject.id}, datetime__hour__range = (11, 17)).count()
  94 + #VAR22
  95 + interactions['access_subject_between_6_to_12_pm'] = Log.objects.filter(action="access", resource="subject",
  96 + user_id= student.id, context__contains = {'subject_id' : subject.id}, datetime__hour__range = (17, 23)).count()
  97 +
  98 + #VAR23
  99 + interactions['access_subject_between_0_to_6_am'] = Log.objects.filter(action="access", resource="subject",
  100 + user_id= student.id, context__contains = {'subject_id' : subject.id}, datetime__hour__range = (23, 5)).count()
  101 +
  102 + #VAR24 through 30
  103 + day_numbers = [0, 1, 2, 3, 4, 5, 6]
  104 + day_names = ["sunday", "monday", "tuesday", "wednesday", "thursday", "friday", "saturday"]
  105 + for day_num in day_numbers:
  106 + interactions['access_subject_'+day_names[day_num]] = Log.objects.filter(action="access", resource="subject",
  107 + user_id= student.id, context__contains = {'subject_id' : subject.id}, datetime__week_day = day_num).count()
  108 +
  109 + data[student] = interactions
  110 +
  111 + context["data"] = data
  112 +
  113 +
  114 + return context
  115 +
  116 +
... ...
topics/templates/resources/list.html
... ... @@ -29,6 +29,9 @@
29 29 </button>
30 30 <ul class="dropdown-menu pull-right" role="menu" aria-labelledby="moreResources">
31 31 <li><a href="{% url resource.update_link topic.slug resource.slug %}" class="edit"><i class="fa fa-pencil fa-fw" aria-hidden="true"></i>{% trans 'Edit' %}</a></li>
  32 + {% if resource|class_name == 'goals' %}
  33 + <li><a href="{% url 'goals:answered_reports' resource.slug %}" class="edit"><i class="fa fa-file-pdf-o fa-fw" aria-hidden="true"></i>{% trans 'Reports' %}</a></li>
  34 + {% endif %}
32 35 <li><a href="javascript:delete_resource('{% url resource.delete_link resource.slug %}')" class="delete"><i class="fa fa-trash fa-fw" aria-hidden="true"></i>{% trans 'Remove' %}</a></li>
33 36 </ul>
34 37 </span>
... ...