chartManD commited on
Commit
7baf813
·
1 Parent(s): 19b9959

Se refactoriza el codigo para usar modalidaes de napping, modificacion de modelos y creacion de DatoPunto para coordenadas

Browse files
tecnicas/controllers/__init__.py CHANGED
@@ -63,3 +63,5 @@ from .api_controller.rating_cata_controller import RatingCataController
63
  from .api_controller.rating_pf_list_controller import RatingPFListController
64
  from .views_controller.tester_list_controller import TesterListController
65
  from .api_controller.rating_sort_controller import RatingSortController
 
 
 
63
  from .api_controller.rating_pf_list_controller import RatingPFListController
64
  from .views_controller.tester_list_controller import TesterListController
65
  from .api_controller.rating_sort_controller import RatingSortController
66
+ from .api_controller.rating_napping_controller import RatingNappingController
67
+
tecnicas/controllers/api_controller/rating_napping_controller.py ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from django.http import JsonResponse
2
+ from django.http import HttpRequest
3
+
4
+ class RatingNappingController:
5
+ @staticmethod
6
+ def saveRating(request: HttpRequest, data: list):
7
+ print(data)
8
+
9
+ try:
10
+ return JsonResponse({"message": "Datos guardados exitosamente"})
11
+ except Exception as e:
12
+ return JsonResponse({"error": "Error al procesar datos"})
tecnicas/controllers/views_controller/session_management/details/details_napping_controller.py CHANGED
@@ -2,7 +2,7 @@ from django.http import HttpRequest
2
  from django.shortcuts import redirect
3
  from django.urls import reverse
4
  from .details_controller import DetallesController
5
- from tecnicas.models import SesionSensorial, Presentador, Modalidad
6
  from collections import defaultdict
7
 
8
 
@@ -20,12 +20,13 @@ class DetallesNappingController(DetallesController):
20
  self.defineStatus()
21
 
22
  modes = Modalidad.objects.all()
23
- technique_modes = self.session.tecnica.modalidad.all()
 
24
 
25
  if not technique_modes.exists():
26
  self.context["modes"] = modes
27
  else:
28
- use_modes = technique_modes.values_list("id", flat=True)
29
 
30
  self.context["modes"] = modes.exclude(
31
  id__in=use_modes)
@@ -45,9 +46,9 @@ class DetallesNappingController(DetallesController):
45
  self.context["status"] = "En espera de la siguiente acción"
46
 
47
  def controllPostResponse(self, request: HttpRequest, action: str):
48
- print(action)
49
  if action == "start_sin_modalidad":
50
- response = self.startNapping(request=request)
 
51
 
52
  elif action == "delete_session":
53
  self.deleteSesorialSession()
@@ -55,17 +56,23 @@ class DetallesNappingController(DetallesController):
55
  reverse("cata_system:panel_sesiones", kwargs={"page": 1}))
56
 
57
  else:
58
- response= self.controllGetResponse(
59
  error="Modalidad sin implantar", request=request)
60
 
61
  return response
62
 
63
- def startNapping(self, request: HttpRequest):
64
  if request.user.user_presentador.user.username != self.session.creadoPor.user.username:
65
  return self.controllGetResponse(error="Solo el presentador que crea la sesión puede iniciar la repetición", request=request)
66
  elif self.session.activo:
67
  return self.controllGetResponse(error="La sesión ya está activada", request=request)
68
 
 
 
 
 
 
 
69
  self.session.activo = True
70
  self.session.save()
71
 
 
2
  from django.shortcuts import redirect
3
  from django.urls import reverse
4
  from .details_controller import DetallesController
5
+ from tecnicas.models import SesionSensorial, Presentador, Modalidad, TecnicaModalidad
6
  from collections import defaultdict
7
 
8
 
 
20
  self.defineStatus()
21
 
22
  modes = Modalidad.objects.all()
23
+ technique_modes = TecnicaModalidad.objects.filter(
24
+ tecnica=self.session.tecnica)
25
 
26
  if not technique_modes.exists():
27
  self.context["modes"] = modes
28
  else:
29
+ use_modes = technique_modes.values_list("modalidad", flat=True)
30
 
31
  self.context["modes"] = modes.exclude(
32
  id__in=use_modes)
 
46
  self.context["status"] = "En espera de la siguiente acción"
47
 
