Browse Source

Merge branch '3.1.x'

pull/1828/merge
João Pedro Sconetto 8 years ago
parent
commit
c997309be3
  1. 6
      .travis.yml
  2. 2
      docker-compose.yml
  3. 6
      docs/instalacao31.rst
  4. 4
      release.sh
  5. 2
      requirements/requirements.txt
  6. 3
      sapl/base/forms.py
  7. 20
      sapl/base/migrations/0017_appconfig_cronometro_consideracoes.py
  8. 5
      sapl/base/models.py
  9. 3
      sapl/comissoes/forms.py
  10. 1
      sapl/legacy/migracao.py
  11. 12
      sapl/legacy/migracao_dados.py
  12. 5
      sapl/legacy/scripts/exporta_zope/exporta_zope.py
  13. 20
      sapl/painel/migrations/0002_auto_20180523_1430.py
  14. 3
      sapl/painel/models.py
  15. 1
      sapl/painel/views.py
  16. 2
      sapl/parlamentares/forms.py
  17. 115
      sapl/protocoloadm/forms.py
  18. 8
      sapl/protocoloadm/urls.py
  19. 48
      sapl/protocoloadm/views.py
  20. 3
      sapl/relatorios/views.py
  21. 4
      sapl/sessao/forms.py
  22. 14
      sapl/sessao/views.py
  23. 2
      sapl/templates/base/layouts.yaml
  24. 30
      sapl/templates/painel/index.html
  25. 12
      sapl/templates/parlamentares/layouts.yaml
  26. 2
      sapl/templates/protocoloadm/protocoloadm_detail.html
  27. 6
      sapl/templates/sessao/blocos_resumo/conteudo_multimidia.html
  28. 92
      sapl/templates/sessao/painel.html
  29. 11
      sapl/utils.py
  30. 10
      scripts/django/check_migrations.sh
  31. 4
      scripts/django/check_qa.sh
  32. 2
      scripts/django/fix_qa.sh
  33. 3
      scripts/django/gerar_grafico_apps.sh
  34. 5
      scripts/django/reset_all_migrations.sh
  35. 5
      scripts/django/test_and_check_qa.sh
  36. 2
      scripts/hooks/pre-commit
  37. 14
      scripts/redbaron.py
  38. 2
      setup.py

6
.travis.yml

@ -1,7 +1,7 @@
language: python language: python
python: python:
- 3.4.3 - 3.5
services: services:
- postgresql - postgresql
@ -14,13 +14,13 @@ before_script:
- cp sapl/.env_test sapl/.env - cp sapl/.env_test sapl/.env
- psql -c "CREATE USER sapl WITH PASSWORD 'sapl'" -U postgres; - psql -c "CREATE USER sapl WITH PASSWORD 'sapl'" -U postgres;
- psql -c "CREATE DATABASE sapl OWNER sapl;" -U postgres - psql -c "CREATE DATABASE sapl OWNER sapl;" -U postgres
- ./check_migrations.sh - ./scripts/django/check_migrations.sh
script: script:
- ./manage.py migrate - ./manage.py migrate
- ./manage.py bower install - ./manage.py bower install
- py.test --create-db - py.test --create-db
# - ./test_and_check_qa.sh # - ./scripts/django/test_and_check_qa.sh
addons: addons:
hosts: hosts:

2
docker-compose.yml

@ -11,7 +11,7 @@ sapldb:
ports: ports:
- "5432:5432" - "5432:5432"
sapl: sapl:
image: interlegis/sapl:3.1.77 image: interlegis/sapl:3.1.81
restart: always restart: always
environment: environment:
ADMIN_PASSWORD: interlegis ADMIN_PASSWORD: interlegis

6
docs/instalacao31.rst

@ -28,10 +28,10 @@ Instalar as seguintes dependências do sistema::
pkg-config postgresql postgresql-contrib pgadmin3 python-psycopg2 \ pkg-config postgresql postgresql-contrib pgadmin3 python-psycopg2 \
software-properties-common build-essential libxml2-dev libjpeg-dev \ software-properties-common build-essential libxml2-dev libjpeg-dev \
libmysqlclient-dev libssl-dev libffi-dev libxslt1-dev python3-setuptools \ libmysqlclient-dev libssl-dev libffi-dev libxslt1-dev python3-setuptools \
python3-pip curl poppler-utils antiword default-jre python3-pip curl poppler-utils antiword default-jre python3-venv
sudo -i sudo -i
curl -sL https://deb.nodesource.com/setup_6.x | bash - curl -sL https://deb.nodesource.com/setup_8.x | bash -
exit exit
sudo apt-get install nodejs sudo apt-get install nodejs
@ -184,6 +184,8 @@ Copie a chave que aparecerá, edite o arquivo .env e altere o valor do parâmetr
* Instalar as dependências do ``bower``:: * Instalar as dependências do ``bower``::
eval $(echo "sudo chown -R $USER:$USER /home/$USER/") eval $(echo "sudo chown -R $USER:$USER /home/$USER/")
sudo chown -R $USER:$GROUP ~/.npm
sudo chown -R $USER:$GROUP ~/.config
./manage.py bower install ./manage.py bower install
* Atualizar e/ou criar as tabelas da base de dados para refletir o modelo da versão clonada:: * Atualizar e/ou criar as tabelas da base de dados para refletir o modelo da versão clonada::

4
release.sh

@ -29,7 +29,7 @@ function commit_and_push {
} }
case "$1" in case "$1" in
--dryrun) --dry-run)
echo "Dry run" echo "Dry run"
bump_version bump_version
echo "done." echo "done."
@ -37,7 +37,7 @@ case "$1" in
exit 0 exit 0
;; ;;
--a) --publish)
echo "generating release" echo "generating release"
bump_version bump_version
commit_and_push commit_and_push

2
requirements/requirements.txt

@ -22,7 +22,7 @@ easy-thumbnails==2.3
django-image-cropping==1.1.0 django-image-cropping==1.1.0
git+git://github.com/interlegis/trml2pdf.git git+git://github.com/interlegis/trml2pdf.git
libsass==0.11.1 libsass==0.11.1
psycopg2==2.7.3 psycopg2-binary==2.7.4
python-decouple==3.0 python-decouple==3.0
pytz==2016.4 pytz==2016.4
pyyaml==3.11 pyyaml==3.11

3
sapl/base/forms.py

