Commit 4ebbf87e95bb73d6afa51750e17616ddffe236b9

Authored by fbormann
1 parent af1350ae

distinct amount of views in resources and amount of views in resource is now co…

…rrect, added blank tag as well as removed duplicates from form
file_link/views.py
... ... @@ -21,7 +21,7 @@ from .models import FileLink
21 21 class DownloadFile(LoginRequiredMixin, LogMixin, generic.DetailView):
22 22 log_component = 'resources'
23 23 log_action = 'view'
24   - log_resource = 'file_link'
  24 + log_resource = 'filelink'
25 25 log_context = {}
26 26  
27 27 login_url = reverse_lazy("users:login")
... ... @@ -63,9 +63,9 @@ class DownloadFile(LoginRequiredMixin, LogMixin, generic.DetailView):
63 63 self.log_context['topic_id'] = file_link.topic.id
64 64 self.log_context['topic_name'] = file_link.topic.name
65 65 self.log_context['topic_slug'] = file_link.topic.slug
66   - self.log_context['file_link_id'] = file_link.id
67   - self.log_context['file_link_name'] = file_link.name
68   - self.log_context['file_link_slug'] = file_link.slug
  66 + self.log_context['filelink_id'] = file_link.id
  67 + self.log_context['filelink_name'] = file_link.name
  68 + self.log_context['filelink_slug'] = file_link.slug
69 69  
70 70 super(DownloadFile, self).createLog(self.request.user, self.log_component, self.log_action, self.log_resource, self.log_context)
71 71  
... ... @@ -74,7 +74,7 @@ class DownloadFile(LoginRequiredMixin, LogMixin, generic.DetailView):
74 74 class CreateView(LoginRequiredMixin, LogMixin, generic.edit.CreateView):
75 75 log_component = 'resources'
76 76 log_action = 'create'
77   - log_resource = 'file_link'
  77 + log_resource = 'filelink'
78 78 log_context = {}
79 79  
80 80 login_url = reverse_lazy("users:login")
... ... @@ -163,9 +163,9 @@ class CreateView(LoginRequiredMixin, LogMixin, generic.edit.CreateView):
163 163 self.log_context['topic_id'] = self.object.topic.id
164 164 self.log_context['topic_name'] = self.object.topic.name
165 165 self.log_context['topic_slug'] = self.object.topic.slug
166   - self.log_context['file_link_id'] = self.object.id
167   - self.log_context['file_link_name'] = self.object.name
168   - self.log_context['file_link_slug'] = self.object.slug
  166 + self.log_context['filelink_id'] = self.object.id
  167 + self.log_context['filelink_name'] = self.object.name
  168 + self.log_context['filelink_slug'] = self.object.slug
169 169  
170 170 super(CreateView, self).createLog(self.request.user, self.log_component, self.log_action, self.log_resource, self.log_context)
171 171  
... ... @@ -192,7 +192,7 @@ class CreateView(LoginRequiredMixin, LogMixin, generic.edit.CreateView):
192 192 class UpdateView(LoginRequiredMixin, LogMixin, generic.UpdateView):
193 193 log_component = 'resources'
194 194 log_action = 'update'
195   - log_resource = 'file_link'
  195 + log_resource = 'filelink'
196 196 log_context = {}
197 197  
198 198 login_url = reverse_lazy("users:login")
... ... @@ -277,9 +277,9 @@ class UpdateView(LoginRequiredMixin, LogMixin, generic.UpdateView):
277 277 self.log_context['topic_id'] = self.object.topic.id
278 278 self.log_context['topic_name'] = self.object.topic.name
279 279 self.log_context['topic_slug'] = self.object.topic.slug
280   - self.log_context['file_link_id'] = self.object.id
281   - self.log_context['file_link_name'] = self.object.name
282   - self.log_context['file_link_slug'] = self.object.slug
  280 + self.log_context['filelink_id'] = self.object.id
  281 + self.log_context['filelink_name'] = self.object.name
  282 + self.log_context['filelink_slug'] = self.object.slug
