wagtail-enap-designsystem 1.2.1.103__py3-none-any.whl → 1.2.1.105__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/blocks/html_blocks.py +582 -19
- enap_designsystem/migrations/0367_alter_areaaluno_body_alter_cursoeadpage_curso_and_more.py +52658 -0
- enap_designsystem/migrations/0368_enaprevista.py +616 -0
- enap_designsystem/migrations/0369_alter_enaprevista_body.py +577 -0
- enap_designsystem/migrations/0370_alter_articlepage_body_alter_enapnoticia_body_and_more.py +1781 -0
- enap_designsystem/migrations/0371_alter_enaprevista_body.py +639 -0
- enap_designsystem/migrations/0372_enaprevista_background_color_and_more.py +98 -0
- enap_designsystem/migrations/0373_alter_jobvacancypage_options_and_more.py +415 -0
- enap_designsystem/migrations/0374_pagetypepermission.py +36 -0
- enap_designsystem/migrations/0375_grouppagepermission_delete_pagetypepermission.py +55 -0
- enap_designsystem/migrations/0376_grouppagetypepermission_delete_grouppagepermission.py +55 -0
- enap_designsystem/migrations/0377_alter_grouppagetypepermission_options_and_more.py +54 -0
- enap_designsystem/models.py +136 -2
- enap_designsystem/static/enap_designsystem/blocks/article_grid_conditional.js +108 -0
- enap_designsystem/static/enap_designsystem/pages/article/joomla/enap_noticia_importada.css +3 -3
- enap_designsystem/templates/enap_designsystem/blocks/article_grid_block.html +202 -0
- enap_designsystem/templates/enap_designsystem/blocks/image_text_block.html +260 -0
- enap_designsystem/templates/enap_designsystem/blocks/suap/apisuap_courses_block.html +8 -8
- enap_designsystem/templates/enap_designsystem/pages/article/enap_revista.html +264 -0
- enap_designsystem/templates/enap_designsystem/pages/template_mba.html +10 -0
- enap_designsystem/views.py +6 -0
- enap_designsystem/wagtail_hooks.py +89 -1
- {wagtail_enap_designsystem-1.2.1.103.dist-info → wagtail_enap_designsystem-1.2.1.105.dist-info}/METADATA +1 -1
- {wagtail_enap_designsystem-1.2.1.103.dist-info → wagtail_enap_designsystem-1.2.1.105.dist-info}/RECORD +27 -12
- {wagtail_enap_designsystem-1.2.1.103.dist-info → wagtail_enap_designsystem-1.2.1.105.dist-info}/WHEEL +0 -0
- {wagtail_enap_designsystem-1.2.1.103.dist-info → wagtail_enap_designsystem-1.2.1.105.dist-info}/licenses/LICENSE +0 -0
- {wagtail_enap_designsystem-1.2.1.103.dist-info → wagtail_enap_designsystem-1.2.1.105.dist-info}/top_level.txt +0 -0
|
@@ -736,13 +736,13 @@ class APISuapCourseBlock(StructBlock):
|
|
|
736
736
|
processed_data = []
|
|
737
737
|
for item in data:
|
|
738
738
|
# Converter data_inicio de string para datetime se existir
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
739
|
+
try:
|
|
740
|
+
# Assumindo formato YYYY-MM-DD
|
|
741
|
+
item['data_inicio'] = datetime.strptime(item['data_inicio'], '%Y-%m-%d').date()
|
|
742
|
+
item['data_inicio_aula'] = datetime.strptime(item['data_inicio_aula'], '%Y-%m-%d').date()
|
|
743
|
+
except (ValueError, TypeError):
|
|
744
|
+
# Se não conseguir converter, mantém como string
|
|
745
|
+
pass
|
|
746
746
|
|
|
747
747
|
processed_data.append(SimpleNamespace(**item))
|
|
748
748
|
|
|
@@ -1371,6 +1371,152 @@ class VideoBlock(blocks.StructBlock):
|
|
|
1371
1371
|
icon = 'media'
|
|
1372
1372
|
label = 'Embed Vídeo'
|
|
1373
1373
|
|
|
1374
|
+
|
|
1375
|
+
|
|
1376
|
+
class ImageTextBlockChoices(blocks.StructBlock):
|
|
1377
|
+
"""
|
|
1378
|
+
Componente flexível de imagem com texto
|
|
1379
|
+
Permite escolher diferentes proporções de layout
|
|
1380
|
+
"""
|
|
1381
|
+
|
|
1382
|
+
# Opções de proporção
|
|
1383
|
+
LAYOUT_CHOICES = [
|
|
1384
|
+
('50-50', 'Imagem 50% - Texto 50%'),
|
|
1385
|
+
('30-70', 'Imagem 30% - Texto 70%'),
|
|
1386
|
+
('70-30', 'Imagem 70% - Texto 30%'),
|
|
1387
|
+
('40-60', 'Imagem 40% - Texto 60%'),
|
|
1388
|
+
('60-40', 'Imagem 60% - Texto 40%'),
|
|
1389
|
+
]
|
|
1390
|
+
|
|
1391
|
+
# Posicionamento da imagem
|
|
1392
|
+
POSITION_CHOICES = [
|
|
1393
|
+
('left', 'Imagem à esquerda'),
|
|
1394
|
+
('right', 'Imagem à direita'),
|
|
1395
|
+
]
|
|
1396
|
+
|
|
1397
|
+
# Configuração do layout
|
|
1398
|
+
layout_proportion = blocks.ChoiceBlock(
|
|
1399
|
+
choices=LAYOUT_CHOICES,
|
|
1400
|
+
default='50-50',
|
|
1401
|
+
label='Proporção do Layout',
|
|
1402
|
+
help_text='Escolha a proporção entre imagem e texto'
|
|
1403
|
+
)
|
|
1404
|
+
|
|
1405
|
+
image_position = blocks.ChoiceBlock(
|
|
1406
|
+
choices=POSITION_CHOICES,
|
|
1407
|
+
default='left',
|
|
1408
|
+
label='Posição da Imagem',
|
|
1409
|
+
help_text='Escolha se a imagem fica à esquerda ou direita do texto'
|
|
1410
|
+
)
|
|
1411
|
+
|
|
1412
|
+
# Conteúdo
|
|
1413
|
+
image = ImageChooserBlock(
|
|
1414
|
+
label='Imagem',
|
|
1415
|
+
help_text='Selecione a imagem a ser exibida'
|
|
1416
|
+
)
|
|
1417
|
+
|
|
1418
|
+
image_alt = blocks.CharBlock(
|
|
1419
|
+
label='Texto alternativo da imagem',
|
|
1420
|
+
help_text='Descrição da imagem para acessibilidade',
|
|
1421
|
+
required=False
|
|
1422
|
+
)
|
|
1423
|
+
|
|
1424
|
+
title = blocks.CharBlock(
|
|
1425
|
+
label='Título',
|
|
1426
|
+
required=False,
|
|
1427
|
+
help_text='Título opcional acima do texto'
|
|
1428
|
+
)
|
|
1429
|
+
|
|
1430
|
+
text = blocks.RichTextBlock(
|
|
1431
|
+
label='Texto',
|
|
1432
|
+
help_text='Conteúdo de texto ao lado da imagem',
|
|
1433
|
+
features=['bold', 'italic', 'link', 'ol', 'ul', 'h2', 'h3', 'h4']
|
|
1434
|
+
)
|
|
1435
|
+
|
|
1436
|
+
# Configurações visuais opcionais
|
|
1437
|
+
background_color = blocks.ChoiceBlock(
|
|
1438
|
+
choices=[
|
|
1439
|
+
('', 'Padrão (sem cor)'),
|
|
1440
|
+
('bg-light', 'Fundo claro'),
|
|
1441
|
+
('bg-secondary', 'Fundo secundário'),
|
|
1442
|
+
('bg-primary-light', 'Fundo primário claro'),
|
|
1443
|
+
],
|
|
1444
|
+
default='',
|
|
1445
|
+
required=False,
|
|
1446
|
+
label='Cor de fundo',
|
|
1447
|
+
help_text='Cor de fundo opcional para o componente'
|
|
1448
|
+
)
|
|
1449
|
+
|
|
1450
|
+
add_container = blocks.BooleanBlock(
|
|
1451
|
+
default=True,
|
|
1452
|
+
required=False,
|
|
1453
|
+
label='Adicionar container',
|
|
1454
|
+
help_text='Adiciona margens laterais responsivas'
|
|
1455
|
+
)
|
|
1456
|
+
|
|
1457
|
+
vertical_spacing = blocks.ChoiceBlock(
|
|
1458
|
+
choices=[
|
|
1459
|
+
('py-3', 'Pequeno'),
|
|
1460
|
+
('py-4', 'Médio'),
|
|
1461
|
+
('py-5', 'Grande'),
|
|
1462
|
+
('py-6', 'Extra Grande'),
|
|
1463
|
+
],
|
|
1464
|
+
default='py-4',
|
|
1465
|
+
label='Espaçamento vertical',
|
|
1466
|
+
help_text='Espaçamento superior e inferior do componente'
|
|
1467
|
+
)
|
|
1468
|
+
|
|
1469
|
+
def get_image_width_class(self, value):
|
|
1470
|
+
"""Retorna a classe CSS para a largura da imagem"""
|
|
1471
|
+
proportion = value.get('layout_proportion', '50-50')
|
|
1472
|
+
width_map = {
|
|
1473
|
+
'30-70': 'col-md-4 col-lg-3',
|
|
1474
|
+
'40-60': 'col-md-5 col-lg-4',
|
|
1475
|
+
'50-50': 'col-md-6',
|
|
1476
|
+
'60-40': 'col-md-7 col-lg-8',
|
|
1477
|
+
'70-30': 'col-md-8 col-lg-9',
|
|
1478
|
+
}
|
|
1479
|
+
return width_map.get(proportion, 'col-md-6')
|
|
1480
|
+
|
|
1481
|
+
def get_text_width_class(self, value):
|
|
1482
|
+
"""Retorna a classe CSS para a largura do texto"""
|
|
1483
|
+
proportion = value.get('layout_proportion', '50-50')
|
|
1484
|
+
width_map = {
|
|
1485
|
+
'30-70': 'col-md-8 col-lg-9',
|
|
1486
|
+
'40-60': 'col-md-7 col-lg-8',
|
|
1487
|
+
'50-50': 'col-md-6',
|
|
1488
|
+
'60-40': 'col-md-5 col-lg-4',
|
|
1489
|
+
'70-30': 'col-md-4 col-lg-3',
|
|
1490
|
+
}
|
|
1491
|
+
return width_map.get(proportion, 'col-md-6')
|
|
1492
|
+
|
|
1493
|
+
def get_column_order(self, value):
|
|
1494
|
+
"""Retorna as classes de ordem para posicionamento responsivo"""
|
|
1495
|
+
position = value.get('image_position', 'left')
|
|
1496
|
+
if position == 'right':
|
|
1497
|
+
return {
|
|
1498
|
+
'image_order': 'order-md-2',
|
|
1499
|
+
'text_order': 'order-md-1'
|
|
1500
|
+
}
|
|
1501
|
+
return {
|
|
1502
|
+
'image_order': '',
|
|
1503
|
+
'text_order': ''
|
|
1504
|
+
}
|
|
1505
|
+
|
|
1506
|
+
class Meta:
|
|
1507
|
+
template = 'enap_designsystem/blocks/image_text_block.html'
|
|
1508
|
+
icon = 'image'
|
|
1509
|
+
label = 'Imagem com Texto'
|
|
1510
|
+
help_text = 'Componente flexível de imagem com texto em diferentes proporções'
|
|
1511
|
+
|
|
1512
|
+
|
|
1513
|
+
|
|
1514
|
+
|
|
1515
|
+
|
|
1516
|
+
|
|
1517
|
+
|
|
1518
|
+
|
|
1519
|
+
|
|
1374
1520
|
ARTICLE_STREAMBLOCKS = [
|
|
1375
1521
|
('richtext', RichTextBlock()),
|
|
1376
1522
|
("button", ButtonBlock()),
|
|
@@ -1381,8 +1527,60 @@ ARTICLE_STREAMBLOCKS = [
|
|
|
1381
1527
|
("embed_video", VideoBlock()),
|
|
1382
1528
|
("noticias_carousel", NewsCarouselBlock()),
|
|
1383
1529
|
("eventos_carousel", EventsCarouselBlock()),
|
|
1530
|
+
("Texto_image_choices", ImageTextBlockChoices()),
|
|
1384
1531
|
]
|
|
1385
1532
|
|
|
1533
|
+
|
|
1534
|
+
|
|
1535
|
+
class ArticleGridBlock(blocks.StructBlock):
|
|
1536
|
+
"""
|
|
1537
|
+
Wrapper para criar layouts de notícia normal ou revista
|
|
1538
|
+
"""
|
|
1539
|
+
|
|
1540
|
+
LAYOUT_CHOICES = [
|
|
1541
|
+
('noticia', 'Notícia Normal (uma coluna)'),
|
|
1542
|
+
('revista', 'Notícia Revista (duas colunas)'),
|
|
1543
|
+
]
|
|
1544
|
+
|
|
1545
|
+
layout_type = blocks.ChoiceBlock(
|
|
1546
|
+
choices=LAYOUT_CHOICES,
|
|
1547
|
+
default='noticia',
|
|
1548
|
+
label='Tipo de Layout',
|
|
1549
|
+
help_text='Escolha entre notícia normal ou formato revista'
|
|
1550
|
+
)
|
|
1551
|
+
|
|
1552
|
+
# Conteúdo para notícia normal (uma coluna)
|
|
1553
|
+
conteudo = blocks.StreamBlock(
|
|
1554
|
+
ARTICLE_STREAMBLOCKS,
|
|
1555
|
+
label='Conteúdo',
|
|
1556
|
+
help_text='Conteúdo da notícia (aparece apenas no formato notícia normal)',
|
|
1557
|
+
required=False
|
|
1558
|
+
)
|
|
1559
|
+
|
|
1560
|
+
# Conteúdos para formato revista (duas colunas)
|
|
1561
|
+
coluna_esquerda = blocks.StreamBlock(
|
|
1562
|
+
ARTICLE_STREAMBLOCKS,
|
|
1563
|
+
label='Coluna Esquerda',
|
|
1564
|
+
help_text='Conteúdo da primeira coluna (aparece apenas no formato revista)',
|
|
1565
|
+
required=False
|
|
1566
|
+
)
|
|
1567
|
+
|
|
1568
|
+
coluna_direita = blocks.StreamBlock(
|
|
1569
|
+
ARTICLE_STREAMBLOCKS,
|
|
1570
|
+
label='Coluna Direita',
|
|
1571
|
+
help_text='Conteúdo da segunda coluna (aparece apenas no formato revista)',
|
|
1572
|
+
required=False
|
|
1573
|
+
)
|
|
1574
|
+
|
|
1575
|
+
class Meta:
|
|
1576
|
+
js = ('enap_designsystem/blocks/article_grid_conditional.js',)
|
|
1577
|
+
template = 'enap_designsystem/blocks/article_grid_block.html'
|
|
1578
|
+
icon = 'doc-full'
|
|
1579
|
+
label = 'Layout de Artigo'
|
|
1580
|
+
help_text = 'Escolha entre notícia normal ou formato revista'
|
|
1581
|
+
|
|
1582
|
+
|
|
1583
|
+
|
|
1386
1584
|
class ArticlePage(Page):
|
|
1387
1585
|
"""
|
|
1388
1586
|
Página de artigo, adequada para notícias ou conteúdo de blog.
|
|
@@ -1643,7 +1841,7 @@ class ArticleIndexPage(Page):
|
|
|
1643
1841
|
|
|
1644
1842
|
|
|
1645
1843
|
class ENAPNoticiasIndexPage(Page):
|
|
1646
|
-
subpage_types = ['enap_designsystem.ENAPNoticiaImportada', 'enap_designsystem.ENAPNoticia']
|
|
1844
|
+
subpage_types = ['enap_designsystem.ENAPNoticiaImportada', 'enap_designsystem.ENAPNoticia', 'enap_designsystem.ENAPRevista']
|
|
1647
1845
|
|
|
1648
1846
|
class Meta:
|
|
1649
1847
|
verbose_name = _("ENAP Índice de Notícias")
|
|
@@ -2071,6 +2269,361 @@ class ENAPNoticiaImportada(Page):
|
|
|
2071
2269
|
verbose_name = _("ENAP Noticias Joomla")
|
|
2072
2270
|
verbose_name_plural = _("ENAP Noticias Joomla")
|
|
2073
2271
|
|
|
2272
|
+
|
|
2273
|
+
|
|
2274
|
+
|
|
2275
|
+
|
|
2276
|
+
|
|
2277
|
+
|
|
2278
|
+
|
|
2279
|
+
class ENAPRevista(Page):
|
|
2280
|
+
"""Modelo para artigos em formato revista com layout em duas colunas."""
|
|
2281
|
+
|
|
2282
|
+
body = StreamField(
|
|
2283
|
+
[
|
|
2284
|
+
("article_grid", ArticleGridBlock()),
|
|
2285
|
+
],
|
|
2286
|
+
null=True,
|
|
2287
|
+
blank=True,
|
|
2288
|
+
verbose_name=_("Conteúdo"),
|
|
2289
|
+
help_text=_("Configure o layout: escolha 'Notícia Normal' ou 'Notícia Revista' e adicione o conteúdo."),
|
|
2290
|
+
use_json_field=True,
|
|
2291
|
+
)
|
|
2292
|
+
|
|
2293
|
+
subtitulo = models.CharField(
|
|
2294
|
+
max_length=255,
|
|
2295
|
+
blank=True,
|
|
2296
|
+
verbose_name=_("Subtítulo"),
|
|
2297
|
+
help_text=_("Texto complementar ao título da revista."),
|
|
2298
|
+
)
|
|
2299
|
+
|
|
2300
|
+
legenda_home = models.TextField(
|
|
2301
|
+
max_length=500,
|
|
2302
|
+
blank=True,
|
|
2303
|
+
verbose_name=_("Legenda para Home"),
|
|
2304
|
+
help_text=_("Texto que aparece nas listagens da home (máx. 500 caracteres). Se vazio, usará o subtítulo."),
|
|
2305
|
+
)
|
|
2306
|
+
|
|
2307
|
+
imagem_externa = models.ForeignKey(
|
|
2308
|
+
get_image_model_string(),
|
|
2309
|
+
null=True,
|
|
2310
|
+
blank=True,
|
|
2311
|
+
on_delete=models.SET_NULL,
|
|
2312
|
+
related_name='+',
|
|
2313
|
+
verbose_name=_("Imagem Externa"),
|
|
2314
|
+
help_text=_("Imagem principal da revista para exibição externa (listagens, cards, etc)."),
|
|
2315
|
+
)
|
|
2316
|
+
|
|
2317
|
+
# Campos de background da página
|
|
2318
|
+
background_type = models.CharField(
|
|
2319
|
+
max_length=20,
|
|
2320
|
+
choices=[
|
|
2321
|
+
('color', _('Cor de Fundo')),
|
|
2322
|
+
('image', _('Imagem de Fundo')),
|
|
2323
|
+
],
|
|
2324
|
+
default='color',
|
|
2325
|
+
verbose_name=_("Tipo de Fundo"),
|
|
2326
|
+
help_text=_("Escolha entre cor sólida ou imagem de fundo."),
|
|
2327
|
+
)
|
|
2328
|
+
|
|
2329
|
+
background_color = models.CharField(
|
|
2330
|
+
max_length=50,
|
|
2331
|
+
choices=[('', _('Padrão (sem cor)'))] + BACKGROUND_COLOR_CHOICES,
|
|
2332
|
+
default='',
|
|
2333
|
+
blank=True,
|
|
2334
|
+
verbose_name=_("Cor de Fundo"),
|
|
2335
|
+
help_text=_("Cor de fundo da página (usado quando 'Tipo de Fundo' é 'Cor')."),
|
|
2336
|
+
)
|
|
2337
|
+
|
|
2338
|
+
background_image = models.ForeignKey(
|
|
2339
|
+
get_image_model_string(),
|
|
2340
|
+
null=True,
|
|
2341
|
+
blank=True,
|
|
2342
|
+
on_delete=models.SET_NULL,
|
|
2343
|
+
related_name='+',
|
|
2344
|
+
verbose_name=_("Imagem de Fundo"),
|
|
2345
|
+
help_text=_("Imagem de fundo da página (usado quando 'Tipo de Fundo' é 'Imagem')."),
|
|
2346
|
+
)
|
|
2347
|
+
|
|
2348
|
+
background_image_position = models.CharField(
|
|
2349
|
+
max_length=30,
|
|
2350
|
+
choices=[
|
|
2351
|
+
('center', _('Centro')),
|
|
2352
|
+
('top', _('Topo')),
|
|
2353
|
+
('bottom', _('Baixo')),
|
|
2354
|
+
('left', _('Esquerda')),
|
|
2355
|
+
('right', _('Direita')),
|
|
2356
|
+
('top-left', _('Topo Esquerda')),
|
|
2357
|
+
('top-right', _('Topo Direita')),
|
|
2358
|
+
('bottom-left', _('Baixo Esquerda')),
|
|
2359
|
+
('bottom-right', _('Baixo Direita')),
|
|
2360
|
+
],
|
|
2361
|
+
default='center',
|
|
2362
|
+
verbose_name=_("Posição da Imagem"),
|
|
2363
|
+
help_text=_("Posição da imagem de fundo."),
|
|
2364
|
+
)
|
|
2365
|
+
|
|
2366
|
+
background_image_size = models.CharField(
|
|
2367
|
+
max_length=20,
|
|
2368
|
+
choices=[
|
|
2369
|
+
('cover', _('Cobrir (Cover)')),
|
|
2370
|
+
('contain', _('Conter (Contain)')),
|
|
2371
|
+
('auto', _('Automático')),
|
|
2372
|
+
],
|
|
2373
|
+
default='cover',
|
|
2374
|
+
verbose_name=_("Tamanho da Imagem"),
|
|
2375
|
+
help_text=_("Como a imagem de fundo deve ser redimensionada."),
|
|
2376
|
+
)
|
|
2377
|
+
|
|
2378
|
+
author = models.ForeignKey(
|
|
2379
|
+
settings.AUTH_USER_MODEL,
|
|
2380
|
+
null=True,
|
|
2381
|
+
blank=True,
|
|
2382
|
+
editable=True,
|
|
2383
|
+
on_delete=models.SET_NULL,
|
|
2384
|
+
verbose_name=_("Autor"),
|
|
2385
|
+
related_name='enap_revista_set',
|
|
2386
|
+
)
|
|
2387
|
+
|
|
2388
|
+
author_display = models.CharField(
|
|
2389
|
+
max_length=255,
|
|
2390
|
+
blank=True,
|
|
2391
|
+
verbose_name=_("Exibir autor como"),
|
|
2392
|
+
help_text=_("Substitui como o nome do autor é exibido neste artigo."),
|
|
2393
|
+
)
|
|
2394
|
+
|
|
2395
|
+
date_display = models.DateField(
|
|
2396
|
+
null=True,
|
|
2397
|
+
blank=False,
|
|
2398
|
+
verbose_name=_("Data de publicação para exibição"),
|
|
2399
|
+
)
|
|
2400
|
+
|
|
2401
|
+
featured_image = StreamField(
|
|
2402
|
+
[
|
|
2403
|
+
("image", ImageBlock()),
|
|
2404
|
+
],
|
|
2405
|
+
null=True,
|
|
2406
|
+
blank=True,
|
|
2407
|
+
verbose_name=_("Imagem Destacada"),
|
|
2408
|
+
help_text=_("Imagem de destaque que aparece no topo do artigo."),
|
|
2409
|
+
use_json_field=True,
|
|
2410
|
+
)
|
|
2411
|
+
|
|
2412
|
+
# Campos específicos para revista
|
|
2413
|
+
edicao_numero = models.CharField(
|
|
2414
|
+
max_length=50,
|
|
2415
|
+
blank=True,
|
|
2416
|
+
verbose_name=_("Número da Edição"),
|
|
2417
|
+
help_text=_("Ex: Edição 15, Vol. 3, etc."),
|
|
2418
|
+
)
|
|
2419
|
+
|
|
2420
|
+
categoria_revista = models.CharField(
|
|
2421
|
+
max_length=100,
|
|
2422
|
+
blank=True,
|
|
2423
|
+
choices=[
|
|
2424
|
+
('entrevista', _('Entrevista')),
|
|
2425
|
+
('artigo', _('Artigo')),
|
|
2426
|
+
('especial', _('Especial')),
|
|
2427
|
+
('inovacao', _('Inovação')),
|
|
2428
|
+
('capacitacao', _('Capacitação')),
|
|
2429
|
+
('pesquisa', _('Pesquisa')),
|
|
2430
|
+
('internacional', _('Internacional')),
|
|
2431
|
+
],
|
|
2432
|
+
verbose_name=_("Categoria da Revista"),
|
|
2433
|
+
help_text=_("Categoria específica para organização da revista."),
|
|
2434
|
+
)
|
|
2435
|
+
|
|
2436
|
+
navbar = models.ForeignKey(
|
|
2437
|
+
"EnapNavbarSnippet",
|
|
2438
|
+
null=True,
|
|
2439
|
+
blank=True,
|
|
2440
|
+
on_delete=models.SET_NULL,
|
|
2441
|
+
related_name="+",
|
|
2442
|
+
)
|
|
2443
|
+
|
|
2444
|
+
footer = models.ForeignKey(
|
|
2445
|
+
"EnapFooterSnippet",
|
|
2446
|
+
null=True,
|
|
2447
|
+
blank=True,
|
|
2448
|
+
on_delete=models.SET_NULL,
|
|
2449
|
+
related_name="+",
|
|
2450
|
+
)
|
|
2451
|
+
|
|
2452
|
+
# Propriedade para obter o estilo CSS do background
|
|
2453
|
+
@property
|
|
2454
|
+
def background_style(self):
|
|
2455
|
+
"""Gera o CSS para o background da página"""
|
|
2456
|
+
if self.background_type == 'image' and self.background_image:
|
|
2457
|
+
return (
|
|
2458
|
+
f"background-image: url('{self.background_image.file.url}'); "
|
|
2459
|
+
f"background-position: {self.background_image_position}; "
|
|
2460
|
+
f"background-size: {self.background_image_size}; "
|
|
2461
|
+
f"background-repeat: no-repeat;"
|
|
2462
|
+
)
|
|
2463
|
+
elif self.background_type == 'color' and self.background_color:
|
|
2464
|
+
return f"background-color: {self.background_color};"
|
|
2465
|
+
return ""
|
|
2466
|
+
|
|
2467
|
+
content_panels = Page.content_panels + [
|
|
2468
|
+
FieldPanel("navbar"),
|
|
2469
|
+
FieldPanel("footer"),
|
|
2470
|
+
MultiFieldPanel(
|
|
2471
|
+
[
|
|
2472
|
+
FieldPanel('subtitulo'),
|
|
2473
|
+
FieldPanel('legenda_home'),
|
|
2474
|
+
FieldPanel('imagem_externa'),
|
|
2475
|
+
FieldPanel('edicao_numero'),
|
|
2476
|
+
FieldPanel('categoria_revista'),
|
|
2477
|
+
],
|
|
2478
|
+
heading=_("Informações da Revista"),
|
|
2479
|
+
),
|
|
2480
|
+
MultiFieldPanel(
|
|
2481
|
+
[
|
|
2482
|
+
FieldPanel('background_type'),
|
|
2483
|
+
FieldPanel('background_color'),
|
|
2484
|
+
FieldPanel('background_image'),
|
|
2485
|
+
FieldPanel('background_image_position'),
|
|
2486
|
+
FieldPanel('background_image_size'),
|
|
2487
|
+
],
|
|
2488
|
+
heading=_("Configurações de Fundo"),
|
|
2489
|
+
help_text=_("Configure o fundo da página - escolha entre cor sólida ou imagem."),
|
|
2490
|
+
),
|
|
2491
|
+
FieldPanel('featured_image'),
|
|
2492
|
+
MultiFieldPanel(
|
|
2493
|
+
[
|
|
2494
|
+
FieldPanel('body'),
|
|
2495
|
+
],
|
|
2496
|
+
heading=_("Conteúdo da Revista"),
|
|
2497
|
+
help_text=_("DICA: Use o bloco 'Layout de Artigo' → 'Notícia Revista' para criar o layout em duas colunas como na imagem exemplo."),
|
|
2498
|
+
),
|
|
2499
|
+
MultiFieldPanel(
|
|
2500
|
+
[
|
|
2501
|
+
FieldPanel('author'),
|
|
2502
|
+
FieldPanel('author_display'),
|
|
2503
|
+
FieldPanel('date_display'),
|
|
2504
|
+
],
|
|
2505
|
+
heading=_("Informações de Publicação"),
|
|
2506
|
+
),
|
|
2507
|
+
]
|
|
2508
|
+
|
|
2509
|
+
# Mesmas propriedades da ENAPNoticia para compatibilidade
|
|
2510
|
+
@property
|
|
2511
|
+
def titulo_filter(self):
|
|
2512
|
+
return strip_tags(self.title or "").strip()
|
|
2513
|
+
|
|
2514
|
+
@property
|
|
2515
|
+
def descricao_filter(self):
|
|
2516
|
+
return strip_tags(self.subtitulo or "").strip()
|
|
2517
|
+
|
|
2518
|
+
@property
|
|
2519
|
+
def legenda_home_filter(self):
|
|
2520
|
+
"""Retorna legenda_home ou fallback para subtítulo"""
|
|
2521
|
+
if self.legenda_home:
|
|
2522
|
+
return strip_tags(self.legenda_home).strip()
|
|
2523
|
+
return strip_tags(self.subtitulo or "").strip()
|
|
2524
|
+
|
|
2525
|
+
@property
|
|
2526
|
+
def categoria(self):
|
|
2527
|
+
return "Notícias"
|
|
2528
|
+
|
|
2529
|
+
@property
|
|
2530
|
+
def data_atualizacao_filter(self):
|
|
2531
|
+
return self.date_display or self.last_published_at or self.latest_revision_created_at or self.first_published_at
|
|
2532
|
+
|
|
2533
|
+
@property
|
|
2534
|
+
def url_filter(self):
|
|
2535
|
+
if hasattr(self, 'full_url') and self.full_url:
|
|
2536
|
+
return self.full_url
|
|
2537
|
+
return self.get_url_parts()[2] if self.get_url_parts() else ""
|
|
2538
|
+
|
|
2539
|
+
@property
|
|
2540
|
+
def imagem_filter(self):
|
|
2541
|
+
"""Retorna URL da imagem externa ou da featured_image como fallback."""
|
|
2542
|
+
# Prioridade: imagem_externa
|
|
2543
|
+
try:
|
|
2544
|
+
if self.imagem_externa:
|
|
2545
|
+
return self.imagem_externa.file.url
|
|
2546
|
+
except Exception:
|
|
2547
|
+
pass
|
|
2548
|
+
|
|
2549
|
+
# Fallback: featured_image
|
|
2550
|
+
if self.featured_image and len(self.featured_image.stream_data) > 0:
|
|
2551
|
+
primeiro_bloco = self.featured_image.stream_data[0]
|
|
2552
|
+
if primeiro_bloco["type"] == "image":
|
|
2553
|
+
valor = primeiro_bloco["value"]
|
|
2554
|
+
if isinstance(valor, dict) and valor.get("id"):
|
|
2555
|
+
try:
|
|
2556
|
+
from wagtail.images import get_image_model
|
|
2557
|
+
Image = get_image_model()
|
|
2558
|
+
imagem = Image.objects.get(id=valor["id"])
|
|
2559
|
+
return imagem.file.url
|
|
2560
|
+
except Image.DoesNotExist:
|
|
2561
|
+
pass
|
|
2562
|
+
return ""
|
|
2563
|
+
|
|
2564
|
+
@property
|
|
2565
|
+
def texto_unificado(self):
|
|
2566
|
+
def extract_text_from_block(block_value):
|
|
2567
|
+
result = []
|
|
2568
|
+
|
|
2569
|
+
if isinstance(block_value, list):
|
|
2570
|
+
for subblock in block_value:
|
|
2571
|
+
result.extend(extract_text_from_block(subblock))
|
|
2572
|
+
elif hasattr(block_value, "get"):
|
|
2573
|
+
for key, val in block_value.items():
|
|
2574
|
+
result.extend(extract_text_from_block(val))
|
|
2575
|
+
elif isinstance(block_value, str):
|
|
2576
|
+
cleaned = strip_tags(block_value).strip()
|
|
2577
|
+
if cleaned and cleaned.lower() not in {
|
|
2578
|
+
"default", "tipo terciário", "tipo secundário", "tipo bg image",
|
|
2579
|
+
"bg-gray", "bg-blue", "bg-white", "fundo cinza", "fundo branco"
|
|
2580
|
+
}:
|
|
2581
|
+
result.append(cleaned)
|
|
2582
|
+
elif hasattr(block_value, "source"):
|
|
2583
|
+
cleaned = strip_tags(block_value.source).strip()
|
|
2584
|
+
if cleaned:
|
|
2585
|
+
result.append(cleaned)
|
|
2586
|
+
|
|
2587
|
+
return result
|
|
2588
|
+
|
|
2589
|
+
textos = []
|
|
2590
|
+
if self.body:
|
|
2591
|
+
for block in self.body:
|
|
2592
|
+
textos.extend(extract_text_from_block(block.value))
|
|
2593
|
+
|
|
2594
|
+
if self.subtitulo:
|
|
2595
|
+
textos.append(strip_tags(self.subtitulo).strip())
|
|
2596
|
+
|
|
2597
|
+
if self.legenda_home:
|
|
2598
|
+
textos.append(strip_tags(self.legenda_home).strip())
|
|
2599
|
+
|
|
2600
|
+
if self.edicao_numero:
|
|
2601
|
+
textos.append(strip_tags(self.edicao_numero).strip())
|
|
2602
|
+
|
|
2603
|
+
return re.sub(r"\s+", " ", " ".join([t for t in textos if t])).strip()
|
|
2604
|
+
|
|
2605
|
+
search_fields = Page.search_fields + [
|
|
2606
|
+
index.SearchField("title", boost=3),
|
|
2607
|
+
index.SearchField("titulo_filter", name="titulo"),
|
|
2608
|
+
index.SearchField("descricao_filter", name="descricao"),
|
|
2609
|
+
index.SearchField("legenda_home_filter", name="legenda_home"),
|
|
2610
|
+
index.FilterField("categoria", name="categoria_filter"),
|
|
2611
|
+
index.SearchField("url_filter", name="url"),
|
|
2612
|
+
index.SearchField("data_atualizacao_filter", name="data_atualizacao"),
|
|
2613
|
+
index.SearchField("imagem_filter", name="imagem"),
|
|
2614
|
+
index.SearchField("texto_unificado", name="body"),
|
|
2615
|
+
index.FilterField("categoria_revista"),
|
|
2616
|
+
index.SearchField("edicao_numero"),
|
|
2617
|
+
]
|
|
2618
|
+
|
|
2619
|
+
class Meta:
|
|
2620
|
+
verbose_name = _("ENAP Revista")
|
|
2621
|
+
verbose_name_plural = _("ENAP Revistas")
|
|
2622
|
+
|
|
2623
|
+
template = "enap_designsystem/pages/article/enap_revista.html"
|
|
2624
|
+
|
|
2625
|
+
|
|
2626
|
+
|
|
2074
2627
|
class ENAPDummyPage(Page):
|
|
2075
2628
|
"""Página usada apenas como container na árvore, sem conteúdo visível."""
|
|
2076
2629
|
|
|
@@ -4141,15 +4694,15 @@ class JobVacancyPage(Page):
|
|
|
4141
4694
|
max_length=20,
|
|
4142
4695
|
choices=STATUS_CHOICES,
|
|
4143
4696
|
default='aberta',
|
|
4144
|
-
verbose_name=_('Status
|
|
4697
|
+
verbose_name=_('Status (Aberto, em andamento ou encerrada)'),
|
|
4145
4698
|
)
|
|
4146
4699
|
|
|
4147
4700
|
area = models.CharField(
|
|
4148
4701
|
max_length=30,
|
|
4149
4702
|
choices=AREA_CHOICES,
|
|
4150
4703
|
default='outros',
|
|
4151
|
-
verbose_name=_('Área
|
|
4152
|
-
help_text=_('Categoria
|
|
4704
|
+
verbose_name=_('Área ou categoria'),
|
|
4705
|
+
help_text=_('Categoria para melhor organização')
|
|
4153
4706
|
)
|
|
4154
4707
|
|
|
4155
4708
|
image = StreamField([
|
|
@@ -4168,7 +4721,7 @@ class JobVacancyPage(Page):
|
|
|
4168
4721
|
|
|
4169
4722
|
link_text = models.CharField(
|
|
4170
4723
|
max_length=100,
|
|
4171
|
-
verbose_name=_('Texto do botão'),
|
|
4724
|
+
verbose_name=_('Texto do botão de destaque'),
|
|
4172
4725
|
default='Ver detalhes',
|
|
4173
4726
|
blank=True
|
|
4174
4727
|
)
|
|
@@ -4180,20 +4733,20 @@ class JobVacancyPage(Page):
|
|
|
4180
4733
|
)
|
|
4181
4734
|
|
|
4182
4735
|
registration_start = models.DateField(
|
|
4183
|
-
verbose_name=_('
|
|
4736
|
+
verbose_name=_('Data de Inicio')
|
|
4184
4737
|
)
|
|
4185
4738
|
|
|
4186
4739
|
registration_end = models.DateField(
|
|
4187
|
-
verbose_name=_('
|
|
4740
|
+
verbose_name=_('Data Final')
|
|
4188
4741
|
)
|
|
4189
4742
|
|
|
4190
4743
|
inscription_link = models.URLField(
|
|
4191
|
-
verbose_name=_('Link
|
|
4744
|
+
verbose_name=_('Link de destaque'),
|
|
4192
4745
|
blank=True
|
|
4193
4746
|
)
|
|
4194
4747
|
|
|
4195
4748
|
full_description = RichTextField(
|
|
4196
|
-
verbose_name=_('Descrição completa
|
|
4749
|
+
verbose_name=_('Descrição completa')
|
|
4197
4750
|
)
|
|
4198
4751
|
|
|
4199
4752
|
download_files = RichTextField(
|
|
@@ -4363,8 +4916,8 @@ class JobVacancyPage(Page):
|
|
|
4363
4916
|
]
|
|
4364
4917
|
|
|
4365
4918
|
class Meta:
|
|
4366
|
-
verbose_name = _('
|
|
4367
|
-
verbose_name_plural = _('Vagas
|
|
4919
|
+
verbose_name = _('Template (Vagas & Licitações)')
|
|
4920
|
+
verbose_name_plural = _('Vagas e Licitações')
|
|
4368
4921
|
|
|
4369
4922
|
|
|
4370
4923
|
|
|
@@ -6881,4 +7434,14 @@ class FormularioDinamicoBlock(blocks.StructBlock):
|
|
|
6881
7434
|
if parent_context:
|
|
6882
7435
|
context['page'] = parent_context.get('page')
|
|
6883
7436
|
|
|
6884
|
-
return context
|
|
7437
|
+
return context
|
|
7438
|
+
|
|
7439
|
+
|
|
7440
|
+
|
|
7441
|
+
|
|
7442
|
+
|
|
7443
|
+
|
|
7444
|
+
|
|
7445
|
+
|
|
7446
|
+
|
|
7447
|
+
|