wagtail-enap-designsystem 1.2.1.130__py3-none-any.whl → 1.2.1.132__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.
Files changed (19) hide show
  1. enap_designsystem/blocks/form.py +81 -49
  2. enap_designsystem/context_processors.py +30 -6
  3. enap_designsystem/migrations/0405_sistemavotacaopage_exigir_recaptcha_and_more.py +41 -0
  4. enap_designsystem/migrations/0406_alter_areaaluno_body_alter_cursoeadpage_curso_and_more.py +55023 -0
  5. enap_designsystem/migrations/0407_alter_formulariopage_form_steps.py +1277 -0
  6. enap_designsystem/migrations/0408_alter_areaaluno_body_alter_enapcomponentes_body_and_more.py +53961 -0
  7. enap_designsystem/migrations/0409_alter_areaaluno_body_alter_enapcomponentes_body_and_more.py +54062 -0
  8. enap_designsystem/migrations/0410_alter_formulariopage_form_steps.py +1278 -0
  9. enap_designsystem/models.py +83 -48
  10. enap_designsystem/settings.py +4 -0
  11. enap_designsystem/templates/enap_designsystem/blocks/recaptcha.html +146 -126
  12. enap_designsystem/templates/enap_designsystem/form_templates/formulario_page.html +457 -109
  13. enap_designsystem/templates/enap_designsystem/includes/form_field.html +108 -443
  14. enap_designsystem/templates/enap_designsystem/sistema_votacao_page.html +580 -548
  15. {wagtail_enap_designsystem-1.2.1.130.dist-info → wagtail_enap_designsystem-1.2.1.132.dist-info}/METADATA +1 -1
  16. {wagtail_enap_designsystem-1.2.1.130.dist-info → wagtail_enap_designsystem-1.2.1.132.dist-info}/RECORD +19 -13
  17. {wagtail_enap_designsystem-1.2.1.130.dist-info → wagtail_enap_designsystem-1.2.1.132.dist-info}/WHEEL +0 -0
  18. {wagtail_enap_designsystem-1.2.1.130.dist-info → wagtail_enap_designsystem-1.2.1.132.dist-info}/licenses/LICENSE +0 -0
  19. {wagtail_enap_designsystem-1.2.1.130.dist-info → wagtail_enap_designsystem-1.2.1.132.dist-info}/top_level.txt +0 -0
@@ -657,7 +657,7 @@ class CheckboxMultiRedirectFieldBlock(blocks.StructBlock):
657
657
  label="Opções e Ações",
658
658
  help_text="Configure as opções e o que acontece para cada uma",
659
659
  min_num=1,
660
- max_num=10
660
+ max_num=500
661
661
  )
662
662
 
663
663
  class Meta:
@@ -708,6 +708,7 @@ class ConditionalFieldBlock(blocks.StructBlock):
708
708
  choices=[
709
709
  ('show_fields', '👁️ Mostrar campos'),
710
710
  ('nothing', '➡️ Não fazer nada (pular)'),
711
+ ('end_form', '⛔ Encerrar formulário'),
711
712
  ],
712
713
  default='nothing'
713
714
  )),
@@ -806,7 +807,7 @@ class SmartNavigationFieldBlock(blocks.StructBlock):
806
807
  label="Opções e Navegação",
807
808
  help_text="Configure para onde cada resposta leva o usuário",
808
809
  min_num=1,
809
- max_num=10
810
+ max_num=100
810
811
  )
811
812
 
812
813
  class Meta:
@@ -980,6 +981,13 @@ class FormStepBlock(StructBlock):
980
981
  required=False,
981
982
  help_text="Imagem que será exibida no cabeçalho desta etapa (opcional)"
982
983
  )
984
+
985
+ order = CharBlock(
986
+ label="Ordem da Etapa",
987
+ max_length=3,
988
+ help_text="Número para definir a ordem (ex: 1, 2, 3...)",
989
+ default="1"
990
+ )
983
991
 