283 283  
284 284 super(UpdateView, self).createLog(self.request.user, self.log_component, self.log_action, self.log_resource, self.log_context)
285 285  
... ... @@ -306,7 +306,7 @@ class UpdateView(LoginRequiredMixin, LogMixin, generic.UpdateView):
306 306 class DeleteView(LoginRequiredMixin, LogMixin, generic.DeleteView):
307 307 log_component = 'resources'
308 308 log_action = 'delete'
309   - log_resource = 'file_link'
  309 + log_resource = 'filelink'
310 310 log_context = {}
311 311  
312 312 login_url = reverse_lazy("users:login")
... ... @@ -337,9 +337,9 @@ class DeleteView(LoginRequiredMixin, LogMixin, generic.DeleteView):
337 337 self.log_context['topic_id'] = self.object.topic.id
338 338 self.log_context['topic_name'] = self.object.topic.name
339 339 self.log_context['topic_slug'] = self.object.topic.slug
340   - self.log_context['file_link_id'] = self.object.id
341   - self.log_context['file_link_name'] = self.object.name
342   - self.log_context['file_link_slug'] = self.object.slug
  340 + self.log_context['filelink_id'] = self.object.id
  341 + self.log_context['filelink_name'] = self.object.name
  342 + self.log_context['filelink_slug'] = self.object.slug
343 343  
344 344 super(DeleteView, self).createLog(self.request.user, self.log_component, self.log_action, self.log_resource, self.log_context)
345 345  
... ...
pdf_file/views.py
... ... @@ -23,7 +23,7 @@ class ViewPDFFile(LoginRequiredMixin, LogMixin, generic.TemplateView):
23 23 template_name='pdf_file/view.html'
24 24 log_component = 'resources'
25 25 log_action = 'view'
26   - log_resource = 'pdf_file'
  26 + log_resource = 'pdffile'
27 27 log_context = {}
28 28 def dispatch(self, request, *args, **kwargs):
29 29 slug = self.kwargs.get('slug', '')
... ... @@ -52,9 +52,9 @@ class ViewPDFFile(LoginRequiredMixin, LogMixin, generic.TemplateView):
52 52 self.log_context['topic_id'] = pdf_file.topic.id
53 53 self.log_context['topic_name'] = pdf_file.topic.name
54 54 self.log_context['topic_slug'] = pdf_file.topic.slug
55   - self.log_context['pdf_id'] = pdf_file.id
56   - self.log_context['pdf_name'] = pdf_file.name
57   - self.log_context['pdf_slug'] = pdf_file.slug
  55 + self.log_context['pdffile_id'] = pdf_file.id
  56 + self.log_context['pdffile_name'] = pdf_file.name
  57 + self.log_context['pdffile_slug'] = pdf_file.slug
58 58  
59 59 super(ViewPDFFile, self).createLog(self.request.user, self.log_component, self.log_action, self.log_resource, self.log_context)
60 60  
... ... @@ -87,6 +87,7 @@ class PDFFileCreateView(LoginRequiredMixin, LogMixin , generic.CreateView):
87 87 login_url = reverse_lazy("users:login")
88 88 redirect_field_name = 'next'
89 89  
  90 + log_resource = 'pdffile'
90 91  
91 92 def dispatch(self, request, *args, **kwargs):
92 93 slug = self.kwargs.get('slug', '')
... ... @@ -168,9 +169,9 @@ class PDFFileCreateView(LoginRequiredMixin, LogMixin , generic.CreateView):
168 169 self.log_context['topic_id'] = self.object.topic.id
169 170 self.log_context['topic_name'] = self.object.topic.name
170 171 self.log_context['topic_slug'] = self.object.topic.slug
171   - self.log_context['pdf_file_id'] = self.object.id
172   - self.log_context['pdf_file_name'] = self.object.name
173   - self.log_context['pdf_file_slug'] = self.object.slug
  172 + self.log_context['pdffile_id'] = self.object.id
  173 + self.log_context['pdffile_name'] = self.object.name
  174 + self.log_context['pdffile_slug'] = self.object.slug
