Spaces:
Sleeping
Sleeping
Se refactoriza el codigo para usar modalidaes de napping, modificacion de modelos y creacion de DatoPunto para coordenadas
Browse files- tecnicas/controllers/__init__.py +2 -0
- tecnicas/controllers/api_controller/rating_napping_controller.py +12 -0
- tecnicas/controllers/views_controller/session_management/details/details_napping_controller.py +14 -7
- tecnicas/controllers/views_controller/sessions_tester/tests_forms/test_napping_controller.py +16 -6
- tecnicas/migrations/0029_remove_tecnica_modalidad_and_more.py +23 -0
- tecnicas/migrations/0030_alter_sesionsensorial_codigo_sesion_tecnicamodalidad.py +29 -0
- tecnicas/migrations/0031_calificacion_palabras_and_more.py +34 -0
- tecnicas/models/__init__.py +2 -1
- tecnicas/models/calificacion.py +12 -4
- tecnicas/models/dato_punto.py +12 -0
- tecnicas/models/tecnica.py +0 -3
- tecnicas/models/tecnica_modalidad.py +12 -0
- tecnicas/static/js/test-napping.js +94 -1
- tecnicas/templates/tecnicas/forms_tester/test_napping.html +7 -7
- tecnicas/templates/tecnicas/manage_sesions/details-session-napping.html +3 -3
- tecnicas/urls.py +4 -0
- tecnicas/views/__init__.py +1 -0
- tecnicas/views/apis/rating_napping.py +16 -0
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 =
|
|
|
|
| 24 |
|
| 25 |
if not technique_modes.exists():
|
| 26 |
self.context["modes"] = modes
|
| 27 |
else:
|
| 28 |
-
use_modes = technique_modes.values_list("
|
| 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 |
-
|
|
|
|
| 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 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 27 |
return self.nappingTest(request)
|
| 28 |
else:
|
| 29 |
-
|
| 30 |
-
|
| 31 |
-
|
| 32 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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(
|
| 10 |
-
|
| 11 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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:
|
| 46 |
</p>
|
| 47 |
</section>
|
| 48 |
</article>
|
|
@@ -71,7 +71,7 @@
|
|
| 71 |
</div>
|
| 72 |
</div>
|
| 73 |
|
| 74 |
-
<
|
| 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
|
| 99 |
podrás ingresar otra vez
|
| 100 |
</span>
|
| 101 |
</div>
|
| 102 |
-
</section>
|
| 103 |
|
| 104 |
-
<
|
| 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="
|
| 130 |
<button
|
| 131 |
-
class="
|
| 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="
|
| 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"})
|