@ -834,6 +834,7 @@ class ConfiguracoesAppForm(ModelForm):
'cronometro_discurso', 'cronometro_discurso',
'cronometro_aparte', 'cronometro_aparte',
'cronometro_ordem', 'cronometro_ordem',
'cronometro_consideracoes',
'mostrar_brasao_painel', 'mostrar_brasao_painel',
'receber_recibo_proposicao'] 'receber_recibo_proposicao']
@ -842,6 +843,8 @@ class ConfiguracoesAppForm(ModelForm):
self.fields['cronometro_discurso'].widget.attrs['class'] = 'cronometro' self.fields['cronometro_discurso'].widget.attrs['class'] = 'cronometro'
self.fields['cronometro_aparte'].widget.attrs['class'] = 'cronometro' self.fields['cronometro_aparte'].widget.attrs['class'] = 'cronometro'
self.fields['cronometro_ordem'].widget.attrs['class'] = 'cronometro' self.fields['cronometro_ordem'].widget.attrs['class'] = 'cronometro'
self.fields['cronometro_consideracoes'].widget.attrs['class'] = 'cronometro'
def clean_mostrar_brasao_painel(self): def clean_mostrar_brasao_painel(self):
mostrar_brasao_painel = self.cleaned_data.get( mostrar_brasao_painel = self.cleaned_data.get(

20
sapl/base/migrations/0017_appconfig_cronometro_consideracoes.py

@ -0,0 +1,20 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9.13 on 2018-05-23 17:30
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('base', '0016_auto_20180326_1840'),
]
operations = [
migrations.AddField(
model_name='appconfig',
name='cronometro_consideracoes',
field=models.TimeField(blank=True, null=True, verbose_name='Cronômetro de Considerações Finais'),
),
]

5
sapl/base/models.py

@ -113,6 +113,11 @@ class AppConfig(models.Model):
blank=True, blank=True,
null=True) null=True)
cronometro_consideracoes = models.TimeField(
verbose_name=_('Cronômetro de Considerações Finais'),
blank=True,
null=True)
mostrar_brasao_painel = models.BooleanField( mostrar_brasao_painel = models.BooleanField(
default=False, default=False,
verbose_name=_('Mostrar brasão da Casa no painel?')) verbose_name=_('Mostrar brasão da Casa no painel?'))

3
sapl/comissoes/forms.py

@ -241,6 +241,9 @@ class ComissaoForm(forms.ModelForm):
if not self.is_valid(): if not self.is_valid():
return self.cleaned_data return self.cleaned_data
if len(self.cleaned_data['nome']) > 50:
msg = _('Nome da Comissão deve ter no máximo 50 caracteres.')
raise ValidationError(msg)
if self.cleaned_data['data_extincao']: if self.cleaned_data['data_extincao']:
if (self.cleaned_data['data_extincao'] < if (self.cleaned_data['data_extincao'] <
self.cleaned_data['data_criacao']): self.cleaned_data['data_criacao']):

1
sapl/legacy/migracao.py

@ -28,6 +28,7 @@ def migrar(interativo=False):
migrar_usuarios(REPO.working_dir) migrar_usuarios(REPO.working_dir)
migrar_documentos(REPO) migrar_documentos(REPO)
gravar_marco() gravar_marco()
compactar_media()
def compactar_media(): def compactar_media():

12
sapl/legacy/migracao_dados.py

@ -1210,10 +1210,9 @@ def adjust_autor(new, old):
break break
if old.col_username: if old.col_username:
user_model = get_user_model() user, created = get_user_model().objects.get_or_create(
if not user_model.objects.filter(username=old.col_username).exists(): username=old.col_username)
# cria um novo ususaŕio para o autor if created:
user = user_model(username=old.col_username)
# gera uma senha inutilizável, que precisará ser trocada # gera uma senha inutilizável, que precisará ser trocada
user.set_password(None) user.set_password(None)
with reversion.create_revision(): with reversion.create_revision():
@ -1221,8 +1220,9 @@ def adjust_autor(new, old):
reversion.set_comment( reversion.set_comment(
'Usuário criado pela migração para o autor {}'.format( 'Usuário criado pela migração para o autor {}'.format(
old.cod_autor)) old.cod_autor))
grupo_autor = Group.objects.get(name="Autor") grupo_autor = Group.objects.get(name="Autor")
user.groups.add(grupo_autor) user.groups.add(grupo_autor)
new.user = user
def adjust_comissao(new, old): def adjust_comissao(new, old):

5
sapl/legacy/scripts/exporta_zope/exporta_zope.py

@ -151,13 +151,14 @@ enumerate_properties = partial(enumerate_by_key_list,
def enumerate_btree(folder): def enumerate_btree(folder):
contagem_esperada = folder['_count'].value contagem_esperada = folder['_count'].value
tree = folder['_tree'] tree = folder['_tree']
contagem_real = 0 # para o caso em que não haja itens
for contagem_real, (id, obj) in enumerate(tree.iteritems(), start=1): for contagem_real, (id, obj) in enumerate(tree.iteritems(), start=1):
obj, meta_type = br(obj), type(obj).__name__ obj, meta_type = br(obj), type(obj).__name__
yield id, obj, meta_type yield id, obj, meta_type
# verificação de consistência # verificação de consistência
if contagem_esperada != contagem_real: if contagem_esperada != contagem_real:
print('ATENÇÃO: contagens diferentes na btree: ' print('ATENÇÃO: contagens diferentes na btree: '
'{} esperada: {} real: {}'.format(folder, '{} esperada: {} real: {}'.format(folder['title'],
contagem_esperada, contagem_esperada,
contagem_real)) contagem_real))
@ -362,7 +363,7 @@ def dump_sapl(sigla):
destino.mkdir(parents=True) destino.mkdir(parents=True)
repo = git.Repo.init(destino) repo = git.Repo.init(destino)
if TAG_ZOPE in repo.tags: if TAG_ZOPE in repo.tags:
print('A exportação de documentos já está feita -- abortando') print('{}: A exportação de documentos já está feita -- abortando'.format(sigla))
return return
repo_execute(repo, 'git annex init') repo_execute(repo, 'git annex init')

20
sapl/painel/migrations/0002_auto_20180523_1430.py

@ -0,0 +1,20 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9.13 on 2018-05-23 17:30
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('painel', '0001_initial'),
]
operations = [
migrations.AlterField(
model_name='cronometro',
name='tipo',
field=models.CharField(choices=[('A', 'Aparte'), ('D', 'Discurso'), ('O', 'Ordem do dia'), ('C', 'Considerações finais')], max_length=1, verbose_name='Tipo Cronômetro'),
),
]

3
sapl/painel/models.py

@ -26,7 +26,8 @@ class Cronometro(models.Model):
CRONOMETRO_TYPES = ( CRONOMETRO_TYPES = (
('A', _('Aparte')), ('A', _('Aparte')),
('D', _('Discurso')), ('D', _('Discurso')),
('O', _('Ordem do dia')) ('O', _('Ordem do dia')),
('C', _('Considerações finais'))
) )
CRONOMETRO_STATUS = ( CRONOMETRO_STATUS = (

1
sapl/painel/views.py

@ -464,6 +464,7 @@ def get_dados_painel(request, pk):
'cronometro_aparte': get_cronometro_status(request, 'aparte'), 'cronometro_aparte': get_cronometro_status(request, 'aparte'),
'cronometro_discurso': get_cronometro_status(request, 'discurso'), 'cronometro_discurso': get_cronometro_status(request, 'discurso'),
'cronometro_ordem': get_cronometro_status(request, 'ordem'), 'cronometro_ordem': get_cronometro_status(request, 'ordem'),
'cronometro_consideracoes': get_cronometro_status(request, 'consideracoes'),
'status_painel': sessao.painel_aberto, 'status_painel': sessao.painel_aberto,
'brasao': brasao 'brasao': brasao
} }