984
992
  logo_alt = CharBlock(
985
993
  label="Texto Alternativo da Logo",
@@ -1059,7 +1067,7 @@ class FormularioPage(Page):
1059
1067
  verbose_name="Etapas do Formulário",
1060
1068
  use_json_field=True,
1061
1069
  min_num=1,
1062
- max_num=10,
1070
+ max_num=100,
1063
1071
  help_text="Adicione quantas etapas precisar (mínimo 1, máximo 10)"
1064
1072
  )
1065
1073
 
@@ -1102,7 +1110,7 @@ class FormularioPage(Page):
1102
1110
  ))],
1103
1111
  verbose_name="Logo",
1104
1112
  use_json_field=True,
1105
- max_num=1, # Só permite uma logo
1113
+ max_num=100, # Só permite uma logo
1106
1114
  blank=True,
1107
1115
  help_text="Adicione o logo do formulário"
1108
1116
  )
@@ -1114,7 +1122,7 @@ class FormularioPage(Page):
1114
1122
  ))],
1115
1123
  verbose_name="Imagem de Fundo",
1116
1124
  use_json_field=True,
1117
- max_num=1,
1125
+ max_num=500,
1118
1126
  blank=True,
1119
1127
  help_text="Adicione uma imagem de fundo para o formulário"
1120
1128
  )
@@ -1126,7 +1134,7 @@ class FormularioPage(Page):
1126
1134
  ))],
1127
1135
  verbose_name="Imagem de Agradecimento",
1128
1136
  use_json_field=True,
1129
- max_num=1,
1137
+ max_num=500,
1130
1138
  blank=True,
1131
1139
  help_text="Adicione uma imagem para a tela de sucesso"
1132
1140
  )
@@ -1262,46 +1270,6 @@ class FormularioPage(Page):
1262
1270
 
1263
1271
  return submission
1264
1272
 
1265
- def get_all_steps(self):
1266
- """Retorna todas as etapas organizadas com seções - SEM title/subtitle"""
1267
- steps = []
1268
- for index, step_block in enumerate(self.form_steps):
1269
- step_data = {
1270
- 'number': index + 1,
1271
- 'logo': step_block.value.get('logo'),
1272
- 'logo_alt': step_block.value.get('logo_alt', ''),
1273
- 'fields': step_block.value['fields'],
1274
- 'id': step_block.id,
1275
- 'sections': []
1276
- }
1277
-
1278
- # Organizar campos em seções
1279
- current_section = None
1280
- for field_block in step_block.value['fields']:
1281
- if field_block.block_type == 'section_header':
1282
- # Nova seção
1283
- current_section = {
1284
- 'title': field_block.value['title'],
1285
- 'subtitle': field_block.value.get('subtitle', ''),
1286
- 'fields': []
1287
- }
1288
- step_data['sections'].append(current_section)
1289
- else:
1290
- # Campo normal
1291
- if current_section is None:
1292
- # Criar seção padrão se não existir
1293
- current_section = {
1294
- 'title': '',
1295
- 'subtitle': '',
1296
- 'fields': []
1297
- }
1298
- step_data['sections'].append(current_section)
1299
-
1300
- current_section['fields'].append(field_block)
1301
-
1302
- steps.append(step_data)
1303
- return steps
1304
-
1305
1273
  def get_total_steps(self):
1306
1274
  """Retorna o número total de etapas (incluindo boas-vindas e sucesso)"""
1307
1275
  return len(self.form_steps) + 2 # +2 para boas-vindas e sucesso
@@ -1899,6 +1867,70 @@ class FormularioPage(Page):
1899
1867
  })
1900
1868
 
1901
1869
  return total_score, score_details
