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.
- enap_designsystem/context_processors.py +30 -6
- enap_designsystem/migrations/0405_sistemavotacaopage_exigir_recaptcha_and_more.py +41 -0
- enap_designsystem/models.py +83 -48
- enap_designsystem/settings.py +4 -0
- enap_designsystem/templates/enap_designsystem/blocks/recaptcha.html +146 -126
- enap_designsystem/templates/enap_designsystem/form_templates/formulario_page.html +1 -0
- enap_designsystem/templates/enap_designsystem/sistema_votacao_page.html +580 -548
- {wagtail_enap_designsystem-1.2.1.130.dist-info → wagtail_enap_designsystem-1.2.1.131.dist-info}/METADATA +1 -1
- {wagtail_enap_designsystem-1.2.1.130.dist-info → wagtail_enap_designsystem-1.2.1.131.dist-info}/RECORD +12 -11
- {wagtail_enap_designsystem-1.2.1.130.dist-info → wagtail_enap_designsystem-1.2.1.131.dist-info}/WHEEL +0 -0
- {wagtail_enap_designsystem-1.2.1.130.dist-info → wagtail_enap_designsystem-1.2.1.131.dist-info}/licenses/LICENSE +0 -0
- {wagtail_enap_designsystem-1.2.1.130.dist-info → wagtail_enap_designsystem-1.2.1.131.dist-info}/top_level.txt +0 -0
|
@@ -1,20 +1,23 @@
|
|
|
1
1
|
<!-- templates/blocks/recaptcha.html -->
|
|
2
|
-
|
|
2
|
+
{% load static %}
|
|
3
|
+
|
|
4
|
+
<div class="recaptcha-container {{ value.css_classes }}" data-recaptcha-id="recaptcha-widget">
|
|
3
5
|
|
|
4
|
-
|
|
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="
|
|
8
|
-
data-theme="{{ value.tema }}"
|
|
9
|
-
data-size="{{ value.tamanho }}"
|
|
10
|
-
data-callback="onRecaptchaSuccess
|
|
11
|
-
data-expired-callback="onRecaptchaExpired
|
|
12
|
-
data-error-callback="onRecaptchaError
|
|
13
|
-
id="recaptcha-
|
|
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-
|
|
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-
|
|
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
|
-
//
|
|
45
|
-
window.
|
|
46
|
-
|
|
47
|
-
|
|
50
|
+
// Verificar se já foi carregado
|
|
51
|
+
if (!window.recaptchaLoaded) {
|
|
52
|
+
window.recaptchaLoaded = true;
|
|
53
|
+
window.recaptchaToken = null;
|
|
48
54
|
|
|
49
|
-
//
|
|
50
|
-
const
|
|
51
|
-
|
|
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
|
-
|
|
54
|
-
|
|
61
|
+
script.onload = function() {
|
|
62
|
+
console.log('📡 reCAPTCHA carregado com sucesso!');
|
|
63
|
+
};
|
|
55
64
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
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
|
-
|
|
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
|
|
124
|
+
window.onRecaptchaExpired = function() {
|
|
82
125
|
console.log('⚠️ reCAPTCHA expirado');
|
|
83
126
|
|
|
84
|
-
|
|
85
|
-
|
|
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
|
|
98
|
-
container
|
|
99
|
-
|
|
100
|
-
|
|
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
|
|
159
|
+
window.onRecaptchaError = function() {
|
|
112
160
|
console.log('❌ Erro no reCAPTCHA');
|
|
113
161
|
|
|
114
|
-
|
|
115
|
-
|
|
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
|
|
128
|
-
container
|
|
129
|
-
|
|
130
|
-
|
|
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
|
|
187
|
+
window.recaptchaUtils = {
|
|
135
188
|
isVerified: function() {
|
|
136
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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-
|
|
162
|
-
const errorDiv = document.getElementById('error-
|
|
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('-
|
|
217
|
-
console.log('-
|
|
218
|
-
console.log('-
|
|
219
|
-
console.log('-
|
|
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.
|
|
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>
|