2
sapl/parlamentares/forms.py

@ -321,7 +321,7 @@ class FrenteForm(ModelForm):
frente = super(FrenteForm, self).save(commit) frente = super(FrenteForm, self).save(commit)
content_type = ContentType.objects.get_for_model(Frente) content_type = ContentType.objects.get_for_model(Frente)
object_id = frente.pk object_id = frente.pk
tipo = TipoAutor.objects.get(descricao='Frente Parlamentar') tipo = TipoAutor.objects.get(descricao__icontains='Frente')
Autor.objects.create( Autor.objects.create(
content_type=content_type, content_type=content_type,
object_id=object_id, object_id=object_id,

115
sapl/protocoloadm/forms.py

@ -757,3 +757,118 @@ class DocumentoAdministrativoForm(ModelForm):
row6, row7)) row6, row7))
super(DocumentoAdministrativoForm, self).__init__( super(DocumentoAdministrativoForm, self).__init__(
*args, **kwargs) *args, **kwargs)
class DesvincularDocumentoForm(ModelForm):
numero = forms.CharField(required=True,
label=DocumentoAdministrativo._meta.
get_field('numero').verbose_name
)
ano = forms.ChoiceField(required=True,
label=DocumentoAdministrativo._meta.
get_field('ano').verbose_name,
choices=RANGE_ANOS,
widget=forms.Select(attrs={'class': 'selector'}))
def clean(self):
super(DesvincularDocumentoForm, self).clean()
cleaned_data = self.cleaned_data
if not self.is_valid():
return cleaned_data
numero = cleaned_data['numero']
ano = cleaned_data['ano']
tipo = cleaned_data['tipo']
try:
documento = DocumentoAdministrativo.objects.get(numero=numero, ano=ano, tipo=tipo)
if not documento.protocolo:
raise forms.ValidationError(
_("%s %s/%s não se encontra vinculado a nenhum protocolo" % (tipo, numero, ano)))
except ObjectDoesNotExist:
raise forms.ValidationError(
_("%s %s/%s não existe" % (tipo, numero, ano)))
return cleaned_data
class Meta:
model = DocumentoAdministrativo
fields = ['tipo',
'numero',
'ano',
]
def __init__(self, *args, **kwargs):
row1 = to_row(
[('numero', 4),
('ano', 4),
('tipo', 4)])
self.helper = FormHelper()
self.helper.layout = Layout(
Fieldset(_('Identificação do Documento'),
row1,
HTML("&nbsp;"),
form_actions(label='Desvincular')
)
)
super(DesvincularDocumentoForm, self).__init__(
*args, **kwargs)
class DesvincularMateriaForm(forms.Form):
numero = forms.CharField(required=True,
label=_('Número da Matéria'))
ano = forms.ChoiceField(required=True,
label=_('Ano da Matéria'),
choices=RANGE_ANOS,
widget=forms.Select(attrs={'class': 'selector'}))
tipo = forms.ModelChoiceField(label=_('Tipo de Matéria'),
required=True,
queryset=TipoMateriaLegislativa.objects.all(),
empty_label='------')
def clean(self):
super(DesvincularMateriaForm, self).clean()
cleaned_data = self.cleaned_data
if not self.is_valid():
return cleaned_data
numero = cleaned_data['numero']
ano = cleaned_data['ano']
tipo = cleaned_data['tipo']
try:
materia = MateriaLegislativa.objects.get(numero=numero, ano=ano, tipo=tipo)
if not materia.numero_protocolo:
raise forms.ValidationError(
_("%s %s/%s não se encontra vinculada a nenhum protocolo" % (tipo, numero, ano)))
except ObjectDoesNotExist:
raise forms.ValidationError(
_("%s %s/%s não existe" % (tipo, numero, ano)))
return cleaned_data
def __init__(self, *args, **kwargs):
super(DesvincularMateriaForm, self).__init__(*args, **kwargs)
row1 = to_row(
[('numero', 4),
('ano', 4),
('tipo', 4)])
self.helper = FormHelper()
self.helper.layout = Layout(
Fieldset(_('Identificação da Matéria'),
row1,
HTML("&nbsp;"),
form_actions(label='Desvincular')
)
)

8
sapl/protocoloadm/urls.py

