chartManD commited on
Commit
079bb3a
·
1 Parent(s): 654787c

Manejo de datos en session, validacion de agregar palabra nueva, trato de palabras seleccionadas

Browse files
tecnicas/forms/atributes_form.py ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from django import forms
2
+
3
+
4
+ class AtributesForm(forms.Form):
5
+ def __init__(self, *args, atributes=[], **kwargs):
6
+ super().__init__(*args, **kwargs)
7
+
8
+ for index, atribute in enumerate(atributes):
9
+ self.fields[f'atributo_{index+1}'] = forms.CharField(max_length=150, required=True, min_length=3, initial=atribute, label=f"Atributo {index+1}", widget=forms.TextInput(attrs={
10
+ "class": "ct-atributo bg-gray-300 p-1 border-b-1 text-center w-full disabled:bg-gray-500 uppercase"
11
+ }))
tecnicas/forms/word_form.py CHANGED
@@ -4,33 +4,33 @@ from ..models import Palabra
4
 
5
 
6
  class WordForm(forms.ModelForm):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7
  class Meta:
8
  model = Palabra
9
  fields = ["nombre_palabra"]
10
 
11
- labels = {
12
- "nombre_palabra": "nombre_palabra"
13
- }
14
-
15
- widgets = {
16
- "nombre_palabra": forms.TextInput(attrs={
17
- "class": "bg-gray-300 border-b text-center text-black pb-1 rounded",
18
- "placeholder": "Ingrese palabra",
19
- "oninput": "this.value = this.value.toLowerCase()"
20
- })
21
- }
22
-
23
- error_messages = {
24
- "nombre_palabra": {
25
- "required": "parametros requeridos",
26
- "unique": "palabra repetida"
27
- }
28
- }
29
-
30
  def clean_nombre_palabra(self):
31
  nombre_palabra = self.cleaned_data.get('nombre_palabra')
32
 
33
  if nombre_palabra:
34
  nombre_palabra = nombre_palabra.lower().strip()
35
 
 
 
 
36
  return nombre_palabra
 
4
 
5
 
6
  class WordForm(forms.ModelForm):
7
+ nombre_palabra = forms.CharField(
8
+ min_length=3,
9
+ max_length=255,
10
+ error_messages={
11
+ "required": "parametros requeridos",
12
+ "unique": "palabra repetida", # Ojo: 'unique' lo maneja ModelForm, no aquí
13
+ "min_length": "la palabra es muy corta",
14
+ "max_length": "la palabra es muy larga",
15
+ },
16
+ widget=forms.TextInput(attrs={
17
+ "class": "bg-gray-300 border-b text-center text-black pb-1 rounded",
18
+ "placeholder": "Ingrese palabra",
19
+ "oninput": "this.value = this.value.toLowerCase()",
20
+ })
21
+ )
22
+
23
  class Meta:
24
  model = Palabra
25
  fields = ["nombre_palabra"]
26
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
27
  def clean_nombre_palabra(self):
28
  nombre_palabra = self.cleaned_data.get('nombre_palabra')
29
 
30
  if nombre_palabra:
31
  nombre_palabra = nombre_palabra.lower().strip()
32
 
33
+ if Palabra.objects.filter(nombre_palabra=nombre_palabra).exists():
34
+ raise forms.ValidationError("palabra repetida")
35
+
36
  return nombre_palabra