1870
+
1871
+ def get_all_steps(self):
1872
+ """Retorna todas as etapas organizadas com seções - COM ORDENAÇÃO"""
1873
+ steps = []
1874
+
1875
+ # DEBUG TEMPORÁRIO
1876
+ print(f"=== GET_ALL_STEPS - PROCESSANDO {len(self.form_steps)} STEPS ===")
1877
+
1878
+ # Criar lista de steps com ordem
1879
+ steps_with_order = []
1880
+ for index, step_block in enumerate(self.form_steps):
1881
+ order = step_block.value.get('order', str(index + 1))
1882
+ print(f"Step {index}: order='{order}'")
1883
+
1884
+ try:
1885
+ order_num = int(order) if order else index + 1
1886
+ except (ValueError, TypeError):
1887
+ order_num = index + 1
1888
+
1889
+ steps_with_order.append((order_num, index, step_block))
1890
+
1891
+ # Ordenar por order_num
1892
+ steps_with_order.sort(key=lambda x: x[0])
1893
+ print(f"Ordem final: {[(x[0], x[1]) for x in steps_with_order]}")
1894
+
1895
+ # Processar steps na ordem correta
1896
+ for position, (order_num, original_index, step_block) in enumerate(steps_with_order):
1897
+ step_data = {
1898
+ 'number': position + 1,
1899
+ 'original_number': original_index + 1,
1900
+ 'order': order_num,
1901
+ 'logo': step_block.value.get('logo'),
1902
+ 'logo_alt': step_block.value.get('logo_alt', ''),
1903
+ 'fields': step_block.value['fields'],
1904
+ 'id': step_block.id,
1905
+ 'sections': []
1906
+ }
1907
+
1908
+ # Organizar campos em seções
1909
+ current_section = None
1910
+ for field_block in step_block.value['fields']:
1911
+ if field_block.block_type == 'section_header':
1912
+ current_section = {
1913
+ 'title': field_block.value['title'],
1914
+ 'subtitle': field_block.value.get('subtitle', ''),
1915
+ 'fields': []
1916
+ }
1917
+ step_data['sections'].append(current_section)
1918
+ else:
1919
+ if current_section is None:
1920
+ current_section = {
1921
+ 'title': '',
1922
+ 'subtitle': '',
1923
+ 'fields': []
1924
+ }
1925
+ step_data['sections'].append(current_section)
1926
+
1927
+ current_section['fields'].append(field_block)
1928
+
1929
+ steps.append(step_data)
1930
+ print(f"Step processado: {position + 1} (ordem {order_num})")
1931
+
1932
+ print(f"=== RETORNANDO {len(steps)} STEPS ===")
1933
+ return steps
1902
1934
  class Meta:
1903
1935
  verbose_name = "Formulário Dinâmico"
1904
1936
  verbose_name_plural = "Formulários Dinâmicos"
@@ -2041,7 +2073,7 @@ class HomePage(Page):
2041
2073
  verbose_name="Botões do Hero",
2042
2074
  use_json_field=True,
2043
2075
  min_num=1,
2044
- max_num=3,
2076
+ max_num=300,
2045
2077
  help_text="Botões principais da seção hero"
2046
2078
  )
2047
2079
 
@@ -2071,7 +2103,7 @@ class HomePage(Page):
2071
2103
  verbose_name="Lista de Funcionalidades",
2072
2104
  use_json_field=True,
2073
2105
  min_num=1,
2074
- max_num=12,
2106
+ max_num=120,
2075
2107
  help_text="Adicione as funcionalidades do sistema"
2076
2108
  )
2077
2109
 
@@ -2094,7 +2126,7 @@ class HomePage(Page):
2094
2126
  verbose_name="Botões do CTA Final",
2095
2127
  use_json_field=True,
2096
2128
  min_num=1,
2097
- max_num=3,
2129
+ max_num=300,
2098
2130
  help_text="Botões da seção final"
2099
2131
  )
2100
2132
 
@@ -5,11 +5,9 @@ from .models import EnapNavbarSnippet
5
5
 
6
6
 
7
7
  def global_template_context(request):
8
- return {
9
- 'debug': settings.DEBUG
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
+ ]