@ -15,7 +15,9 @@ from sapl.protocoloadm.views import (AnularProtocoloAdmView,
TipoDocumentoAdministrativoCrud, TipoDocumentoAdministrativoCrud,
TramitacaoAdmCrud, TramitacaoAdmCrud,
atualizar_numero_documento, atualizar_numero_documento,
doc_texto_integral) doc_texto_integral,
DesvincularDocumentoView,
DesvincularMateriaView)
from .apps import AppConfig from .apps import AppConfig
@ -61,6 +63,10 @@ urlpatterns_protocolo = [
url(r'^protocoloadm/anular-protocolo', url(r'^protocoloadm/anular-protocolo',
AnularProtocoloAdmView.as_view(), name='anular_protocolo'), AnularProtocoloAdmView.as_view(), name='anular_protocolo'),
url(r'^protocoloadm/desvincular-documento',
DesvincularDocumentoView.as_view(), name='desvincular_documento'),
url(r'^protocoloadm/desvincular-materia',
DesvincularMateriaView.as_view(), name='desvincular_materia'),
url(r'^protocoloadm/protocolar-mat', url(r'^protocoloadm/protocolar-mat',
ProtocoloMateriaView.as_view(), name='protocolar_mat'), ProtocoloMateriaView.as_view(), name='protocolar_mat'),

48
sapl/protocoloadm/views.py

@ -13,6 +13,7 @@ from django.utils import timezone
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from django.views.generic import CreateView, ListView from django.views.generic import CreateView, ListView
from django.views.generic.base import RedirectView, TemplateView from django.views.generic.base import RedirectView, TemplateView
from django.views.generic.edit import FormView
from django_filters.views import FilterView from django_filters.views import FilterView
import sapl import sapl
@ -30,7 +31,7 @@ from .forms import (AnularProcoloAdmForm, DocumentoAcessorioAdministrativoForm,
DocumentoAdministrativoFilterSet, DocumentoAdministrativoFilterSet,
DocumentoAdministrativoForm, ProtocoloDocumentForm, DocumentoAdministrativoForm, ProtocoloDocumentForm,
ProtocoloFilterSet, ProtocoloMateriaForm, ProtocoloFilterSet, ProtocoloMateriaForm,
TramitacaoAdmEditForm, TramitacaoAdmForm) TramitacaoAdmEditForm, TramitacaoAdmForm, DesvincularDocumentoForm, DesvincularMateriaForm)
from .models import (DocumentoAcessorioAdministrativo, DocumentoAdministrativo, from .models import (DocumentoAcessorioAdministrativo, DocumentoAdministrativo,
StatusTramitacaoAdministrativo, StatusTramitacaoAdministrativo,
TipoDocumentoAdministrativo, TramitacaoAdministrativo) TipoDocumentoAdministrativo, TramitacaoAdministrativo)
@ -451,10 +452,11 @@ class ProtocoloMateriaView(PermissionRequiredMixin, CreateView):
if not protocolo.numero: if not protocolo.numero:
protocolo.numero = (numero['numero__max'] + 1) if numero['numero__max'] else 1 protocolo.numero = (numero['numero__max'] + 1) if numero['numero__max'] else 1
if protocolo.numero < (numero['numero__max'] + 1): if numero['numero__max']:
msg = _('Número de protocolo deve ser maior que {}').format(numero['numero__max']) if protocolo.numero < (numero['numero__max'] + 1):
messages.add_message(self.request, messages.ERROR, msg) msg = _('Número de protocolo deve ser maior que {}').format(numero['numero__max'])
return self.render_to_response(self.get_context_data()) messages.add_message(self.request, messages.ERROR, msg)
return self.render_to_response(self.get_context_data())
protocolo.ano = timezone.now().year protocolo.ano = timezone.now().year
protocolo.data = timezone.now().date() protocolo.data = timezone.now().date()
protocolo.hora = timezone.now().time() protocolo.hora = timezone.now().time()
@ -720,3 +722,39 @@ def atualizar_numero_documento(request):
{'numero': 1, 'ano': ano}) {'numero': 1, 'ano': ano})
return response return response
class DesvincularDocumentoView(PermissionRequiredMixin, CreateView):
template_name = 'protocoloadm/anular_protocoloadm.html'
form_class = DesvincularDocumentoForm
form_valid_message = _('Documento desvinculado com sucesso!')
permission_required = ('protocoloadm.action_anular_protocolo', )
def get_success_url(self):
return reverse('sapl.protocoloadm:protocolo')
def form_valid(self, form):
documento = DocumentoAdministrativo.objects.get(numero=form.cleaned_data['numero'],
ano=form.cleaned_data['ano'],
tipo=form.cleaned_data['tipo'])
documento.protocolo = None
documento.save()
return redirect(self.get_success_url())
class DesvincularMateriaView(PermissionRequiredMixin, FormView):
template_name = 'protocoloadm/anular_protocoloadm.html'
form_class = DesvincularMateriaForm
form_valid_message = _('Matéria desvinculado com sucesso!')
permission_required = ('protocoloadm.action_anular_protocolo', )
def get_success_url(self):
return reverse('sapl.protocoloadm:protocolo')
def form_valid(self, form):
materia = MateriaLegislativa.objects.get(numero=form.cleaned_data['numero'],
ano=form.cleaned_data['ano'],
tipo=form.cleaned_data['tipo'])
materia.numero_protocolo = None
materia.save()
return redirect(self.get_success_url())

3
sapl/relatorios/views.py

