wagtail-enap-designsystem 1.2.1.130__py3-none-any.whl → 1.2.1.131__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of wagtail-enap-designsystem might be problematic. Click here for more details.

@@ -1,20 +1,23 @@
1
1
  <!-- templates/blocks/recaptcha.html -->
2
- <div class="recaptcha-container {{ value.css_classes }}" data-recaptcha-id="{{ block.id }}">
2
+ {% load static %}
3
+
4
+ <div class="recaptcha-container {{ value.css_classes }}" data-recaptcha-id="recaptcha-widget">
3
5
 
4
- {% if has_recaptcha_keys %}
6
+ <!-- Forçar has_recaptcha_keys = True -->
7
+ {% comment %} {% if has_recaptcha_keys %} {% endcomment %}
5
8
  <!-- reCAPTCHA v2 (checkbox + desafio) -->
6
9
  <div class="g-recaptcha"
7
- data-sitekey="{{ recaptcha_public_key }}"
8
- data-theme="{{ value.tema }}"
9
- data-size="{{ value.tamanho }}"
10
- data-callback="onRecaptchaSuccess{{ block.id }}"
11
- data-expired-callback="onRecaptchaExpired{{ block.id }}"
12
- data-error-callback="onRecaptchaError{{ block.id }}"
13
- id="recaptcha-{{ block.id }}">
10
+ data-sitekey="6Lf_9MMrAAAAAOAsVXk8F5scxr6vsZJzC2jJnGHb"
11
+ data-theme="{{ value.tema|default:'light' }}"
12
+ data-size="{{ value.tamanho|default:'normal' }}"
13
+ data-callback="onRecaptchaSuccess"
14
+ data-expired-callback="onRecaptchaExpired"
15
+ data-error-callback="onRecaptchaError"
16
+ id="recaptcha-widget">
14
17
  </div>
15
18
 
16
19
  <!-- Status da verificação -->
17
- <div id="status-{{ block.id }}" class="recaptcha-status mt-3" style="display: none;">
20
+ <div id="status-recaptcha" class="recaptcha-status mt-3" style="display: none;">
18
21
  <div class="alert alert-success">
19
22
  <i class="fas fa-check-circle"></i>
20
23
  <strong>Verificação completa!</strong>
@@ -23,7 +26,7 @@
23
26
  </div>
24
27
 
25
28
  <!-- Status de erro -->
26
- <div id="error-{{ block.id }}" class="recaptcha-error mt-3" style="display: none;">
29
+ <div id="error-recaptcha" class="recaptcha-error mt-3" style="display: none;">
27
30
  <div class="alert alert-danger">
28
31
  <i class="fas fa-exclamation-triangle"></i>
29
32
  <strong>Erro no reCAPTCHA!</strong>
@@ -31,58 +34,100 @@
31
34
  </div>
32
35
  </div>
33
36
 
37
+ {% comment %}
34
38
  {% else %}
35
39
  <div class="alert alert-warning">
36
40
  <i class="fas fa-exclamation-triangle"></i>
37
41
  <strong>reCAPTCHA não configurado!</strong>
38
- <br><small>Configure RECAPTCHA_PUBLIC_KEY no settings.py</small>
42
+ <br><small>Configure RECAPTCHA_PUBLIC_KEY e RECAPTCHA_PRIVATE_KEY no settings.py</small>
39
43
  </div>
40
44
  {% endif %}
45
+ {% endcomment %}
41
46
  </div>
42
47
 
48
+ <!-- Script do Google reCAPTCHA (sempre carregar) -->
43
49
  <script>
