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
|
@@ -5,11 +5,9 @@ from .models import EnapNavbarSnippet
|
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
def global_template_context(request):
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
8
|
+
return {
|
|
9
|
+
'debug': settings.DEBUG
|
|
10
|
+
}
|
|
13
11
|
|
|
14
12
|
|
|
15
13
|
def navbar_context(request):
|
|
@@ -20,4 +18,30 @@ def navbar_context(request):
|
|
|
20
18
|
navbar = EnapNavbarSnippet.objects.first()
|
|
21
19
|
return {'enap_navbar': navbar}
|
|
22
20
|
except EnapNavbarSnippet.DoesNotExist:
|
|
23
|
-
return {'enap_navbar': None}
|
|
21
|
+
return {'enap_navbar': None}
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def recaptcha_context(request):
|
|
25
|
+
"""Adiciona configurações do reCAPTCHA ao contexto global"""
|
|
26
|
+
try:
|
|
27
|
+
from django.conf import settings
|
|
28
|
+
|
|
29
|
+
# Obter chaves do settings
|
|
30
|
+
public_key = getattr(settings, 'RECAPTCHA_PUBLIC_KEY', '')
|
|
31
|
+
private_key = getattr(settings, 'RECAPTCHA_PRIVATE_KEY', '')
|
|
32
|
+
|
|
33
|
+
print(f"DEBUG reCAPTCHA Context - EXECUTANDO:")
|
|
34
|
+
print(f"- Public Key: {public_key[:20]}..." if public_key else "- Public Key: VAZIA")
|
|
35
|
+
print(f"- Private Key: {private_key[:20]}..." if private_key else "- Private Key: VAZIA")
|
|
36
|
+
print(f"- Has Keys: {bool(public_key and private_key)}")
|
|
37
|
+
|
|
38
|
+
return {
|
|
39
|
+
'recaptcha_public_key': public_key,
|
|
40
|
+
'has_recaptcha_keys': bool(public_key and private_key),
|
|
41
|
+
}
|
|
42
|
+
except Exception as e:
|
|
43
|
+
print(f"ERRO no context processor: {e}")
|
|
44
|
+
return {
|
|
45
|
+
'recaptcha_public_key': '',
|
|
46
|
+
'has_recaptcha_keys': False,
|
|
47
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# Generated by Django 5.1.6 on 2025-09-09 20:42
|
|
2
|
+
|
|
3
|
+
import wagtail.fields
|
|
4
|
+
from django.db import migrations, models
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class Migration(migrations.Migration):
|
|
8
|
+
|
|
9
|
+
dependencies = [
|
|
10
|
+
("enap_designsystem", "0404_sistemavotacaopage_conteudo_pagina"),
|
|
11
|
+
]
|
|
12
|
+
|
|
13
|
+
operations = [
|
|
14
|
+
migrations.AddField(
|
|
15
|
+
model_name="sistemavotacaopage",
|
|
16
|
+
name="exigir_recaptcha",
|
|
17
|
+
field=models.BooleanField(
|
|
18
|
+
default=True,
|
|
19
|
+
help_text="Marque para exigir verificação reCAPTCHA antes de mostrar votação",
|
|
20
|
+
verbose_name="Exigir reCAPTCHA",
|
|
21
|
+
),
|
|
22
|
+
),
|
|
23
|
+
migrations.AddField(
|
|
24
|
+
model_name="sistemavotacaopage",
|
|
25
|
+
name="texto_pos_recaptcha",
|
|
26
|
+
field=wagtail.fields.RichTextField(
|
|
27
|
+
blank=True,
|
|
28
|
+
help_text="Mensagem exibida após verificação bem-sucedida (opcional)",
|
|
29
|
+
verbose_name="Texto após verificação",
|
|
30
|
+
),
|
|
31
|
+
),
|
|
32
|
+
migrations.AddField(
|
|
33
|
+
model_name="sistemavotacaopage",
|
|
34
|
+
name="texto_pre_recaptcha",
|
|
35
|
+
field=wagtail.fields.RichTextField(
|
|
36
|
+
default="<p>Para acessar o sistema de votação, confirme que você não é um robô:</p>",
|
|
37
|
+
help_text="Mensagem exibida antes da verificação do reCAPTCHA",
|
|
38
|
+
verbose_name="Texto antes do reCAPTCHA",
|
|
39
|
+
),
|
|
40
|
+
),
|
|
41
|
+
]
|
enap_designsystem/models.py
CHANGED
|
@@ -4791,15 +4791,15 @@ class SistemaVotacaoPage(Page):
|
|
|
4791
4791
|
)
|
|
4792
4792
|
|
|
4793
4793
|
background_image_fundo = StreamField(
|
|
4794
|
-
|
|
4795
|
-
|
|
4796
|
-
|
|
4797
|
-
|
|
4798
|
-
|
|
4799
|
-
|
|
4800
|
-
|
|
4801
|
-
|
|
4802
|
-
|
|
4794
|
+
[('background_image_stream', ImageChooserBlock(
|
|
4795
|
+
label="Imagem de Fundo",
|
|
4796
|
+
help_text="Selecione uma imagem de fundo para o formulário"
|
|
4797
|
+
))],
|
|
4798
|
+
verbose_name="Imagem de Fundo",
|
|
4799
|
+
use_json_field=True,
|
|
4800
|
+
max_num=1,
|
|
4801
|
+
blank=True,
|
|
4802
|
+
help_text="Adicione uma imagem de fundo para o formulário"
|
|
4803
4803
|
)
|
|
4804
4804
|
|
|
4805
4805
|
subtitulo = models.CharField(
|
|
@@ -4815,6 +4815,25 @@ class SistemaVotacaoPage(Page):
|
|
|
4815
4815
|
help_text="Texto adicional no topo da página (opcional)"
|
|
4816
4816
|
)
|
|
4817
4817
|
|
|
4818
|
+
# Campos para reCAPTCHA
|
|
4819
|
+
texto_pre_recaptcha = RichTextField(
|
|
4820
|
+
default="<p>Para acessar o sistema de votação, confirme que você não é um robô:</p>",
|
|
4821
|
+
verbose_name="Texto antes do reCAPTCHA",
|
|
4822
|
+
help_text="Mensagem exibida antes da verificação do reCAPTCHA"
|
|
4823
|
+
)
|
|
4824
|
+
|
|
4825
|
+
texto_pos_recaptcha = RichTextField(
|
|
4826
|
+
blank=True,
|
|
4827
|
+
verbose_name="Texto após verificação",
|
|
4828
|
+
help_text="Mensagem exibida após verificação bem-sucedida (opcional)"
|
|
4829
|
+
)
|
|
4830
|
+
|
|
4831
|
+
exigir_recaptcha = models.BooleanField(
|
|
4832
|
+
default=True,
|
|
4833
|
+
verbose_name="Exigir reCAPTCHA",
|
|
4834
|
+
help_text="Marque para exigir verificação reCAPTCHA antes de mostrar votação"
|
|
4835
|
+
)
|
|
4836
|
+
|
|
4818
4837
|
imagem_fundo = StreamField([
|
|
4819
4838
|
("image", ImageChooserBlock(
|
|
4820
4839
|
required=False,
|
|
@@ -4828,7 +4847,6 @@ class SistemaVotacaoPage(Page):
|
|
|
4828
4847
|
|
|
4829
4848
|
conteudo_pagina = StreamField([
|
|
4830
4849
|
('secao_apresentacao', SecaoApresentacaoBlock()),
|
|
4831
|
-
# Você pode adicionar outros blocos aqui também
|
|
4832
4850
|
],
|
|
4833
4851
|
blank=True,
|
|
4834
4852
|
use_json_field=True,
|
|
@@ -4861,7 +4879,6 @@ class SistemaVotacaoPage(Page):
|
|
|
4861
4879
|
verbose_name="Ordenação dos Projetos"
|
|
4862
4880
|
)
|
|
4863
4881
|
|
|
4864
|
-
# Meta configurações
|
|
4865
4882
|
votacao_ativa = models.BooleanField(
|
|
4866
4883
|
default=True,
|
|
4867
4884
|
verbose_name="Votação Ativa",
|
|
@@ -4883,13 +4900,13 @@ class SistemaVotacaoPage(Page):
|
|
|
4883
4900
|
)
|
|
4884
4901
|
|
|
4885
4902
|
configuracoes_votacao = StreamField([
|
|
4886
|
-
|
|
4887
|
-
|
|
4888
|
-
|
|
4889
|
-
|
|
4890
|
-
|
|
4891
|
-
|
|
4892
|
-
|
|
4903
|
+
('recaptcha', RecaptchaBlock()),
|
|
4904
|
+
],
|
|
4905
|
+
blank=True,
|
|
4906
|
+
use_json_field=True,
|
|
4907
|
+
verbose_name="Configurações e Elementos da Votação",
|
|
4908
|
+
help_text="Adicione reCAPTCHA para a página de votação"
|
|
4909
|
+
)
|
|
4893
4910
|
|
|
4894
4911
|
footer = models.ForeignKey(
|
|
4895
4912
|
"EnapFooterSnippet",
|
|
@@ -4898,22 +4915,26 @@ class SistemaVotacaoPage(Page):
|
|
|
4898
4915
|
on_delete=models.SET_NULL,
|
|
4899
4916
|
related_name="+",
|
|
4900
4917
|
)
|
|
4901
|
-
|
|
4902
4918
|
|
|
4903
4919
|
content_panels = Page.content_panels + [
|
|
4904
|
-
|
|
4905
4920
|
MultiFieldPanel([
|
|
4906
4921
|
FieldPanel('subtitulo'),
|
|
4907
4922
|
FieldPanel('descricao_header'),
|
|
4908
|
-
|
|
4909
|
-
|
|
4910
|
-
|
|
4911
|
-
|
|
4923
|
+
FieldPanel('imagem_fundo'),
|
|
4924
|
+
FieldPanel('navbar'),
|
|
4925
|
+
FieldPanel('footer'),
|
|
4926
|
+
FieldPanel('background_image_fundo'),
|
|
4912
4927
|
], heading="Conteúdo do Header"),
|
|
4913
4928
|
|
|
4914
|
-
|
|
4929
|
+
# Nova seção para reCAPTCHA
|
|
4930
|
+
MultiFieldPanel([
|
|
4931
|
+
FieldPanel('exigir_recaptcha'),
|
|
4932
|
+
FieldPanel('texto_pre_recaptcha'),
|
|
4933
|
+
FieldPanel('texto_pos_recaptcha'),
|
|
4934
|
+
], heading="Configurações do reCAPTCHA"),
|
|
4915
4935
|
|
|
4916
|
-
|
|
4936
|
+
FieldPanel('conteudo_pagina'),
|
|
4937
|
+
FieldPanel('configuracoes_votacao'),
|
|
4917
4938
|
|
|
4918
4939
|
MultiFieldPanel([
|
|
4919
4940
|
FieldPanel('mostrar_progresso'),
|
|
@@ -4933,16 +4954,29 @@ class SistemaVotacaoPage(Page):
|
|
|
4933
4954
|
|
|
4934
4955
|
def get_context(self, request):
|
|
4935
4956
|
context = super().get_context(request)
|
|
4936
|
-
|
|
4937
|
-
|
|
4957
|
+
|
|
4958
|
+
# Adicionar configuração do reCAPTCHA ao contexto
|
|
4959
|
+
context.update({
|
|
4960
|
+
'exigir_recaptcha': self.exigir_recaptcha,
|
|
4961
|
+
'recaptcha_config': {
|
|
4962
|
+
'tema': 'light',
|
|
4963
|
+
'tamanho': 'normal',
|
|
4964
|
+
'css_classes': 'text-center my-4'
|
|
4965
|
+
}
|
|
4966
|
+
})
|
|
4967
|
+
|
|
4968
|
+
# SEMPRE carregar dados de votação (sem verificação de reCAPTCHA)
|
|
4969
|
+
print("✅ Carregando dados de votação...")
|
|
4970
|
+
|
|
4971
|
+
# Buscar categorias ativas
|
|
4938
4972
|
categorias = CategoriaVotacao.objects.filter(ativo=True).order_by('ordem')
|
|
4939
|
-
|
|
4940
|
-
|
|
4973
|
+
|
|
4974
|
+
# Buscar projetos por categoria
|
|
4941
4975
|
projetos_por_categoria = {}
|
|
4942
4976
|
for categoria in categorias:
|
|
4943
4977
|
projetos = categoria.projetos.filter(ativo=True)
|
|
4944
|
-
|
|
4945
|
-
|
|
4978
|
+
|
|
4979
|
+
# Aplicar ordenação
|
|
4946
4980
|
if self.ordenacao_projetos == 'votos_desc':
|
|
4947
4981
|
projetos = sorted(projetos, key=lambda p: p.total_votos, reverse=True)
|
|
4948
4982
|
elif self.ordenacao_projetos == 'votos_asc':
|
|
@@ -4953,36 +4987,37 @@ class SistemaVotacaoPage(Page):
|
|
|
4953
4987
|
projetos = projetos.order_by('-created_at')
|
|
4954
4988
|
else: # 'ordem'
|
|
4955
4989
|
projetos = projetos.order_by('ordem', 'titulo')
|
|
4956
|
-
|
|
4990
|
+
|
|
4957
4991
|
projetos_por_categoria[categoria] = projetos
|
|
4958
|
-
|
|
4959
|
-
|
|
4992
|
+
|
|
4993
|
+
# Estatísticas gerais
|
|
4960
4994
|
total_categorias = categorias.count()
|
|
4961
4995
|
total_projetos = ProjetoVotacao.objects.filter(ativo=True).count()
|
|
4962
4996
|
total_votos = VotoRegistrado.objects.count()
|
|
4963
|
-
|
|
4997
|
+
|
|
4998
|
+
# Adicionar todos os dados ao contexto
|
|
4964
4999
|
context.update({
|
|
4965
|
-
|
|
4966
|
-
|
|
4967
|
-
|
|
4968
|
-
|
|
4969
|
-
|
|
4970
|
-
|
|
4971
|
-
|
|
4972
|
-
|
|
5000
|
+
'categorias': categorias,
|
|
5001
|
+
'projetos_por_categoria': projetos_por_categoria,
|
|
5002
|
+
'total_categorias': total_categorias,
|
|
5003
|
+
'total_projetos': total_projetos,
|
|
5004
|
+
'total_votos': total_votos,
|
|
5005
|
+
})
|
|
5006
|
+
|
|
5007
|
+
context['votacao_ativa'] = self.is_votacao_ativa()
|
|
4973
5008
|
return context
|
|
4974
5009
|
|
|
4975
5010
|
def is_votacao_ativa(self):
|
|
4976
5011
|
"""Verifica se a votação está ativa baseado nas configurações"""
|
|
4977
5012
|
if not self.votacao_ativa:
|
|
4978
5013
|
return False
|
|
4979
|
-
|
|
5014
|
+
|
|
5015
|
+
from django.utils import timezone
|
|
4980
5016
|
now = timezone.now()
|
|
4981
|
-
|
|
5017
|
+
|
|
4982
5018
|
if self.data_inicio and now < self.data_inicio:
|
|
4983
5019
|
return False
|
|
4984
|
-
|
|
5020
|
+
|
|
4985
5021
|
if self.data_fim and now > self.data_fim:
|
|
4986
5022
|
return False
|
|
4987
|
-
|
|
4988
5023
|
return True
|
enap_designsystem/settings.py
CHANGED
|
@@ -2,6 +2,9 @@ import os
|
|
|
2
2
|
|
|
3
3
|
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
|
|
4
4
|
|
|
5
|
+
RECAPTCHA_PUBLIC_KEY = "6Lf_9MMrAAAAAOAsVXk8F5scxr6vsZJzC2jJnGHb"
|
|
6
|
+
RECAPTCHA_PRIVATE_KEY = "6Lf_9MMrAAAAAJqd_uA1_ekq3F-bD24KRhBcfKCF"
|
|
7
|
+
|
|
5
8
|
WAGTAIL_404_TEMPLATE = '404.html'
|
|
6
9
|
|
|
7
10
|
STATICFILES_DIRS = [os.path.join(BASE_DIR, "static")]
|
|
@@ -18,6 +21,7 @@ TEMPLATES = [
|
|
|
18
21
|
"django.contrib.auth.context_processors.auth",
|
|
19
22
|
"django.contrib.messages.context_processors.messages",
|
|
20
23
|
"enap_designsystem.context_processors.navbar_context",
|
|
24
|
+
"enap_designsystem.context_processors.recaptcha_context",
|
|
21
25
|
],
|
|
22
26
|
},
|
|
23
27
|
},
|