@ -795,7 +795,8 @@ def relatorio_sessao_plenaria(request, pk):
for idx in range(len(lst_expedientes)): for idx in range(len(lst_expedientes)):
txt_expedientes = lst_expedientes[idx]['txt_expediente'] txt_expedientes = lst_expedientes[idx]['txt_expediente']
txt_expedientes = TrocaTag(txt_expedientes, '<table', 'table>', 6, 6, 'expedientes') txt_expedientes = TrocaTag(txt_expedientes, '<table', 'table>', 6, 6,
'expedientes', '</para><blockTable style = "', 'blockTable><para>')
lst_expedientes[idx]['txt_expediente'] = txt_expedientes lst_expedientes[idx]['txt_expediente'] = txt_expedientes
pdf = pdf_sessao_plenaria_gerar.principal( pdf = pdf_sessao_plenaria_gerar.principal(

4
sapl/sessao/forms.py

@ -124,7 +124,7 @@ class BancadaForm(ModelForm):
bancada = super(BancadaForm, self).save(commit) bancada = super(BancadaForm, self).save(commit)
content_type = ContentType.objects.get_for_model(Bancada) content_type = ContentType.objects.get_for_model(Bancada)
object_id = bancada.pk object_id = bancada.pk
tipo = TipoAutor.objects.get(descricao='Bancada Parlamentar') tipo = TipoAutor.objects.get(descricao__icontains='Bancada')
Autor.objects.create( Autor.objects.create(
content_type=content_type, content_type=content_type,
object_id=object_id, object_id=object_id,
@ -159,7 +159,7 @@ class BlocoForm(ModelForm):
bloco = super(BlocoForm, self).save(commit) bloco = super(BlocoForm, self).save(commit)
content_type = ContentType.objects.get_for_model(Bloco) content_type = ContentType.objects.get_for_model(Bloco)
object_id = bloco.pk object_id = bloco.pk
tipo = TipoAutor.objects.get(descricao='Bloco Parlamentar') tipo = TipoAutor.objects.get(descricao__icontains='Bloco')
Autor.objects.create( Autor.objects.create(
content_type=content_type, content_type=content_type,
object_id=object_id, object_id=object_id,

14
sapl/sessao/views.py

@ -277,8 +277,8 @@ def customize_link_materia(context, pk, has_permission, is_expediente):
else: else:
resultado = '''Não há resultado''' resultado = '''Não há resultado'''
else: else:
resultado = obj.registrovotacao_set.get( resultado = obj.registrovotacao_set.filter(
materia_id=obj.materia_id) materia_id=obj.materia_id).last()
resultado_descricao = resultado.tipo_resultado_votacao.nome resultado_descricao = resultado.tipo_resultado_votacao.nome
resultado_observacao = resultado.observacao resultado_observacao = resultado.observacao
@ -761,6 +761,7 @@ class PainelView(PermissionRequiredForAppCrudMixin, TemplateView):
request.session['discurso'] = 'stop' request.session['discurso'] = 'stop'
request.session['aparte'] = 'stop' request.session['aparte'] = 'stop'
request.session['ordem'] = 'stop' request.session['ordem'] = 'stop'
request.session['consideracoes'] = 'stop'
return TemplateView.get(self, request, *args, **kwargs) return TemplateView.get(self, request, *args, **kwargs)
@ -768,9 +769,10 @@ class PainelView(PermissionRequiredForAppCrudMixin, TemplateView):
cronometro_discurso = AppsAppConfig.attr('cronometro_discurso') cronometro_discurso = AppsAppConfig.attr('cronometro_discurso')
cronometro_aparte = AppsAppConfig.attr('cronometro_aparte') cronometro_aparte = AppsAppConfig.attr('cronometro_aparte')
cronometro_ordem = AppsAppConfig.attr('cronometro_ordem') cronometro_ordem = AppsAppConfig.attr('cronometro_ordem')
cronometro_consideracoes = AppsAppConfig.attr('cronometro_consideracoes')
if (not cronometro_discurso or not cronometro_aparte if (not cronometro_discurso or not cronometro_aparte
or not cronometro_ordem): or not cronometro_ordem or not cronometro_consideracoes):
msg = _( msg = _(
'Você precisa primeiro configurar os cronômetros \ 'Você precisa primeiro configurar os cronômetros \
nas Configurações da Aplicação') nas Configurações da Aplicação')
@ -786,6 +788,9 @@ class PainelView(PermissionRequiredForAppCrudMixin, TemplateView):
m, s, x = cronometro_ordem.isoformat().split(':') m, s, x = cronometro_ordem.isoformat().split(':')
cronometro_ordem = int(m) * 60 + int(s) cronometro_ordem = int(m) * 60 + int(s)
m, s, x = cronometro_consideracoes.isoformat().split(':')
cronometro_consideracoes = int(m) * 60 + int(s)
context = TemplateView.get_context_data(self, **kwargs) context = TemplateView.get_context_data(self, **kwargs)
context.update({ context.update({
'head_title': str(_('Painel Plenário')), 'head_title': str(_('Painel Plenário')),
@ -794,7 +799,8 @@ class PainelView(PermissionRequiredForAppCrudMixin, TemplateView):
'sessaoplenaria': SessaoPlenaria.objects.get(pk=kwargs['pk']), 'sessaoplenaria': SessaoPlenaria.objects.get(pk=kwargs['pk']),
'cronometro_discurso': cronometro_discurso, 'cronometro_discurso': cronometro_discurso,
'cronometro_aparte': cronometro_aparte, 'cronometro_aparte': cronometro_aparte,
'cronometro_ordem': cronometro_ordem}) 'cronometro_ordem': cronometro_ordem,
'cronometro_consideracoes': cronometro_consideracoes})
return context return context

2
sapl/templates/base/layouts.yaml

@ -21,7 +21,7 @@ AppConfig:
- texto_articulado_proposicao texto_articulado_materia texto_articulado_norma - texto_articulado_proposicao texto_articulado_materia texto_articulado_norma
{% trans 'Cronômetros do Painel' %}: {% trans 'Cronômetros do Painel' %}:
- cronometro_discurso cronometro_aparte cronometro_ordem - cronometro_discurso cronometro_aparte cronometro_ordem cronometro_consideracoes
{% trans 'Configurações do Painel' %}: {% trans 'Configurações do Painel' %}:
- mostrar_brasao_painel - mostrar_brasao_painel

30
sapl/templates/painel/index.html

@ -28,7 +28,7 @@
ul, li { ul, li {
list-style-type: none; list-style-type: none;
} }
#date, #sessao_plenaria, #sessao_plenaria_data, #sessao_plenaria_hora_inicio, #message, #cronometro_discurso, #cronometro_aparte, #cronometro_ordem, #relogio, #parlamentares, #votacao, #materia_legislativa_texto, #observacao_materia, #resultado_votacao, #orador { #date, #sessao_plenaria, #sessao_plenaria_data, #sessao_plenaria_hora_inicio, #message, #cronometro_discurso, #cronometro_aparte, #cronometro_ordem, #cronometro_consideracoes, #relogio, #parlamentares, #votacao, #materia_legislativa_texto, #observacao_materia, #resultado_votacao, #orador {
font-family: Verdana; font-family: Verdana;
} }
} }
@ -108,6 +108,9 @@
<tr> <tr>
<td style="font-family:Verdana; text-align:center;"><font size="5" color="white">Questão de Ordem: <span id="cronometro_ordem"></span></font></td> <td style="font-family:Verdana; text-align:center;"><font size="5" color="white">Questão de Ordem: <span id="cronometro_ordem"></span></font></td>
</tr> </tr>
<tr>
<td style="font-family:Verdana; text-align:center;"><font size="5" color="white">Considerações Finais: <span id="cronometro_consideracoes"></span></font></td>
</tr>
</table> </table>
</div> </div>
@ -195,9 +198,20 @@
audioAlertFinish.play(); audioAlertFinish.play();
}); });
$('#cronometro_consideracoes').runner({
autostart: false,
countdown: true,
startAt: {{ 'consideracoes'|cronometro_to_seconds }} * 1000,
stopAt: 0,
milliseconds: false
}).on('runnerFinish', function(eventObject, info){
audioAlertFinish.play();
});
var discurso_previous; var discurso_previous;
var ordem_previous; var ordem_previous;
var aparte_previous; var aparte_previous;
var consideracoes_previous;
var counter = 1; var counter = 1;
(function poll() { (function poll() {
@ -325,6 +339,16 @@
ordem_previous = ordem_current; ordem_previous = ordem_current;
} }
var consideracoes_current = data["cronometro_consideracoes"];
if (!consideracoes_previous){
consideracoes_previous = ''
}
if (consideracoes_current != consideracoes_previous) {
$('#cronometro_consideracoes').runner(consideracoes_current);
consideracoes_previous = consideracoes_current;
}
if($('#cronometro_discurso').runner('info').formattedTime == 30) { if($('#cronometro_discurso').runner('info').formattedTime == 30) {
audioAlertFinish.play(); audioAlertFinish.play();
} }
@ -337,6 +361,10 @@
audioAlertFinish.play(); audioAlertFinish.play();
} }
if($('#cronometro_consideracoes').runner('info').formattedTime == 30) {
audioAlertFinish.play();
}
if (data['materia_legislativa_texto']){ if (data['materia_legislativa_texto']){
$("#materia_legislativa_texto").text(data["materia_legislativa_texto"]); $("#materia_legislativa_texto").text(data["materia_legislativa_texto"]);
} }

12
sapl/templates/parlamentares/layouts.yaml

@ -37,10 +37,10 @@ Parlamentar:
- situacao_militar profissao - situacao_militar profissao
- endereco_web - endereco_web
- email - email
- numero_gab_parlamentar telefone fax - numero_gab_parlamentar telefone
- endereco_residencia cep_residencia - endereco_residencia cep_residencia
- municipio_residencia uf_residencia - municipio_residencia uf_residencia
- telefone_residencia fax_residencia - telefone_residencia
- locais_atuacao - locais_atuacao
- fotografia:5 - fotografia:5
- biografia - biografia
@ -54,10 +54,10 @@ ParlamentarUpdate:
- situacao_militar profissao - situacao_militar profissao
- endereco_web - endereco_web
- email - email
- numero_gab_parlamentar telefone fax - numero_gab_parlamentar telefone
- endereco_residencia cep_residencia - endereco_residencia cep_residencia
- municipio_residencia uf_residencia - municipio_residencia uf_residencia
- telefone_residencia fax_residencia - telefone_residencia
- locais_atuacao - locais_atuacao
- fotografia cropping - fotografia cropping
- biografia - biografia
@ -73,10 +73,10 @@ ParlamentarCreate:
- situacao_militar profissao - situacao_militar profissao
- endereco_web - endereco_web
- email - email
- numero_gab_parlamentar telefone fax - numero_gab_parlamentar telefone
- endereco_residencia cep_residencia - endereco_residencia cep_residencia
- municipio_residencia - municipio_residencia
- telefone_residencia fax_residencia - telefone_residencia
- locais_atuacao - locais_atuacao
- fotografia - fotografia
- biografia - biografia