48
  def controllPostResponse(self, request: HttpRequest, action: str):
 
49
  if action == "start_sin_modalidad":
50
+ name_mode = action.replace("start_", "").replace("_", " ")
51
+ response = self.startNapping(request=request, name_mode=name_mode)
52
 
53
  elif action == "delete_session":
54
  self.deleteSesorialSession()
 
56
  reverse("cata_system:panel_sesiones", kwargs={"page": 1}))
57
 
58
  else:
59
+ response = self.controllGetResponse(
60
  error="Modalidad sin implantar", request=request)
61
 
62
  return response
63
 
64
+ def startNapping(self, request: HttpRequest, name_mode: str):
65
  if request.user.user_presentador.user.username != self.session.creadoPor.user.username:
66
  return self.controllGetResponse(error="Solo el presentador que crea la sesión puede iniciar la repetición", request=request)
67
  elif self.session.activo:
68
  return self.controllGetResponse(error="La sesión ya está activada", request=request)
69
 
70
+ tecnique_mode = TecnicaModalidad.objects.get_or_create(
71
+ tecnica=self.session.tecnica, modalidad=Modalidad.objects.get(nombre=name_mode), usando=True)
72
+
73
+ if not tecnique_mode:
74
+ return self.controllGetResponse(error="Modalidad no encontrada", request=request)
75
+
76
  self.session.activo = True
77
  self.session.save()
78
 
tecnicas/controllers/views_controller/sessions_tester/tests_forms/test_napping_controller.py CHANGED
@@ -1,7 +1,8 @@
1
  from django.http import HttpRequest
2
  from django.shortcuts import redirect, render
3
  from django.urls import reverse
4
- from tecnicas.models import Participacion, Producto
 
5
  from .general_test_controller import GenetalTestController
6
 
7
 
@@ -23,13 +24,22 @@ class TestNappingController(GenetalTestController):
23
  }
24
  return redirect(reverse(self.previus_directory, kwargs=params))
25
 
26
- if technique.repeticion == 1:
 
 
 
 
27
  return self.nappingTest(request)
28
  else:
29
- params = {
30
- "code_sesion": self.session.codigo_sesion
31
- }
32
- return redirect(reverse(self.previus_directory, kwargs=params))
 
 
 
 
 
33
 
34
  def nappingTest(self, request: HttpRequest):
35
  self.context["session"] = self.session
 
1
  from django.http import HttpRequest
2
  from django.shortcuts import redirect, render
3
  from django.urls import reverse
4
+ from tecnicas.models import Participacion, Producto, TecnicaModalidad
5
+ from tecnicas.utils import noValidTechnique
6
  from .general_test_controller import GenetalTestController
7
 
8
 
 
24
  }
25
  return redirect(reverse(self.previus_directory, kwargs=params))
26
 
27
+ name_mode_activate = TecnicaModalidad.objects.get(
28
+ tecnica=technique, usando=True).modalidad.nombre
29
+
30
+ if name_mode_activate == "sin modalidad":
31
+ self.context["mode"] = "sin modalidad"
32
  return self.nappingTest(request)
33
  else:
34
+ return noValidTechnique(
35
+ name_view=self.previus_directory,
36
+ query_params={
37
+ "error": "La técnica no tiene modalidad activada"
38
+ },
39
+ params={
40
+ "code_sesion": self.session.codigo_sesion
41
+ }
42
+ )
43
 
44
  def nappingTest(self, request: HttpRequest):
45
  self.context["session"] = self.session
