Commit ebc0db3dc2231f189437d2ae0be93e6a737b55dc
1 parent
1e152bf2
Exists in
master
and in
3 other branches
saving progress on report view
Showing
8 changed files
with
299 additions
and
63 deletions
Show diff stats
amadeus/static/css/base/amadeus.css
... | ... | @@ -1209,4 +1209,10 @@ div.dataTables_wrapper div.dataTables_paginate { |
1209 | 1209 | width: 15%; |
1210 | 1210 | text-align: center; |
1211 | 1211 | } |
1212 | + | |
1213 | +#report-header li { | |
1214 | + display: inline; | |
1215 | + margin-right: 10px; | |
1216 | + font-size: 16px; | |
1217 | +} | |
1212 | 1218 | /* End Reports */ |
1213 | 1219 | \ No newline at end of file | ... | ... |
reports/forms.py
... | ... | @@ -5,12 +5,12 @@ import datetime |
5 | 5 | |
6 | 6 | |
7 | 7 | class CreateInteractionReportForm(forms.Form): |
8 | - topic = forms.ChoiceField(required=True, label= _("topics to select data from")) | |
9 | - init_date = forms.DateField(required=True) | |
10 | - end_date = forms.DateField(required=True) | |
8 | + topic = forms.ChoiceField( label= _("topics to select data from")) | |
9 | + init_date = forms.DateField() | |
10 | + end_date = forms.DateField() | |
11 | 11 | |
12 | - from_mural = forms.BooleanField() | |
13 | - from_messages = forms.BooleanField() | |
12 | + from_mural = forms.BooleanField(required=False) | |
13 | + from_messages = forms.BooleanField(required=False) | |
14 | 14 | |
15 | 15 | class Meta: |
16 | 16 | fields = ('topic', 'init_date', 'end_date', 'from_mural' , 'from_messages') |
... | ... | @@ -22,3 +22,4 @@ class CreateInteractionReportForm(forms.Form): |
22 | 22 | topics = list(initial['topic']) |
23 | 23 | |
24 | 24 | self.fields['topic'].choices = [(topic.id, topic.name) for topic in topics] |
25 | + self.fields['topic'].choices.append((_("all"), _("all"))) | ... | ... |
reports/templates/reports/_form.html
... | ... | @@ -11,6 +11,21 @@ |
11 | 11 | {% render_field field class='form-control' %} |
12 | 12 | {% endif %} |
13 | 13 | |
14 | + {% if field.errors %} | |
15 | + <div class="row"> | |
16 | + </br> | |
17 | + <div class="alert alert-danger alert-dismissible" role="alert"> | |
18 | + <button type="button" class="close" data-dismiss="alert" aria-label="Close"> | |
19 | + <span aria-hidden="true">×</span> | |
20 | + </button> | |
21 | + <ul> | |
22 | + {% for error in field.errors %} | |
23 | + <li>{{ error }}</li> | |
24 | + {% endfor %} | |
25 | + </ul> | |
26 | + </div> | |
27 | + </div> | |
28 | + {% endif %} | |
14 | 29 | {% endfor %} |
15 | 30 | <div class="row text-center"> |
16 | 31 | <input type="submit" value="Search" class="btn btn-success btn-raised" /> | ... | ... |
... | ... | @@ -0,0 +1,44 @@ |
1 | +{% extends 'base.html' %} | |
2 | + | |
3 | +{% load static i18n pagination %} | |
4 | +{% load django_bootstrap_breadcrumbs %} | |
5 | +{% load widget_tweaks %} | |
6 | + | |
7 | +{% block breadcrumbs %} | |
8 | + {{ block.super }} | |
9 | + | |
10 | + {% breadcrumb 'analytics' '' %} | |
11 | +{% endblock %} | |
12 | + | |
13 | +{% block content %} | |
14 | + | |
15 | + <div class="panel panel-info topic-panel"> | |
16 | + <div class="panel-heading"> | |
17 | + <div class="row"> | |
18 | + <div class="col-md-12 category-header"> | |
19 | + <h4 class="panel-title" style="margin-top: 10px; margin-bottom: 8px"> | |
20 | + <span>{% trans "Analytics" %}</span> | |
21 | + </h4> | |
22 | + </div> | |
23 | + </div> | |
24 | + </div> | |
25 | + </div> | |
26 | + | |
27 | + <div id="core-subjects-options-div"> | |
28 | + <ul class="core-subjects-options report-menu-choice"> | |
29 | + <li class="active"> | |
30 | + {% trans "Interaction Data" %} | |
31 | + </li> | |
32 | + <li> | |
33 | + {% trans "Report Card" %} | |
34 | + </li> | |
35 | + <li> | |
36 | + {% trans "Participation" %} | |
37 | + </li> | |
38 | + </ul> | |
39 | + </div> | |
40 | + | |
41 | + {% include "reports/_form.html" %} | |
42 | + | |
43 | + | |
44 | +{% endblock content %} | |
0 | 45 | \ No newline at end of file | ... | ... |
reports/templates/reports/report.html
... | ... | @@ -1,57 +0,0 @@ |
1 | -{% extends 'base.html' %} | |
2 | - | |
3 | -{% load static i18n pagination %} | |
4 | -{% load django_bootstrap_breadcrumbs %} | |
5 | -{% load widget_tweaks %} | |
6 | - | |
7 | -{% block breadcrumbs %} | |
8 | - {{ block.super }} | |
9 | - | |
10 | - {% breadcrumb 'analytics' '' %} | |
11 | -{% endblock %} | |
12 | - | |
13 | -{% block content %} | |
14 | - | |
15 | - <div class="panel panel-info topic-panel"> | |
16 | - <div class="panel-heading"> | |
17 | - <div class="row"> | |
18 | - <div class="col-md-12 category-header"> | |
19 | - <h4 class="panel-title" style="margin-top: 10px; margin-bottom: 8px"> | |
20 | - <span>{% trans "Analytics" %}</span> | |
21 | - </h4> | |
22 | - </div> | |
23 | - </div> | |
24 | - </div> | |
25 | - </div> | |
26 | - | |
27 | - <div id="core-subjects-options-div"> | |
28 | - <ul class="core-subjects-options report-menu-choice"> | |
29 | - <li class="active"> | |
30 | - {% trans "Interaction Data" %} | |
31 | - </li> | |
32 | - <li> | |
33 | - {% trans "Report Card" %} | |
34 | - </li> | |
35 | - <li> | |
36 | - {% trans "Participation" %} | |
37 | - </li> | |
38 | - </ul> | |
39 | - </div> | |
40 | - | |
41 | - {% include "reports/_form.html" %} | |
42 | - | |
43 | - {% for user, datum in data.items %} | |
44 | - | |
45 | - | |
46 | - <p> | |
47 | - <ul> | |
48 | - | |
49 | - {{user}} : | |
50 | - {% for key, value in datum.items %} | |
51 | - <li>{{key}}: {{value}}</li> | |
52 | - {% endfor %} | |
53 | - </ul> | |
54 | - | |
55 | - </p> | |
56 | - {% endfor %} | |
57 | -{% endblock content %} | |
58 | 0 | \ No newline at end of file |
... | ... | @@ -0,0 +1,87 @@ |
1 | +{% extends 'base.html' %} | |
2 | + | |
3 | +{% load static i18n pagination %} | |
4 | +{% load django_bootstrap_breadcrumbs %} | |
5 | +{% load widget_tweaks %} | |
6 | + | |
7 | +{% block breadcrumbs %} | |
8 | + {{ block.super }} | |
9 | + | |
10 | + {% breadcrumb 'analytics' '' %} | |
11 | +{% endblock %} | |
12 | + | |
13 | +{% block content %} | |
14 | + | |
15 | + {% if messages %} | |
16 | + {% for message in messages %} | |
17 | + <div class="alert alert-{{ message.tags }} alert-dismissible" role="alert"> | |
18 | + <button type="button" class="close" data-dismiss="alert" aria-label="Close"> | |
19 | + <span aria-hidden="true">×</span> | |
20 | + </button> | |
21 | + <p>{{ message }}</p> | |
22 | + </div> | |
23 | + {% endfor %} | |
24 | + {% endif %} | |
25 | + | |
26 | + | |
27 | + <div class="panel panel-info topic-panel"> | |
28 | + <div class="panel-heading"> | |
29 | + <div class="row"> | |
30 | + <div class="col-md-12 category-header"> | |
31 | + <h4 class="panel-title" style="margin-top: 10px; margin-bottom: 8px"> | |
32 | + <span>{% trans "Analytics" %}</span> | |
33 | + </h4> | |
34 | + </div> | |
35 | + </div> | |
36 | + </div> | |
37 | + </div> | |
38 | + | |
39 | + <div id="core-subjects-options-div"> | |
40 | + <ul class="core-subjects-options report-menu-choice"> | |
41 | + <li class="active"> | |
42 | + {% trans "Interaction Data" %} | |
43 | + </li> | |
44 | + <li> | |
45 | + {% trans "Report Card" %} | |
46 | + </li> | |
47 | + <li> | |
48 | + {% trans "Participation" %} | |
49 | + </li> | |
50 | + </ul> | |
51 | + </div> | |
52 | + | |
53 | + <div class="col-md-12"> | |
54 | + <ul id="report-header"> | |
55 | + <li><b>{% trans "Subject" %}:</b> {{subject_name}}</li> | |
56 | + <li><b>{% trans "Topic" %}:</b> {{topic_name}}</li> | |
57 | + <li><b>{% trans "Initial Date" %}:</b> {{init_date}}</li> | |
58 | + <li><b>{% trans "End Date" %}:</b> {{end_date}}</li> | |
59 | + <li><button class="btn btn-success btn-raised">{% trans "new search" %}</button></li> | |
60 | + | |
61 | + </ul> | |
62 | + <div class="table-responsive"> | |
63 | + <table class="table table-stripped"> | |
64 | + <thead> | |
65 | + <tr> | |
66 | + {% for key in data.keys %} | |
67 | + <th>{{key}}</th> | |
68 | + {% endfor %} | |
69 | + </tr> | |
70 | + </thead> | |
71 | + <tbody> | |
72 | + | |
73 | + {% for value_dict in data.values %} | |
74 | + <tr> | |
75 | + {% for key, value in value_dict.items %} | |
76 | + <td>{{value}}</td> | |
77 | + {% endfor %} | |
78 | + </tr> | |
79 | + {% endfor %} | |
80 | + </tbody> | |
81 | + | |
82 | + </table> | |
83 | + </div> | |
84 | + </div> | |
85 | + | |
86 | + | |
87 | +{% endblock content %} | |
0 | 88 | \ No newline at end of file | ... | ... |
reports/urls.py
reports/views.py
... | ... | @@ -3,6 +3,9 @@ from django.http import HttpResponse, JsonResponse |
3 | 3 | from django.utils.translation import ugettext_lazy as _ |
4 | 4 | |
5 | 5 | from django import forms |
6 | +from django.core.urlresolvers import reverse_lazy | |
7 | + | |
8 | +from django.contrib import messages | |
6 | 9 | |
7 | 10 | import django.views.generic as generic |
8 | 11 | from mural.models import SubjectPost, Comment, MuralVisualizations |
... | ... | @@ -15,7 +18,7 @@ from log.models import Log |
15 | 18 | |
16 | 19 | |
17 | 20 | class ReportView(LoginRequiredMixin, generic.FormView): |
18 | - template_name = "reports/report.html" | |
21 | + template_name = "reports/create.html" | |
19 | 22 | form_class = CreateInteractionReportForm |
20 | 23 | |
21 | 24 | def get_initial(self): |
... | ... | @@ -30,3 +33,139 @@ class ReportView(LoginRequiredMixin, generic.FormView): |
30 | 33 | initial['topic'] = topics |
31 | 34 | initial['end_date'] = date.today() |
32 | 35 | return initial |
36 | + | |
37 | + | |
38 | + def get_success_url(self): | |
39 | + | |
40 | + messages.success(self.request, _("Report created successfully")) | |
41 | + | |
42 | + get_params = "?" | |
43 | + #passing form data through GET | |
44 | + for key, value in self.form_data.items(): | |
45 | + get_params += key + "=" + str(value) + "&" | |
46 | + | |
47 | + | |
48 | + #retrieving subject id for data purposes | |
49 | + for key, value in self.request.GET.items(): | |
50 | + get_params += key + "=" + str(value) | |
51 | + | |
52 | + return reverse_lazy('subjects:reports:view_report', kwargs={}) + get_params | |
53 | + | |
54 | + def post(self, request, *args, **kwargs): | |
55 | + """ | |
56 | + Handles POST requests, instantiating a form instance with the passed | |
57 | + POST variables and then checked for validity. | |
58 | + """ | |
59 | + form = self.get_form() | |
60 | + if form.is_valid(): | |
61 | + | |
62 | + self.form_data = form.cleaned_data | |
63 | + return self.form_valid(form) | |
64 | + else: | |
65 | + return self.form_invalid(form) | |
66 | + | |
67 | + | |
68 | +class ViewReportView(LoginRequiredMixin, generic.TemplateView): | |
69 | + template_name = "reports/view.html" | |
70 | + | |
71 | + | |
72 | + def get_context_data(self, **kwargs): | |
73 | + context = {} | |
74 | + params_data = self.request.GET | |
75 | + subject = Subject.objects.get(id=params_data['subject_id']) | |
76 | + context['subject_name'] = subject.name | |
77 | + context['topic_name'] = params_data['topic'] | |
78 | + context['init_date'] = params_data['init_date'] | |
79 | + context['end_date'] = params_data['end_date'] | |
80 | + | |
81 | + if params_data['from_mural']: | |
82 | + context['data'] = self.get_mural_data(subject, params_data['init_date'], params_data['end_date']) | |
83 | + return context | |
84 | + | |
85 | + def get_mural_data(self, subject, init_date, end_date): | |
86 | + data = {} | |
87 | + students = subject.students.all() | |
88 | + formats = ["%d/%m/%Y", "%m/%d/%Y"] #so it accepts english and portuguese date formats | |
89 | + for fmt in formats: | |
90 | + try: | |
91 | + init_date = datetime.strptime(init_date, fmt) | |
92 | + end_date = datetime.strptime(end_date, fmt) | |
93 | + except ValueError: | |
94 | + pass | |
95 | + | |
96 | + | |
97 | + for student in students: | |
98 | + interactions = {} | |
99 | + interactions['username'] = student.social_name | |
100 | + | |
101 | + help_posts_made_by_user = SubjectPost.objects.filter(action="help",space__id=subject.id, user=student, | |
102 | + create_date__range=(init_date, end_date)) | |
103 | + | |
104 | + #number of help posts created by the student | |
105 | + interactions['doubts_count'] = help_posts_made_by_user.count() | |
106 | + | |
107 | + help_posts = SubjectPost.objects.filter(action="help", create_date__range=(init_date, end_date), | |
108 | + space__id=subject.id) | |
109 | + | |
110 | + #comments count on help posts created by the student | |
111 | + interactions['comments_count'] = Comment.objects.filter(post__in = help_posts.filter(user=student), | |
112 | + create_date__range=(init_date, end_date)).count() | |
113 | + | |
114 | + | |
115 | + #count the amount of comments made by the student on posts made by one of the professors | |
116 | + interactions['comments_professor_count'] = Comment.objects.filter(post__in = help_posts.filter(user__in= subject.professor.all()), create_date__range=(init_date, end_date), | |
117 | + user=student).count() | |
118 | + | |
119 | + #comments made by the user on other users posts | |
120 | + interactions['comments_on_others_count'] = Comment.objects.filter(post__in = help_posts.exclude(user=student), | |
121 | + create_date__range=(init_date, end_date), | |
122 | + user= student).count() | |
123 | + | |
124 | + | |
125 | + | |
126 | + comments_by_teacher = Comment.objects.filter(user__in=subject.professor.all()) | |
127 | + help_posts_ids = [] | |
128 | + for comment in comments_by_teacher: | |
129 | + help_posts_ids.append(comment.post.id) | |
130 | + #number of help posts created by the user that the teacher commented on | |
131 | + interactions['help_posts_commented_by_teacher'] = help_posts.filter(user=student, id__in = help_posts_ids).count() | |
132 | + | |
133 | + | |
134 | + comments_by_others = Comment.objects.filter(user__in=subject.students.exclude(id = student.id)) | |
135 | + help_posts_ids = [] | |
136 | + for comment in comments_by_teacher: | |
137 | + help_posts_ids.append(comment.post.id) | |
138 | + #number of help posts created by the user others students commented on | |
139 | + interactions['help_posts_commented_by_others'] = help_posts.filter(user=student, id__in = help_posts_ids).count() | |
140 | + | |
141 | + #Number of student visualizations on the mural of the subject | |
142 | + interactions['mural_visualizations_count'] = MuralVisualizations.objects.filter(post__in = SubjectPost.objects.filter(space__id=subject.id), | |
143 | + user = student).count() | |
144 | + | |
145 | + | |
146 | + #VAR20 - number of access to mural between 6 a.m to 12a.m. | |
147 | + interactions['access_subject_between_6_to_12_am'] = Log.objects.filter(action="access", resource="subject", | |
148 | + user_id= student.id, context__contains = {'subject_id' : subject.id}, datetime__hour__range = (5, 11)).count() | |
149 | + | |
150 | + #VAR21 - number of access to mural between 6 a.m to 12a.m. | |
151 | + interactions['access_subject_between_0_to_6_pm'] = Log.objects.filter(action="access", resource="subject", | |
152 | + user_id= student.id, context__contains = {'subject_id' : subject.id}, datetime__hour__range = (11, 17)).count() | |
153 | + #VAR22 | |
154 | + interactions['access_subject_between_6_to_12_pm'] = Log.objects.filter(action="access", resource="subject", | |
155 | + user_id= student.id, context__contains = {'subject_id' : subject.id}, datetime__hour__range = (17, 23)).count() | |
156 | + | |
157 | + #VAR23 | |
158 | + interactions['access_subject_between_0_to_6_am'] = Log.objects.filter(action="access", resource="subject", | |
159 | + user_id= student.id, context__contains = {'subject_id' : subject.id}, datetime__hour__range = (23, 5)).count() | |
160 | + | |
161 | + #VAR24 through 30 | |
162 | + day_numbers = [0, 1, 2, 3, 4, 5, 6] | |
163 | + day_names = ["sunday", "monday", "tuesday", "wednesday", "thursday", "friday", "saturday"] | |
164 | + for day_num in day_numbers: | |
165 | + interactions['access_subject_'+day_names[day_num]] = Log.objects.filter(action="access", resource="subject", | |
166 | + user_id= student.id, context__contains = {'subject_id' : subject.id}, datetime__week_day = day_num).count() | |
167 | + | |
168 | + data[student] = interactions | |
169 | + print(data) | |
170 | + return data | |
171 | + | ... | ... |