2
sapl/templates/protocoloadm/protocoloadm_detail.html

@ -5,5 +5,7 @@
<a href="{% url 'sapl.protocoloadm:protocolar_mat' %}" class="btn btn-default">{% trans 'Protocolar Matéria' %}</a> <a href="{% url 'sapl.protocoloadm:protocolar_mat' %}" class="btn btn-default">{% trans 'Protocolar Matéria' %}</a>
<a href="{% url 'sapl.protocoloadm:protocolar_doc' %}" class="btn btn-default">{% trans 'Protocolar Documento' %}</a> <a href="{% url 'sapl.protocoloadm:protocolar_doc' %}" class="btn btn-default">{% trans 'Protocolar Documento' %}</a>
<a href="{% url 'sapl.protocoloadm:anular_protocolo' %}" class="btn btn-default btn-excluir">{% trans 'Anular Protocolo' %}</a> <a href="{% url 'sapl.protocoloadm:anular_protocolo' %}" class="btn btn-default btn-excluir">{% trans 'Anular Protocolo' %}</a>
<a href="{% url 'sapl.protocoloadm:desvincular_documento' %}" class="btn btn-default btn-excluir">{% trans 'Desvincular Documentos' %}</a>
<a href="{% url 'sapl.protocoloadm:desvincular_materia' %}" class="btn btn-default btn-excluir">{% trans 'Desvincular Matérias' %}</a>
</div> </div>
{% endblock editions %} {% endblock editions %}

6
sapl/templates/sessao/blocos_resumo/conteudo_multimidia.html

@ -1,8 +1,8 @@
<fieldset> <fieldset>
<legend>Conteúdo Multimídia</legend> <legend>Conteúdo Multimídia</legend>
<div class="row"> <div class="row">
<div class="col-md-6">{{multimidia_audio}}</div> <div class="col-md-6">Audio: <a href={{multimidia_audio|slice:"6:"}}>{{multimidia_audio|slice:"6:"}}</a></div>
<div class="col-md-6">{{multimidia_video}}</div> <div class="col-md-6">Video: <a href={{multimidia_video|slice:"6:"}}>{{multimidia_video|slice:"6:"}}</a></div>
</div> </div>
</fieldset> </fieldset>
<br /><br /><br /> <br /><br /><br />

92
sapl/templates/sessao/painel.html