tecnicas/migrations/0029_remove_tecnica_modalidad_and_more.py ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Generated by Django 5.2.1 on 2025-11-28 21:48
2
+
3
+ import shortuuid.main
4
+ from django.db import migrations, models
5
+
6
+
7
+ class Migration(migrations.Migration):
8
+
9
+ dependencies = [
10
+ ('tecnicas', '0028_alter_sesionsensorial_codigo_sesion_and_more'),
11
+ ]
12
+
13
+ operations = [
14
+ migrations.RemoveField(
15
+ model_name='tecnica',
16
+ name='modalidad',
17
+ ),
18
+ migrations.AlterField(
19
+ model_name='sesionsensorial',
20
+ name='codigo_sesion',
21
+ field=models.CharField(default=shortuuid.main.ShortUUID.uuid, editable=False, max_length=22, primary_key=True, serialize=False),
22
+ ),
23
+ ]
tecnicas/migrations/0030_alter_sesionsensorial_codigo_sesion_tecnicamodalidad.py ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Generated by Django 5.2.1 on 2025-11-28 21:54
2
+
3
+ import django.db.models.deletion
4
+ import shortuuid.main
5
+ from django.db import migrations, models
6
+
7
+
8
+ class Migration(migrations.Migration):
9
+
10
+ dependencies = [
11
+ ('tecnicas', '0029_remove_tecnica_modalidad_and_more'),
12
+ ]
13
+
14
+ operations = [
15
+ migrations.AlterField(
16
+ model_name='sesionsensorial',
17
+ name='codigo_sesion',
18
+ field=models.CharField(default=shortuuid.main.ShortUUID.uuid, editable=False, max_length=22, primary_key=True, serialize=False),
19
+ ),
20
+ migrations.CreateModel(
21
+ name='TecnicaModalidad',
22
+ fields=[
23
+ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
24
+ ('usando', models.BooleanField(default=False)),
25
+ ('modalidad', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='modalidad_tecnica', to='tecnicas.modalidad')),
26
+ ('tecnica', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='tecnica_modalidad', to='tecnicas.tecnica')),
27
+ ],
28
+ ),
29
+ ]
tecnicas/migrations/0031_calificacion_palabras_and_more.py ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Generated by Django 5.2.1 on 2025-11-29 03:05
2
+
3
+ import django.db.models.deletion
4
+ import shortuuid.main
5
+ from django.db import migrations, models
6
+
7
+
8
+ class Migration(migrations.Migration):
9
+
10
+ dependencies = [
11
+ ('tecnicas', '0030_alter_sesionsensorial_codigo_sesion_tecnicamodalidad'),
12
+ ]
13
+
14
+ operations = [
15
+ migrations.AddField(
16
+ model_name='calificacion',
17
+ name='palabras',
18
+ field=models.ManyToManyField(blank=True, related_name='calificacion_palabras', to='tecnicas.palabra'),
19
+ ),
20
+ migrations.AlterField(
21
+ model_name='sesionsensorial',
22
+ name='codigo_sesion',
23
+ field=models.CharField(default=shortuuid.main.ShortUUID.uuid, editable=False, max_length=22, primary_key=True, serialize=False),
24
+ ),
25
+ migrations.CreateModel(
26
+ name='DatoPunto',
27
+ fields=[
28
+ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
29
+ ('x', models.FloatField(default=0)),
30
+ ('y', models.FloatField(default=0)),
31
+ ('calificacion', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='data_punto', to='tecnicas.calificacion')),
32
+ ],
33
+ ),
34
+ ]
tecnicas/models/__init__.py CHANGED
@@ -32,4 +32,5 @@ from .participacion import Participacion
32
 
33
  from .lista_palabras import ListaPalabras
34
  from .grupo_producto import GrupoProducto
35
-
 
 
32
 
33
  from .lista_palabras import ListaPalabras
34
  from .grupo_producto import GrupoProducto
35
+ from .tecnica_modalidad import TecnicaModalidad
36
+ from .dato_punto import DatoPunto
tecnicas/models/calificacion.py CHANGED
@@ -3,12 +3,20 @@ from django.db import models
3
  from .producto import Producto
4
  from .tecnica import Tecnica
5
  from .catador import Catador
 
 
6
 
7
  class Calificacion(models.Model):
8
  num_repeticion = models.IntegerField()
9
- id_producto = models.ForeignKey(Producto, on_delete=models.CASCADE, related_name="calificacion_producto")
10
- id_tecnica = models.ForeignKey(Tecnica, on_delete=models.CASCADE, related_name="calificacion_tecnica")
11
- id_catador = models.ForeignKey(Catador, on_delete=models.CASCADE, related_name="calificacion_catador")
 
 
 
 
 
 
12
 
13
  def __str__(self):
14
- return f"{self.id} - {self.id_tecnica.sesion_tecnica} - {self.num_repeticion} - {self.id_catador.user.username}"
 
3
  from .producto import Producto
4
  from .tecnica import Tecnica
5
  from .catador import Catador
6
+ from .palabra import Palabra
7
+
8
 
9
  class Calificacion(models.Model):
10
  num_repeticion = models.IntegerField()
