Spaces:
Sleeping
Sleeping
Descarga de datos para sesion con PF
Browse files
tecnicas/static/js/download-table-zip.js
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
document.addEventListener("DOMContentLoaded", function () {
|
| 2 |
+
const btn = document.getElementById("download-csv-btn");
|
| 3 |
+
if (!btn) return;
|
| 4 |
+
|
| 5 |
+
btn.addEventListener("click", async function () {
|
| 6 |
+
if (typeof JSZip === "undefined" || typeof saveAs === "undefined") {
|
| 7 |
+
alert(
|
| 8 |
+
"Librerías JSZip o FileSaver no están cargadas. Asegúrate de incluir los CDN de JSZip y FileSaver."
|
| 9 |
+
);
|
| 10 |
+
return;
|
| 11 |
+
}
|
| 12 |
+
|
| 13 |
+
const sections = document.querySelectorAll("section[data-tester]");
|
| 14 |
+
if (!sections || sections.length === 0) {
|
| 15 |
+
alert("No hay tablas para descargar.");
|
| 16 |
+
return;
|
| 17 |
+
}
|
| 18 |
+
|
| 19 |
+
const zip = new JSZip();
|
| 20 |
+
|
| 21 |
+
let zipName = "";
|
| 22 |
+
|
| 23 |
+
sections.forEach((sec) => {
|
| 24 |
+
const tester = sec.getAttribute("data-tester") || "tester";
|
| 25 |
+
const sessionName = sec.getAttribute("data-session-name") || "";
|
| 26 |
+
const sessionCode = sec.getAttribute("data-session-code") || "";
|
| 27 |
+
|
| 28 |
+
const fileName = `${tester}_${
|
| 29 |
+
sessionName ? sessionName.trim() : sessionCode.trim()
|
| 30 |
+
}`;
|
| 31 |
+
|
| 32 |
+
zipName = `datos_sesion_${
|
| 33 |
+
sessionName ? sessionName.trim() : sessionCode.trim()
|
| 34 |
+
}`;
|
| 35 |
+
|
| 36 |
+
const table = sec.querySelector("table");
|
| 37 |
+
if (!table) return;
|
| 38 |
+
|
| 39 |
+
// Build CSV
|
| 40 |
+
const rows = [];
|
| 41 |
+
const headerCells = Array.from(table.querySelectorAll("thead tr th"));
|
| 42 |
+
const headers = headerCells.map((h) => h.textContent.trim());
|
| 43 |
+
rows.push(headers.map(escapeCsv).join(","));
|
| 44 |
+
|
| 45 |
+
const trs = table.querySelectorAll("tbody tr");
|
| 46 |
+
trs.forEach((tr) => {
|
| 47 |
+
const tds = Array.from(tr.querySelectorAll("td"));
|
| 48 |
+
const values = tds.map((td) => escapeCsv(td.textContent.trim()));
|
| 49 |
+
rows.push(values.join(","));
|
| 50 |
+
});
|
| 51 |
+
|
| 52 |
+
const csvContent = rows.join("\r\n");
|
| 53 |
+
zip.file(`${fileName}.csv`, csvContent);
|
| 54 |
+
});
|
| 55 |
+
|
| 56 |
+
try {
|
| 57 |
+
const blob = await zip.generateAsync({ type: "blob" });
|
| 58 |
+
const zipNameWithExtension = zipName + ".zip";
|
| 59 |
+
saveAs(blob, zipNameWithExtension);
|
| 60 |
+
} catch (err) {
|
| 61 |
+
console.error(err);
|
| 62 |
+
alert("Error al generar el ZIP: " + err.message);
|
| 63 |
+
}
|
| 64 |
+
});
|
| 65 |
+
|
| 66 |
+
const escapeCsv = (val) => {
|
| 67 |
+
if (val == null) return "";
|
| 68 |
+
let normalVal = val.normalize("NFD").replace(/[\u0300-\u036f]/g, "");
|
| 69 |
+
const needsQuotes = /[",\n,]/.test(normalVal);
|
| 70 |
+
let v = String(normalVal).replace(/"/g, '""');
|
| 71 |
+
if (needsQuotes) v = `"${v}"`;
|
| 72 |
+
return v;
|
| 73 |
+
};
|
| 74 |
+
});
|
tecnicas/templates/tecnicas/components/table_pf.html
CHANGED
|
@@ -1,9 +1,11 @@
|
|
| 1 |
{% load static %}
|
| 2 |
-
|
|
|
|
|
|
|
| 3 |
<h3 class="text-xl font-bold">Datos de usuario {{ data.tester }}</h3>
|
| 4 |
|
| 5 |
<div class="overflow-x-auto rounded-lg border border-surface-general">
|
| 6 |
-
<table
|
| 7 |
<thead class="bg-surface-sweet text-black font-semibold">
|
| 8 |
<tr>
|
| 9 |
<th class="py-2 px-3 border border-surface-general">Repetición</th>
|
|
@@ -15,33 +17,23 @@
|
|
| 15 |
</thead>
|
| 16 |
<tbody class="bg-surface-ligt divide-y divide-gray-200">
|
| 17 |
{% for repeticion, data_product in data.ratings.items %}
|
| 18 |
-
|
| 19 |
-
|
| 20 |
-
|
| 21 |
-
|
| 22 |
-
|
| 23 |
-
|
| 24 |
-
|
| 25 |
-
|
| 26 |
-
|
| 27 |
-
|
| 28 |
-
|
| 29 |
-
|
| 30 |
-
{% endfor %}
|
| 31 |
-
{% if match %}0{% endif %}
|
| 32 |
-
{% endwith %}
|
| 33 |
-
</td>
|
| 34 |
-
{% endfor %}
|
| 35 |
-
</tr>
|
| 36 |
{% endfor %}
|
|
|
|
|
|
|
| 37 |
{% endfor %}
|
| 38 |
</tbody>
|
| 39 |
</table>
|
| 40 |
</div>
|
| 41 |
-
|
| 42 |
-
<div class="flex justify-end mt-3">
|
| 43 |
-
<button id="download-csv-btn" class="cts-btn-general cts-btn-primary btn-push">
|
| 44 |
-
Descargar CSV
|
| 45 |
-
</button>
|
| 46 |
-
</div>
|
| 47 |
</section>
|
|
|
|
| 1 |
{% load static %}
|
| 2 |
+
|
| 3 |
+
<section data-tester="{{ data.tester }}" {% if session_name %} data-session-name="{{ session_name }}" {% endif %}
|
| 4 |
+
data-session-code="{{ session_code }}">
|
| 5 |
<h3 class="text-xl font-bold">Datos de usuario {{ data.tester }}</h3>
|
| 6 |
|
| 7 |
<div class="overflow-x-auto rounded-lg border border-surface-general">
|
| 8 |
+
<table class="convencional-table min-w-max w-full text-sm text-center border-collapse">
|
| 9 |
<thead class="bg-surface-sweet text-black font-semibold">
|
| 10 |
<tr>
|
| 11 |
<th class="py-2 px-3 border border-surface-general">Repetición</th>
|
|
|
|
| 17 |
</thead>
|
| 18 |
<tbody class="bg-surface-ligt divide-y divide-gray-200">
|
| 19 |
{% for repeticion, data_product in data.ratings.items %}
|
| 20 |
+
{% for codigo, valores in data_product.items %}
|
| 21 |
+
<tr>
|
| 22 |
+
<td class="py-2 px-3 border border-surface-general">{{ repeticion }}</td>
|
| 23 |
+
<td class="py-2 px-3 border border-surface-general">{{ codigo }}</td>
|
| 24 |
+
{% for word in data.words %}
|
| 25 |
+
<td class="py-2 px-3 border border-surface-general">
|
| 26 |
+
{% for valor in valores %}
|
| 27 |
+
{% if valor.nombre_palabra == word.nombre_palabra %}
|
| 28 |
+
{{ valor.dato_valor }}
|
| 29 |
+
{% endif %}
|
| 30 |
+
{% endfor %}
|
| 31 |
+
</td>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 32 |
{% endfor %}
|
| 33 |
+
</tr>
|
| 34 |
+
{% endfor %}
|
| 35 |
{% endfor %}
|
| 36 |
</tbody>
|
| 37 |
</table>
|
| 38 |
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 39 |
</section>
|
tecnicas/templates/tecnicas/manage_sesions/details-session-pf.html
CHANGED
|
@@ -218,11 +218,16 @@
|
|
| 218 |
</article>
|
| 219 |
|
| 220 |
{% if data_ratings %}
|
| 221 |
-
<article class="overflow-x-auto py-2">
|
| 222 |
{% for data_tester in data_ratings %}
|
| 223 |
-
|
| 224 |
{% endfor %}
|
| 225 |
</article>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 226 |
{% else %}
|
| 227 |
{% include "../components/error-message.html" with message='Sin datos por mostrar aún' %}
|
| 228 |
{% endif %}
|
|
@@ -238,6 +243,9 @@
|
|
| 238 |
{% endblock %}
|
| 239 |
|
| 240 |
{% block extra_js %}
|
|
|
|
|
|
|
|
|
|
| 241 |
<script src="{% static 'js/details-session.js' %}"></script>
|
| 242 |
<script src="{% static 'js/showHiddenElement.js' %}"></script>
|
| 243 |
{% endblock %}
|
|
|
|
| 218 |
</article>
|
| 219 |
|
| 220 |
{% if data_ratings %}
|
| 221 |
+
<article class="overflow-x-auto py-2 space-y-4">
|
| 222 |
{% for data_tester in data_ratings %}
|
| 223 |
+
{% include "../components/table_pf.html" with data=data_tester session_name=sesion.nombre_sesion session_code=sesion.codigo_sesion %}
|
| 224 |
{% endfor %}
|
| 225 |
</article>
|
| 226 |
+
<div class="flex justify-end mt-3">
|
| 227 |
+
<button id="download-csv-btn" class="cts-btn-general cts-btn-primary btn-push">
|
| 228 |
+
Descargar datos como CSV en zip
|
| 229 |
+
</button>
|
| 230 |
+
</div>
|
| 231 |
{% else %}
|
| 232 |
{% include "../components/error-message.html" with message='Sin datos por mostrar aún' %}
|
| 233 |
{% endif %}
|
|
|
|
| 243 |
{% endblock %}
|
| 244 |
|
| 245 |
{% block extra_js %}
|
| 246 |
+
<script src="https://cdnjs.cloudflare.com/ajax/libs/jszip/3.10.1/jszip.min.js" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
|
| 247 |
+
<script src="https://cdnjs.cloudflare.com/ajax/libs/FileSaver.js/2.0.5/FileSaver.min.js" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
|
| 248 |
+
<script src="{% static 'js/download-table-zip.js' %}"></script>
|
| 249 |
<script src="{% static 'js/details-session.js' %}"></script>
|
| 250 |
<script src="{% static 'js/showHiddenElement.js' %}"></script>
|
| 251 |
{% endblock %}
|