174 175  
175 176 super(PDFFileCreateView, self).createLog(self.request.user, self.log_component, self.log_action, self.log_resource, self.log_context)
176 177  
... ... @@ -198,7 +199,7 @@ class PDFFileCreateView(LoginRequiredMixin, LogMixin , generic.CreateView):
198 199 class UpdateView(LoginRequiredMixin, LogMixin, generic.UpdateView):
199 200 log_component = 'resources'
200 201 log_action = 'update'
201   - log_resource = 'pdf_file'
  202 + log_resource = 'pdffile'
202 203 log_context = {}
203 204  
204 205 login_url = reverse_lazy("users:login")
... ... @@ -283,9 +284,9 @@ class UpdateView(LoginRequiredMixin, LogMixin, generic.UpdateView):
283 284 self.log_context['topic_id'] = self.object.topic.id
284 285 self.log_context['topic_name'] = self.object.topic.name
285 286 self.log_context['topic_slug'] = self.object.topic.slug
286   - self.log_context['pdf_file_id'] = self.object.id
287   - self.log_context['pdf_file_name'] = self.object.name
288   - self.log_context['pdf_file_slug'] = self.object.slug
  287 + self.log_context['pdffile_id'] = self.object.id
  288 + self.log_context['pdffile_name'] = self.object.name
  289 + self.log_context['pdffile_slug'] = self.object.slug
289 290  
290 291 super(UpdateView, self).createLog(self.request.user, self.log_component, self.log_action, self.log_resource, self.log_context)
291 292  
... ... @@ -343,9 +344,9 @@ class DeleteView(LoginRequiredMixin, LogMixin, generic.DeleteView):
343 344 self.log_context['topic_id'] = self.object.topic.id
344 345 self.log_context['topic_name'] = self.object.topic.name
345 346 self.log_context['topic_slug'] = self.object.topic.slug
346   - self.log_context['pdf_file_id'] = self.object.id
347   - self.log_context['pdf_file_name'] = self.object.name
348   - self.log_context['pdf_file_slug'] = self.object.slug
  347 + self.log_context['pdffile_id'] = self.object.id
  348 + self.log_context['pdffile_name'] = self.object.name
  349 + self.log_context['pdffile_slug'] = self.object.slug
349 350  
350 351 super(DeleteView, self).createLog(self.request.user, self.log_component, self.log_action, self.log_resource, self.log_context)
351 352  
... ...
reports/migrations/0002_reportxls.py 0 → 100644
... ... @@ -0,0 +1,30 @@
  1 +# -*- coding: utf-8 -*-
  2 +# Generated by Django 1.10.4 on 2017-03-21 00:55
  3 +from __future__ import unicode_literals
  4 +
  5 +from django.conf import settings
  6 +from django.db import migrations, models
  7 +import django.db.models.deletion
  8 +
  9 +
  10 +class Migration(migrations.Migration):
  11 +
  12 + dependencies = [
  13 + migrations.swappable_dependency(settings.AUTH_USER_MODEL),
  14 + ('reports', '0001_initial'),
  15 + ]
  16 +
  17 + operations = [
  18 + migrations.CreateModel(
  19 + name='ReportXLS',
  20 + fields=[
  21 + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
  22 + ('xls_data', models.TextField()),
  23 + ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
  24 + ],
  25 + options={
  26 + 'verbose_name': 'ReportCSV',
  27 + 'verbose_name_plural': 'ReportCSVs',
  28 + },
  29 + ),
  30 + ]
... ...
reports/models.py
... ... @@ -12,4 +12,17 @@ class ReportCSV(models.Model):
12 12  
13 13 def __str__(self):
14 14 pass
  15 +
  16 +
  17 +class ReportXLS(models.Model):
  18 +
  19 + user = models.ForeignKey(User)
  20 + xls_data = models.TextField()
  21 +
  22 + class Meta:
  23 + verbose_name = "ReportCSV"
  24 + verbose_name_plural = "ReportCSVs"
  25 +
  26 + def __str__(self):
  27 + pass