44
- // Callback quando o usuário completa o reCAPTCHA
45
- window.onRecaptchaSuccess{{ block.id }} = function(response) {
46
- console.log('✅ reCAPTCHA completado com sucesso!');
47
- console.log('Token recebido:', response);
50
+ // Verificar se foi carregado
51
+ if (!window.recaptchaLoaded) {
52
+ window.recaptchaLoaded = true;
53
+ window.recaptchaToken = null;
48
54
 
49
- // Mostrar mensagem de sucesso
50
- const statusDiv = document.getElementById('status-{{ block.id }}');
51
- const errorDiv = document.getElementById('error-{{ block.id }}');
55
+ // Carregar script do Google
56
+ const script = document.createElement('script');
57
+ script.src = 'https://www.google.com/recaptcha/api.js';
58
+ script.async = true;
59
+ script.defer = true;
52
60
 
53
- if (statusDiv) statusDiv.style.display = 'block';
54
- if (errorDiv) errorDiv.style.display = 'none';
61
+ script.onload = function() {
62
+ console.log('📡 reCAPTCHA carregado com sucesso!');
63
+ };
55
64
 
56
- // Marcar como verificado
57
- const container = document.querySelector('[data-recaptcha-id="{{ block.id }}"]');
58
- container.setAttribute('data-verified', 'true');
59
- container.setAttribute('data-response', response);
60
- container.classList.add('recaptcha-verified');
61
- container.classList.remove('recaptcha-error');
65
+ script.onerror = function() {
66
+ console.error(' Erro ao carregar reCAPTCHA do Google');
67
+
68
+ // Mostrar erro visual
69
+ const errorDiv = document.getElementById('error-recaptcha');
70
+ if (errorDiv) {
71
+ errorDiv.querySelector('.alert').innerHTML = `
72
+ <i class="fas fa-wifi"></i>
73
+ <strong>Erro de conexão!</strong>
74
+ Não foi possível carregar o reCAPTCHA.
75
+ `;
76
+ errorDiv.style.display = 'block';
77
+ }
78
+ };
62
79
 
63
- // Disparar evento personalizado para integração
80
+ document.head.appendChild(script);
81
+ console.log('📡 Carregando reCAPTCHA do Google...');
82
+ }
83
+
84
+ // Callback quando reCAPTCHA é completado (nome deve coincidir com template)
85
+ function onRecaptchaSuccess(response) {
86
+ console.log('✅ reCAPTCHA completado com sucesso!');
87
+ console.log('Token recebido:', response.substring(0, 50) + '...');
88
+
89
+ recaptchaVerified = true;
90
+ recaptchaResponse = response;
91
+
92
+ // Habilitar botão de prosseguir
93
+ const botaoProsseguir = document.getElementById('prosseguir-votacao');
94
+ if (botaoProsseguir) {
95
+ botaoProsseguir.disabled = false;
96
+ botaoProsseguir.innerHTML = '✓ Iniciar Votação';
97
+ botaoProsseguir.style.background = '#007D7A';
98
+ botaoProsseguir.style.color = 'white';
99
+ }
100
+
101
+ // Mostrar texto pós-recaptcha se existir
102
+ const posTexto = document.getElementById('pos-recaptcha-text');
103
+ if (posTexto) {
104
+ posTexto.style.display = 'block';
105
+ }
106
+
107
+ // Marcar como verificado no container
108
+ const container = document.querySelector('[data-recaptcha-id]');
109
+ if (container) {
110
+ container.setAttribute('data-verified', 'true');
111
+ container.setAttribute('data-response', response);
112
+ }
113
+
114
+ // Disparar evento customizado para integração
64
115
  document.dispatchEvent(new CustomEvent('recaptchaCompleted', {
65
116
  detail: {
66
- blockId: '{{ block.id }}',
67
117
  response: response,
68
118
  success: true
69
119
  }
70
120
  }));
71
-
72
- // Habilitar botões de submit se existirem
73
- const submitButtons = document.querySelectorAll('button[type="submit"], input[type="submit"]');
74
- submitButtons.forEach(btn => {
75
- btn.disabled = false;
76
- btn.classList.remove('disabled');
77
- });
78
- };
121
+ }
79
122
 
80
123
  // Callback quando expira