tecnicas/static/js/panel-words.js CHANGED
@@ -14,6 +14,8 @@ const foundWordsContainer = document.getElementsByClassName(
14
  const formSearch = document.getElementsByClassName("ct-serach-words")[0];
15
  formSearch.addEventListener("submit", getWordsByName);
16
 
 
 
17
  async function getWordsByName(e) {
18
  e.preventDefault();
19
  errorp.classList.add("hidden");
@@ -175,6 +177,7 @@ function removeWordToUse(word) {
175
 
176
  function updatelistWordsSelect() {
177
  wordsSelectContainer.innerHTML = "";
 
178
  listWordsSelect.forEach((word) => {
179
  const elemtnLi = createWordElement({
180
  word: word,
@@ -231,3 +234,39 @@ async function postNewWord(e) {
231
  spanNotificationRed(`Error: ${error}`);
232
  }
233
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
14
  const formSearch = document.getElementsByClassName("ct-serach-words")[0];
15
  formSearch.addEventListener("submit", getWordsByName);
16
 
17
+ checInitWords();
18
+
19
  async function getWordsByName(e) {
20
  e.preventDefault();
21
  errorp.classList.add("hidden");
 
177
 
178
  function updatelistWordsSelect() {
179
  wordsSelectContainer.innerHTML = "";
180
+
181
  listWordsSelect.forEach((word) => {
182
  const elemtnLi = createWordElement({
183
  word: word,
 
234
  spanNotificationRed(`Error: ${error}`);
235
  }
236
  }
237
+
238
+ // **************************************
239
+ // Create Session
240
+ // **************************************
241
+ const formCreateSession = document.querySelector(".ct-creat-session");
242
+ formCreateSession.addEventListener("submit", createSession);
243
+
244
+ async function createSession(e) {
245
+ e.preventDefault();
246
+
247
+ if (listWordsSelect.length === 0) {
248
+ spanNotificationRed("Debe seleccionar al menos una palabra");
249
+ return;
250
+ }
251
+
252
+ const wordsInput = document.createElement("input");
253
+ wordsInput.type = "hidden";
254
+ wordsInput.name = "words";
255
+ wordsInput.value = JSON.stringify(listWordsSelect);
256
+ this.appendChild(wordsInput);
257
+
258
+ this.submit();
259
+ }
260
+
261
+ function checInitWords() {
262
+ const wordsSends = document.getElementsByClassName("ct-word-received");
263
+
264
+ for (let i = 0; i < wordsSends.length; i++) {
265
+ const id = parseInt(wordsSends.item(i).id);
266
+ const name = wordsSends.item(i).textContent;
267
+ const newWord = { id: id, nombre_palabra: name };
268
+ listWordsSelect.push(newWord);
269
+ }
270
+
271
+ updatelistWordsSelect();
272
+ }
tecnicas/templates/tecnicas/create_sesion/configuracion-panel-words.html CHANGED
@@ -7,14 +7,6 @@
7
  <article class="w-full flex flex-col justify-center items-center bg-gray-600 my-10">
8
  <section class="w-fit h-fit relative">
9
  <article class="flex flex-col gap-4 bg-gray-400 md:p-10 p-5 rounded-2xl lg:w-4xl w-full">
10
- <ul class="all-words hidden">
11
- {% for word in words %}
12
- <li class="word">
13
- <p>{{ word.nombre_palabra }}</p>
14
- <p>{{ word.id }}</p>
15
- </li>
16
- {% endfor %}
17
- </ul>
18
  <h1 class="text-center font-bold text-4xl">Panel de configuración</h1>
19
  <hr>
20
  {% if error %}
@@ -36,7 +28,7 @@
36
  class="p-2 px-4 bg-gray-200 rounded-lg w-full text-lg font-medium">
37
  </label>
38
  <button type="submit"
39
- class="text-lg tracking-wider font-medium p-2 px-4 border-b-2 active:border-b-0 active:border-t-2 active:border-yellow-500 border-yellow-800 transition-all rounded-xl bg-yellow-500 text-white w-fit capitalize">
40
  Buscar
41
  </button>
42
  </section>
@@ -44,17 +36,27 @@
44
  <p
45
  class="ct-error-words hidden capitalize text-white bg-red-600 text-center text-2xl p-1.5 rounded">
46
  error</p>
47
- <ul class="ct-palabras-encontradas gap-2 grid-cols-2 max-h-96 overflow-y-auto">
48
- <object type="image/svg" class="flex justify-center items-center h-full">
49
- <img src="{% static 'img/lupa.svg' %}" alt="lupa de busqueda" class="h-full">
50
- </object>
51
  </ul>
52
  </section>
53
  <section class="flex-1/3 bg-gray-600 text-white p-4 rounded-lg text-center min-h-96">
54
  <p class="text-xl font-bold pb-3">Lista de palabras</p>
55
  <hr class="mb-3 text-white">
56
  <ul class="ct-palabras-usadas flex flex-col gap-3">
 
57
  <img src="{% static 'img/list.svg' %}" alt="lista de palabras" class="ct-img-list">
 
 
 
 
 
 
 
 
 
58
  </ul>
59
  </section>
60
  </article>
@@ -62,24 +64,39 @@
62
  <article class="ct-new-tags bg-gray-600 p-5 flex justify-center items-center rounded-2xl">
63
  <form method="post" action="" class="ct-form-new-word p-3">
64
  {% csrf_token %}
65
- <p class="mb-4 text-2xl font-bold text-center text-white">¿No encuentras una palabra?</p>
 
 
66
  <label for="{{ form_word.nombre_palabra.id_for_label }}"
67
- class="font-medium text-xl text-white flex gap-3 mb-4">
68
  <p class="px-4">Nueva palabra:</p>
69
  {{ form_word.nombre_palabra }}
70
  </label>
71
  <p
72
  class="ct-error-word mb-4 font-bold bg-red-500 text-white text-md capitalize text-center rounded hidden">
73
- error</p>
 
74
  <hr class="text-white">
75
  <article class="flex justify-center gap-8 mt-4 text-white font-medium tracking-wide">
76
- <button class="rounded px-3 py-1 bg-green-700 active:bg-green-600" type="submit">
 
 
77
  Crear y agregar a la lista
78
  </button>
79
  </article>
80
  </form>
81
  </article>
82
 
 
 
 
 
 
 
 
 
 
 
83
  <article
84
  class="ct-notification-red absolute max-md:fixed bottom-0 mb-4 left-1/2 -translate-x-1/2 bg-red-600 text-white p-2 px-4 rounded-lg text-center font-medium hidden uppercase">
85
  </article>
 
7
  <article class="w-full flex flex-col justify-center items-center bg-gray-600 my-10">
8
  <section class="w-fit h-fit relative">
9
  <article class="flex flex-col gap-4 bg-gray-400 md:p-10 p-5 rounded-2xl lg:w-4xl w-full">
 
 
 
 
 
 
 
 
10
  <h1 class="text-center font-bold text-4xl">Panel de configuración</h1>
11
  <hr>
12
  {% if error %}
 
28
  class="p-2 px-4 bg-gray-200 rounded-lg w-full text-lg font-medium">
29
  </label>
30
  <button type="submit"
31
+ class="text-lg tracking-wider font-medium p-2 px-4 border-b-2 active:border-b-0 active:border-t-2 active:border-blue-500 border-blue-800 transition-all rounded-xl bg-blue-500 text-white w-fit capitalize">
32
  Buscar
33
  </button>
34
  </section>
 
36
  <p
37
  class="ct-error-words hidden capitalize text-white bg-red-600 text-center text-2xl p-1.5 rounded">
38
  error</p>
39
+ <ul class="ct-palabras-encontradas gap-2 grid-cols-2 max-h-96 overflow-y-auto">
40
+ <div class="flex justify-center items-center">
41
+ <img src="{% static 'img/lupa.svg' %}" alt="lupa de busqueda" style="width: 50%;">
42
+ </div>
43
  </ul>
44
  </section>
45
  <section class="flex-1/3 bg-gray-600 text-white p-4 rounded-lg text-center min-h-96">
46
  <p class="text-xl font-bold pb-3">Lista de palabras</p>
47
  <hr class="mb-3 text-white">
48
  <ul class="ct-palabras-usadas flex flex-col gap-3">
49
+ {% if not words %}
50
  <img src="{% static 'img/list.svg' %}" alt="lista de palabras" class="ct-img-list">
51
+ {% endif %}
52
+ {% for word in words %}
53
+ <li
54
+ class="bg-gray-400 text-black rounded font-bold text-lg px-4 py-3 flex flex-wrap flex-row flex-1 min-w-fit justify-center items-center gap-3">
55
+ <p class="ct-word-received" id="{{ word.id }}">{{ word.nombre_palabra }}</p>
56
+ <button
57
+ class="px-4 border-b-2 active:border-b-0 active:border-t-2 transition-all rounded-xl font-black w-fit capitalize active:border-red-500 border-red-800 bg-red-500">➖</button>
58
+ </li>
59
+ {% endfor %}
60
  </ul>
61
  </section>
62
  </article>
 
64
  <article class="ct-new-tags bg-gray-600 p-5 flex justify-center items-center rounded-2xl">
65
  <form method="post" action="" class="ct-form-new-word p-3">
66
  {% csrf_token %}
67
+ <p class="mb-4 text-2xl min-md:text-xl font-bold text-center text-white">
68
+ ¿No encuentras una palabra?
69
+ </p>
70
  <label for="{{ form_word.nombre_palabra.id_for_label }}"
71
+ class="font-medium text-xl text-white flex flex-wrap justify-center items-center gap-3 mb-4">
72
  <p class="px-4">Nueva palabra:</p>
73
  {{ form_word.nombre_palabra }}
74
  </label>
75
  <p
76
  class="ct-error-word mb-4 font-bold bg-red-500 text-white text-md capitalize text-center rounded hidden">
77
+ error
78
+ </p>
79
  <hr class="text-white">
80
  <article class="flex justify-center gap-8 mt-4 text-white font-medium tracking-wide">
81
+ <button
82
+ class="text-lg tracking-wider font-medium p-2 px-4 border-b-2 active:border-b-0 active:border-t-2 active:border-green-500 border-green-800 transition-all rounded-xl bg-green-600 text-white w-fit"
83
+ type="submit">
84
  Crear y agregar a la lista
85
  </button>
86
  </article>
87
  </form>
88
  </article>
89
 
90
+ <article>
91
+ <form action="" method="post" class="ct-creat-session flex justify-center mt-4">
92
+ {% csrf_token %}
93
+ <button type="submit" name="start"
94
+ class="text-lg tracking-wider font-medium p-2 px-4 border-b-2 active:border-b-0 active:border-t-2 active:border-yellow-500 border-yellow-800 transition-all rounded-xl bg-yellow-500 text-white w-fit capitalize">
95
+ Iniciar sesión
96
+ </button>
97
+ </form>
98
+ </article>
99
+
100
  <article
101
  class="ct-notification-red absolute max-md:fixed bottom-0 mb-4 left-1/2 -translate-x-1/2 bg-red-600 text-white p-2 px-4 rounded-lg text-center font-medium hidden uppercase">
102
  </article>
tecnicas/test/test_words.py CHANGED
@@ -116,3 +116,18 @@ class TestsApiWords(TestCase):
116
  res_json = response.json()
117
  self.assertIn("error", res_json)
118
  self.assertEqual(res_json["error"], expected_error)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
116
  res_json = response.json()
117
  self.assertIn("error", res_json)
118
  self.assertEqual(res_json["error"], expected_error)
119
+
120
+ def test_post_word_too_short(self):
121
+ word_name = "ab"
122
+ expected_error = "la palabra es muy corta"
123
+
124
+ data = {"nombre_palabra": word_name}
125
+
126
+ response = self.client.post(
127
+ reverse("cata_system:api_palabras"),
128
+ data
129
+ )
130
+
131
+ res_json = response.json()
132
+ self.assertIn("error", res_json)
133
+ self.assertEqual(res_json["error"], expected_error)
tecnicas/views/configuration_panel_codes.py CHANGED
@@ -7,12 +7,12 @@ import json
7
 
8
 
9
  def configurationPanelCodes(req: HttpRequest):
10
- data_basic = req.session["form_basic"]
11
- data_tags = req.session["form_tags"]
 
 
12
 
13
- if not data_basic or not data_tags:
14
- redirect(reverse("cata_system:seleccion_tecnica") +
15
- "?error=datos del formulario requerido no encontrados")
16
 
17
  num_products = data_basic["numero_productos"]
18
  num_tester = data_basic["numero_catadores"]
 
7
 
8
 
9
  def configurationPanelCodes(req: HttpRequest):
10
+ if not req.session.get("form_basic") or not req.session.get("form_tags"):
11
+ req.session.flush()
12
+ return redirect(reverse("cata_system:seleccion_tecnica") +
13
+ "?error=datos del formulario requerido no encontrados")
14
 
15
+ data_basic = req.session["form_basic"]
 
 
16
 
17
  num_products = data_basic["numero_productos"]
18
  num_tester = data_basic["numero_catadores"]
tecnicas/views/configuration_panel_words.py CHANGED
@@ -1,15 +1,51 @@
1
  from django.http import HttpRequest
2
- from django.shortcuts import render
 
3
  from ..models.palabra import Palabra
4
  from ..forms.word_form import WordForm
5
 
 
 
6
 
7
  def configurationPanelWords(req: HttpRequest):
 
 
 
 
 
 
 
 
 
 
8
  if req.method == "GET":
9
- form = WordForm()
10
- all_words = Palabra.objects.all()
11
- context = {
12
- "words": all_words,
13
- "form_word": form
14
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
15
  return render(req, "tecnicas/create_sesion/configuracion-panel-words.html", context)
 
1
  from django.http import HttpRequest
2
+ from django.shortcuts import render, redirect
3
+ from django.urls import reverse
4
  from ..models.palabra import Palabra
5
  from ..forms.word_form import WordForm
6
 
7
+ import json
8
+
9
 
10
  def configurationPanelWords(req: HttpRequest):
11
+ if not req.session.get("form_basic") or not req.session.get("form_tags") or not req.session.get("form_codes"):
12
+ req.session.flush()
13
+ return redirect(reverse("cata_system:seleccion_tecnica") +
14
+ "?error=datos del formulario requerido no encontrados")
15
+
16
+ form = WordForm()
17
+ context = {
18
+ "form_word": form
19
+ }
20
+
21
  if req.method == "GET":
22
+ return render(req, "tecnicas/create_sesion/configuracion-panel-words.html", context)
23
+ elif req.method == "POST":
24
+ if not req.POST.get("words"):
25
+ return render(req, "tecnicas/create_sesion/configuracion-panel-words.html", context)
26
+
27
+ words = json.loads(req.POST.get("words"))
28
+
29
+ context["words"] = words
30
+
31
+ print(words)
32
+
33
+ # form = WordForm(req.POST)
34
+ # all_words = Palabra.objects.all()
35
+ # context = {
36
+ # "words": all_words,
37
+ # "form_word": form
38
+ # }
39
+
40
+ # if form.is_valid():
41
+ # new_word = form.cleaned_data.get("nombre_palabra")
42
+ # if not Palabra.objects.filter(nombre_palabra__iexact=new_word).exists():
43
+ # Palabra.objects.create(nombre_palabra=new_word)
44
+ # context["form_word"] = WordForm()
45
+ # context["words"] = Palabra.objects.all()
46
+ # else:
47
+ # context["error"] = "La palabra ya existe"
48
+ # else:
49
+ # context["error"] = "Error en los datos recibidos"
50
+
51
  return render(req, "tecnicas/create_sesion/configuracion-panel-words.html", context)