15 28  
16 29 \ No newline at end of file
... ...
reports/templates/reports/view.html
... ... @@ -65,7 +65,7 @@
65 65 <ul id="report-info">
66 66 <li> {{data.values|length}} {% trans "register(s)" %} </li>
67 67 <li>
68   - <a href="{% url 'subjects:reports:download_report' %}?{{csv_data}}"><i class="fa fa-download" aria-hidden="true"></i> {% trans "Interactions Data" %}</a>
  68 + <a href="{% url 'subjects:reports:download_report_csv' %}"><i class="fa fa-download" aria-hidden="true"></i> {% trans "Interactions Data" %}</a>
69 69  
70 70  
71 71 </li>
... ...
reports/urls.py
... ... @@ -7,5 +7,5 @@ urlpatterns = [
7 7 url(r'^view/interactions/$', views.ViewReportView.as_view(), name='view_report'),
8 8 url(r'^get/resources/$', views.get_resources, name='get_resource_and_tags'),
9 9 url(r'^get/tags/$', views.get_tags, name='get_tags'),
10   - url(r'^post/download_report/$', views.download_report, name="download_report"),
  10 + url(r'^post/download_report/$', views.download_report_csv, name="download_report_csv"),
11 11 ]
12 12 \ No newline at end of file
... ...
reports/views.py
... ... @@ -11,14 +11,14 @@ import django.views.generic as generic
11 11 from mural.models import SubjectPost, Comment, MuralVisualizations
12 12 from django.db.models import Q
13 13 from django.contrib.auth.mixins import LoginRequiredMixin
14   -from datetime import datetime, date
  14 +from datetime import datetime, date, timedelta
15 15 from subjects.models import Subject, Tag
16 16 from .forms import CreateInteractionReportForm, ResourceAndTagForm, BaseResourceAndTagFormset
17 17 from log.models import Log
18 18 from topics.models import Resource, Topic
19 19 from collections import OrderedDict
20 20 from django.forms import formset_factory
21   -from .models import ReportCSV
  21 +from .models import ReportCSV, ReportXLS
22 22 import pandas as pd
23 23  
24 24 class ReportView(LoginRequiredMixin, generic.FormView):
... ... @@ -143,32 +143,47 @@ class ViewReportView(LoginRequiredMixin, generic.TemplateView):
143 143  
144 144 #this is to save the csv for further download
145 145 df = pd.DataFrame.from_dict(context['data'], orient='index')
146   -
147 146 df.columns = context['header']
148 147 #so it does not exist more than one report CSV available for that user to download
149 148 if ReportCSV.objects.filter(user= self.request.user).count() > 0:
150 149 report = ReportCSV.objects.get(user=self.request.user)
151 150 report.delete()
152 151  
153   -
  152 +
154 153 report = ReportCSV(user= self.request.user, csv_data = df.to_csv())
155 154 report.save()
156 155  
  156 + #for excel files
  157 + """ if ReportXLS.objects.filter(user= self.request.user).count() > 0:
  158 + report = ReportXLS.objects.get(user=self.request.user)
  159 + report.delete()
  160 +
  161 + df.drop(df.columns[[0]], axis=1, inplace=True)
  162 + writer = pd.ExcelWriter('pandas_simple.xlsx')
  163 + report = ReportXLS(user= self.request.user, xls_data = df.to_excel(writer))
  164 + report.save()"""
  165 +
  166 +
157 167 return context
158 168  
159 169 def get_mural_data(self, subject, init_date, end_date, resources_id, tags_id):
160 170 data = {}
161 171 students = subject.students.all()
162   - formats = ["%d/%m/%Y", "%m/%d/%Y"] #so it accepts english and portuguese date formats
  172 + formats = ["%d/%m/%Y", "%m/%d/%Y", "%Y-%m-%d"] #so it accepts english and portuguese date formats
163 173 for fmt in formats:
164 174 try:
165   - init_date = datetime.strptime(init_date, fmt)
166   - end_date = datetime.strptime(end_date, fmt)
  175 + init_date = datetime.strptime(init_date, fmt).date()
  176 + end_date = datetime.strptime(end_date, fmt).date()
  177 +
167 178 except ValueError:
168 179 pass
169 180  
170 181 header = ['User']
171   -
  182 +
  183 + #I use this so the system can gather data up to end_date 11h59 p.m.
  184 + end_date = end_date + timedelta(days=1)
  185 +
  186 +