11
+ id_producto = models.ForeignKey(
12
+ Producto, on_delete=models.CASCADE, related_name="calificacion_producto")
13
+ id_tecnica = models.ForeignKey(
14
+ Tecnica, on_delete=models.CASCADE, related_name="calificacion_tecnica")
15
+ id_catador = models.ForeignKey(
16
+ Catador, on_delete=models.CASCADE, related_name="calificacion_catador")
17
+
18
+ palabras = models.ManyToManyField(
19
+ Palabra, related_name="calificacion_palabras", blank=True)
20
 
21
  def __str__(self):
22
+ return f"{self.id} - {self.id_tecnica.sesion_tecnica} - {self.num_repeticion} - {self.id_catador.user.username}"
tecnicas/models/dato_punto.py ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from django.db import models
2
+ from .calificacion import Calificacion
3
+
4
+
5
+ class DatoPunto(models.Model):
6
+ x = models.FloatField(null=False, default=0)
7
+ y = models.FloatField(null=False, default=0)
8
+ calificacion = models.ForeignKey(
9
+ Calificacion, on_delete=models.CASCADE, related_name="data_punto")
10
+
11
+ def __str__(self):
12
+ return f"({self.calificacion.id_producto.codigoProducto}: {self.x}, {self.y})"
tecnicas/models/tecnica.py CHANGED
@@ -15,9 +15,6 @@ class Tecnica(models.Model):
15
  id_estilo = models.ForeignKey(
16
  EstiloPalabra, on_delete=models.CASCADE, related_name="estilo_tecnica")
17
 
18
- modalidad = models.ManyToManyField(
19
- Modalidad, related_name="modalidad_tecnica", blank=True)
20
-
21
  def __str__(self):
22
  return f"{self.id} : {self.tipo_tecnica.nombre_tecnica} : {self.id_estilo.nombre_estilo}"
23
 
 
15
  id_estilo = models.ForeignKey(
16
  EstiloPalabra, on_delete=models.CASCADE, related_name="estilo_tecnica")
17
 
 
 
 
18
  def __str__(self):
19
  return f"{self.id} : {self.tipo_tecnica.nombre_tecnica} : {self.id_estilo.nombre_estilo}"
20
 
tecnicas/models/tecnica_modalidad.py ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from django.db import models
2
+ from .tecnica import Tecnica
3
+ from .modalidad import Modalidad
4
+
5
+
6
+ class TecnicaModalidad(models.Model):
7
+ tecnica = models.ForeignKey(
8
+ Tecnica, on_delete=models.CASCADE, related_name="tecnica_modalidad")
9
+ modalidad = models.ForeignKey(
10
+ Modalidad, on_delete=models.CASCADE, related_name="modalidad_tecnica")
11
+
12
+ usando = models.BooleanField(default=False)
tecnicas/static/js/test-napping.js CHANGED
@@ -1,4 +1,3 @@
1
-
2
  const planeContainer = document.getElementById('napping-plane');
3
  const productsContainer = document.getElementById('items');
4
  const products = document.querySelectorAll('.item-product');
@@ -90,3 +89,97 @@ function renderPoint(code, xPx, yPx, xVal, yVal) {
90
  point.appendChild(textLabel);
91
  }
92
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  const planeContainer = document.getElementById('napping-plane');
2
  const productsContainer = document.getElementById('items');
3
  const products = document.querySelectorAll('.item-product');
 
89
  point.appendChild(textLabel);
90
  }
91
 
