Commit 7714c440f6e41b8f87515e8acf041b91f003698e
1 parent
2102fa3d
Exists in
master
and in
2 other branches
started building general report, tag data is ready but tag cloud chart is not, a…
…dded gradient where it was needed
Showing
16 changed files
with
713 additions
and
0 deletions
Show diff stats
analytics/static/.sass-cache/9bdb779ec82a4a96f72be09b83b7c997addd0129/general.sassc
0 → 100644
No preview for this file type
@@ -0,0 +1,43 @@ | @@ -0,0 +1,43 @@ | ||
1 | +.report-body { | ||
2 | + border: 1px solid #3ebeb4; | ||
3 | + border-radius: 20px; | ||
4 | + padding: 10px; } | ||
5 | + | ||
6 | +#general-report-header { | ||
7 | + height: 10%; | ||
8 | + display: block; } | ||
9 | + #general-report-header h3 { | ||
10 | + color: #009688; } | ||
11 | + #general-report-header ul { | ||
12 | + float: right; | ||
13 | + display: inline-flex; | ||
14 | + width: 50%; | ||
15 | + height: 15%; } | ||
16 | + #general-report-header ul li { | ||
17 | + margin-right: 2%; | ||
18 | + width: 50%; | ||
19 | + color: white; } | ||
20 | + #general-report-header ul li div.selected { | ||
21 | + background-color: #4dcfbd; | ||
22 | + width: 100%; | ||
23 | + text-align: center; | ||
24 | + border-radius: 20px; } | ||
25 | + #general-report-header ul li div { | ||
26 | + background-color: #0f8a9a; | ||
27 | + width: 100%; | ||
28 | + text-align: center; | ||
29 | + border-radius: 20px; } | ||
30 | + | ||
31 | +#most-used-tags-header { | ||
32 | + background: linear-gradient(to right, #0e8999, #6bf0ce); | ||
33 | + height: 40px; | ||
34 | + border-radius: 10px; | ||
35 | + color: #ffffff; } | ||
36 | + | ||
37 | +div.tag-cloud { | ||
38 | + width: 10%; | ||
39 | + border-radius: 25px; | ||
40 | + color: #ffffff; | ||
41 | + background-color: #52b7bd; } | ||
42 | + | ||
43 | +/*# sourceMappingURL=general.css.map */ |
@@ -0,0 +1,7 @@ | @@ -0,0 +1,7 @@ | ||
1 | +{ | ||
2 | +"version": 3, | ||
3 | +"mappings": "AAAA,YAAY;EACX,MAAM,EAAE,iBAAiB;EACzB,aAAa,EAAE,IAAI;EACnB,OAAO,EAAE,IAAI;;AAGd,sBAAsB;EACrB,MAAM,EAAE,GAAG;EACX,OAAO,EAAE,KAAK;EACd,yBAAE;IACD,KAAK,EAAE,OAAO;EAEf,yBAAE;IACD,KAAK,EAAE,KAAK;IACZ,OAAO,EAAE,WAAW;IACpB,KAAK,EAAE,GAAG;IACV,MAAM,EAAE,GAAG;IAEX,4BAAE;MACD,YAAY,EAAE,EAAE;MAChB,KAAK,EAAE,GAAG;MACV,KAAK,EAAE,KAAK;MAEZ,yCAAY;QACX,gBAAgB,EAAE,OAAO;QACzB,KAAK,EAAE,IAAI;QACX,UAAU,EAAE,MAAM;QAClB,aAAa,EAAE,IAAI;MAEpB,gCAAG;QACF,gBAAgB,EAAE,OAAO;QACzB,KAAK,EAAE,IAAI;QACX,UAAU,EAAE,MAAM;QAClB,aAAa,EAAE,IAAI;;AAIvB,sBAAsB;EACrB,UAAU,EAAE,2CAA2C;EACvD,MAAM,EAAE,IAAI;EACZ,aAAa,EAAE,IAAI;EACnB,KAAK,EAAE,OAAO;;AAEf,aAAa;EACZ,KAAK,EAAE,GAAG;EACV,aAAa,EAAE,IAAI;EACnB,KAAK,EAAE,OAAO;EACd,gBAAgB,EAAE,OAAO", | ||
4 | +"sources": ["general.sass"], | ||
5 | +"names": [], | ||
6 | +"file": "general.css" | ||
7 | +} | ||
0 | \ No newline at end of file | 8 | \ No newline at end of file |
@@ -0,0 +1,48 @@ | @@ -0,0 +1,48 @@ | ||
1 | +.report-body | ||
2 | + border: 1px solid #3ebeb4 | ||
3 | + border-radius: 20px | ||
4 | + padding: 10px | ||
5 | + | ||
6 | + | ||
7 | +#general-report-header | ||
8 | + height: 10% | ||
9 | + display: block | ||
10 | + h3 | ||
11 | + color: #009688 | ||
12 | + | ||
13 | + ul | ||
14 | + float: right | ||
15 | + display: inline-flex | ||
16 | + width: 50% | ||
17 | + height: 15% | ||
18 | + | ||
19 | + li | ||
20 | + margin-right: 2% | ||
21 | + width: 50% | ||
22 | + color: white | ||
23 | + | ||
24 | + div.selected | ||
25 | + background-color: #4dcfbd | ||
26 | + width: 100% | ||
27 | + text-align: center | ||
28 | + border-radius: 20px | ||
29 | + | ||
30 | + div | ||
31 | + background-color: #0f8a9a | ||
32 | + width: 100% | ||
33 | + text-align: center | ||
34 | + border-radius: 20px | ||
35 | + | ||
36 | + | ||
37 | + | ||
38 | +#most-used-tags-header | ||
39 | + background: linear-gradient(to right, #0e8999, #6bf0ce) | ||
40 | + height: 40px | ||
41 | + border-radius: 10px | ||
42 | + color: #ffffff | ||
43 | + | ||
44 | +div.tag-cloud | ||
45 | + width: 10% | ||
46 | + border-radius: 25px | ||
47 | + color: #ffffff | ||
48 | + background-color: #52b7bd | ||
0 | \ No newline at end of file | 49 | \ No newline at end of file |
@@ -0,0 +1,378 @@ | @@ -0,0 +1,378 @@ | ||
1 | +/* | ||
2 | + HOME CHARTS | ||
3 | +*/ | ||
4 | + | ||
5 | +//Adding this code by @jshanley to create a filter to look for the last child | ||
6 | + | ||
7 | +d3.selection.prototype.first = function() { | ||
8 | + return d3.select(this[0]); | ||
9 | +}; | ||
10 | +d3.selection.prototype.last = function() { | ||
11 | + var last = this.size() - 1; | ||
12 | + return d3.select(this[last]); | ||
13 | +}; | ||
14 | + | ||
15 | +var charts = { | ||
16 | + build_resource: function(url){ | ||
17 | + $.get(url, function(dataset){ | ||
18 | + | ||
19 | + | ||
20 | + var width = 600; | ||
21 | + var height = 300; | ||
22 | + var padding = 30; | ||
23 | + var radius = Math.min(width, height) / 2 - padding; | ||
24 | + | ||
25 | + var color = d3.scaleOrdinal(d3.schemeCategory20); | ||
26 | + var new_div = d3.select(".carousel-inner").append("div").attr("class","item"); | ||
27 | + var svg = new_div.append("svg").attr("width", width).attr("height", height) | ||
28 | + .style("margin","auto") | ||
29 | + .style("display","block") | ||
30 | + .append('g') | ||
31 | + .attr('transform', 'translate(' + (width / 2) + | ||
32 | + ',' + (height / 2 + padding ) + ')'); | ||
33 | + | ||
34 | + | ||
35 | + | ||
36 | + var donutInner = 20; | ||
37 | + var arc = d3.arc() | ||
38 | + .innerRadius(radius - donutInner) | ||
39 | + .outerRadius(radius); | ||
40 | + | ||
41 | + svg.append("text") | ||
42 | + .attr("text-anchor", "middle") | ||
43 | + .attr("x",0 ) | ||
44 | + .attr("y", -height/2 ) | ||
45 | + .style("font-size", "30px") | ||
46 | + .text("Recursos mais utilizados") | ||
47 | + .attr("fill", "#003333") | ||
48 | + .style("font-weight", "bold") | ||
49 | + .style("font-style", "italic"); | ||
50 | + | ||
51 | + | ||
52 | + var pie = d3.pie() | ||
53 | + .value(function(d) { return d[1]; }) | ||
54 | + .sort(null); | ||
55 | + | ||
56 | + | ||
57 | + | ||
58 | + var path = svg.selectAll('path') | ||
59 | + .data(pie(dataset)) | ||
60 | + .enter() | ||
61 | + .append('path') | ||
62 | + .attr('d', arc) | ||
63 | + .attr('fill', function(d, i) { | ||
64 | + return color(i); | ||
65 | + }); | ||
66 | + var labelArc = d3.arc() | ||
67 | + .outerRadius(radius - donutInner + 30) | ||
68 | + .innerRadius(radius + 20 ); | ||
69 | + | ||
70 | + //Adding tooltips to each part of the pie chart. | ||
71 | + svg.selectAll("text.pie-tooltip") | ||
72 | + .data(pie(dataset)) | ||
73 | + .enter() | ||
74 | + .append("text") | ||
75 | + .attr("id", function(d){ | ||
76 | + return d.data[0]; | ||
77 | + }) | ||
78 | + .attr("class","pie-tooltip") | ||
79 | + .attr('fill',"#172121") | ||
80 | + .attr("transform", function(d) { | ||
81 | + c = labelArc.centroid(d); | ||
82 | + return "translate(" + (c[0]*1.0 - 20) +"," + c[1]*0.8 + ")"; | ||
83 | + }) | ||
84 | + .attr("dy", ".25em") | ||
85 | + .text(function(d) { return d.data[0] +'('+ d.data[1] +')'; }); | ||
86 | + | ||
87 | + | ||
88 | + | ||
89 | + }) // end of the get method | ||
90 | + }, | ||
91 | + | ||
92 | + build_bubble_user: function(url){ | ||
93 | + $.get(url, function(dataset){ | ||
94 | + var width = 600; | ||
95 | + var height = 300; | ||
96 | + | ||
97 | + | ||
98 | + function min(){ | ||
99 | + min = 100000000000; | ||
100 | + for(var i = 0; i < dataset.length; i++){ | ||
101 | + if (dataset[i]['count'] < min){ | ||
102 | + min = dataset[i]['count']; | ||
103 | + } | ||
104 | + } | ||
105 | + | ||
106 | + return min | ||
107 | + } | ||
108 | + | ||
109 | + function max(){ | ||
110 | + max = 0; | ||
111 | + for(var i = 0; i < dataset.length; i++){ | ||
112 | + if (dataset[i]['count'] > max){ | ||
113 | + max = dataset[i]['count']; | ||
114 | + } | ||
115 | + } | ||
116 | + | ||
117 | + return max | ||
118 | + } | ||
119 | + | ||
120 | + | ||
121 | + | ||
122 | + var color = d3.scaleOrdinal(d3.schemeCategory20); | ||
123 | + //adding new div to carousel-inner div | ||
124 | + var new_div = d3.select(".carousel-inner").append("div").attr("class","item"); | ||
125 | + var radiusScale = d3.scaleSqrt().domain([min(), max()]).range([10,50]); | ||
126 | + var svg = new_div.append("svg").attr("width", width).attr("height", height) | ||
127 | + .style("margin","auto") | ||
128 | + .style("display","block") | ||
129 | + .append('g') | ||
130 | + .attr("transform", "translate(0,0)") | ||
131 | + .attr("width", width) | ||
132 | + .attr("height", height); | ||
133 | + | ||
134 | + //adding svg title | ||
135 | + | ||
136 | + svg.append("text") | ||
137 | + .attr("text-anchor", "middle") | ||
138 | + .attr("x", width/2 ) | ||
139 | + .attr("y", 30) | ||
140 | + .style("font-size", "30px") | ||
141 | + .text("Usuários mais ativos no Amadeus") | ||
142 | + .attr("fill", "#003333") | ||
143 | + .style("font-weight", "bold") | ||
144 | + .style("font-style", "italic"); | ||
145 | + | ||
146 | + var simulation = d3.forceSimulation() | ||
147 | + .force("x", d3.forceX(width/2).strength(0.05)) | ||
148 | + .force("y", d3.forceY(height/2).strength(0.05)) | ||
149 | + .force("collide", d3.forceCollide(function(d){ | ||
150 | + return radiusScale(d['count']); | ||
151 | + })); | ||
152 | + | ||
153 | + //First I create as many groups as datapoints so | ||
154 | + //it can hold all other objects (circle, texts, images) | ||
155 | + var groups = svg.selectAll('.users-item') | ||
156 | + .data(dataset) | ||
157 | + .enter() | ||
158 | + .append("g") | ||
159 | + .attr("class",".user-dot"); | ||
160 | + | ||
161 | + //Create circles to be drawn | ||
162 | + var circles = groups | ||
163 | + .append('circle') | ||
164 | + .attr("r", function(d){ | ||
165 | + return radiusScale(d['count']); | ||
166 | + }) | ||
167 | + | ||
168 | + .attr("fill", function(d){ | ||
169 | + return 'url('+'#'+'user_'+d['user_id']+')'; | ||
170 | + }); | ||
171 | + | ||
172 | + | ||
173 | + | ||
174 | + //Add texts to show user names | ||
175 | + groups.append("text") | ||
176 | + .text(function(d){ | ||
177 | + return d['user'] +'('+ d['count'] + ')'; | ||
178 | + }).attr("fill", "#FFFFFF") | ||
179 | + .attr("id", function(d){ | ||
180 | + return "user_tooltip_"+d['user_id']; | ||
181 | + }).style("display", "none"); | ||
182 | + | ||
183 | + | ||
184 | + groups.on("mouseover", function(d){ | ||
185 | + $("#"+"user_tooltip_"+d['user_id']).show(); | ||
186 | + }); | ||
187 | + | ||
188 | + | ||
189 | + groups.on("mouseout", function(d){ | ||
190 | + $("#"+"user_tooltip_"+d['user_id']).hide(); | ||
191 | + }); | ||
192 | + | ||
193 | + var defs = groups.append('svg:defs'); | ||
194 | + | ||
195 | + //Attching images to bubbles | ||
196 | + defs.append("svg:pattern") | ||
197 | + .attr("id", function(d){ | ||
198 | + return "user_"+d['user_id']; | ||
199 | + }) | ||
200 | + .attr("width", function(d){ | ||
201 | + return radiusScale(d['count']); | ||
202 | + }) | ||
203 | + .attr("height", function(d){ | ||
204 | + return radiusScale(d['count']); | ||
205 | + }) | ||
206 | + .append("svg:image") | ||
207 | + .attr("xlink:href", function(d){ | ||
208 | + return d['image']; | ||
209 | + }) | ||
210 | + .attr("width",function(d){ | ||
211 | + return radiusScale(d['count'])*2; | ||
212 | + }) | ||
213 | + .attr("height", function(d){ | ||
214 | + return radiusScale(d['count'])*2; | ||
215 | + }) | ||
216 | + .attr("x", 0) | ||
217 | + .attr("y", 0); | ||
218 | + | ||
219 | + | ||
220 | + | ||
221 | + //simulation | ||
222 | + simulation.nodes(dataset) | ||
223 | + .on('tick', ticked); //so all data points are attached to it | ||
224 | + | ||
225 | + function ticked(){ | ||
226 | + groups.attr("transform", function(d){ | ||
227 | + return "translate(" + d.x + "," + d.y + ")"; | ||
228 | + }) | ||
229 | + } | ||
230 | + }); | ||
231 | + | ||
232 | + | ||
233 | + }, | ||
234 | + | ||
235 | + most_accessed_subjects: function(url){ | ||
236 | + $.get(url, function(dataset){ | ||
237 | + var width = 800; | ||
238 | + var height = 300; | ||
239 | + | ||
240 | + var new_div = d3.select(".carousel-inner").append("div").attr("class","item"); | ||
241 | + | ||
242 | + var svg = new_div.append("svg").attr("width", "100%").attr("height", height) | ||
243 | + .style("margin","auto") | ||
244 | + .style("display","block"); | ||
245 | + | ||
246 | + var barPadding = 2 | ||
247 | + var bottomPadding = 15; | ||
248 | + var marginLeft = 170; //Margin Left for all bars inside the graph | ||
249 | + | ||
250 | + var yScale = d3.scaleLinear() | ||
251 | + .domain([0, d3.max(dataset, function(d) { return d.count; })]) | ||
252 | + .range([bottomPadding, 260]); | ||
253 | + | ||
254 | + var rects = svg.selectAll("rect") | ||
255 | + .data(dataset) | ||
256 | + .enter() | ||
257 | + .append("g"); | ||
258 | + | ||
259 | + rects.append("rect") | ||
260 | + .attr("x", function(d, i){ | ||
261 | + return i * (width / dataset.length ) + barPadding + marginLeft ; | ||
262 | + }) | ||
263 | + .attr("y", function(d){ | ||
264 | + return height - yScale(d.count) - bottomPadding; | ||
265 | + }) | ||
266 | + .attr("width", | ||
267 | + width / dataset.length - barPadding | ||
268 | + ) | ||
269 | + .attr("height", function(d){ | ||
270 | + return yScale(d.count); | ||
271 | + }); | ||
272 | + | ||
273 | + | ||
274 | + var tooltipDiv = new_div.append("div").attr("class","bar-tip"); | ||
275 | + | ||
276 | + rects.on("mouseover", function(d, i){ | ||
277 | + $(this).attr("fill", "red"); | ||
278 | + $("#accessed_subject_"+i).show(); //So the tooltip is hidden | ||
279 | + tooltipDiv.transition() | ||
280 | + .duration(200) | ||
281 | + .style("opacity", .9); | ||
282 | + tooltipDiv.html("<p style='font-size:9px'>" + d.name + "( " + d.count + " )" +"</p>") | ||
283 | + .style("left", (i * (width / dataset.length ) + barPadding + marginLeft) + "px") | ||
284 | + .style("top", (height - yScale(d.count) - bottomPadding) + "px"); | ||
285 | + }); | ||
286 | + | ||
287 | + rects.on("mouseout", function(d, i ){ | ||
288 | + $(this).attr("fill", "black"); | ||
289 | + | ||
290 | + $("#accessed_subject_"+i).hide(); //So the tooltip shows up | ||
291 | + | ||
292 | + | ||
293 | + tooltipDiv.transition() | ||
294 | + .duration(500) | ||
295 | + .style("opacity", 0); | ||
296 | + | ||
297 | + }); | ||
298 | + | ||
299 | + | ||
300 | + | ||
301 | + //Styling title | ||
302 | + svg.append("text") | ||
303 | + .attr("x", width/2) | ||
304 | + .attr("y", 30) | ||
305 | + .attr("text-anchor", "middle") | ||
306 | + .style("font-size", "30px") | ||
307 | + .text("Subjects mais acessados") | ||
308 | + .attr("fill", "#003333") | ||
309 | + .style("font-weight", "bold") | ||
310 | + .style("font-style", "italic"); | ||
311 | + | ||
312 | + }); | ||
313 | + }, | ||
314 | + most_used_tags: function(url){ | ||
315 | + $.get(url, function(dataset){ | ||
316 | + //get most used tags across all amadeus | ||
317 | + var width = 800; | ||
318 | + var height = 300; | ||
319 | + | ||
320 | + function min(){ | ||
321 | + min = 100000000000; | ||
322 | + for(var i = 0; i < dataset.length; i++){ | ||
323 | + if (dataset[i]['count'] < min){ | ||
324 | + min = dataset[i]['count']; | ||
325 | + } | ||
326 | + } | ||
327 | + | ||
328 | + return min | ||
329 | + } | ||
330 | + | ||
331 | + function max(){ | ||
332 | + max = 0; | ||
333 | + for(var i = 0; i < dataset.length; i++){ | ||
334 | + if (dataset[i]['count'] > max){ | ||
335 | + max = dataset[i]['count']; | ||
336 | + } | ||
337 | + } | ||
338 | + | ||
339 | + return max | ||
340 | + } | ||
341 | + | ||
342 | + console.log(dataset); | ||
343 | + | ||
344 | + var container_div = d3.select("#most-used-tags-body"); | ||
345 | + var svg = container_div.append("svg").attr("width", "100%").attr("height", height) | ||
346 | + .style("margin","auto") | ||
347 | + .style("display","block") | ||
348 | + .style("background","#ddf8e7") | ||
349 | + .append('g') | ||
350 | + .attr("transform", "translate(0,0)") | ||
351 | + .attr("width", width) | ||
352 | + .attr("height", height); | ||
353 | + | ||
354 | + | ||
355 | + | ||
356 | + var radiusScale = d3.scaleSqrt().domain([min(), max()]).range([10,50]); | ||
357 | + var tag_cloud = svg.selectAll('.tag-cloud-div') | ||
358 | + .data(dataset) | ||
359 | + .enter() | ||
360 | + .append('g') | ||
361 | + .attr("class", "data-container"); | ||
362 | + | ||
363 | + | ||
364 | + var tag_divs = tag_cloud | ||
365 | + .append('div') | ||
366 | + .attr('class', 'tag-cloud') | ||
367 | + .attr('text', function(d){ | ||
368 | + return d['name']; | ||
369 | + }); | ||
370 | + | ||
371 | + }); | ||
372 | + } | ||
373 | +} | ||
374 | + | ||
375 | +charts.most_used_tags('/analytics/most_used_tags'); | ||
376 | +//charts.build_resource('/topics/count_resources/'); | ||
377 | +//charts.build_bubble_user('/users/get_users_log/'); | ||
378 | +//charts.most_accessed_subjects('/subjects/most_accessed_subjects'); | ||
0 | \ No newline at end of file | 379 | \ No newline at end of file |
@@ -0,0 +1,76 @@ | @@ -0,0 +1,76 @@ | ||
1 | +{% extends 'base.html' %} | ||
2 | + | ||
3 | +{% load static i18n pagination %} | ||
4 | +{% load django_bootstrap_breadcrumbs %} | ||
5 | +{% block style %} | ||
6 | + <link rel="stylesheet" type="text/css" href="{% static 'analytics/general.css' %}"> | ||
7 | +{% endblock style %} | ||
8 | + | ||
9 | +{% block javascript %} | ||
10 | + <script type="text/javascript" src="{% static "analytics/js/charts.js" %}"></script> | ||
11 | +{% endblock javascript %} | ||
12 | + | ||
13 | +{% block breadcrumbs %} | ||
14 | + {{ block.super }} | ||
15 | + | ||
16 | + {% trans 'Analytics General' as general %} | ||
17 | + | ||
18 | + {% breadcrumb general 'dashboard:view_general' %} | ||
19 | +{% endblock %} | ||
20 | + | ||
21 | + | ||
22 | +{% block content %} | ||
23 | + <div id="core-subjects-options-div"> | ||
24 | + <ul class="core-subjects-options report-menu-choice"> | ||
25 | + <li class="active"> | ||
26 | + {% trans "Platform Report" %} | ||
27 | + </li> | ||
28 | + <li> | ||
29 | + {% trans "Category Report" %} | ||
30 | + </li> | ||
31 | + <li> | ||
32 | + {% trans "Subject Report" %} | ||
33 | + </li> | ||
34 | + </ul> | ||
35 | + </div> | ||
36 | + | ||
37 | + <div id="general-report"> | ||
38 | + <div id="general-report-header"> | ||
39 | + <h3>{% trans "Amadeus Report" %}</h3> | ||
40 | + | ||
41 | + <ul id="report-header-options"> | ||
42 | + <li > | ||
43 | + <div class="selected">{% trans "Focus" %}<div> | ||
44 | + </li> | ||
45 | + <li> | ||
46 | + <div>{% trans "Log" %}<div> | ||
47 | + </li> | ||
48 | + </ul> | ||
49 | + </div> | ||
50 | + | ||
51 | + <div class="report-body"> | ||
52 | + | ||
53 | + <div id="most-used-tags"> | ||
54 | + <div id="most-used-tags-header"> | ||
55 | + <h4 > | ||
56 | + {% trans "most used tags" %} | ||
57 | + </h4> | ||
58 | + </div> | ||
59 | + <div id="most-used-tags-body"> | ||
60 | + | ||
61 | + </div> | ||
62 | + </div> | ||
63 | + <div class="bottom-section"> | ||
64 | + <div class="left-chart"></div> | ||
65 | + <div class="middle-chart"></div> | ||
66 | + <div class="right-chart"></div> | ||
67 | + </div> | ||
68 | + | ||
69 | + </div> | ||
70 | + </div> | ||
71 | + | ||
72 | + <script type="text/javascript"> | ||
73 | + </script> | ||
74 | + | ||
75 | + | ||
76 | +{% endblock content %} | ||
0 | \ No newline at end of file | 77 | \ No newline at end of file |
@@ -0,0 +1,45 @@ | @@ -0,0 +1,45 @@ | ||
1 | +from django.test import TestCase, Client, override_settings | ||
2 | +from django.core.urlresolvers import resolve | ||
3 | +from reports.views import ReportView | ||
4 | +from subjects.models import Subject, Tag | ||
5 | +from users.models import User | ||
6 | +from topics.models import Topic, Resource | ||
7 | +from chat.models import Conversation, TalkMessages | ||
8 | +from datetime import datetime | ||
9 | +from log.models import Log | ||
10 | +from django.db.models import Q | ||
11 | +from ..views import most_used_tags | ||
12 | +from django.http import HttpResponse, JsonResponse | ||
13 | + | ||
14 | +class APIDashBoardTest(TestCase): | ||
15 | + | ||
16 | + def setUp(self): | ||
17 | + self.c = Client() | ||
18 | + self.student = User.objects.create(username = "student01", email= "student01@amadeus.br", password="amadeus") | ||
19 | + if self.c.login(email="student01@amadeus.br", password="amadeus"): | ||
20 | + print("student01 logged in") | ||
21 | + | ||
22 | + | ||
23 | + def test_most_used_tags(self): | ||
24 | + t = Tag(name="felipe") | ||
25 | + t.save() | ||
26 | + t1 = Tag(name="b2") | ||
27 | + t1.save() | ||
28 | + | ||
29 | + s1 = Subject.objects.create(name="subject", visible= True, init_date= datetime.now(), end_date= datetime.now(), | ||
30 | + subscribe_begin = datetime.now(), subscribe_end= datetime.now() ) | ||
31 | + s1.tags.add(t) | ||
32 | + s1.save() | ||
33 | + s2 = Subject.objects.create(name="subject dois", visible= True, init_date= datetime.now(), end_date= datetime.now(), | ||
34 | + subscribe_begin = datetime.now(), subscribe_end= datetime.now() ) | ||
35 | + s2.tags.add(t) | ||
36 | + s2.save() | ||
37 | + r1 = Resource.objects.create(name="resource um") | ||
38 | + r1.tags.add(t1) | ||
39 | + r1.save() | ||
40 | + | ||
41 | + | ||
42 | + expected_data = {'felipe': 2, 'b2': 1} | ||
43 | + data = self.c.get('/analytics/most_used_tags/') | ||
44 | + print(data) | ||
45 | + self.assertEqual(data, expected_data) |
@@ -0,0 +1,10 @@ | @@ -0,0 +1,10 @@ | ||
1 | +from django.conf.urls import url, include | ||
2 | +from . import views | ||
3 | + | ||
4 | + | ||
5 | +urlpatterns = [ | ||
6 | + url(r'^view/general/$', views.GeneralView.as_view(), name='view_general'), | ||
7 | + | ||
8 | + #"api" callls | ||
9 | + url(r'^most_used_tags/$', views.most_used_tags, name="most_used_tags"), | ||
10 | +] | ||
0 | \ No newline at end of file | 11 | \ No newline at end of file |
@@ -0,0 +1,92 @@ | @@ -0,0 +1,92 @@ | ||
1 | +from django.shortcuts import render | ||
2 | + | ||
3 | +# Create your views here. | ||
4 | +from django.views import generic | ||
5 | +from django.db.models import Count | ||
6 | + | ||
7 | +from subjects.models import Tag, Subject | ||
8 | +from topics.models import Resource | ||
9 | +from users.models import User | ||
10 | +from django.http import HttpResponse, JsonResponse | ||
11 | + | ||
12 | + | ||
13 | +class GeneralView(generic.TemplateView): | ||
14 | + template_name = "analytics/general.html" | ||
15 | + | ||
16 | + def get_context_data(self, **kwargs): | ||
17 | + context = {} | ||
18 | + | ||
19 | + return context | ||
20 | + | ||
21 | + | ||
22 | + | ||
23 | +def most_used_tags(request): | ||
24 | + tags = Tag.objects.all() | ||
25 | + | ||
26 | + data = {} | ||
27 | + #grab all references to that tag | ||
28 | + for tag in tags: | ||
29 | + subjects_count = Subject.objects.filter(tags = tag).count() | ||
30 | + if subjects_count > 0: | ||
31 | + data[tag.name] = {'name': tag.name} | ||
32 | + data[tag.name]['count'] = subjects_count | ||
33 | + | ||
34 | + resources_count = Resource.objects.filter(tags = tag).count() | ||
35 | + if resources_count > 0: | ||
36 | + if data.get(tag.name): | ||
37 | + data[tag.name]['count'] = data[tag.name]['count'] + resources_count | ||
38 | + else: | ||
39 | + data[tag.name] = {'name': tag.name} | ||
40 | + data[tag.name]['count'] = resources_count | ||
41 | + | ||
42 | + data = sorted(data.values(), key = lambda x: x['count'], reverse=True ) | ||
43 | + data = data[:30] #get top 30 tags | ||
44 | + return JsonResponse(data, safe= False) | ||
45 | + | ||
46 | + | ||
47 | +def heatmap(request): | ||
48 | + return None | ||
49 | + | ||
50 | + | ||
51 | + | ||
52 | +""" | ||
53 | +Subject view that returns a list of the most used subjects """ | ||
54 | + | ||
55 | + | ||
56 | +def most_acessed_subjects(request): | ||
57 | + data = {} #empty response | ||
58 | + | ||
59 | + data = Log.objects.filter(resource = 'subject') | ||
60 | + subjects = {} | ||
61 | + for datum in data: | ||
62 | + if datum.context: | ||
63 | + subject_id = datum.context['subject_id'] | ||
64 | + if subject_id in subjects.keys(): | ||
65 | + subjects[subject_id]['count'] = subjects[subject_id]['count'] + 1 | ||
66 | + else: | ||
67 | + subjects[subject_id] = {'name': datum.context['subject_name'], 'count':0 } | ||
68 | + | ||
69 | + | ||
70 | + #order the values of the dictionary by the count in descendent order | ||
71 | + subjects = sorted(subjects.values(), key = lambda x: x['count'], reverse=True ) | ||
72 | + subjects = subjects[:30] | ||
73 | + | ||
74 | + return JsonResponse(subjects, safe=False) | ||
75 | + | ||
76 | + | ||
77 | + | ||
78 | +def most_accessed_categories(request): | ||
79 | + return None | ||
80 | + | ||
81 | +def most_accessed_resource_kind(request): | ||
82 | + return None | ||
83 | + | ||
84 | + | ||
85 | +def get_users_log(request): | ||
86 | + fifty_users = Log.objects.values('user_id').annotate(count = Count('user_id')).order_by('-count')[:50] | ||
87 | + fifty_users = list(fifty_users) | ||
88 | + for user in fifty_users: | ||
89 | + user_object = User.objects.get(id=user['user_id']) | ||
90 | + user['image'] = user_object.image_url | ||
91 | + user['user'] = user_object.social_name | ||
92 | + return JsonResponse(fifty_users, safe=False) | ||
0 | \ No newline at end of file | 93 | \ No newline at end of file |