172 187 #For each student in the subject
173 188 for student in students:
174 189 data[student] = []
... ... @@ -226,7 +241,7 @@ class ViewReportView(LoginRequiredMixin, generic.TemplateView):
226 241  
227 242 #VAR08 through VAR_019 of documenttation:
228 243 if len(resources_id) > 0:
229   - resources_data = self.get_resources_and_tags_data(resources_id, tags_id, student, subject)
  244 + resources_data = self.get_resources_and_tags_data(resources_id, tags_id, student, subject, init_date, end_date)
230 245 for key, value in resources_data.items():
231 246 interactions[key] = value
232 247  
... ... @@ -268,12 +283,26 @@ class ViewReportView(LoginRequiredMixin, generic.TemplateView):
268 283 header.append(key)
269 284 return data, header
270 285  
271   - def get_resources_and_tags_data(self, resources, tags, student, subject):
272   - data = {}
  286 + def get_resources_and_tags_data(self, resources_types, tags, student, subject, init_date, end_date):
  287 + data = OrderedDict()
273 288  
274   - for i in range(len(resources)):
275   - data[str(resources[i]) + " with tag " + Tag.objects.get(id=int(tags[i])).name] = Log.objects.filter(action="view", resource=resources[i].lower(),
276   - user_id = student.id, context__contains = {'subject_id': subject.id}).count()
  289 + for i in range(len(resources_types)):
  290 +
  291 + resources = Resource.objects.select_related(resources_types[i].lower()).filter(tags__in = tags, topic__in=subject.topic_subject.all())
  292 + distinct_resources = 0
  293 + total_count = 0
  294 + for resource in resources:
  295 + count = Log.objects.filter(action="view", resource=resources_types[i].lower(),
  296 + user_id = student.id, context__contains = {'subject_id': subject.id,
  297 + resources_types[i].lower()+'_id': resource.id}, datetime__range=(init_date, end_date)).count()
  298 + if count > 0:
  299 + distinct_resources += 1
  300 + total_count += count
  301 +
  302 + data[str(resources_types[i]) + " with tag " + Tag.objects.get(id=int(tags[i])).name] = total_count
  303 + data["distintic " + str(resources_types[i]) + " with tag " + Tag.objects.get(id=int(tags[i])).name] = distinct_resources
  304 + """data["distinct" + str(resources[i]) + " with tag " + Tag.objects.get(id=int(tags[i])).name] = Log.objects.filter(action="view", resource=resources[i].lower(),
  305 + user_id = student.id, context__contains = {'subject_id': subject.id}).distinct().count()"""
277 306  
278 307 return data
279 308  
... ... @@ -317,27 +346,32 @@ def get_tags(request):
317 346 resource_type = request.GET['resource_class_name']
318 347 subject = Subject.objects.get(id=request.GET['subject_id'])
319 348 topic_choice = request.GET["topic_choice"]
  349 +
  350 + #Have to fix this to accept translated options
320 351 if topic_choice.lower() == "all" or topic_choice.lower() == "todos":
321 352 topics = subject.topic_subject.all()
322 353 else:
323 354 topics = [Topic.objects.get(id=int(topic_choice))]
324 355 data = {}
325   - tags = []
  356 + tags = set()
326 357 for topic in topics:
327 358 resource_set = Resource.objects.select_related(resource_type.lower()).filter(topic = topic)
328 359  
329 360 for resource in resource_set:
330 361 if resource._my_subclass == resource_type.lower():
331 362 for tag in resource.tags.all():
332   - tags.append(tag)
333   -
  363 + if tag.name != "":
  364 + tags.add(tag)
  365 +
334 366  
335   -
  367 + #adding empty tag for the purpose of giving the user this option for adicional behavior
  368 + tags = list(tags)
  369 + tags.append(Tag(name=""))
336 370 data['tags'] = [ {'id':tag.id, 'name':tag.name} for tag in tags]
337 371 return JsonResponse(data)
338 372  
339 373  
340   -def download_report(request):
  374 +def download_report_csv(request):
341 375 report = ReportCSV.objects.get(user=request.user)
342 376  
343 377 response = HttpResponse(report.csv_data,content_type='text/csv')
... ...