wagtail-enap-designsystem 1.2.1.129__py3-none-any.whl → 1.2.1.130__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.
- enap_designsystem/blocks/__init__.py +6 -0
- enap_designsystem/blocks/form.py +243 -2
- enap_designsystem/blocks/html_blocks.py +316 -6
- enap_designsystem/blocks/semana_inovacao.py +1 -0
- enap_designsystem/migrations/0395_formulariopage_enable_scoring_and_more.py +106 -0
- enap_designsystem/migrations/0396_alter_areaaluno_body_alter_enapcomponentes_body_and_more.py +51263 -0
- enap_designsystem/migrations/0397_alter_areaaluno_body_alter_enapcomponentes_body_and_more.py +51718 -0
- enap_designsystem/migrations/0398_alter_areaaluno_body_alter_enapcomponentes_body_and_more.py +51718 -0
- enap_designsystem/migrations/0399_alter_areaaluno_body_alter_enapcomponentes_body_and_more.py +51718 -0
- enap_designsystem/migrations/0400_alter_areaaluno_body_alter_enapcomponentes_body_and_more.py +51718 -0
- enap_designsystem/migrations/0401_alter_areaaluno_body_alter_cursoeadpage_curso_and_more.py +52692 -0
- enap_designsystem/migrations/0402_alter_areaaluno_body_alter_enapcomponentes_body_and_more.py +52082 -0
- enap_designsystem/migrations/0403_alter_areaaluno_body_alter_enapcomponentes_body_and_more.py +52802 -0
- enap_designsystem/migrations/0404_sistemavotacaopage_conteudo_pagina.py +253 -0
- enap_designsystem/models.py +13 -0
- enap_designsystem/templates/enap_designsystem/blocks/apresentacao_simple_block.html +1 -1
- enap_designsystem/templates/enap_designsystem/blocks/cards_titles.html +309 -0
- enap_designsystem/templates/enap_designsystem/blocks/clientes_block.html +1 -1
- enap_designsystem/templates/enap_designsystem/blocks/cpnu_dashboard_block.html +5 -0
- enap_designsystem/templates/enap_designsystem/blocks/logos_simple_block.html +329 -0
- enap_designsystem/templates/enap_designsystem/blocks/numeros_block.html +195 -0
- enap_designsystem/templates/enap_designsystem/blocks/page/pagenoticias_block.html +6 -0
- enap_designsystem/templates/enap_designsystem/sistema_votacao_page.html +10 -2
- enap_designsystem/views.py +1 -1
- enap_designsystem/wagtail_hooks.py +390 -9
- {wagtail_enap_designsystem-1.2.1.129.dist-info → wagtail_enap_designsystem-1.2.1.130.dist-info}/METADATA +1 -1
- {wagtail_enap_designsystem-1.2.1.129.dist-info → wagtail_enap_designsystem-1.2.1.130.dist-info}/RECORD +30 -17
- {wagtail_enap_designsystem-1.2.1.129.dist-info → wagtail_enap_designsystem-1.2.1.130.dist-info}/WHEEL +0 -0
- {wagtail_enap_designsystem-1.2.1.129.dist-info → wagtail_enap_designsystem-1.2.1.130.dist-info}/licenses/LICENSE +0 -0
- {wagtail_enap_designsystem-1.2.1.129.dist-info → wagtail_enap_designsystem-1.2.1.130.dist-info}/top_level.txt +0 -0
|
@@ -29,6 +29,9 @@ from .html_blocks import (
|
|
|
29
29
|
ApresentacaoBlock,
|
|
30
30
|
ApresentacaoSimpleBlock,
|
|
31
31
|
RecaptchaBlock,
|
|
32
|
+
SecaoApresentacaoCardsBlock,
|
|
33
|
+
LogosSimpleBlock,
|
|
34
|
+
NumerosBlock
|
|
32
35
|
)
|
|
33
36
|
|
|
34
37
|
from .semana_blocks import (
|
|
@@ -358,6 +361,9 @@ class ContentStreamBlock(StreamBlock):
|
|
|
358
361
|
html = HTMLCustomBlock(label="🔧 HTML Customizado")
|
|
359
362
|
apresentcao = ApresentacaoBlock(label="📰 Componente simples com título, quadrado de conteúdo e botão")
|
|
360
363
|
ApresentacaoBlock = ApresentacaoSimpleBlock(label="Componente com título, texto e grid flexível de cards")
|
|
364
|
+
enap_cards_apresentacao = SecaoApresentacaoCardsBlock(label="🎴 Seção com título & cards")
|
|
365
|
+
enap_cards_logs = LogosSimpleBlock(label="🎴 Seção com logos")
|
|
366
|
+
enap_cards_numebrs = NumerosBlock(label="🎴 Seção com numeros")
|
|
361
367
|
|
|
362
368
|
class Meta:
|
|
363
369
|
label = "📰 Conteúdo e Texto"
|
enap_designsystem/blocks/form.py
CHANGED
|
@@ -1001,6 +1001,46 @@ class FormStepBlock(StructBlock):
|
|
|
1001
1001
|
|
|
1002
1002
|
|
|
1003
1003
|
|
|
1004
|
+
class FormFieldScoring(models.Model):
|
|
1005
|
+
"""Armazena pontuação configurada para cada campo"""
|
|
1006
|
+
formulario_page = models.ForeignKey('FormularioPage', on_delete=models.CASCADE, related_name='field_scorings')
|
|
1007
|
+
field_id = models.CharField(max_length=255, verbose_name="ID do Campo")
|
|
1008
|
+
field_label = models.CharField(max_length=500, verbose_name="Pergunta")
|
|
1009
|
+
field_type = models.CharField(max_length=100, verbose_name="Tipo de Campo")
|
|
1010
|
+
scoring_data = models.JSONField(verbose_name="Dados de Pontuação", default=dict)
|
|
1011
|
+
|
|
1012
|
+
class Meta:
|
|
1013
|
+
verbose_name = "Pontuação do Campo"
|
|
1014
|
+
verbose_name_plural = "Pontuações dos Campos"
|
|
1015
|
+
unique_together = ['formulario_page', 'field_id']
|
|
1016
|
+
|
|
1017
|
+
def __str__(self):
|
|
1018
|
+
return f"{self.field_label} ({self.field_type})"
|
|
1019
|
+
|
|
1020
|
+
|
|
1021
|
+
# MODELO para submissões com pontuação
|
|
1022
|
+
class FormularioSubmissionScored(models.Model):
|
|
1023
|
+
"""Submissões com pontuação calculada"""
|
|
1024
|
+
original_submission = models.OneToOneField(
|
|
1025
|
+
'FormularioSubmission',
|
|
1026
|
+
on_delete=models.CASCADE,
|
|
1027
|
+
related_name='scoring'
|
|
1028
|
+
)
|
|
1029
|
+
total_score = models.FloatField(verbose_name="Pontuação Total", default=0)
|
|
1030
|
+
score_details = models.JSONField(verbose_name="Detalhes da Pontuação", default=list)
|
|
1031
|
+
calculated_at = models.DateTimeField(auto_now_add=True)
|
|
1032
|
+
|
|
1033
|
+
class Meta:
|
|
1034
|
+
verbose_name = "Pontuação da Submissão"
|
|
1035
|
+
verbose_name_plural = "Pontuações das Submissões"
|
|
1036
|
+
|
|
1037
|
+
def __str__(self):
|
|
1038
|
+
return f"Pontuação: {self.total_score} pts"
|
|
1039
|
+
|
|
1040
|
+
|
|
1041
|
+
|
|
1042
|
+
|
|
1043
|
+
|
|
1004
1044
|
class FormularioPage(Page):
|
|
1005
1045
|
"""Página de formulário com steps dinâmicos - Wagtail 7.0"""
|
|
1006
1046
|
|
|
@@ -1132,6 +1172,12 @@ class FormularioPage(Page):
|
|
|
1132
1172
|
help_text="Email para receber notificações (ex: admin@enap.gov.br)"
|
|
1133
1173
|
)
|
|
1134
1174
|
|
|
1175
|
+
enable_scoring = models.BooleanField(
|
|
1176
|
+
verbose_name="Ativar Sistema de Pontuação",
|
|
1177
|
+
default=False,
|
|
1178
|
+
help_text="Ativar para poder configurar pontos (invisível para usuários)"
|
|
1179
|
+
)
|
|
1180
|
+
|
|
1135
1181
|
content_panels = Page.content_panels + [
|
|
1136
1182
|
MultiFieldPanel([
|
|
1137
1183
|
FieldPanel('form_title'),
|
|
@@ -1140,8 +1186,11 @@ class FormularioPage(Page):
|
|
|
1140
1186
|
], "🎬 Tela de Boas-vindas"),
|
|
1141
1187
|
|
|
1142
1188
|
FieldPanel('intro'),
|
|
1189
|
+
|
|
1190
|
+
MultiFieldPanel([
|
|
1191
|
+
FieldPanel('enable_scoring'),
|
|
1192
|
+
], "Sistema de Pontuação (Oculto)"),
|
|
1143
1193
|
|
|
1144
|
-
# 🚀 NOVO: StreamField para steps dinâmicos
|
|
1145
1194
|
FieldPanel('form_steps'),
|
|
1146
1195
|
|
|
1147
1196
|
MultiFieldPanel([
|
|
@@ -1653,11 +1702,203 @@ class FormularioPage(Page):
|
|
|
1653
1702
|
}
|
|
1654
1703
|
|
|
1655
1704
|
return conditional_data
|
|
1705
|
+
|
|
1706
|
+
def save_field_scoring(self, field_id, scoring_data):
|
|
1707
|
+
'''Salva pontuação para um campo'''
|
|
1708
|
+
field_info = None
|
|
1709
|
+
|
|
1710
|
+
for field in self.extract_scorable_fields():
|
|
1711
|
+
if field['field_id'] == field_id:
|
|
1712
|
+
field_info = field
|
|
1713
|
+
break
|
|
1714
|
+
|
|
1715
|
+
if not field_info:
|
|
1716
|
+
return False
|
|
1717
|
+
|
|
1718
|
+
scoring, created = FormFieldScoring.objects.get_or_create(
|
|
1719
|
+
formulario_page=self,
|
|
1720
|
+
field_id=field_id,
|
|
1721
|
+
defaults={
|
|
1722
|
+
'field_label': field_info['field_label'],
|
|
1723
|
+
'field_type': field_info['field_type'],
|
|
1724
|
+
'scoring_data': scoring_data
|
|
1725
|
+
}
|
|
1726
|
+
)
|
|
1727
|
+
|
|
1728
|
+
if not created:
|
|
1729
|
+
scoring.scoring_data = scoring_data
|
|
1730
|
+
scoring.save()
|
|
1731
|
+
|
|
1732
|
+
return True
|
|
1733
|
+
|
|
1734
|
+
def calculate_submission_score(self, submission):
|
|
1735
|
+
'''Calcula pontuação para uma submissão'''
|
|
1736
|
+
if not self.enable_scoring:
|
|
1737
|
+
return 0, []
|
|
1738
|
+
|
|
1739
|
+
total_score = 0
|
|
1740
|
+
score_details = []
|
|
1741
|
+
form_data = submission.form_data
|
|
1742
|
+
|
|
1743
|
+
field_scorings = FormFieldScoring.objects.filter(formulario_page=self)
|
|
1744
|
+
|
|
1745
|
+
for scoring in field_scorings:
|
|
1746
|
+
field_id = scoring.field_id
|
|
1747
|
+
user_response = form_data.get(field_id)
|
|
1748
|
+
|
|
1749
|
+
if not user_response:
|
|
1750
|
+
continue
|
|
1751
|
+
|
|
1752
|
+
field_score = 0
|
|
1753
|
+
|
|
1754
|
+
if scoring.field_type in ['dropdown_field', 'radio_field']:
|
|
1755
|
+
option_scores = scoring.scoring_data.get('option_scores', {})
|
|
1756
|
+
field_score = option_scores.get(user_response, 0)
|
|
1757
|
+
|
|
1758
|
+
elif scoring.field_type == 'checkbox_multiple_field':
|
|
1759
|
+
if isinstance(user_response, list):
|
|
1760
|
+
option_scores = scoring.scoring_data.get('option_scores', {})
|
|
1761
|
+
calculation_method = scoring.scoring_data.get('calculation_method', 'sum')
|
|
1762
|
+
|
|
1763
|
+
scores = [option_scores.get(option, 0) for option in user_response]
|
|
1764
|
+
|
|
1765
|
+
if calculation_method == 'sum':
|
|
1766
|
+
field_score = sum(scores)
|
|
1767
|
+
elif calculation_method == 'max':
|
|
1768
|
+
field_score = max(scores) if scores else 0
|
|
1769
|
+
elif calculation_method == 'average':
|
|
1770
|
+
field_score = sum(scores) / len(scores) if scores else 0
|
|
1771
|
+
|
|
1772
|
+
elif scoring.field_type == 'rating_field':
|
|
1773
|
+
try:
|
|
1774
|
+
rating_value = float(user_response)
|
|
1775
|
+
multiplier = scoring.scoring_data.get('multiplier', 1.0)
|
|
1776
|
+
field_score = rating_value * multiplier
|
|
1777
|
+
except (ValueError, TypeError):
|
|
1778
|
+
field_score = 0
|
|
1779
|
+
|
|
1780
|
+
total_score += field_score
|
|
1781
|
+
|
|
1782
|
+
score_details.append({
|
|
1783
|
+
'field_label': scoring.field_label,
|
|
1784
|
+
'user_response': user_response,
|
|
1785
|
+
'field_score': field_score
|
|
1786
|
+
})
|
|
1787
|
+
|
|
1788
|
+
return total_score, score_details
|
|
1789
|
+
|
|
1790
|
+
def get_scoring_url(self):
|
|
1791
|
+
'''URL para configurar pontuação'''
|
|
1792
|
+
return reverse('formulario_scoring', args=[self.pk])
|
|
1793
|
+
|
|
1794
|
+
def get_results_url(self):
|
|
1795
|
+
'''URL para ver resultados'''
|
|
1796
|
+
return reverse('formulario_results', args=[self.pk])
|
|
1656
1797
|
|
|
1657
|
-
|
|
1798
|
+
def extract_scorable_fields(self):
|
|
1799
|
+
scorable_fields = []
|
|
1658
1800
|
|
|
1801
|
+
for step_index, step_block in enumerate(self.form_steps):
|
|
1802
|
+
step_number = step_index + 1
|
|
1803
|
+
|
|
1804
|
+
for block in step_block.value['fields']:
|
|
1805
|
+
field_id = f"{block.block_type}_{block.id}"
|
|
1806
|
+
|
|
1807
|
+
# Apenas campos que fazem sentido pontuar
|
|
1808
|
+
if block.block_type in ['dropdown_field', 'radio_field', 'checkbox_multiple_field', 'rating_field']:
|
|
1809
|
+
field_data = {
|
|
1810
|
+
'field_id': field_id,
|
|
1811
|
+
'field_label': block.value.get('label', 'Campo sem título'),
|
|
1812
|
+
'field_type': block.block_type,
|
|
1813
|
+
'step_number': step_number,
|
|
1814
|
+
'options': block.value.get('options', []),
|
|
1815
|
+
'block_data': block.value
|
|
1816
|
+
}
|
|
1817
|
+
scorable_fields.append(field_data)
|
|
1818
|
+
|
|
1819
|
+
return scorable_fields
|
|
1659
1820
|
|
|
1821
|
+
def save_field_scoring(self, field_id, scoring_data):
|
|
1822
|
+
field_info = None
|
|
1823
|
+
|
|
1824
|
+
for field in self.extract_scorable_fields():
|
|
1825
|
+
if field['field_id'] == field_id:
|
|
1826
|
+
field_info = field
|
|
1827
|
+
break
|
|
1828
|
+
|
|
1829
|
+
if not field_info:
|
|
1830
|
+
return False
|
|
1831
|
+
|
|
1832
|
+
scoring, created = FormFieldScoring.objects.get_or_create(
|
|
1833
|
+
formulario_page=self,
|
|
1834
|
+
field_id=field_id,
|
|
1835
|
+
defaults={
|
|
1836
|
+
'field_label': field_info['field_label'],
|
|
1837
|
+
'field_type': field_info['field_type'],
|
|
1838
|
+
'scoring_data': scoring_data
|
|
1839
|
+
}
|
|
1840
|
+
)
|
|
1841
|
+
|
|
1842
|
+
if not created:
|
|
1843
|
+
scoring.scoring_data = scoring_data
|
|
1844
|
+
scoring.save()
|
|
1845
|
+
|
|
1846
|
+
return True
|
|
1660
1847
|
|
|
1848
|
+
def calculate_submission_score(self, submission):
|
|
1849
|
+
if not self.enable_scoring:
|
|
1850
|
+
return 0, []
|
|
1851
|
+
|
|
1852
|
+
total_score = 0
|
|
1853
|
+
score_details = []
|
|
1854
|
+
form_data = submission.form_data
|
|
1855
|
+
|
|
1856
|
+
field_scorings = FormFieldScoring.objects.filter(formulario_page=self)
|
|
1857
|
+
|
|
1858
|
+
for scoring in field_scorings:
|
|
1859
|
+
field_id = scoring.field_id
|
|
1860
|
+
user_response = form_data.get(field_id)
|
|
1861
|
+
|
|
1862
|
+
if not user_response:
|
|
1863
|
+
continue
|
|
1864
|
+
|
|
1865
|
+
field_score = 0
|
|
1866
|
+
|
|
1867
|
+
if scoring.field_type in ['dropdown_field', 'radio_field']:
|
|
1868
|
+
option_scores = scoring.scoring_data.get('option_scores', {})
|
|
1869
|
+
field_score = option_scores.get(user_response, 0)
|
|
1870
|
+
|
|
1871
|
+
elif scoring.field_type == 'checkbox_multiple_field':
|
|
1872
|
+
if isinstance(user_response, list):
|
|
1873
|
+
option_scores = scoring.scoring_data.get('option_scores', {})
|
|
1874
|
+
calculation_method = scoring.scoring_data.get('calculation_method', 'sum')
|
|
1875
|
+
|
|
1876
|
+
scores = [option_scores.get(option, 0) for option in user_response]
|
|
1877
|
+
|
|
1878
|
+
if calculation_method == 'sum':
|
|
1879
|
+
field_score = sum(scores)
|
|
1880
|
+
elif calculation_method == 'max':
|
|
1881
|
+
field_score = max(scores) if scores else 0
|
|
1882
|
+
elif calculation_method == 'average':
|
|
1883
|
+
field_score = sum(scores) / len(scores) if scores else 0
|
|
1884
|
+
|
|
1885
|
+
elif scoring.field_type == 'rating_field':
|
|
1886
|
+
try:
|
|
1887
|
+
rating_value = float(user_response)
|
|
1888
|
+
multiplier = scoring.scoring_data.get('multiplier', 1.0)
|
|
1889
|
+
field_score = rating_value * multiplier
|
|
1890
|
+
except (ValueError, TypeError):
|
|
1891
|
+
field_score = 0
|
|
1892
|
+
|
|
1893
|
+
total_score += field_score
|
|
1894
|
+
|
|
1895
|
+
score_details.append({
|
|
1896
|
+
'field_label': scoring.field_label,
|
|
1897
|
+
'user_response': user_response,
|
|
1898
|
+
'field_score': field_score
|
|
1899
|
+
})
|
|
1900
|
+
|
|
1901
|
+
return total_score, score_details
|
|
1661
1902
|
class Meta:
|
|
1662
1903
|
verbose_name = "Formulário Dinâmico"
|
|
1663
1904
|
verbose_name_plural = "Formulários Dinâmicos"
|
|
@@ -7582,25 +7582,86 @@ class ApresentacaoSimpleBlock(blocks.StructBlock):
|
|
|
7582
7582
|
help_text="Quantos cards por linha",
|
|
7583
7583
|
label="Cards por linha"
|
|
7584
7584
|
)
|
|
7585
|
-
|
|
7586
|
-
#
|
|
7585
|
+
|
|
7586
|
+
# Lista de cards
|
|
7587
7587
|
cards = blocks.StreamBlock([
|
|
7588
|
-
('
|
|
7588
|
+
('card_apresentacao', ApresentacaoCardBlock()),
|
|
7589
7589
|
],
|
|
7590
7590
|
required=False,
|
|
7591
|
-
help_text="
|
|
7591
|
+
help_text="Cards da seção de apresentação",
|
|
7592
|
+
label="Cards"
|
|
7592
7593
|
)
|
|
7593
7594
|
|
|
7594
7595
|
class Meta:
|
|
7595
7596
|
template = 'enap_designsystem/blocks/apresentacao_simple_block.html'
|
|
7596
7597
|
icon = 'doc-full'
|
|
7597
|
-
label = '
|
|
7598
|
+
label = 'Componente com título, texto e grid flexível de cards'
|
|
7598
7599
|
help_text = 'Componente com título, texto e grid flexível de cards'
|
|
7599
7600
|
|
|
7600
7601
|
|
|
7601
7602
|
|
|
7602
7603
|
|
|
7603
7604
|
|
|
7605
|
+
class SecaoApresentacaoCardsBlock(blocks.StructBlock):
|
|
7606
|
+
"""
|
|
7607
|
+
Seção de apresentação com título, conteúdo e grid de cards
|
|
7608
|
+
Componente do Design System ENAP
|
|
7609
|
+
"""
|
|
7610
|
+
|
|
7611
|
+
background_image_fundo_bg = StreamField(
|
|
7612
|
+
[('background_image_stream', ImageChooserBlock(
|
|
7613
|
+
label="Imagem de Fundo",
|
|
7614
|
+
help_text="Selecione uma imagem de fundo para o formulário"
|
|
7615
|
+
))],
|
|
7616
|
+
verbose_name="Imagem de Fundo",
|
|
7617
|
+
use_json_field=True,
|
|
7618
|
+
max_num=1,
|
|
7619
|
+
blank=True,
|
|
7620
|
+
help_text="Adicione uma imagem de fundo para o formulário"
|
|
7621
|
+
)
|
|
7622
|
+
|
|
7623
|
+
# Título
|
|
7624
|
+
titulo = blocks.CharBlock(
|
|
7625
|
+
required=True,
|
|
7626
|
+
max_length=200,
|
|
7627
|
+
help_text="Título da seção"
|
|
7628
|
+
)
|
|
7629
|
+
|
|
7630
|
+
cor_titulo = blocks.ChoiceBlock(
|
|
7631
|
+
choices=ENAP_GREEN_COLORS + [('#FFFFFF', 'Branco (#FFFFFF)')],
|
|
7632
|
+
required=False,
|
|
7633
|
+
default='#FFFFFF',
|
|
7634
|
+
help_text="Cor do título"
|
|
7635
|
+
)
|
|
7636
|
+
|
|
7637
|
+
# Layout dos cards
|
|
7638
|
+
layout_cards = blocks.ChoiceBlock(
|
|
7639
|
+
choices=[
|
|
7640
|
+
('cards-1-coluna', '1 card por linha'),
|
|
7641
|
+
('cards-2-colunas', 'Até 2 cards por linha'),
|
|
7642
|
+
('cards-3-colunas', 'Até 3 cards por linha'),
|
|
7643
|
+
('cards-4-colunas', 'Até 4 cards por linha'),
|
|
7644
|
+
('cards-5-colunas', 'Até 5 cards por linha')
|
|
7645
|
+
],
|
|
7646
|
+
default='cards-5-colunas',
|
|
7647
|
+
help_text="Layout da grade de cards",
|
|
7648
|
+
label="Layout dos cards"
|
|
7649
|
+
)
|
|
7650
|
+
|
|
7651
|
+
# Stream de cards
|
|
7652
|
+
cards = blocks.StreamBlock([
|
|
7653
|
+
('card', CardBlock()),
|
|
7654
|
+
],
|
|
7655
|
+
required=False,
|
|
7656
|
+
help_text="Adicione quantos cards precisar"
|
|
7657
|
+
)
|
|
7658
|
+
|
|
7659
|
+
class Meta:
|
|
7660
|
+
template = 'enap_designsystem/blocks/cards_titles.html'
|
|
7661
|
+
icon = 'doc-full'
|
|
7662
|
+
label = 'Seção com título & cards'
|
|
7663
|
+
help_text = 'Seção com título & cards'
|
|
7664
|
+
|
|
7604
7665
|
|
|
7605
7666
|
class RecaptchaBlock(StructBlock):
|
|
7606
7667
|
"""Componente reCAPTCHA isolado para usar em qualquer formulário"""
|
|
@@ -7656,4 +7717,253 @@ class RecaptchaBlock(StructBlock):
|
|
|
7656
7717
|
template = 'enap_designsystem/blocks/recaptcha.html'
|
|
7657
7718
|
icon = 'lock'
|
|
7658
7719
|
label = 'reCAPTCHA'
|
|
7659
|
-
help_text = 'Componente de verificação reCAPTCHA'
|
|
7720
|
+
help_text = 'Componente de verificação reCAPTCHA'
|
|
7721
|
+
|
|
7722
|
+
|
|
7723
|
+
|
|
7724
|
+
|
|
7725
|
+
|
|
7726
|
+
|
|
7727
|
+
|
|
7728
|
+
|
|
7729
|
+
class LogoCardBlock(blocks.StructBlock):
|
|
7730
|
+
"""
|
|
7731
|
+
Bloco individual para cada logo/card
|
|
7732
|
+
"""
|
|
7733
|
+
logo = ImageChooserBlock(
|
|
7734
|
+
required=True,
|
|
7735
|
+
help_text="Logo ou imagem do card"
|
|
7736
|
+
)
|
|
7737
|
+
|
|
7738
|
+
class Meta:
|
|
7739
|
+
icon = 'image'
|
|
7740
|
+
label = 'Logo Card'
|
|
7741
|
+
|
|
7742
|
+
|
|
7743
|
+
class LogosSimpleBlock(blocks.StructBlock):
|
|
7744
|
+
"""
|
|
7745
|
+
Componente de apresentação com título, texto e grid de logos/cards
|
|
7746
|
+
"""
|
|
7747
|
+
|
|
7748
|
+
# Background
|
|
7749
|
+
cor_fundo = blocks.ChoiceBlock(
|
|
7750
|
+
choices=BACKGROUND_COLOR_CHOICES,
|
|
7751
|
+
required=False,
|
|
7752
|
+
default='#6A1B9A', # Roxo como na imagem
|
|
7753
|
+
help_text="Cor de fundo do componente"
|
|
7754
|
+
)
|
|
7755
|
+
|
|
7756
|
+
# Título
|
|
7757
|
+
titulo = blocks.CharBlock(
|
|
7758
|
+
required=True,
|
|
7759
|
+
max_length=200,
|
|
7760
|
+
help_text="Título principal da seção"
|
|
7761
|
+
)
|
|
7762
|
+
|
|
7763
|
+
cor_titulo = blocks.ChoiceBlock(
|
|
7764
|
+
choices=ENAP_GREEN_COLORS + [('#FFFFFF', 'Branco (#FFFFFF)')],
|
|
7765
|
+
required=False,
|
|
7766
|
+
default='#FFFFFF',
|
|
7767
|
+
help_text="Cor do título"
|
|
7768
|
+
)
|
|
7769
|
+
|
|
7770
|
+
# Quadrado de conteúdo
|
|
7771
|
+
cor_fundo_conteudo = blocks.ChoiceBlock(
|
|
7772
|
+
choices=BACKGROUND_COLOR_CHOICES,
|
|
7773
|
+
required=False,
|
|
7774
|
+
default='#FFFFFF',
|
|
7775
|
+
help_text="Cor de fundo do quadrado de conteúdo"
|
|
7776
|
+
)
|
|
7777
|
+
|
|
7778
|
+
# Grid de logos/cards
|
|
7779
|
+
tipo_grid_logos = blocks.ChoiceBlock(
|
|
7780
|
+
choices=[
|
|
7781
|
+
('logos-grid-1', '1 logo por linha'),
|
|
7782
|
+
('logos-grid-2', 'Até 2 logos por linha'),
|
|
7783
|
+
('logos-grid-3', 'Até 3 logos por linha'),
|
|
7784
|
+
('logos-grid-4', 'Até 4 logos por linha'),
|
|
7785
|
+
('logos-grid-5', 'Até 5 logos por linha'),
|
|
7786
|
+
('logos-grid-6', 'Até 6 logos por linha')
|
|
7787
|
+
],
|
|
7788
|
+
default='logos-grid-5',
|
|
7789
|
+
help_text="Quantas logos por linha no desktop",
|
|
7790
|
+
label="Layout do grid de logos"
|
|
7791
|
+
)
|
|
7792
|
+
|
|
7793
|
+
# Lista de logos/cards
|
|
7794
|
+
lista_logos = blocks.ListBlock(
|
|
7795
|
+
LogoCardBlock(),
|
|
7796
|
+
min_num=1,
|
|
7797
|
+
max_num=30,
|
|
7798
|
+
help_text="Adicione as logos/cards que serão exibidas no grid"
|
|
7799
|
+
)
|
|
7800
|
+
|
|
7801
|
+
# Configurações adicionais do grid
|
|
7802
|
+
espacamento_logos = blocks.ChoiceBlock(
|
|
7803
|
+
choices=[
|
|
7804
|
+
('spacing-sm', 'Espaçamento pequeno'),
|
|
7805
|
+
('spacing-md', 'Espaçamento médio'),
|
|
7806
|
+
('spacing-lg', 'Espaçamento grande'),
|
|
7807
|
+
],
|
|
7808
|
+
default='spacing-md',
|
|
7809
|
+
help_text="Espaçamento entre as logos"
|
|
7810
|
+
)
|
|
7811
|
+
|
|
7812
|
+
tamanho_logos = blocks.ChoiceBlock(
|
|
7813
|
+
choices=[
|
|
7814
|
+
('logo-sm', 'Logos pequenas'),
|
|
7815
|
+
('logo-md', 'Logos médias'),
|
|
7816
|
+
('logo-lg', 'Logos grandes'),
|
|
7817
|
+
],
|
|
7818
|
+
default='logo-md',
|
|
7819
|
+
help_text="Tamanho das logos no grid"
|
|
7820
|
+
)
|
|
7821
|
+
|
|
7822
|
+
centralizar_logos = blocks.BooleanBlock(
|
|
7823
|
+
required=False,
|
|
7824
|
+
default=True,
|
|
7825
|
+
help_text="Centralizar logos dentro dos cards"
|
|
7826
|
+
)
|
|
7827
|
+
|
|
7828
|
+
class Meta:
|
|
7829
|
+
template = 'enap_designsystem/blocks/logos_simple_block.html'
|
|
7830
|
+
icon = 'doc-full'
|
|
7831
|
+
label = 'Apresentação com Grid de Logos'
|
|
7832
|
+
help_text = 'Componente com título & logos'
|
|
7833
|
+
|
|
7834
|
+
|
|
7835
|
+
|
|
7836
|
+
|
|
7837
|
+
|
|
7838
|
+
|
|
7839
|
+
class NumeroCardBlock(blocks.StructBlock):
|
|
7840
|
+
"""
|
|
7841
|
+
Bloco individual para cada card de número/estatística
|
|
7842
|
+
"""
|
|
7843
|
+
numero = blocks.CharBlock(
|
|
7844
|
+
required=True,
|
|
7845
|
+
max_length=50,
|
|
7846
|
+
help_text="Número ou estatística (ex: 29, +4960, 10)"
|
|
7847
|
+
)
|
|
7848
|
+
|
|
7849
|
+
descricao = blocks.CharBlock(
|
|
7850
|
+
required=True,
|
|
7851
|
+
max_length=200,
|
|
7852
|
+
help_text="Descrição do número (ex: Parceiros Impactados)"
|
|
7853
|
+
)
|
|
7854
|
+
|
|
7855
|
+
cor_card = blocks.ChoiceBlock(
|
|
7856
|
+
choices=BACKGROUND_COLOR_CHOICES,
|
|
7857
|
+
required=False,
|
|
7858
|
+
default='#6A1B9A', # Roxo padrão
|
|
7859
|
+
help_text="Cor de fundo do card"
|
|
7860
|
+
)
|
|
7861
|
+
|
|
7862
|
+
cor_numero = blocks.ChoiceBlock(
|
|
7863
|
+
choices=ENAP_GREEN_COLORS + [('#FFFFFF', 'Branco (#FFFFFF)')],
|
|
7864
|
+
required=False,
|
|
7865
|
+
default='#FFFFFF',
|
|
7866
|
+
help_text="Cor do número"
|
|
7867
|
+
)
|
|
7868
|
+
|
|
7869
|
+
cor_descricao = blocks.ChoiceBlock(
|
|
7870
|
+
choices=ENAP_GREEN_COLORS + [('#FFFFFF', 'Branco (#FFFFFF)')],
|
|
7871
|
+
required=False,
|
|
7872
|
+
default='#FFFFFF',
|
|
7873
|
+
help_text="Cor da descrição"
|
|
7874
|
+
)
|
|
7875
|
+
|
|
7876
|
+
class Meta:
|
|
7877
|
+
icon = 'snippet'
|
|
7878
|
+
label = 'Card de Número'
|
|
7879
|
+
|
|
7880
|
+
|
|
7881
|
+
class NumerosBlock(blocks.StructBlock):
|
|
7882
|
+
"""
|
|
7883
|
+
Componente de apresentação de números/estatísticas
|
|
7884
|
+
"""
|
|
7885
|
+
|
|
7886
|
+
# Background
|
|
7887
|
+
cor_fundo = blocks.ChoiceBlock(
|
|
7888
|
+
choices=BACKGROUND_COLOR_CHOICES,
|
|
7889
|
+
required=False,
|
|
7890
|
+
default='#F8F9FA', # Cinza claro ENAP
|
|
7891
|
+
help_text="Cor de fundo do componente"
|
|
7892
|
+
)
|
|
7893
|
+
|
|
7894
|
+
# Título
|
|
7895
|
+
titulo = blocks.CharBlock(
|
|
7896
|
+
required=True,
|
|
7897
|
+
max_length=200,
|
|
7898
|
+
help_text="Título principal da seção (ex: Nossos números)"
|
|
7899
|
+
)
|
|
7900
|
+
|
|
7901
|
+
cor_titulo = blocks.ChoiceBlock(
|
|
7902
|
+
choices=ENAP_GREEN_COLORS,
|
|
7903
|
+
required=False,
|
|
7904
|
+
default='#024248',
|
|
7905
|
+
help_text="Cor do título"
|
|
7906
|
+
)
|
|
7907
|
+
|
|
7908
|
+
# Quadrado de conteúdo
|
|
7909
|
+
cor_fundo_conteudo = blocks.ChoiceBlock(
|
|
7910
|
+
choices=BACKGROUND_COLOR_CHOICES,
|
|
7911
|
+
required=False,
|
|
7912
|
+
default='#FFFFFF',
|
|
7913
|
+
help_text="Cor de fundo do quadrado de conteúdo"
|
|
7914
|
+
)
|
|
7915
|
+
|
|
7916
|
+
# Grid de cards
|
|
7917
|
+
tipo_grid_numeros = blocks.ChoiceBlock(
|
|
7918
|
+
choices=[
|
|
7919
|
+
('numeros-grid-1', '1 card por linha'),
|
|
7920
|
+
('numeros-grid-2', 'Até 2 cards por linha'),
|
|
7921
|
+
('numeros-grid-3', 'Até 3 cards por linha'),
|
|
7922
|
+
('numeros-grid-4', 'Até 4 cards por linha'),
|
|
7923
|
+
('numeros-grid-5', 'Até 5 cards por linha'),
|
|
7924
|
+
],
|
|
7925
|
+
default='numeros-grid-4',
|
|
7926
|
+
help_text="Quantos cards por linha no desktop",
|
|
7927
|
+
label="Layout do grid de números"
|
|
7928
|
+
)
|
|
7929
|
+
|
|
7930
|
+
# Lista de cards de números
|
|
7931
|
+
lista_numeros = blocks.ListBlock(
|
|
7932
|
+
NumeroCardBlock(),
|
|
7933
|
+
min_num=1,
|
|
7934
|
+
max_num=20,
|
|
7935
|
+
help_text="Adicione os cards de números/estatísticas"
|
|
7936
|
+
)
|
|
7937
|
+
|
|
7938
|
+
# Configurações adicionais do grid
|
|
7939
|
+
espacamento_cards = blocks.ChoiceBlock(
|
|
7940
|
+
choices=[
|
|
7941
|
+
('spacing-sm', 'Espaçamento pequeno'),
|
|
7942
|
+
('spacing-md', 'Espaçamento médio'),
|
|
7943
|
+
('spacing-lg', 'Espaçamento grande'),
|
|
7944
|
+
],
|
|
7945
|
+
default='spacing-md',
|
|
7946
|
+
help_text="Espaçamento entre os cards"
|
|
7947
|
+
)
|
|
7948
|
+
|
|
7949
|
+
tamanho_cards = blocks.ChoiceBlock(
|
|
7950
|
+
choices=[
|
|
7951
|
+
('card-sm', 'Cards pequenos'),
|
|
7952
|
+
('card-md', 'Cards médios'),
|
|
7953
|
+
('card-lg', 'Cards grandes'),
|
|
7954
|
+
],
|
|
7955
|
+
default='card-md',
|
|
7956
|
+
help_text="Tamanho dos cards"
|
|
7957
|
+
)
|
|
7958
|
+
|
|
7959
|
+
bordas_arredondadas = blocks.BooleanBlock(
|
|
7960
|
+
required=False,
|
|
7961
|
+
default=True,
|
|
7962
|
+
help_text="Cards com bordas arredondadas"
|
|
7963
|
+
)
|
|
7964
|
+
|
|
7965
|
+
class Meta:
|
|
7966
|
+
template = 'enap_designsystem/blocks/numeros_block.html'
|
|
7967
|
+
icon = 'snippet'
|
|
7968
|
+
label = 'Grid de Números/Estatísticas'
|
|
7969
|
+
help_text = 'Componente para exibir números e estatísticas importantes'
|
|
@@ -1066,6 +1066,7 @@ class EditalConcursoInovacao(Page):
|
|
|
1066
1066
|
'enap_designsystem.SejaAvaliador',
|
|
1067
1067
|
'enap_designsystem.ENAPComponentes',
|
|
1068
1068
|
'enap_designsystem.ENAPSemana',
|
|
1069
|
+
'enap_designsystem.SistemaVotacaoPage',
|
|
1069
1070
|
]
|
|
1070
1071
|
|
|
1071
1072
|
def get_context(self, request, *args, **kwargs):
|