Commit 17776dcf618219e0278b2331bd3ab9abed3de0eb

Authored by Felipe Bormann
2 parents 7433e08d 2c9d9435

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

amadeus/static/css/.sass-cache/a7f87b90919294b62ab4f8079e31dcda8f485534/green.sassc
No preview for this file type
amadeus/static/css/base/amadeus.css
@@ -1612,7 +1612,7 @@ div.dataTables_wrapper div.dataTables_paginate { @@ -1612,7 +1612,7 @@ div.dataTables_wrapper div.dataTables_paginate {
1612 font-size: 14px; 1612 font-size: 14px;
1613 } 1613 }
1614 1614
1615 -.subject-related-panel .panel { 1615 +.subject-related-panel .panel:not(.participant) {
1616 margin-bottom: 0px; 1616 margin-bottom: 0px;
1617 } 1617 }
1618 1618
amadeus/static/css/base/amadeus_responsive.css
@@ -7,11 +7,6 @@ @@ -7,11 +7,6 @@
7 height: 38px; 7 height: 38px;
8 } 8 }
9 9
10 - .mural .post_make .user-img img {  
11 - max-width: 70px;  
12 - max-height: 70px;  
13 - }  
14 -  
15 .mural .post_make .post-field h4 { 10 .mural .post_make .post-field h4 {
16 line-height: 2.6em; 11 line-height: 2.6em;
17 } 12 }
@@ -35,11 +30,6 @@ @@ -35,11 +30,6 @@
35 height: 38px; 30 height: 38px;
36 } 31 }
37 32
38 - .mural .post_make .user-img img {  
39 - max-width: 65px;  
40 - max-height: 65px;  
41 - }  
42 -  
43 .mural .post_make .post-field h4 { 33 .mural .post_make .post-field h4 {
44 line-height: 2.3em; 34 line-height: 2.3em;
45 } 35 }
@@ -134,11 +124,6 @@ @@ -134,11 +124,6 @@
134 height: 60px; 124 height: 60px;
135 } 125 }
136 126
137 - .mural .post_make .user-img img {  
138 - max-width: 60px;  
139 - max-height: 60px;  
140 - }  
141 -  
142 .mural .post_make .post-field h4 { 127 .mural .post_make .post-field h4 {
143 line-height: 2em; 128 line-height: 2em;
144 } 129 }
@@ -228,11 +213,6 @@ @@ -228,11 +213,6 @@
228 height: 50px; 213 height: 50px;
229 } 214 }
230 215
231 - .mural .post_make .user-img img {  
232 - max-width: 50px;  
233 - max-height: 50px;  
234 - }  
235 -  
236 .mural .post_make .post-field h4 { 216 .mural .post_make .post-field h4 {
237 line-height: 1.6em; 217 line-height: 1.6em;
238 } 218 }
amadeus/static/css/themes/green.css
@@ -396,9 +396,6 @@ a.add-row { @@ -396,9 +396,6 @@ a.add-row {
396 .mural .post_make { 396 .mural .post_make {
397 background: #FFFFFF; } 397 background: #FFFFFF; }
398 398
399 -.mural .post_make .user-img, .post .post-img, .post .post-comment .user-img div, .comment .comment-img div {  
400 - background: #CCCCCC; }  
401 -  
402 .mural .post_make .post-field div { 399 .mural .post_make .post-field div {
403 border-color: #CCCCCC; } 400 border-color: #CCCCCC; }
404 401
amadeus/static/css/themes/green.css.map
1 { 1 {
2 "version": 3, 2 "version": 3,
3 -"mappings": "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", 3 +"mappings": "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",
4 "sources": ["green.sass"], 4 "sources": ["green.sass"],
5 "names": [], 5 "names": [],
6 "file": "green.css" 6 "file": "green.css"
amadeus/static/css/themes/green.sass
@@ -544,10 +544,6 @@ a.add-row @@ -544,10 +544,6 @@ a.add-row
544 background: $white 544 background: $white
545 545
546 546
547 -.mural .post_make .user-img, .post .post-img, .post .post-comment .user-img div, .comment .comment-img div  
548 - background: #CCCCCC  
549 -  
550 -  
551 .mural .post_make .post-field div 547 .mural .post_make .post-field div
552 border-color: #CCCCCC 548 border-color: #CCCCCC
553 549
amadeus/templates/base.html
@@ -145,7 +145,7 @@ @@ -145,7 +145,7 @@
145 </ul> 145 </ul>
146 </li> 146 </li>
147 <li style="width:40px;"> 147 <li style="width:40px;">
148 - <a href="" id="contrast_button"> 148 + <a href="{% url 'themes:contrast' %}" id="contrast_button">
149 <i style="font-size:15px;right: 150%;" class="glyphicon glyphicon-adjust"></i> 149 <i style="font-size:15px;right: 150%;" class="glyphicon glyphicon-adjust"></i>
150 </a> 150 </a>
151 151
@@ -209,11 +209,11 @@ @@ -209,11 +209,11 @@
209 $("#contrast_button" ).click(function() { 209 $("#contrast_button" ).click(function() {
210 if (Cookies.get('contrast_check')) { 210 if (Cookies.get('contrast_check')) {
211 Cookies.remove('contrast_check') 211 Cookies.remove('contrast_check')
212 - location.reload() 212 + //location.reload()
213 } 213 }
214 else { 214 else {
215 Cookies.set('contrast_check','contrast') 215 Cookies.set('contrast_check','contrast')
216 - location.reload() 216 + //location.reload()
217 } 217 }
218 218
219 }); 219 });
file_link/locale/pt_BR/LC_MESSAGES/django.po
@@ -8,7 +8,7 @@ msgid &quot;&quot; @@ -8,7 +8,7 @@ msgid &quot;&quot;
8 msgstr "" 8 msgstr ""
9 "Project-Id-Version: PACKAGE VERSION\n" 9 "Project-Id-Version: PACKAGE VERSION\n"
10 "Report-Msgid-Bugs-To: \n" 10 "Report-Msgid-Bugs-To: \n"
11 -"POT-Creation-Date: 2017-04-15 00:13-0300\n" 11 +"POT-Creation-Date: 2017-05-05 17:50-0300\n"
12 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" 12 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
13 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" 13 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
14 "Language-Team: LANGUAGE <LL@li.org>\n" 14 "Language-Team: LANGUAGE <LL@li.org>\n"
@@ -18,27 +18,27 @@ msgstr &quot;&quot; @@ -18,27 +18,27 @@ msgstr &quot;&quot;
18 "Content-Transfer-Encoding: 8bit\n" 18 "Content-Transfer-Encoding: 8bit\n"
19 "Plural-Forms: nplurals=2; plural=(n > 1);\n" 19 "Plural-Forms: nplurals=2; plural=(n > 1);\n"
20 20
21 -#: file_link/forms.py:26 21 +#: forms.py:26
22 msgid "Tags" 22 msgid "Tags"
23 msgstr "Tags" 23 msgstr "Tags"
24 24
25 -#: file_link/forms.py:32 25 +#: forms.py:32
26 msgid "File name" 26 msgid "File name"
27 msgstr "Nome do arquivo" 27 msgstr "Nome do arquivo"
28 28
29 -#: file_link/forms.py:52 29 +#: forms.py:52
30 msgid "This subject already has a file link with this name" 30 msgid "This subject already has a file link with this name"
31 msgstr "Esse assunto já possui um Link para Arquivo com esse nome" 31 msgstr "Esse assunto já possui um Link para Arquivo com esse nome"
32 32
33 -#: file_link/forms.py:64 33 +#: forms.py:64
34 msgid "The file is too large. It should have less than 10MB." 34 msgid "The file is too large. It should have less than 10MB."
35 msgstr "Esse arquivo é muito grande. Ele deve conter menos de 10MB." 35 msgstr "Esse arquivo é muito grande. Ele deve conter menos de 10MB."
36 36
37 -#: file_link/forms.py:69 37 +#: forms.py:69
38 msgid "This field is required." 38 msgid "This field is required."
39 msgstr "Esse campo é obrigatório." 39 msgstr "Esse campo é obrigatório."
40 40
41 -#: file_link/models.py:23 41 +#: models.py:23
42 msgid "" 42 msgid ""
43 "Please select a valid file. The uploaded file must have one of the following " 43 "Please select a valid file. The uploaded file must have one of the following "
44 "extensions: .doc, .docx, .html, .jpg, .odp, .ods, .odt, .pdf, .png, .ppt, ." 44 "extensions: .doc, .docx, .html, .jpg, .odp, .ods, .odt, .pdf, .png, .ppt, ."
@@ -48,76 +48,146 @@ msgstr &quot;&quot; @@ -48,76 +48,146 @@ msgstr &quot;&quot;
48 "das seguintes extensões: .doc, .docx, .html, .jpg, .odp, .ods, .odt, .pdf, ." 48 "das seguintes extensões: .doc, .docx, .html, .jpg, .odp, .ods, .odt, .pdf, ."
49 "png, .ppt, .pptx, .xlx e .xlsx" 49 "png, .ppt, .pptx, .xlx e .xlsx"
50 50
51 -#: file_link/models.py:26 51 +#: models.py:26
52 msgid "File" 52 msgid "File"
53 msgstr "Arquivo" 53 msgstr "Arquivo"
54 54
55 -#: file_link/models.py:29 55 +#: models.py:29
56 msgid "File Link" 56 msgid "File Link"
57 msgstr "Link para Arquivo" 57 msgstr "Link para Arquivo"
58 58
59 -#: file_link/models.py:30 59 +#: models.py:30
60 msgid "File Links" 60 msgid "File Links"
61 msgstr "Links para Arquivo" 61 msgstr "Links para Arquivo"
62 62
63 -#: file_link/models.py:49 63 +#: models.py:49
64 msgid "Are you sure you want delete the file link" 64 msgid "Are you sure you want delete the file link"
65 msgstr "Você tem certeza que deseja remover o Link para Arquivo" 65 msgstr "Você tem certeza que deseja remover o Link para Arquivo"
66 66
67 -#: file_link/templates/file_links/_form.html:33 67 +#: templates/file_links/_form.html:33
68 msgid "Choose your file..." 68 msgid "Choose your file..."
69 msgstr "Escolha seu arquivo..." 69 msgstr "Escolha seu arquivo..."
70 70
71 -#: file_link/templates/file_links/_form.html:47 71 +#: templates/file_links/_form.html:47
72 msgid "Click or drop the file here" 72 msgid "Click or drop the file here"
73 msgstr "Clique ou solte o arquivo aqui" 73 msgstr "Clique ou solte o arquivo aqui"
74 74
75 -#: file_link/templates/file_links/_form.html:49 75 +#: templates/file_links/_form.html:49
76 msgid "The file could not exceed 10MB." 76 msgid "The file could not exceed 10MB."
77 msgstr "O arquivo não pode exceder 10MB." 77 msgstr "O arquivo não pode exceder 10MB."
78 78
79 -#: file_link/templates/file_links/_form.html:69 79 +#: templates/file_links/_form.html:69
80 msgid "Common resources settings" 80 msgid "Common resources settings"
81 msgstr "Configurações comuns à todos os recursos" 81 msgstr "Configurações comuns à todos os recursos"
82 82
83 -#: file_link/templates/file_links/_form.html:118 83 +#: templates/file_links/_form.html:118
84 msgid "Pendencies Notifications" 84 msgid "Pendencies Notifications"
85 msgstr "Notificações de Pendências" 85 msgstr "Notificações de Pendências"
86 86
87 -#: file_link/templates/file_links/_form.html:134 87 +#: templates/file_links/_form.html:134
88 msgid "Action not performed by the user" 88 msgid "Action not performed by the user"
89 msgstr "Ação não realizada pelo usuário" 89 msgstr "Ação não realizada pelo usuário"
90 90
91 -#: file_link/templates/file_links/_form.html:160 91 +#: templates/file_links/_form.html:160
92 msgid "Wished period" 92 msgid "Wished period"
93 msgstr "Período desejado" 93 msgstr "Período desejado"
94 94
95 -#: file_link/templates/file_links/_form.html:256 95 +#: templates/file_links/_form.html:256
96 msgid "Attribute students to file link" 96 msgid "Attribute students to file link"
97 msgstr "Atribuir estudantes ao Link para Arquivo" 97 msgstr "Atribuir estudantes ao Link para Arquivo"
98 98
99 -#: file_link/templates/file_links/_form.html:276 99 +#: templates/file_links/_form.html:276
100 msgid "Attribute groups to file link" 100 msgid "Attribute groups to file link"
101 msgstr "Atribuir grupos de estudo ao Link para Arquivo" 101 msgstr "Atribuir grupos de estudo ao Link para Arquivo"
102 102
103 -#: file_link/templates/file_links/_form.html:322 103 +#: templates/file_links/_form.html:322
104 msgid "Save" 104 msgid "Save"
105 msgstr "Salvar" 105 msgstr "Salvar"
106 106
107 -#: file_link/templates/file_links/create.html:20 file_link/views.py:177 107 +#: templates/file_links/create.html:20 views.py:186
108 msgid "Create File Link" 108 msgid "Create File Link"
109 msgstr "Criar Link para Arquivo" 109 msgstr "Criar Link para Arquivo"
110 110
111 -#: file_link/templates/file_links/update.html:20 111 +#: templates/file_links/relatorios.html:17
  112 +#: templates/file_links/relatorios.html:37
  113 +msgid "User"
  114 +msgstr "Usuário"
  115 +
  116 +#: templates/file_links/relatorios.html:17
  117 +#: templates/file_links/relatorios.html:37
  118 +msgid "Group"
  119 +msgstr "Grupo"
  120 +
  121 +#: templates/file_links/relatorios.html:17
  122 +msgid "Action"
  123 +msgstr "Ação"
  124 +
  125 +#: templates/file_links/relatorios.html:17
  126 +msgid "Date of Action"
  127 +msgstr "Data da ação"
  128 +
  129 +#: templates/file_links/relatorios.html:37
  130 +msgid "Send message"
  131 +msgstr "Enviar Mensagem"
  132 +
  133 +#: templates/file_links/relatorios.html:37
  134 +msgid "Action don't realized"
  135 +msgstr "Ação não realizada"
  136 +
  137 +#: templates/file_links/relatorios.html:151
  138 +#: templates/file_links/relatorios.html:171
  139 +msgid "Reports"
  140 +msgstr "Relatórios"
  141 +
  142 +#: templates/file_links/relatorios.html:178
  143 +msgid "Report of the resource "
  144 +msgstr "Relatórios do recurso "
  145 +
  146 +#: templates/file_links/relatorios.html:187
  147 +msgid "Select the period: "
  148 +msgstr "Selecione o período: "
  149 +
  150 +#: templates/file_links/relatorios.html:196
  151 +msgid "Search"
  152 +msgstr "Pesquisar"
  153 +
  154 +#: templates/file_links/relatorios.html:220
  155 +msgid "Filter: "
  156 +msgstr "Filtro: "
  157 +
  158 +#: templates/file_links/relatorios.html:244
  159 +#: templates/file_links/relatorios.html:329
  160 +msgid "record(s)"
  161 +msgstr "Relatório(s)"
  162 +
  163 +#: templates/file_links/send_message.html:38
  164 +#| msgid "Click or drop the file here"
  165 +msgid "Click or drop the picture here"
  166 +msgstr "Clique ou solte a imagem aqui"
  167 +
  168 +#: templates/file_links/send_message.html:40
  169 +#| msgid "The file could not exceed 10MB."
  170 +msgid "The picture could not exceed 5MB."
  171 +msgstr "A imagem não pode exceder 5MB."
  172 +
  173 +#: templates/file_links/send_message.html:62
  174 +msgid "Close"
  175 +msgstr "Fechar"
  176 +
  177 +#: templates/file_links/send_message.html:63
  178 +msgid "Send"
  179 +msgstr "Enviar"
  180 +
  181 +#: templates/file_links/update.html:20
112 msgid "Edit: " 182 msgid "Edit: "
113 msgstr "Editar: " 183 msgstr "Editar: "
114 184
115 -#: file_link/views.py:104 file_link/views.py:117 file_link/views.py:227  
116 -#: file_link/views.py:229 file_link/views.py:245 file_link/views.py:247 185 +#: views.py:113 views.py:126 views.py:236 views.py:238 views.py:254
  186 +#: views.py:256
117 msgid "Visualize" 187 msgid "Visualize"
118 msgstr "Visualizar" 188 msgstr "Visualizar"
119 189
120 -#: file_link/views.py:188 190 +#: views.py:197
121 #, python-format 191 #, python-format
122 msgid "" 192 msgid ""
123 "The File Link \"%s\" was added to the Topic \"%s\" of the virtual " 193 "The File Link \"%s\" was added to the Topic \"%s\" of the virtual "
@@ -126,16 +196,16 @@ msgstr &quot;&quot; @@ -126,16 +196,16 @@ msgstr &quot;&quot;
126 "O Link para Arquivo \"%s\" foi adicionado ao tópico \"%s\" do ambiente " 196 "O Link para Arquivo \"%s\" foi adicionado ao tópico \"%s\" do ambiente "
127 "virtual \"%s\" com sucesso!" 197 "virtual \"%s\" com sucesso!"
128 198
129 -#: file_link/views.py:291 199 +#: views.py:300
130 msgid "Update File Link" 200 msgid "Update File Link"
131 msgstr "Atualizar Link para Arquivo" 201 msgstr "Atualizar Link para Arquivo"
132 202
133 -#: file_link/views.py:302 203 +#: views.py:311
134 #, python-format 204 #, python-format
135 msgid "The File Link \"%s\" was updated successfully!" 205 msgid "The File Link \"%s\" was updated successfully!"
136 msgstr "O Link para Arquivo \"%s\" foi atualizado com sucesso!" 206 msgstr "O Link para Arquivo \"%s\" foi atualizado com sucesso!"
137 207
138 -#: file_link/views.py:329 208 +#: views.py:338
139 #, python-format 209 #, python-format
140 msgid "" 210 msgid ""
141 "The File Link \"%s\" was removed successfully from virtual environment \"%s" 211 "The File Link \"%s\" was removed successfully from virtual environment \"%s"
@@ -144,11 +214,43 @@ msgstr &quot;&quot; @@ -144,11 +214,43 @@ msgstr &quot;&quot;
144 "O Link para Arquivo \"%s\" foi removido do ambiente virtual \"%s\" com " 214 "O Link para Arquivo \"%s\" foi removido do ambiente virtual \"%s\" com "
145 "sucesso!" 215 "sucesso!"
146 216
  217 +#: views.py:397
  218 +#| msgid "File Links"
  219 +msgid "File Link Reports"
  220 +msgstr "Relatŕios de Link para Arquivo"
  221 +
  222 +#: views.py:416
  223 +msgid "Realized"
  224 +msgstr "Realizado"
  225 +
  226 +#: views.py:416
  227 +msgid "Unrealized"
  228 +msgstr "Não Realizado"
  229 +
  230 +#: views.py:416
  231 +msgid "Historic"
  232 +msgstr "Histórico"
  233 +
  234 +#: views.py:434 views.py:443
  235 +msgid "View"
  236 +msgstr "Visualizar"
  237 +
  238 +#: views.py:442
  239 +#, fuzzy
  240 +#| msgid "File Link"
  241 +msgid "File link"
  242 +msgstr "Link para Arquivo"
  243 +
  244 +#: views.py:447
  245 +msgid "Actions about resource"
  246 +msgstr "Ações sobre o recurso"
  247 +
  248 +#: views.py:448
  249 +msgid "Quantity"
  250 +msgstr "Quantidade"
  251 +
147 #~ msgid "File not supported." 252 #~ msgid "File not supported."
148 #~ msgstr "Arquivo não suportado." 253 #~ msgstr "Arquivo não suportado."
149 254
150 -#~ msgid "Close"  
151 -#~ msgstr "Fechar"  
152 -  
153 #~ msgid "Delete" 255 #~ msgid "Delete"
154 #~ msgstr "Remover" 256 #~ msgstr "Remover"
file_link/templates/file_links/relatorios.html 0 → 100644
@@ -0,0 +1,408 @@ @@ -0,0 +1,408 @@
  1 +{% extends "subjects/view.html" %}
  2 +
  3 +{% load static i18n pagination permissions_tags subject_counter %}
  4 +{% load django_bootstrap_breadcrumbs %}
  5 +
  6 +{% block javascript%}
  7 + {{ block.super }}
  8 + <script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
  9 + <script type="text/javascript">
  10 + var tabela_atual = true;
  11 +
  12 + var array_history = [];
  13 + {%for data_json in json_history.data %}
  14 + array_history.push(["{{data_json.0}}","{{data_json.1}}","{{view}}",{% if data_json.3 is not None %}new Date('{{data_json.3.isoformat}}'){% else%}null{% endif %}]);
  15 + {% endfor%}
  16 + var json_history = {"data":array_history};
  17 + var column_history = [{"string":'{% trans "User" %}'},{"string":'{% trans "Group" %}'},{"string":'{% trans "Action" %}'},{"date":'{% trans "Date of Action" %}'}];
  18 +
  19 + var search = [];
  20 + for (var i in json_history["data"]){
  21 + search.push([json_history["data"][i][0],json_history["data"][i][1],
  22 + json_history["data"][i][2],json_history["data"][i][3]]);
  23 + }
  24 +
  25 + var array_n_did = [];
  26 + var checkbox = {};
  27 + {%for data_json in json_n_did.data%}
  28 + var input = '<div class="checkbox">\
  29 + <label for="{{data_json.0}}_google_table">\
  30 + <input id="{{data_json.0}}_google_table" name="{{data_json.0}}_google_table" type="checkbox"><span class="checkbox-material"><span class="check"></span></span>\
  31 + </label>\
  32 + </div>'
  33 + checkbox["{{data_json.0}}_google_table"] = "{{data_json.4}}";
  34 + array_n_did.push([input,"{{data_json.1}}","{{data_json.2}}","{{data_json.3}}"]);
  35 + {% endfor%}
  36 + var json_n_did = {"data":array_n_did};
  37 + var column_n_did = [{"string":'<a href="javascript:void(0);" onclick="return openmodal();"> {% trans "Send message" %}</a>'},{"string":'{% trans "User" %}'},{"string":'{% trans "Group" %}'},{"string":"{% trans "Action don't realized" %}"}];
  38 + </script>
  39 +
  40 +
  41 + <script type="text/javascript">
  42 + google.charts.load('current', {'packages':['corechart',"table"]});
  43 + google.charts.setOnLoadCallback(drawChart);
  44 + google.charts.setOnLoadCallback(drawTable);
  45 +
  46 + function drawChart() {
  47 + var data = google.visualization.arrayToDataTable({{db_data|safe}});
  48 + var options = {
  49 + title: '{{title_chart}}',
  50 + // legend: {position: 'right', maxLines: 1},
  51 + bar: { groupWidth: '30%' },
  52 + chartArea:{width:"50%"},
  53 + titlePosition: 'out',
  54 + vAxis: {
  55 + title: '{{title_vAxis}}',
  56 + ticks: [0, .20, .40, .60, .80, 1],
  57 + viewWindow: {
  58 + min: 0,
  59 + max: 1
  60 + }
  61 + },
  62 + isStacked: "percent",
  63 + };
  64 +
  65 + function selectHandler() {
  66 + var selectedItem = chart.getSelection()[0];
  67 + if (selectedItem) {
  68 + var col = data.getColumnLabel(selectedItem.column);
  69 + if (col == "{{n_did_table}}"){
  70 + tabela_atual = false;
  71 + search = [];
  72 + for (var i in json_n_did["data"]){
  73 + search.push([json_n_did["data"][i][0],json_n_did["data"][i][1],
  74 + json_n_did["data"][i][2],json_n_did["data"][i][3]]);
  75 + }
  76 + searcher(col, tabela_atual,true);
  77 +
  78 + } else if (col == "{{did_table}}"){
  79 + tabela_atual = true;
  80 + search = [];
  81 + for (var i in json_history["data"]){
  82 + search.push([json_history["data"][i][0],json_history["data"][i][1],
  83 + json_history["data"][i][2],json_history["data"][i][3]]);
  84 + }
  85 + searcher(col, tabela_atual,true);
  86 + }
  87 + }
  88 + chart.setSelection([])
  89 + }
  90 +
  91 + var chart = new google.visualization.ColumnChart(document.getElementById('chart_div'));
  92 + google.visualization.events.addListener(chart, 'select', selectHandler);
  93 + chart.draw(data, options);
  94 +
  95 + }
  96 +
  97 + var sortAscending = {0:false,1:false,2:false,3:false};
  98 + function drawTable(columns = column_history,rows = pagination(json_history["data"],1),isdate = true,columndate = 3) {
  99 + var data_table = new google.visualization.DataTable();
  100 + for (var i in columns){
  101 + for (var item in columns[i]){
  102 + data_table.addColumn(item,columns[i][item]);
  103 + }
  104 + }
  105 +
  106 + data_table.addRows(rows);
  107 + var formate_date = new google.visualization.DateFormat({pattern: 'dd/MM/yyyy HH:mm'});
  108 + if (isdate) formate_date.format(data_table, columndate);
  109 +
  110 + // var methods = [];
  111 + // for (var m in data_table) {
  112 + // if (typeof data_table[m] == "function") {
  113 + // methods.push(m);
  114 + // }
  115 + // }
  116 + // console.log(methods.join(","));
  117 + var options = {
  118 + sort: "event",
  119 + allowHtml: true,
  120 + cssClassNames : {
  121 + tableRow: 'text-center',
  122 + tableCell: 'text-center',
  123 + headerCell: 'text-center'
  124 + },
  125 + showRowNumber: true,
  126 + width: '100%',
  127 + height: '100%',
  128 + }
  129 + function ordenar(properties){
  130 + var columnIndex = properties['column'];
  131 + if (columnIndex > 0) {
  132 + options["sortColumn"] = columnIndex;
  133 + options["sortAscending"] = sortAscending[columnIndex];
  134 + data_table.sort({column:columnIndex,desc:sortAscending[columnIndex]});
  135 + sortAscending = {0:false,1:false,2:false,3:false};
  136 + sortAscending[columnIndex] = !sortAscending[columnIndex];
  137 + // console.log(sortAscending);
  138 + table.draw(data_table, options);
  139 + }
  140 + }
  141 +
  142 + var table = new google.visualization.Table(document.getElementById('table_div'));
  143 + google.visualization.events.addListener(table, 'sort', function(e) {ordenar(e)});
  144 + table.draw(data_table, options);
  145 + }
  146 + </script>
  147 +{% endblock%}
  148 +
  149 +{% block breadcrumbs %}
  150 + {{ block.super }}
  151 + {% trans 'Reports' as bread %}
  152 + {% breadcrumb bread filelink%}
  153 +{% endblock %}
  154 +
  155 +{% block content %}
  156 + {% if messages %}
  157 + {% for message in messages %}
  158 + <div class="alert alert-{{ message.tags }} alert-dismissible" role="alert">
  159 + <button type="button" class="close" data-dismiss="alert" aria-label="Close">
  160 + <span aria-hidden="true">&times;</span>
  161 + </button>
  162 + <p>{{ message }}</p>
  163 + </div>
  164 + {% endfor %}
  165 + {% endif %}
  166 + <div class="panel panel-info topic-panel">
  167 + <div class="panel-heading">
  168 + <div class="row">
  169 + <div class="col-md-12 category-header">
  170 + <h4 class="panel-title" style="margin-top: 10px; margin-bottom: 8px">
  171 + <span>{{filelink}} / {% trans "Reports" %}</span>
  172 + </h4>
  173 + </div>
  174 + </div>
  175 + </div>
  176 + <div class="row">
  177 + <div class="col-md-12 text-center">
  178 + <h4 style="margin-top: 15px; margin-bottom: 10px" ><strong>{% trans "Report of the resource " %}{{filelink}}</strong></h4>
  179 + </div>
  180 + </div>
  181 + <div class="row">
  182 + <div class="col-md-12">
  183 +
  184 + <ul class="list-inline nav-justified">
  185 + <div id="general-parameters-div">
  186 + <div class="general-parameters-field">
  187 + <li class="text-right"><h4>{% trans "Select the period: " %}</h4></li>
  188 + </div>
  189 + <form id="period-form" action="" method="get">
  190 + <div class="general-parameters-field">
  191 + <li> <input class="form-control datetime-picker" name="init_date" type="text" required="" value="{% if LANGUAGE_CODE == 'pt-br' %}{{init_date|date:'d/m/Y H:i'}} {% else %} {{init_date|date:'m/d/Y H:i P'}} {% endif %}"></li>
  192 + </div>
  193 + <div class="general-parameters-field">
  194 + <li><input id="inputdate" class="form-control datetime-picker" name="end_date" type="text" required="" value="{% if LANGUAGE_CODE == 'pt-br' %}{{end_date|date:'d/m/Y H:i'}} {% else %} {{end_date|date:'m/d/Y H:i P'}} {% endif %}"></li>
  195 + </div>
  196 + <li><input type="submit" value="{% trans 'Search' %}" style="margin-left: 15px;" class="btn btn-success btn-raised"></li>
  197 + </form>
  198 + </div>
  199 + <ul>
  200 + </div>
  201 + </div>
  202 +
  203 + <div class="row">
  204 + <div class="col-md-10 col-md-offset-1">
  205 + <div id="chart_div" style="height: 500px; margin-top: -50px;"></div>
  206 + </div>
  207 + </div>
  208 +
  209 + <div class="row">
  210 + <div class="col-md-10 col-md-offset-1">
  211 + <div class="text-center">
  212 + <ul class="list-inline nav-justified">
  213 + <li>
  214 + <ul id="view-table" class="list-inline text-right">
  215 + <li><h3 id="title-table"></h3></li>
  216 + </ul>
  217 + </li>
  218 + <li>
  219 + <ul class="list-inline text-right">
  220 + <li><p>{% trans "Filter: " %}</p></li>
  221 + <li><input id="search-input" class="form-control" type="text" name="search" value=""></li>
  222 + </ul>
  223 + </li>
  224 + </ul>
  225 + </div>
  226 + <form id="google-chart-checkbox" action="" method="get">
  227 + <div id="table_div"></div>
  228 + </form>
  229 + <div class="col-md-12 col-lg-12 col-sm-12 col-xs-12 text-center">
  230 + <ul class="pagination">
  231 +
  232 + </ul>
  233 + </div>
  234 + </div>
  235 + </div>
  236 + <div id="modal-message"></div>
  237 + <div class="row">
  238 + <br><br>
  239 + </div>
  240 + </div>
  241 +
  242 + <script type="text/javascript">
  243 +
  244 + $("#title-table").text(search.length + " {% trans 'record(s)' %}");
  245 + function putpagination(data = json_history["data"], load_histoty = true){
  246 + var len = Math.ceil(data.length / 20);
  247 + $(".pagination").empty();
  248 + $(".pagination").append('<li class="disabled"><span>«</span></li>');
  249 + $(".pagination").append('<li id="1" class="active">\
  250 + <a href="javascript:void(0);" onclick="return clickPagination(1, '+ load_histoty +');">1</a>\
  251 + </li>');
  252 + for (var i = 2; i <= len;i++){
  253 + $(".pagination").append('<li id="' + i + '">\
  254 + <a href="javascript:void(0);" onclick="return clickPagination(' + i +', ' + load_histoty + ');">' + i + '</a>\
  255 + </li>');
  256 + }
  257 + if (len > 1) $(".pagination").append('<li><a href="javascript:void(0);" onclick="return clickPagination(2, '+ load_histoty +');"><span>»</span></a></li>');
  258 + else $(".pagination").append('<li class="disabled"><span>»</span></li>');
  259 + };
  260 + putpagination();
  261 +
  262 + $('#period-form').submit(function(event) {
  263 + $('<input />').attr('type', 'hidden')
  264 + .attr('name', "language")
  265 + .attr('value', '{{ LANGUAGE_CODE }}')
  266 + .appendTo('#period-form');
  267 + });
  268 + function add(element,local, first = false){
  269 + if (first) $(local).prepend(element);
  270 + else $(local).append(element);
  271 + }
  272 + function text(element){
  273 + return $(element).text();
  274 + }
  275 + function length(element) {
  276 + return $(element).length;
  277 + }
  278 +
  279 + $("#search-input").on("keyup",function(){
  280 + search = [];
  281 + var text = $("#search-input").val();
  282 + searcher(text,tabela_atual);
  283 + });
  284 +
  285 + function searcher(text, load_histoty = false,apaga=false){
  286 + if(apaga){
  287 + $("#search-input").val("");
  288 + }
  289 + var data = [];
  290 + if (!load_histoty){
  291 + data = $.map(json_n_did["data"], function (obj) {
  292 + return $.extend(true, {}, obj);
  293 + });
  294 + } else {
  295 + data = $.map(json_history["data"], function (obj) {
  296 + return $.extend(true, {}, obj);
  297 + });
  298 + }
  299 + if (load_histoty){
  300 + for (var i in data){
  301 + data[i][3] = moment(data[i][3]).format("DD/MM/YYYY HH:mm");
  302 + }
  303 + }
  304 + if (load_histoty){
  305 + for (var i in data){
  306 + if (data[i][0].toLowerCase().includes(text.toLowerCase())
  307 + || data[i][1].toLowerCase().includes(text.toLowerCase())
  308 + || data[i][2].toLowerCase().includes(text.toLowerCase())
  309 + || data[i][3].toLowerCase().includes(text.toLowerCase())){
  310 + search.push(json_history["data"][i]);
  311 + }
  312 + }
  313 + }
  314 + else {
  315 + for (var i in data){
  316 + if (data[i][1].toLowerCase().includes(text.toLowerCase())
  317 + || data[i][2].toLowerCase().includes(text.toLowerCase())
  318 + || data[i][3].toLowerCase().includes(text.toLowerCase())){
  319 + search.push(json_n_did["data"][i]);
  320 + }
  321 + }
  322 + }
  323 + console.log(search);
  324 + if (!load_histoty){
  325 + drawTable(column_n_did,pagination(search,1),false);
  326 + } else {
  327 + drawTable(column_history,pagination(search,1),true,3);
  328 + }
  329 + $("#title-table").text(search.length + " {% trans 'record(s)' %}");
  330 + putpagination(search,load_histoty);
  331 + }
  332 +
  333 + function pagination(data,pag){
  334 + var len = data.length;
  335 + var first = (pag * 20 - 20 < len) ? pag * 20 - 20:len;
  336 + var end = (pag * 20 < len) ? pag * 20:len;
  337 + var search = data.slice(first,end);
  338 + return search;
  339 + }
  340 +
  341 + function clickPagination(pag, load_histoty = false){
  342 + $(".pagination > li").last().remove();
  343 + $(".pagination > li").first().remove();
  344 +
  345 + if (!load_histoty){
  346 + drawTable(column_n_did,pagination(search,pag),false);
  347 + } else {
  348 + drawTable(column_history,pagination(search,pag),true,3);
  349 + }
  350 +
  351 + if (pag < Math.ceil(search.length / 20))
  352 + $(".pagination").append('<li><a href="javascript:void(0);" onclick="return clickPagination(' + (pag + 1) + ', '+ load_histoty +');"><span>»</span></a></li>');
  353 + else $(".pagination").append('<li class="disabled"><span>»</span></li>');
  354 + if (pag > 1)
  355 + $(".pagination").prepend('<li><a href="javascript:void(0);" onclick="return clickPagination(' + (pag - 1) + ', '+ load_histoty +');"><span>«</span></a></li>');
  356 + else $(".pagination").prepend('<li class="disabled"><span>«</span></li>');
  357 + $(".active").removeClass("active");
  358 + $("#" + pag).addClass("active");
  359 + }
  360 +
  361 + function openmodal(){
  362 + $( "#modal-message" ).empty();
  363 + $.get( "{% url 'file_links:send_message' filelink.slug %}", function( data ) {
  364 + $( "#modal-message" ).append( data );
  365 + $("#send-message-modal").modal("show");
  366 + });
  367 + }
  368 +
  369 + function sendMessage(){
  370 + $("#send-message-modal").modal("hide");
  371 + var checked = $("#google-chart-checkbox").serializeArray();
  372 + var email = [];
  373 + for (var i in checked){
  374 + email.push(checkbox[checked[i]["name"]]);
  375 + }
  376 + $('<input />').attr('type', 'hidden')
  377 + .attr('name', "users[]")
  378 + .attr('value', email)
  379 + .appendTo('#text_chat_form');
  380 +
  381 + var formData = new FormData($('#text_chat_form').get(0));
  382 + $.ajax({
  383 + url: "{% url 'file_links:send_message' filelink.slug %}",
  384 + type: "POST",
  385 + data: formData,
  386 + cache: false,
  387 + processData: false,
  388 + contentType: false,
  389 + success: function(data) {
  390 + if (data["message"]){
  391 + console.log("success");
  392 + $("body").removeClass("modal-open");
  393 + $( "#modal-message" ).empty();
  394 + $(".modal-backdrop.fade.in").remove();
  395 + } else {
  396 + $( "#modal-message" ).empty();
  397 + $(".modal-backdrop.fade.in").remove();
  398 + $( "#modal-message" ).append( data );
  399 + $("#send-message-modal").modal("show");
  400 + }
  401 + },
  402 + error: function(data){
  403 + console.log("erro");
  404 + }
  405 + });
  406 + }
  407 + </script>
  408 +{% endblock %}
file_link/templates/file_links/send_message.html 0 → 100644
@@ -0,0 +1,112 @@ @@ -0,0 +1,112 @@
  1 +
  2 + {% load widget_tweaks i18n %}
  3 + <!-- Modal (remember to change the ids!!!) -->
  4 +<div class="modal fade" id="send-message-modal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
  5 + <div class="modal-dialog" role="document">
  6 + <div class="modal-content">
  7 + <!-- Modal Body -->
  8 + <div class="modal-body">
  9 + <form id="text_chat_form" action="" method="POST" enctype="multipart/form-data">
  10 + {% csrf_token %}
  11 + {% comment %}Area para o Texto{% endcomment %}
  12 + <div class="form-group{% if form.has_error %} has-error {% endif %}">
  13 + <label for="{{ form.comment.auto_id }}">{{ form.comment.label }}: <span>*</span></label>
  14 + {% render_field form.comment class='form-control text_simple_wysiwyg' %}
  15 +
  16 + <span id="helpBlock" class="help-block">{{ form.comment.help_text }}</span>
  17 +
  18 + {% if form.comment.errors %}
  19 + <div class="alert alert-danger alert-dismissible" role="alert">
  20 + <button type="button" class="close" data-dismiss="alert" aria-label="Close">
  21 + <span aria-hidden="true">&times;</span>
  22 + </button>
  23 + <ul>
  24 + {% for error in form.comment.errors %}
  25 + <li>{{ error }}</li>
  26 + {% endfor %}
  27 + </ul>
  28 + </div>
  29 + {% endif %}
  30 + </div>
  31 + {% comment %}Area para anexar a imagem {% endcomment %}
  32 + <div class="form-group{% if form.has_error %} has-error {% endif %} is-fileinput">
  33 + {% render_field form.image %}
  34 +
  35 + <div class="filedrag">
  36 + {% trans 'Click or drop the picture here' %}<br />
  37 +
  38 + <small>{% trans 'The picture could not exceed 5MB.' %}</small>
  39 + </div>
  40 +
  41 + {% if form.image.errors %}
  42 + <div class="alert alert-danger alert-dismissible" role="alert">
  43 + <button type="button" class="close" data-dismiss="alert" aria-label="Close">
  44 + <span aria-hidden="true">&times;</span>
  45 + </button>
  46 + <ul>
  47 + {% for error in form.image.errors %}
  48 + <li>{{ error }}</li>
  49 + {% endfor %}
  50 + </ul>
  51 + </div>
  52 + {% endif %}
  53 +
  54 + </div>
  55 + </form>
  56 + </div>
  57 + <!-- Modal Footer -->
  58 + <div id="delete-category-footer"class="modal-footer">
  59 + <!-- Don't remove that!!! -->
  60 + <button type="button" class="btn btn-default btn-raised" data-dismiss="modal">{% trans "Close" %}</button>
  61 + <a href="javascript:void(0)" onclick="return sendMessage()" form="text_chat_form" class="btn btn-success btn-raised erase-button">{% trans "Send" %}</a>
  62 + </div>
  63 + </div>
  64 + </div>
  65 +</div>
  66 +
  67 +<script type="text/javascript">
  68 +
  69 + $('.text_simple_wysiwyg').summernote({
  70 + dialogsInBody: true,
  71 + disableDragAndDrop: true,
  72 + height: 150,
  73 + toolbar: [
  74 + // [groupName, [list of button]]
  75 + ['style', ['bold', 'italic']],
  76 + ['insert', ['link']]
  77 + ]
  78 + });
  79 +
  80 + if (window.File && window.FileList && window.FileReader) {
  81 + Init();
  82 + }
  83 +
  84 + function Init() {
  85 + var small = $("#id_image"),
  86 + filedrag = $(".filedrag"),
  87 + common = $(".common-file-input");
  88 +
  89 + // file select
  90 + small.on("change", FileSelectHandler);
  91 +
  92 + // is XHR2 available?
  93 + var xhr = new XMLHttpRequest();
  94 + if (xhr.upload) {
  95 + // file drop
  96 + filedrag.on("drop", FileSelectHandler);
  97 + filedrag.attr('style', 'display:block');
  98 + common.attr('style', 'display:none');
  99 + }
  100 + }
  101 +
  102 + // file selection
  103 + function FileSelectHandler(e) {
  104 + var files = e.target.files || e.dataTransfer.files,
  105 + parent = $(e.target.offsetParent);
  106 +
  107 + // process all File objects
  108 + for (var i = 0, f; f = files[i]; i++) {
  109 + parent.find('.filedrag').html(f.name);
  110 + }
  111 + }
  112 +</script>
0 \ No newline at end of file 113 \ No newline at end of file
file_link/urls.py
@@ -8,4 +8,6 @@ urlpatterns = [ @@ -8,4 +8,6 @@ urlpatterns = [
8 url(r'^update/(?P<topic_slug>[\w_-]+)/(?P<slug>[\w_-]+)/$', views.UpdateView.as_view(), name = 'update'), 8 url(r'^update/(?P<topic_slug>[\w_-]+)/(?P<slug>[\w_-]+)/$', views.UpdateView.as_view(), name = 'update'),
9 url(r'^delete/(?P<slug>[\w_-]+)/$', views.DeleteView.as_view(), name = 'delete'), 9 url(r'^delete/(?P<slug>[\w_-]+)/$', views.DeleteView.as_view(), name = 'delete'),
10 url(r'^download/(?P<slug>[\w_-]+)/$', views.DownloadFile.as_view(), name = 'download'), 10 url(r'^download/(?P<slug>[\w_-]+)/$', views.DownloadFile.as_view(), name = 'download'),
  11 + url(r'^chart/(?P<slug>[\w_-]+)/$', views.StatisticsView.as_view(), name = 'get_chart'),
  12 + url(r'^send-message/(?P<slug>[\w_-]+)/$', views.SendMessage.as_view(), name = 'send_message'),
11 ] 13 ]
file_link/views.py
@@ -18,6 +18,15 @@ from pendencies.forms import PendenciesForm @@ -18,6 +18,15 @@ from pendencies.forms import PendenciesForm
18 from .forms import FileLinkForm 18 from .forms import FileLinkForm
19 from .models import FileLink 19 from .models import FileLink
20 20
  21 +
  22 +import datetime
  23 +from log.models import Log
  24 +from chat.models import Conversation, TalkMessages
  25 +from users.models import User
  26 +from subjects.models import Subject
  27 +
  28 +from webpage.forms import FormModalMessage
  29 +
21 class DownloadFile(LoginRequiredMixin, LogMixin, generic.DetailView): 30 class DownloadFile(LoginRequiredMixin, LogMixin, generic.DetailView):
22 log_component = 'resources' 31 log_component = 'resources'
23 log_action = 'view' 32 log_action = 'view'
@@ -343,4 +352,145 @@ class DeleteView(LoginRequiredMixin, LogMixin, generic.DeleteView): @@ -343,4 +352,145 @@ class DeleteView(LoginRequiredMixin, LogMixin, generic.DeleteView):
343 352
344 super(DeleteView, self).createLog(self.request.user, self.log_component, self.log_action, self.log_resource, self.log_context) 353 super(DeleteView, self).createLog(self.request.user, self.log_component, self.log_action, self.log_resource, self.log_context)
345 354
346 - return reverse_lazy('subjects:view', kwargs = {'slug': self.object.topic.subject.slug})  
347 \ No newline at end of file 355 \ No newline at end of file
  356 + return reverse_lazy('subjects:view', kwargs = {'slug': self.object.topic.subject.slug})
  357 +
  358 +
  359 +class StatisticsView(LoginRequiredMixin, LogMixin, generic.DetailView):
  360 + log_component = 'resources'
  361 + log_action = 'view_statistics'
  362 + log_resource = 'filelink'
  363 + log_context = {}
  364 +
  365 + login_url = reverse_lazy("users:login")
  366 + redirect_field_name = 'next'
  367 + model = FileLink
  368 + template_name = 'file_links/relatorios.html'
  369 +
  370 + def dispatch(self, request, *args, **kwargs):
  371 + slug = self.kwargs.get('slug', '')
  372 + filelink = get_object_or_404(FileLink, slug = slug)
  373 +
  374 + if not has_subject_permissions(request.user, filelink.topic.subject):
  375 + return redirect(reverse_lazy('subjects:home'))
  376 +
  377 + return super(StatisticsView, self).dispatch(request, *args, **kwargs)
  378 +
  379 + def get_context_data(self, **kwargs):
  380 + context = super(StatisticsView, self).get_context_data(**kwargs)
  381 +
  382 + self.log_context['category_id'] = self.object.topic.subject.category.id
  383 + self.log_context['category_name'] = self.object.topic.subject.category.name
  384 + self.log_context['category_slug'] = self.object.topic.subject.category.slug
  385 + self.log_context['subject_id'] = self.object.topic.subject.id
  386 + self.log_context['subject_name'] = self.object.topic.subject.name
  387 + self.log_context['subject_slug'] = self.object.topic.subject.slug
  388 + self.log_context['topic_id'] = self.object.topic.id
  389 + self.log_context['topic_name'] = self.object.topic.name
  390 + self.log_context['topic_slug'] = self.object.topic.slug
  391 + self.log_context['filelink_id'] = self.object.id
  392 + self.log_context['filelink_name'] = self.object.name
  393 + self.log_context['filelink_slug'] = self.object.slug
  394 +
  395 + super(StatisticsView, self).createLog(self.request.user, self.log_component, self.log_action, self.log_resource, self.log_context)
  396 +
  397 +
  398 + context['title'] = _('File Link Reports')
  399 +
  400 + slug = self.kwargs.get('slug')
  401 + filelink = get_object_or_404(FileLink, slug = slug)
  402 + print (self.request.GET.get('init_date',''))
  403 + date_format = "%d/%m/%Y %H:%M" if self.request.GET.get('language','') == 'pt-br' else "%m/%d/%Y %I:%M %p"
  404 + if self.request.GET.get('language','') == "":
  405 + start_date = datetime.datetime.now() - datetime.timedelta(30)
  406 + end_date = datetime.datetime.now()
  407 + else :
  408 + start_date = datetime.datetime.strptime(self.request.GET.get('init_date',''),date_format)
  409 + end_date = datetime.datetime.strptime(self.request.GET.get('end_date',''),date_format)
  410 + context["init_date"] = start_date
  411 + context["end_date"] = end_date
  412 + alunos = filelink.students.all()
  413 + if filelink.all_students :
  414 + alunos = filelink.topic.subject.students.all()
  415 +
  416 + vis_ou = Log.objects.filter(context__contains={'filelink_id':filelink.id},resource="filelink",action="view",user_email__in=(aluno.email for aluno in alunos), datetime__range=(start_date,end_date + datetime.timedelta(minutes = 1)))
  417 + did,n_did,history = str(_("Realized")),str(_("Unrealized")),str(_("Historic"))
  418 + re = []
  419 + data_n_did,data_history = [],[]
  420 + json_n_did, json_history = {},{}
  421 +
  422 + from django.db.models import Count, Max
  423 + views_user = vis_ou.values("user_email").annotate(views=Count("user_email"))
  424 + date_last = vis_ou.values("user_email").annotate(last=Max("datetime"))
  425 +
  426 + for log_al in vis_ou.order_by("datetime"):
  427 + data_history.append([str(alunos.get(email=log_al.user_email)),
  428 + ", ".join([str(x) for x in filelink.topic.subject.group_subject.filter(participants__email=log_al.user_email)]),
  429 + log_al.action,log_al.datetime])
  430 + json_history["data"] = data_history
  431 +
  432 + not_view = alunos.exclude(email__in=[log.user_email for log in vis_ou.distinct("user_email")])
  433 + index = 0
  434 + for alun in not_view:
  435 + data_n_did.append([index,str(alun),", ".join([str(x) for x in filelink.topic.subject.group_subject.filter(participants__email=alun.email)]),str(_('View')), str(alun.email)])
  436 + index += 1
  437 + json_n_did["data"] = data_n_did
  438 +
  439 +
  440 + context["json_n_did"] = json_n_did
  441 + context["json_history"] = json_history
  442 + c_visualizou = vis_ou.distinct("user_email").count()
  443 + column_view = str(_('View'))
  444 + re.append([str(_('File link')),did,n_did])
  445 + re.append([column_view,c_visualizou, alunos.count() - c_visualizou])
  446 + context['topic'] = filelink.topic
  447 + context['subject'] = filelink.topic.subject
  448 + context['db_data'] = re
  449 + context['title_chart'] = _('Actions about resource')
  450 + context['title_vAxis'] = _('Quantity')
  451 + context['view'] = column_view
  452 + context["n_did_table"] = n_did
  453 + context["did_table"] = did
  454 + context["history_table"] = history
  455 + return context
  456 +
  457 +
  458 +
  459 +class SendMessage(LoginRequiredMixin, LogMixin, generic.edit.FormView):
  460 + log_component = 'resources'
  461 + log_action = 'send'
  462 + log_resource = 'filelink'
  463 + log_context = {}
  464 +
  465 + login_url = reverse_lazy("users:login")
  466 + redirect_field_name = 'next'
  467 +
  468 + template_name = 'file_links/send_message.html'
  469 + form_class = FormModalMessage
  470 +
  471 + def dispatch(self, request, *args, **kwargs):
  472 + slug = self.kwargs.get('slug', '')
  473 + filelink = get_object_or_404(FileLink, slug = slug)
  474 + self.filelink = filelink
  475 +
  476 + if not has_subject_permissions(request.user, filelink.topic.subject):
  477 + return redirect(reverse_lazy('subjects:home'))
  478 +
  479 + return super(SendMessage, self).dispatch(request, *args, **kwargs)
  480 +
  481 + def form_valid(self, form):
  482 + message = form.cleaned_data.get('comment')
  483 + image = form.cleaned_data.get("image")
  484 + users = (self.request.POST.get('users[]','')).split(",")
  485 + user = self.request.user
  486 + subject = self.filelink.topic.subject
  487 + for u in users:
  488 + to_user = User.objects.get(email=u)
  489 + talk, create = Conversation.objects.get_or_create(user_one=user,user_two=to_user)
  490 + created = TalkMessages.objects.create(text=message,talk=talk,user=user,subject=subject,image=image)
  491 + return JsonResponse({"message":"ok"})
  492 +
  493 + def get_context_data(self, **kwargs):
  494 + context = super(SendMessage,self).get_context_data()
  495 + context["filelink"] = get_object_or_404(FileLink, slug=self.kwargs.get('slug', ''))
  496 + return context
  497 +
links/locale/pt-br/LC_MESSAGES/django.po
@@ -8,7 +8,7 @@ msgid &quot;&quot; @@ -8,7 +8,7 @@ msgid &quot;&quot;
8 msgstr "" 8 msgstr ""
9 "Project-Id-Version: PACKAGE VERSION\n" 9 "Project-Id-Version: PACKAGE VERSION\n"
10 "Report-Msgid-Bugs-To: \n" 10 "Report-Msgid-Bugs-To: \n"
11 -"POT-Creation-Date: 2017-02-09 18:40-0300\n" 11 +"POT-Creation-Date: 2017-05-05 19:49-0300\n"
12 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" 12 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
13 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" 13 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
14 "Language-Team: LANGUAGE <LL@li.org>\n" 14 "Language-Team: LANGUAGE <LL@li.org>\n"
@@ -17,106 +17,197 @@ msgstr &quot;&quot; @@ -17,106 +17,197 @@ msgstr &quot;&quot;
17 "Content-Type: text/plain; charset=UTF-8\n" 17 "Content-Type: text/plain; charset=UTF-8\n"
18 "Content-Transfer-Encoding: 8bit\n" 18 "Content-Transfer-Encoding: 8bit\n"
19 19
20 -#: links/forms.py:27 20 +#: forms.py:27
21 msgid "Tags" 21 msgid "Tags"
22 msgstr "" 22 msgstr ""
23 23
24 -#: links/forms.py:28 24 +#: forms.py:28
25 msgid "Website URL" 25 msgid "Website URL"
26 msgstr "" 26 msgstr ""
27 27
28 -#: links/forms.py:34 28 +#: forms.py:34
29 msgid "Link name" 29 msgid "Link name"
30 msgstr "" 30 msgstr ""
31 31
32 -#: links/forms.py:35 32 +#: forms.py:35
33 msgid "End View" 33 msgid "End View"
34 msgstr "" 34 msgstr ""
35 35
36 -#: links/forms.py:36 36 +#: forms.py:36
37 msgid "End View Date" 37 msgid "End View Date"
38 msgstr "" 38 msgstr ""
39 39
40 -#: links/forms.py:64 40 +#: forms.py:64
41 msgid "There is already a link with this name on this subject" 41 msgid "There is already a link with this name on this subject"
42 msgstr "" 42 msgstr ""
43 43
44 -#: links/models.py:11 44 +#: models.py:13
45 msgid "Link_URL" 45 msgid "Link_URL"
46 msgstr "" 46 msgstr ""
47 47
48 -#: links/models.py:31 links/templates/links/delete.html:9 48 +#: models.py:33 templates/links/delete.html:12
49 msgid "Are you sure you want delete the Website link" 49 msgid "Are you sure you want delete the Website link"
50 msgstr "" 50 msgstr ""
51 51
52 -#: links/templates/links/_form.html:112 52 +#: templates/links/_form.html:112
53 msgid "Pendencies Notifications" 53 msgid "Pendencies Notifications"
54 msgstr "" 54 msgstr ""
55 55
56 -#: links/templates/links/_form.html:130 56 +#: templates/links/_form.html:130
57 msgid "Action not performed by the user" 57 msgid "Action not performed by the user"
58 msgstr "" 58 msgstr ""
59 59
60 -#: links/templates/links/_form.html:156 60 +#: templates/links/_form.html:156
61 msgid "Wished period" 61 msgid "Wished period"
62 msgstr "" 62 msgstr ""
63 63
64 -#: links/templates/links/_form.html:252 64 +#: templates/links/_form.html:252
65 msgid "Attribute students to file link" 65 msgid "Attribute students to file link"
66 msgstr "" 66 msgstr ""
67 67
68 -#: links/templates/links/_form.html:272 68 +#: templates/links/_form.html:272
69 msgid "Attribute groups to file link" 69 msgid "Attribute groups to file link"
70 msgstr "" 70 msgstr ""
71 71
72 -#: links/templates/links/_form.html:320 72 +#: templates/links/_form.html:320
73 msgid "Save" 73 msgid "Save"
74 msgstr "" 74 msgstr ""
75 75
76 -#: links/templates/links/create.html:20 76 +#: templates/links/create.html:20
77 msgid "Create Website Link" 77 msgid "Create Website Link"
78 msgstr "" 78 msgstr ""
79 79
80 -#: links/templates/links/delete.html:14 80 +#: templates/links/delete.html:18 templates/links/send_message.html:62
81 msgid "Close" 81 msgid "Close"
82 msgstr "" 82 msgstr ""
83 83
84 -#: links/templates/links/delete.html:17 84 +#: templates/links/delete.html:19
85 msgid "Delete" 85 msgid "Delete"
86 msgstr "" 86 msgstr ""
87 87
88 -#: links/templates/links/update.html:20 88 +#: templates/links/relatorios.html:17 templates/links/relatorios.html:37
  89 +msgid "User"
  90 +msgstr ""
  91 +
  92 +#: templates/links/relatorios.html:17 templates/links/relatorios.html:37
  93 +msgid "Group"
  94 +msgstr ""
  95 +
  96 +#: templates/links/relatorios.html:17
  97 +msgid "Action"
  98 +msgstr ""
  99 +
  100 +#: templates/links/relatorios.html:17
  101 +msgid "Date of Action"
  102 +msgstr ""
  103 +
  104 +#: templates/links/relatorios.html:37
  105 +msgid "Send message"
  106 +msgstr ""
  107 +
  108 +#: templates/links/relatorios.html:37
  109 +msgid "Action don't realized"
  110 +msgstr ""
  111 +
  112 +#: templates/links/relatorios.html:151 templates/links/relatorios.html:171
  113 +msgid "Reports"
  114 +msgstr ""
  115 +
  116 +#: templates/links/relatorios.html:178
  117 +msgid "Report of the resource "
  118 +msgstr ""
  119 +
  120 +#: templates/links/relatorios.html:187
  121 +msgid "Select the period: "
  122 +msgstr ""
  123 +
  124 +#: templates/links/relatorios.html:196
  125 +msgid "Search"
  126 +msgstr ""
  127 +
  128 +#: templates/links/relatorios.html:220
  129 +msgid "Filter: "
  130 +msgstr ""
  131 +
  132 +#: templates/links/relatorios.html:244 templates/links/relatorios.html:329
  133 +msgid "record(s)"
  134 +msgstr ""
  135 +
  136 +#: templates/links/send_message.html:38
  137 +msgid "Click or drop the picture here"
  138 +msgstr ""
  139 +
  140 +#: templates/links/send_message.html:40
  141 +msgid "The picture could not exceed 5MB."
  142 +msgstr ""
  143 +
  144 +#: templates/links/send_message.html:63
  145 +msgid "Send"
  146 +msgstr ""
  147 +
  148 +#: templates/links/update.html:20
89 msgid "Edit: " 149 msgid "Edit: "
90 msgstr "" 150 msgstr ""
91 151
92 -#: links/views.py:51 links/views.py:64 links/views.py:224 links/views.py:226  
93 -#: links/views.py:242 links/views.py:244 152 +#: views.py:59 views.py:72 views.py:256 views.py:258 views.py:274 views.py:276
94 msgid "Visualize" 153 msgid "Visualize"
95 msgstr "" 154 msgstr ""
96 155
97 -#: links/views.py:124 156 +#: views.py:134
98 msgid "Create Webiste Link" 157 msgid "Create Webiste Link"
99 msgstr "" 158 msgstr ""
100 159
101 -#: links/views.py:135 160 +#: views.py:145
102 #, python-format 161 #, python-format
103 msgid "" 162 msgid ""
104 "The Link \"%s\" was added to the Topic \"%s\" of the virtual environment " 163 "The Link \"%s\" was added to the Topic \"%s\" of the virtual environment "
105 "\"%s\" successfully!" 164 "\"%s\" successfully!"
106 msgstr "" 165 msgstr ""
107 166
108 -#: links/views.py:163 167 +#: views.py:173
109 #, python-format 168 #, python-format
110 msgid "" 169 msgid ""
111 "The Website Link \"%s\" was removed successfully from virtual environment " 170 "The Website Link \"%s\" was removed successfully from virtual environment "
112 "\"%s\"!" 171 "\"%s\"!"
113 msgstr "" 172 msgstr ""
114 173
115 -#: links/views.py:288 174 +#: views.py:322
116 msgid "Update Website Link" 175 msgid "Update Website Link"
117 msgstr "" 176 msgstr ""
118 177
119 -#: links/views.py:299 178 +#: views.py:333
120 #, python-format 179 #, python-format
121 msgid "The Website Link \"%s\" was updated successfully!" 180 msgid "The Website Link \"%s\" was updated successfully!"
122 msgstr "" 181 msgstr ""
  182 +
  183 +#: views.py:377
  184 +msgid "Links Reports"
  185 +msgstr ""
  186 +
  187 +#: views.py:396
  188 +msgid "Realized"
  189 +msgstr ""
  190 +
  191 +#: views.py:396
  192 +msgid "Unrealized"
  193 +msgstr ""
  194 +
  195 +#: views.py:396
  196 +msgid "Historic"
  197 +msgstr ""
  198 +
  199 +#: views.py:414 views.py:423
  200 +msgid "View"
  201 +msgstr ""
  202 +
  203 +#: views.py:422
  204 +msgid "Links"
  205 +msgstr ""
  206 +
  207 +#: views.py:427
  208 +msgid "Actions about resource"
  209 +msgstr ""
  210 +
  211 +#: views.py:428
  212 +msgid "Quantity"
  213 +msgstr ""
links/locale/pt_BR/LC_MESSAGES/django.po
@@ -8,7 +8,7 @@ msgid &quot;&quot; @@ -8,7 +8,7 @@ msgid &quot;&quot;
8 msgstr "" 8 msgstr ""
9 "Project-Id-Version: PACKAGE VERSION\n" 9 "Project-Id-Version: PACKAGE VERSION\n"
10 "Report-Msgid-Bugs-To: \n" 10 "Report-Msgid-Bugs-To: \n"
11 -"POT-Creation-Date: 2017-04-15 00:13-0300\n" 11 +"POT-Creation-Date: 2017-05-05 19:49-0300\n"
12 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" 12 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
13 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" 13 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
14 "Language-Team: LANGUAGE <LL@li.org>\n" 14 "Language-Team: LANGUAGE <LL@li.org>\n"
@@ -18,88 +18,147 @@ msgstr &quot;&quot; @@ -18,88 +18,147 @@ msgstr &quot;&quot;
18 "Content-Transfer-Encoding: 8bit\n" 18 "Content-Transfer-Encoding: 8bit\n"
19 "Plural-Forms: nplurals=2; plural=(n > 1);\n" 19 "Plural-Forms: nplurals=2; plural=(n > 1);\n"
20 20
21 -#: links/forms.py:27 21 +#: forms.py:27
22 msgid "Tags" 22 msgid "Tags"
23 msgstr "" 23 msgstr ""
24 24
25 -#: links/forms.py:28 25 +#: forms.py:28
26 msgid "Website URL" 26 msgid "Website URL"
27 msgstr "URL do site:" 27 msgstr "URL do site:"
28 28
29 -#: links/forms.py:34 29 +#: forms.py:34
30 msgid "Link name" 30 msgid "Link name"
31 msgstr "Nome do Link" 31 msgstr "Nome do Link"
32 32
33 -#: links/forms.py:35 33 +#: forms.py:35
34 msgid "End View" 34 msgid "End View"
35 msgstr "" 35 msgstr ""
36 36
37 -#: links/forms.py:36 37 +#: forms.py:36
38 msgid "End View Date" 38 msgid "End View Date"
39 msgstr "" 39 msgstr ""
40 40
41 -#: links/forms.py:64 41 +#: forms.py:64
42 msgid "There is already a link with this name on this subject" 42 msgid "There is already a link with this name on this subject"
43 msgstr "Ja existe um link com este nome neste Assunto" 43 msgstr "Ja existe um link com este nome neste Assunto"
44 44
45 -#: links/models.py:11 45 +#: models.py:13
46 msgid "Link_URL" 46 msgid "Link_URL"
47 msgstr "URL do link" 47 msgstr "URL do link"
48 48
49 -#: links/models.py:31 links/templates/links/delete.html:12 49 +#: models.py:33 templates/links/delete.html:12
50 msgid "Are you sure you want delete the Website link" 50 msgid "Are you sure you want delete the Website link"
51 msgstr "Tem certeza que voce deseja remover esse Link para Website" 51 msgstr "Tem certeza que voce deseja remover esse Link para Website"
52 52
53 -#: links/templates/links/_form.html:112 53 +#: templates/links/_form.html:112
54 msgid "Pendencies Notifications" 54 msgid "Pendencies Notifications"
55 msgstr "" 55 msgstr ""
56 56
57 -#: links/templates/links/_form.html:130 57 +#: templates/links/_form.html:130
58 msgid "Action not performed by the user" 58 msgid "Action not performed by the user"
59 msgstr "" 59 msgstr ""
60 60
61 -#: links/templates/links/_form.html:156 61 +#: templates/links/_form.html:156
62 msgid "Wished period" 62 msgid "Wished period"
63 msgstr "" 63 msgstr ""
64 64
65 -#: links/templates/links/_form.html:252 65 +#: templates/links/_form.html:252
66 msgid "Attribute students to file link" 66 msgid "Attribute students to file link"
67 msgstr "" 67 msgstr ""
68 68
69 -#: links/templates/links/_form.html:272 69 +#: templates/links/_form.html:272
70 msgid "Attribute groups to file link" 70 msgid "Attribute groups to file link"
71 msgstr "" 71 msgstr ""
72 72
73 -#: links/templates/links/_form.html:320 73 +#: templates/links/_form.html:320
74 msgid "Save" 74 msgid "Save"
75 msgstr "Salvar" 75 msgstr "Salvar"
76 76
77 -#: links/templates/links/create.html:20 77 +#: templates/links/create.html:20
78 msgid "Create Website Link" 78 msgid "Create Website Link"
79 msgstr "Criar Link do Website" 79 msgstr "Criar Link do Website"
80 80
81 -#: links/templates/links/delete.html:18 81 +#: templates/links/delete.html:18 templates/links/send_message.html:62
82 msgid "Close" 82 msgid "Close"
83 msgstr "Fechar" 83 msgstr "Fechar"
84 84
85 -#: links/templates/links/delete.html:19 85 +#: templates/links/delete.html:19
86 msgid "Delete" 86 msgid "Delete"
87 msgstr "Remover" 87 msgstr "Remover"
88 88
89 -#: links/templates/links/update.html:20 89 +#: templates/links/relatorios.html:17 templates/links/relatorios.html:37
  90 +msgid "User"
  91 +msgstr "Usuário"
  92 +
  93 +#: templates/links/relatorios.html:17 templates/links/relatorios.html:37
  94 +msgid "Group"
  95 +msgstr "Grupo"
  96 +
  97 +#: templates/links/relatorios.html:17
  98 +msgid "Action"
  99 +msgstr "Ação"
  100 +
  101 +#: templates/links/relatorios.html:17
  102 +msgid "Date of Action"
  103 +msgstr "Data da ação"
  104 +
  105 +#: templates/links/relatorios.html:37
  106 +msgid "Send message"
  107 +msgstr "Enviar Mensagem"
  108 +
  109 +#: templates/links/relatorios.html:37
  110 +msgid "Action don't realized"
  111 +msgstr "Ação não realizada"
  112 +
  113 +#: templates/links/relatorios.html:151 templates/links/relatorios.html:171
  114 +msgid "Reports"
  115 +msgstr "Relatórios"
  116 +
  117 +#: templates/links/relatorios.html:178
  118 +msgid "Report of the resource "
  119 +msgstr "Relatórios do recurso "
  120 +
  121 +#: templates/links/relatorios.html:187
  122 +msgid "Select the period: "
  123 +msgstr "Selecione o período: "
  124 +
  125 +#: templates/links/relatorios.html:196
  126 +msgid "Search"
  127 +msgstr "Pesquisar"
  128 +
  129 +#: templates/links/relatorios.html:220
  130 +msgid "Filter: "
  131 +msgstr "Filtro: "
  132 +
  133 +#: templates/links/relatorios.html:244 templates/links/relatorios.html:329
  134 +msgid "record(s)"
  135 +msgstr "Relatório(s)"
  136 +
  137 +#: templates/links/send_message.html:38
  138 +msgid "Click or drop the picture here"
  139 +msgstr "Clique ou solte a imagem aqui"
  140 +
  141 +#: templates/links/send_message.html:40
  142 +msgid "The picture could not exceed 5MB."
  143 +msgstr "A imagem não pode exceder 5MB."
  144 +
  145 +#: templates/links/send_message.html:63
  146 +msgid "Send"
  147 +msgstr "Enviar"
  148 +
  149 +#: templates/links/update.html:20
90 msgid "Edit: " 150 msgid "Edit: "
91 msgstr "Editar: " 151 msgstr "Editar: "
92 152
93 -#: links/views.py:51 links/views.py:64 links/views.py:234 links/views.py:236  
94 -#: links/views.py:252 links/views.py:254 153 +#: views.py:59 views.py:72 views.py:256 views.py:258 views.py:274 views.py:276
95 msgid "Visualize" 154 msgid "Visualize"
96 msgstr "Visualizar" 155 msgstr "Visualizar"
97 156
98 -#: links/views.py:126 157 +#: views.py:134
99 msgid "Create Webiste Link" 158 msgid "Create Webiste Link"
100 msgstr "Criar Link de Website" 159 msgstr "Criar Link de Website"
101 160
102 -#: links/views.py:137 161 +#: views.py:145
103 #, python-format 162 #, python-format
104 msgid "" 163 msgid ""
105 "The Link \"%s\" was added to the Topic \"%s\" of the virtual environment " 164 "The Link \"%s\" was added to the Topic \"%s\" of the virtual environment "
@@ -108,7 +167,7 @@ msgstr &quot;&quot; @@ -108,7 +167,7 @@ msgstr &quot;&quot;
108 "O link \"%s\" foi adicionado com sucesso ao Topico \"%s\" do ambiente " 167 "O link \"%s\" foi adicionado com sucesso ao Topico \"%s\" do ambiente "
109 "virtual \"%s\" " 168 "virtual \"%s\" "
110 169
111 -#: links/views.py:165 170 +#: views.py:173
112 #, python-format 171 #, python-format
113 msgid "" 172 msgid ""
114 "The Website Link \"%s\" was removed successfully from virtual environment " 173 "The Website Link \"%s\" was removed successfully from virtual environment "
@@ -116,11 +175,45 @@ msgid &quot;&quot; @@ -116,11 +175,45 @@ msgid &quot;&quot;
116 msgstr "" 175 msgstr ""
117 "O Link do site \"%s\" foi removido com sucesso do ambiente virtual \"%s\" " 176 "O Link do site \"%s\" foi removido com sucesso do ambiente virtual \"%s\" "
118 177
119 -#: links/views.py:300 178 +#: views.py:322
120 msgid "Update Website Link" 179 msgid "Update Website Link"
121 msgstr "Atualizar Link do website" 180 msgstr "Atualizar Link do website"
122 181
123 -#: links/views.py:311 182 +#: views.py:333
124 #, python-format 183 #, python-format
125 msgid "The Website Link \"%s\" was updated successfully!" 184 msgid "The Website Link \"%s\" was updated successfully!"
126 msgstr "O link do website \"%s\" foi atualizado com sucesso! " 185 msgstr "O link do website \"%s\" foi atualizado com sucesso! "
  186 +
  187 +#: views.py:377
  188 +msgid "Links Reports"
  189 +msgstr "Relatórios de links"
  190 +
  191 +#: views.py:396
  192 +msgid "Realized"
  193 +msgstr "Realizado"
  194 +
  195 +#: views.py:396
  196 +msgid "Unrealized"
  197 +msgstr "Não Realizado"
  198 +
  199 +#: views.py:396
  200 +msgid "Historic"
  201 +msgstr "Histórico"
  202 +
  203 +#: views.py:414 views.py:423
  204 +msgid "View"
  205 +msgstr "Visualizar"
  206 +
  207 +#: views.py:422
  208 +#, fuzzy
  209 +#| msgid "Link_URL"
  210 +msgid "Links"
  211 +msgstr "Links"
  212 +
  213 +#: views.py:427
  214 +msgid "Actions about resource"
  215 +msgstr "Ações sobre o recurso"
  216 +
  217 +#: views.py:428
  218 +msgid "Quantity"
  219 +msgstr "Quantidade"
links/models.py
@@ -6,6 +6,8 @@ import datetime @@ -6,6 +6,8 @@ import datetime
6 from topics.models import Topic, Resource 6 from topics.models import Topic, Resource
7 from users.models import User 7 from users.models import User
8 from django.utils import timezone 8 from django.utils import timezone
  9 +from django.core.urlresolvers import reverse_lazy
  10 +
9 # Create your models here. 11 # Create your models here.
10 class Link(Resource): 12 class Link(Resource):
11 link_url = models.URLField(verbose_name = _("Link_URL")) 13 link_url = models.URLField(verbose_name = _("Link_URL"))
@@ -19,7 +21,7 @@ class Link(Resource): @@ -19,7 +21,7 @@ class Link(Resource):
19 return self.name 21 return self.name
20 22
21 def access_link(self): 23 def access_link(self):
22 - return self.link_url 24 + return reverse_lazy('links:view', kwargs = {'slug': self.slug})
23 25
24 def update_link(self): 26 def update_link(self):
25 return 'links:update' 27 return 'links:update'
links/templates/links/relatorios.html 0 → 100644
@@ -0,0 +1,408 @@ @@ -0,0 +1,408 @@
  1 +{% extends "subjects/view.html" %}
  2 +
  3 +{% load static i18n pagination permissions_tags subject_counter %}
  4 +{% load django_bootstrap_breadcrumbs %}
  5 +
  6 +{% block javascript%}
  7 + {{ block.super }}
  8 + <script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
  9 + <script type="text/javascript">
  10 + var tabela_atual = true;
  11 +
  12 + var array_history = [];
  13 + {%for data_json in json_history.data %}
  14 + array_history.push(["{{data_json.0}}","{{data_json.1}}","{{view}}",{% if data_json.3 is not None %}new Date('{{data_json.3.isoformat}}'){% else%}null{% endif %}]);
  15 + {% endfor%}
  16 + var json_history = {"data":array_history};
  17 + var column_history = [{"string":'{% trans "User" %}'},{"string":'{% trans "Group" %}'},{"string":'{% trans "Action" %}'},{"date":'{% trans "Date of Action" %}'}];
  18 +
  19 + var search = [];
  20 + for (var i in json_history["data"]){
  21 + search.push([json_history["data"][i][0],json_history["data"][i][1],
  22 + json_history["data"][i][2],json_history["data"][i][3]]);
  23 + }
  24 +
  25 + var array_n_did = [];
  26 + var checkbox = {};
  27 + {%for data_json in json_n_did.data%}
  28 + var input = '<div class="checkbox">\
  29 + <label for="{{data_json.0}}_google_table">\
  30 + <input id="{{data_json.0}}_google_table" name="{{data_json.0}}_google_table" type="checkbox"><span class="checkbox-material"><span class="check"></span></span>\
  31 + </label>\
  32 + </div>'
  33 + checkbox["{{data_json.0}}_google_table"] = "{{data_json.4}}";
  34 + array_n_did.push([input,"{{data_json.1}}","{{data_json.2}}","{{data_json.3}}"]);
  35 + {% endfor%}
  36 + var json_n_did = {"data":array_n_did};
  37 + var column_n_did = [{"string":'<a href="javascript:void(0);" onclick="return openmodal();"> {% trans "Send message" %}</a>'},{"string":'{% trans "User" %}'},{"string":'{% trans "Group" %}'},{"string":"{% trans "Action don't realized" %}"}];
  38 + </script>
  39 +
  40 +
  41 + <script type="text/javascript">
  42 + google.charts.load('current', {'packages':['corechart',"table"]});
  43 + google.charts.setOnLoadCallback(drawChart);
  44 + google.charts.setOnLoadCallback(drawTable);
  45 +
  46 + function drawChart() {
  47 + var data = google.visualization.arrayToDataTable({{db_data|safe}});
  48 + var options = {
  49 + title: '{{title_chart}}',
  50 + // legend: {position: 'right', maxLines: 1},
  51 + bar: { groupWidth: '30%' },
  52 + chartArea:{width:"50%"},
  53 + titlePosition: 'out',
  54 + vAxis: {
  55 + title: '{{title_vAxis}}',
  56 + ticks: [0, .20, .40, .60, .80, 1],
  57 + viewWindow: {
  58 + min: 0,
  59 + max: 1
  60 + }
  61 + },
  62 + isStacked: "percent",
  63 + };
  64 +
  65 + function selectHandler() {
  66 + var selectedItem = chart.getSelection()[0];
  67 + if (selectedItem) {
  68 + var col = data.getColumnLabel(selectedItem.column);
  69 + if (col == "{{n_did_table}}"){
  70 + tabela_atual = false;
  71 + search = [];
  72 + for (var i in json_n_did["data"]){
  73 + search.push([json_n_did["data"][i][0],json_n_did["data"][i][1],
  74 + json_n_did["data"][i][2],json_n_did["data"][i][3]]);
  75 + }
  76 + searcher(col, tabela_atual,true);
  77 +
  78 + } else if (col == "{{did_table}}"){
  79 + tabela_atual = true;
  80 + search = [];
  81 + for (var i in json_history["data"]){
  82 + search.push([json_history["data"][i][0],json_history["data"][i][1],
  83 + json_history["data"][i][2],json_history["data"][i][3]]);
  84 + }
  85 + searcher(col, tabela_atual,true);
  86 + }
  87 + }
  88 + chart.setSelection([])
  89 + }
  90 +
  91 + var chart = new google.visualization.ColumnChart(document.getElementById('chart_div'));
  92 + google.visualization.events.addListener(chart, 'select', selectHandler);
  93 + chart.draw(data, options);
  94 +
  95 + }
  96 +
  97 + var sortAscending = {0:false,1:false,2:false,3:false};
  98 + function drawTable(columns = column_history,rows = pagination(json_history["data"],1),isdate = true,columndate = 3) {
  99 + var data_table = new google.visualization.DataTable();
  100 + for (var i in columns){
  101 + for (var item in columns[i]){
  102 + data_table.addColumn(item,columns[i][item]);
  103 + }
  104 + }
  105 +
  106 + data_table.addRows(rows);
  107 + var formate_date = new google.visualization.DateFormat({pattern: 'dd/MM/yyyy HH:mm'});
  108 + if (isdate) formate_date.format(data_table, columndate);
  109 +
  110 + // var methods = [];
  111 + // for (var m in data_table) {
  112 + // if (typeof data_table[m] == "function") {
  113 + // methods.push(m);
  114 + // }
  115 + // }
  116 + // console.log(methods.join(","));
  117 + var options = {
  118 + sort: "event",
  119 + allowHtml: true,
  120 + cssClassNames : {
  121 + tableRow: 'text-center',
  122 + tableCell: 'text-center',
  123 + headerCell: 'text-center'
  124 + },
  125 + showRowNumber: true,
  126 + width: '100%',
  127 + height: '100%',
  128 + }
  129 + function ordenar(properties){
  130 + var columnIndex = properties['column'];
  131 + if (columnIndex > 0) {
  132 + options["sortColumn"] = columnIndex;
  133 + options["sortAscending"] = sortAscending[columnIndex];
  134 + data_table.sort({column:columnIndex,desc:sortAscending[columnIndex]});
  135 + sortAscending = {0:false,1:false,2:false,3:false};
  136 + sortAscending[columnIndex] = !sortAscending[columnIndex];
  137 + // console.log(sortAscending);
  138 + table.draw(data_table, options);
  139 + }
  140 + }
  141 +
  142 + var table = new google.visualization.Table(document.getElementById('table_div'));
  143 + google.visualization.events.addListener(table, 'sort', function(e) {ordenar(e)});
  144 + table.draw(data_table, options);
  145 + }
  146 + </script>
  147 +{% endblock%}
  148 +
  149 +{% block breadcrumbs %}
  150 + {{ block.super }}
  151 + {% trans 'Reports' as bread %}
  152 + {% breadcrumb bread link%}
  153 +{% endblock %}
  154 +
  155 +{% block content %}
  156 + {% if messages %}
  157 + {% for message in messages %}
  158 + <div class="alert alert-{{ message.tags }} alert-dismissible" role="alert">
  159 + <button type="button" class="close" data-dismiss="alert" aria-label="Close">
  160 + <span aria-hidden="true">&times;</span>
  161 + </button>
  162 + <p>{{ message }}</p>
  163 + </div>
  164 + {% endfor %}
  165 + {% endif %}
  166 + <div class="panel panel-info topic-panel">
  167 + <div class="panel-heading">
  168 + <div class="row">
  169 + <div class="col-md-12 category-header">
  170 + <h4 class="panel-title" style="margin-top: 10px; margin-bottom: 8px">
  171 + <span>{{link}} / {% trans "Reports" %}</span>
  172 + </h4>
  173 + </div>
  174 + </div>
  175 + </div>
  176 + <div class="row">
  177 + <div class="col-md-12 text-center">
  178 + <h4 style="margin-top: 15px; margin-bottom: 10px" ><strong>{% trans "Report of the resource " %}{{link}}</strong></h4>
  179 + </div>
  180 + </div>
  181 + <div class="row">
  182 + <div class="col-md-12">
  183 +
  184 + <ul class="list-inline nav-justified">
  185 + <div id="general-parameters-div">
  186 + <div class="general-parameters-field">
  187 + <li class="text-right"><h4>{% trans "Select the period: " %}</h4></li>
  188 + </div>
  189 + <form id="period-form" action="" method="get">
  190 + <div class="general-parameters-field">
  191 + <li> <input class="form-control datetime-picker" name="init_date" type="text" required="" value="{% if LANGUAGE_CODE == 'pt-br' %}{{init_date|date:'d/m/Y H:i'}} {% else %} {{init_date|date:'m/d/Y H:i P'}} {% endif %}"></li>
  192 + </div>
  193 + <div class="general-parameters-field">
  194 + <li><input id="inputdate" class="form-control datetime-picker" name="end_date" type="text" required="" value="{% if LANGUAGE_CODE == 'pt-br' %}{{end_date|date:'d/m/Y H:i'}} {% else %} {{end_date|date:'m/d/Y H:i P'}} {% endif %}"></li>
  195 + </div>
  196 + <li><input type="submit" value="{% trans 'Search' %}" style="margin-left: 15px;" class="btn btn-success btn-raised"></li>
  197 + </form>
  198 + </div>
  199 + <ul>
  200 + </div>
  201 + </div>
  202 +
  203 + <div class="row">
  204 + <div class="col-md-10 col-md-offset-1">
  205 + <div id="chart_div" style="height: 500px; margin-top: -50px;"></div>
  206 + </div>
  207 + </div>
  208 +
  209 + <div class="row">
  210 + <div class="col-md-10 col-md-offset-1">
  211 + <div class="text-center">
  212 + <ul class="list-inline nav-justified">
  213 + <li>
  214 + <ul id="view-table" class="list-inline text-right">
  215 + <li><h3 id="title-table"></h3></li>
  216 + </ul>
  217 + </li>
  218 + <li>
  219 + <ul class="list-inline text-right">
  220 + <li><p>{% trans "Filter: " %}</p></li>
  221 + <li><input id="search-input" class="form-control" type="text" name="search" value=""></li>
  222 + </ul>
  223 + </li>
  224 + </ul>
  225 + </div>
  226 + <form id="google-chart-checkbox" action="" method="get">
  227 + <div id="table_div"></div>
  228 + </form>
  229 + <div class="col-md-12 col-lg-12 col-sm-12 col-xs-12 text-center">
  230 + <ul class="pagination">
  231 +
  232 + </ul>
  233 + </div>
  234 + </div>
  235 + </div>
  236 + <div id="modal-message"></div>
  237 + <div class="row">
  238 + <br><br>
  239 + </div>
  240 + </div>
  241 +
  242 + <script type="text/javascript">
  243 +
  244 + $("#title-table").text(search.length + " {% trans 'record(s)' %}");
  245 + function putpagination(data = json_history["data"], load_histoty = true){
  246 + var len = Math.ceil(data.length / 20);
  247 + $(".pagination").empty();
  248 + $(".pagination").append('<li class="disabled"><span>«</span></li>');
  249 + $(".pagination").append('<li id="1" class="active">\
  250 + <a href="javascript:void(0);" onclick="return clickPagination(1, '+ load_histoty +');">1</a>\
  251 + </li>');
  252 + for (var i = 2; i <= len;i++){
  253 + $(".pagination").append('<li id="' + i + '">\
  254 + <a href="javascript:void(0);" onclick="return clickPagination(' + i +', ' + load_histoty + ');">' + i + '</a>\
  255 + </li>');
  256 + }
  257 + if (len > 1) $(".pagination").append('<li><a href="javascript:void(0);" onclick="return clickPagination(2, '+ load_histoty +');"><span>»</span></a></li>');
  258 + else $(".pagination").append('<li class="disabled"><span>»</span></li>');
  259 + };
  260 + putpagination();
  261 +
  262 + $('#period-form').submit(function(event) {
  263 + $('<input />').attr('type', 'hidden')
  264 + .attr('name', "language")
  265 + .attr('value', '{{ LANGUAGE_CODE }}')
  266 + .appendTo('#period-form');
  267 + });
  268 + function add(element,local, first = false){
  269 + if (first) $(local).prepend(element);
  270 + else $(local).append(element);
  271 + }
  272 + function text(element){
  273 + return $(element).text();
  274 + }
  275 + function length(element) {
  276 + return $(element).length;
  277 + }
  278 +
  279 + $("#search-input").on("keyup",function(){
  280 + search = [];
  281 + var text = $("#search-input").val();
  282 + searcher(text,tabela_atual);
  283 + });
  284 +
  285 + function searcher(text, load_histoty = false,apaga=false){
  286 + if(apaga){
  287 + $("#search-input").val("");
  288 + }
  289 + var data = [];
  290 + if (!load_histoty){
  291 + data = $.map(json_n_did["data"], function (obj) {
  292 + return $.extend(true, {}, obj);
  293 + });
  294 + } else {
  295 + data = $.map(json_history["data"], function (obj) {
  296 + return $.extend(true, {}, obj);
  297 + });
  298 + }
  299 + if (load_histoty){
  300 + for (var i in data){
  301 + data[i][3] = moment(data[i][3]).format("DD/MM/YYYY HH:mm");
  302 + }
  303 + }
  304 + if (load_histoty){
  305 + for (var i in data){
  306 + if (data[i][0].toLowerCase().includes(text.toLowerCase())
  307 + || data[i][1].toLowerCase().includes(text.toLowerCase())
  308 + || data[i][2].toLowerCase().includes(text.toLowerCase())
  309 + || data[i][3].toLowerCase().includes(text.toLowerCase())){
  310 + search.push(json_history["data"][i]);
  311 + }
  312 + }
  313 + }
  314 + else {
  315 + for (var i in data){
  316 + if (data[i][1].toLowerCase().includes(text.toLowerCase())
  317 + || data[i][2].toLowerCase().includes(text.toLowerCase())
  318 + || data[i][3].toLowerCase().includes(text.toLowerCase())){
  319 + search.push(json_n_did["data"][i]);
  320 + }
  321 + }
  322 + }
  323 + console.log(search);
  324 + if (!load_histoty){
  325 + drawTable(column_n_did,pagination(search,1),false);
  326 + } else {
  327 + drawTable(column_history,pagination(search,1),true,3);
  328 + }
  329 + $("#title-table").text(search.length + " {% trans 'record(s)' %}");
  330 + putpagination(search,load_histoty);
  331 + }
  332 +
  333 + function pagination(data,pag){
  334 + var len = data.length;
  335 + var first = (pag * 20 - 20 < len) ? pag * 20 - 20:len;
  336 + var end = (pag * 20 < len) ? pag * 20:len;
  337 + var search = data.slice(first,end);
  338 + return search;
  339 + }
  340 +
  341 + function clickPagination(pag, load_histoty = false){
  342 + $(".pagination > li").last().remove();
  343 + $(".pagination > li").first().remove();
  344 +
  345 + if (!load_histoty){
  346 + drawTable(column_n_did,pagination(search,pag),false);
  347 + } else {
  348 + drawTable(column_history,pagination(search,pag),true,3);
  349 + }
  350 +
  351 + if (pag < Math.ceil(search.length / 20))
  352 + $(".pagination").append('<li><a href="javascript:void(0);" onclick="return clickPagination(' + (pag + 1) + ', '+ load_histoty +');"><span>»</span></a></li>');
  353 + else $(".pagination").append('<li class="disabled"><span>»</span></li>');
  354 + if (pag > 1)
  355 + $(".pagination").prepend('<li><a href="javascript:void(0);" onclick="return clickPagination(' + (pag - 1) + ', '+ load_histoty +');"><span>«</span></a></li>');
  356 + else $(".pagination").prepend('<li class="disabled"><span>«</span></li>');
  357 + $(".active").removeClass("active");
  358 + $("#" + pag).addClass("active");
  359 + }
  360 +
  361 + function openmodal(){
  362 + $( "#modal-message" ).empty();
  363 + $.get( "{% url 'links:send_message' link.slug %}", function( data ) {
  364 + $( "#modal-message" ).append( data );
  365 + $("#send-message-modal").modal("show");
  366 + });
  367 + }
  368 +
  369 + function sendMessage(){
  370 + $("#send-message-modal").modal("hide");
  371 + var checked = $("#google-chart-checkbox").serializeArray();
  372 + var email = [];
  373 + for (var i in checked){
  374 + email.push(checkbox[checked[i]["name"]]);
  375 + }
  376 + $('<input />').attr('type', 'hidden')
  377 + .attr('name', "users[]")
  378 + .attr('value', email)
  379 + .appendTo('#text_chat_form');
  380 +
  381 + var formData = new FormData($('#text_chat_form').get(0));
  382 + $.ajax({
  383 + url: "{% url 'links:send_message' link.slug %}",
  384 + type: "POST",
  385 + data: formData,
  386 + cache: false,
  387 + processData: false,
  388 + contentType: false,
  389 + success: function(data) {
  390 + if (data["message"]){
  391 + console.log("success");
  392 + $("body").removeClass("modal-open");
  393 + $( "#modal-message" ).empty();
  394 + $(".modal-backdrop.fade.in").remove();
  395 + } else {
  396 + $( "#modal-message" ).empty();
  397 + $(".modal-backdrop.fade.in").remove();
  398 + $( "#modal-message" ).append( data );
  399 + $("#send-message-modal").modal("show");
  400 + }
  401 + },
  402 + error: function(data){
  403 + console.log("erro");
  404 + }
  405 + });
  406 + }
  407 + </script>
  408 +{% endblock %}
links/templates/links/send_message.html 0 → 100644
@@ -0,0 +1,112 @@ @@ -0,0 +1,112 @@
  1 +
  2 + {% load widget_tweaks i18n %}
  3 + <!-- Modal (remember to change the ids!!!) -->
  4 +<div class="modal fade" id="send-message-modal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
  5 + <div class="modal-dialog" role="document">
  6 + <div class="modal-content">
  7 + <!-- Modal Body -->
  8 + <div class="modal-body">
  9 + <form id="text_chat_form" action="" method="POST" enctype="multipart/form-data">
  10 + {% csrf_token %}
  11 + {% comment %}Area para o Texto{% endcomment %}
  12 + <div class="form-group{% if form.has_error %} has-error {% endif %}">
  13 + <label for="{{ form.comment.auto_id }}">{{ form.comment.label }}: <span>*</span></label>
  14 + {% render_field form.comment class='form-control text_simple_wysiwyg' %}
  15 +
  16 + <span id="helpBlock" class="help-block">{{ form.comment.help_text }}</span>
  17 +
  18 + {% if form.comment.errors %}
  19 + <div class="alert alert-danger alert-dismissible" role="alert">
  20 + <button type="button" class="close" data-dismiss="alert" aria-label="Close">
  21 + <span aria-hidden="true">&times;</span>
  22 + </button>
  23 + <ul>
  24 + {% for error in form.comment.errors %}
  25 + <li>{{ error }}</li>
  26 + {% endfor %}
  27 + </ul>
  28 + </div>
  29 + {% endif %}
  30 + </div>
  31 + {% comment %}Area para anexar a imagem {% endcomment %}
  32 + <div class="form-group{% if form.has_error %} has-error {% endif %} is-fileinput">
  33 + {% render_field form.image %}
  34 +
  35 + <div class="filedrag">
  36 + {% trans 'Click or drop the picture here' %}<br />
  37 +
  38 + <small>{% trans 'The picture could not exceed 5MB.' %}</small>
  39 + </div>
  40 +
  41 + {% if form.image.errors %}
  42 + <div class="alert alert-danger alert-dismissible" role="alert">
  43 + <button type="button" class="close" data-dismiss="alert" aria-label="Close">
  44 + <span aria-hidden="true">&times;</span>
  45 + </button>
  46 + <ul>
  47 + {% for error in form.image.errors %}
  48 + <li>{{ error }}</li>
  49 + {% endfor %}
  50 + </ul>
  51 + </div>
  52 + {% endif %}
  53 +
  54 + </div>
  55 + </form>
  56 + </div>
  57 + <!-- Modal Footer -->
  58 + <div id="delete-category-footer"class="modal-footer">
  59 + <!-- Don't remove that!!! -->
  60 + <button type="button" class="btn btn-default btn-raised" data-dismiss="modal">{% trans "Close" %}</button>
  61 + <a href="javascript:void(0)" onclick="return sendMessage()" form="text_chat_form" class="btn btn-success btn-raised erase-button">{% trans "Send" %}</a>
  62 + </div>
  63 + </div>
  64 + </div>
  65 +</div>
  66 +
  67 +<script type="text/javascript">
  68 +
  69 + $('.text_simple_wysiwyg').summernote({
  70 + dialogsInBody: true,
  71 + disableDragAndDrop: true,
  72 + height: 150,
  73 + toolbar: [
  74 + // [groupName, [list of button]]
  75 + ['style', ['bold', 'italic']],
  76 + ['insert', ['link']]
  77 + ]
  78 + });
  79 +
  80 + if (window.File && window.FileList && window.FileReader) {
  81 + Init();
  82 + }
  83 +
  84 + function Init() {
  85 + var small = $("#id_image"),
  86 + filedrag = $(".filedrag"),
  87 + common = $(".common-file-input");
  88 +
  89 + // file select
  90 + small.on("change", FileSelectHandler);
  91 +
  92 + // is XHR2 available?
  93 + var xhr = new XMLHttpRequest();
  94 + if (xhr.upload) {
  95 + // file drop
  96 + filedrag.on("drop", FileSelectHandler);
  97 + filedrag.attr('style', 'display:block');
  98 + common.attr('style', 'display:none');
  99 + }
  100 + }
  101 +
  102 + // file selection
  103 + function FileSelectHandler(e) {
  104 + var files = e.target.files || e.dataTransfer.files,
  105 + parent = $(e.target.offsetParent);
  106 +
  107 + // process all File objects
  108 + for (var i = 0, f; f = files[i]; i++) {
  109 + parent.find('.filedrag').html(f.name);
  110 + }
  111 + }
  112 +</script>
0 \ No newline at end of file 113 \ No newline at end of file
@@ -7,4 +7,7 @@ urlpatterns = [ @@ -7,4 +7,7 @@ urlpatterns = [
7 url(r'^create/(?P<slug>[\w_-]+)/$', views.CreateLinkView.as_view(), name='create'), 7 url(r'^create/(?P<slug>[\w_-]+)/$', views.CreateLinkView.as_view(), name='create'),
8 url(r'^delete/(?P<slug>[\w_-]+)/$', views.DeleteLinkView.as_view(), name='delete'), 8 url(r'^delete/(?P<slug>[\w_-]+)/$', views.DeleteLinkView.as_view(), name='delete'),
9 url(r'^update/(?P<topic_slug>[\w_-]+)/(?P<slug>[\w_-]+)/$', views.UpdateLinkView.as_view(), name='update'), 9 url(r'^update/(?P<topic_slug>[\w_-]+)/(?P<slug>[\w_-]+)/$', views.UpdateLinkView.as_view(), name='update'),
10 - url(r'^view/(?P<slug>[\w_-]+)/$', views.DetailLinkView.as_view(), name='view')]  
11 \ No newline at end of file 10 \ No newline at end of file
  11 + url(r'^view/(?P<slug>[\w_-]+)/$', views.RedirectUrl.as_view(), name='view'),
  12 + url(r'^chart/(?P<slug>[\w_-]+)/$', views.StatisticsView.as_view(), name = 'get_chart'),
  13 + url(r'^send-message/(?P<slug>[\w_-]+)/$', views.SendMessage.as_view(), name = 'send_message'),
  14 +]
links/views.py
@@ -17,6 +17,14 @@ from pendencies.forms import PendenciesForm @@ -17,6 +17,14 @@ from pendencies.forms import PendenciesForm
17 from amadeus.permissions import has_subject_permissions, has_resource_permissions 17 from amadeus.permissions import has_subject_permissions, has_resource_permissions
18 18
19 from topics.models import Topic 19 from topics.models import Topic
  20 +
  21 +import datetime
  22 +from chat.models import Conversation, TalkMessages
  23 +from users.models import User
  24 +from subjects.models import Subject
  25 +
  26 +from webpage.forms import FormModalMessage
  27 +
20 # Create your views here. 28 # Create your views here.
21 class CreateLinkView(LoginRequiredMixin, LogMixin, generic.edit.CreateView): 29 class CreateLinkView(LoginRequiredMixin, LogMixin, generic.edit.CreateView):
22 log_component = 'resources' 30 log_component = 'resources'
@@ -181,18 +189,32 @@ class DeleteLinkView(LoginRequiredMixin, LogMixin, generic.edit.DeleteView): @@ -181,18 +189,32 @@ class DeleteLinkView(LoginRequiredMixin, LogMixin, generic.edit.DeleteView):
181 189
182 return reverse_lazy('subjects:view', kwargs = {'slug': self.object.topic.subject.slug}) 190 return reverse_lazy('subjects:view', kwargs = {'slug': self.object.topic.subject.slug})
183 191
  192 +from django.views.generic.base import RedirectView
184 193
185 -class DetailLinkView(LoginRequiredMixin, LogMixin, generic.detail.DetailView): 194 +class RedirectUrl(LogMixin, RedirectView):
186 log_component = 'resources' 195 log_component = 'resources'
187 log_action = 'view' 196 log_action = 'view'
188 log_resource = 'link' 197 log_resource = 'link'
189 log_context = {} 198 log_context = {}
190 - login_url = reverse_lazy("users:login")  
191 - redirect_field_name = 'next'  
192 199
193 - model = Link  
194 - template_name = 'links/view.html'  
195 - context_object_name = 'web_link' 200 + def get_redirect_url(self, *args, **kwargs):
  201 + link = get_object_or_404(Link,slug=self.kwargs.get("slug",""))
  202 + self.log_context['category_id'] = link.topic.subject.category.id
  203 + self.log_context['category_name'] = link.topic.subject.category.name
  204 + self.log_context['category_slug'] = link.topic.subject.category.slug
  205 + self.log_context['subject_id'] = link.topic.subject.id
  206 + self.log_context['subject_name'] = link.topic.subject.name
  207 + self.log_context['subject_slug'] = link.topic.subject.slug
  208 + self.log_context['topic_id'] = link.topic.id
  209 + self.log_context['topic_name'] = link.topic.name
  210 + self.log_context['topic_slug'] = link.topic.slug
  211 + self.log_context['link_id'] = link.id
  212 + self.log_context['link_name'] = link.name
  213 + self.log_context['link_slug'] = link.slug
  214 +
  215 + super(RedirectUrl, self).createLog(self.request.user, self.log_component, self.log_action, self.log_resource, self.log_context)
  216 +
  217 + return link.link_url
196 218
197 class UpdateLinkView(LoginRequiredMixin, LogMixin, generic.edit.UpdateView): 219 class UpdateLinkView(LoginRequiredMixin, LogMixin, generic.edit.UpdateView):
198 220
@@ -311,3 +333,144 @@ class UpdateLinkView(LoginRequiredMixin, LogMixin, generic.edit.UpdateView): @@ -311,3 +333,144 @@ class UpdateLinkView(LoginRequiredMixin, LogMixin, generic.edit.UpdateView):
311 messages.success(self.request, _('The Website Link "%s" was updated successfully!')%(self.object.name)) 333 messages.success(self.request, _('The Website Link "%s" was updated successfully!')%(self.object.name))
312 334
313 return reverse_lazy('subjects:view', kwargs = {'slug': self.object.topic.subject.slug}) 335 return reverse_lazy('subjects:view', kwargs = {'slug': self.object.topic.subject.slug})
  336 +
  337 +
  338 +class StatisticsView(LoginRequiredMixin, LogMixin, generic.DetailView):
  339 + log_component = 'resources'
  340 + log_action = 'view_statistics'
  341 + log_resource = 'link'
  342 + log_context = {}
  343 +
  344 + login_url = reverse_lazy("users:login")
  345 + redirect_field_name = 'next'
  346 + model = Link
  347 + template_name = 'links/relatorios.html'
  348 +
  349 + def dispatch(self, request, *args, **kwargs):
  350 + slug = self.kwargs.get('slug', '')
  351 + link = get_object_or_404(Link, slug = slug)
  352 +
  353 + if not has_subject_permissions(request.user, link.topic.subject):
  354 + return redirect(reverse_lazy('subjects:home'))
  355 +
  356 + return super(StatisticsView, self).dispatch(request, *args, **kwargs)
  357 +
  358 + def get_context_data(self, **kwargs):
  359 + context = super(StatisticsView, self).get_context_data(**kwargs)
  360 +
  361 + self.log_context['category_id'] = self.object.topic.subject.category.id
  362 + self.log_context['category_name'] = self.object.topic.subject.category.name
  363 + self.log_context['category_slug'] = self.object.topic.subject.category.slug
  364 + self.log_context['subject_id'] = self.object.topic.subject.id
  365 + self.log_context['subject_name'] = self.object.topic.subject.name
  366 + self.log_context['subject_slug'] = self.object.topic.subject.slug
  367 + self.log_context['topic_id'] = self.object.topic.id
  368 + self.log_context['topic_name'] = self.object.topic.name
  369 + self.log_context['topic_slug'] = self.object.topic.slug
  370 + self.log_context['link_id'] = self.object.id
  371 + self.log_context['link_name'] = self.object.name
  372 + self.log_context['link_slug'] = self.object.slug
  373 +
  374 + super(StatisticsView, self).createLog(self.request.user, self.log_component, self.log_action, self.log_resource, self.log_context)
  375 +
  376 +
  377 + context['title'] = _('Links Reports')
  378 +
  379 + slug = self.kwargs.get('slug')
  380 + link = get_object_or_404(Link, slug = slug)
  381 + print (self.request.GET.get('init_date',''))
  382 + date_format = "%d/%m/%Y %H:%M" if self.request.GET.get('language','') == 'pt-br' else "%m/%d/%Y %I:%M %p"
  383 + if self.request.GET.get('language','') == "":
  384 + start_date = datetime.datetime.now() - datetime.timedelta(30)
  385 + end_date = datetime.datetime.now()
  386 + else :
  387 + start_date = datetime.datetime.strptime(self.request.GET.get('init_date',''),date_format)
  388 + end_date = datetime.datetime.strptime(self.request.GET.get('end_date',''),date_format)
  389 + context["init_date"] = start_date
  390 + context["end_date"] = end_date
  391 + alunos = link.students.all()
  392 + if link.all_students :
  393 + alunos = link.topic.subject.students.all()
  394 +
  395 + vis_ou = Log.objects.filter(context__contains={'link_id':link.id},resource="link",action="view",user_email__in=(aluno.email for aluno in alunos), datetime__range=(start_date,end_date + datetime.timedelta(minutes = 1)))
  396 + did,n_did,history = str(_("Realized")),str(_("Unrealized")),str(_("Historic"))
  397 + re = []
  398 + data_n_did,data_history = [],[]
  399 + json_n_did, json_history = {},{}
  400 +
  401 + from django.db.models import Count, Max
  402 + views_user = vis_ou.values("user_email").annotate(views=Count("user_email"))
  403 + date_last = vis_ou.values("user_email").annotate(last=Max("datetime"))
  404 +
  405 + for log_al in vis_ou.order_by("datetime"):
  406 + data_history.append([str(alunos.get(email=log_al.user_email)),
  407 + ", ".join([str(x) for x in link.topic.subject.group_subject.filter(participants__email=log_al.user_email)]),
  408 + log_al.action,log_al.datetime])
  409 + json_history["data"] = data_history
  410 +
  411 + not_view = alunos.exclude(email__in=[log.user_email for log in vis_ou.distinct("user_email")])
  412 + index = 0
  413 + for alun in not_view:
  414 + data_n_did.append([index,str(alun),", ".join([str(x) for x in link.topic.subject.group_subject.filter(participants__email=alun.email)]),str(_('View')), str(alun.email)])
  415 + index += 1
  416 + json_n_did["data"] = data_n_did
  417 +
  418 +
  419 + context["json_n_did"] = json_n_did
  420 + context["json_history"] = json_history
  421 + c_visualizou = vis_ou.distinct("user_email").count()
  422 + column_view = str(_('View'))
  423 + re.append([str(_('Links')),did,n_did])
  424 + re.append([column_view,c_visualizou, alunos.count() - c_visualizou])
  425 + context['topic'] = link.topic
  426 + context['subject'] = link.topic.subject
  427 + context['db_data'] = re
  428 + context['title_chart'] = _('Actions about resource')
  429 + context['title_vAxis'] = _('Quantity')
  430 + context['view'] = column_view
  431 + context["n_did_table"] = n_did
  432 + context["did_table"] = did
  433 + context["history_table"] = history
  434 + return context
  435 +
  436 +
  437 +
  438 +class SendMessage(LoginRequiredMixin, LogMixin, generic.edit.FormView):
  439 + log_component = 'resources'
  440 + log_action = 'send'
  441 + log_resource = 'link'
  442 + log_context = {}
  443 +
  444 + login_url = reverse_lazy("users:login")
  445 + redirect_field_name = 'next'
  446 +
  447 + template_name = 'links/send_message.html'
  448 + form_class = FormModalMessage
  449 +
  450 + def dispatch(self, request, *args, **kwargs):
  451 + slug = self.kwargs.get('slug', '')
  452 + link = get_object_or_404(Link, slug = slug)
  453 + self.link = link
  454 +
  455 + if not has_subject_permissions(request.user, link.topic.subject):
  456 + return redirect(reverse_lazy('subjects:home'))
  457 +
  458 + return super(SendMessage, self).dispatch(request, *args, **kwargs)
  459 +
  460 + def form_valid(self, form):
  461 + message = form.cleaned_data.get('comment')
  462 + image = form.cleaned_data.get("image")
  463 + users = (self.request.POST.get('users[]','')).split(",")
  464 + user = self.request.user
  465 + subject = self.link.topic.subject
  466 + for u in users:
  467 + to_user = User.objects.get(email=u)
  468 + talk, create = Conversation.objects.get_or_create(user_one=user,user_two=to_user)
  469 + created = TalkMessages.objects.create(text=message,talk=talk,user=user,subject=subject,image=image)
  470 + return JsonResponse({"message":"ok"})
  471 +
  472 + def get_context_data(self, **kwargs):
  473 + context = super(SendMessage,self).get_context_data()
  474 + context["link"] = get_object_or_404(Link, slug=self.kwargs.get('slug', ''))
  475 + return context
  476 +
pdf_file/locale/pt_BR/LC_MESSAGES/django.po
@@ -8,7 +8,7 @@ msgid &quot;&quot; @@ -8,7 +8,7 @@ msgid &quot;&quot;
8 msgstr "" 8 msgstr ""
9 "Project-Id-Version: PACKAGE VERSION\n" 9 "Project-Id-Version: PACKAGE VERSION\n"
10 "Report-Msgid-Bugs-To: \n" 10 "Report-Msgid-Bugs-To: \n"
11 -"POT-Creation-Date: 2017-04-28 20:39-0300\n" 11 +"POT-Creation-Date: 2017-05-05 17:16-0300\n"
12 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" 12 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
13 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" 13 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
14 "Language-Team: LANGUAGE <LL@li.org>\n" 14 "Language-Team: LANGUAGE <LL@li.org>\n"
@@ -76,7 +76,7 @@ msgstr &quot;Ação não permitida pelo usuário&quot; @@ -76,7 +76,7 @@ msgstr &quot;Ação não permitida pelo usuário&quot;
76 76
77 #: templates/pdf_file/_form.html:161 77 #: templates/pdf_file/_form.html:161
78 msgid "Wished period" 78 msgid "Wished period"
79 -msgstr "" 79 +msgstr "Período desejado"
80 80
81 #: templates/pdf_file/_form.html:257 81 #: templates/pdf_file/_form.html:257
82 msgid "Attribute students to file link" 82 msgid "Attribute students to file link"
@@ -94,45 +94,73 @@ msgstr &quot;Salvar&quot; @@ -94,45 +94,73 @@ msgstr &quot;Salvar&quot;
94 msgid "Create PDF file" 94 msgid "Create PDF file"
95 msgstr "Criar arquivo PDF" 95 msgstr "Criar arquivo PDF"
96 96
97 -#: templates/pdf_file/relatorios.html:16 templates/pdf_file/relatorios.html:30  
98 -#: templates/pdf_file/relatorios.html:37 97 +#: templates/pdf_file/relatorios.html:17 templates/pdf_file/relatorios.html:37
99 msgid "User" 98 msgid "User"
100 msgstr "Usuário" 99 msgstr "Usuário"
101 100
102 -#: templates/pdf_file/relatorios.html:16 templates/pdf_file/relatorios.html:30  
103 -#: templates/pdf_file/relatorios.html:37 101 +#: templates/pdf_file/relatorios.html:17 templates/pdf_file/relatorios.html:37
104 msgid "Group" 102 msgid "Group"
105 msgstr "Grupo" 103 msgstr "Grupo"
106 104
107 -#: templates/pdf_file/relatorios.html:16 templates/pdf_file/relatorios.html:30 105 +#: templates/pdf_file/relatorios.html:17
108 msgid "Action" 106 msgid "Action"
109 msgstr "Ação" 107 msgstr "Ação"
110 108
111 -#: templates/pdf_file/relatorios.html:16 templates/pdf_file/relatorios.html:30 109 +#: templates/pdf_file/relatorios.html:17
112 msgid "Date of Action" 110 msgid "Date of Action"
113 msgstr "Data da ação" 111 msgstr "Data da ação"
114 112
115 -#: templates/pdf_file/relatorios.html:135  
116 -#: templates/pdf_file/relatorios.html:155 113 +#: templates/pdf_file/relatorios.html:37
  114 +msgid "Send message"
  115 +msgstr "Enviar Mensagem"
  116 +
  117 +#: templates/pdf_file/relatorios.html:37
  118 +#| msgid "Actions about resource"
  119 +msgid "Action don't realized"
  120 +msgstr "Ação não realizada"
  121 +
  122 +#: templates/pdf_file/relatorios.html:151
  123 +#: templates/pdf_file/relatorios.html:171
117 msgid "Reports" 124 msgid "Reports"
118 msgstr "Relatórios" 125 msgstr "Relatórios"
119 126
120 -#: templates/pdf_file/relatorios.html:162 127 +#: templates/pdf_file/relatorios.html:178
121 msgid "Report of the resource " 128 msgid "Report of the resource "
122 msgstr "Relatórios do recurso " 129 msgstr "Relatórios do recurso "
123 130
124 -#: templates/pdf_file/relatorios.html:165 131 +#: templates/pdf_file/relatorios.html:187
125 msgid "Select the period: " 132 msgid "Select the period: "
126 msgstr "Selecione o período: " 133 msgstr "Selecione o período: "
127 134
128 -#: templates/pdf_file/relatorios.html:178 135 +#: templates/pdf_file/relatorios.html:196
129 msgid "Search" 136 msgid "Search"
130 msgstr "Pesquisar" 137 msgstr "Pesquisar"
131 138
132 -#: templates/pdf_file/relatorios.html:200 139 +#: templates/pdf_file/relatorios.html:220
133 msgid "Filter: " 140 msgid "Filter: "
134 msgstr "Filtro: " 141 msgstr "Filtro: "
135 142
  143 +#: templates/pdf_file/relatorios.html:244
  144 +#: templates/pdf_file/relatorios.html:329
  145 +msgid "record(s)"
  146 +msgstr "Relatório(s)"
  147 +
  148 +#: templates/pdf_file/send_message.html:38
  149 +msgid "Click or drop the picture here"
  150 +msgstr "Clique ou arraste a imagem aqui"
  151 +
  152 +#: templates/pdf_file/send_message.html:40
  153 +msgid "The picture could not exceed 5MB."
  154 +msgstr "A imagem não pode exceder 5MB."
  155 +
  156 +#: templates/pdf_file/send_message.html:62
  157 +msgid "Close"
  158 +msgstr "Fechar"
  159 +
  160 +#: templates/pdf_file/send_message.html:63
  161 +msgid "Send"
  162 +msgstr "Enviar"
  163 +
136 #: templates/pdf_file/update.html:20 164 #: templates/pdf_file/update.html:20
137 msgid "Edit: " 165 msgid "Edit: "
138 msgstr "Editar: " 166 msgstr "Editar: "
@@ -141,16 +169,16 @@ msgstr &quot;Editar: &quot; @@ -141,16 +169,16 @@ msgstr &quot;Editar: &quot;
141 msgid "PDF could not be displayed" 169 msgid "PDF could not be displayed"
142 msgstr "PDF não pode ser mostrado" 170 msgstr "PDF não pode ser mostrado"
143 171
144 -#: views.py:112 views.py:125 views.py:236 views.py:238 views.py:254  
145 -#: views.py:256 172 +#: views.py:116 views.py:129 views.py:240 views.py:242 views.py:258
  173 +#: views.py:260
146 msgid "Visualize" 174 msgid "Visualize"
147 msgstr "Visualizar" 175 msgstr "Visualizar"
148 176
149 -#: views.py:185 177 +#: views.py:189
150 msgid "Create PDF File" 178 msgid "Create PDF File"
151 msgstr "Criar o arquivo PDF" 179 msgstr "Criar o arquivo PDF"
152 180
153 -#: views.py:196 181 +#: views.py:200
154 #, python-format 182 #, python-format
155 msgid "" 183 msgid ""
156 "The PDF File \"%s\" was added to the Topic \"%s\" of the virtual environment " 184 "The PDF File \"%s\" was added to the Topic \"%s\" of the virtual environment "
@@ -159,50 +187,59 @@ msgstr &quot;&quot; @@ -159,50 +187,59 @@ msgstr &quot;&quot;
159 "O arquivo PDF \"%s\" foi adicionado ao topico \"%s\" do ambiente virtual " 187 "O arquivo PDF \"%s\" foi adicionado ao topico \"%s\" do ambiente virtual "
160 "\"%s\" com sucesso!" 188 "\"%s\" com sucesso!"
161 189
162 -#: views.py:300 190 +#: views.py:304
163 msgid "Update PDF File" 191 msgid "Update PDF File"
164 msgstr "Atualize arquivo PDF" 192 msgstr "Atualize arquivo PDF"
165 193
166 -#: views.py:311 194 +#: views.py:315
167 #, python-format 195 #, python-format
168 msgid "The PDF File \"%s\" was updated successfully!" 196 msgid "The PDF File \"%s\" was updated successfully!"
169 msgstr "O arquivo PDF \"%s\" foi atualizado com sucesso!" 197 msgstr "O arquivo PDF \"%s\" foi atualizado com sucesso!"
170 198
171 -#: views.py:338 199 +#: views.py:342
172 #, python-format 200 #, python-format
173 msgid "" 201 msgid ""
174 "The PDF File \"%s\" was removed successfully from virtual environment \"%s\"!" 202 "The PDF File \"%s\" was removed successfully from virtual environment \"%s\"!"
175 msgstr "" 203 msgstr ""
176 "O arquivo PDF \"%s\" foi removido com sucesso do ambiente virtual \"%s\" " 204 "O arquivo PDF \"%s\" foi removido com sucesso do ambiente virtual \"%s\" "
177 205
178 -#: views.py:396 206 +#: views.py:400
179 msgid "PDF File Reports" 207 msgid "PDF File Reports"
180 msgstr "Relatórios do arquivo de PDF" 208 msgstr "Relatórios do arquivo de PDF"
181 209
182 -#: views.py:414  
183 -msgid "Users who viewed"  
184 -msgstr "Usuário que visualizaram" 210 +#: views.py:420
  211 +msgid "Realized"
  212 +msgstr "Realizado"
185 213
186 -#: views.py:414  
187 -msgid "Users who did not viewed"  
188 -msgstr "Usuários que não visualizaram" 214 +#: views.py:420
  215 +msgid "Unrealized"
  216 +msgstr "Não Realizado"
189 217
190 -#: views.py:414 218 +#: views.py:420
191 msgid "Historic" 219 msgid "Historic"
192 msgstr "Histórico" 220 msgstr "Histórico"
193 221
194 -#: views.py:446  
195 -msgid "PDF File"  
196 -msgstr "Criar o arquivo PDF"  
197 -  
198 -#: views.py:447 222 +#: views.py:439 views.py:448
199 msgid "View" 223 msgid "View"
200 msgstr "Visualizar" 224 msgstr "Visualizar"
201 225
202 -#: views.py:451  
203 -msgid "Students viewing the PDF File"  
204 -msgstr "Estudantes que visualizaram o arquivo PDF" 226 +#: views.py:447
  227 +msgid "PDF File"
  228 +msgstr "Criar o arquivo PDF"
205 229
206 #: views.py:452 230 #: views.py:452
  231 +msgid "Actions about resource"
  232 +msgstr "Ações sobre o recurso"
  233 +
  234 +#: views.py:453
207 msgid "Quantity" 235 msgid "Quantity"
208 msgstr "Quantidade" 236 msgstr "Quantidade"
  237 +
  238 +#~ msgid "Users who viewed"
  239 +#~ msgstr "Usuário que visualizaram"
  240 +
  241 +#~ msgid "Users who did not viewed"
  242 +#~ msgstr "Usuários que não visualizaram"
  243 +
  244 +#~ msgid "Students viewing the PDF File"
  245 +#~ msgstr "Estudantes que visualizaram o arquivo PDF"
pdf_file/templates/pdf_file/relatorios.html
@@ -11,7 +11,7 @@ @@ -11,7 +11,7 @@
11 11
12 var array_history = []; 12 var array_history = [];
13 {%for data_json in json_history.data%} 13 {%for data_json in json_history.data%}
14 - array_history.push(["{{data_json.0}}","{{data_json.1}}","{{data_json.2}}",{% if data_json.3 is not None %}new Date('{{data_json.3.isoformat}}'){% else%}null{% endif %}]); 14 + array_history.push(["{{data_json.0}}","{{data_json.1}}","{{view}}",{% if data_json.3 is not None %}new Date('{{data_json.3.isoformat}}'){% else%}null{% endif %}]);
15 {% endfor%} 15 {% endfor%}
16 var json_history = {"data":array_history}; 16 var json_history = {"data":array_history};
17 var column_history = [{"string":"{% trans 'User' %}"},{"string":"{% trans 'Group' %}"},{"string":"{% trans 'Action' %}"},{"date":"{% trans 'Date of Action' %}"}]; 17 var column_history = [{"string":"{% trans 'User' %}"},{"string":"{% trans 'Group' %}"},{"string":"{% trans 'Action' %}"},{"date":"{% trans 'Date of Action' %}"}];
@@ -34,7 +34,7 @@ @@ -34,7 +34,7 @@
34 array_n_did.push([input,"{{data_json.1}}","{{data_json.2}}", "{{data_json.3}}"]); 34 array_n_did.push([input,"{{data_json.1}}","{{data_json.2}}", "{{data_json.3}}"]);
35 {% endfor%} 35 {% endfor%}
36 var json_n_did = {"data":array_n_did}; 36 var json_n_did = {"data":array_n_did};
37 - var column_n_did = [{"string":'<a href="javascript:void(0);" onclick="return openmodal();"> {% trans "Send message" %}</a>'},{"string":'{% trans "User" %}'},{"string":'{% trans "Group" %}'},{"string":"Action don't realized"}]; 37 + var column_n_did = [{"string":'<a href="javascript:void(0);" onclick="return openmodal();"> {% trans "Send message" %}</a>'},{"string":'{% trans "User" %}'},{"string":'{% trans "Group" %}'},{"string":"{% trans "Action don't realized" %}"}];
38 </script> 38 </script>
39 39
40 40
@@ -138,6 +138,7 @@ @@ -138,6 +138,7 @@
138 table.draw(data_table, options); 138 table.draw(data_table, options);
139 } 139 }
140 } 140 }
  141 +
141 var table = new google.visualization.Table(document.getElementById('table_div')); 142 var table = new google.visualization.Table(document.getElementById('table_div'));
142 google.visualization.events.addListener(table, 'sort', function(e) {ordenar(e)}); 143 google.visualization.events.addListener(table, 'sort', function(e) {ordenar(e)});
143 table.draw(data_table, options); 144 table.draw(data_table, options);
@@ -205,13 +206,13 @@ @@ -205,13 +206,13 @@
205 </div> 206 </div>
206 </div> 207 </div>
207 208
208 - <div class="row"> 209 + <div class="row">
209 <div class="col-md-10 col-md-offset-1"> 210 <div class="col-md-10 col-md-offset-1">
210 <div class="text-center"> 211 <div class="text-center">
211 <ul class="list-inline nav-justified"> 212 <ul class="list-inline nav-justified">
212 <li> 213 <li>
213 <ul id="view-table" class="list-inline text-right"> 214 <ul id="view-table" class="list-inline text-right">
214 - <li><h3 id="title-table">{{history_table}}</h3></li> 215 + <li><h3 id="title-table"></h3></li>
215 </ul> 216 </ul>
216 </li> 217 </li>
217 <li> 218 <li>
@@ -222,8 +223,9 @@ @@ -222,8 +223,9 @@
222 </li> 223 </li>
223 </ul> 224 </ul>
224 </div> 225 </div>
225 -  
226 - <div id="table_div"></div> 226 + <form id="google-chart-checkbox" action="" method="get">
  227 + <div id="table_div"></div>
  228 + </form>
227 <div class="col-md-12 col-lg-12 col-sm-12 col-xs-12 text-center"> 229 <div class="col-md-12 col-lg-12 col-sm-12 col-xs-12 text-center">
228 <ul class="pagination"> 230 <ul class="pagination">
229 231
@@ -231,44 +233,14 @@ @@ -231,44 +233,14 @@
231 </div> 233 </div>
232 </div> 234 </div>
233 </div> 235 </div>
234 - <!-- Modal (remember to change the ids!!!) -->  
235 - <div class="modal fade" id="send-message-modal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">  
236 - <div class="modal-dialog" role="document">  
237 - <div class="modal-content">  
238 - <!-- Modal Body -->  
239 - <div class="modal-body">  
240 - <!-- Put ONLY your content here!!! -->  
241 - <h3>{% trans "Message: " %}</h3>  
242 - <form id="text_chat_form" action="" method="GET">  
243 - <textarea id="message" name="message" rows="5" cols="80"></textarea>  
244 - </form>  
245 - </div>  
246 - <!-- Modal Footer -->  
247 - <div id="delete-category-footer"class="modal-footer">  
248 - <!-- Don't remove that!!! -->  
249 - <button type="button" class="btn btn-default btn-raised" data-dismiss="modal">{% trans "Close" %}</button>  
250 - <a href="javascript:void(0)" onclick="return sendMessage()" form="text_chat_form" class="btn btn-success btn-raised erase-button">{% trans "Send" %}</a>  
251 - </div>  
252 - </div>  
253 - </div>  
254 - </div>  
255 - 236 + <div id="modal-message"></div>
256 <div class="row"> 237 <div class="row">
257 <br><br> 238 <br><br>
258 </div> 239 </div>
259 </div> 240 </div>
260 241
261 <script type="text/javascript"> 242 <script type="text/javascript">
262 - $('#message').summernote({  
263 - dialogsInBody: true,  
264 - disableDragAndDrop: true,  
265 - height: 150,  
266 - toolbar: [  
267 - // [groupName, [list of button]]  
268 - ['style', ['bold', 'italic']],  
269 - ['insert', ['link']]  
270 - ]  
271 - }); 243 +
272 $("#title-table").text(search.length + " {% trans 'record(s)' %}"); 244 $("#title-table").text(search.length + " {% trans 'record(s)' %}");
273 function putpagination(data = json_history["data"], load_histoty = true){ 245 function putpagination(data = json_history["data"], load_histoty = true){
274 var len = Math.ceil(data.length / 20); 246 var len = Math.ceil(data.length / 20);
@@ -384,6 +356,15 @@ @@ -384,6 +356,15 @@
384 $(".active").removeClass("active"); 356 $(".active").removeClass("active");
385 $("#" + pag).addClass("active"); 357 $("#" + pag).addClass("active");
386 } 358 }
  359 +
  360 + function openmodal(){
  361 + $( "#modal-message" ).empty();
  362 + $.get( "{% url 'pdf_files:send_message' pdf_file.slug %}", function( data ) {
  363 + $( "#modal-message" ).append( data );
  364 + $("#send-message-modal").modal("show");
  365 + });
  366 + }
  367 +
387 function sendMessage(){ 368 function sendMessage(){
388 $("#send-message-modal").modal("hide"); 369 $("#send-message-modal").modal("hide");
389 var checked = $("#google-chart-checkbox").serializeArray(); 370 var checked = $("#google-chart-checkbox").serializeArray();
@@ -391,19 +372,36 @@ @@ -391,19 +372,36 @@
391 for (var i in checked){ 372 for (var i in checked){
392 email.push(checkbox[checked[i]["name"]]); 373 email.push(checkbox[checked[i]["name"]]);
393 } 374 }
394 - var message = $("#text_chat_form").serializeArray()[0]["value"]; 375 + $('<input />').attr('type', 'hidden')
  376 + .attr('name', "users[]")
  377 + .attr('value', email)
  378 + .appendTo('#text_chat_form');
  379 +
  380 + var formData = new FormData($('#text_chat_form').get(0));
395 $.ajax({ 381 $.ajax({
396 - type: "GET",  
397 - data: {"message":message,"users[]":email},  
398 - url: "{% url 'pdf_files:send_message' subject.slug %}",  
399 - success: function(msg){  
400 - console.log(msg);  
401 - $('#message').summernote("reset");  
402 - }  
403 - });  
404 - }  
405 - function openmodal(){  
406 - $("#send-message-modal").modal("show"); 382 + url: "{% url 'pdf_files:send_message' pdf_file.slug %}",
  383 + type: "POST",
  384 + data: formData,
  385 + cache: false,
  386 + processData: false,
  387 + contentType: false,
  388 + success: function(data) {
  389 + if (data["message"]){
  390 + console.log("success");
  391 + $("body").removeClass("modal-open");
  392 + $( "#modal-message" ).empty();
  393 + $(".modal-backdrop.fade.in").remove();
  394 + } else {
  395 + $( "#modal-message" ).empty();
  396 + $(".modal-backdrop.fade.in").remove();
  397 + $( "#modal-message" ).append( data );
  398 + $("#send-message-modal").modal("show");
  399 + }
  400 + },
  401 + error: function(data){
  402 + console.log("erro");
  403 + }
  404 + });
407 } 405 }
408 </script> 406 </script>
409 {% endblock %} 407 {% endblock %}
pdf_file/templates/pdf_file/send_message.html 0 → 100644
@@ -0,0 +1,112 @@ @@ -0,0 +1,112 @@
  1 +
  2 + {% load widget_tweaks i18n %}
  3 + <!-- Modal (remember to change the ids!!!) -->
  4 +<div class="modal fade" id="send-message-modal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
  5 + <div class="modal-dialog" role="document">
  6 + <div class="modal-content">
  7 + <!-- Modal Body -->
  8 + <div class="modal-body">
  9 + <form id="text_chat_form" action="" method="POST" enctype="multipart/form-data">
  10 + {% csrf_token %}
  11 + {% comment %}Area para o Texto{% endcomment %}
  12 + <div class="form-group{% if form.has_error %} has-error {% endif %}">
  13 + <label for="{{ form.comment.auto_id }}">{{ form.comment.label }}: <span>*</span></label>
  14 + {% render_field form.comment class='form-control text_simple_wysiwyg' %}
  15 +
  16 + <span id="helpBlock" class="help-block">{{ form.comment.help_text }}</span>
  17 +
  18 + {% if form.comment.errors %}
  19 + <div class="alert alert-danger alert-dismissible" role="alert">
  20 + <button type="button" class="close" data-dismiss="alert" aria-label="Close">
  21 + <span aria-hidden="true">&times;</span>
  22 + </button>
  23 + <ul>
  24 + {% for error in form.comment.errors %}
  25 + <li>{{ error }}</li>
  26 + {% endfor %}
  27 + </ul>
  28 + </div>
  29 + {% endif %}
  30 + </div>
  31 + {% comment %}Area para anexar a imagem {% endcomment %}
  32 + <div class="form-group{% if form.has_error %} has-error {% endif %} is-fileinput">
  33 + {% render_field form.image %}
  34 +
  35 + <div class="filedrag">
  36 + {% trans 'Click or drop the picture here' %}<br />
  37 +
  38 + <small>{% trans 'The picture could not exceed 5MB.' %}</small>
  39 + </div>
  40 +
  41 + {% if form.image.errors %}
  42 + <div class="alert alert-danger alert-dismissible" role="alert">
  43 + <button type="button" class="close" data-dismiss="alert" aria-label="Close">
  44 + <span aria-hidden="true">&times;</span>
  45 + </button>
  46 + <ul>
  47 + {% for error in form.image.errors %}
  48 + <li>{{ error }}</li>
  49 + {% endfor %}
  50 + </ul>
  51 + </div>
  52 + {% endif %}
  53 +
  54 + </div>
  55 + </form>
  56 + </div>
  57 + <!-- Modal Footer -->
  58 + <div id="delete-category-footer"class="modal-footer">
  59 + <!-- Don't remove that!!! -->
  60 + <button type="button" class="btn btn-default btn-raised" data-dismiss="modal">{% trans "Close" %}</button>
  61 + <a href="javascript:void(0)" onclick="return sendMessage()" form="text_chat_form" class="btn btn-success btn-raised erase-button">{% trans "Send" %}</a>
  62 + </div>
  63 + </div>
  64 + </div>
  65 +</div>
  66 +
  67 +<script type="text/javascript">
  68 +
  69 + $('.text_simple_wysiwyg').summernote({
  70 + dialogsInBody: true,
  71 + disableDragAndDrop: true,
  72 + height: 150,
  73 + toolbar: [
  74 + // [groupName, [list of button]]
  75 + ['style', ['bold', 'italic']],
  76 + ['insert', ['link']]
  77 + ]
  78 + });
  79 +
  80 + if (window.File && window.FileList && window.FileReader) {
  81 + Init();
  82 + }
  83 +
  84 + function Init() {
  85 + var small = $("#id_image"),
  86 + filedrag = $(".filedrag"),
  87 + common = $(".common-file-input");
  88 +
  89 + // file select
  90 + small.on("change", FileSelectHandler);
  91 +
  92 + // is XHR2 available?
  93 + var xhr = new XMLHttpRequest();
  94 + if (xhr.upload) {
  95 + // file drop
  96 + filedrag.on("drop", FileSelectHandler);
  97 + filedrag.attr('style', 'display:block');
  98 + common.attr('style', 'display:none');
  99 + }
  100 + }
  101 +
  102 + // file selection
  103 + function FileSelectHandler(e) {
  104 + var files = e.target.files || e.dataTransfer.files,
  105 + parent = $(e.target.offsetParent);
  106 +
  107 + // process all File objects
  108 + for (var i = 0, f; f = files[i]; i++) {
  109 + parent.find('.filedrag').html(f.name);
  110 + }
  111 + }
  112 +</script>
0 \ No newline at end of file 113 \ No newline at end of file
pdf_file/urls.py
@@ -4,10 +4,10 @@ from django.contrib.auth import views as auth_views @@ -4,10 +4,10 @@ from django.contrib.auth import views as auth_views
4 from . import views 4 from . import views
5 5
6 urlpatterns = [ 6 urlpatterns = [
7 - url(r'^create/(?P<slug>[\w_-]+)/$', views.PDFFileCreateView.as_view(), name='create'),  
8 - url(r'^update/(?P<topic_slug>[\w_-]+)/(?P<slug>[\w_-]+)/$', views.UpdateView.as_view(), name = 'update'),  
9 - url(r'^delete/(?P<slug>[\w_-]+)/$', views.DeleteView.as_view(), name = 'delete'),  
10 - url(r'^view/(?P<slug>[\w_-]+)/$', views.ViewPDFFile.as_view(), name = 'view'),  
11 - url(r'^chart/(?P<slug>[\w_-]+)/$', views.StatisticsView.as_view(), name = 'get_chart'),  
12 - url(r'^send-message/(?P<slug>[\w_-]+)/$', views.sendMessage, name = 'send_message'), 7 + url(r'^create/(?P<slug>[\w_-]+)/$', views.PDFFileCreateView.as_view(), name='create'),
  8 + url(r'^update/(?P<topic_slug>[\w_-]+)/(?P<slug>[\w_-]+)/$', views.UpdateView.as_view(), name = 'update'),
  9 + url(r'^delete/(?P<slug>[\w_-]+)/$', views.DeleteView.as_view(), name = 'delete'),
  10 + url(r'^view/(?P<slug>[\w_-]+)/$', views.ViewPDFFile.as_view(), name = 'view'),
  11 + url(r'^chart/(?P<slug>[\w_-]+)/$', views.StatisticsView.as_view(), name = 'get_chart'),
  12 + url(r'^send-message/(?P<slug>[\w_-]+)/$', views.SendMessage.as_view(), name = 'send_message'),
13 ] 13 ]
pdf_file/views.py
@@ -19,6 +19,10 @@ from topics.models import Topic, Resource @@ -19,6 +19,10 @@ from topics.models import Topic, Resource
19 from .models import PDFFile 19 from .models import PDFFile
20 from pendencies.forms import PendenciesForm 20 from pendencies.forms import PendenciesForm
21 21
  22 +from chat.models import Conversation, TalkMessages
  23 +from users.models import User
  24 +from subjects.models import Subject
  25 +from webpage.forms import FormModalMessage
22 26
23 27
24 class ViewPDFFile(LoginRequiredMixin, LogMixin, generic.TemplateView): 28 class ViewPDFFile(LoginRequiredMixin, LogMixin, generic.TemplateView):
@@ -154,9 +158,6 @@ class PDFFileCreateView(LoginRequiredMixin, LogMixin , generic.CreateView): @@ -154,9 +158,6 @@ class PDFFileCreateView(LoginRequiredMixin, LogMixin , generic.CreateView):
154 if not self.object.topic.visible and not self.object.topic.repository: 158 if not self.object.topic.visible and not self.object.topic.repository:
155 self.object.visible = False 159 self.object.visible = False
156 160
157 - if form.cleaned_data["all_students"]:  
158 - self.object.students.add(*self.object.topic.subject.students.all())  
159 -  
160 self.object.save() 161 self.object.save()
161 162
162 pend_form = pendencies_form.save(commit = False) 163 pend_form = pendencies_form.save(commit = False)
@@ -412,6 +413,8 @@ class StatisticsView(LoginRequiredMixin, LogMixin, generic.DetailView): @@ -412,6 +413,8 @@ class StatisticsView(LoginRequiredMixin, LogMixin, generic.DetailView):
412 context["init_date"] = start_date 413 context["init_date"] = start_date
413 context["end_date"] = end_date 414 context["end_date"] = end_date
414 alunos = pdf_file.students.all() 415 alunos = pdf_file.students.all()
  416 + if pdf_file.all_students :
  417 + alunos = pdf_file.topic.subject.students.all()
415 418
416 vis_ou = Log.objects.filter(context__contains={'pdffile_id':pdf_file.id},resource="pdffile",action="view",user_email__in=(aluno.email for aluno in alunos), datetime__range=(start_date,end_date + datetime.timedelta(minutes = 1))) 419 vis_ou = Log.objects.filter(context__contains={'pdffile_id':pdf_file.id},resource="pdffile",action="view",user_email__in=(aluno.email for aluno in alunos), datetime__range=(start_date,end_date + datetime.timedelta(minutes = 1)))
417 did,n_did,history = str(_("Realized")),str(_("Unrealized")),str(_("Historic")) 420 did,n_did,history = str(_("Realized")),str(_("Unrealized")),str(_("Historic"))
@@ -441,32 +444,56 @@ class StatisticsView(LoginRequiredMixin, LogMixin, generic.DetailView): @@ -441,32 +444,56 @@ class StatisticsView(LoginRequiredMixin, LogMixin, generic.DetailView):
441 context["json_n_did"] = json_n_did 444 context["json_n_did"] = json_n_did
442 context["json_history"] = json_history 445 context["json_history"] = json_history
443 c_visualizou = vis_ou.distinct("user_email").count() 446 c_visualizou = vis_ou.distinct("user_email").count()
  447 + column_view = str(_('View'))
444 re.append([str(_('PDF File')),did,n_did]) 448 re.append([str(_('PDF File')),did,n_did])
445 - re.append([str(_('View')),c_visualizou, alunos.count() - c_visualizou]) 449 + re.append([column_view,c_visualizou, alunos.count() - c_visualizou])
446 context['topic'] = pdf_file.topic 450 context['topic'] = pdf_file.topic
447 context['subject'] = pdf_file.topic.subject 451 context['subject'] = pdf_file.topic.subject
448 context['db_data'] = re 452 context['db_data'] = re
449 context['title_chart'] = _('Actions about resource') 453 context['title_chart'] = _('Actions about resource')
450 context['title_vAxis'] = _('Quantity') 454 context['title_vAxis'] = _('Quantity')
451 - 455 + context['view'] = column_view
452 context["n_did_table"] = n_did 456 context["n_did_table"] = n_did
453 context["did_table"] = did 457 context["did_table"] = did
454 context["history_table"] = history 458 context["history_table"] = history
455 return context 459 return context
456 460
  461 +class SendMessage(LoginRequiredMixin, LogMixin, generic.edit.FormView):
  462 + log_component = 'resources'
  463 + log_action = 'send'
  464 + log_resource = 'pdffile'
  465 + log_context = {}
  466 +
  467 + login_url = reverse_lazy("users:login")
  468 + redirect_field_name = 'next'
  469 +
  470 + template_name = 'pdf_file/send_message.html'
  471 + form_class = FormModalMessage
  472 +
  473 + def dispatch(self, request, *args, **kwargs):
  474 + slug = self.kwargs.get('slug', '')
  475 + pdf_file = get_object_or_404(PDFFile, slug = slug)
  476 + self.pdf_file = pdf_file
  477 +
  478 + if not has_subject_permissions(request.user, pdf_file.topic.subject):
  479 + return redirect(reverse_lazy('subjects:home'))
  480 +
  481 + return super(SendMessage, self).dispatch(request, *args, **kwargs)
  482 +
  483 + def form_valid(self, form):
  484 + message = form.cleaned_data.get('comment')
  485 + image = form.cleaned_data.get("image")
  486 + users = (self.request.POST.get('users[]','')).split(",")
  487 + user = self.request.user
  488 + subject = self.pdf_file.topic.subject
  489 + for u in users:
  490 + to_user = User.objects.get(email=u)
  491 + talk, create = Conversation.objects.get_or_create(user_one=user,user_two=to_user)
  492 + created = TalkMessages.objects.create(text=message,talk=talk,user=user,subject=subject,image=image)
  493 + return JsonResponse({"message":"ok"})
  494 +
  495 + def get_context_data(self, **kwargs):
  496 + context = super(SendMessage,self).get_context_data()
  497 + context["pdf_file"] = get_object_or_404(PDFFile, slug=self.kwargs.get('slug', ''))
  498 + return context
457 499
458 -from chat.models import Conversation, TalkMessages  
459 -from users.models import User  
460 -from subjects.models import Subject  
461 -def sendMessage(request, slug):  
462 - message = request.GET.get('message','')  
463 - users = request.GET.getlist('users[]','')  
464 - user = request.user  
465 - subject = get_object_or_404(Subject,slug = slug)  
466 -  
467 - for u in users:  
468 - to_user = User.objects.get(email=u)  
469 - talk, create = Conversation.objects.get_or_create(user_one=user,user_two=to_user)  
470 - created = TalkMessages.objects.create(text=message,talk=talk,user=user,subject=subject)  
471 -  
472 - return JsonResponse({"message":"ok"})  
themes/urls.py
@@ -5,4 +5,5 @@ urlpatterns = [ @@ -5,4 +5,5 @@ urlpatterns = [
5 url(r'^$', views.IndexView.as_view(), name = 'manage'), 5 url(r'^$', views.IndexView.as_view(), name = 'manage'),
6 url(r'^basic_elements$', views.BasicElementsSettings.as_view(), name = 'basic'), 6 url(r'^basic_elements$', views.BasicElementsSettings.as_view(), name = 'basic'),
7 url(r'^css_selector$', views.CSSStyleSettings.as_view(), name = 'css'), 7 url(r'^css_selector$', views.CSSStyleSettings.as_view(), name = 'css'),
  8 + url(r'^contrast$',views.Contrast, name = 'contrast'),
8 ] 9 ]
themes/views.py
@@ -5,7 +5,7 @@ from django.core.urlresolvers import reverse, reverse_lazy @@ -5,7 +5,7 @@ from django.core.urlresolvers import reverse, reverse_lazy
5 from django.utils.translation import ugettext_lazy as _ 5 from django.utils.translation import ugettext_lazy as _
6 from django.http import HttpResponse, JsonResponse, HttpResponseRedirect,HttpRequest 6 from django.http import HttpResponse, JsonResponse, HttpResponseRedirect,HttpRequest
7 from django.shortcuts import redirect 7 from django.shortcuts import redirect
8 - 8 +from log.decorators import log_decorator
9 from braces import views as braces_mixins 9 from braces import views as braces_mixins
10 10
11 from .models import Themes 11 from .models import Themes
@@ -79,3 +79,8 @@ class CSSStyleSettings(braces_mixins.LoginRequiredMixin, braces_mixins.Staffuser @@ -79,3 +79,8 @@ class CSSStyleSettings(braces_mixins.LoginRequiredMixin, braces_mixins.Staffuser
79 context['settings_menu_active'] = "settings_menu_active" 79 context['settings_menu_active'] = "settings_menu_active"
80 80
81 return context 81 return context
  82 +
  83 +@log_decorator("contrast", "click", "contrast")
  84 +def Contrast(request):
  85 + caminho = request.META.get('HTTP_REFERER')
  86 + return HttpResponseRedirect(caminho)
topics/templates/resources/list.html
@@ -29,7 +29,15 @@ @@ -29,7 +29,15 @@
29 </button> 29 </button>
30 <ul class="dropdown-menu pull-right" role="menu" aria-labelledby="moreResources"> 30 <ul class="dropdown-menu pull-right" role="menu" aria-labelledby="moreResources">
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> 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 - 32 + {% if resource|class_name == 'ytvideo' %}
  33 + <li><a href="{% url 'youtube:get_chart' resource.slug %}" class="edit"><i class="fa fa-line-chart fa-fw" aria-hidden="true"></i>{% trans 'Reports' %}</a></li>
  34 + {% endif %}
  35 + {% if resource|class_name == 'link' %}
  36 + <li><a href="{% url 'links:get_chart' resource.slug %}" class="edit"><i class="fa fa-line-chart fa-fw" aria-hidden="true"></i>{% trans 'Reports' %}</a></li>
  37 + {% endif %}
  38 + {% if resource|class_name == 'filelink' %}
  39 + <li><a href="{% url 'file_links:get_chart' resource.slug %}" class="edit"><i class="fa fa-line-chart fa-fw" aria-hidden="true"></i>{% trans 'Reports' %}</a></li>
  40 + {% endif %}
33 {% if resource|class_name == 'webpage' %} 41 {% if resource|class_name == 'webpage' %}
34 <li><a href="{% url 'webpages:get_chart' resource.slug %}" class="edit"><i class="fa fa-line-chart fa-fw" aria-hidden="true"></i>{% trans 'Reports' %}</a></li> 42 <li><a href="{% url 'webpages:get_chart' resource.slug %}" class="edit"><i class="fa fa-line-chart fa-fw" aria-hidden="true"></i>{% trans 'Reports' %}</a></li>
35 {% endif %} 43 {% endif %}
users/templates/users/login.html
@@ -87,7 +87,7 @@ @@ -87,7 +87,7 @@
87 <span >[{{LANGUAGE_CODE}}] </span> 87 <span >[{{LANGUAGE_CODE}}] </span>
88 88
89 </a> 89 </a>
90 - <a href="" id = "contrast_button" style="margin-left:10px;"><i class="glyphicon glyphicon-adjust"></i></a> 90 + <a href="{% url 'themes:contrast' %}" id = "contrast_button" style="margin-left:10px;"><i class="glyphicon glyphicon-adjust"></i></a>
91 <ul class="dropdown-menu"> 91 <ul class="dropdown-menu">
92 92
93 93
@@ -150,11 +150,11 @@ @@ -150,11 +150,11 @@
150 $("#contrast_button" ).click(function() { 150 $("#contrast_button" ).click(function() {
151 if (Cookies.get('contrast_check')) { 151 if (Cookies.get('contrast_check')) {
152 Cookies.remove('contrast_check') 152 Cookies.remove('contrast_check')
153 - location.reload() 153 + //location.reload()
154 } 154 }
155 else { 155 else {
156 Cookies.set('contrast_check','contrast') 156 Cookies.set('contrast_check','contrast')
157 - location.reload() 157 + //location.reload()
158 } 158 }
159 159
160 }); 160 });
webpage/forms.py
@@ -7,91 +7,122 @@ from subjects.models import Tag @@ -7,91 +7,122 @@ from subjects.models import Tag
7 7
8 from .models import Webpage 8 from .models import Webpage
9 9
  10 +from resubmit.widgets import ResubmitFileWidget
  11 +
10 class WebpageForm(forms.ModelForm): 12 class WebpageForm(forms.ModelForm):
11 - subject = None  
12 -  
13 - def __init__(self, *args, **kwargs):  
14 - super(WebpageForm, self).__init__(*args, **kwargs)  
15 -  
16 - self.subject = kwargs['initial'].get('subject', None)  
17 -  
18 - if self.instance.id:  
19 - self.subject = self.instance.topic.subject  
20 - self.initial['tags'] = ", ".join(self.instance.tags.all().values_list("name", flat = True))  
21 -  
22 - self.fields['students'].queryset = self.subject.students.all()  
23 - self.fields['groups'].queryset = self.subject.group_subject.all()  
24 -  
25 - tags = forms.CharField(label = _('Tags'), required = False)  
26 -  
27 - class Meta:  
28 - model = Webpage  
29 - fields = ['name', 'content', 'brief_description', 'all_students', 'students', 'groups', 'show_window', 'visible']  
30 - labels = {  
31 - 'name': _('Webpage name'),  
32 - 'content': _('Webpage content'),  
33 - }  
34 - widgets = {  
35 - 'content': forms.Textarea,  
36 - 'brief_description': forms.Textarea,  
37 - 'students': forms.SelectMultiple,  
38 - 'groups': forms.SelectMultiple,  
39 - }  
40 -  
41 - def clean_name(self):  
42 - name = self.cleaned_data.get('name', '')  
43 -  
44 - topics = self.subject.topic_subject.all()  
45 -  
46 - for topic in topics:  
47 - if self.instance.id:  
48 - same_name = topic.resource_topic.filter(name__unaccent__iexact = name).exclude(id = self.instance.id).count()  
49 - else:  
50 - same_name = topic.resource_topic.filter(name__unaccent__iexact = name).count()  
51 -  
52 - if same_name > 0:  
53 - self._errors['name'] = [_('This subject already has a webpage with this name')]  
54 -  
55 - return ValueError  
56 -  
57 - return name  
58 -  
59 - def clean_content(self):  
60 - content = self.cleaned_data.get('content', '')  
61 - cleaned_content = strip_tags(content)  
62 -  
63 - if cleaned_content == '':  
64 - self._errors['content'] = [_('This field is required.')]  
65 -  
66 - return ValueError  
67 -  
68 - return content  
69 -  
70 - def save(self, commit = True):  
71 - super(WebpageForm, self).save(commit = True)  
72 -  
73 - self.instance.save()  
74 -  
75 - previous_tags = self.instance.tags.all()  
76 -  
77 - tags = self.cleaned_data['tags'].split(",") 13 + subject = None
  14 +
  15 + def __init__(self, *args, **kwargs):
  16 + super(WebpageForm, self).__init__(*args, **kwargs)
  17 +
  18 + self.subject = kwargs['initial'].get('subject', None)
  19 +
  20 + if self.instance.id:
  21 + self.subject = self.instance.topic.subject
  22 + self.initial['tags'] = ", ".join(self.instance.tags.all().values_list("name", flat = True))
  23 +
  24 + self.fields['students'].queryset = self.subject.students.all()
  25 + self.fields['groups'].queryset = self.subject.group_subject.all()
  26 +
  27 + tags = forms.CharField(label = _('Tags'), required = False)
  28 +
  29 + class Meta:
  30 + model = Webpage
  31 + fields = ['name', 'content', 'brief_description', 'all_students', 'students', 'groups', 'show_window', 'visible']
  32 + labels = {
  33 + 'name': _('Webpage name'),
  34 + 'content': _('Webpage content'),
  35 + }
  36 + widgets = {
  37 + 'content': forms.Textarea,
  38 + 'brief_description': forms.Textarea,
  39 + 'students': forms.SelectMultiple,
  40 + 'groups': forms.SelectMultiple,
  41 + }
  42 +
  43 + def clean_name(self):
  44 + name = self.cleaned_data.get('name', '')
  45 +
  46 + topics = self.subject.topic_subject.all()
  47 +
  48 + for topic in topics:
  49 + if self.instance.id:
  50 + same_name = topic.resource_topic.filter(name__unaccent__iexact = name).exclude(id = self.instance.id).count()
  51 + else:
  52 + same_name = topic.resource_topic.filter(name__unaccent__iexact = name).count()
  53 +
  54 + if same_name > 0:
  55 + self._errors['name'] = [_('This subject already has a webpage with this name')]
  56 +
  57 + return ValueError
  58 +
  59 + return name
  60 +
  61 + def clean_content(self):
  62 + content = self.cleaned_data.get('content', '')
  63 + cleaned_content = strip_tags(content)
  64 +
  65 + if cleaned_content == '':
  66 + self._errors['content'] = [_('This field is required.')]
  67 +
  68 + return ValueError
  69 +
  70 + return content
  71 +
  72 + def save(self, commit = True):
  73 + super(WebpageForm, self).save(commit = True)
  74 +
  75 + self.instance.save()
  76 +
  77 + previous_tags = self.instance.tags.all()
  78 +
  79 + tags = self.cleaned_data['tags'].split(",")
78 80
79 #Excluding unwanted tags 81 #Excluding unwanted tags
80 - for prev in previous_tags:  
81 - if not prev.name in tags:  
82 - self.instance.tags.remove(prev) 82 + for prev in previous_tags:
  83 + if not prev.name in tags:
  84 + self.instance.tags.remove(prev)
83 85
84 - for tag in tags:  
85 - tag = tag.strip() 86 + for tag in tags:
  87 + tag = tag.strip()
  88 +
  89 + exist = Tag.objects.filter(name = tag).exists()
  90 +
  91 + if exist:
  92 + new_tag = Tag.objects.get(name = tag)
  93 + else:
  94 + new_tag = Tag.objects.create(name = tag)
  95 +
  96 + if not new_tag in self.instance.tags.all():
  97 + self.instance.tags.add(new_tag)
  98 +
  99 + return self.instance
  100 +
  101 +class FormModalMessage(forms.Form):
  102 + MAX_UPLOAD_SIZE = 5*1024*1024
  103 +
  104 + comment = forms.CharField(widget=forms.Textarea,label=_("Message"))
  105 + image = forms.FileField(widget=ResubmitFileWidget(attrs={'accept':'image/*'}))
  106 +
  107 + def clean_comment(self):
  108 + comment = self.cleaned_data.get('comment', '')
  109 + cleaned_comment = strip_tags(comment)
  110 +
  111 + if cleaned_comment == '':
  112 + self._errors['comment'] = [_('This field is required.')]
  113 +
  114 + return ValueError
  115 +
  116 + return comment
86 117
87 - exist = Tag.objects.filter(name = tag).exists() 118 + def clean_image(self):
  119 + image = self.cleaned_data.get('image', False)
88 120
89 - if exist:  
90 - new_tag = Tag.objects.get(name = tag)  
91 - else:  
92 - new_tag = Tag.objects.create(name = tag) 121 + if image:
  122 + if hasattr(image, '_size'):
  123 + if image._size > self.MAX_UPLOAD_SIZE:
  124 + self._errors['image'] = [_("The image is too large. It should have less than 5MB.")]
93 125
94 - if not new_tag in self.instance.tags.all():  
95 - self.instance.tags.add(new_tag) 126 + return ValueError
96 127
97 - return self.instance  
98 \ No newline at end of file 128 \ No newline at end of file
  129 + return image
99 \ No newline at end of file 130 \ No newline at end of file
webpage/locale/pt_BR/LC_MESSAGES/django.po
@@ -8,7 +8,7 @@ msgid &quot;&quot; @@ -8,7 +8,7 @@ msgid &quot;&quot;
8 msgstr "" 8 msgstr ""
9 "Project-Id-Version: PACKAGE VERSION\n" 9 "Project-Id-Version: PACKAGE VERSION\n"
10 "Report-Msgid-Bugs-To: \n" 10 "Report-Msgid-Bugs-To: \n"
11 -"POT-Creation-Date: 2017-04-28 20:41-0300\n" 11 +"POT-Creation-Date: 2017-05-05 17:59-0300\n"
12 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" 12 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
13 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" 13 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
14 "Language-Team: LANGUAGE <LL@li.org>\n" 14 "Language-Team: LANGUAGE <LL@li.org>\n"
@@ -18,26 +18,35 @@ msgstr &quot;&quot; @@ -18,26 +18,35 @@ msgstr &quot;&quot;
18 "Content-Transfer-Encoding: 8bit\n" 18 "Content-Transfer-Encoding: 8bit\n"
19 "Plural-Forms: nplurals=2; plural=(n > 1);\n" 19 "Plural-Forms: nplurals=2; plural=(n > 1);\n"
20 20
21 -#: forms.py:25 21 +#: forms.py:27
22 msgid "Tags" 22 msgid "Tags"
23 msgstr "Tags" 23 msgstr "Tags"
24 24
25 -#: forms.py:31 25 +#: forms.py:33
26 msgid "Webpage name" 26 msgid "Webpage name"
27 msgstr "Nome da Página Web" 27 msgstr "Nome da Página Web"
28 28
29 -#: forms.py:32 29 +#: forms.py:34
30 msgid "Webpage content" 30 msgid "Webpage content"
31 msgstr "Conteúdo da Página Web" 31 msgstr "Conteúdo da Página Web"
32 32
33 -#: forms.py:53 33 +#: forms.py:55
34 msgid "This subject already has a webpage with this name" 34 msgid "This subject already has a webpage with this name"
35 msgstr "Esse assunto já possui uma Página Web com esse nome" 35 msgstr "Esse assunto já possui uma Página Web com esse nome"
36 36
37 -#: forms.py:64 37 +#: forms.py:66 forms.py:112
38 msgid "This field is required." 38 msgid "This field is required."
39 msgstr "Esse campo é obrigatório." 39 msgstr "Esse campo é obrigatório."
40 40
  41 +#: forms.py:104
  42 +#| msgid "Send message"
  43 +msgid "Message"
  44 +msgstr "Mensagem"
  45 +
  46 +#: forms.py:124
  47 +msgid "The image is too large. It should have less than 5MB."
  48 +msgstr "A imagem é muito grande. Deve ser menor do que 5MB"
  49 +
41 #: models.py:8 50 #: models.py:8
42 msgid "Webpage Content" 51 msgid "Webpage Content"
43 msgstr "Conteúdo da Página Web" 52 msgstr "Conteúdo da Página Web"
@@ -82,59 +91,86 @@ msgstr &quot;Atribuir grupos de estudo à Página Web&quot; @@ -82,59 +91,86 @@ msgstr &quot;Atribuir grupos de estudo à Página Web&quot;
82 msgid "Save" 91 msgid "Save"
83 msgstr "Salvar" 92 msgstr "Salvar"
84 93
85 -#: templates/webpages/create.html:20 views.py:221 94 +#: templates/webpages/create.html:20 views.py:227
86 msgid "Create Webpage" 95 msgid "Create Webpage"
87 msgstr "Criar Página Web" 96 msgstr "Criar Página Web"
88 97
89 -#: templates/webpages/relatorios.html:16 templates/webpages/relatorios.html:30  
90 -#: templates/webpages/relatorios.html:37 98 +#: templates/webpages/relatorios.html:17 templates/webpages/relatorios.html:37
91 msgid "User" 99 msgid "User"
92 msgstr "Usuário" 100 msgstr "Usuário"
93 101
94 -#: templates/webpages/relatorios.html:16 templates/webpages/relatorios.html:30  
95 -#: templates/webpages/relatorios.html:37 102 +#: templates/webpages/relatorios.html:17 templates/webpages/relatorios.html:37
96 msgid "Group" 103 msgid "Group"
97 msgstr "Grupo" 104 msgstr "Grupo"
98 105
99 -#: templates/webpages/relatorios.html:16 templates/webpages/relatorios.html:30 106 +#: templates/webpages/relatorios.html:17
100 msgid "Action" 107 msgid "Action"
101 msgstr "Ação" 108 msgstr "Ação"
102 109
103 -#: templates/webpages/relatorios.html:16 templates/webpages/relatorios.html:30 110 +#: templates/webpages/relatorios.html:17
104 msgid "Date of Action" 111 msgid "Date of Action"
105 msgstr "Data da ação" 112 msgstr "Data da ação"
106 113
107 -#: templates/webpages/relatorios.html:135  
108 -#: templates/webpages/relatorios.html:155 114 +#: templates/webpages/relatorios.html:37
  115 +msgid "Send message"
  116 +msgstr "Enviar Mensagem"
  117 +
  118 +#: templates/webpages/relatorios.html:37
  119 +msgid "Action don't realized"
  120 +msgstr "Ação não realizada"
  121 +
  122 +#: templates/webpages/relatorios.html:151
  123 +#: templates/webpages/relatorios.html:171
109 msgid "Reports" 124 msgid "Reports"
110 msgstr "Relatórios" 125 msgstr "Relatórios"
111 126
112 -#: templates/webpages/relatorios.html:162 127 +#: templates/webpages/relatorios.html:178
113 msgid "Report of the resource " 128 msgid "Report of the resource "
114 msgstr "Relatórios do recurso " 129 msgstr "Relatórios do recurso "
115 130
116 -#: templates/webpages/relatorios.html:165 131 +#: templates/webpages/relatorios.html:187
117 msgid "Select the period: " 132 msgid "Select the period: "
118 msgstr "Selecione o período: " 133 msgstr "Selecione o período: "
119 134
120 -#: templates/webpages/relatorios.html:179 135 +#: templates/webpages/relatorios.html:196
121 msgid "Search" 136 msgid "Search"
122 msgstr "Pesquisar" 137 msgstr "Pesquisar"
123 138
124 -#: templates/webpages/relatorios.html:201 139 +#: templates/webpages/relatorios.html:220
125 msgid "Filter: " 140 msgid "Filter: "
126 msgstr "Filtro: " 141 msgstr "Filtro: "
127 142
  143 +#: templates/webpages/relatorios.html:244
  144 +#: templates/webpages/relatorios.html:329
  145 +msgid "record(s)"
  146 +msgstr "Relatório(s)"
  147 +
  148 +#: templates/webpages/send_message.html:38
  149 +msgid "Click or drop the picture here"
  150 +msgstr "Clique ou solte a imagem aqui"
  151 +
  152 +#: templates/webpages/send_message.html:40
  153 +msgid "The picture could not exceed 5MB."
  154 +msgstr "A imagem não pode exceder 5MB."
  155 +
  156 +#: templates/webpages/send_message.html:62
  157 +msgid "Close"
  158 +msgstr "Fechar"
  159 +
  160 +#: templates/webpages/send_message.html:63
  161 +msgid "Send"
  162 +msgstr "Enviar"
  163 +
128 #: templates/webpages/update.html:20 164 #: templates/webpages/update.html:20
129 msgid "Edit: " 165 msgid "Edit: "
130 msgstr "Editar: " 166 msgstr "Editar: "
131 167
132 -#: views.py:148 views.py:161 views.py:279 views.py:281 views.py:297  
133 -#: views.py:299 168 +#: views.py:155 views.py:168 views.py:285 views.py:287 views.py:303
  169 +#: views.py:305
134 msgid "Visualize" 170 msgid "Visualize"
135 msgstr "Visualizar" 171 msgstr "Visualizar"
136 172
137 -#: views.py:232 173 +#: views.py:238
138 #, python-format 174 #, python-format
139 msgid "" 175 msgid ""
140 "The Webpage \"%s\" was added to the Topic \"%s\" of the virtual environment " 176 "The Webpage \"%s\" was added to the Topic \"%s\" of the virtual environment "
@@ -143,50 +179,59 @@ msgstr &quot;&quot; @@ -143,50 +179,59 @@ msgstr &quot;&quot;
143 "A Página Web \"%s\" foi adicionado ao tópico \"%s\" do ambiente virtual \"%s" 179 "A Página Web \"%s\" foi adicionado ao tópico \"%s\" do ambiente virtual \"%s"
144 "\" com sucesso!" 180 "\" com sucesso!"
145 181
146 -#: views.py:343 182 +#: views.py:349
147 msgid "Update Webpage" 183 msgid "Update Webpage"
148 msgstr "Atualizar Página Web" 184 msgstr "Atualizar Página Web"
149 185
150 -#: views.py:354 186 +#: views.py:360
151 #, python-format 187 #, python-format
152 msgid "The Webpage \"%s\" was updated successfully!" 188 msgid "The Webpage \"%s\" was updated successfully!"
153 msgstr "A Página Web \"%s\" foi atualizada com sucesso!" 189 msgstr "A Página Web \"%s\" foi atualizada com sucesso!"
154 190
155 -#: views.py:390 191 +#: views.py:396
156 #, python-format 192 #, python-format
157 msgid "" 193 msgid ""
158 "The webpage \"%s\" was removed successfully from virtual environment \"%s\"!" 194 "The webpage \"%s\" was removed successfully from virtual environment \"%s\"!"
159 msgstr "" 195 msgstr ""
160 "A Página Web \"%s\" foi removida do ambiente virtual \"%s\" com sucesso!" 196 "A Página Web \"%s\" foi removida do ambiente virtual \"%s\" com sucesso!"
161 197
162 -#: views.py:460 198 +#: views.py:455
163 msgid "Webpage Reports" 199 msgid "Webpage Reports"
164 -msgstr "Nome da Página Web" 200 +msgstr "Relatórios da Webpage"
165 201
166 -#: views.py:478  
167 -msgid "Users who viewed"  
168 -msgstr "Usuários que visualizaram" 202 +#: views.py:474
  203 +msgid "Realized"
  204 +msgstr "Realizado"
169 205
170 -#: views.py:478  
171 -msgid "Users who did not viewed"  
172 -msgstr "Usuários que não visualizaram" 206 +#: views.py:474
  207 +msgid "Unrealized"
  208 +msgstr "Não Realizado"
173 209
174 -#: views.py:478 210 +#: views.py:474
175 msgid "Historic" 211 msgid "Historic"
176 msgstr "Histórico" 212 msgstr "Histórico"
177 213
178 -#: views.py:515  
179 -msgid "Webpage"  
180 -msgstr "Nome da Página Web"  
181 -  
182 -#: views.py:516 214 +#: views.py:492 views.py:501
183 msgid "View" 215 msgid "View"
184 msgstr "Visualizar" 216 msgstr "Visualizar"
185 217
186 -#: views.py:520  
187 -msgid "Students viewing the webpage"  
188 -msgstr "Estudantes que visualizaram a webpage" 218 +#: views.py:500
  219 +msgid "Webpage"
  220 +msgstr "Nome da Página Web"
  221 +
  222 +#: views.py:505
  223 +msgid "Actions about resource"
  224 +msgstr "Ações sobre o recurso"
189 225
190 -#: views.py:521 226 +#: views.py:506
191 msgid "Quantity" 227 msgid "Quantity"
192 msgstr "Quantidade" 228 msgstr "Quantidade"
  229 +
  230 +#~ msgid "Users who viewed"
  231 +#~ msgstr "Usuários que visualizaram"
  232 +
  233 +#~ msgid "Users who did not viewed"
  234 +#~ msgstr "Usuários que não visualizaram"
  235 +
  236 +#~ msgid "Students viewing the webpage"
  237 +#~ msgstr "Estudantes que visualizaram a webpage"
webpage/templates/webpages/relatorios.html
@@ -9,10 +9,9 @@ @@ -9,10 +9,9 @@
9 <script type="text/javascript"> 9 <script type="text/javascript">
10 var tabela_atual = true; 10 var tabela_atual = true;
11 11
12 -  
13 var array_history = []; 12 var array_history = [];
14 - {%for data_json in json_history.data%}  
15 - array_history.push(["{{data_json.0}}","{{data_json.1}}","{{data_json.2}}",{% if data_json.3 is not None %}new Date('{{data_json.3.isoformat}}'){% else%}null{% endif %}]); 13 + {%for data_json in json_history.data %}
  14 + array_history.push(["{{data_json.0}}","{{data_json.1}}","{{view}}",{% if data_json.3 is not None %}new Date('{{data_json.3.isoformat}}'){% else%}null{% endif %}]);
16 {% endfor%} 15 {% endfor%}
17 var json_history = {"data":array_history}; 16 var json_history = {"data":array_history};
18 var column_history = [{"string":'{% trans "User" %}'},{"string":'{% trans "Group" %}'},{"string":'{% trans "Action" %}'},{"date":'{% trans "Date of Action" %}'}]; 17 var column_history = [{"string":'{% trans "User" %}'},{"string":'{% trans "Group" %}'},{"string":'{% trans "Action" %}'},{"date":'{% trans "Date of Action" %}'}];
@@ -35,7 +34,7 @@ @@ -35,7 +34,7 @@
35 array_n_did.push([input,"{{data_json.1}}","{{data_json.2}}","{{data_json.3}}"]); 34 array_n_did.push([input,"{{data_json.1}}","{{data_json.2}}","{{data_json.3}}"]);
36 {% endfor%} 35 {% endfor%}
37 var json_n_did = {"data":array_n_did}; 36 var json_n_did = {"data":array_n_did};
38 - var column_n_did = [{"string":'<a href="javascript:void(0);" onclick="return openmodal();"> {% trans "Send message" %}</a>'},{"string":'{% trans "User" %}'},{"string":'{% trans "Group" %}'},{"string":"Action don't realized"}]; 37 + var column_n_did = [{"string":'<a href="javascript:void(0);" onclick="return openmodal();"> {% trans "Send message" %}</a>'},{"string":'{% trans "User" %}'},{"string":'{% trans "Group" %}'},{"string":"{% trans "Action don't realized" %}"}];
39 </script> 38 </script>
40 39
41 40
@@ -75,6 +74,7 @@ @@ -75,6 +74,7 @@
75 json_n_did["data"][i][2],json_n_did["data"][i][3]]); 74 json_n_did["data"][i][2],json_n_did["data"][i][3]]);
76 } 75 }
77 searcher(col, tabela_atual,true); 76 searcher(col, tabela_atual,true);
  77 +
78 } else if (col == "{{did_table}}"){ 78 } else if (col == "{{did_table}}"){
79 tabela_atual = true; 79 tabela_atual = true;
80 search = []; 80 search = [];
@@ -93,6 +93,7 @@ @@ -93,6 +93,7 @@
93 chart.draw(data, options); 93 chart.draw(data, options);
94 94
95 } 95 }
  96 +
96 var sortAscending = {0:false,1:false,2:false,3:false}; 97 var sortAscending = {0:false,1:false,2:false,3:false};
97 function drawTable(columns = column_history,rows = pagination(json_history["data"],1),isdate = true,columndate = 3) { 98 function drawTable(columns = column_history,rows = pagination(json_history["data"],1),isdate = true,columndate = 3) {
98 var data_table = new google.visualization.DataTable(); 99 var data_table = new google.visualization.DataTable();
@@ -198,6 +199,7 @@ @@ -198,6 +199,7 @@
198 <ul> 199 <ul>
199 </div> 200 </div>
200 </div> 201 </div>
  202 +
201 <div class="row"> 203 <div class="row">
202 <div class="col-md-10 col-md-offset-1"> 204 <div class="col-md-10 col-md-offset-1">
203 <div id="chart_div" style="height: 500px; margin-top: -50px;"></div> 205 <div id="chart_div" style="height: 500px; margin-top: -50px;"></div>
@@ -231,44 +233,14 @@ @@ -231,44 +233,14 @@
231 </div> 233 </div>
232 </div> 234 </div>
233 </div> 235 </div>
234 -  
235 - <!-- Modal (remember to change the ids!!!) -->  
236 - <div class="modal fade" id="send-message-modal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">  
237 - <div class="modal-dialog" role="document">  
238 - <div class="modal-content">  
239 - <!-- Modal Body -->  
240 - <div class="modal-body">  
241 - <!-- Put ONLY your content here!!! -->  
242 - <h3>{% trans "Message: " %}</h3>  
243 - <form id="text_chat_form" action="" method="GET">  
244 - <textarea id="message" name="message" rows="5" cols="80"></textarea>  
245 - </form>  
246 - </div>  
247 - <!-- Modal Footer -->  
248 - <div id="delete-category-footer"class="modal-footer">  
249 - <!-- Don't remove that!!! -->  
250 - <button type="button" class="btn btn-default btn-raised" data-dismiss="modal">{% trans "Close" %}</button>  
251 - <a href="javascript:void(0)" onclick="return sendMessage()" form="text_chat_form" class="btn btn-success btn-raised erase-button">{% trans "Send" %}</a>  
252 - </div>  
253 - </div>  
254 - </div>  
255 - </div> 236 + <div id="modal-message"></div>
256 <div class="row"> 237 <div class="row">
257 <br><br> 238 <br><br>
258 </div> 239 </div>
259 </div> 240 </div>
260 241
261 <script type="text/javascript"> 242 <script type="text/javascript">
262 - $('#message').summernote({  
263 - dialogsInBody: true,  
264 - disableDragAndDrop: true,  
265 - height: 150,  
266 - toolbar: [  
267 - // [groupName, [list of button]]  
268 - ['style', ['bold', 'italic']],  
269 - ['insert', ['link']]  
270 - ]  
271 - }); 243 +
272 $("#title-table").text(search.length + " {% trans 'record(s)' %}"); 244 $("#title-table").text(search.length + " {% trans 'record(s)' %}");
273 function putpagination(data = json_history["data"], load_histoty = true){ 245 function putpagination(data = json_history["data"], load_histoty = true){
274 var len = Math.ceil(data.length / 20); 246 var len = Math.ceil(data.length / 20);
@@ -385,6 +357,15 @@ @@ -385,6 +357,15 @@
385 $(".active").removeClass("active"); 357 $(".active").removeClass("active");
386 $("#" + pag).addClass("active"); 358 $("#" + pag).addClass("active");
387 } 359 }
  360 +
  361 + function openmodal(){
  362 + $( "#modal-message" ).empty();
  363 + $.get( "{% url 'webpages:send_message' webpage.slug %}", function( data ) {
  364 + $( "#modal-message" ).append( data );
  365 + $("#send-message-modal").modal("show");
  366 + });
  367 + }
  368 +
388 function sendMessage(){ 369 function sendMessage(){
389 $("#send-message-modal").modal("hide"); 370 $("#send-message-modal").modal("hide");
390 var checked = $("#google-chart-checkbox").serializeArray(); 371 var checked = $("#google-chart-checkbox").serializeArray();
@@ -392,19 +373,36 @@ @@ -392,19 +373,36 @@
392 for (var i in checked){ 373 for (var i in checked){
393 email.push(checkbox[checked[i]["name"]]); 374 email.push(checkbox[checked[i]["name"]]);
394 } 375 }
395 - var message = $("#text_chat_form").serializeArray()[0]["value"]; 376 + $('<input />').attr('type', 'hidden')
  377 + .attr('name', "users[]")
  378 + .attr('value', email)
  379 + .appendTo('#text_chat_form');
  380 +
  381 + var formData = new FormData($('#text_chat_form').get(0));
396 $.ajax({ 382 $.ajax({
397 - type: "GET",  
398 - data: {"message":message,"users[]":email},  
399 - url: "{% url 'webpages:send_message' subject.slug %}",  
400 - success: function(msg){  
401 - console.log(msg);  
402 - $('#message').summernote("reset");  
403 - }  
404 - });  
405 - }  
406 - function openmodal(){  
407 - $("#send-message-modal").modal("show"); 383 + url: "{% url 'webpages:send_message' webpage.slug %}",
  384 + type: "POST",
  385 + data: formData,
  386 + cache: false,
  387 + processData: false,
  388 + contentType: false,
  389 + success: function(data) {
  390 + if (data["message"]){
  391 + console.log("success");
  392 + $("body").removeClass("modal-open");
  393 + $( "#modal-message" ).empty();
  394 + $(".modal-backdrop.fade.in").remove();
  395 + } else {
  396 + $( "#modal-message" ).empty();
  397 + $(".modal-backdrop.fade.in").remove();
  398 + $( "#modal-message" ).append( data );
  399 + $("#send-message-modal").modal("show");
  400 + }
  401 + },
  402 + error: function(data){
  403 + console.log("erro");
  404 + }
  405 + });
408 } 406 }
409 </script> 407 </script>
410 {% endblock %} 408 {% endblock %}
webpage/templates/webpages/send_message.html 0 → 100644
@@ -0,0 +1,112 @@ @@ -0,0 +1,112 @@
  1 +
  2 + {% load widget_tweaks i18n %}
  3 + <!-- Modal (remember to change the ids!!!) -->
  4 +<div class="modal fade" id="send-message-modal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
  5 + <div class="modal-dialog" role="document">
  6 + <div class="modal-content">
  7 + <!-- Modal Body -->
  8 + <div class="modal-body">
  9 + <form id="text_chat_form" action="" method="POST" enctype="multipart/form-data">
  10 + {% csrf_token %}
  11 + {% comment %}Area para o Texto{% endcomment %}
  12 + <div class="form-group{% if form.has_error %} has-error {% endif %}">
  13 + <label for="{{ form.comment.auto_id }}">{{ form.comment.label }}: <span>*</span></label>
  14 + {% render_field form.comment class='form-control text_simple_wysiwyg' %}
  15 +
  16 + <span id="helpBlock" class="help-block">{{ form.comment.help_text }}</span>
  17 +
  18 + {% if form.comment.errors %}
  19 + <div class="alert alert-danger alert-dismissible" role="alert">
  20 + <button type="button" class="close" data-dismiss="alert" aria-label="Close">
  21 + <span aria-hidden="true">&times;</span>
  22 + </button>
  23 + <ul>
  24 + {% for error in form.comment.errors %}
  25 + <li>{{ error }}</li>
  26 + {% endfor %}
  27 + </ul>
  28 + </div>
  29 + {% endif %}
  30 + </div>
  31 + {% comment %}Area para anexar a imagem {% endcomment %}
  32 + <div class="form-group{% if form.has_error %} has-error {% endif %} is-fileinput">
  33 + {% render_field form.image %}
  34 +
  35 + <div class="filedrag">
  36 + {% trans 'Click or drop the picture here' %}<br />
  37 +
  38 + <small>{% trans 'The picture could not exceed 5MB.' %}</small>
  39 + </div>
  40 +
  41 + {% if form.image.errors %}
  42 + <div class="alert alert-danger alert-dismissible" role="alert">
  43 + <button type="button" class="close" data-dismiss="alert" aria-label="Close">
  44 + <span aria-hidden="true">&times;</span>
  45 + </button>
  46 + <ul>
  47 + {% for error in form.image.errors %}
  48 + <li>{{ error }}</li>
  49 + {% endfor %}
  50 + </ul>
  51 + </div>
  52 + {% endif %}
  53 +
  54 + </div>
  55 + </form>
  56 + </div>
  57 + <!-- Modal Footer -->
  58 + <div id="delete-category-footer"class="modal-footer">
  59 + <!-- Don't remove that!!! -->
  60 + <button type="button" class="btn btn-default btn-raised" data-dismiss="modal">{% trans "Close" %}</button>
  61 + <a href="javascript:void(0)" onclick="return sendMessage()" form="text_chat_form" class="btn btn-success btn-raised erase-button">{% trans "Send" %}</a>
  62 + </div>
  63 + </div>
  64 + </div>
  65 +</div>
  66 +
  67 +<script type="text/javascript">
  68 +
  69 + $('.text_simple_wysiwyg').summernote({
  70 + dialogsInBody: true,
  71 + disableDragAndDrop: true,
  72 + height: 150,
  73 + toolbar: [
  74 + // [groupName, [list of button]]
  75 + ['style', ['bold', 'italic']],
  76 + ['insert', ['link']]
  77 + ]
  78 + });
  79 +
  80 + if (window.File && window.FileList && window.FileReader) {
  81 + Init();
  82 + }
  83 +
  84 + function Init() {
  85 + var small = $("#id_image"),
  86 + filedrag = $(".filedrag"),
  87 + common = $(".common-file-input");
  88 +
  89 + // file select
  90 + small.on("change", FileSelectHandler);
  91 +
  92 + // is XHR2 available?
  93 + var xhr = new XMLHttpRequest();
  94 + if (xhr.upload) {
  95 + // file drop
  96 + filedrag.on("drop", FileSelectHandler);
  97 + filedrag.attr('style', 'display:block');
  98 + common.attr('style', 'display:none');
  99 + }
  100 + }
  101 +
  102 + // file selection
  103 + function FileSelectHandler(e) {
  104 + var files = e.target.files || e.dataTransfer.files,
  105 + parent = $(e.target.offsetParent);
  106 +
  107 + // process all File objects
  108 + for (var i = 0, f; f = files[i]; i++) {
  109 + parent.find('.filedrag').html(f.name);
  110 + }
  111 + }
  112 +</script>
0 \ No newline at end of file 113 \ No newline at end of file
webpage/urls.py
@@ -10,5 +10,5 @@ urlpatterns = [ @@ -10,5 +10,5 @@ urlpatterns = [
10 url(r'^window_view/(?P<slug>[\w_-]+)/$', views.NewWindowView.as_view(), name = 'window_view'), 10 url(r'^window_view/(?P<slug>[\w_-]+)/$', views.NewWindowView.as_view(), name = 'window_view'),
11 url(r'^view/(?P<slug>[\w_-]+)/$', views.InsideView.as_view(), name = 'view'), 11 url(r'^view/(?P<slug>[\w_-]+)/$', views.InsideView.as_view(), name = 'view'),
12 url(r'^chart/(?P<slug>[\w_-]+)/$', views.StatisticsView.as_view(), name = 'get_chart'), 12 url(r'^chart/(?P<slug>[\w_-]+)/$', views.StatisticsView.as_view(), name = 'get_chart'),
13 - url(r'^send-message/(?P<slug>[\w_-]+)/$', views.sendMessage, name = 'send_message'), 13 + url(r'^send-message/(?P<slug>[\w_-]+)/$', views.SendMessage.as_view(), name = 'send_message'),
14 ] 14 ]
webpage/views.py
@@ -10,7 +10,6 @@ from amadeus.permissions import has_subject_permissions, has_resource_permission @@ -10,7 +10,6 @@ from amadeus.permissions import has_subject_permissions, has_resource_permission
10 10
11 import time 11 import time
12 import datetime 12 import datetime
13 -from log.models import Log  
14 from log.mixins import LogMixin 13 from log.mixins import LogMixin
15 14
16 from topics.models import Topic 15 from topics.models import Topic
@@ -20,100 +19,108 @@ from pendencies.forms import PendenciesForm @@ -20,100 +19,108 @@ from pendencies.forms import PendenciesForm
20 from .forms import WebpageForm 19 from .forms import WebpageForm
21 from .models import Webpage 20 from .models import Webpage
22 21
  22 +from log.models import Log
  23 +from chat.models import Conversation, TalkMessages
  24 +from users.models import User
  25 +from subjects.models import Subject
  26 +
  27 +from .forms import FormModalMessage
  28 +
23 class NewWindowView(LoginRequiredMixin, LogMixin, generic.DetailView): 29 class NewWindowView(LoginRequiredMixin, LogMixin, generic.DetailView):
24 - log_component = 'resources'  
25 - log_action = 'view'  
26 - log_resource = 'webpage'  
27 - log_context = {} 30 + log_component = 'resources'
  31 + log_action = 'view'
  32 + log_resource = 'webpage'
  33 + log_context = {}
28 34
29 - login_url = reverse_lazy("users:login")  
30 - redirect_field_name = 'next' 35 + login_url = reverse_lazy("users:login")
  36 + redirect_field_name = 'next'
31 37
32 - template_name = 'webpages/window_view.html'  
33 - model = Webpage  
34 - context_object_name = 'webpage' 38 + template_name = 'webpages/window_view.html'
  39 + model = Webpage
  40 + context_object_name = 'webpage'
35 41
36 - def dispatch(self, request, *args, **kwargs):  
37 - slug = self.kwargs.get('slug', '')  
38 - webpage = get_object_or_404(Webpage, slug = slug) 42 + def dispatch(self, request, *args, **kwargs):
  43 + slug = self.kwargs.get('slug', '')
  44 + webpage = get_object_or_404(Webpage, slug=slug)
39 45
40 - if not has_resource_permissions(request.user, webpage):  
41 - return redirect(reverse_lazy('subjects:home')) 46 + if not has_resource_permissions(request.user, webpage):
  47 + return redirect(reverse_lazy('subjects:home'))
42 48
43 - return super(NewWindowView, self).dispatch(request, *args, **kwargs) 49 + return super(NewWindowView, self).dispatch(request, *args, **kwargs)
44 50
45 - def get_context_data(self, **kwargs):  
46 - context = super(NewWindowView, self).get_context_data(**kwargs) 51 + def get_context_data(self, **kwargs):
  52 + context = super(NewWindowView, self).get_context_data(**kwargs)
47 53
48 - self.log_context['category_id'] = self.object.topic.subject.category.id  
49 - self.log_context['category_name'] = self.object.topic.subject.category.name  
50 - self.log_context['category_slug'] = self.object.topic.subject.category.slug  
51 - self.log_context['subject_id'] = self.object.topic.subject.id  
52 - self.log_context['subject_name'] = self.object.topic.subject.name  
53 - self.log_context['subject_slug'] = self.object.topic.subject.slug  
54 - self.log_context['topic_id'] = self.object.topic.id  
55 - self.log_context['topic_name'] = self.object.topic.name  
56 - self.log_context['topic_slug'] = self.object.topic.slug  
57 - self.log_context['webpage_id'] = self.object.id  
58 - self.log_context['webpage_name'] = self.object.name  
59 - self.log_context['webpage_slug'] = self.object.slug  
60 - self.log_context['timestamp_start'] = str(int(time.time())) 54 + self.log_context['category_id'] = self.object.topic.subject.category.id
  55 + self.log_context['category_name'] = self.object.topic.subject.category.name
  56 + self.log_context['category_slug'] = self.object.topic.subject.category.slug
  57 + self.log_context['subject_id'] = self.object.topic.subject.id
  58 + self.log_context['subject_name'] = self.object.topic.subject.name
  59 + self.log_context['subject_slug'] = self.object.topic.subject.slug
  60 + self.log_context['topic_id'] = self.object.topic.id
  61 + self.log_context['topic_name'] = self.object.topic.name
  62 + self.log_context['topic_slug'] = self.object.topic.slug
  63 + self.log_context['webpage_id'] = self.object.id
  64 + self.log_context['webpage_name'] = self.object.name
  65 + self.log_context['webpage_slug'] = self.object.slug
  66 + self.log_context['timestamp_start'] = str(int(time.time()))
61 67
62 - super(NewWindowView, self).createLog(self.request.user, self.log_component, self.log_action, self.log_resource, self.log_context) 68 + super(NewWindowView, self).createLog(self.request.user, self.log_component, self.log_action,
  69 + self.log_resource, self.log_context)
63 70
64 - self.request.session['log_id'] = Log.objects.latest('id').id 71 + self.request.session['log_id'] = Log.objects.latest('id').id
65 72
66 - return context 73 + return context
67 74
68 class InsideView(LoginRequiredMixin, LogMixin, generic.DetailView): 75 class InsideView(LoginRequiredMixin, LogMixin, generic.DetailView):
69 - log_component = 'resources'  
70 - log_action = 'view'  
71 - log_resource = 'webpage'  
72 - log_context = {} 76 + log_component = 'resources'
  77 + log_action = 'view'
  78 + log_resource = 'webpage'
  79 + log_context = {}
73 80
74 - login_url = reverse_lazy("users:login")  
75 - redirect_field_name = 'next' 81 + login_url = reverse_lazy("users:login")
  82 + redirect_field_name = 'next'
76 83
77 - template_name = 'webpages/view.html'  
78 - model = Webpage  
79 - context_object_name = 'webpage' 84 + template_name = 'webpages/view.html'
  85 + model = Webpage
  86 + context_object_name = 'webpage'
80 87
81 - def dispatch(self, request, *args, **kwargs):  
82 - slug = self.kwargs.get('slug', '')  
83 - webpage = get_object_or_404(Webpage, slug = slug) 88 + def dispatch(self, request, *args, **kwargs):
  89 + slug = self.kwargs.get('slug', '')
  90 + webpage = get_object_or_404(Webpage, slug=slug)
84 91
85 - if not has_resource_permissions(request.user, webpage):  
86 - return redirect(reverse_lazy('subjects:home')) 92 + if not has_resource_permissions(request.user, webpage):
  93 + return redirect(reverse_lazy('subjects:home'))
87 94
88 - return super(InsideView, self).dispatch(request, *args, **kwargs) 95 + return super(InsideView, self).dispatch(request, *args, **kwargs)
89 96
90 - def get_context_data(self, **kwargs):  
91 - context = super(InsideView, self).get_context_data(**kwargs) 97 + def get_context_data(self, **kwargs):
  98 + context = super(InsideView, self).get_context_data(**kwargs)
92 99
93 - context['title'] = self.object.name 100 + context['title'] = self.object.name
94 101
95 - context['topic'] = self.object.topic  
96 - context['subject'] = self.object.topic.subject 102 + context['topic'] = self.object.topic
  103 + context['subject'] = self.object.topic.subject
97 104
98 - self.log_context['category_id'] = self.object.topic.subject.category.id  
99 - self.log_context['category_name'] = self.object.topic.subject.category.name  
100 - self.log_context['category_slug'] = self.object.topic.subject.category.slug  
101 - self.log_context['subject_id'] = self.object.topic.subject.id  
102 - self.log_context['subject_name'] = self.object.topic.subject.name  
103 - self.log_context['subject_slug'] = self.object.topic.subject.slug  
104 - self.log_context['topic_id'] = self.object.topic.id  
105 - self.log_context['topic_name'] = self.object.topic.name  
106 - self.log_context['topic_slug'] = self.object.topic.slug  
107 - self.log_context['webpage_id'] = self.object.id  
108 - self.log_context['webpage_name'] = self.object.name  
109 - self.log_context['webpage_slug'] = self.object.slug  
110 - self.log_context['timestamp_start'] = str(int(time.time())) 105 + self.log_context['category_id'] = self.object.topic.subject.category.id
  106 + self.log_context['category_name'] = self.object.topic.subject.category.name
  107 + self.log_context['category_slug'] = self.object.topic.subject.category.slug
  108 + self.log_context['subject_id'] = self.object.topic.subject.id
  109 + self.log_context['subject_name'] = self.object.topic.subject.name
  110 + self.log_context['subject_slug'] = self.object.topic.subject.slug
  111 + self.log_context['topic_id'] = self.object.topic.id
  112 + self.log_context['topic_name'] = self.object.topic.name
  113 + self.log_context['topic_slug'] = self.object.topic.slug
  114 + self.log_context['webpage_id'] = self.object.id
  115 + self.log_context['webpage_name'] = self.object.name
  116 + self.log_context['webpage_slug'] = self.object.slug
  117 + self.log_context['timestamp_start'] = str(int(time.time()))
111 118
112 - super(InsideView, self).createLog(self.request.user, self.log_component, self.log_action, self.log_resource, self.log_context) 119 + super(InsideView, self).createLog(self.request.user, self.log_component, self.log_action, self.log_resource, self.log_context)
113 120
114 - self.request.session['log_id'] = Log.objects.latest('id').id 121 + self.request.session['log_id'] = Log.objects.latest('id').id
115 122
116 - return context 123 + return context
117 124
118 class CreateView(LoginRequiredMixin, LogMixin, generic.edit.CreateView): 125 class CreateView(LoginRequiredMixin, LogMixin, generic.edit.CreateView):
119 log_component = 'resources' 126 log_component = 'resources'
@@ -128,55 +135,55 @@ class CreateView(LoginRequiredMixin, LogMixin, generic.edit.CreateView): @@ -128,55 +135,55 @@ class CreateView(LoginRequiredMixin, LogMixin, generic.edit.CreateView):
128 form_class = WebpageForm 135 form_class = WebpageForm
129 136
130 def dispatch(self, request, *args, **kwargs): 137 def dispatch(self, request, *args, **kwargs):
131 - slug = self.kwargs.get('slug', '')  
132 - topic = get_object_or_404(Topic, slug = slug)  
133 -  
134 - if not has_subject_permissions(request.user, topic.subject):  
135 - return redirect(reverse_lazy('subjects:home')) 138 + slug = self.kwargs.get('slug', '')
  139 + topic = get_object_or_404(Topic, slug = slug)
  140 +
  141 + if not has_subject_permissions(request.user, topic.subject):
  142 + return redirect(reverse_lazy('subjects:home'))
136 143
137 - return super(CreateView, self).dispatch(request, *args, **kwargs) 144 + return super(CreateView, self).dispatch(request, *args, **kwargs)
138 145
139 def get(self, request, *args, **kwargs): 146 def get(self, request, *args, **kwargs):
140 - self.object = None 147 + self.object = None
141 148
142 - form_class = self.get_form_class()  
143 - form = self.get_form(form_class) 149 + form_class = self.get_form_class()
  150 + form = self.get_form(form_class)
144 151
145 - slug = self.kwargs.get('slug', '')  
146 - topic = get_object_or_404(Topic, slug = slug) 152 + slug = self.kwargs.get('slug', '')
  153 + topic = get_object_or_404(Topic, slug = slug)
147 154
148 - pendencies_form = PendenciesForm(initial = {'subject': topic.subject.id, 'actions': [("", "-------"),("view", _("Visualize"))]}) 155 + pendencies_form = PendenciesForm(initial = {'subject': topic.subject.id, 'actions': [("", "-------"),("view", _("Visualize"))]})
149 156
150 - return self.render_to_response(self.get_context_data(form = form, pendencies_form = pendencies_form)) 157 + return self.render_to_response(self.get_context_data(form = form, pendencies_form = pendencies_form))
151 158
152 def post(self, request, *args, **kwargs): 159 def post(self, request, *args, **kwargs):
153 - self.object = None 160 + self.object = None
154 161
155 - form_class = self.get_form_class()  
156 - form = self.get_form(form_class) 162 + form_class = self.get_form_class()
  163 + form = self.get_form(form_class)
157 164
158 - slug = self.kwargs.get('slug', '')  
159 - topic = get_object_or_404(Topic, slug = slug) 165 + slug = self.kwargs.get('slug', '')
  166 + topic = get_object_or_404(Topic, slug = slug)
160 167
161 - pendencies_form = PendenciesForm(self.request.POST, initial = {'subject': topic.subject.id, 'actions': [("", "-------"),("view", _("Visualize"))]}) 168 + pendencies_form = PendenciesForm(self.request.POST, initial = {'subject': topic.subject.id, 'actions': [("", "-------"),("view", _("Visualize"))]})
162 169
163 - if (form.is_valid() and pendencies_form.is_valid()):  
164 - return self.form_valid(form, pendencies_form)  
165 - else:  
166 - return self.form_invalid(form, pendencies_form) 170 + if (form.is_valid() and pendencies_form.is_valid()):
  171 + return self.form_valid(form, pendencies_form)
  172 + else:
  173 + return self.form_invalid(form, pendencies_form)
167 174
168 def get_initial(self): 175 def get_initial(self):
169 - initial = super(CreateView, self).get_initial() 176 + initial = super(CreateView, self).get_initial()
170 177
171 - slug = self.kwargs.get('slug', '') 178 + slug = self.kwargs.get('slug', '')
172 179
173 - topic = get_object_or_404(Topic, slug = slug)  
174 - initial['subject'] = topic.subject 180 + topic = get_object_or_404(Topic, slug = slug)
  181 + initial['subject'] = topic.subject
175 182
176 - return initial 183 + return initial
177 184
178 def form_invalid(self, form, pendencies_form): 185 def form_invalid(self, form, pendencies_form):
179 - return self.render_to_response(self.get_context_data(form = form, pendencies_form = pendencies_form)) 186 + return self.render_to_response(self.get_context_data(form = form, pendencies_form = pendencies_form))
180 187
181 def form_valid(self, form, pendencies_form): 188 def form_valid(self, form, pendencies_form):
182 self.object = form.save(commit = False) 189 self.object = form.save(commit = False)
@@ -187,18 +194,15 @@ class CreateView(LoginRequiredMixin, LogMixin, generic.edit.CreateView): @@ -187,18 +194,15 @@ class CreateView(LoginRequiredMixin, LogMixin, generic.edit.CreateView):
187 self.object.order = topic.resource_topic.count() + 1 194 self.object.order = topic.resource_topic.count() + 1
188 195
189 if not self.object.topic.visible and not self.object.topic.repository: 196 if not self.object.topic.visible and not self.object.topic.repository:
190 - self.object.visible = False 197 + self.object.visible = False
191 198
192 -  
193 - if form.cleaned_data["all_students"]:  
194 - self.object.students.add(*self.object.topic.subject.students.all())  
195 self.object.save() 199 self.object.save()
196 200
197 pend_form = pendencies_form.save(commit = False) 201 pend_form = pendencies_form.save(commit = False)
198 pend_form.resource = self.object 202 pend_form.resource = self.object
199 203
200 if not pend_form.action == "": 204 if not pend_form.action == "":
201 - pend_form.save() 205 + pend_form.save()
202 206
203 self.log_context['category_id'] = self.object.topic.subject.category.id 207 self.log_context['category_id'] = self.object.topic.subject.category.id
204 self.log_context['category_name'] = self.object.topic.subject.category.name 208 self.log_context['category_name'] = self.object.topic.subject.category.name
@@ -218,153 +222,153 @@ class CreateView(LoginRequiredMixin, LogMixin, generic.edit.CreateView): @@ -218,153 +222,153 @@ class CreateView(LoginRequiredMixin, LogMixin, generic.edit.CreateView):
218 return redirect(self.get_success_url()) 222 return redirect(self.get_success_url())
219 223
220 def get_context_data(self, **kwargs): 224 def get_context_data(self, **kwargs):
221 - context = super(CreateView, self).get_context_data(**kwargs) 225 + context = super(CreateView, self).get_context_data(**kwargs)
222 226
223 - context['title'] = _('Create Webpage') 227 + context['title'] = _('Create Webpage')
224 228
225 - slug = self.kwargs.get('slug', '')  
226 - topic = get_object_or_404(Topic, slug = slug) 229 + slug = self.kwargs.get('slug', '')
  230 + topic = get_object_or_404(Topic, slug = slug)
227 231
228 - context['topic'] = topic  
229 - context['subject'] = topic.subject 232 + context['topic'] = topic
  233 + context['subject'] = topic.subject
230 234
231 - return context 235 + return context
232 236
233 def get_success_url(self): 237 def get_success_url(self):
234 - messages.success(self.request, _('The Webpage "%s" was added to the Topic "%s" of the virtual environment "%s" successfully!')%(self.object.name, self.object.topic.name, self.object.topic.subject.name)) 238 + messages.success(self.request, _('The Webpage "%s" was added to the Topic "%s" of the virtual environment "%s" successfully!')%(self.object.name, self.object.topic.name, self.object.topic.subject.name))
235 239
236 - success_url = reverse_lazy('webpages:view', kwargs = {'slug': self.object.slug}) 240 + success_url = reverse_lazy('webpages:view', kwargs = {'slug': self.object.slug})
237 241
238 - if self.object.show_window:  
239 - self.request.session['resources'] = {}  
240 - self.request.session['resources']['new_page'] = True  
241 - self.request.session['resources']['new_page_url'] = reverse('webpages:window_view', kwargs = {'slug': self.object.slug}) 242 + if self.object.show_window:
  243 + self.request.session['resources'] = {}
  244 + self.request.session['resources']['new_page'] = True
  245 + self.request.session['resources']['new_page_url'] = reverse('webpages:window_view', kwargs = {'slug': self.object.slug})
242 246
243 - success_url = reverse_lazy('subjects:view', kwargs = {'slug': self.object.topic.subject.slug}) 247 + success_url = reverse_lazy('subjects:view', kwargs = {'slug': self.object.topic.subject.slug})
244 248
245 - return success_url 249 + return success_url
246 250
247 class UpdateView(LoginRequiredMixin, LogMixin, generic.UpdateView): 251 class UpdateView(LoginRequiredMixin, LogMixin, generic.UpdateView):
248 - log_component = 'resources'  
249 - log_action = 'update'  
250 - log_resource = 'webpage'  
251 - log_context = {} 252 + log_component = 'resources'
  253 + log_action = 'update'
  254 + log_resource = 'webpage'
  255 + log_context = {}
252 256
253 - login_url = reverse_lazy("users:login")  
254 - redirect_field_name = 'next' 257 + login_url = reverse_lazy("users:login")
  258 + redirect_field_name = 'next'
255 259
256 - template_name = 'webpages/update.html'  
257 - model = Webpage  
258 - form_class = WebpageForm 260 + template_name = 'webpages/update.html'
  261 + model = Webpage
  262 + form_class = WebpageForm
259 263
260 - def dispatch(self, request, *args, **kwargs):  
261 - slug = self.kwargs.get('topic_slug', '')  
262 - topic = get_object_or_404(Topic, slug = slug) 264 + def dispatch(self, request, *args, **kwargs):
  265 + slug = self.kwargs.get('topic_slug', '')
  266 + topic = get_object_or_404(Topic, slug = slug)
263 267
264 - if not has_subject_permissions(request.user, topic.subject):  
265 - return redirect(reverse_lazy('subjects:home')) 268 + if not has_subject_permissions(request.user, topic.subject):
  269 + return redirect(reverse_lazy('subjects:home'))
266 270
267 - return super(UpdateView, self).dispatch(request, *args, **kwargs) 271 + return super(UpdateView, self).dispatch(request, *args, **kwargs)
268 272
269 - def get(self, request, *args, **kwargs):  
270 - self.object = self.get_object() 273 + def get(self, request, *args, **kwargs):
  274 + self.object = self.get_object()
271 275
272 - form_class = self.get_form_class()  
273 - form = self.get_form(form_class) 276 + form_class = self.get_form_class()
  277 + form = self.get_form(form_class)
274 278
275 - slug = self.kwargs.get('topic_slug', '')  
276 - topic = get_object_or_404(Topic, slug = slug) 279 + slug = self.kwargs.get('topic_slug', '')
  280 + topic = get_object_or_404(Topic, slug = slug)
277 281
278 - pend_form = self.object.pendencies_resource.all() 282 + pend_form = self.object.pendencies_resource.all()
279 283
280 - if len(pend_form) > 0:  
281 - pendencies_form = PendenciesForm(instance = pend_form[0], initial = {'subject': topic.subject.id, 'actions': [("", "-------"),("view", _("Visualize"))]})  
282 - else:  
283 - pendencies_form = PendenciesForm(initial = {'subject': topic.subject.id, 'actions': [("", "-------"),("view", _("Visualize"))]}) 284 + if len(pend_form) > 0:
  285 + pendencies_form = PendenciesForm(instance = pend_form[0], initial = {'subject': topic.subject.id, 'actions': [("", "-------"),("view", _("Visualize"))]})
  286 + else:
  287 + pendencies_form = PendenciesForm(initial = {'subject': topic.subject.id, 'actions': [("", "-------"),("view", _("Visualize"))]})
284 288
285 - return self.render_to_response(self.get_context_data(form = form, pendencies_form = pendencies_form)) 289 + return self.render_to_response(self.get_context_data(form = form, pendencies_form = pendencies_form))
286 290
287 - def post(self, request, *args, **kwargs):  
288 - self.object = self.get_object() 291 + def post(self, request, *args, **kwargs):
  292 + self.object = self.get_object()
289 293
290 - form_class = self.get_form_class()  
291 - form = self.get_form(form_class) 294 + form_class = self.get_form_class()
  295 + form = self.get_form(form_class)
292 296
293 - slug = self.kwargs.get('topic_slug', '')  
294 - topic = get_object_or_404(Topic, slug = slug) 297 + slug = self.kwargs.get('topic_slug', '')
  298 + topic = get_object_or_404(Topic, slug = slug)
295 299
296 - pend_form = self.object.pendencies_resource.all() 300 + pend_form = self.object.pendencies_resource.all()
297 301
298 - if len(pend_form) > 0:  
299 - pendencies_form = PendenciesForm(self.request.POST, instance = pend_form[0], initial = {'subject': topic.subject.id, 'actions': [("", "-------"),("view", _("Visualize"))]})  
300 - else:  
301 - pendencies_form = PendenciesForm(self.request.POST, initial = {'subject': topic.subject.id, 'actions': [("", "-------"),("view", _("Visualize"))]}) 302 + if len(pend_form) > 0:
  303 + pendencies_form = PendenciesForm(self.request.POST, instance = pend_form[0], initial = {'subject': topic.subject.id, 'actions': [("", "-------"),("view", _("Visualize"))]})
  304 + else:
  305 + pendencies_form = PendenciesForm(self.request.POST, initial = {'subject': topic.subject.id, 'actions': [("", "-------"),("view", _("Visualize"))]})
302 306
303 - if (form.is_valid() and pendencies_form.is_valid()):  
304 - return self.form_valid(form, pendencies_form)  
305 - else:  
306 - return self.form_invalid(form, pendencies_form) 307 + if (form.is_valid() and pendencies_form.is_valid()):
  308 + return self.form_valid(form, pendencies_form)
  309 + else:
  310 + return self.form_invalid(form, pendencies_form)
307 311
308 - def form_invalid(self, form, pendencies_form):  
309 - return self.render_to_response(self.get_context_data(form = form, pendencies_form = pendencies_form)) 312 + def form_invalid(self, form, pendencies_form):
  313 + return self.render_to_response(self.get_context_data(form = form, pendencies_form = pendencies_form))
310 314
311 - def form_valid(self, form, pendencies_form):  
312 - self.object = form.save(commit = False) 315 + def form_valid(self, form, pendencies_form):
  316 + self.object = form.save(commit = False)
313 317
314 - if not self.object.topic.visible and not self.object.topic.repository:  
315 - self.object.visible = False 318 + if not self.object.topic.visible and not self.object.topic.repository:
  319 + self.object.visible = False
316 320
317 - self.object.save() 321 + self.object.save()
318 322
319 - pend_form = pendencies_form.save(commit = False)  
320 - pend_form.resource = self.object 323 + pend_form = pendencies_form.save(commit = False)
  324 + pend_form.resource = self.object
321 325
322 - if not pend_form.action == "":  
323 - pend_form.save() 326 + if not pend_form.action == "":
  327 + pend_form.save()
324 328
325 - self.log_context['category_id'] = self.object.topic.subject.category.id  
326 - self.log_context['category_name'] = self.object.topic.subject.category.name  
327 - self.log_context['category_slug'] = self.object.topic.subject.category.slug  
328 - self.log_context['subject_id'] = self.object.topic.subject.id  
329 - self.log_context['subject_name'] = self.object.topic.subject.name  
330 - self.log_context['subject_slug'] = self.object.topic.subject.slug  
331 - self.log_context['topic_id'] = self.object.topic.id  
332 - self.log_context['topic_name'] = self.object.topic.name  
333 - self.log_context['topic_slug'] = self.object.topic.slug  
334 - self.log_context['webpage_id'] = self.object.id  
335 - self.log_context['webpage_name'] = self.object.name  
336 - self.log_context['webpage_slug'] = self.object.slug 329 + self.log_context['category_id'] = self.object.topic.subject.category.id
  330 + self.log_context['category_name'] = self.object.topic.subject.category.name
  331 + self.log_context['category_slug'] = self.object.topic.subject.category.slug
  332 + self.log_context['subject_id'] = self.object.topic.subject.id
  333 + self.log_context['subject_name'] = self.object.topic.subject.name
  334 + self.log_context['subject_slug'] = self.object.topic.subject.slug
  335 + self.log_context['topic_id'] = self.object.topic.id
  336 + self.log_context['topic_name'] = self.object.topic.name
  337 + self.log_context['topic_slug'] = self.object.topic.slug
  338 + self.log_context['webpage_id'] = self.object.id
  339 + self.log_context['webpage_name'] = self.object.name
  340 + self.log_context['webpage_slug'] = self.object.slug
337 341
338 - super(UpdateView, self).createLog(self.request.user, self.log_component, self.log_action, self.log_resource, self.log_context) 342 + super(UpdateView, self).createLog(self.request.user, self.log_component, self.log_action, self.log_resource, self.log_context)
339 343
340 - return redirect(self.get_success_url()) 344 + return redirect(self.get_success_url())
341 345
342 - def get_context_data(self, **kwargs):  
343 - context = super(UpdateView, self).get_context_data(**kwargs) 346 + def get_context_data(self, **kwargs):
  347 + context = super(UpdateView, self).get_context_data(**kwargs)
344 348
345 - context['title'] = _('Update Webpage') 349 + context['title'] = _('Update Webpage')
346 350
347 - slug = self.kwargs.get('topic_slug', '')  
348 - topic = get_object_or_404(Topic, slug = slug) 351 + slug = self.kwargs.get('topic_slug', '')
  352 + topic = get_object_or_404(Topic, slug = slug)
349 353
350 - context['topic'] = topic  
351 - context['subject'] = topic.subject 354 + context['topic'] = topic
  355 + context['subject'] = topic.subject
352 356
353 - return context 357 + return context
354 358
355 - def get_success_url(self):  
356 - messages.success(self.request, _('The Webpage "%s" was updated successfully!')%(self.object.name)) 359 + def get_success_url(self):
  360 + messages.success(self.request, _('The Webpage "%s" was updated successfully!')%(self.object.name))
357 361
358 - success_url = reverse_lazy('webpages:view', kwargs = {'slug': self.object.slug}) 362 + success_url = reverse_lazy('webpages:view', kwargs = {'slug': self.object.slug})
359 363
360 - if self.object.show_window:  
361 - self.request.session['resources'] = {}  
362 - self.request.session['resources']['new_page'] = True  
363 - self.request.session['resources']['new_page_url'] = reverse('webpages:window_view', kwargs = {'slug': self.object.slug}) 364 + if self.object.show_window:
  365 + self.request.session['resources'] = {}
  366 + self.request.session['resources']['new_page'] = True
  367 + self.request.session['resources']['new_page_url'] = reverse('webpages:window_view', kwargs = {'slug': self.object.slug})
364 368
365 - success_url = reverse_lazy('subjects:view', kwargs = {'slug': self.object.topic.subject.slug}) 369 + success_url = reverse_lazy('subjects:view', kwargs = {'slug': self.object.topic.subject.slug})
366 370
367 - return success_url 371 + return success_url
368 372
369 class DeleteView(LoginRequiredMixin, LogMixin, generic.DeleteView): 373 class DeleteView(LoginRequiredMixin, LogMixin, generic.DeleteView):
370 log_component = 'resources' 374 log_component = 'resources'
@@ -409,17 +413,6 @@ class DeleteView(LoginRequiredMixin, LogMixin, generic.DeleteView): @@ -409,17 +413,6 @@ class DeleteView(LoginRequiredMixin, LogMixin, generic.DeleteView):
409 return reverse_lazy('subjects:view', kwargs = {'slug': self.object.topic.subject.slug}) 413 return reverse_lazy('subjects:view', kwargs = {'slug': self.object.topic.subject.slug})
410 414
411 415
412 -def get_chart(request,slug):  
413 - webpage = get_object_or_404(Webpage, slug=slug)  
414 - alunos = webpage.students.all()  
415 - visualizou = Log.objects.filter(context__contains={'webpage_id':webpage.id},resource="webpage",action="view",user_email__in=(aluno.email for aluno in alunos)).distinct("user_email")  
416 - re = []  
417 - c_visualizou = visualizou.count()  
418 - re.append(["Página Web","Fez","Não fez"])  
419 - re.append(["Visualizar",c_visualizou, alunos.count() - c_visualizou])  
420 - return JsonResponse({"dados":re})  
421 -  
422 -  
423 class StatisticsView(LoginRequiredMixin, LogMixin, generic.DetailView): 416 class StatisticsView(LoginRequiredMixin, LogMixin, generic.DetailView):
424 log_component = 'resources' 417 log_component = 'resources'
425 log_action = 'view_statistics' 418 log_action = 'view_statistics'
@@ -474,6 +467,8 @@ class StatisticsView(LoginRequiredMixin, LogMixin, generic.DetailView): @@ -474,6 +467,8 @@ class StatisticsView(LoginRequiredMixin, LogMixin, generic.DetailView):
474 context["init_date"] = start_date 467 context["init_date"] = start_date
475 context["end_date"] = end_date 468 context["end_date"] = end_date
476 alunos = webpage.students.all() 469 alunos = webpage.students.all()
  470 + if webpage.all_students :
  471 + alunos = webpage.topic.subject.students.all()
477 472
478 vis_ou = Log.objects.filter(context__contains={'webpage_id':webpage.id},resource="webpage",action="view",user_email__in=(aluno.email for aluno in alunos), datetime__range=(start_date,end_date + datetime.timedelta(minutes = 1))) 473 vis_ou = Log.objects.filter(context__contains={'webpage_id':webpage.id},resource="webpage",action="view",user_email__in=(aluno.email for aluno in alunos), datetime__range=(start_date,end_date + datetime.timedelta(minutes = 1)))
479 did,n_did,history = str(_("Realized")),str(_("Unrealized")),str(_("Historic")) 474 did,n_did,history = str(_("Realized")),str(_("Unrealized")),str(_("Historic"))
@@ -502,32 +497,59 @@ class StatisticsView(LoginRequiredMixin, LogMixin, generic.DetailView): @@ -502,32 +497,59 @@ class StatisticsView(LoginRequiredMixin, LogMixin, generic.DetailView):
502 context["json_n_did"] = json_n_did 497 context["json_n_did"] = json_n_did
503 context["json_history"] = json_history 498 context["json_history"] = json_history
504 c_visualizou = vis_ou.distinct("user_email").count() 499 c_visualizou = vis_ou.distinct("user_email").count()
  500 + column_view = str(_('View'))
505 re.append([str(_('Webpage')),did,n_did]) 501 re.append([str(_('Webpage')),did,n_did])
506 - re.append([str(_('View')),c_visualizou, alunos.count() - c_visualizou]) 502 + re.append([column_view,c_visualizou, alunos.count() - c_visualizou])
507 context['topic'] = webpage.topic 503 context['topic'] = webpage.topic
508 context['subject'] = webpage.topic.subject 504 context['subject'] = webpage.topic.subject
509 context['db_data'] = re 505 context['db_data'] = re
510 context['title_chart'] = _('Actions about resource') 506 context['title_chart'] = _('Actions about resource')
511 context['title_vAxis'] = _('Quantity') 507 context['title_vAxis'] = _('Quantity')
512 - 508 + context['view'] = column_view
513 context["n_did_table"] = n_did 509 context["n_did_table"] = n_did
514 context["did_table"] = did 510 context["did_table"] = did
515 context["history_table"] = history 511 context["history_table"] = history
516 return context 512 return context
517 513
518 514
519 -from chat.models import Conversation, TalkMessages  
520 -from users.models import User  
521 -from subjects.models import Subject  
522 -def sendMessage(request, slug):  
523 - message = request.GET.get('message','')  
524 - users = request.GET.getlist('users[]','')  
525 - user = request.user  
526 - subject = get_object_or_404(Subject,slug = slug)  
527 -  
528 - for u in users:  
529 - to_user = User.objects.get(email=u)  
530 - talk, create = Conversation.objects.get_or_create(user_one=user,user_two=to_user)  
531 - created = TalkMessages.objects.create(text=message,talk=talk,user=user,subject=subject)  
532 -  
533 - return JsonResponse({"message":"ok"}) 515 +
  516 +class SendMessage(LoginRequiredMixin, LogMixin, generic.edit.FormView):
  517 + log_component = 'resources'
  518 + log_action = 'send'
  519 + log_resource = 'webpage'
  520 + log_context = {}
  521 +
  522 + login_url = reverse_lazy("users:login")
  523 + redirect_field_name = 'next'
  524 +
  525 + template_name = 'webpages/send_message.html'
  526 + form_class = FormModalMessage
  527 +
  528 + def dispatch(self, request, *args, **kwargs):
  529 + slug = self.kwargs.get('slug', '')
  530 + webpage = get_object_or_404(Webpage, slug = slug)
  531 + self.webpage = webpage
  532 +
  533 + if not has_subject_permissions(request.user, webpage.topic.subject):
  534 + return redirect(reverse_lazy('subjects:home'))
  535 +
  536 + return super(SendMessage, self).dispatch(request, *args, **kwargs)
  537 +
  538 + def form_valid(self, form):
  539 + message = form.cleaned_data.get('comment')
  540 + image = form.cleaned_data.get("image")
  541 + users = (self.request.POST.get('users[]','')).split(",")
  542 + user = self.request.user
  543 + subject = self.webpage.topic.subject
  544 + for u in users:
  545 + to_user = User.objects.get(email=u)
  546 + talk, create = Conversation.objects.get_or_create(user_one=user,user_two=to_user)
  547 + created = TalkMessages.objects.create(text=message,talk=talk,user=user,subject=subject,image=image)
  548 + return JsonResponse({"message":"ok"})
  549 +
  550 + def get_context_data(self, **kwargs):
  551 + context = super(SendMessage,self).get_context_data()
  552 + context["webpage"] = get_object_or_404(Webpage, slug=self.kwargs.get('slug', ''))
  553 + return context
  554 +
  555 +
youtube_video/locale/pt_BR/LC_MESSAGES/django.po
@@ -8,7 +8,7 @@ msgid &quot;&quot; @@ -8,7 +8,7 @@ msgid &quot;&quot;
8 msgstr "" 8 msgstr ""
9 "Project-Id-Version: PACKAGE VERSION\n" 9 "Project-Id-Version: PACKAGE VERSION\n"
10 "Report-Msgid-Bugs-To: \n" 10 "Report-Msgid-Bugs-To: \n"
11 -"POT-Creation-Date: 2017-04-15 00:13-0300\n" 11 +"POT-Creation-Date: 2017-05-05 21:46-0300\n"
12 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" 12 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
13 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" 13 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
14 "Language-Team: LANGUAGE <LL@li.org>\n" 14 "Language-Team: LANGUAGE <LL@li.org>\n"
@@ -18,104 +18,167 @@ msgstr &quot;&quot; @@ -18,104 +18,167 @@ msgstr &quot;&quot;
18 "Content-Transfer-Encoding: 8bit\n" 18 "Content-Transfer-Encoding: 8bit\n"
19 "Plural-Forms: nplurals=2; plural=(n > 1);\n" 19 "Plural-Forms: nplurals=2; plural=(n > 1);\n"
20 20
21 -#: youtube_video/forms.py:36 21 +#: forms.py:36
22 msgid "Tags" 22 msgid "Tags"
23 msgstr "Tags" 23 msgstr "Tags"
24 24
25 -#: youtube_video/forms.py:42 25 +#: forms.py:42
26 msgid "Video title" 26 msgid "Video title"
27 msgstr "Título do Vídeo" 27 msgstr "Título do Vídeo"
28 28
29 -#: youtube_video/forms.py:62 29 +#: forms.py:62
30 msgid "This subject already has a resource with this name" 30 msgid "This subject already has a resource with this name"
31 msgstr "Esse assunto já possui um recurso com esse nome" 31 msgstr "Esse assunto já possui um recurso com esse nome"
32 32
33 -#: youtube_video/forms.py:71 33 +#: forms.py:71
34 msgid "Invalid URL. It should be an YouTube link." 34 msgid "Invalid URL. It should be an YouTube link."
35 msgstr "URL inválida. Ela deve ser uma URL de um vídeo do YouTube." 35 msgstr "URL inválida. Ela deve ser uma URL de um vídeo do YouTube."
36 36
37 -#: youtube_video/models.py:8 37 +#: models.py:8
38 msgid "URL" 38 msgid "URL"
39 msgstr "URL" 39 msgstr "URL"
40 40
41 -#: youtube_video/models.py:11 41 +#: models.py:11
42 msgid "YTVideo" 42 msgid "YTVideo"
43 msgstr "Vídeo do YouTube" 43 msgstr "Vídeo do YouTube"
44 44
45 -#: youtube_video/models.py:12 45 +#: models.py:12
46 msgid "YTVideos" 46 msgid "YTVideos"
47 msgstr "Vídeos do YouTube" 47 msgstr "Vídeos do YouTube"
48 48
49 -#: youtube_video/models.py:30 49 +#: models.py:30
50 msgid "Are you sure you want delete the YouTube Video" 50 msgid "Are you sure you want delete the YouTube Video"
51 msgstr "Você tem certeza que deseja deletar o Vídeo do YouTube" 51 msgstr "Você tem certeza que deseja deletar o Vídeo do YouTube"
52 52
53 -#: youtube_video/templates/youtube/_form.html:49 53 +#: templates/youtube/_form.html:49
54 msgid "Common resources settings" 54 msgid "Common resources settings"
55 msgstr "Configurações comuns à todos os recursos" 55 msgstr "Configurações comuns à todos os recursos"
56 56
57 -#: youtube_video/templates/youtube/_form.html:98 57 +#: templates/youtube/_form.html:98
58 msgid "Pendencies Notifications" 58 msgid "Pendencies Notifications"
59 msgstr "Notificações de Pendências" 59 msgstr "Notificações de Pendências"
60 60
61 -#: youtube_video/templates/youtube/_form.html:119 61 +#: templates/youtube/_form.html:119
62 msgid "Action not performed by the user" 62 msgid "Action not performed by the user"
63 msgstr "Ação não realizada pelo usuário" 63 msgstr "Ação não realizada pelo usuário"
64 64
65 -#: youtube_video/templates/youtube/_form.html:145 65 +#: templates/youtube/_form.html:145
66 msgid "Wished period" 66 msgid "Wished period"
67 msgstr "Período desejado" 67 msgstr "Período desejado"
68 68
69 -#: youtube_video/templates/youtube/_form.html:242 69 +#: templates/youtube/_form.html:242
70 msgid "Attribute students to YouTube Video" 70 msgid "Attribute students to YouTube Video"
71 msgstr "Atribuir estudantes ao Vídeo do YouTube" 71 msgstr "Atribuir estudantes ao Vídeo do YouTube"
72 72
73 -#: youtube_video/templates/youtube/_form.html:262 73 +#: templates/youtube/_form.html:262
74 msgid "Attribute groups to YouTube Video" 74 msgid "Attribute groups to YouTube Video"
75 msgstr "Atribuir grupos de estudo ao Vídeo do YouTube" 75 msgstr "Atribuir grupos de estudo ao Vídeo do YouTube"
76 76
77 -#: youtube_video/templates/youtube/_form.html:331 77 +#: templates/youtube/_form.html:331
78 msgid "Save" 78 msgid "Save"
79 msgstr "Salvar" 79 msgstr "Salvar"
80 80
81 -#: youtube_video/templates/youtube/_form.html:338 81 +#: templates/youtube/_form.html:338
82 msgid "Add new notification" 82 msgid "Add new notification"
83 msgstr "Adicionar nova notificação" 83 msgstr "Adicionar nova notificação"
84 84
85 -#: youtube_video/templates/youtube/_form.html:339 85 +#: templates/youtube/_form.html:339
86 msgid "Remove this" 86 msgid "Remove this"
87 msgstr "Remover essa notificação" 87 msgstr "Remover essa notificação"
88 88
89 -#: youtube_video/templates/youtube/create.html:21 89 +#: templates/youtube/create.html:21
90 msgid "Create YouTube Video" 90 msgid "Create YouTube Video"
91 msgstr "Adicionar Vídeo do YouTube" 91 msgstr "Adicionar Vídeo do YouTube"
92 92
93 -#: youtube_video/templates/youtube/update.html:21 93 +#: templates/youtube/relatorios.html:17 templates/youtube/relatorios.html:37
  94 +msgid "User"
  95 +msgstr "Usuário"
  96 +
  97 +#: templates/youtube/relatorios.html:17 templates/youtube/relatorios.html:37
  98 +msgid "Group"
  99 +msgstr "Grupo"
  100 +
  101 +#: templates/youtube/relatorios.html:17
  102 +msgid "Action"
  103 +msgstr "Ação"
  104 +
  105 +#: templates/youtube/relatorios.html:17
  106 +msgid "Date of Action"
  107 +msgstr "Data da ação"
  108 +
  109 +#: templates/youtube/relatorios.html:37
  110 +msgid "Send message"
  111 +msgstr "Enviar Mensagem"
  112 +
  113 +#: templates/youtube/relatorios.html:37
  114 +msgid "Action don't realized"
  115 +msgstr "Ação não realizada"
  116 +
  117 +#: templates/youtube/relatorios.html:212 templates/youtube/relatorios.html:232
  118 +msgid "Reports"
  119 +msgstr "Relatórios"
  120 +
  121 +#: templates/youtube/relatorios.html:239
  122 +msgid "Report of the resource "
  123 +msgstr "Relatórios do recurso "
  124 +
  125 +#: templates/youtube/relatorios.html:248
  126 +msgid "Select the period: "
  127 +msgstr "Selecione o período: "
  128 +
  129 +#: templates/youtube/relatorios.html:257
  130 +msgid "Search"
  131 +msgstr "Pesquisar"
  132 +
  133 +#: templates/youtube/relatorios.html:281
  134 +msgid "Filter: "
  135 +msgstr "Filtro: "
  136 +
  137 +#: templates/youtube/relatorios.html:305 templates/youtube/relatorios.html:390
  138 +#: templates/youtube/relatorios.html:470
  139 +msgid "record(s)"
  140 +msgstr "Relatório(s)"
  141 +
  142 +#: templates/youtube/send_message.html:38
  143 +msgid "Click or drop the picture here"
  144 +msgstr "Clique ou solte a imagem aqui"
  145 +
  146 +#: templates/youtube/send_message.html:40
  147 +msgid "The picture could not exceed 5MB."
  148 +msgstr "A imagem não pode exceder 5MB."
  149 +
  150 +#: templates/youtube/send_message.html:62
  151 +msgid "Close"
  152 +msgstr "Fechar"
  153 +
  154 +#: templates/youtube/send_message.html:63
  155 +msgid "Send"
  156 +msgstr "Enviar"
  157 +
  158 +#: templates/youtube/update.html:21
94 msgid "Edit: " 159 msgid "Edit: "
95 msgstr "Editar: " 160 msgstr "Editar: "
96 161
97 -#: youtube_video/views.py:46 162 +#: views.py:56
98 #, python-format 163 #, python-format
99 msgid "%s - Video" 164 msgid "%s - Video"
100 msgstr "%s - Vídeo" 165 msgstr "%s - Vídeo"
101 166
102 -#: youtube_video/views.py:148 youtube_video/views.py:161  
103 -#: youtube_video/views.py:180 youtube_video/views.py:283  
104 -#: youtube_video/views.py:296 youtube_video/views.py:305 167 +#: views.py:158 views.py:171 views.py:190 views.py:293 views.py:306
  168 +#: views.py:315
105 msgid "Visualize" 169 msgid "Visualize"
106 msgstr "Visualizar" 170 msgstr "Visualizar"
107 171
108 -#: youtube_video/views.py:148 youtube_video/views.py:161  
109 -#: youtube_video/views.py:180 youtube_video/views.py:283  
110 -#: youtube_video/views.py:296 youtube_video/views.py:305 172 +#: views.py:158 views.py:171 views.py:190 views.py:293 views.py:306
  173 +#: views.py:315 views.py:549
111 msgid "Finish" 174 msgid "Finish"
112 msgstr "Finalizar" 175 msgstr "Finalizar"
113 176
114 -#: youtube_video/views.py:227 177 +#: views.py:237
115 msgid "Create Youtube Video" 178 msgid "Create Youtube Video"
116 msgstr "Adicionar Vídeo do YouTube" 179 msgstr "Adicionar Vídeo do YouTube"
117 180
118 -#: youtube_video/views.py:238 181 +#: views.py:248
119 #, python-format 182 #, python-format
120 msgid "" 183 msgid ""
121 "The Youtube Video \"%s\" was added to the Topic \"%s\" of the virtual " 184 "The Youtube Video \"%s\" was added to the Topic \"%s\" of the virtual "
@@ -124,16 +187,16 @@ msgstr &quot;&quot; @@ -124,16 +187,16 @@ msgstr &quot;&quot;
124 "O Vídeo do YouTube \"%s\" foi adicionado ao tópico \"%s\" do ambiente " 187 "O Vídeo do YouTube \"%s\" foi adicionado ao tópico \"%s\" do ambiente "
125 "virtual \"%s\" com sucesso!" 188 "virtual \"%s\" com sucesso!"
126 189
127 -#: youtube_video/views.py:346 190 +#: views.py:356
128 msgid "Update YouTube Video" 191 msgid "Update YouTube Video"
129 msgstr "Atualizar Vídeo do YouTube" 192 msgstr "Atualizar Vídeo do YouTube"
130 193
131 -#: youtube_video/views.py:357 194 +#: views.py:367
132 #, python-format 195 #, python-format
133 msgid "The YouTube Video \"%s\" was updated successfully!" 196 msgid "The YouTube Video \"%s\" was updated successfully!"
134 msgstr "O Vídeo do YouTube \"%s\" foi atualizado com sucesso!" 197 msgstr "O Vídeo do YouTube \"%s\" foi atualizado com sucesso!"
135 198
136 -#: youtube_video/views.py:393 199 +#: views.py:403
137 #, python-format 200 #, python-format
138 msgid "" 201 msgid ""
139 "The YouTube Video \"%s\" was removed successfully from virtual environment " 202 "The YouTube Video \"%s\" was removed successfully from virtual environment "
@@ -141,3 +204,41 @@ msgid &quot;&quot; @@ -141,3 +204,41 @@ msgid &quot;&quot;
141 msgstr "" 204 msgstr ""
142 "O Vídeo do YouTube \"%s\" foi removido do ambiente virtual \"%s\" com " 205 "O Vídeo do YouTube \"%s\" foi removido do ambiente virtual \"%s\" com "
143 "sucesso!" 206 "sucesso!"
  207 +
  208 +#: views.py:515
  209 +#| msgid "Create Youtube Video"
  210 +msgid "Youtube Video Reports"
  211 +msgstr "Relatórios de Vídeo do YouTube"
  212 +
  213 +#: views.py:534
  214 +msgid "Realized"
  215 +msgstr "Realizado"
  216 +
  217 +#: views.py:534
  218 +msgid "Unrealized"
  219 +msgstr "Não Realizado"
  220 +
  221 +#: views.py:534
  222 +msgid "Historic"
  223 +msgstr "Histórico"
  224 +
  225 +#: views.py:549
  226 +msgid "View"
  227 +msgstr "Visualizar"
  228 +
  229 +#: views.py:549
  230 +msgid "Watch"
  231 +msgstr "Assistir"
  232 +
  233 +#: views.py:575
  234 +#| msgid "Create Youtube Video"
  235 +msgid "Youtube Video"
  236 +msgstr "Vídeo do YouTube"
  237 +
  238 +#: views.py:587
  239 +msgid "Actions about resource"
  240 +msgstr "Ações sobre o recurso"
  241 +
  242 +#: views.py:588
  243 +msgid "Quantity"
  244 +msgstr "Quantidade"
youtube_video/templates/youtube/relatorios.html 0 → 100644
@@ -0,0 +1,473 @@ @@ -0,0 +1,473 @@
  1 +{% extends "youtube/view.html" %}
  2 +
  3 +{% load static i18n pagination permissions_tags subject_counter %}
  4 +{% load django_bootstrap_breadcrumbs %}
  5 +
  6 +{% block javascript%}
  7 + {{ block.super }}
  8 + <script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
  9 + <script type="text/javascript">
  10 + var tabela_atual = true;
  11 +
  12 + var array_history = [];
  13 + {%for data_json in json_history.data %}
  14 + array_history.push(["{{data_json.0}}","{{data_json.1}}","{% if data_json.2 == 'view' %} {{view}} {% elif data_json.2 == 'watch' %} {{watch}} {% else %} {{finish}} {% endif %}",{% if data_json.3 is not None %}new Date('{{data_json.3.isoformat}}'){% else%}null{% endif %}]);
  15 + {% endfor%}
  16 + var json_history = {"data":array_history};
  17 + var column_history = [{"string":'{% trans "User" %}'},{"string":'{% trans "Group" %}'},{"string":'{% trans "Action" %}'},{"date":'{% trans "Date of Action" %}'}];
  18 +
  19 + var search = [];
  20 + for (var i in json_history["data"]){
  21 + search.push([json_history["data"][i][0],json_history["data"][i][1],
  22 + json_history["data"][i][2],json_history["data"][i][3]]);
  23 + }
  24 +
  25 + var array_n_did = [];
  26 + var checkbox = {};
  27 + {%for data_json in json_n_did.data%}
  28 + var input = '<div class="checkbox">\
  29 + <label for="{{data_json.0}}_google_table">\
  30 + <input id="{{data_json.0}}_google_table" name="{{data_json.0}}_google_table" type="checkbox"><span class="checkbox-material"><span class="check"></span></span>\
  31 + </label>\
  32 + </div>'
  33 + checkbox["{{data_json.0}}_google_table"] = "{{data_json.4}}";
  34 + array_n_did.push([input,"{{data_json.1}}","{{data_json.2}}","{{data_json.3}}"]);
  35 + {% endfor%}
  36 + var json_n_did = {"data":array_n_did};
  37 + var column_n_did = [{"string":'<a href="javascript:void(0);" onclick="return openmodal();"> {% trans "Send message" %}</a>'},{"string":'{% trans "User" %}'},{"string":'{% trans "Group" %}'},{"string":"{% trans "Action don't realized" %}"}];
  38 + </script>
  39 +
  40 +
  41 + <script type="text/javascript">
  42 + google.charts.load('current', {'packages':['corechart',"table"]});
  43 + google.charts.setOnLoadCallback(drawChart);
  44 + google.charts.setOnLoadCallback(drawTable);
  45 +
  46 + function drawChart() {
  47 + var data = google.visualization.arrayToDataTable({{db_data|safe}});
  48 + var options = {
  49 + title: '{{title_chart}}',
  50 + // legend: {position: 'right', maxLines: 1},
  51 + bar: { groupWidth: '50%' },
  52 + chartArea:{width:"50%"},
  53 + titlePosition: 'out',
  54 + vAxis: {
  55 + title: '{{title_vAxis}}',
  56 + ticks: [0, .20, .40, .60, .80, 1],
  57 + viewWindow: {
  58 + min: 0,
  59 + max: 1
  60 + }
  61 + },
  62 + isStacked: "percent",
  63 + };
  64 +
  65 + function selectHandler() {
  66 + var selectedItem = chart.getSelection()[0];
  67 + console.log(selectedItem.row,selectedItem.column);
  68 + if (selectedItem) {
  69 + if (selectedItem.row == 0 && selectedItem.column == 1){
  70 + tabela_atual = true;
  71 + search = [];
  72 + var text = "{{view}}";
  73 + for (var i in json_history["data"]){
  74 + if (json_history["data"][i][2].toLowerCase().includes(text.toLowerCase())){
  75 + search.push([json_history["data"][i][0],json_history["data"][i][1],
  76 + json_history["data"][i][2],json_history["data"][i][3]]);
  77 + }
  78 + }
  79 + drawTable(column_history,pagination(search,1),true,3);
  80 + alterTitleTable(search.length);
  81 + putpagination(search,tabela_atual);
  82 + } else if(selectedItem.row == 0 && selectedItem.column == 2){
  83 + tabela_atual = false;
  84 + search = [];
  85 + var text = "{{view}}";
  86 + for (var i in json_n_did["data"]){
  87 + if (json_n_did["data"][i][3].toLowerCase().includes(text.toLowerCase())){
  88 + search.push([json_n_did["data"][i][0],json_n_did["data"][i][1],
  89 + json_n_did["data"][i][2],json_n_did["data"][i][3]]);
  90 + }
  91 + }
  92 + drawTable(column_n_did,pagination(search,1),false);
  93 + alterTitleTable(search.length);
  94 + putpagination(search,tabela_atual);
  95 + } else if (selectedItem.row == 1 && selectedItem.column == 1){
  96 + tabela_atual = true;
  97 + search = [];
  98 + var text = "{{watch}}";
  99 + for (var i in json_history["data"]){
  100 + if (json_history["data"][i][2].toLowerCase().includes(text.toLowerCase())){
  101 + search.push([json_history["data"][i][0],json_history["data"][i][1],
  102 + json_history["data"][i][2],json_history["data"][i][3]]);
  103 + }
  104 + }
  105 + drawTable(column_history,pagination(search,1),true,3);
  106 + alterTitleTable(search.length);
  107 + putpagination(search,tabela_atual);
  108 + } else if(selectedItem.row == 1 && selectedItem.column == 2){
  109 + tabela_atual = false;
  110 + search = [];
  111 + var text = "{{watch}}";
  112 + for (var i in json_n_did["data"]){
  113 + if (json_n_did["data"][i][3].toLowerCase().includes(text.toLowerCase())){
  114 + search.push([json_n_did["data"][i][0],json_n_did["data"][i][1],
  115 + json_n_did["data"][i][2],json_n_did["data"][i][3]]);
  116 + }
  117 + }
  118 + drawTable(column_n_did,pagination(search,1),false);
  119 + alterTitleTable(search.length);
  120 + putpagination(search,tabela_atual);
  121 + } else if (selectedItem.row == 2 && selectedItem.column == 1){
  122 + tabela_atual = true;
  123 + search = [];
  124 + var text = "{{finish}}";
  125 + for (var i in json_history["data"]){
  126 + if (json_history["data"][i][2].toLowerCase().includes(text.toLowerCase())){
  127 + search.push([json_history["data"][i][0],json_history["data"][i][1],
  128 + json_history["data"][i][2],json_history["data"][i][3]]);
  129 + }
  130 + }
  131 + drawTable(column_history,pagination(search,1),true,3);
  132 + alterTitleTable(search.length);
  133 + putpagination(search,tabela_atual);
  134 + } else if(selectedItem.row == 2 && selectedItem.column == 2){
  135 + tabela_atual = false;
  136 + search = [];
  137 + var text = "{{finish}}";
  138 + for (var i in json_n_did["data"]){
  139 + if (json_n_did["data"][i][3].toLowerCase().includes(text.toLowerCase())){
  140 + search.push([json_n_did["data"][i][0],json_n_did["data"][i][1],
  141 + json_n_did["data"][i][2],json_n_did["data"][i][3]]);
  142 + }
  143 + }
  144 + drawTable(column_n_did,pagination(search,1),false);
  145 + alterTitleTable(search.length);
  146 + putpagination(search,tabela_atual);
  147 + }
  148 + }
  149 + chart.setSelection([])
  150 + }
  151 +
  152 + var chart = new google.visualization.ColumnChart(document.getElementById('chart_div'));
  153 + google.visualization.events.addListener(chart, 'select', selectHandler);
  154 + chart.draw(data, options);
  155 +
  156 + }
  157 +
  158 + var sortAscending = {0:false,1:false,2:false,3:false};
  159 + function drawTable(columns = column_history,rows = pagination(json_history["data"],1),isdate = true,columndate = 3) {
  160 + var data_table = new google.visualization.DataTable();
  161 + for (var i in columns){
  162 + for (var item in columns[i]){
  163 + data_table.addColumn(item,columns[i][item]);
  164 + }
  165 + }
  166 +
  167 + data_table.addRows(rows);
  168 + var formate_date = new google.visualization.DateFormat({pattern: 'dd/MM/yyyy HH:mm'});
  169 + if (isdate) formate_date.format(data_table, columndate);
  170 +
  171 + // var methods = [];
  172 + // for (var m in data_table) {
  173 + // if (typeof data_table[m] == "function") {
  174 + // methods.push(m);
  175 + // }
  176 + // }
  177 + // console.log(methods.join(","));
  178 + var options = {
  179 + sort: "event",
  180 + allowHtml: true,
  181 + cssClassNames : {
  182 + tableRow: 'text-center',
  183 + tableCell: 'text-center',
  184 + headerCell: 'text-center'
  185 + },
  186 + showRowNumber: true,
  187 + width: '100%',
  188 + height: '100%',
  189 + }
  190 + function ordenar(properties){
  191 + var columnIndex = properties['column'];
  192 + if (columnIndex > 0) {
  193 + options["sortColumn"] = columnIndex;
  194 + options["sortAscending"] = sortAscending[columnIndex];
  195 + data_table.sort({column:columnIndex,desc:sortAscending[columnIndex]});
  196 + sortAscending = {0:false,1:false,2:false,3:false};
  197 + sortAscending[columnIndex] = !sortAscending[columnIndex];
  198 + // console.log(sortAscending);
  199 + table.draw(data_table, options);
  200 + }
  201 + }
  202 +
  203 + var table = new google.visualization.Table(document.getElementById('table_div'));
  204 + google.visualization.events.addListener(table, 'sort', function(e) {ordenar(e)});
  205 + table.draw(data_table, options);
  206 + }
  207 + </script>
  208 +{% endblock%}
  209 +
  210 +{% block breadcrumbs %}
  211 + {{ block.super }}
  212 + {% trans 'Reports' as bread %}
  213 + {% breadcrumb bread ytvideo%}
  214 +{% endblock %}
  215 +
  216 +{% block content %}
  217 + {% if messages %}
  218 + {% for message in messages %}
  219 + <div class="alert alert-{{ message.tags }} alert-dismissible" role="alert">
  220 + <button type="button" class="close" data-dismiss="alert" aria-label="Close">
  221 + <span aria-hidden="true">&times;</span>
  222 + </button>
  223 + <p>{{ message }}</p>
  224 + </div>
  225 + {% endfor %}
  226 + {% endif %}
  227 + <div class="panel panel-info topic-panel">
  228 + <div class="panel-heading">
  229 + <div class="row">
  230 + <div class="col-md-12 category-header">
  231 + <h4 class="panel-title" style="margin-top: 10px; margin-bottom: 8px">
  232 + <span>{{ytvideo}} / {% trans "Reports" %}</span>
  233 + </h4>
  234 + </div>
  235 + </div>
  236 + </div>
  237 + <div class="row">
  238 + <div class="col-md-12 text-center">
  239 + <h4 style="margin-top: 15px; margin-bottom: 10px" ><strong>{% trans "Report of the resource " %}{{ytvideo}}</strong></h4>
  240 + </div>
  241 + </div>
  242 + <div class="row">
  243 + <div class="col-md-12">
  244 +
  245 + <ul class="list-inline nav-justified">
  246 + <div id="general-parameters-div">
  247 + <div class="general-parameters-field">
  248 + <li class="text-right"><h4>{% trans "Select the period: " %}</h4></li>
  249 + </div>
  250 + <form id="period-form" action="" method="get">
  251 + <div class="general-parameters-field">
  252 + <li> <input class="form-control datetime-picker" name="init_date" type="text" required="" value="{% if LANGUAGE_CODE == 'pt-br' %}{{init_date|date:'d/m/Y H:i'}} {% else %} {{init_date|date:'m/d/Y H:i P'}} {% endif %}"></li>
  253 + </div>
  254 + <div class="general-parameters-field">
  255 + <li><input id="inputdate" class="form-control datetime-picker" name="end_date" type="text" required="" value="{% if LANGUAGE_CODE == 'pt-br' %}{{end_date|date:'d/m/Y H:i'}} {% else %} {{end_date|date:'m/d/Y H:i P'}} {% endif %}"></li>
  256 + </div>
  257 + <li><input type="submit" value="{% trans 'Search' %}" style="margin-left: 15px;" class="btn btn-success btn-raised"></li>
  258 + </form>
  259 + </div>
  260 + <ul>
  261 + </div>
  262 + </div>
  263 +
  264 + <div class="row">
  265 + <div class="col-md-10 col-md-offset-1">
  266 + <div id="chart_div" style="height: 500px; margin-top: -50px;"></div>
  267 + </div>
  268 + </div>
  269 +
  270 + <div class="row">
  271 + <div class="col-md-10 col-md-offset-1">
  272 + <div class="text-center">
  273 + <ul class="list-inline nav-justified">
  274 + <li>
  275 + <ul id="view-table" class="list-inline text-right">
  276 + <li><h3 id="title-table"></h3></li>
  277 + </ul>
  278 + </li>
  279 + <li>
  280 + <ul class="list-inline text-right">
  281 + <li><p>{% trans "Filter: " %}</p></li>
  282 + <li><input id="search-input" class="form-control" type="text" name="search" value=""></li>
  283 + </ul>
  284 + </li>
  285 + </ul>
  286 + </div>
  287 + <form id="google-chart-checkbox" action="" method="get">
  288 + <div id="table_div"></div>
  289 + </form>
  290 + <div class="col-md-12 col-lg-12 col-sm-12 col-xs-12 text-center">
  291 + <ul class="pagination">
  292 +
  293 + </ul>
  294 + </div>
  295 + </div>
  296 + </div>
  297 + <div id="modal-message"></div>
  298 + <div class="row">
  299 + <br><br>
  300 + </div>
  301 + </div>
  302 +
  303 + <script type="text/javascript">
  304 +
  305 + $("#title-table").text(search.length + " {% trans 'record(s)' %}");
  306 + function putpagination(data = json_history["data"], load_histoty = true){
  307 + var len = Math.ceil(data.length / 20);
  308 + $(".pagination").empty();
  309 + $(".pagination").append('<li class="disabled"><span>«</span></li>');
  310 + $(".pagination").append('<li id="1" class="active">\
  311 + <a href="javascript:void(0);" onclick="return clickPagination(1, '+ load_histoty +');">1</a>\
  312 + </li>');
  313 + for (var i = 2; i <= len;i++){
  314 + $(".pagination").append('<li id="' + i + '">\
  315 + <a href="javascript:void(0);" onclick="return clickPagination(' + i +', ' + load_histoty + ');">' + i + '</a>\
  316 + </li>');
  317 + }
  318 + if (len > 1) $(".pagination").append('<li><a href="javascript:void(0);" onclick="return clickPagination(2, '+ load_histoty +');"><span>»</span></a></li>');
  319 + else $(".pagination").append('<li class="disabled"><span>»</span></li>');
  320 + };
  321 + putpagination();
  322 +
  323 + $('#period-form').submit(function(event) {
  324 + $('<input />').attr('type', 'hidden')
  325 + .attr('name', "language")
  326 + .attr('value', '{{ LANGUAGE_CODE }}')
  327 + .appendTo('#period-form');
  328 + });
  329 + function add(element,local, first = false){
  330 + if (first) $(local).prepend(element);
  331 + else $(local).append(element);
  332 + }
  333 + function text(element){
  334 + return $(element).text();
  335 + }
  336 + function length(element) {
  337 + return $(element).length;
  338 + }
  339 +
  340 + $("#search-input").on("keyup",function(){
  341 + search = [];
  342 + var text = $("#search-input").val();
  343 + searcher(text,tabela_atual);
  344 + });
  345 +
  346 + function searcher(text, load_histoty = false,apaga=false){
  347 + if(apaga){
  348 + $("#search-input").val("");
  349 + }
  350 + var data = [];
  351 + if (!load_histoty){
  352 + data = $.map(json_n_did["data"], function (obj) {
  353 + return $.extend(true, {}, obj);
  354 + });
  355 + } else {
  356 + data = $.map(json_history["data"], function (obj) {
  357 + return $.extend(true, {}, obj);
  358 + });
  359 + }
  360 + if (load_histoty){
  361 + for (var i in data){
  362 + data[i][3] = moment(data[i][3]).format("DD/MM/YYYY HH:mm");
  363 + }
  364 + }
  365 + if (load_histoty){
  366 + for (var i in data){
  367 + if (data[i][0].toLowerCase().includes(text.toLowerCase())
  368 + || data[i][1].toLowerCase().includes(text.toLowerCase())
  369 + || data[i][2].toLowerCase().includes(text.toLowerCase())
  370 + || data[i][3].toLowerCase().includes(text.toLowerCase())){
  371 + search.push(json_history["data"][i]);
  372 + }
  373 + }
  374 + }
  375 + else {
  376 + for (var i in data){
  377 + if (data[i][1].toLowerCase().includes(text.toLowerCase())
  378 + || data[i][2].toLowerCase().includes(text.toLowerCase())
  379 + || data[i][3].toLowerCase().includes(text.toLowerCase())){
  380 + search.push(json_n_did["data"][i]);
  381 + }
  382 + }
  383 + }
  384 + console.log(search);
  385 + if (!load_histoty){
  386 + drawTable(column_n_did,pagination(search,1),false);
  387 + } else {
  388 + drawTable(column_history,pagination(search,1),true,3);
  389 + }
  390 + $("#title-table").text(search.length + " {% trans 'record(s)' %}");
  391 + putpagination(search,load_histoty);
  392 + }
  393 +
  394 + function pagination(data,pag){
  395 + var len = data.length;
  396 + var first = (pag * 20 - 20 < len) ? pag * 20 - 20:len;
  397 + var end = (pag * 20 < len) ? pag * 20:len;
  398 + var search = data.slice(first,end);
  399 + return search;
  400 + }
  401 +
  402 + function clickPagination(pag, load_histoty = false){
  403 + $(".pagination > li").last().remove();
  404 + $(".pagination > li").first().remove();
  405 +
  406 + if (!load_histoty){
  407 + drawTable(column_n_did,pagination(search,pag),false);
  408 + } else {
  409 + drawTable(column_history,pagination(search,pag),true,3);
  410 + }
  411 +
  412 + if (pag < Math.ceil(search.length / 20))
  413 + $(".pagination").append('<li><a href="javascript:void(0);" onclick="return clickPagination(' + (pag + 1) + ', '+ load_histoty +');"><span>»</span></a></li>');
  414 + else $(".pagination").append('<li class="disabled"><span>»</span></li>');
  415 + if (pag > 1)
  416 + $(".pagination").prepend('<li><a href="javascript:void(0);" onclick="return clickPagination(' + (pag - 1) + ', '+ load_histoty +');"><span>«</span></a></li>');
  417 + else $(".pagination").prepend('<li class="disabled"><span>«</span></li>');
  418 + $(".active").removeClass("active");
  419 + $("#" + pag).addClass("active");
  420 + }
  421 +
  422 + function openmodal(){
  423 + $( "#modal-message" ).empty();
  424 + $.get( "{% url 'youtube:send_message' ytvideo.slug %}", function( data ) {
  425 + $( "#modal-message" ).append( data );
  426 + $("#send-message-modal").modal("show");
  427 + });
  428 + }
  429 +
  430 + function sendMessage(){
  431 + $("#send-message-modal").modal("hide");
  432 + var checked = $("#google-chart-checkbox").serializeArray();
  433 + var email = [];
  434 + for (var i in checked){
  435 + email.push(checkbox[checked[i]["name"]]);
  436 + }
  437 + $('<input />').attr('type', 'hidden')
  438 + .attr('name', "users[]")
  439 + .attr('value', email)
  440 + .appendTo('#text_chat_form');
  441 +
  442 + var formData = new FormData($('#text_chat_form').get(0));
  443 + $.ajax({
  444 + url: "{% url 'youtube:send_message' ytvideo.slug %}",
  445 + type: "POST",
  446 + data: formData,
  447 + cache: false,
  448 + processData: false,
  449 + contentType: false,
  450 + success: function(data) {
  451 + if (data["message"]){
  452 + console.log("success");
  453 + $("body").removeClass("modal-open");
  454 + $( "#modal-message" ).empty();
  455 + $(".modal-backdrop.fade.in").remove();
  456 + } else {
  457 + $( "#modal-message" ).empty();
  458 + $(".modal-backdrop.fade.in").remove();
  459 + $( "#modal-message" ).append( data );
  460 + $("#send-message-modal").modal("show");
  461 + }
  462 + },
  463 + error: function(data){
  464 + console.log("erro");
  465 + }
  466 + });
  467 + }
  468 +
  469 + function alterTitleTable (quant){
  470 + $("#title-table").text(quant + " {% trans 'record(s)' %}");
  471 + }
  472 + </script>
  473 +{% endblock %}
youtube_video/templates/youtube/send_message.html 0 → 100644
@@ -0,0 +1,112 @@ @@ -0,0 +1,112 @@
  1 +
  2 + {% load widget_tweaks i18n %}
  3 + <!-- Modal (remember to change the ids!!!) -->
  4 +<div class="modal fade" id="send-message-modal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
  5 + <div class="modal-dialog" role="document">
  6 + <div class="modal-content">
  7 + <!-- Modal Body -->
  8 + <div class="modal-body">
  9 + <form id="text_chat_form" action="" method="POST" enctype="multipart/form-data">
  10 + {% csrf_token %}
  11 + {% comment %}Area para o Texto{% endcomment %}
  12 + <div class="form-group{% if form.has_error %} has-error {% endif %}">
  13 + <label for="{{ form.comment.auto_id }}">{{ form.comment.label }}: <span>*</span></label>
  14 + {% render_field form.comment class='form-control text_simple_wysiwyg' %}
  15 +
  16 + <span id="helpBlock" class="help-block">{{ form.comment.help_text }}</span>
  17 +
  18 + {% if form.comment.errors %}
  19 + <div class="alert alert-danger alert-dismissible" role="alert">
  20 + <button type="button" class="close" data-dismiss="alert" aria-label="Close">
  21 + <span aria-hidden="true">&times;</span>
  22 + </button>
  23 + <ul>
  24 + {% for error in form.comment.errors %}
  25 + <li>{{ error }}</li>
  26 + {% endfor %}
  27 + </ul>
  28 + </div>
  29 + {% endif %}
  30 + </div>
  31 + {% comment %}Area para anexar a imagem {% endcomment %}
  32 + <div class="form-group{% if form.has_error %} has-error {% endif %} is-fileinput">
  33 + {% render_field form.image %}
  34 +
  35 + <div class="filedrag">
  36 + {% trans 'Click or drop the picture here' %}<br />
  37 +
  38 + <small>{% trans 'The picture could not exceed 5MB.' %}</small>
  39 + </div>
  40 +
  41 + {% if form.image.errors %}
  42 + <div class="alert alert-danger alert-dismissible" role="alert">
  43 + <button type="button" class="close" data-dismiss="alert" aria-label="Close">
  44 + <span aria-hidden="true">&times;</span>
  45 + </button>
  46 + <ul>
  47 + {% for error in form.image.errors %}
  48 + <li>{{ error }}</li>
  49 + {% endfor %}
  50 + </ul>
  51 + </div>
  52 + {% endif %}
  53 +
  54 + </div>
  55 + </form>
  56 + </div>
  57 + <!-- Modal Footer -->
  58 + <div id="delete-category-footer"class="modal-footer">
  59 + <!-- Don't remove that!!! -->
  60 + <button type="button" class="btn btn-default btn-raised" data-dismiss="modal">{% trans "Close" %}</button>
  61 + <a href="javascript:void(0)" onclick="return sendMessage()" form="text_chat_form" class="btn btn-success btn-raised erase-button">{% trans "Send" %}</a>
  62 + </div>
  63 + </div>
  64 + </div>
  65 +</div>
  66 +
  67 +<script type="text/javascript">
  68 +
  69 + $('.text_simple_wysiwyg').summernote({
  70 + dialogsInBody: true,
  71 + disableDragAndDrop: true,
  72 + height: 150,
  73 + toolbar: [
  74 + // [groupName, [list of button]]
  75 + ['style', ['bold', 'italic']],
  76 + ['insert', ['link']]
  77 + ]
  78 + });
  79 +
  80 + if (window.File && window.FileList && window.FileReader) {
  81 + Init();
  82 + }
  83 +
  84 + function Init() {
  85 + var small = $("#id_image"),
  86 + filedrag = $(".filedrag"),
  87 + common = $(".common-file-input");
  88 +
  89 + // file select
  90 + small.on("change", FileSelectHandler);
  91 +
  92 + // is XHR2 available?
  93 + var xhr = new XMLHttpRequest();
  94 + if (xhr.upload) {
  95 + // file drop
  96 + filedrag.on("drop", FileSelectHandler);
  97 + filedrag.attr('style', 'display:block');
  98 + common.attr('style', 'display:none');
  99 + }
  100 + }
  101 +
  102 + // file selection
  103 + function FileSelectHandler(e) {
  104 + var files = e.target.files || e.dataTransfer.files,
  105 + parent = $(e.target.offsetParent);
  106 +
  107 + // process all File objects
  108 + for (var i = 0, f; f = files[i]; i++) {
  109 + parent.find('.filedrag').html(f.name);
  110 + }
  111 + }
  112 +</script>
0 \ No newline at end of file 113 \ No newline at end of file
youtube_video/urls.py
@@ -11,4 +11,6 @@ urlpatterns = [ @@ -11,4 +11,6 @@ urlpatterns = [
11 url(r'^view/(?P<slug>[\w_-]+)/$', views.InsideView.as_view(), name = 'view'), 11 url(r'^view/(?P<slug>[\w_-]+)/$', views.InsideView.as_view(), name = 'view'),
12 url(r'^watch/(?P<ytvideo>[\w_-]+)/$', views.ytvideo_watch_log, name = 'watch'), 12 url(r'^watch/(?P<ytvideo>[\w_-]+)/$', views.ytvideo_watch_log, name = 'watch'),
13 url(r'^finish/(?P<ytvideo>[\w_-]+)/$', views.ytvideo_finish_log, name = 'finish'), 13 url(r'^finish/(?P<ytvideo>[\w_-]+)/$', views.ytvideo_finish_log, name = 'finish'),
  14 + url(r'^chart/(?P<slug>[\w_-]+)/$', views.StatisticsView.as_view(), name = 'get_chart'),
  15 + url(r'^send-message/(?P<slug>[\w_-]+)/$', views.SendMessage.as_view(), name = 'send_message'),
14 ] 16 ]
youtube_video/views.py
@@ -18,6 +18,16 @@ from topics.models import Topic @@ -18,6 +18,16 @@ from topics.models import Topic
18 from .forms import YTVideoForm, InlinePendenciesFormset 18 from .forms import YTVideoForm, InlinePendenciesFormset
19 from .models import YTVideo 19 from .models import YTVideo
20 20
  21 +import datetime
  22 +from log.models import Log
  23 +from chat.models import Conversation, TalkMessages
  24 +from users.models import User
  25 +from subjects.models import Subject
  26 +
  27 +from webpage.forms import FormModalMessage
  28 +
  29 +from django.db.models import Q
  30 +
21 class NewWindowView(LoginRequiredMixin, LogMixin, generic.DetailView): 31 class NewWindowView(LoginRequiredMixin, LogMixin, generic.DetailView):
22 log_component = 'resources' 32 log_component = 'resources'
23 log_action = 'view' 33 log_action = 'view'
@@ -460,4 +470,167 @@ def ytvideo_finish_log(request, ytvideo): @@ -460,4 +470,167 @@ def ytvideo_finish_log(request, ytvideo):
460 470
461 request.log_context = log_context 471 request.log_context = log_context
462 472
463 - return JsonResponse({'message': 'ok'})  
464 \ No newline at end of file 473 \ No newline at end of file
  474 + return JsonResponse({'message': 'ok'})
  475 +
  476 +
  477 +class StatisticsView(LoginRequiredMixin, LogMixin, generic.DetailView):
  478 + log_component = 'resources'
  479 + log_action = 'view_statistics'
  480 + log_resource = 'ytvideo'
  481 + log_context = {}
  482 +
  483 + login_url = reverse_lazy("users:login")
  484 + redirect_field_name = 'next'
  485 + model = YTVideo
  486 + template_name = 'youtube/relatorios.html'
  487 +
  488 + def dispatch(self, request, *args, **kwargs):
  489 + slug = self.kwargs.get('slug', '')
  490 + ytvideo = get_object_or_404(YTVideo, slug = slug)
  491 +
  492 + if not has_subject_permissions(request.user, ytvideo.topic.subject):
  493 + return redirect(reverse_lazy('subjects:home'))
  494 +
  495 + return super(StatisticsView, self).dispatch(request, *args, **kwargs)
  496 +
  497 + def get_context_data(self, **kwargs):
  498 + context = super(StatisticsView, self).get_context_data(**kwargs)
  499 +
  500 + self.log_context['category_id'] = self.object.topic.subject.category.id
  501 + self.log_context['category_name'] = self.object.topic.subject.category.name
  502 + self.log_context['category_slug'] = self.object.topic.subject.category.slug
  503 + self.log_context['subject_id'] = self.object.topic.subject.id
  504 + self.log_context['subject_name'] = self.object.topic.subject.name
  505 + self.log_context['subject_slug'] = self.object.topic.subject.slug
  506 + self.log_context['topic_id'] = self.object.topic.id
  507 + self.log_context['topic_name'] = self.object.topic.name
  508 + self.log_context['topic_slug'] = self.object.topic.slug
  509 + self.log_context['ytvideo_id'] = self.object.id
  510 + self.log_context['ytvideo_name'] = self.object.name
  511 + self.log_context['ytvideo_slug'] = self.object.slug
  512 +
  513 + super(StatisticsView, self).createLog(self.request.user, self.log_component, self.log_action, self.log_resource, self.log_context)
  514 +
  515 +
  516 + context['title'] = _('Youtube Video Reports')
  517 +
  518 + slug = self.kwargs.get('slug')
  519 + ytvideo = get_object_or_404(YTVideo, slug = slug)
  520 + print (self.request.GET.get('init_date',''))
  521 + date_format = "%d/%m/%Y %H:%M" if self.request.GET.get('language','') == 'pt-br' else "%m/%d/%Y %I:%M %p"
  522 + if self.request.GET.get('language','') == "":
  523 + start_date = datetime.datetime.now() - datetime.timedelta(30)
  524 + end_date = datetime.datetime.now()
  525 + else :
  526 + start_date = datetime.datetime.strptime(self.request.GET.get('init_date',''),date_format)
  527 + end_date = datetime.datetime.strptime(self.request.GET.get('end_date',''),date_format)
  528 + context["init_date"] = start_date
  529 + context["end_date"] = end_date
  530 + alunos = ytvideo.students.all()
  531 + if ytvideo.all_students :
  532 + alunos = ytvideo.topic.subject.students.all()
  533 +
  534 + vis_ou = Log.objects.filter(context__contains={'ytvideo_id':ytvideo.id},resource="ytvideo",user_email__in=(aluno.email for aluno in alunos), datetime__range=(start_date,end_date + datetime.timedelta(minutes = 1))).filter(Q(action="view") | Q(action="watch") | Q(action="finish"))
  535 + did,n_did,history = str(_("Realized")),str(_("Unrealized")),str(_("Historic"))
  536 + re = []
  537 + data_n_did,data_history = [],[]
  538 + json_n_did, json_history = {},{}
  539 +
  540 + from django.db.models import Count, Max
  541 + views_user = vis_ou.values("user_email").annotate(views=Count("user_email"))
  542 + date_last = vis_ou.values("user_email").annotate(last=Max("datetime"))
  543 +
  544 + for log_al in vis_ou.order_by("datetime"):
  545 + data_history.append([str(alunos.get(email=log_al.user_email)),
  546 + ", ".join([str(x) for x in ytvideo.topic.subject.group_subject.filter(participants__email=log_al.user_email)]),
  547 + log_al.action,log_al.datetime])
  548 + json_history["data"] = data_history
  549 +
  550 + column_view,column_watch,column_finish = str(_('View')),str(_('Watch')),str(_('Finish'))
  551 +
  552 + not_view = alunos.exclude(email__in=[log.user_email for log in vis_ou.filter(action="view").distinct("user_email")])
  553 + index = 0
  554 + for alun in not_view:
  555 + data_n_did.append([index,str(alun),", ".join([str(x) for x in ytvideo.topic.subject.group_subject.filter(participants__email=alun.email)]),column_view, str(alun.email)])
  556 + index += 1
  557 +
  558 + not_watch = alunos.exclude(email__in=[log.user_email for log in vis_ou.filter(action="watch").distinct("user_email")])
  559 + for alun in not_watch:
  560 + data_n_did.append([index,str(alun),", ".join([str(x) for x in ytvideo.topic.subject.group_subject.filter(participants__email=alun.email)]),column_watch, str(alun.email)])
  561 + index += 1
  562 +
  563 + not_finish = alunos.exclude(email__in=[log.user_email for log in vis_ou.filter(action="finish").distinct("user_email")])
  564 + for alun in not_finish:
  565 + data_n_did.append([index,str(alun),", ".join([str(x) for x in ytvideo.topic.subject.group_subject.filter(participants__email=alun.email)]),column_finish, str(alun.email)])
  566 + index += 1
  567 +
  568 + json_n_did["data"] = data_n_did
  569 +
  570 +
  571 + context["json_n_did"] = json_n_did
  572 + context["json_history"] = json_history
  573 + c_visualizou = vis_ou.filter(action="view").distinct("user_email").count()
  574 + c_watch = vis_ou.filter(action="watch").distinct("user_email").count()
  575 + c_finish = vis_ou.filter(action="finish").distinct("user_email").count()
  576 + re.append([str(_('Youtube Video')),did,n_did])
  577 +
  578 + re.append([column_view,c_visualizou, alunos.count() - c_visualizou])
  579 + re.append([column_watch,c_watch, alunos.count() - c_watch])
  580 + re.append([column_finish,c_finish, alunos.count() - c_finish])
  581 +
  582 + context['view'] = column_view
  583 + context['watch'] = column_watch
  584 + context['finish'] = column_finish
  585 + context['topic'] = ytvideo.topic
  586 + context['subject'] = ytvideo.topic.subject
  587 + context['youtube'] = ytvideo
  588 + context['db_data'] = re
  589 + context['title_chart'] = _('Actions about resource')
  590 + context['title_vAxis'] = _('Quantity')
  591 +
  592 + context["n_did_table"] = n_did
  593 + context["did_table"] = did
  594 + context["history_table"] = history
  595 + return context
  596 +
  597 +
  598 +
  599 +class SendMessage(LoginRequiredMixin, LogMixin, generic.edit.FormView):
  600 + log_component = 'resources'
  601 + log_action = 'send'
  602 + log_resource = 'ytvideo'
  603 + log_context = {}
  604 +
  605 + login_url = reverse_lazy("users:login")
  606 + redirect_field_name = 'next'
  607 +
  608 + template_name = 'youtube/send_message.html'
  609 + form_class = FormModalMessage
  610 +
  611 + def dispatch(self, request, *args, **kwargs):
  612 + slug = self.kwargs.get('slug', '')
  613 + ytvideo = get_object_or_404(YTVideo, slug = slug)
  614 + self.ytvideo = ytvideo
  615 +
  616 + if not has_subject_permissions(request.user, ytvideo.topic.subject):
  617 + return redirect(reverse_lazy('subjects:home'))
  618 +
  619 + return super(SendMessage, self).dispatch(request, *args, **kwargs)
  620 +
  621 + def form_valid(self, form):
  622 + message = form.cleaned_data.get('comment')
  623 + image = form.cleaned_data.get("image")
  624 + users = (self.request.POST.get('users[]','')).split(",")
  625 + user = self.request.user
  626 + subject = self.ytvideo.topic.subject
  627 + for u in users:
  628 + to_user = User.objects.get(email=u)
  629 + talk, create = Conversation.objects.get_or_create(user_one=user,user_two=to_user)
  630 + created = TalkMessages.objects.create(text=message,talk=talk,user=user,subject=subject,image=image)
  631 + return JsonResponse({"message":"ok"})
  632 +
  633 + def get_context_data(self, **kwargs):
  634 + context = super(SendMessage,self).get_context_data()
  635 + context["ytvideo"] = get_object_or_404(YTVideo, slug=self.kwargs.get('slug', ''))
  636 + return context
  637 +