dataConsolidate.html 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350
  1. <!DOCTYPE html>
  2. <html xmlns="http://www.w3.org/1999/xhtml"
  3. xmlns:th="http://www.thymeleaf.org">
  4. <head th:replace="~{layouts/common.html :: head}"></head>
  5. <body id="page-top">
  6. <!-- Navigation -->
  7. <nav th:replace="~{layouts/common.html :: navbar}"></nav>
  8. <!-- Content -->
  9. <div class="content uv-content d-flex" id="uv-wrapper">
  10. <div class="bg-light border-right" id="uv-sidebar-wrapper" th:replace="~{layouts/sidebar.html :: sidebar}"></div>
  11. <div class="container uv-home-section navVisible" id="uv-content-wrapper">
  12. <div class="uv-loading-spinner" th:text="#{global.loading}"></div>
  13. <div class="col-sm-12"></div>
  14. <div class="uv-container">
  15. <div class="uv-table-group-procedure-info" style="margin-bottom:20px;margin-top:30px;cursor:auto;">
  16. <div class="uv-table-title">
  17. <h6 class="uv-table-header-h6" th:text="#{data.consolide.title}"></h6>
  18. <hr class="uv-procedure-hr">
  19. <span th:text="#{data.consolide.subtitle}"></span>
  20. </div>
  21. </div>
  22. <div class="uv-table-group-procedure row" style="padding:20px;">
  23. <select class="selectpicker" name="enquesta" data-live-search="true" data-width="100%" data-actions-box="true" th:attr="data-none-selected-text=#{global.selectors.noData}" required>
  24. <option disabled selected th:text="#{data.input.select}">Selecciona un conjunto de datos</option>
  25. <option value="dades_1er">[Grado] Estudiantes primero (dades_1er)</option>
  26. <option value="dades_3er">[Grado] Estudiantes tercero (dades_3er)</option>
  27. <option value="dades_graduats">[Grado] Graduados (dades_graduats)</option>
  28. <option value="profes">[Grado] Profesores (profes)</option>
  29. <option value="data">[Master] Estudiantes (data)</option>
  30. <option value="data_g">[Master] Graduados (data_g)</option>
  31. <option value="profes_tancades">[Master] Profesores (profes_tancades)</option>
  32. <option value="doc_estud">[Doctorado] Estudiantes (doc_estud)</option>
  33. <option value="doc_etesi">[Doctorado] Graduados (doc_etesi)</option>
  34. <option value="doc_prof">[Doctorado] Profesores (doc_prof)</option>
  35. <option value="doc_inds">[Doctorado] Indicadores (doc_inds)</option>
  36. <option value="doc_tasas">[Doctorado] Tasas (doc_tasas)</option>
  37. <option value="doc_recom">[Doctorado] Recomendaciones (doc_recom)</option>
  38. <option value="evalprof">[Evaluación del profesorado] (evalprof)</option>
  39. <option value="dadespas">[PAS] Encuestas PAS (dadespas)</option>
  40. <option value="otros">[Indicadores] Profesorado + Tasas</option>
  41. <option value="sprodw">[Indicadores] Indicadores</option>
  42. <option value="docentia">[Docentia] Evaluación Docentia</option>
  43. <option value="enquestes">[SAE/SAEM] Asignaturas para encuestas (enquestes)</option>
  44. </select>
  45. <div class="uv-table-group-procedure" style="padding-left:20px;padding-top:20px;">
  46. <span class="btn btn-primary" onclick="run();"><i class="fas fa-clipboard-check"></i> <span th:text="#{data.btn.check}">Comprobar</span></span>
  47. </div>
  48. </div>
  49. <div id="resultsContainer" class="uv-table-group-procedure" style="padding-left:20px;padding-top:20px;cursor:auto;">
  50. </div>
  51. </div>
  52. </div>
  53. </div>
  54. <!-- contactModal -->
  55. <div th:replace="~{layouts/common.html :: contactModal}"></div>
  56. <!-- Footer -->
  57. <footer class="uv-footer uv-footer-text" th:replace="~{layouts/common.html :: footer}"></footer>
  58. <script th:src="@{/js/jquery/jquery.min.js}"></script>
  59. <script th:src="@{/js/popper.js}"></script>
  60. <script th:src="@{/js/bootstrap/bootstrap.min.js}"></script>
  61. <script th:src="@{/js/fa/all.js}"></script>
  62. <script th:src="@{/js/jquery/jquery.dataTables.min.js}"></script>
  63. <script th:src="@{/js/jquery/jquery.dataTables.responsive.min.js}"></script>
  64. <script th:src="@{/js/jquery/jquery.dataTables.rowReorder.min.js}"></script>
  65. <script th:src="@{/js/bootstrap/dataTables.bootstrap4.min.js}"></script>
  66. <script th:src="@{/js/jquery-easing/jquery.easing.min.js}"></script>
  67. <script th:src="@{/js/saic.js}"></script>
  68. <script th:src="@{/js/datepicker/bootstrap-datepicker.min.js}"></script>
  69. <script th:src="@{/js/bootstrap-select/bootstrap-select.js}"></script>
  70. <script th:src="@{/js/bootstrap-select/i18n/defaults-es_ES.js}" th:if="${#locale.language} == 'es'"></script>
  71. <script th:src="@{/js/bootstrap-select/i18n/defaults-ca_CA.js}" th:if="${#locale.language} != 'es'"></script>
  72. <script type="text/javascript">
  73. var locale = '[[${#locale.language}]]';
  74. var orderCol1 = [3, 'asc'], orderCol2 = [1, 'asc'];
  75. var cursorPosition;
  76. var numPending;
  77. var tabParams = {
  78. paging: true,
  79. language:{
  80. "lengthMenu": "[[#{admin.stats.table.lengthMenu}]]",
  81. "zeroRecords": "[[#{admin.stats.table.zeroRecords}]]",
  82. "info": "[[#{admin.stats.table.info}]]",
  83. "infoEmpty": "[[#{admin.stats.table.infoEmpty}]]",
  84. "infoFiltered": "[[#{admin.stats.table.infoFiltered}]]",
  85. "paginate": {
  86. "previous": "[[#{admin.stats.table.previous}]]",
  87. "next": "[[#{admin.stats.table.next}]]"
  88. }
  89. },
  90. searching: true,
  91. order:[orderCol1, orderCol2],
  92. orderCellsTop: true,
  93. //fixedHeader: true, // Not compatible with android
  94. info: false,
  95. responsive: false,
  96. initComplete: function () {
  97. var api = this.api();
  98. this.api()
  99. .columns()
  100. .eq(0)
  101. .each(function (colIdx) {
  102. var cell = $('.filters th').eq(
  103. $(api.column(colIdx).header()).index()
  104. );
  105. var title = $(cell).text();
  106. $(cell).html('<input type="text" placeholder="' + title + '" />');
  107. $('input', $('.filters th').eq($(api.column(colIdx).header()).index()))
  108. .off('keyup change')
  109. .on('change', function (e) {
  110. $(this).attr('title', $(this).val());
  111. var regexr = '({search})';
  112. cursorPosition = this.selectionStart;
  113. api.column(colIdx)
  114. .search(
  115. this.value != ''
  116. ? regexr.replace('{search}', '(((' + this.value + ')))')
  117. : '',
  118. this.value != '',
  119. this.value == ''
  120. )
  121. .draw();
  122. })
  123. .on('keyup', function (e) {
  124. e.preventDefault();
  125. e.stopPropagation();
  126. $(this).trigger('change');
  127. $(this)
  128. .focus()[0]
  129. .setSelectionRange(cursorPosition, cursorPosition);
  130. });
  131. });
  132. }
  133. };
  134. $( document ).ready(function(){
  135. layout = new Layout("");
  136. layout.initTableLayout({paging:false});
  137. layout.closeLoadingSpinner(".uv-loading-spinner");
  138. });
  139. function showSpinner(){
  140. var spinner = `<div class="d-flex justify-content-center">
  141. <div class="spinner-border text-primary" role="status" style="font-size: 150%; text-align: center; width: 100px; height: 100px;">
  142. <span class="sr-only">Loading...</span>
  143. </div>
  144. </div>
  145. `;
  146. $('#resultsContainer').html(spinner);
  147. }
  148. function run(){
  149. showSpinner();
  150. $.post("/data/count", {enquesta:$('select[name="enquesta"]:enabled').val()})
  151. .done(function(d){
  152. if(d == 0){
  153. $('#resultsContainer').html(`[INFO] [[#{data.consolide.nodata}]]`);
  154. }
  155. else{
  156. numPending = d;
  157. checkDuplicates();
  158. }
  159. });
  160. }
  161. function consolidate(){
  162. showSpinner();
  163. $.post("/data/consolidate", {enquesta:$('select[name="enquesta"]:enabled').val()})
  164. .done(function(d){
  165. if(d == -1){
  166. $('#resultsContainer').html(`
  167. <div class="uv-table-group-procedure" style="margin-bottom:50px;cursor:default;">
  168. <span style="color:red;">[ERROR] </span>
  169. <span>
  170. [[#{data.consolide.err3}]]
  171. </span>
  172. </div>`);
  173. }
  174. else{
  175. $('#resultsContainer').html(`
  176. <div class="uv-table-group-procedure" style="margin-bottom:50px;cursor:default;">
  177. <span style="color:green;">[INFO] </span><span> [[#{data.consolide.ok}]] </span>
  178. </div>`);
  179. }
  180. });
  181. }
  182. function checkDuplicates(){
  183. $.post("/data/check/1", {enquesta:$('select[name="enquesta"]:enabled').val()})
  184. .done(function(data) {
  185. var msgErr = `
  186. <div class="uv-table-group-procedure" style="margin-bottom:50px;cursor:default;">
  187. <span style="color:red;">[ERROR] </span>
  188. <span>
  189. [[#{data.consolide.err1}]] <br>
  190. [[#{data.consolide.count}]]: ${numPending}<br>
  191. [[#{data.consolide.tabdesc}]]
  192. </span>
  193. </div>
  194. <div>
  195. <p><strong>[[#{data.consolide.actions.info}]]</strong></p>
  196. <span class="btn btn-secondary pointer" onclick="fixDuplicationIssues();"><i class="fas fa-cog"></i> [[#{data.consolide.actions.action1}]]</span>
  197. </div>
  198. `;
  199. if(data.length > 0){
  200. drawTable(data, msgErr);
  201. }
  202. else {
  203. checkIntegrity();
  204. }
  205. }
  206. );
  207. }
  208. function checkIntegrity(){
  209. $.post("/data/check/2", {enquesta:$('select[name="enquesta"]:enabled').val()})
  210. .done(function(data) {
  211. var msgOk = `
  212. <div class="uv-table-group-procedure" style="margin-bottom:50px;cursor:default;">
  213. <span style="color:green;">[INFO] </span>
  214. <span> [[#{data.consolide.noerr}]].</span>
  215. <span> [[#{data.consolide.count}]]: ${numPending} </span>
  216. </div>
  217. <div class="uv-table-group-procedure" style="padding-left:20px;padding-top:20px;cursor:default;">
  218. <span class="btn btn-primary" onclick="consolidate();"><i class="fas fa-clone"></i> <span>[[#{data.btn.run}]]</span></span>
  219. </div>`;
  220. var msgErr = `
  221. <div class="uv-table-group-procedure" style="margin-bottom:50px;cursor:default;">
  222. <span style="color:red;">[ERROR] </span>
  223. <span>
  224. [[#{data.consolide.err2}]] <br>
  225. [[#{data.consolide.count}]]: ${numPending}<br>
  226. [[#{data.consolide.tabdesc}]]
  227. </span>
  228. <div style="margin-top:10px;">
  229. <span><strong>[[#{data.consolide.actions.info}]]:</strong></span><br>
  230. <span class="btn btn-secondary pointer" onclick="fixIntegrityIssues('current')"><i class="fas fa-cog"></i> [[#{data.consolide.actions.action2}]]</span>
  231. <span class="btn btn-secondary pointer" onclick="fixIntegrityIssues('new')"><i class="fas fa-cog"></i> [[#{data.consolide.actions.action3}]]</span>
  232. </div>
  233. </div>
  234. `;
  235. if(data.length > 0){
  236. drawTable(data, msgErr);
  237. }
  238. else {
  239. $('#resultsContainer').html(`
  240. ${msgOk}
  241. `);
  242. }
  243. }
  244. );
  245. }
  246. function drawTable(data, msgErr){
  247. var trs = '';
  248. data.forEach(function(d){
  249. trs += `
  250. <tr>
  251. <td>${d.curs}</td>
  252. <td>${d.titulacio == null ? '' : d.titulacio}</td>
  253. <td>${d.centre == null ? '' : d.centre}</td>
  254. <td>${d.ambit}</td>
  255. <td>${d.tipus}</td>
  256. <td>${d.indicador}</td>
  257. </tr>
  258. `;});
  259. if(data.length > 0){
  260. $('#resultsContainer').html(`
  261. ${msgErr}
  262. <div class="uv-table-group-procedure" style="cursor:default;">
  263. <table class="table table-striped table-bordered display responsive no-wrap" style="margin-bottom:50px;">
  264. <thead>
  265. <tr>
  266. <th class="uv-table">[[#{data.table.0}]]</th>
  267. <th class="uv-table">[[#{data.table.1}]]</th>
  268. <th class="uv-table">[[#{data.table.2}]]</th>
  269. <th class="uv-table">[[#{data.table.3}]]</th>
  270. <th class="uv-table">[[#{data.table.4}]]</th>
  271. <th class="uv-table">[[#{data.table.5}]]</th>
  272. </tr>
  273. </thead>
  274. <tbody>
  275. ${trs}
  276. </tbody>
  277. </table>
  278. </div>
  279. `);
  280. }
  281. else{
  282. $('#resultsContainer').html(`
  283. ${msgOk}
  284. `);
  285. }
  286. $('.table thead tr').clone(true)
  287. .addClass('filters')
  288. .appendTo('.table thead');
  289. $('.table').DataTable({
  290. searching: tabParams.searching,
  291. paging: tabParams.paging,
  292. orderCellsTop: tabParams.orderCellsTop,
  293. // fixedHeader: tabParams.fixedHeader, // Not compatible with Android
  294. info: tabParams.info,
  295. responsive: tabParams.responsive,
  296. order: tabParams.order,
  297. "language": ((!("language" in tabParams)) ? { "emptyTable": this.emptyMsg } : tabParams.language),
  298. initComplete: tabParams.initComplete
  299. });
  300. }
  301. function fixIntegrityIssues(deleteFrom){
  302. $.post("/data/fix/integrity/"+deleteFrom, {enquesta:$('select[name="enquesta"]:enabled').val()})
  303. .done(function(data) {
  304. alert("[[#{data.consolide.actions.msg}]]: "+data);
  305. checkIntegrity();
  306. }
  307. );
  308. }
  309. function fixDuplicationIssues(){
  310. $.post("/data/fix/duplication", {enquesta:$('select[name="enquesta"]:enabled').val()})
  311. .done(function(data) {
  312. alert("[[#{data.consolide.actions.msg}]]: "+data);
  313. checkIntegrity();
  314. }
  315. );
  316. }
  317. </script>
  318. </body>
  319. </html>