@ -69,6 +69,20 @@
</div> </div>
<br/> <br/>
<br/> <br/>
<div class="row">
<div class="col-md-12"><h3>Cronômetro de Considerações Finais</h3></div>
</div>
<div class="row">
<div class="col-xs-2"><input size="2" id="consideracoes" name="consideracoes" value="" readyonly="true" class="form-control"></div>
</div>
<br />
<div class="row">
<div class="col-md-6"><button type="button" id="consideracoesStart" class="btn btn-success">Iniciar</button></div>
<div class="col-md-6"><button type="button" id="consideracoesReset" class="btn btn-success">Reiniciar</button></div>
</div>
<br /><br >
<div class="row"> <div class="row">
<div class="col-md-6"><button type="button" id="sinalSonoro" class="btn btn-success" onclick="document.getElementById('audio').play();">Sinal Sonoro</button></div> <div class="col-md-6"><button type="button" id="sinalSonoro" class="btn btn-success" onclick="document.getElementById('audio').play();">Sinal Sonoro</button></div>
</div> </div>
@ -102,6 +116,7 @@ $(function() {
$('#discurso').prop('disabled', true); $('#discurso').prop('disabled', true);
$('#aparte').prop('disabled', true); $('#aparte').prop('disabled', true);
$('#ordem').prop('disabled', true); $('#ordem').prop('disabled', true);
$('#consideracoes').prop('disabled', true);
$('#discurso').runner({ $('#discurso').runner({
autostart: false, autostart: false,
@ -119,6 +134,8 @@ $(function() {
$('#aparteReset').prop('disabled', false); $('#aparteReset').prop('disabled', false);
$('#ordemStart').prop('disabled', false); $('#ordemStart').prop('disabled', false);
$('#ordemReset').prop('disabled', false); $('#ordemReset').prop('disabled', false);
$('#consideracoesStart').prop('disabled', false);
$('#consideracoesReset').prop('disabled', false);
}); });
@ -135,6 +152,8 @@ $(function() {
$('#aparteReset').prop('disabled', false); $('#aparteReset').prop('disabled', false);
$('#ordemStart').prop('disabled', false); $('#ordemStart').prop('disabled', false);
$('#ordemReset').prop('disabled', false); $('#ordemReset').prop('disabled', false);
$('#consideracoesStart').prop('disabled', false);
$('#consideracoesReset').prop('disabled', false);
} else { } else {
@ -147,6 +166,8 @@ $(function() {
$('#aparteReset').prop('disabled', false); $('#aparteReset').prop('disabled', false);
$('#ordemStart').prop('disabled', false); $('#ordemStart').prop('disabled', false);
$('#ordemReset').prop('disabled', false); $('#ordemReset').prop('disabled', false);
$('#consideracoesStart').prop('disabled', false);
$('#consideracoesReset').prop('disabled', false);
} }
}); });
@ -174,6 +195,8 @@ $(function() {
$('#discursoReset').prop('disabled', false); $('#discursoReset').prop('disabled', false);
$('#ordemStart').prop('disabled', false); $('#ordemStart').prop('disabled', false);
$('#ordemReset').prop('disabled', false); $('#ordemReset').prop('disabled', false);
$('#consideracoesStart').prop('disabled', false);
$('#consideracoesReset').prop('disabled', false);
}); });
@ -189,6 +212,8 @@ $(function() {
$('#discursoReset').prop('disabled', false); $('#discursoReset').prop('disabled', false);
$('#ordemStart').prop('disabled', false); $('#ordemStart').prop('disabled', false);
$('#ordemReset').prop('disabled', false); $('#ordemReset').prop('disabled', false);
$('#consideracoesStart').prop('disabled', false);
$('#consideracoesReset').prop('disabled', false);
} else { } else {
$.get('/painel/cronometro', { tipo: 'aparte', action: 'stop' } ); $.get('/painel/cronometro', { tipo: 'aparte', action: 'stop' } );
@ -200,6 +225,8 @@ $(function() {
$('#discursoReset').prop('disabled', false); $('#discursoReset').prop('disabled', false);
$('#ordemStart').prop('disabled', false); $('#ordemStart').prop('disabled', false);
$('#ordemReset').prop('disabled', false); $('#ordemReset').prop('disabled', false);
$('#consideracoesStart').prop('disabled', false);
$('#consideracoesReset').prop('disabled', false);
} }
}); });
@ -227,6 +254,8 @@ $(function() {
$('#discursoReset').prop('disabled', false); $('#discursoReset').prop('disabled', false);
$('#aparteStart').prop('disabled', false); $('#aparteStart').prop('disabled', false);
$('#aparteReset').prop('disabled', false); $('#aparteReset').prop('disabled', false);
$('#consideracoesStart').prop('disabled', false);
$('#consideracoesReset').prop('disabled', false);
}); });
$('#ordemStart').click(function() { $('#ordemStart').click(function() {
@ -241,6 +270,8 @@ $(function() {
$('#discursoReset').prop('disabled', false); $('#discursoReset').prop('disabled', false);
$('#aparteStart').prop('disabled', false); $('#aparteStart').prop('disabled', false);
$('#aparteReset').prop('disabled', false); $('#aparteReset').prop('disabled', false);
$('#consideracoesStart').prop('disabled', false);
$('#consideracoesReset').prop('disabled', false);
} else { } else {
@ -253,6 +284,8 @@ $(function() {
$('#discursoReset').prop('disabled', false); $('#discursoReset').prop('disabled', false);
$('#aparteStart').prop('disabled', false); $('#aparteStart').prop('disabled', false);
$('#aparteReset').prop('disabled', false); $('#aparteReset').prop('disabled', false);
$('#consideracoesStart').prop('disabled', false);
$('#consideracoesReset').prop('disabled', false);
} }
}); });
@ -264,6 +297,65 @@ $(function() {
$('#ordem').runner('reset'); $('#ordem').runner('reset');
}); });
$('#consideracoes').runner({
autostart: false,
countdown: true,
startAt: {{cronometro_consideracoes}} * 1000,
stopAt: 0,
milliseconds: false
}).on('runnerFinish', function(eventObject, info){
$.get('/painel/cronometro', { tipo: 'consideracoes', action: 'stop' } );
$('#consideracoesReset').show();
$('#consideracoes').runner('stop');
$('#consideracoesStart').text('Iniciar');
$('#discursoStart').prop('disabled', false);
$('#discursoReset').prop('disabled', false);
$('#ordemStart').prop('disabled', false);
$('#ordemReset').prop('disabled', false);
$('#aparteStart').prop('disabled', false);
$('#aparteReset').prop('disabled', false);
});
$('#consideracoesStart').click(function(){
if ($('#consideracoesStart').text() == 'Iniciar') {
$.get('/painel/cronometro', { tipo: 'consideracoes', action: 'start' } );
$('#consideracoesReset').hide();
$('#consideracoes').runner('start');
$('#consideracoesStart').text('Parar');
$('#discursoStart').prop('disabled', false);
$('#discursoReset').prop('disabled', false);
$('#ordemStart').prop('disabled', false);
$('#ordemReset').prop('disabled', false);
$('#aparteStart').prop('disabled', false);
$('#aparteReset').prop('disabled', false);
} else {
$.get('/painel/cronometro', { tipo: 'consideracoes', action: 'stop' } );
$('#consideracoesReset').show();
$('#consideracoes').runner('stop');
$('#consideracoesStart').text('Iniciar');
$('#discursoStart').prop('disabled', false);
$('#discursoReset').prop('disabled', false);
$('#ordemStart').prop('disabled', false);
$('#ordemReset').prop('disabled', false);
$('#aparteStart').prop('disabled', false);
$('#aparteReset').prop('disabled', false);
}
});
$('#consideracoesReset').click(function() {
$.get('/painel/cronometro', { tipo: 'consideracoes', action: 'reset' } );
$('#consideracoes').runner('stop');
$('#consideracoes').runner('reset');
});
}); });
function switch_painel(aberto) { function switch_painel(aberto) {

11
sapl/utils.py

@ -688,7 +688,7 @@ def ExtraiTag(texto, posicao):
return i + 1 return i + 1
def TrocaTag(texto, startTag, endTag, sizeStart, sizeEnd, styleName): def TrocaTag(texto, startTag, endTag, sizeStart, sizeEnd, styleName, subinitiTag, subendTag):
textoSaida = '' textoSaida = ''
insideTag = 0 insideTag = 0
i = 0 i = 0
@ -697,16 +697,19 @@ def TrocaTag(texto, startTag, endTag, sizeStart, sizeEnd, styleName):
if '<tbody>' in texto: if '<tbody>' in texto:
texto = texto.replace('<tbody>', '') texto = texto.replace('<tbody>', '')
texto = texto.replace('</tbody>', '') texto = texto.replace('</tbody>', '')
if '<p>' in texto:
texto = texto.replace('<p>', '')
texto = texto.replace('</p>', '')
while (i < len(texto)): while (i < len(texto)):
shard = texto[i:i + sizeStart] shard = texto[i:i + sizeStart]
if (shard == startTag): if (shard == startTag):
i = ExtraiTag(texto, i) i = ExtraiTag(texto, i)
textoSaida += '</para><blockTable style = "' + styleName + '">' textoSaida += subinitiTag + styleName + '">'
insideTag = 1 insideTag = 1
else: else:
if (insideTag == 1): if (insideTag == 1):
if (texto[i:i + sizeEnd] == endTag): if (texto[i:i + sizeEnd] == endTag):
textoSaida += 'blockTable><para>' textoSaida += subendTag
insideTag = 0 insideTag = 0
i += sizeEnd i += sizeEnd
else: else:
@ -735,4 +738,4 @@ def RemoveTag(texto):
return textoSaida return textoSaida
def remover_acentos(string): def remover_acentos(string):
return unicodedata.normalize('NFKD', string).encode('ASCII', 'ignore').decode() return unicodedata.normalize('NFKD', string).encode('ASCII', 'ignore').decode()

10
check_migrations.sh → scripts/django/check_migrations.sh

@ -11,13 +11,15 @@
# A chamada do django 1.10 INVERTE ISSO. # A chamada do django 1.10 INVERTE ISSO.
# #
# https://docs.djangoproject.com/en/1.10/ref/django-admin/#cmdoption-makemigrations-check # https://docs.djangoproject.com/en/1.10/ref/django-admin/#cmdoption-makemigrations-check
if python manage.py makemigrations --dry-run --exit > /dev/null; then
git_project_root=$(git rev-parse --show-toplevel)
if python ${git_project_root}/manage.py makemigrations --dry-run --exit > /dev/null; then
NC='\033[0m' NC='\033[0m'
RED='\033[0;31m' RED='\033[0;31m'
echo echo
echo -e "${RED}ALGUMAS ALTERAÇÕES EXIGEM MIGRAÇÃO.${NC}" echo -e "${RED}ALGUMAS ALTERAÇÕES EXIGEM MIGRAÇÃO.${NC}"
echo -e "${RED}RODE 'python manage.py makemigrations' ANTES DE SUBMETER SEU CÓDIGO...${NC}" echo -e "${RED}Execute o comando 'python manage.py makemigrations' ANTES DE SUBMETER SEU CÓDIGO...${NC}"
echo -e "${RED}lembre de adicionar os arquivos criados ao git com 'git add .' ou semelhante.${NC}" echo -e "${RED}Lembre de adicionar os arquivos criados ao git com 'git add <arquivo>' ou semelhante.${NC}"
echo echo
exit 1 exit 1
fi fi

4
check_qa.sh → scripts/django/check_qa.sh

@ -2,6 +2,10 @@
# Verifica se um breakpoint foi esquecido no código # Verifica se um breakpoint foi esquecido no código
me=`basename "$0"` me=`basename "$0"`
git_project_root=$(git rev-parse --show-toplevel)
cd ${git_project_root}
busca=`grep --color=auto --exclude=$me --exclude=ipython_log.py* -r -l "pdb.set_trace()" .` busca=`grep --color=auto --exclude=$me --exclude=ipython_log.py* -r -l "pdb.set_trace()" .`
if [ ! -z "$busca" ] if [ ! -z "$busca" ]

2
fix_qa.sh → scripts/django/fix_qa.sh

@ -8,5 +8,7 @@
# Uma forma simples de fazer isso é adicionando antes suas mudanças à # Uma forma simples de fazer isso é adicionando antes suas mudanças à
# "staging area" do git, com `git add .` e após usar o script `git diff`. # "staging area" do git, com `git add .` e após usar o script `git diff`.
git_project_root=$(git rev-parse --show-toplevel)
cd ${git_project_root}
isort --recursive --skip='migrations' --skip='templates' --skip='ipython_log.py*' . isort --recursive --skip='migrations' --skip='templates' --skip='ipython_log.py*' .
autopep8 --in-place --recursive . --exclude='migrations,ipython_log.py*' autopep8 --in-place --recursive . --exclude='migrations,ipython_log.py*'

3
scripts/gerar_grafico_apps.sh → scripts/django/gerar_grafico_apps.sh

@ -1,3 +1,6 @@
#!/bin/bash #!/bin/bash
git_project_root=$(git rev-parse --show-toplevel)
cd ${git_project_root}
python -c "from sapl.settings import SAPL_APPS; print(*[s.split('.')[-1] for s in SAPL_APPS])" | xargs -t ./manage.py graph_models -d -g -o zzz.png -l fdp python -c "from sapl.settings import SAPL_APPS; print(*[s.split('.')[-1] for s in SAPL_APPS])" | xargs -t ./manage.py graph_models -d -g -o zzz.png -l fdp

5
scripts/reset_all_migrations.sh → scripts/django/reset_all_migrations.sh

@ -3,6 +3,11 @@
# Sends all django migrations to the trash bin # Sends all django migrations to the trash bin
# Requires trash-cli. To install: # Requires trash-cli. To install:
# sudo apt-get install trash-cli # sudo apt-get install trash-cli
hash trash-put 2>/dev/null || { echo >&2 "I require trash-put but it's not installed. Aborting."; exit 1; }
git_project_root=$(git rev-parse --show-toplevel)
cd ${git_project_root}
find -name 00*.py | grep /migrations/ | xargs trash-put find -name 00*.py | grep /migrations/ | xargs trash-put
# Make all migrations from scratch # Make all migrations from scratch

5
test_and_check_qa.sh → scripts/django/test_and_check_qa.sh

@ -2,6 +2,9 @@
# QA checks: run this before every commit # QA checks: run this before every commit
git_project_root=$(git rev-parse --show-toplevel)
cd ${git_project_root}
py.test py.test
py.test --ds=sapl.crud.tests.settings sapl/crud/tests py.test --ds=sapl.crud.tests.settings sapl/crud/tests
./check_qa.sh ./scripts/django/check_qa.sh

2
scripts/hooks/pre-commit

@ -4,5 +4,5 @@
if git diff --cached --name-status | grep -q '^M.*models\.py$'; then if git diff --cached --name-status | grep -q '^M.*models\.py$'; then
# se a checagem de migrations falhar impedimos o commit # se a checagem de migrations falhar impedimos o commit
set -e set -e
./check_migrations.sh ./scripts/django/check_migrations.sh
fi fi

14
scripts/redbaron.py

@ -1,10 +1,14 @@
import os import os
import re import re
import subprocess
from redbaron import RedBaron from redbaron import RedBaron
from redbaron.nodes import EndlNode, ReturnNode, StringNode from redbaron.nodes import EndlNode, ReturnNode, StringNode
root = '/home/mazza/work/sapl' git_project_root = subprocess.Popen(
["git", "rev-parse", "--show-toplevel"],
stdout=subprocess.PIPE
).communicate()[0].decode('utf-8').replace('\n', '')
def ignorado(path, name): def ignorado(path, name):
@ -13,13 +17,13 @@ def ignorado(path, name):
'relatorios/templates.*', 'relatorios/templates.*',
'.*/migrations', '.*/migrations',
]: ]:
if re.match(os.path.join(root, pattern), path): if re.match(os.path.join(git_project_root, pattern), path):
return True return True
return name.startswith('ipython_log.py') or name == 'manage.py' return name.startswith('ipython_log.py') or name == 'manage.py'
filenames = [os.path.join(path, name) filenames = [os.path.join(path, name)
for path, subdirs, files in os.walk(root) for path, subdirs, files in os.walk(git_project_root)
for name in files for name in files
if name.endswith('.py') and not ignorado(path, name)] if name.endswith('.py') and not ignorado(path, name)]
@ -37,7 +41,7 @@ def build_red(filename):
def write(node): def write(node):
red = node.root red = node.git_project_root
with open(red.__filename__, "w") as source_code: with open(red.__filename__, "w") as source_code:
source_code.write(red.dumps()) source_code.write(red.dumps())
@ -82,7 +86,7 @@ def fix(n):
def local(node): def local(node):
res = '%s:%s' % (node.root.__filename__, res = '%s:%s' % (node.git_project_root.__filename__,
node.absolute_bounding_box.top_left.line) node.absolute_bounding_box.top_left.line)
os.system("echo '%s' | xclip -selection c" % res) os.system("echo '%s' | xclip -selection c" % res)
return res return res

2
setup.py

@ -49,7 +49,7 @@ install_requires = [
] ]
setup( setup(
name='interlegis-sapl', name='interlegis-sapl',
version='3.1.77', version='3.1.81',
packages=find_packages(), packages=find_packages(),
include_package_data=True, include_package_data=True,
license='GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007', license='GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007',

Loading…
Cancel
Save