81
- window.onRecaptchaExpired{{ block.id }} = function() {
124
+ window.onRecaptchaExpired = function() {
82
125
  console.log('⚠️ reCAPTCHA expirado');
83
126
 
84
- const statusDiv = document.getElementById('status-{{ block.id }}');
85
- const errorDiv = document.getElementById('error-{{ block.id }}');
127
+ window.recaptchaToken = null;
128
+
129
+ const statusDiv = document.getElementById('status-recaptcha');
130
+ const errorDiv = document.getElementById('error-recaptcha');
86
131
 
87
132
  if (statusDiv) statusDiv.style.display = 'none';
88
133
  if (errorDiv) {
@@ -94,10 +139,13 @@ window.onRecaptchaExpired{{ block.id }} = function() {
94
139
  errorDiv.style.display = 'block';
95
140
  }
96
141
 
97
- const container = document.querySelector('[data-recaptcha-id="{{ block.id }}"]');
98
- container.setAttribute('data-verified', 'false');
99
- container.classList.remove('recaptcha-verified');
100
- container.classList.add('recaptcha-error');
142
+ const container = document.querySelector('[data-recaptcha-id]');
143
+ if (container) {
144
+ container.setAttribute('data-verified', 'false');
145
+ container.setAttribute('data-response', '');
146
+ container.classList.remove('recaptcha-verified');
147
+ container.classList.add('recaptcha-error');
148
+ }
101
149
 
102
150
  // Desabilitar botões de submit
103
151
  const submitButtons = document.querySelectorAll('button[type="submit"], input[type="submit"]');
@@ -108,11 +156,13 @@ window.onRecaptchaExpired{{ block.id }} = function() {
108
156
  };
109
157
 
110
158
  // Callback de erro
111
- window.onRecaptchaError{{ block.id }} = function() {
159
+ window.onRecaptchaError = function() {
112
160
  console.log('❌ Erro no reCAPTCHA');
113
161
 
114
- const statusDiv = document.getElementById('status-{{ block.id }}');
115
- const errorDiv = document.getElementById('error-{{ block.id }}');
162
+ window.recaptchaToken = null;
163
+
164
+ const statusDiv = document.getElementById('status-recaptcha');
165
+ const errorDiv = document.getElementById('error-recaptcha');
116
166
 
117
167
  if (statusDiv) statusDiv.style.display = 'none';
118
168
  if (errorDiv) {
@@ -124,22 +174,23 @@ window.onRecaptchaError{{ block.id }} = function() {
124
174
  errorDiv.style.display = 'block';
125
175
  }
126
176
 
127
- const container = document.querySelector('[data-recaptcha-id="{{ block.id }}"]');
128
- container.setAttribute('data-verified', 'false');
129
- container.classList.remove('recaptcha-verified');
130
- container.classList.add('recaptcha-error');
177
+ const container = document.querySelector('[data-recaptcha-id]');
178
+ if (container) {
179
+ container.setAttribute('data-verified', 'false');
180
+ container.setAttribute('data-response', '');
181
+ container.classList.remove('recaptcha-verified');
182
+ container.classList.add('recaptcha-error');
183
+ }
131
184
  };
132
185
 
133
186
  // Utilitários públicos para JavaScript
134
- window.recaptchaUtils{{ block.id }} = {
187
+ window.recaptchaUtils = {
135
188
  isVerified: function() {
136
- const container = document.querySelector('[data-recaptcha-id="{{ block.id }}"]');
137
- return container && container.getAttribute('data-verified') === 'true';
189
+ return window.recaptchaToken && window.recaptchaToken.length > 0;
138
190
  },
139
191
 
140
192
  getResponse: function() {
141
- const container = document.querySelector('[data-recaptcha-id="{{ block.id }}"]');
142
- return container ? (container.getAttribute('data-response') || '') : '';
193
+ return window.recaptchaToken || '';
143
194
  },
144
195
 
145
196
  reset: function() {
@@ -152,72 +203,29 @@ window.recaptchaUtils{{ block.id }} = {
152
203
  }
153
204
  }
154
205
 
155
- const container = document.querySelector('[data-recaptcha-id="{{ block.id }}"]');
206
+ window.recaptchaToken = null;
207
+
208
+ const container = document.querySelector('[data-recaptcha-id]');
156
209
  if (container) {
157
210
  container.setAttribute('data-verified', 'false');
211
+ container.setAttribute('data-response', '');
158
212
  container.classList.remove('recaptcha-verified', 'recaptcha-error');
159
213
  }
160
214
 
161
- const statusDiv = document.getElementById('status-{{ block.id }}');
162
- const errorDiv = document.getElementById('error-{{ block.id }}');
215
+ const statusDiv = document.getElementById('status-recaptcha');
216
+ const errorDiv = document.getElementById('error-recaptcha');
163
217
 
164
218
  if (statusDiv) statusDiv.style.display = 'none';
165
219
  if (errorDiv) errorDiv.style.display = 'none';
166
- },
167
-
168
- execute: function() {
169
- if (typeof grecaptcha !== 'undefined') {
170
- try {
171
- grecaptcha.execute();
172
- console.log('▶️ reCAPTCHA executado');
173
- } catch (e) {
174
- console.log('⚠️ Erro ao executar reCAPTCHA:', e);
175
- }
176
- }
177
220
  }
178
221
  };
179
222
 
180
- // Carregar script do Google reCAPTCHA (apenas uma vez)
181
- if (!document.querySelector('script[src*="recaptcha/api.js"]') && {{ has_recaptcha_keys|yesno:"true,false" }}) {
182
- const script = document.createElement('script');
183
- script.src = 'https://www.google.com/recaptcha/api.js';
184
- script.async = true;
185
- script.defer = true;
186
-
187
- script.onload = function() {
188
- console.log('📡 reCAPTCHA carregado com sucesso!');
189
- };
190
-
191
- script.onerror = function() {
192
- console.log('❌ Erro ao carregar reCAPTCHA do Google');
193
-
194
- const errorDiv = document.getElementById('error-{{ block.id }}');
195
- if (errorDiv) {
196
- errorDiv.querySelector('.alert').innerHTML = `
197
- <i class="fas fa-wifi"></i>
198
- <strong>Erro de conexão!</strong>
199
- Não foi possível carregar o reCAPTCHA.
200
- `;
201
- errorDiv.style.display = 'block';
202
- }
203
- };
204
-
205
- document.head.appendChild(script);
206
- console.log('📡 Carregando reCAPTCHA do Google...');
207
- }
208
-
209
- // Event listener global para debug
210
- document.addEventListener('recaptchaCompleted', function(e) {
211
- console.log('🎉 Evento reCAPTCHA global:', e.detail);
212
- });
213
-
214
223
  // Debug: informações da configuração
215
- console.log('🔍 reCAPTCHA Config:');
216
- console.log('- Block ID:', '{{ block.id }}');
217
- console.log('- Public Key:', '{{ recaptcha_public_key|truncatechars:20 }}...');
218
- console.log('- Has Keys:', {{ has_recaptcha_keys|yesno:"true,false" }});
219
- console.log('- Tema:', '{{ value.tema }}');
220
- console.log('- Tamanho:', '{{ value.tamanho }}');
224
+ console.log('🔍 reCAPTCHA Config (FIXED):');
225
+ console.log('- Public Key: 6Lf_9MMrAAAAAOAsVXk8...');
226
+ console.log('- Has Keys: true');
227
+ console.log('- Tema:', '{{ value.tema|default:"light" }}');
228
+ console.log('- Tamanho:', '{{ value.tamanho|default:"normal" }}');
221
229
  </script>
222
230
 
223
231
  <style>
@@ -229,6 +237,7 @@ console.log('- Tamanho:', '{{ value.tamanho }}');
229
237
  align-items: center;
230
238
  border-radius: 8px;
231
239
  transition: all 0.3s ease;
240
+ border: 2px solid #e5e7eb;
232
241
  }
233
242
 
234
243
  .recaptcha-container .g-recaptcha {
@@ -285,6 +294,32 @@ console.log('- Tamanho:', '{{ value.tamanho }}');
285
294
  }
286
295
  }
287
296
 
297
+ /* Alertas */
298
+ .alert {
299
+ padding: 12px 16px;
300
+ border-radius: 6px;
301
+ margin: 10px 0;
302
+ border: 1px solid transparent;
303
+ }
304
+
305
+ .alert-success {
306
+ background-color: #d4edda;
307
+ border-color: #c3e6cb;
308
+ color: #155724;
309
+ }
310
+
311
+ .alert-danger {
312
+ background-color: #f8d7da;
313
+ border-color: #f5c6cb;
314
+ color: #721c24;
315
+ }
316
+
317
+ .alert-warning {
318
+ background-color: #fff3cd;
319
+ border-color: #ffeaa7;
320
+ color: #856404;
321
+ }
322
+
288
323
  /* Responsivo */
289
324
  @media (max-width: 576px) {
290
325
  .recaptcha-container {
@@ -293,7 +328,7 @@ console.log('- Tamanho:', '{{ value.tamanho }}');
293
328
  }
294
329
 
295
330
  .recaptcha-container .g-recaptcha {
296
- transform: scale(0.9);
331
+ transform: scale(0.85);
297
332
  transform-origin: center;
298
333
  }
299
334
  }
@@ -318,19 +353,4 @@ console.log('- Tamanho:', '{{ value.tamanho }}');
318
353
  margin-left: auto;
319
354
  margin-right: auto;
320
355
  }
321
-
322
- /* Tema escuro */
323
- .recaptcha-container[data-theme="dark"] {
324
- background: #343a40;
325
- border-color: #495057;
326
- color: #fff;
327
- }
328
-
329
- .recaptcha-container[data-theme="dark"].recaptcha-verified {
330
- background: linear-gradient(135deg, #1e5c3a 0%, #28a745 100%);
331
- }
332
-
333
- .recaptcha-container[data-theme="dark"].recaptcha-error {
334
- background: linear-gradient(135deg, #5c1e1e 0%, #dc3545 100%);
335
- }
336
356
  </style>
@@ -241,6 +241,7 @@
241
241
  line-height: 1.6;
242
242
  color: #555;
243
243
  margin-bottom: 2rem;
244
+ text-align: left;
244
245
  }
245
246
 
246
247
  .start-btn {