92
+ /*
93
+ ////
94
+ //////
95
+ //////// Question to finish session
96
+ //////
97
+ ////
98
+ */
99
+
100
+ function showOptionsSave() {
101
+ document.getElementById("question-save").classList.add("hidden");
102
+ document.getElementById("finish-session").classList.remove("hidden");
103
+ document.getElementById("cancel-save").classList.remove("hidden");
104
+ }
105
+
106
+ function showQuestionSave() {
107
+ document.getElementById("question-save").classList.remove("hidden");
108
+ document.getElementById("finish-session").classList.add("hidden");
109
+ document.getElementById("cancel-save").classList.add("hidden");
110
+ }
111
+
112
+ document
113
+ .getElementById("question-save")
114
+ .addEventListener("click", showOptionsSave);
115
+
116
+ document
117
+ .getElementById("cancel-save")
118
+ .addEventListener("click", showQuestionSave);
119
+
120
+ /*
121
+ ////
122
+ //////
123
+ //////// Save data and finish session
124
+ //////
125
+ ////
126
+ */
127
+
128
+ async function saveData() {
129
+ const codeProducts = Object.keys(placedPoints);
130
+ const data = [];
131
+
132
+ if (products.length != codeProducts.length) {
133
+ spanNotifaction("Por favor, coloca todos los puntos")
134
+ return;
135
+ }
136
+
137
+ codeProducts.forEach((code) => {
138
+ const point = placedPoints[code];
139
+
140
+ const objData = {
141
+ code: code,
142
+ x: point.x,
143
+ y: point.y,
144
+ idProduct: point.id
145
+ };
146
+
147
+ data.push(objData);
148
+ })
149
+
150
+ const URL = "/cata/testers/api/rating-napping/no-mode"
151
+ const csrfToken = document.querySelector('[name=csrfmiddlewaretoken]').value;
152
+
153
+ try {
154
+ const response = await fetch(URL, {
155
+ method: "POST",
156
+ headers: {
157
+ "Content-Type": "application/json",
158
+ "X-CSRFToken": csrfToken,
159
+ },
160
+ body: JSON.stringify(data),
161
+ })
162
+
163
+ if (!response.ok) {
164
+ spanNotifaction("Error en la respuesta del servidor")
165
+ return false;
166
+ }
167
+
168
+ const result = await response.json()
169
+
170
+ if (result.error) {
171
+ spanNotifaction(result.error)
172
+ return false
173
+ } else {
174
+ spanNotifaction(result.message, false)
175
+ return true
176
+ }
177
+ } catch (error) {
178
+ spanNotifaction("Error en proceso de guardar los datos")
179
+ return false
180
+ }
181
+ }
182
+
183
+ document
184
+ .getElementById("save-progress")
185
+ .addEventListener("click", saveData);
tecnicas/templates/tecnicas/forms_tester/test_napping.html CHANGED
@@ -41,8 +41,8 @@
41
  </section>
42
 
43
  <section class="flex items-center justify-center flex-wrap gap-4 bg-surface-ligt p-2 rounded-lg">
44
- <p class="text-xl font-bold text-center">
45
- Modalidad: Napping
46
  </p>
47
  </section>
48
  </article>
@@ -71,7 +71,7 @@
71
  </div>
72
  </div>
73
 
74
- <!-- <section role="alert" class="alert alert-info">
75
  <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"
76
  class="h-6 w-6 shrink-0 stroke-current">
77
  <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
@@ -95,13 +95,13 @@
95
  perderás todo lo que no hayas guardado antes
96
  </span>
97
  <span class="text-lg block">
98
- Con el botón <b>“Finalizar la sesión”</b>, se guardan las palabras, sales de la sesión y no
99
  podrás ingresar otra vez
100
  </span>
101
  </div>
102
- </section> -->
103
 
104
- <!-- <section class="flex justify-end gap-4 max-sm:flex-col">
105
  <button id="save-progress" class="cts-btn-general cts-btn-primary btn-push">
106
  Guardar progreso
107
  </button>
@@ -117,7 +117,7 @@
117
  </button>
118
  </div>
119
  <span id="loading-data-save" class="loading loading-spinner loading-xl text-accent hidden"></span>
120
- </section> -->
121
  </article>
122
 
123
  {% include "../components/toast-container.html" %}
 
41
  </section>
42
 
43
  <section class="flex items-center justify-center flex-wrap gap-4 bg-surface-ligt p-2 rounded-lg">
44
+ <p class="text-xl font-bold text-center capitalize">
45
+ Modalidad: {{ mode }}
46
  </p>
47
  </section>
48
  </article>
 
71
  </div>
72
  </div>
73
 
74
+ <section role="alert" class="alert alert-info">
75
  <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"
76
  class="h-6 w-6 shrink-0 stroke-current">
77
  <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
 
95
  perderás todo lo que no hayas guardado antes
96
  </span>
97
  <span class="text-lg block">
98
+ Con el botón <b>“Finalizar”</b>, se guardan las posiciones, sales de la sesión y no
99
  podrás ingresar otra vez
100
  </span>
101
  </div>
102
+ </section>
103
 
