Commit 34817c0f312f39881f901daa0af9a273a7e6df91
Exists in
master
and in
2 other branches
Merge branch 'refactoring' of https://github.com/amadeusproject/amadeuslms into refactoring
Showing
12 changed files
with
293 additions
and
80 deletions
Show diff stats
analytics/static/.sass-cache/01cecb7b42e56765f6ed49ed3c70281ebdc742c7/general.sassc
No preview for this file type
analytics/static/analytics/general.css
... | ... | @@ -47,8 +47,7 @@ |
47 | 47 | color: #ffffff; } |
48 | 48 | |
49 | 49 | .tag-name { |
50 | - color: #ffffff; | |
51 | - font-size: 10px; } | |
50 | + color: #ffffff; } | |
52 | 51 | |
53 | 52 | #left-data-selector { |
54 | 53 | background: linear-gradient(#0e8999, #6bf0ce); |
... | ... | @@ -60,7 +59,8 @@ |
60 | 59 | width: 30%; |
61 | 60 | float: left; } |
62 | 61 | .chart h4 { |
63 | - color: #009688; } | |
62 | + color: #009688; | |
63 | + text-align: center; } | |
64 | 64 | |
65 | 65 | .selector { |
66 | 66 | width: 90%; |
... | ... | @@ -115,4 +115,8 @@ |
115 | 115 | .most-accessed-item:hover { |
116 | 116 | background-color: #3aa7ad; } |
117 | 117 | |
118 | +#month_selector_div { | |
119 | + text-align: center; | |
120 | + color: #009688; } | |
121 | + | |
118 | 122 | /*# sourceMappingURL=general.css.map */ | ... | ... |
analytics/static/analytics/general.css.map
1 | 1 | { |
2 | 2 | "version": 3, |
3 | -"mappings": "AAEA,YAAY;EACR,MAAM,EAAE,iBAAiB;EACzB,aAAa,EAAE,IAAI;EACnB,OAAO,EAAE,IAAI;EACb,QAAQ,EAAE,IAAI;EACd,KAAK,EAAE,IAAI;EACX,gBAAgB,EAAE,OAAO;;AAE7B,sBAAsB;EAClB,MAAM,EAAE,GAAG;EACX,OAAO,EAAE,KAAK;EACd,yBAAE;IACE,KAAK,EAdC,OAAO;EAgBjB,yBAAE;IACE,KAAK,EAAE,KAAK;IACZ,OAAO,EAAE,WAAW;IACpB,KAAK,EAAE,GAAG;IACV,aAAa,EAAE,GAAG;IAElB,4BAAE;MACE,YAAY,EAAE,EAAE;MAChB,KAAK,EAAE,GAAG;MACV,KAAK,EAAE,KAAK;MACZ,SAAS,EAAE,IAAI;MACf,gBAAgB,EAAE,OAAO;MACzB,KAAK,EAAE,IAAI;MACX,UAAU,EAAE,MAAM;MAClB,aAAa,EAAE,IAAI;MACnB,MAAM,EAAE,IAAI;IAGhB,qCAAW;MACP,gBAAgB,EAAE,OAAO;MACzB,KAAK,EAAE,IAAI;MACX,UAAU,EAAE,MAAM;MAClB,aAAa,EAAE,IAAI;;AAM/B,sBAAsB;EAClB,UAAU,EAAE,2CAA2C;EACvD,MAAM,EAAE,IAAI;EACZ,aAAa,EAAE,IAAI;EACnB,KAAK,EAAE,OAAO;EACd,WAAW,EAAE,GAAG;EAChB,UAAU,EAAE,IAAI;EAEhB,yBAAE;IACE,WAAW,EAAE,EAAE;;AAGvB,UAAU;EACN,aAAa,EAAE,IAAI;EACnB,KAAK,EAAE,OAAO;;AAKlB,SAAS;EACL,KAAK,EAAE,OAAO;EACd,SAAS,EAAE,IAAI;;AAGnB,mBAAmB;EACf,UAAU,EAAE,iCAAmC;EAC/C,UAAU,EAAE,EAAE;EACd,WAAW,EAAE,EAAE;EACf,cAAc,EAAE,EAAE;;AAEtB,MAAM;EACF,KAAK,EAAE,GAAG;EACV,KAAK,EAAE,IAAI;EACX,SAAE;IACE,KAAK,EA9EC,OAAO;;AAgFrB,SAAS;EACL,KAAK,EAAE,GAAG;EACV,MAAM,EAAE,IAAI;EACZ,KAAK,EAAE,KAAK;EACZ,YAAY,EAAE,GAAG;EACjB,gBAAgB,EAAE,OAAO;EACzB,UAAU,EAAE,GAAG;EACf,aAAa,EAAE,iBAAiB;EAChC,WAAC;IACG,WAAW,EAAE,IAAI;IACjB,SAAS,EAAE,IAAI;;AAInB,qBAAO;EACH,UAAU,EAAE,MAAM;;AAE1B,aAAa;EACT,UAAU,EAAE,iCAAkC;EAC9C,KAAK,EAAE,KAAK;EACZ,aAAa,EAAE,IAAI;EACnB,OAAO,EAAE,GAAG;;AAEhB,mBAAmB;EACf,gBAAgB,EAAE,OAAO;EACzB,KAAK,EAAE,GAAG;EACV,WAAW,EAAE,EAAE;EACf,UAAU,EAAE,EAAE;EACd,QAAQ,EAAE,QAAQ;EAClB,YAAY,EAAE,CAAC;EACf,KAAK,EAAE,KAAK;EACZ,MAAM,EAAE,iBAAiB;EACzB,UAAU,EAAE,sDAAsD;EAElE,sBAAE;IACE,YAAY,EAAE,EAAE;;AAExB,qDAAqD;EACjD,MAAM,EAAE,IAAI;EACZ,IAAI,EAAE,GAAG;EACT,MAAM,EAAE,iBAAiB;EACzB,OAAO,EAAE,GAAG;EACZ,MAAM,EAAE,CAAC;EACT,KAAK,EAAE,CAAC;EACR,QAAQ,EAAE,QAAQ;EAClB,cAAc,EAAE,IAAI;;AAGxB,0BAA0B;EACtB,YAAY,EAAE,IAAI;EAClB,WAAW,EAAE,IAAI;EACjB,YAAY,EAAE,sBAAsB;EACpC,mBAAmB,EAAE,OAAO;;AAEhC,yBAAyB;EACrB,gBAAgB,EAAE,OAAO", | |
3 | +"mappings": "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", | |
4 | 4 | "sources": ["general.sass"], |
5 | 5 | "names": [], |
6 | 6 | "file": "general.css" | ... | ... |
analytics/static/analytics/general.sass
... | ... | @@ -63,7 +63,6 @@ $title-color: #009688 |
63 | 63 | |
64 | 64 | .tag-name |
65 | 65 | color: #ffffff |
66 | - font-size: 10px | |
67 | 66 | |
68 | 67 | |
69 | 68 | #left-data-selector |
... | ... | @@ -75,8 +74,10 @@ $title-color: #009688 |
75 | 74 | .chart |
76 | 75 | width: 30% |
77 | 76 | float: left |
77 | + | |
78 | 78 | h4 |
79 | 79 | color: $title-color |
80 | + text-align: center | |
80 | 81 | |
81 | 82 | .selector |
82 | 83 | width: 90% |
... | ... | @@ -133,4 +134,9 @@ $title-color: #009688 |
133 | 134 | border-bottom-color: #52b7bd |
134 | 135 | |
135 | 136 | .most-accessed-item:hover |
136 | - background-color: #3aa7ad | |
137 | 137 | \ No newline at end of file |
138 | + background-color: #3aa7ad | |
139 | + | |
140 | + | |
141 | +#month_selector_div | |
142 | + text-align: center | |
143 | + color: #009688 | |
138 | 144 | \ No newline at end of file | ... | ... |
analytics/static/analytics/js/behavior.js
1 | 1 | |
2 | + | |
3 | + | |
2 | 4 | $(document).ready(function(){ |
3 | 5 | selectors_options.init(); |
6 | + | |
7 | + //for month selector | |
8 | + | |
9 | + $('#month_selector').change(function(){ | |
10 | + $.get('/analytics/amount_active_users_per_day', {month: $(this).val() }).done(function(data){ | |
11 | + charts.month_heatmap(data, '#right-chart-body'); | |
12 | + | |
13 | + }); | |
14 | + }); | |
15 | + //week date selector at the right-chart field | |
16 | + $('input.datepicker').datetimepicker({ | |
17 | + format: 'L', | |
18 | + defaultDate: new Date(), | |
19 | + }).on('dp.change', function(ev){ | |
20 | + $.get('/analytics/get_days_of_the_week_log', {date: ev.date._i}).done(function(data){ | |
21 | + charts.month_heatmap(data, '#bottom-right-chart-body'); | |
22 | + }); | |
23 | + | |
24 | + }); | |
25 | + | |
26 | + | |
27 | + | |
28 | + | |
4 | 29 | }); |
5 | 30 | |
6 | 31 | |
32 | + | |
7 | 33 | var selectors_options = { |
8 | 34 | init: function(){ |
9 | 35 | selectors = $("div.selector"); |
... | ... | @@ -66,3 +92,5 @@ var selectors_options = { |
66 | 92 | $(e).removeAttr("opened"); //remove attribute so it can call API again |
67 | 93 | }, |
68 | 94 | }; |
95 | + | |
96 | + | ... | ... |
analytics/static/analytics/js/charts.js
... | ... | @@ -348,27 +348,7 @@ var charts = { |
348 | 348 | var width = 800; |
349 | 349 | var height = 300; |
350 | 350 | |
351 | - function min(){ | |
352 | - minimum = 100000000000; | |
353 | - for(var i = 0; i < dataset.length; i++){ | |
354 | - if (dataset[i]['count'] < min){ | |
355 | - minimum = dataset[i]['count']; | |
356 | - } | |
357 | - } | |
358 | - | |
359 | - return minimum | |
360 | - } | |
361 | - | |
362 | - function max(){ | |
363 | - maximum = 0; | |
364 | - for(var i = 0; i < dataset.length; i++){ | |
365 | - if (dataset[i]['count'] > max){ | |
366 | - maximum = dataset[i]['count']; | |
367 | - } | |
368 | - } | |
369 | - | |
370 | - return maximum | |
371 | - } | |
351 | + | |
372 | 352 | |
373 | 353 | |
374 | 354 | var container_div = d3.select("#most-used-tags-body"); |
... | ... | @@ -378,8 +358,8 @@ var charts = { |
378 | 358 | .style("background","#ddf8e7") |
379 | 359 | .append('g') |
380 | 360 | .attr("transform", "translate(0,0)") |
381 | - .style("width", width) | |
382 | - .attr("height", height); | |
361 | + .attr("width", "100%") | |
362 | + .attr("height", height - 60); | |
383 | 363 | |
384 | 364 | |
385 | 365 | var color = d3.scaleLinear() |
... | ... | @@ -392,7 +372,8 @@ var charts = { |
392 | 372 | return Math.floor(Math.random() * (max - min)) + min; |
393 | 373 | } |
394 | 374 | |
395 | - var xScale = d3.scaleSqrt().domain([min(), max()]).range([10,80]); | |
375 | + var xScale = d3.scaleSqrt().domain([d3.min(dataset, function(d){ return d['count']}), | |
376 | + d3.max(dataset, function(d){ return d.count; })]).range([100,200]); | |
396 | 377 | var tag_cloud = svg.selectAll('.tag-cloud-div') |
397 | 378 | .data(dataset) |
398 | 379 | .enter() |
... | ... | @@ -420,23 +401,29 @@ var charts = { |
420 | 401 | .text(function(d){ |
421 | 402 | return d['name']; |
422 | 403 | }) |
404 | + .attr("text-anchor", "middle") | |
423 | 405 | .attr("x", function(d){ |
424 | - return xScale(d['count'])*0.2; | |
406 | + return xScale(d['count'])*1.2/2; | |
425 | 407 | }) |
426 | 408 | .attr("y", function(d){ |
427 | - return xScale(d["count"])*0.2; | |
409 | + return xScale(d["count"])*0.4/2; | |
428 | 410 | }) |
429 | 411 | .attr("class", "tag-name") |
430 | - .attr("fill", "#ffffff"); | |
412 | + .attr("fill", "#ffffff") | |
413 | + .style("font-size", function(d){ | |
414 | + return xScale(d["count"])*0.1 + "px"; | |
415 | + }); | |
431 | 416 | |
432 | 417 | |
433 | 418 | var simulation = d3.forceSimulation() |
434 | 419 | .force("x", d3.forceX(width/2).strength(0.05)) |
435 | 420 | .force("y", d3.forceY(height/2).strength(0.05)) |
436 | - .force("collide", d3.forceCollide(function(d){ | |
437 | - return xScale(d['count'])*0.4; | |
438 | - })); | |
439 | - | |
421 | + .force("charge", d3.forceManyBody().strength(-120).distanceMax(300) | |
422 | + .distanceMin(0)); | |
423 | + /* | |
424 | + .force("collide", d3.forceCollide(function(d){ | |
425 | + return xScale(d['count'])*0.3; | |
426 | + }))*/ | |
440 | 427 | //simulation |
441 | 428 | simulation.nodes(dataset) |
442 | 429 | .on('tick', ticked); //so all data points are attached to it |
... | ... | @@ -448,6 +435,65 @@ var charts = { |
448 | 435 | } |
449 | 436 | |
450 | 437 | }); |
438 | + }, | |
439 | + month_heatmap: function(data, target){ | |
440 | + | |
441 | + | |
442 | + if(target == '#right-chart-body' && $('#month-chart').length != 0){ | |
443 | + $('#month-chart').fadeOut(); | |
444 | + $('#month-chart').remove(); | |
445 | + } | |
446 | + | |
447 | + if(target == "#bottom-right-chart-body" && $('#weekly-chart').length != 0){ | |
448 | + $('#weekly-chart').fadeOut(); | |
449 | + $('#weekly-chart').remove(); | |
450 | + } | |
451 | + | |
452 | + var svg = d3.select(target).append('svg') | |
453 | + .attr('width', 300) | |
454 | + .attr('height', 200); | |
455 | + | |
456 | + if (target == "#right-chart-body"){ | |
457 | + svg.attr('id', 'month-chart'); | |
458 | + } | |
459 | + | |
460 | + if (target == "#bottom-right-chart-body"){ | |
461 | + svg.attr('id', 'weekly-chart'); | |
462 | + } | |
463 | + | |
464 | + //color range | |
465 | + var color = d3.scaleLinear().range(["#29c8b8", '#149e91']).domain([0, d3.max(data, function(d){ return d.count; })]); | |
466 | + | |
467 | + var rects = svg.selectAll("rect") | |
468 | + .data(data) | |
469 | + .enter() | |
470 | + .append("g"); | |
471 | + rect_width = 40; | |
472 | + rect_height = 40; | |
473 | + rects.append("rect") | |
474 | + .attr("width", rect_width) | |
475 | + .attr("height", rect_height) | |
476 | + .attr("class", "day_rect") | |
477 | + .attr("x", function(d, i){ | |
478 | + | |
479 | + return rect_width* (i % 7); | |
480 | + }).attr("y", function(d, i){ | |
481 | + return rect_height*(Math.floor(i / 7)); | |
482 | + }).attr("fill", function(d, i ){ | |
483 | + return color(d.count); | |
484 | + }); | |
485 | + | |
486 | + rects.append("text") | |
487 | + .text( function(d){ | |
488 | + return d.day; | |
489 | + }).attr("fill", "white") | |
490 | + .attr("text-anchor", "middle") | |
491 | + .attr("x", function(d, i){ | |
492 | + return rect_width* ( i % 7) + rect_width/2; | |
493 | + }).attr("y", function(d, i){ | |
494 | + return rect_height*(Math.floor( i / 7)) + rect_height/2; | |
495 | + }); | |
496 | + | |
451 | 497 | } |
452 | 498 | } |
453 | 499 | ... | ... |
analytics/templates/analytics/category.html
analytics/templates/analytics/general.html
... | ... | @@ -7,6 +7,7 @@ |
7 | 7 | {% endblock style %} |
8 | 8 | |
9 | 9 | {% block javascript %} |
10 | + | |
10 | 11 | <script type="text/javascript" src="{% static "analytics/js/charts.js" %}"></script> |
11 | 12 | <script type="text/javascript" src=" {% static "analytics/js/behavior.js" %} "></script> |
12 | 13 | {% endblock javascript %} |
... | ... | @@ -68,19 +69,20 @@ |
68 | 69 | <section class="bottom-section"> |
69 | 70 | <div class="chart left-chart"> |
70 | 71 | |
71 | - | |
72 | + <h4>{% trans "Most accessed " %}</h4> | |
72 | 73 | <div id="left-data-selector"> |
74 | + | |
73 | 75 | |
74 | 76 | <div class="selector" data-url="categories"> |
75 | - <p> {% trans "most accessed categories" %} </p> | |
77 | + <p> {% trans "Most accessed categories" %} </p> | |
76 | 78 | </div> |
77 | 79 | |
78 | 80 | <div class="selector" data-url="subjects"> |
79 | - <p> {% trans "most accessed subjects" %} </p> | |
81 | + <p> {% trans "Most accessed subjects" %} </p> | |
80 | 82 | </div> |
81 | 83 | |
82 | 84 | <div class="selector" data-url="resources"> |
83 | - <p> {% trans "most accessed resource" %} </p> | |
85 | + <p> {% trans "Most accessed resource" %} </p> | |
84 | 86 | </div> |
85 | 87 | |
86 | 88 | </div> |
... | ... | @@ -88,13 +90,36 @@ |
88 | 90 | </div> |
89 | 91 | <div class="chart middle-chart"> |
90 | 92 | <article> |
91 | - <h4>{% trans "most active users" %}</h4> | |
93 | + <h4>{% trans "Most active users" %}</h4> | |
92 | 94 | </article> |
93 | 95 | |
94 | 96 | </div> |
95 | 97 | <div class="chart right-chart"> |
96 | - | |
98 | + <div id="month_selector_div"> | |
99 | + <h4>{% trans "Amount of access in: " %} | |
100 | + <select id="month_selector"> | |
101 | + {% for month in months %} | |
102 | + <option>{{month}}</option> | |
103 | + {% endfor %} | |
104 | + | |
105 | + </select> | |
106 | + </h4> | |
107 | + </div> | |
97 | 108 | |
109 | + <div id="right-chart-body"> | |
110 | + | |
111 | + </div> | |
112 | + | |
113 | + <div class='input-group date'> | |
114 | + <label>{% trans "Select the begin of the week: " %}</label> | |
115 | + <input type='text' class="datepicker form-control" /> | |
116 | + <span class="input-group-addon"> | |
117 | + <span class="glyphicon glyphicon-calendar"></span> | |
118 | + </span> | |
119 | + </div> | |
120 | + <div id="bottom-right-chart-body"> | |
121 | + | |
122 | + </div> | |
98 | 123 | </div> |
99 | 124 | </section> |
100 | 125 | ... | ... |
analytics/urls.py
... | ... | @@ -4,6 +4,7 @@ from . import views |
4 | 4 | |
5 | 5 | urlpatterns = [ |
6 | 6 | url(r'^view/general/$', views.GeneralView.as_view(), name='view_general'), |
7 | + url(r'^view/category/data$', views.CategoryView.as_view(), name='view_category_data'), | |
7 | 8 | |
8 | 9 | #"api" callls |
9 | 10 | url(r'^most_used_tags/$', views.most_used_tags, name="most_used_tags"), |
... | ... | @@ -11,4 +12,6 @@ urlpatterns = [ |
11 | 12 | url(r'^most_accessed_categories/$', views.most_accessed_categories, name = "most_accessed_categories"), |
12 | 13 | url(r'^most_accessed_resources/$', views.most_accessed_resource_kind, name= "most_accessed_resources"), |
13 | 14 | url(r'^most_active_users/$', views.most_active_users, name= "most_active_users"), |
15 | + url(r'^amount_active_users_per_day/$', views.most_active_users_in_a_month, name="most_active_users_in_a_month"), | |
16 | + url(r'^get_days_of_the_week_log/$', views.get_days_of_the_week_log, name="get_days_of_the_week_log"), | |
14 | 17 | ] |
15 | 18 | \ No newline at end of file | ... | ... |
analytics/views.py
... | ... | @@ -13,6 +13,10 @@ import operator |
13 | 13 | from django.utils.translation import ugettext_lazy as _ |
14 | 14 | from django.shortcuts import render, get_object_or_404, redirect |
15 | 15 | |
16 | +from datetime import date, timedelta, datetime | |
17 | +import calendar | |
18 | +from collections import OrderedDict | |
19 | + | |
16 | 20 | |
17 | 21 | class GeneralView(generic.TemplateView): |
18 | 22 | template_name = "analytics/general.html" |
... | ... | @@ -20,20 +24,31 @@ class GeneralView(generic.TemplateView): |
20 | 24 | def dispatch(self, request, *args, **kwargs): |
21 | 25 | |
22 | 26 | if not request.user.is_staff: |
23 | - self.template_name = "analytics/category.html" | |
27 | + return redirect('analytics:view_category_data') | |
24 | 28 | return super(GeneralView, self).dispatch(request, *args, **kwargs) |
25 | 29 | |
26 | 30 | |
27 | 31 | def get_context_data(self, **kwargs): |
28 | 32 | context = {} |
33 | + | |
34 | + context['months'] = [_('January'), _('February'), _('March'), _('April'), _('May'), _('June'), _('July'), _('August'), | |
35 | + _('September'), _('October'), _('November'), _('December')] | |
29 | 36 | |
30 | 37 | return context |
31 | 38 | |
32 | 39 | |
33 | 40 | |
34 | 41 | def most_used_tags(request): |
35 | - tags = Tag.objects.all() | |
42 | + | |
43 | + | |
44 | + data = get_most_used_tags() | |
45 | + data = sorted(data.values(), key = lambda x: x['count'], reverse=True ) | |
46 | + data = data[:15] #get top 15 tags | |
47 | + return JsonResponse(data, safe= False) | |
48 | + | |
49 | +def get_most_used_tags(): | |
36 | 50 | |
51 | + tags = Tag.objects.all() | |
37 | 52 | data = {} |
38 | 53 | #grab all references to that tag |
39 | 54 | for tag in tags: |
... | ... | @@ -49,17 +64,31 @@ def most_used_tags(request): |
49 | 64 | else: |
50 | 65 | data[tag.name] = {'name': tag.name} |
51 | 66 | data[tag.name]['count'] = resources_count |
52 | - | |
53 | - data = sorted(data.values(), key = lambda x: x['count'], reverse=True ) | |
54 | - data = data[:30] #get top 30 tags | |
55 | - return JsonResponse(data, safe= False) | |
56 | - | |
57 | - | |
58 | -def heatmap(request): | |
59 | - return None | |
67 | + return data | |
68 | + | |
69 | + | |
70 | +def most_active_users_in_a_month(request): | |
71 | + params = request.GET | |
72 | + days = get_days_of_the_month(params['month']) | |
73 | + mappings = {_('January'): 1, _('February'): 2, _('March'): 3, _('April'): 4, _('May'): 5, _('June'): 6, _('July'): 7 | |
74 | + , _('August'): 8, _('September'): 9, _('October'): 10, _('November'): 11, _('December'): 12} | |
75 | + | |
76 | + days_list = [] | |
77 | + for day in days: | |
78 | + built_date = date(date.today().year, mappings[params['month']], day) | |
79 | + days_list.append(built_date) | |
80 | + data = activity_in_timestamp(days_list) | |
81 | + data = [{"day": day.day, "count": day_count} for day, day_count in data.items()] | |
82 | + return JsonResponse(data, safe=False) | |
60 | 83 | |
61 | 84 | |
85 | +def activity_in_timestamp(days): | |
86 | + data = {} | |
87 | + for day in days: | |
88 | + day_count = Log.objects.filter(datetime__date = day).count() | |
89 | + data[day] = day_count | |
62 | 90 | |
91 | + return data | |
63 | 92 | """ |
64 | 93 | Subject view that returns a list of the most used subjects """ |
65 | 94 | |
... | ... | @@ -68,44 +97,45 @@ def most_accessed_subjects(request): |
68 | 97 | data = {} #empty response |
69 | 98 | |
70 | 99 | data = Log.objects.filter(resource = 'subject') |
71 | - subjects = {} | |
72 | - for datum in data: | |
73 | - if datum.context: | |
74 | - subject_id = datum.context['subject_id'] | |
75 | - if subject_id in subjects.keys(): | |
76 | - subjects[subject_id]['count'] = subjects[subject_id]['count'] + 1 | |
77 | - | |
78 | - else: | |
79 | - subjects[subject_id] = {'name': datum.context['subject_name'], 'count': 1 } | |
80 | - | |
100 | + subjects = get_log_count_of_resource(resource='subject') | |
81 | 101 | #order the values of the dictionary by the count in descendent order |
82 | 102 | subjects = sorted(subjects.values(), key = lambda x: x['count'], reverse=True ) |
83 | 103 | subjects = subjects[:5] |
84 | 104 | |
85 | 105 | return JsonResponse(subjects, safe=False) |
86 | 106 | |
107 | +def get_log_count_of_resource(resource = ''): | |
108 | + | |
109 | + data = Log.objects.filter(resource = resource) | |
110 | + items = {} | |
111 | + for datum in data: | |
112 | + if datum.context: | |
113 | + item_id = datum.context[resource + '_id'] | |
114 | + if item_id in items.keys(): | |
115 | + items[item_id]['count'] = items[item_id]['count'] + 1 | |
116 | + else: | |
117 | + items[item_id] = {'name': datum.context[resource+'_name'], 'count': 1} | |
118 | + return items | |
87 | 119 | |
88 | 120 | |
89 | 121 | def most_accessed_categories(request): |
90 | 122 | data = {} |
91 | 123 | |
92 | 124 | data = Log.objects.filter(resource = 'category') |
93 | - categories = {} | |
94 | - for datum in data: | |
95 | - if datum.context: | |
96 | - category_id = datum.context['category_id'] | |
97 | - if category_id in categories.keys(): | |
98 | - categories[category_id]['count'] = categories[category_id]['count'] + 1 | |
99 | - else: | |
100 | - categories[category_id] = {'name': datum.context['category_name'], 'count': 1 } | |
125 | + categories = get_log_count_of_resource('category') | |
126 | + | |
127 | + | |
101 | 128 | |
102 | 129 | categories = sorted(categories.values(), key = lambda x: x['count'], reverse = True) |
103 | 130 | categories = categories[:5] |
104 | 131 | return JsonResponse(categories, safe= False) |
105 | 132 | |
106 | -def most_accessed_resource_kind(request): | |
107 | - resources = Resource.objects.distinct() | |
108 | 133 | |
134 | +def get_resource_subclasses_count(): | |
135 | + """ | |
136 | + get the amount of objects in each sub_class of resource | |
137 | + """ | |
138 | + resources = Resource.objects.distinct() | |
109 | 139 | data = {} |
110 | 140 | for resource in resources: |
111 | 141 | key = resource.__dict__['_my_subclass'] |
... | ... | @@ -114,6 +144,13 @@ def most_accessed_resource_kind(request): |
114 | 144 | else: |
115 | 145 | data[key] = {'name': key, 'count': 1} |
116 | 146 | |
147 | + return data | |
148 | + | |
149 | + | |
150 | +def most_accessed_resource_kind(request): | |
151 | + | |
152 | + data = get_resource_subclasses_count() | |
153 | + | |
117 | 154 | data = sorted(data.values(), key = lambda x: x['count'], reverse= True) |
118 | 155 | mapping = {} |
119 | 156 | mapping['pdffile'] = str(_('PDF File')) |
... | ... | @@ -136,4 +173,46 @@ def most_active_users(request): |
136 | 173 | user_object = User.objects.get(id=user['user_id']) |
137 | 174 | user['image'] = user_object.image_url |
138 | 175 | user['user'] = user_object.social_name |
139 | - return JsonResponse(fifty_users, safe=False) | |
140 | 176 | \ No newline at end of file |
177 | + return JsonResponse(fifty_users, safe=False) | |
178 | + | |
179 | + | |
180 | + | |
181 | + | |
182 | +def get_days_of_the_month(month): | |
183 | + | |
184 | + #get current year | |
185 | + year = date.today().year | |
186 | + mappings = {_('January'): 1, _('February'): 2, _('March'): 3, _('April'): 4, _('May'): 5, _('June'): 6, _('July'): 7 | |
187 | + , _('August'): 8, _('September'): 9, _('October'): 10, _('November'): 11, _('December'): 12} | |
188 | + | |
189 | + c = calendar.Calendar() | |
190 | + days = c.itermonthdays(year, mappings[month]) | |
191 | + days_set = set() | |
192 | + for day in days: | |
193 | + days_set.add(day) | |
194 | + | |
195 | + days_set.remove(0) #because 0 is not aan actual day from that month | |
196 | + return days_set | |
197 | + | |
198 | + | |
199 | + | |
200 | +def get_days_of_the_week_log(request): | |
201 | + date = request.GET['date'] | |
202 | + date = datetime.strptime( date, '%m/%d/%Y',) | |
203 | + days = get_days_of_the_week(date) | |
204 | + data = activity_in_timestamp(days) | |
205 | + data = [{"day": day.day, "count": day_count} for day, day_count in data.items()] | |
206 | + | |
207 | + return JsonResponse(data, safe= False) | |
208 | + | |
209 | +def get_days_of_the_week(date): | |
210 | + | |
211 | + days_set = [] | |
212 | + days_set.append(date) | |
213 | + for j in range(1, 7): | |
214 | + days_set.append(date + timedelta(days=j)) | |
215 | + return days_set | |
216 | + | |
217 | + | |
218 | +class CategoryView(generic.TemplateView): | |
219 | + template_name = "analytics/category.html" | ... | ... |
subjects/templates/subjects/home.html
... | ... | @@ -15,16 +15,21 @@ |
15 | 15 | {% endif %} |
16 | 16 | |
17 | 17 | |
18 | +{% if news %} | |
19 | + | |
20 | + | |
18 | 21 | |
19 | 22 | |
20 | 23 | <!-- Wrapper for slides --> |
21 | 24 | <div id="myCarousel" class="carousel slide " data-ride="carousel"> |
22 | 25 | <!-- Indicators --> |
23 | 26 | <ol class="carousel-indicators"> |
24 | - <li data-target="#myCarousel" data-slide-to="0" class="active"></li> | |
25 | - <li data-target="#myCarousel" data-slide-to="1"></li> | |
26 | - <li data-target="#myCarousel" data-slide-to="2"></li> | |
27 | - <li data-target="#myCarousel" data-slide-to="3"></li> | |
27 | + <li data-target="#myCarousel" data-slide-to="0" class="active"></li> | |
28 | + {% for new in news %} | |
29 | + {% if forloop.counter != news.count %} | |
30 | + <li data-target="#myCarousel" data-slide-to="{{forloop.counter}}"></li> | |
31 | + {% endif %} | |
32 | + {% endfor %} | |
28 | 33 | </ol> |
29 | 34 | |
30 | 35 | <div class="carousel-inner" role="listbox"> |
... | ... | @@ -52,6 +57,7 @@ |
52 | 57 | </a> |
53 | 58 | </div> |
54 | 59 | |
60 | +{% endif %} | |
55 | 61 | |
56 | 62 | |
57 | 63 | ... | ... |
subjects/views.py
... | ... | @@ -40,6 +40,7 @@ from io import BytesIO |
40 | 40 | from itertools import chain |
41 | 41 | from django.core import serializers |
42 | 42 | from rest_framework.renderers import JSONRenderer |
43 | +from rest_framework.parsers import JSONParser | |
43 | 44 | |
44 | 45 | from users.serializers import UserSerializer |
45 | 46 | from file_link.serializers import SimpleFileLinkSerializer, CompleteFileLinkSerializer |
... | ... | @@ -871,6 +872,21 @@ def realize_restore(request, subject): |
871 | 872 | if zip_file: |
872 | 873 | if zipfile.is_zipfile(zip_file): |
873 | 874 | file = zipfile.ZipFile(zip_file) |
874 | - print(file.namelist()) | |
875 | + total_files = len(file.namelist()) | |
876 | + | |
877 | + json_file = file.namelist()[total_files-1] | |
878 | + | |
879 | + dst_path = os.path.join(settings.MEDIA_ROOT, "tmp") | |
880 | + | |
881 | + path = file.extract(json_file, dst_path) | |
882 | + | |
883 | + for line in open(path, 'r'): | |
884 | + print(line) | |
885 | + #print(json.loads(line)) | |
886 | + | |
887 | + # with open(path) as bkp_file: | |
888 | + # data = json.loads(bkp_file.read()) | |
889 | + | |
890 | + # print(data) | |
875 | 891 | |
876 | 892 | return JsonResponse({'message': 'ok'}) |
877 | 893 | \ No newline at end of file | ... | ... |