diff --git a/estudio_socio_economico/admin.py b/estudio_socio_economico/admin.py index 61a4e9faffd0baad1836be9f64c963201f74a1bc..f5d3b9a4f9b68cbac665ccc9968cfe3174d21546 100644 --- a/estudio_socio_economico/admin.py +++ b/estudio_socio_economico/admin.py @@ -2,6 +2,9 @@ from django.contrib import admin from .models import Seccion, Opcion, Respuesta, RTextoCorto, RTextoParrafo, ROpcionMultiple, RCasillas, RDesplegable, Elemento # Register your models here. +class ElementoAdmin(admin.ModelAdmin): + list_display = ('nombre', 'tipo', 'row', 'col') + admin.site.register(Seccion) admin.site.register(Opcion) admin.site.register(Respuesta) @@ -10,4 +13,4 @@ admin.site.register(RTextoParrafo) admin.site.register(ROpcionMultiple) admin.site.register(RCasillas) admin.site.register(RDesplegable) -admin.site.register(Elemento) \ No newline at end of file +admin.site.register(Elemento, ElementoAdmin) \ No newline at end of file diff --git a/estudio_socio_economico/forms.py b/estudio_socio_economico/forms.py new file mode 100644 index 0000000000000000000000000000000000000000..5fb49b8706d7144961b43815a8e067fcb4ec36dc --- /dev/null +++ b/estudio_socio_economico/forms.py @@ -0,0 +1,60 @@ +from django import forms +from .models import Seccion, Opcion, Elemento +from django.forms import inlineformset_factory, modelformset_factory + + + +class SeccionForm(forms.ModelForm): + class Meta: + model = Seccion + fields = ['nombre', 'tipo'] + widgets = { + 'nombre': forms.TextInput(attrs={'class': 'form-control form-control-lg font-semi-bold border-3'}), + 'tipo': forms.RadioSelect(attrs={'class': 'ms-3'}), + } + labels = { + 'nombre': 'Nombre de la Sección', + 'tipo': 'Tipo de la Sección', + } + + + +class OpcionForm(forms.ModelForm): + class Meta: + model = Opcion + fields = ['elemento', 'nombre'] + widgets = { + 'elemento': forms.Select(attrs={'class': 'form-control'}), + 'nombre': forms.TextInput(attrs={'class': 'form-control'}), + } + labels = { + 'elemento': 'Elemento', + 'nombre': 'Nombre Opción', + } + + + +class ElementoForm(forms.ModelForm): + class Meta: + model = Elemento + fields = ['seccion', 'nombre', 'obligatorio', 'row', 'col', 'tipo',] + widgets = { + 'seccion': forms.Select(attrs={'class': 'form-control border-3', 'placeholder': 'Selecciona una sección'}), + 'nombre': forms.TextInput(attrs={'class': 'form-control font-semi-bold border-3 ', 'placeholder': 'Nombre de la pregunta'}), + 'obligatorio': forms.CheckboxInput(attrs={'class': 'checkbox-principal form-check-input'}), + 'row': forms.NumberInput(attrs={'class': 'form-control border-3', 'type': 'hidden'}), + 'col': forms.NumberInput(attrs={'class': 'form-control border-3', 'type': 'hidden'}), + 'tipo': forms.Select(attrs={'class': 'form-select border-3', 'placeholder': 'Tipo de pregunta'}), + } + labels = { + 'seccion': 'Sección', + 'nombre': 'Nombre de la Pregunta', + 'obligatorio': 'Obligatorio', + 'row': 'row', + 'col': 'col', + 'tipo': 'Tipo de Pregunta', + } + +SeccionFormSet = modelformset_factory(Seccion, form=SeccionForm, extra=0, can_delete=True) +ElementoFormSet = inlineformset_factory(Seccion, Elemento, form=ElementoForm, extra=1, can_delete=True) + diff --git a/estudio_socio_economico/models.py b/estudio_socio_economico/models.py index af3f99a97431be275f1ac3620c2bb38c1c9c84af..4f86a2c0e014fa3c10b11a0d7d8cf6639cb305ec 100644 --- a/estudio_socio_economico/models.py +++ b/estudio_socio_economico/models.py @@ -5,6 +5,7 @@ from django.core.validators import MinLengthValidator, MaxLengthValidator from django.db import models from model_utils.managers import InheritanceManager from usuarios.models import Solicitante +import uuid class Seccion(models.Model): TIPOS_CHOICES = ( @@ -13,13 +14,14 @@ class Seccion(models.Model): ) nombre = models.CharField(max_length=255) - tipo = models.CharField(max_length=10, choices=TIPOS_CHOICES) + tipo = models.CharField(max_length=10, choices=TIPOS_CHOICES, default=TIPOS_CHOICES[0]) def __str__(self): return self.nombre class Opcion(models.Model): + elemento = models.ForeignKey('Elemento', on_delete=models.CASCADE) nombre = models.CharField(max_length=255, verbose_name='Nombre Opción') def __str__(self): @@ -87,11 +89,10 @@ class Elemento(models.Model): seccion = models.ForeignKey(Seccion, on_delete=models.CASCADE) nombre = models.CharField(max_length=255, verbose_name='Nombre') - obligatorio = models.BooleanField(default=True, verbose_name='Obligatorio') - lookup_id = models.UUIDField(verbose_name='Lookup ID') - order = models.IntegerField(verbose_name='Orden') - tipo = models.CharField(max_length=20, choices=TIPO_CHOICES, verbose_name='Tipo') - opciones = models.ManyToManyField(Opcion) + obligatorio = models.BooleanField(default=True, verbose_name='Obligatorio') + row = models.IntegerField(verbose_name='row', default=100_000) + col = models.IntegerField(verbose_name='col', default=100_000) + tipo = models.CharField(max_length=20, choices=TIPO_CHOICES, verbose_name='Tipo') def __str__(self): return self.nombre @@ -112,4 +113,5 @@ class Elemento(models.Model): class Meta: verbose_name = 'Elemento' - verbose_name_plural = 'Elementos' + verbose_name_plural = 'Elementos' + ordering = ['seccion','row', 'col', ] diff --git a/estudio_socio_economico/templates/admin/config_estudioSE.html b/estudio_socio_economico/templates/admin/config_estudioSE.html index bb7aee0df9bc8e5d42374540e32a979296f73d92..31936cf212194ee959c5cdc4f027cd890f839258 100644 --- a/estudio_socio_economico/templates/admin/config_estudioSE.html +++ b/estudio_socio_economico/templates/admin/config_estudioSE.html @@ -5,8 +5,393 @@ {% endblock titulo %} {% block body %} + {% load custom_filters %} + + {% include 'admin/config_nav.html' %} -
Configuracion Estudio Socioeconomico (implementacion pendiente)
+Modificar Estudio Socioeconomico
+ + + + + {% endblock body %} \ No newline at end of file diff --git a/estudio_socio_economico/templatetags/__init__.py b/estudio_socio_economico/templatetags/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/estudio_socio_economico/templatetags/custom_filters.py b/estudio_socio_economico/templatetags/custom_filters.py new file mode 100644 index 0000000000000000000000000000000000000000..0fd0fd32f155ce29deff8601cee07de881a68424 --- /dev/null +++ b/estudio_socio_economico/templatetags/custom_filters.py @@ -0,0 +1,13 @@ +from django import template +import logging + +register = template.Library() +logger = logging.getLogger(__name__) + +@register.filter +def hashD(d, key): + try: + return d[key] + except Exception as e: + #logger.exception("Ocurrió una excepción al usar filtro: %s", str(e)) + return None \ No newline at end of file diff --git a/estudio_socio_economico/viewsAdmin.py b/estudio_socio_economico/viewsAdmin.py index 50a177260e5b31d902bb306426d2a886534f9103..a27931d351f69398996b8cf76f09556e86c8ab85 100644 --- a/estudio_socio_economico/viewsAdmin.py +++ b/estudio_socio_economico/viewsAdmin.py @@ -1,14 +1,72 @@ from django.shortcuts import get_object_or_404, redirect, render from usuarios.views import verificarRedirect from usuarios.models import Usuario +from .models import Seccion, Elemento, Opcion +from.forms import SeccionFormSet, ElementoFormSet # Create your views here. +# Crear el inline formset para Elemento +# Donde "ElementoForm" es el ModelForm personalizado para el modelo Elemento que definiste anteriormente. def configEstudio(request): - usuario = get_object_or_404(Usuario, pk=request.user.id) url = verificarRedirect(usuario, 'permiso_administrador') if url: #Verifica si el usuario ha llenaodo su informacion personal por primera vez y tiene los permisos necesarios - return redirect(url) + return redirect(url) + + secciones = Seccion.objects.all() + seccionFormset = SeccionFormSet(queryset=secciones, prefix='seccion_formset') + dictElemForm = {} + for seccion in secciones: + dictElemForm[str(seccion.id)] = ElementoFormSet(instance=seccion, prefix='elemento_formset_%s' % seccion.id) + + if request.method == 'POST': + seccionFormset = SeccionFormSet(request.POST, prefix='seccion_formset') + + if seccionFormset.is_valid(): # and elementoFormset.is_valid(): + todoValido = True + dictElemForm = {} + seccionFormset.save() + for seccion in seccionFormset.forms: + seccionInstancia = seccion.instance + elementoFormset = ElementoFormSet(request.POST, prefix='elemento_formset_%s' % seccionInstancia.id, instance=seccionInstancia) + + elementoFormset.is_valid() + non_empty_forms = [] + empty_forms = [] + for form in elementoFormset.forms: + if form.cleaned_data: + non_empty_forms.append(form) + else: + empty_forms.append(form) + # Unir ambas listas para tener los formularios no vacíos al principio y los vacíos al final + ordered_forms = non_empty_forms + empty_forms + # Actualizar el formset con la nueva lista de formularios + elementoFormset.forms = ordered_forms + + dictElemForm[str(seccionInstancia.id)] = elementoFormset + if elementoFormset.is_valid(): + elementoFormset.save() + pass + else: + todoValido = False + + print("todo valido: ") + print(todoValido) + if todoValido: + return redirect('estudioSE:AConfigEstudio') + else: + print('seccion no valid') + print(seccionFormset.errors) + + + + context = { + 'seccionFormset': seccionFormset, + 'dictElemForm': dictElemForm, + } + + - return render(request, 'admin/config_estudioSE.html') \ No newline at end of file + return render(request, 'admin/config_estudioSE.html', context) + \ No newline at end of file diff --git a/static/css/main.css b/static/css/main.css index a67ce1587db4da45e4c7b86040ff77b39c334248..ec4ef1713e5f22d0f74bb5649ae49cc011d35be9 100644 --- a/static/css/main.css +++ b/static/css/main.css @@ -11,6 +11,7 @@ --cancelar-desactivado: rgba(233, 195, 193, 1); --cancelar-activado: rgba(234, 94, 94, 1); --pagina-fondo: #EEE5E5/*#F1ECEC*/; + --pagina-gris: #b9b4b4; } * { @@ -25,6 +26,10 @@ body { background-color: var(--pagina-blanco) !important; } +.pagina-fondo { + background-color: var(--pagina-fondo) !important; +} + .pagina-fuerte { background-color: var(--pagina-fuerte) !important; } @@ -65,10 +70,18 @@ body { background-color: var(--cancelar-activado) !important; } +.pagina-gris { + background-color: var(--pagina-gris) !important; +} + .borde-pagina-blanco { border-color: var(--pagina-blanco) !important; } +.borde-pagina-gris { + border-color: var(--pagina-gris) !important; +} + .borde-pagina-fuerte { border-color: var(--pagina-fuerte) !important; } @@ -105,6 +118,14 @@ body { border-color: var(--cancelar-activado) !important; } +.borde-punteado { + border: 1px dashed #000; /* Puedes ajustar el color y el grosor según tus necesidades */ +} + +.altura-min-100px { + min-height: 30px; +} + /* Login */ .login-contenedor { max-width: 500px; @@ -187,14 +208,45 @@ body { border-color: var(--pagina-tenue); } +/* Estilo para el checkbox principal */ +.checkbox-principal.form-check-input:checked { + background-color: var(--pagina-principal); + border-color: var(--pagina-fuerte); +} + +.checkbox-principal.form-check-input:checked:focus { + box-shadow: 0 0 0 0.25rem var(--pagina-fuerte); +} + +.checkbox-principal.form-check-input:checked:hover { + background-color: var(--pagina-principal); + border-color: var(--pagina-principal); +} + +/* Estilo para el label (etiqueta) del checkbox principal */ +.checkbox-principal.form-check-label { + color: var(--pagina-fuerte); +} + +.checkbox-principal.form-check-input:disabled { + background-color: var(--pagina-principal); + opacity: 0.65; +} + +.handle { + cursor: move; +} + +.handle2 { + cursor: move; +} .nav .nav-link.active { border-left: 12px solid var(--pagina-principal); background-color: var(--pagina-fuerte); } -.nav-pills .nav-link.active{ - border-left: 12px solid var(--pagina-principal); +.nav-pills .nav-link.active{ background-color: var(--pagina-fuerte); } @@ -250,3 +302,35 @@ input[type=text], input[type=password], [type=email]{ .errorlist { color: red; } */ + +/* Clase para fuente normal */ +.font-normal { + font-weight: normal; +} + +/* Clase para fuente en negrita */ +.font-bold { + font-weight: bold; +} + +/* Clase para fuente semi-bold */ +.font-semi-bold { + font-weight: 600; +} + +/* Clase para fuente ligera */ +.font-light { + font-weight: lighter; +} + +/* Clase para fuente más negrita */ +.font-bolder { + font-weight: bolder; +} + +/* Clase para fuente con peso personalizado */ +.font-custom-weight { + font-weight: 700; /* Cambia el valor a tu preferencia */ +} + + diff --git a/usuarios/templates/admin/config_nav.html b/usuarios/templates/admin/config_nav.html index 9b58ac97df4e1092bb97b0ace40904eea0672191..4aaf87280d2416df793c518f2d93f69b32ca9bcc 100644 --- a/usuarios/templates/admin/config_nav.html +++ b/usuarios/templates/admin/config_nav.html @@ -1,4 +1,4 @@ -Configuración
+Configuración