104
+ <section class="flex justify-end gap-4 max-sm:flex-col">
105
  <button id="save-progress" class="cts-btn-general cts-btn-primary btn-push">
106
  Guardar progreso
107
  </button>
 
117
  </button>
118
  </div>
119
  <span id="loading-data-save" class="loading loading-spinner loading-xl text-accent hidden"></span>
120
+ </section>
121
  </article>
122
 
123
  {% include "../components/toast-container.html" %}
tecnicas/templates/tecnicas/manage_sesions/details-session-napping.html CHANGED
@@ -126,9 +126,9 @@
126
  </button>
127
  {% endfor %}
128
  {% else %}
129
- <a href="{% url 'cata_system:monitor_sesion' session_code=session.codigo_sesion %}" class="flex-1 w-fit">
130
  <button
131
- class="ct-btn-start-repition cts-btn-general cts-btn-primary btn-push">
132
  Monitorear repetición
133
  <figure class="w-10">
134
  <img src="{% static 'img/monitor.svg' %}" alt="flechas girando" class="invert">
@@ -137,7 +137,7 @@
137
  </a>
138
  {% endif %}
139
  <button
140
- class="flex-1 uppercase text-lg cts-btn-general cts-btn-error btn-push flex flex-col justify-center items-center gap-2"
141
  onclick="showWarningDialog('cts-warnig-dialog')">
142
  borrar
143
  <figure class="w-10">
 
126
  </button>
127
  {% endfor %}
128
  {% else %}
129
+ <a href="{% url 'cata_system:monitor_sesion' session_code=session.codigo_sesion %}" class="w-full">
130
  <button
131
+ class="cts-btn-general capitalize active:border-orange-500 border-orange-800 bg-orange-600 btn-push flex flex-col justify-center items-center gap-2 w-full">
132
  Monitorear repetición
133
  <figure class="w-10">
134
  <img src="{% static 'img/monitor.svg' %}" alt="flechas girando" class="invert">
 
137
  </a>
138
  {% endif %}
139
  <button
140
+ class="uppercase text-lg cts-btn-general cts-btn-error btn-push flex flex-col justify-center items-center gap-2 w-full"
141
  onclick="showWarningDialog('cts-warnig-dialog')">
142
  borrar
143
  <figure class="w-10">
tecnicas/urls.py CHANGED
@@ -155,4 +155,8 @@ urlpatterns = [
155
  path("testers/api/rating-sort",
156
  views.ratingSort,
157
  name="api_rating_sort"),
 
 
 
 
158
  ]
 
155
  path("testers/api/rating-sort",
156
  views.ratingSort,
157
  name="api_rating_sort"),
158
+
159
+ path("testers/api/rating-napping/no-mode",
160
+ views.ratingNappingNoMode,
161
+ name="api_rating_napping_no_mode"),
162
  ]
tecnicas/views/__init__.py CHANGED
@@ -29,6 +29,7 @@ from .apis.api_list_words_pf import apiListWordsPF
29
  from .apis.rating_word_scales import ratingWordScales
30
  from .apis.rating_word_cata import ratingWordCata
31
  from .apis.rating_sort import ratingSort
 
32
 
33
  from .tester_forms.init_tester_form import initTesterForm
34
  from .tester_forms.panel_main_tester import mainPanelTester
 
29
  from .apis.rating_word_scales import ratingWordScales
30
  from .apis.rating_word_cata import ratingWordCata
31
  from .apis.rating_sort import ratingSort
32
+ from .apis.rating_napping import ratingNappingNoMode
33
 
34
  from .tester_forms.init_tester_form import initTesterForm
35
  from .tester_forms.panel_main_tester import mainPanelTester
tecnicas/views/apis/rating_napping.py ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from django.http import HttpRequest, JsonResponse
2
+ from tecnicas.controllers import RatingNappingController
3
+ import json
4
+
5
+
6
+ def ratingNappingNoMode(req: HttpRequest):
7
+ if req.method == "POST":
8
+ try:
9
+ data = json.loads(req.body.decode("utf-8"))
10
+ response = RatingNappingController.saveRating(
11
+ request=req, data=data)
12
+ return response
13
+ except Exception as e:
14
+ return JsonResponse({"error": "Error al procesar datos"})
15
+ else:
16
+ return JsonResponse({"error": "Método no permitido"})