mirror of https://github.com/interlegis/sapl.git
committed by
GitHub
22 changed files with 1026 additions and 878 deletions
@ -0,0 +1,89 @@ |
|||
@import "~bootstrap/scss/variables"; |
|||
|
|||
// Estilização do tab-content conectado ao nav-tabs (substitui inline style) |
|||
.nav-tabs + .tab-content { |
|||
border: 1px solid $nav-tabs-border-color; |
|||
border-top: 0; |
|||
border-radius: 0 0 $border-radius $border-radius; |
|||
} |
|||
|
|||
@media (max-width: 992px) { |
|||
.nav-tabs { |
|||
position: relative; |
|||
flex-direction: column; |
|||
border: 1px solid $nav-tabs-border-color; |
|||
border-radius: $border-radius; // Totalmente arredondado — parece um botão/select |
|||
background-color: $white; |
|||
overflow: hidden; // Recorta filhos nas bordas arredondadas |
|||
|
|||
// Seta indicando dropdown |
|||
&::after { |
|||
content: "▾"; |
|||
position: absolute; |
|||
right: 0.75rem; |
|||
top: 0.6rem; |
|||
font-size: 1rem; |
|||
color: $secondary; |
|||
pointer-events: none; |
|||
transition: transform 0.2s ease; |
|||
} |
|||
|
|||
// Oculta todos os itens por padrão |
|||
.nav-item { |
|||
display: none; |
|||
width: 100%; |
|||
|
|||
.nav-link { |
|||
border: none; |
|||
border-bottom: 1px solid $nav-tabs-border-color; |
|||
border-radius: 0; |
|||
width: 100%; |
|||
text-align: left; |
|||
padding-right: 2rem; |
|||
margin-bottom: 0; |
|||
|
|||
&.active { |
|||
background-color: $nav-tabs-link-active-bg; |
|||
color: $nav-tabs-link-active-color; |
|||
border-color: transparent; |
|||
} |
|||
|
|||
&:hover:not(.active) { |
|||
background-color: $light; |
|||
} |
|||
} |
|||
|
|||
&:last-child .nav-link { |
|||
border-bottom: none; |
|||
} |
|||
} |
|||
|
|||
// CSS nativo: exibe somente o item ativo (browsers com suporte a :has) |
|||
.nav-item:has(.nav-link.active) { |
|||
display: block; |
|||
} |
|||
|
|||
// Estado expandido: via :focus-within (nativo) ou .nav-tabs--open (fallback JS) |
|||
&:focus-within, |
|||
&.nav-tabs--open { |
|||
border-radius: $border-radius $border-radius 0 0; // Arredonda apenas topo quando aberto |
|||
overflow: visible; |
|||
z-index: $zindex-dropdown; |
|||
|
|||
&::after { |
|||
transform: rotate(180deg); |
|||
} |
|||
|
|||
.nav-item { |
|||
display: block; |
|||
} |
|||
} |
|||
} |
|||
|
|||
// Em mobile, tab-content é visualmente independente do nav-tabs (que vira um select) |
|||
.nav-tabs + .tab-content { |
|||
border-top: 1px solid $nav-tabs-border-color; |
|||
border-radius: $border-radius; // Rounding completo — desconectado do nav-tabs |
|||
margin-top: 0.5rem; |
|||
} |
|||
} |
|||
@ -1,2 +1,3 @@ |
|||
@import "./bootstrap/nav_navbar"; |
|||
@import "./bootstrap/nav_tabs"; |
|||
@import "./bootstrap/table"; |
|||
|
|||
@ -0,0 +1,34 @@ |
|||
# Generated by Django 2.2.28 on 2026-04-13 01:48 |
|||
|
|||
from django.db import migrations, models |
|||
import django.db.models.deletion |
|||
from datetime import date |
|||
|
|||
def add_legislatura_to_mesa_diretora(apps, schema_editor): |
|||
schema_editor.execute(""" |
|||
UPDATE parlamentares_mesadiretora md |
|||
SET |
|||
legislatura_id = sl.legislatura_id, |
|||
data_inicio = sl.data_inicio, |
|||
data_fim = sl.data_fim |
|||
FROM |
|||
parlamentares_sessaolegislativa sl |
|||
WHERE |
|||
sl.id = md.sessao_legislativa_id |
|||
""") |
|||
|
|||
|
|||
class Migration(migrations.Migration): |
|||
|
|||
dependencies = [ |
|||
('parlamentares', '0045_auto_20251201_1531'), |
|||
] |
|||
|
|||
operations = [ |
|||
migrations.AddField( |
|||
model_name='mesadiretora', |
|||
name='legislatura', |
|||
field=models.ForeignKey(blank=True, default=None, null=True, on_delete=django.db.models.deletion.PROTECT, to='parlamentares.Legislatura', verbose_name='Legislatura'), |
|||
), |
|||
migrations.RunPython(add_legislatura_to_mesa_diretora), |
|||
] |
|||
@ -0,0 +1,23 @@ |
|||
# Generated by Django 2.2.28 on 2026-04-13 01:56 |
|||
|
|||
from django.db import migrations, models |
|||
import django.db.models.deletion |
|||
|
|||
|
|||
class Migration(migrations.Migration): |
|||
|
|||
dependencies = [ |
|||
('parlamentares', '0046_mesadiretora_legislatura'), |
|||
] |
|||
|
|||
operations = [ |
|||
migrations.AlterField( |
|||
model_name='mesadiretora', |
|||
name='legislatura', |
|||
field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='parlamentares.Legislatura', verbose_name='Legislatura'), |
|||
), |
|||
migrations.RemoveField( |
|||
model_name='mesadiretora', |
|||
name='sessao_legislativa', |
|||
), |
|||
] |
|||
@ -0,0 +1,42 @@ |
|||
# Generated by Django 2.2.28 on 2026-04-13 13:49 |
|||
|
|||
from django.db import migrations, models |
|||
import django.db.models.deletion |
|||
|
|||
def preencher_titulo_mesa_diretora(apps, schema_editor): |
|||
schema_editor.execute(""" |
|||
UPDATE parlamentares_mesadiretora |
|||
SET titulo = 'Mesa Diretora' || |
|||
CASE WHEN EXTRACT(YEAR FROM data_fim)::integer - EXTRACT(YEAR FROM data_inicio)::integer = 1 |
|||
THEN ' Biênio' |
|||
ELSE '' |
|||
END || ' ' || |
|||
EXTRACT(YEAR FROM data_inicio)::integer::text || '/' || |
|||
EXTRACT(YEAR FROM data_fim)::integer::text |
|||
WHERE data_inicio IS NOT NULL AND data_fim IS NOT NULL |
|||
""") |
|||
|
|||
|
|||
class Migration(migrations.Migration): |
|||
|
|||
dependencies = [ |
|||
('parlamentares', '0047_auto_20260412_2256'), |
|||
] |
|||
|
|||
operations = [ |
|||
migrations.AlterModelOptions( |
|||
name='mesadiretora', |
|||
options={'ordering': ('-legislatura', '-data_inicio'), 'verbose_name': 'Mesa Diretora', 'verbose_name_plural': 'Mesas Diretoras'}, |
|||
), |
|||
migrations.AddField( |
|||
model_name='mesadiretora', |
|||
name='titulo', |
|||
field=models.CharField(default='', max_length=100, verbose_name='Título da Mesa Diretora'), |
|||
), |
|||
migrations.AlterField( |
|||
model_name='composicaomesa', |
|||
name='mesa_diretora', |
|||
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, related_name='composicaomesa_set', to='parlamentares.MesaDiretora'), |
|||
), |
|||
migrations.RunPython(preencher_titulo_mesa_diretora), |
|||
] |
|||
@ -0,0 +1,39 @@ |
|||
# Generated by Django 2.2.28 on 2026-04-17 22:17 |
|||
|
|||
from django.db import migrations, models |
|||
import django.db.models.deletion |
|||
|
|||
|
|||
class Migration(migrations.Migration): |
|||
|
|||
dependencies = [ |
|||
('parlamentares', '0048_auto_20260413_1049'), |
|||
] |
|||
|
|||
operations = [ |
|||
migrations.AlterField( |
|||
model_name='composicaomesa', |
|||
name='cargo', |
|||
field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='parlamentares.CargoMesa', verbose_name='Cargo'), |
|||
), |
|||
migrations.AlterField( |
|||
model_name='composicaomesa', |
|||
name='mesa_diretora', |
|||
field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='composicaomesa_set', to='parlamentares.MesaDiretora', verbose_name='Mesa Diretora'), |
|||
), |
|||
migrations.AlterField( |
|||
model_name='composicaomesa', |
|||
name='parlamentar', |
|||
field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='parlamentares.Parlamentar', verbose_name='Parlamentar'), |
|||
), |
|||
migrations.AlterField( |
|||
model_name='mesadiretora', |
|||
name='data_fim', |
|||
field=models.DateField(verbose_name='Data Fim'), |
|||
), |
|||
migrations.AlterField( |
|||
model_name='mesadiretora', |
|||
name='data_inicio', |
|||
field=models.DateField(verbose_name='Data Início'), |
|||
), |
|||
] |
|||
@ -0,0 +1,19 @@ |
|||
# Generated by Django 2.2.28 on 2026-04-18 01:35 |
|||
|
|||
from django.db import migrations, models |
|||
import django.db.models.deletion |
|||
|
|||
|
|||
class Migration(migrations.Migration): |
|||
|
|||
dependencies = [ |
|||
('parlamentares', '0049_auto_20260417_1917'), |
|||
] |
|||
|
|||
operations = [ |
|||
migrations.AlterField( |
|||
model_name='mesadiretora', |
|||
name='legislatura', |
|||
field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='mesadiretora_set', to='parlamentares.Legislatura', verbose_name='Legislatura'), |
|||
), |
|||
] |
|||
@ -0,0 +1,401 @@ |
|||
import pytest |
|||
from datetime import date |
|||
|
|||
from django.core.exceptions import ValidationError |
|||
from django.urls import reverse |
|||
from django.utils.translation import ugettext_lazy as _ |
|||
from model_bakery import baker |
|||
|
|||
from sapl.parlamentares.forms import ComposicaoMesaForm, MesaDiretoraForm |
|||
from sapl.parlamentares.models import ComposicaoMesa, MesaDiretora |
|||
|
|||
|
|||
# ===================================================================== |
|||
# Testes de validação a nível de Model — MesaDiretora |
|||
# ===================================================================== |
|||
|
|||
@pytest.mark.django_db(transaction=False) |
|||
def test_mesadiretora_model_clean_data_inicio_maior_que_data_fim(): |
|||
legislatura = baker.make( |
|||
'parlamentares.Legislatura', |
|||
data_inicio=date(2021, 1, 1), |
|||
data_fim=date(2024, 12, 31) |
|||
) |
|||
mesa = MesaDiretora( |
|||
titulo='Mesa', |
|||
data_inicio=date(2022, 1, 1), |
|||
data_fim=date(2021, 12, 31), |
|||
legislatura=legislatura |
|||
) |
|||
with pytest.raises(ValidationError, match='A data de início deve ser anterior à data de fim.'): |
|||
mesa.clean() |
|||
|
|||
|
|||
@pytest.mark.django_db(transaction=False) |
|||
def test_mesadiretora_model_clean_data_fora_da_legislatura(): |
|||
legislatura = baker.make( |
|||
'parlamentares.Legislatura', |
|||
data_inicio=date(2021, 1, 1), |
|||
data_fim=date(2024, 12, 31) |
|||
) |
|||
mesa = MesaDiretora( |
|||
titulo='Mesa', |
|||
data_inicio=date(2020, 1, 1), |
|||
data_fim=date(2021, 12, 31), |
|||
legislatura=legislatura |
|||
) |
|||
with pytest.raises(ValidationError, match='As datas da mesa diretora devem estar dentro do período da legislatura.'): |
|||
mesa.clean() |
|||
|
|||
|
|||
@pytest.mark.django_db(transaction=False) |
|||
def test_mesadiretora_model_clean_intersecao(): |
|||
legislatura = baker.make( |
|||
'parlamentares.Legislatura', |
|||
data_inicio=date(2021, 1, 1), |
|||
data_fim=date(2024, 12, 31) |
|||
) |
|||
baker.make( |
|||
'parlamentares.MesaDiretora', |
|||
legislatura=legislatura, |
|||
titulo='Mesa Existente', |
|||
data_inicio=date(2021, 1, 1), |
|||
data_fim=date(2022, 12, 31) |
|||
) |
|||
mesa = MesaDiretora( |
|||
titulo='Nova Mesa', |
|||
data_inicio=date(2022, 1, 1), |
|||
data_fim=date(2023, 12, 31), |
|||
legislatura=legislatura |
|||
) |
|||
with pytest.raises(ValidationError, match='As datas da mesa diretora se sobrepõem com outra mesa diretora existente.'): |
|||
mesa.clean() |
|||
|
|||
|
|||
@pytest.mark.django_db(transaction=False) |
|||
def test_mesadiretora_model_clean_valido(): |
|||
legislatura = baker.make( |
|||
'parlamentares.Legislatura', |
|||
data_inicio=date(2021, 1, 1), |
|||
data_fim=date(2024, 12, 31) |
|||
) |
|||
mesa = MesaDiretora( |
|||
titulo='Mesa', |
|||
data_inicio=date(2021, 1, 1), |
|||
data_fim=date(2022, 12, 31), |
|||
legislatura=legislatura |
|||
) |
|||
mesa.clean() # não deve lançar exceção |
|||
|
|||
|
|||
@pytest.mark.django_db(transaction=False) |
|||
def test_mesadiretora_model_full_clean_sem_data_inicio(): |
|||
legislatura = baker.make( |
|||
'parlamentares.Legislatura', |
|||
data_inicio=date(2021, 1, 1), |
|||
data_fim=date(2024, 12, 31) |
|||
) |
|||
mesa = MesaDiretora( |
|||
titulo='Mesa', |
|||
data_fim=date(2022, 12, 31), |
|||
legislatura=legislatura |
|||
) |
|||
with pytest.raises(ValidationError) as exc_info: |
|||
mesa.full_clean() |
|||
|
|||
assert 'data_inicio' in exc_info.value.message_dict |
|||
assert exc_info.value.message_dict['data_inicio'] == [_('Este campo não pode ser nulo.')] |
|||
|
|||
|
|||
# ===================================================================== |
|||
# Testes de validação a nível de Model — ComposicaoMesa |
|||
# ===================================================================== |
|||
|
|||
@pytest.mark.django_db(transaction=False) |
|||
def test_composicaomesa_model_clean_parlamentar_duplicado(): |
|||
parlamentar = baker.make('parlamentares.Parlamentar') |
|||
cargo1 = baker.make('parlamentares.CargoMesa') |
|||
cargo2 = baker.make('parlamentares.CargoMesa') |
|||
mesa_diretora = baker.make('parlamentares.MesaDiretora') |
|||
|
|||
ComposicaoMesa.objects.create( |
|||
parlamentar=parlamentar, cargo=cargo1, mesa_diretora=mesa_diretora |
|||
) |
|||
|
|||
composicao = ComposicaoMesa( |
|||
parlamentar=parlamentar, cargo=cargo2, mesa_diretora=mesa_diretora |
|||
) |
|||
with pytest.raises(ValidationError, match='Parlamentar já ocupa um cargo nesta mesa diretora.'): |
|||
composicao.clean() |
|||
|
|||
|
|||
@pytest.mark.django_db(transaction=False) |
|||
def test_composicaomesa_model_clean_cargo_unico(): |
|||
parlamentar1 = baker.make('parlamentares.Parlamentar') |
|||
parlamentar2 = baker.make('parlamentares.Parlamentar') |
|||
cargo = baker.make('parlamentares.CargoMesa', unico=True) |
|||
mesa_diretora = baker.make('parlamentares.MesaDiretora') |
|||
|
|||
ComposicaoMesa.objects.create( |
|||
parlamentar=parlamentar1, cargo=cargo, mesa_diretora=mesa_diretora |
|||
) |
|||
|
|||
composicao = ComposicaoMesa( |
|||
parlamentar=parlamentar2, cargo=cargo, mesa_diretora=mesa_diretora |
|||
) |
|||
with pytest.raises(ValidationError, match='Cargo único já ocupado por outro parlamentar.'): |
|||
composicao.clean() |
|||
|
|||
|
|||
@pytest.mark.django_db(transaction=False) |
|||
def test_composicaomesa_model_clean_valido(): |
|||
parlamentar = baker.make('parlamentares.Parlamentar') |
|||
cargo = baker.make('parlamentares.CargoMesa') |
|||
mesa_diretora = baker.make('parlamentares.MesaDiretora') |
|||
|
|||
composicao = ComposicaoMesa( |
|||
parlamentar=parlamentar, cargo=cargo, mesa_diretora=mesa_diretora |
|||
) |
|||
composicao.clean() # não deve lançar exceção |
|||
|
|||
|
|||
# ===================================================================== |
|||
# Testes de validação via Form — MesaDiretora |
|||
# ===================================================================== |
|||
|
|||
def test_mesadiretora_form_invalido(): |
|||
form = MesaDiretoraForm(data={}) |
|||
|
|||
assert not form.is_valid() |
|||
|
|||
errors = form.errors |
|||
|
|||
assert errors['titulo'] == [_('Este campo é obrigatório.')] |
|||
assert errors['data_inicio'] == [_('Este campo é obrigatório.')] |
|||
assert errors['data_fim'] == [_('Este campo é obrigatório.')] |
|||
assert errors['legislatura'] == [_('Este campo é obrigatório.')] |
|||
|
|||
|
|||
@pytest.mark.django_db(transaction=False) |
|||
def test_mesadiretora_form_data_inicio_maior_que_data_fim(): |
|||
legislatura = baker.make( |
|||
'parlamentares.Legislatura', |
|||
data_inicio='2021-01-01', |
|||
data_fim='2024-12-31' |
|||
) |
|||
|
|||
form = MesaDiretoraForm(data={ |
|||
'titulo': 'Mesa Diretora 2021-2022', |
|||
'data_inicio': '2022-01-01', |
|||
'data_fim': '2021-12-31', |
|||
'legislatura': legislatura.id, |
|||
}) |
|||
|
|||
assert not form.is_valid() |
|||
errors = form.errors |
|||
assert errors['__all__'] == [_('A data de início deve ser anterior à data de fim.')] |
|||
|
|||
|
|||
@pytest.mark.django_db(transaction=False) |
|||
def test_mesadiretora_form_valido(): |
|||
legislatura = baker.make( |
|||
'parlamentares.Legislatura', |
|||
data_inicio='2021-01-01', |
|||
data_fim='2024-12-31' |
|||
) |
|||
|
|||
form = MesaDiretoraForm(data={ |
|||
'titulo': 'Mesa Diretora 2021-2022', |
|||
'data_inicio': '2021-01-01', |
|||
'data_fim': '2022-12-31', |
|||
'legislatura': legislatura.id, |
|||
}) |
|||
|
|||
assert form.is_valid() |
|||
|
|||
@pytest.mark.django_db(transaction=False) |
|||
def test_mesadiretora_form_intersecao(): |
|||
legislatura = baker.make( |
|||
'parlamentares.Legislatura', |
|||
data_inicio='2021-01-01', |
|||
data_fim='2024-12-31' |
|||
) |
|||
baker.make( |
|||
'parlamentares.MesaDiretora', |
|||
legislatura=legislatura, |
|||
titulo='Mesa Diretora 2021-2022', |
|||
data_inicio='2021-01-01', |
|||
data_fim='2022-12-31') |
|||
|
|||
form = MesaDiretoraForm(data={ |
|||
'titulo': 'Mesa Diretora 2022-2023', |
|||
'data_inicio': '2022-01-01', |
|||
'data_fim': '2023-12-31', |
|||
'legislatura': legislatura.id, |
|||
}) |
|||
|
|||
assert not form.is_valid() |
|||
errors = form.errors |
|||
assert errors['__all__'] == [_('As datas da mesa diretora se sobrepõem com outra mesa diretora existente.')] |
|||
|
|||
|
|||
@pytest.mark.django_db(transaction=False) |
|||
def test_mesadiretora_form_data_fora_da_legislatura(): |
|||
legislatura = baker.make( |
|||
'parlamentares.Legislatura', |
|||
data_inicio='2021-01-01', |
|||
data_fim='2024-12-31') |
|||
|
|||
form = MesaDiretoraForm(data={ |
|||
'titulo': 'Mesa Diretora 2020-2021', |
|||
'data_inicio': '2020-01-01', |
|||
'data_fim': '2021-12-31', |
|||
'legislatura': legislatura.id, |
|||
}) |
|||
|
|||
assert not form.is_valid() |
|||
errors = form.errors |
|||
assert errors['__all__'] == [_('As datas da mesa diretora devem estar dentro do período da legislatura.')] |
|||
|
|||
|
|||
# ===================================================================== |
|||
# Testes de validação via Form — ComposicaoMesa |
|||
# ===================================================================== |
|||
|
|||
@pytest.mark.django_db(transaction=False) |
|||
def test_composicaomesa_form_invalido(): |
|||
mesa_diretora = baker.make('parlamentares.MesaDiretora') |
|||
form = ComposicaoMesaForm(data={}, initial={'mesa_diretora': mesa_diretora}) |
|||
|
|||
assert not form.is_valid() |
|||
|
|||
errors = form.errors |
|||
|
|||
assert errors['parlamentar'] == [_('Este campo é obrigatório.')] |
|||
assert errors['cargo'] == [_('Este campo é obrigatório.')] |
|||
|
|||
|
|||
@pytest.mark.django_db(transaction=False) |
|||
def test_composicaomesa_form_valido(): |
|||
parlamentar = baker.make('parlamentares.Parlamentar') |
|||
cargo = baker.make('parlamentares.CargoMesa') |
|||
mesa_diretora = baker.make('parlamentares.MesaDiretora') |
|||
mandato = baker.make( |
|||
'parlamentares.Mandato', |
|||
parlamentar=parlamentar, |
|||
legislatura=mesa_diretora.legislatura) |
|||
|
|||
form = ComposicaoMesaForm(data={ |
|||
'parlamentar': parlamentar.id, |
|||
'cargo': cargo.id, |
|||
}, initial={ |
|||
'mesa_diretora': mesa_diretora, |
|||
}) |
|||
|
|||
assert form.is_valid() |
|||
|
|||
@pytest.mark.django_db(transaction=False) |
|||
def test_composicaomesa_form_parlamentar_ocupando_cargo_na_mesma_mesa(): |
|||
parlamentar = baker.make('parlamentares.Parlamentar') |
|||
cargo1 = baker.make('parlamentares.CargoMesa') |
|||
cargo2 = baker.make('parlamentares.CargoMesa') |
|||
mesa_diretora = baker.make('parlamentares.MesaDiretora') |
|||
mandato = baker.make( |
|||
'parlamentares.Mandato', |
|||
parlamentar=parlamentar, |
|||
legislatura=mesa_diretora.legislatura) |
|||
|
|||
ComposicaoMesa.objects.create( |
|||
parlamentar=parlamentar, |
|||
cargo=cargo1, |
|||
mesa_diretora=mesa_diretora |
|||
) |
|||
|
|||
form = ComposicaoMesaForm(data={ |
|||
'parlamentar': parlamentar.id, |
|||
'cargo': cargo2.id, |
|||
}, initial={ |
|||
'mesa_diretora': mesa_diretora, |
|||
}) |
|||
|
|||
assert not form.is_valid() |
|||
errors = form.errors |
|||
assert errors['__all__'] == [_('Parlamentar já ocupa um cargo nesta mesa diretora.')] |
|||
|
|||
|
|||
@pytest.mark.django_db(transaction=False) |
|||
def test_composicaomesa_form_parlamentar_cargo_unico_mesma_mesa(): |
|||
parlamentar1 = baker.make('parlamentares.Parlamentar') |
|||
parlamentar2 = baker.make('parlamentares.Parlamentar') |
|||
|
|||
cargo = baker.make('parlamentares.CargoMesa', unico=True) |
|||
|
|||
mesa_diretora = baker.make('parlamentares.MesaDiretora') |
|||
|
|||
mandato1 = baker.make('parlamentares.Mandato', parlamentar=parlamentar1, legislatura=mesa_diretora.legislatura) |
|||
mandato2 = baker.make('parlamentares.Mandato', parlamentar=parlamentar2, legislatura=mesa_diretora.legislatura) |
|||
|
|||
ComposicaoMesa.objects.create( |
|||
parlamentar=parlamentar1, |
|||
cargo=cargo, |
|||
mesa_diretora=mesa_diretora |
|||
) |
|||
|
|||
form = ComposicaoMesaForm(data={ |
|||
'parlamentar': parlamentar2.id, |
|||
'cargo': cargo.id, |
|||
}, initial={ |
|||
'mesa_diretora': mesa_diretora, |
|||
}) |
|||
|
|||
assert not form.is_valid() |
|||
errors = form.errors |
|||
assert errors['__all__'] == [_('Cargo único já ocupado por outro parlamentar.')] |
|||
|
|||
|
|||
# ===================================================================== |
|||
# Testes de integração via View — ComposicaoMesa |
|||
# ===================================================================== |
|||
|
|||
@pytest.mark.django_db(transaction=False) |
|||
def test_composicaomesa_form_view_create(admin_client): |
|||
parlamentar = baker.make('parlamentares.Parlamentar') |
|||
cargo = baker.make('parlamentares.CargoMesa') |
|||
mesa_diretora = baker.make('parlamentares.MesaDiretora') |
|||
mandato = baker.make( |
|||
'parlamentares.Mandato', |
|||
parlamentar=parlamentar, |
|||
legislatura=mesa_diretora.legislatura) |
|||
|
|||
response = admin_client.post(reverse('sapl.parlamentares:composicaomesa_create', kwargs={'pk': mesa_diretora.id}), data={ |
|||
'parlamentar': parlamentar.id, |
|||
'cargo': cargo.id, |
|||
}) |
|||
|
|||
assert ComposicaoMesa.objects.filter(parlamentar=parlamentar, cargo=cargo, mesa_diretora=mesa_diretora).exists() |
|||
|
|||
@pytest.mark.django_db(transaction=False) |
|||
def test_composicaomesa_form_view_update(admin_client): |
|||
parlamentar = baker.make('parlamentares.Parlamentar') |
|||
cargo = baker.make('parlamentares.CargoMesa') |
|||
mesa_diretora = baker.make('parlamentares.MesaDiretora') |
|||
mandato = baker.make( |
|||
'parlamentares.Mandato', |
|||
parlamentar=parlamentar, |
|||
legislatura=mesa_diretora.legislatura) |
|||
|
|||
composicao = ComposicaoMesa.objects.create( |
|||
parlamentar=parlamentar, |
|||
cargo=cargo, |
|||
mesa_diretora=mesa_diretora |
|||
) |
|||
|
|||
new_cargo = baker.make('parlamentares.CargoMesa') |
|||
|
|||
response = admin_client.post(reverse('sapl.parlamentares:composicaomesa_update', kwargs={'pk': composicao.id}), data={ |
|||
'parlamentar': parlamentar.id, |
|||
'cargo': new_cargo.id, |
|||
}) |
|||
|
|||
composicao.refresh_from_db() |
|||
assert composicao.cargo == new_cargo |
|||
@ -1,312 +0,0 @@ |
|||
{% extends "crud/detail.html" %} |
|||
{% load i18n %} |
|||
{% block actions %} {% endblock %} |
|||
|
|||
{% block detail_content %} |
|||
{% if sessoes|length == 0 %} |
|||
<div class="alert alert-danger alert-dismissible" role="alert"> |
|||
<b>{{legislatura_selecionada}}</b> não possui nenhuma Sessão Legislativa cadastrada.<br /> |
|||
Clique <a href="{% url 'sapl.parlamentares:sessaolegislativa_create' %}">aqui</a> para cadastrar uma nova. |
|||
</div> |
|||
|
|||
{% else %} |
|||
<div class="alert alert-danger alert-dismissible" id="div-error" role="alert" style="display: none"> |
|||
<button type="button" class="close" data-dismiss="alert" aria-label="Close"> |
|||
<span aria-hidden="true">×</span> |
|||
</button> |
|||
<b><span id="error-message"></span></b> |
|||
</div> |
|||
|
|||
<div class="alert alert-success alert-dismissible" id="div-success" style="display: none" role="alert"> |
|||
<button type="button" class="close" data-dismiss="alert" aria-label="Close"> |
|||
<span aria-hidden="true">×</span> |
|||
</button> |
|||
<b><span id="success-message"></span></b> |
|||
</div> |
|||
|
|||
<fieldset class="form-group"> |
|||
<legend>Escolha da Legislatura e da Sessão Legislativa</legend> |
|||
<div class="row"> |
|||
<div class="col-md-6"> |
|||
<label>Escolha uma Legislatura</label> |
|||
<select name="legislatura" id="id_legislatura" class="form-control"> |
|||
{% for l in legislaturas %} |
|||
<option value="{{l.id}}" {% if l == legislatura_selecionada %} selected {% endif %}> |
|||
{{l}} |
|||
</option> |
|||
{% endfor %} |
|||
</select> |
|||
</div> |
|||
<div class="col-md-6"> |
|||
<label>Escolha uma Sessão Legislativa</label> |
|||
<select name="sessao" id="id_sessao_legislativa" class="form-control"> |
|||
{% for s in sessoes %} |
|||
<option value="{{s.id}}" {% if s == sessao_selecionada %} selected {% endif %}> |
|||
{{s}} |
|||
</option> |
|||
{% endfor %} |
|||
</select> |
|||
</div> |
|||
</div> |
|||
</fieldset> |
|||
<br /> |
|||
<fieldset class="form-group"> |
|||
<legend>Escolha da Composição da Mesa Diretora</legend> |
|||
<div class="row"> |
|||
<div class="col-md-4"> |
|||
<label>Composição da Mesa Diretora</label> |
|||
<select multiple size="5" class="form-control" id="id_composicao_mesa" name="composicao_mesa"> |
|||
{% for p in composicao_mesa %} |
|||
<option value="{{p.id}}"> |
|||
{{p.parlamentar}} || {{p.cargo}} |
|||
</option> |
|||
{% endfor %} |
|||
</select> |
|||
</div> |
|||
|
|||
<div class="col-md-4" align="center"> |
|||
<br /><br /> |
|||
{% if perms.parlamentares.add_cargomesa %} |
|||
<input type="submit" style="display: none" name="Incluir" id="id_incluir" Value="Incluir" class="btn btn-primary" /> |
|||
{% endif %} |
|||
<br /> |
|||
<br /> |
|||
{% if perms.parlamentares.add_composicaomesa %} |
|||
<input type="submit" style="display: none" name="Excluir" id="id_excluir" Value="Excluir" class="btn btn-danger" /> |
|||
{% endif %} |
|||
</div> |
|||
|
|||
<div class="col-md-4"> |
|||
<label id='parlamentar-cargo-title' style="display: none">Parlamentar | Cargo</label> |
|||
<select class="form-control" name="parlamentar" id="id_parlamentar" style="display: none"> |
|||
{% for p in parlamentares %} |
|||
<option value="{{p.id}}">{{p.nome_parlamentar}}</option> |
|||
{% endfor %} |
|||
</select> |
|||
<br /> |
|||
<select class="form-control" name="cargo" id="id_cargo" style="display: none"> |
|||
{% for c in cargos_vagos %} |
|||
<option value="{{c.id}}">{{c}}</option> |
|||
{% endfor %} |
|||
</select> |
|||
</div> |
|||
|
|||
</div> |
|||
</fieldset> |
|||
{% endif %} |
|||
{% endblock detail_content %} |
|||
|
|||
|
|||
{% block extra_js %} |
|||
|
|||
<script language="Javascript"> |
|||
|
|||
//############################################################## |
|||
// Inicialização da View # |
|||
//############################################################## |
|||
|
|||
// Se a composicao estiver completa, deve-se esconder o botão e os |
|||
// campos de inserção |
|||
$(document).ready(function(){ |
|||
if($("#id_parlamentar").val() == null || $("#id_cargo").val() == null){ |
|||
$("#id_parlamentar").hide(); |
|||
$("#id_cargo").hide(); |
|||
$("#parlamentar-cargo-title").hide(); |
|||
$('#id_incluir').hide(); |
|||
} |
|||
else{ |
|||
$("#id_parlamentar").show(); |
|||
$("#id_cargo").show(); |
|||
$("#parlamentar-cargo-title").show(); |
|||
$('#id_incluir').show(); |
|||
} |
|||
|
|||
// Se a composição estiver vazia, deve-se esconder |
|||
// de Excluir |
|||
if (!$("#id_composicao_mesa option").val()){ |
|||
$("#id_excluir").hide() |
|||
} |
|||
else{ |
|||
$("#id_excluir").show() |
|||
} |
|||
}); |
|||
|
|||
//############################################################## |
|||
//# EVENT HANDLERS # |
|||
//############################################################## |
|||
|
|||
function errors_handler(msg){ |
|||
if (msg == null){ |
|||
$("#div-success").hide() |
|||
$("#div-error").hide() |
|||
$("#success-message").html('') |
|||
$("#error-message").html('') |
|||
} |
|||
else{ |
|||
if (msg[1] == 0){ |
|||
$("#div-error").show() |
|||
$("#error-message").html(msg[0]) |
|||
} |
|||
else{ |
|||
$("#div-success").show() |
|||
$("#success-message").html(msg[0]) |
|||
} |
|||
} |
|||
|
|||
} |
|||
|
|||
// Atualiza os campos após alguma operação de mudança da Legislatura/Sessao ou |
|||
// Inserção/Remoção |
|||
function altera_field(id_legislatura, id_sessao=null, msg=null){ |
|||
// Pega o novo valor dos campos modificados |
|||
var sessao_value = id_sessao |
|||
var legislatura_value = id_legislatura |
|||
|
|||
// Limpa os campos que serão atualizados |
|||
$("#id_sessao_legislativa option").remove(); |
|||
$("#id_composicao_mesa option").remove(); |
|||
$("#id_parlamentar option").remove(); |
|||
$("#id_cargo option").remove(); |
|||
|
|||
|
|||
$.get("{% url 'sapl.parlamentares:altera_field_mesa' %}", |
|||
{legislatura: legislatura_value, sessao: sessao_value}, |
|||
function(data) { |
|||
// Caso não venha nenhum dado da requisição, retorna null |
|||
if ($.isEmptyObject(data)){ |
|||
return null |
|||
} |
|||
|
|||
lista_sessoes = data['lista_sessoes']; |
|||
lista_composicao = data['lista_composicao']; |
|||
lista_parlamentares = data['lista_parlamentares']; |
|||
lista_cargos = data['lista_cargos']; |
|||
|
|||
// Atualiza a listagem dos campos |
|||
if (lista_sessoes != undefined) { |
|||
for (i = 0; i < lista_sessoes.length; i++) { |
|||
$('#id_sessao_legislativa').append('<option value="' + lista_sessoes[i][0] + '">' + lista_sessoes[i][1] + '</option>'); |
|||
} |
|||
} |
|||
|
|||
if (lista_composicao != null) { |
|||
for (i = 0; i < lista_composicao.length; i++) { |
|||
$('#id_composicao_mesa').append('<option value="' + lista_composicao[i][0] + '">' + lista_composicao[i][1] + ' || ' + lista_composicao[i][2] + '</option>'); |
|||
} |
|||
} |
|||
|
|||
// Caso ainda tenha parlamentares/cargos a serem inseridos, preenche a listagem com |
|||
// os disponíveis e garante que as ferramentas de inserção estejam disponíveis |
|||
if (lista_parlamentares != null && lista_parlamentares.length != 0 && lista_cargos.length != 0){ |
|||
$('#id_incluir').show() |
|||
$('#id_cargo').show(); |
|||
$('#id_parlamentar').show(); |
|||
$("#parlamentar-cargo-title").show(); |
|||
|
|||
for (i = 0; i < lista_parlamentares.length; i++) { |
|||
$('#id_parlamentar').append('<option value="' + lista_parlamentares[i][0] + '">' + lista_parlamentares[i][1] + '</option>'); |
|||
} |
|||
|
|||
for (i = 0; i < lista_cargos.length; i++) { |
|||
$('#id_cargo').append('<option value="' + lista_cargos[i][0] + '">' + lista_cargos[i][1] + '</option>'); |
|||
} |
|||
} |
|||
|
|||
// Caso contrário, esconde do usuário essas opções |
|||
else{ |
|||
$('#id_incluir').hide(); |
|||
$('#id_cargo').hide(); |
|||
$('#id_parlamentar').hide(); |
|||
$("#parlamentar-cargo-title").hide(); |
|||
} |
|||
|
|||
// Garante que o botão de remoção aparecerá, caso tenha |
|||
// algum parlamentar na composição |
|||
if (lista_composicao != null && lista_composicao.length != 0){ |
|||
$("#id_excluir").show() |
|||
} |
|||
else{ |
|||
$("#id_excluir").hide() |
|||
} |
|||
|
|||
// Garante que a Sessão atual será a selecionada previamente e, no caso em que |
|||
// o campo modificado seja o de Legislatura, que a Sessão seja a última daquela |
|||
// legislatura |
|||
$("#id_sessao_legislativa").val(data['sessao_selecionada']) |
|||
|
|||
// Caso haja algum erro que venha após a alteração da legislatura/sessao |
|||
// Essa mensagem de erro é prioridade |
|||
if (data['msg'][1] == 0){ |
|||
msg = data['msg'] |
|||
} |
|||
|
|||
errors_handler(msg) |
|||
|
|||
}); |
|||
} |
|||
|
|||
//############################################################# |
|||
//# EVENTS CATCH # |
|||
//############################################################# |
|||
$("#id_legislatura").change(function(){ |
|||
legislatura = $("#id_legislatura").val(); |
|||
altera_field(legislatura); |
|||
}); |
|||
|
|||
$("#id_sessao_legislativa").change(function(){ |
|||
legislatura = $("#id_legislatura").val(); |
|||
sessao = $("#id_sessao_legislativa").val(); |
|||
altera_field(legislatura, sessao); |
|||
}); |
|||
|
|||
$('#id_incluir').click(function(){ |
|||
$.ajax({ |
|||
data: {sessao: $("#id_sessao_legislativa").val(), |
|||
parlamentar: $("#id_parlamentar").val(), |
|||
cargo: $("#id_cargo").val()}, |
|||
type: 'POST', |
|||
url: "{% url 'sapl.parlamentares:insere_parlamentar_composicao' %}", |
|||
headers: { |
|||
'X-CSRFToken': getCookie('csrftoken') |
|||
}, |
|||
success: function(data){ |
|||
var msg = data['msg']; |
|||
legislatura = $("#id_legislatura").val(); |
|||
sessao = $("#id_sessao_legislativa").val(); |
|||
setTimeout(function(data){ |
|||
// Atualiza os campos após a inserção |
|||
altera_field(legislatura, sessao, msg) |
|||
}, 500) |
|||
}, |
|||
}); |
|||
}) |
|||
|
|||
$('#id_excluir').click(function(){ |
|||
// Pega o id do parlamentar que foi selecionado |
|||
selecionado = $("#id_composicao_mesa option:selected").val() |
|||
|
|||
if (selecionado){ |
|||
$.ajax({ |
|||
data: {composicao_mesa: selecionado}, |
|||
type: 'POST', |
|||
url: "{% url 'sapl.parlamentares:remove_parlamentar_composicao' %}", |
|||
headers: { |
|||
'X-CSRFToken': getCookie('csrftoken') |
|||
}, |
|||
success: function(data){ |
|||
var msg = data['msg']; |
|||
legislatura = $("#id_legislatura").val(); |
|||
sessao = $("#id_sessao_legislativa").val(); |
|||
|
|||
setTimeout(function(data){ |
|||
// Atualiza os campos após a remoção |
|||
altera_field(legislatura, sessao, msg) |
|||
}, 500) |
|||
}, |
|||
}); |
|||
} |
|||
}); |
|||
|
|||
</script> |
|||
|
|||
{% endblock %} |
|||
@ -0,0 +1,156 @@ |
|||
{% extends "crud/list.html" %} |
|||
{% load i18n common_tags crispy_forms_tags cropping %} |
|||
|
|||
{% block actions_search %} |
|||
<div class="actions search flex-grow-1 pr-3"> |
|||
{% if filter.form %} |
|||
{% crispy filter.form %} |
|||
{% endif %} |
|||
</div> |
|||
{% endblock actions_search %} |
|||
|
|||
{% block container_table_list %} |
|||
{% if perms.parlamentares.add_mesadiretora %} |
|||
{{ block.super }} |
|||
{% else %} |
|||
<div class="row"> |
|||
<div class="col-12"> |
|||
|
|||
<ul class="nav nav-tabs" role="tablist"> |
|||
{% for md in object_list %} |
|||
{% if request.GET.mesa == md.id|stringformat:"s" or not request.GET.mesa and forloop.first %} |
|||
<li class="nav-item" role="presentation"> |
|||
<button class="nav-link active" id="tab-mesa-{{ md.id }}-tab" data-toggle="tab" data-target="#tab-mesa-{{ md.id }}" type="button" role="tab" aria-controls="tab-mesa-{{ md.id }}" aria-selected="true">{{ md }}</button> |
|||
</li> |
|||
{% else %} |
|||
<li class="nav-item" role="presentation"> |
|||
<button class="nav-link" id="tab-mesa-{{ md.id }}-tab" data-toggle="tab" data-target="#tab-mesa-{{ md.id }}" type="button" role="tab" aria-controls="tab-mesa-{{ md.id }}" aria-selected="false">{{ md }}</button> |
|||
</li> |
|||
{% endif %} |
|||
{% endfor %} |
|||
</ul> |
|||
<div class="tab-content"> |
|||
{% for md in object_list %} |
|||
{% if request.GET.mesa == md.id|stringformat:"s" or not request.GET.mesa and forloop.first %} |
|||
<div class="lista-parlamentares tab-pane fade show active" id="tab-mesa-{{ md.id }}" role="tabpanel" aria-labelledby="tab-mesa-{{ md.id }}-tab"> |
|||
{% else %} |
|||
<div class="lista-parlamentares tab-pane fade" id="tab-mesa-{{ md.id }}" role="tabpanel" aria-labelledby="tab-mesa-{{ md.id }}-tab"> |
|||
{% endif %} |
|||
<i class="text-muted p-2 d-inline-block">(De {{md.data_inicio }} a {{ md.data_fim }})</i> |
|||
<a href="{% url 'sapl.parlamentares:mesadiretora_list' %}?mesa={{ md.id }}" class="btn btn-sm btn-link float-right mb-2"> |
|||
<i class="fas fa-external-link-alt"></i> |
|||
</a> |
|||
<table class="table table-striped table-hover table-link-ordering m-0 p-0"> |
|||
<thead> |
|||
<tr> |
|||
<th>Nome do Parlamentar</th> |
|||
<th>Partido</th> |
|||
<th>Cargo</th> |
|||
</tr> |
|||
</thead> |
|||
<tbody> |
|||
{% for composicao in md.composicaomesa_set.all %} |
|||
<tr> |
|||
<td> |
|||
<div id="d-flex"> |
|||
{% if composicao.parlamentar.fotografia %} |
|||
<img class="img-fluid img-thumbnail" src="{% cropped_thumbnail composicao.parlamentar "cropping"%}"> |
|||
{% endif %} |
|||
<a class="pl-2" href="{% url 'sapl.parlamentares:parlamentar_detail' composicao.parlamentar.pk %}"> |
|||
{{composicao.parlamentar.nome_parlamentar}}</a> |
|||
</div> |
|||
</td> |
|||
<td>{{composicao.parlamentar.filiacao_atual}}</td> |
|||
<td>{{composicao.cargo}}</td> |
|||
</tr> |
|||
{% endfor %} |
|||
</tbody> |
|||
</table> |
|||
</div> |
|||
{% endfor %} |
|||
</div> |
|||
</div> |
|||
</div> |
|||
{% endif %} |
|||
|
|||
{% endblock container_table_list %} |
|||
|
|||
{% block extra_js %} |
|||
<script> |
|||
(function () { |
|||
// Suporte nativo a :has() — o CSS cuida de tudo, JS não é necessário |
|||
if (typeof CSS !== 'undefined' && CSS.supports && CSS.supports('selector(:has(*))')) return; |
|||
|
|||
var mq = window.matchMedia('(max-width: 767px)'); |
|||
|
|||
function collapse(tabs) { |
|||
tabs.classList.remove('nav-tabs--open'); |
|||
[].forEach.call(tabs.querySelectorAll('.nav-item'), function (item) { |
|||
item.style.display = item.querySelector('.nav-link.active') ? 'block' : 'none'; |
|||
}); |
|||
} |
|||
|
|||
function expand(tabs) { |
|||
[].forEach.call(tabs.querySelectorAll('.nav-item'), function (item) { |
|||
item.style.display = 'block'; |
|||
}); |
|||
tabs.classList.add('nav-tabs--open'); |
|||
} |
|||
|
|||
function init() { |
|||
[].forEach.call(document.querySelectorAll('.nav-tabs'), function (tabs) { |
|||
if (tabs._dropdownBound) return; |
|||
tabs._dropdownBound = true; |
|||
|
|||
// Expande ao clicar no container (apenas quando fechado) |
|||
tabs.addEventListener('click', function () { |
|||
if (!mq.matches || tabs.classList.contains('nav-tabs--open')) return; |
|||
expand(tabs); |
|||
setTimeout(function () { |
|||
document.addEventListener('click', function onOutside(ev) { |
|||
if (!tabs.contains(ev.target)) { |
|||
collapse(tabs); |
|||
document.removeEventListener('click', onOutside); |
|||
} |
|||
}); |
|||
}, 0); |
|||
}); |
|||
|
|||
// Colapsa ao selecionar uma aba (apenas quando aberto) |
|||
[].forEach.call(tabs.querySelectorAll('.nav-link'), function (link) { |
|||
link.addEventListener('click', function () { |
|||
if (!tabs.classList.contains('nav-tabs--open')) return; |
|||
// Aguarda Bootstrap atualizar a classe .active |
|||
setTimeout(function () { collapse(tabs); }, 50); |
|||
}); |
|||
}); |
|||
}); |
|||
|
|||
// Estado inicial e ao redimensionar |
|||
function applyState(matches) { |
|||
[].forEach.call(document.querySelectorAll('.nav-tabs'), function (tabs) { |
|||
tabs.classList.remove('nav-tabs--open'); |
|||
[].forEach.call(tabs.querySelectorAll('.nav-item'), function (item) { |
|||
item.style.display = ''; |
|||
}); |
|||
if (matches) collapse(tabs); |
|||
}); |
|||
} |
|||
|
|||
applyState(mq.matches); |
|||
|
|||
if (mq.addEventListener) { |
|||
mq.addEventListener('change', function (e) { applyState(e.matches); }); |
|||
} else { |
|||
mq.addListener(function (e) { applyState(e.matches); }); |
|||
} |
|||
} |
|||
|
|||
if (document.readyState === 'loading') { |
|||
document.addEventListener('DOMContentLoaded', init); |
|||
} else { |
|||
init(); |
|||
} |
|||
}()); |
|||
</script> |
|||
{% endblock extra_js %} |
|||
@ -1,146 +0,0 @@ |
|||
{% extends "crud/detail.html" %} |
|||
{% load i18n cropping%} |
|||
{% block actions %} {% endblock %} |
|||
|
|||
{% block detail_content %} |
|||
<form method="POST"> |
|||
{% csrf_token %} |
|||
<fieldset class="form-group"> |
|||
<legend>Escolha da Legislatura e da Sessão Legislativa</legend> |
|||
<div class="row"> |
|||
<div class="col-md-6"> |
|||
<label>Escolha uma Legislatura</label> |
|||
<select name="legislatura" id="id_legislatura" class="form-control"> |
|||
{% for l in legislaturas %} |
|||
<option value="{{l.id}}" {% if l == legislatura_selecionada %} selected {% endif %}> |
|||
{{l}} |
|||
</option> |
|||
{% endfor %} |
|||
</select> |
|||
</div> |
|||
<div class="col-md-6"> |
|||
<label>Escolha uma Sessão Legislativa</label> |
|||
<select name="sessao" id="id_sessao_legislativa" class="form-control"> |
|||
{% for s in sessoes %} |
|||
<option value="{{s.id}}" {% if s == sessao_selecionada %} selected {% endif %}> |
|||
{{s}} |
|||
</option> |
|||
{% endfor %} |
|||
</select> |
|||
</div> |
|||
</div> |
|||
</fieldset> |
|||
<br /> |
|||
<fieldset class="form-group lista-parlamentares"> |
|||
<legend>Composição da Mesa Diretora</legend> |
|||
<table id="tabela-composicao" class="table table-striped table-hover table-link-ordering"> |
|||
<thead> |
|||
<tr> |
|||
<th></th> |
|||
<th>Nome do Parlamentar</th> |
|||
<th>Partido</th> |
|||
<th>Cargo</th> |
|||
</tr> |
|||
</thead> |
|||
<tbody> |
|||
{% for p in composicao_mesa %} |
|||
<tr> |
|||
{% if p.parlamentar.fotografia %} |
|||
<td> |
|||
<div id="w-100"> |
|||
<img class="img-fluid img-thumbnail" src="{% cropped_thumbnail p.parlamentar "cropping"%}"> |
|||
</div> |
|||
{% else %} |
|||
<td></td> |
|||
{% endif %} |
|||
<td><a href="{% url 'sapl.parlamentares:parlamentar_detail' p.parlamentar.pk %}">{{p.parlamentar.nome_parlamentar}}</a></td> |
|||
<td>{{p.parlamentar.filiacao_atual}}</td> |
|||
<td>{{p.cargo}}</td> |
|||
</tr> |
|||
{% endfor %} |
|||
</tbody> |
|||
</table> |
|||
</fieldset> |
|||
</form> |
|||
{% endblock detail_content %} |
|||
|
|||
{% block extra_js %} |
|||
|
|||
<script language="Javascript"> |
|||
|
|||
//############################################################## |
|||
//# USEFUL FUNCTIONS # |
|||
//############################################################## |
|||
function retorna_imagem(url){ |
|||
if (url != null){ |
|||
image_component = '<img class="img-fluid img-thumbnail" src="' + url + '">' |
|||
return image_component |
|||
} |
|||
|
|||
else{ |
|||
return '' |
|||
} |
|||
} |
|||
|
|||
//############################################################## |
|||
//# EVENT HANDLERS # |
|||
//############################################################## |
|||
|
|||
function altera_field(id_legislatura, id_sessao=null){ |
|||
// Pega o novo valor do campo que foi modificado (Sessao/Legislatura) |
|||
var sessao_value = id_sessao |
|||
var legislatura_value = id_legislatura |
|||
|
|||
// Limpa o campo que será atualizado |
|||
$("#id_sessao_legislativa option").remove(); |
|||
$("#tabela-composicao tbody").empty(); |
|||
|
|||
$.get("/mesa-diretora/altera-field-mesa-public-view", |
|||
{legislatura: legislatura_value, sessao: sessao_value}, |
|||
function(data) { |
|||
// Caso não venha nenhum dado da requisição, retorna null |
|||
if ($.isEmptyObject(data)){ |
|||
return null |
|||
} |
|||
|
|||
lista_sessoes = data['lista_sessoes']; |
|||
lista_parlamentares = data['lista_parlamentares']; |
|||
lista_cargos = data['lista_cargos']; |
|||
lista_fotos = data['lista_fotos'] |
|||
lista_partidos = data['lista_partidos'] |
|||
|
|||
// Atualiza a listagem de sessões |
|||
for (i = 0; i < lista_sessoes.length; i++) { |
|||
$('#id_sessao_legislativa').append('<option value="' + lista_sessoes[i][0] + '">' + lista_sessoes[i][1] + '</option>'); |
|||
} |
|||
|
|||
// Atualiza a tabela de composição |
|||
for (i = 0; i < lista_parlamentares.length; i++) { |
|||
$("#tabela-composicao tbody").append('<tr> <td> <div class="w-100">' + retorna_imagem(lista_fotos[i]) +' </div> </td> <td><a href="/parlamentar/' + lista_parlamentares[i][0] + '">' + lista_parlamentares[i][1] + '</a></td> <td>' + lista_partidos[i] + '</td> <td>'+ lista_cargos[i][1] + '</td> </tr>'); |
|||
} |
|||
|
|||
// Garante que a Sessão atual será a selecionada previamente e, no caso em que |
|||
// o campo modificado seja o de Legislatura, que a Sessão seja a última daquela |
|||
// legislatura |
|||
$("#id_sessao_legislativa").val(data['sessao_selecionada']) |
|||
|
|||
}); |
|||
} |
|||
|
|||
//############################################################# |
|||
//# EVENTS CATCH # |
|||
//############################################################# |
|||
$("#id_legislatura").change(function(){ |
|||
legislatura = $("#id_legislatura").val(); |
|||
altera_field(legislatura); |
|||
}); |
|||
|
|||
$("#id_sessao_legislativa").change(function(){ |
|||
legislatura = $("#id_legislatura").val(); |
|||
sessao = $("#id_sessao_legislativa").val(); |
|||
altera_field(legislatura, sessao); |
|||
}); |
|||
|
|||
</script> |
|||
|
|||
{% endblock %} |
|||
@ -0,0 +1,5 @@ |
|||
{% load i18n common_tags %} |
|||
- title: {% trans 'Mesa Diretora' %} |
|||
url: sapl.parlamentares:mesadiretora_detail |
|||
- title: {% trans 'Composição da Mesa' %} |
|||
url: sapl.parlamentares:composicaomesa_list |
|||
Loading…
Reference in new issue