Browse Source

Painel do Contato Interlegis

pull/159/head
Sesostris Vieira 2 years ago
parent
commit
753ef26ab5
  1. 6
      sigi/apps/casas/admin_urls.py
  2. 38
      sigi/apps/casas/forms.py
  3. 37
      sigi/apps/casas/templates/casas/casas_sem_convenio_pdf.html
  4. 10
      sigi/apps/casas/templates/casas/lista_casas_carteira_snippet.html
  5. 2
      sigi/apps/casas/templates/casas/painel.html
  6. 4
      sigi/apps/casas/templates/casas/resumo_carteira_snippet.html
  7. 35
      sigi/apps/casas/templates/public/casas/funcionario_delete.html
  8. 67
      sigi/apps/casas/templates/public/casas/funcionario_list.html
  9. 34
      sigi/apps/casas/templates/public/casas/funcionario_update.html
  10. 28
      sigi/apps/casas/templates/public/casas/orgao_update.html
  11. 85
      sigi/apps/casas/urls.py
  12. 1085
      sigi/apps/casas/views.py
  13. 8
      sigi/apps/contatos/admin.py
  14. 11
      sigi/apps/convenios/urls.py
  15. 7
      sigi/apps/convenios/views.py
  16. 25
      sigi/apps/eventos/admin.py
  17. 14
      sigi/apps/eventos/admin_urls.py
  18. 7
      sigi/apps/eventos/forms.py
  19. 38
      sigi/apps/eventos/migrations/0024_evento_banner_evento_contato_evento_link_inscricao_and_more.py
  20. 18
      sigi/apps/eventos/migrations/0025_evento_turma.py
  21. 31
      sigi/apps/eventos/migrations/0026_preenche_turma.py
  22. 20
      sigi/apps/eventos/migrations/0027_tipoevento_casa_solicita.py
  23. 26
      sigi/apps/eventos/migrations/0028_evento_solicitacao.py
  24. 24
      sigi/apps/eventos/models.py
  25. 2
      sigi/apps/eventos/templates/eventos/convida_casa.html
  26. 21
      sigi/apps/eventos/templates/eventos/lista.html
  27. 45
      sigi/apps/eventos/urls.py
  28. 224
      sigi/apps/eventos/views.py
  29. 37
      sigi/apps/home/accounts_urls.py
  30. 2
      sigi/apps/home/fixtures/cards.json
  31. 6
      sigi/apps/home/forms.py
  32. 35
      sigi/apps/home/mixins.py
  33. 11
      sigi/apps/home/templates/home/dashboard/card.html
  34. 18
      sigi/apps/home/templates/home/openmap.html
  35. 63
      sigi/apps/home/templates/home/public_site/index.html
  36. 2
      sigi/apps/home/urls.py
  37. 138
      sigi/apps/home/views.py
  38. 18
      sigi/apps/ocorrencias/admin_urls.py
  39. 7
      sigi/apps/ocorrencias/apps.py
  40. 98
      sigi/apps/ocorrencias/forms.py
  41. 22
      sigi/apps/ocorrencias/migrations/0010_alter_ocorrencia_options_ocorrencia_interno.py
  42. 27
      sigi/apps/ocorrencias/migrations/0011_alter_categoria_tipo.py
  43. 18
      sigi/apps/ocorrencias/migrations/0012_alter_comentario_descricao.py
  44. 58
      sigi/apps/ocorrencias/models.py
  45. 65
      sigi/apps/ocorrencias/static/ocorrencias/css/painel_ocorrencias.css
  46. 5
      sigi/apps/ocorrencias/static/ocorrencias/js/painel_ocorrencias.js
  47. 14
      sigi/apps/ocorrencias/templates/ocorrencias/anexo_form.html
  48. 24
      sigi/apps/ocorrencias/templates/ocorrencias/anexos_snippet.html
  49. 53
      sigi/apps/ocorrencias/templates/ocorrencias/convenio/atualiza_casa.html
  50. 4
      sigi/apps/ocorrencias/templates/ocorrencias/convenio/ocorrencia.html
  51. 40
      sigi/apps/ocorrencias/templates/ocorrencias/convenio/painel_convenio.html
  52. 128
      sigi/apps/ocorrencias/templates/ocorrencias/convenio/painel_convenio_detail.html
  53. 2
      sigi/apps/ocorrencias/templates/ocorrencias/convenio/seleciona_casa.html
  54. 128
      sigi/apps/ocorrencias/templates/ocorrencias/ocorrencia_detail.html
  55. 7
      sigi/apps/ocorrencias/templates/ocorrencias/ocorrencia_form.html
  56. 113
      sigi/apps/ocorrencias/templates/ocorrencias/ocorrencia_snippet.html
  57. 12
      sigi/apps/ocorrencias/templates/ocorrencias/oficina/email_senador.html
  58. 90
      sigi/apps/ocorrencias/templates/ocorrencias/oficina/painel_oficina_detail.html
  59. 198
      sigi/apps/ocorrencias/templates/ocorrencias/painel-old.html
  60. 252
      sigi/apps/ocorrencias/templates/ocorrencias/painel.html
  61. 153
      sigi/apps/ocorrencias/templates/ocorrencias/painel_snippet.html
  62. 44
      sigi/apps/ocorrencias/templates/public/ocorrencias/ocorrencia_list.html
  63. 61
      sigi/apps/ocorrencias/templates/public/ocorrencias/oficio_oficina_pdf.html
  64. 57
      sigi/apps/ocorrencias/templates/public/ocorrencias/seleciona_casa.html
  65. 252
      sigi/apps/ocorrencias/templates/public/ocorrencias/solicita_convenio_create.html
  66. 24
      sigi/apps/ocorrencias/templates/public/ocorrencias/solicita_treinamento_create.html
  67. 67
      sigi/apps/ocorrencias/templates/public/ocorrencias/solicita_treinamento_view.html
  68. 67
      sigi/apps/ocorrencias/urls.py
  69. 1456
      sigi/apps/ocorrencias/views.py
  70. 132
      sigi/apps/parlamentares/admin.py
  71. 2
      sigi/apps/parlamentares/apps.py
  72. 25
      sigi/apps/parlamentares/forms.py
  73. 17
      sigi/apps/parlamentares/migrations/0011_alter_parlamentar_options.py
  74. 77
      sigi/apps/parlamentares/migrations/0012_senador.py
  75. 39
      sigi/apps/parlamentares/models.py
  76. 84
      sigi/apps/parlamentares/templates/public/parlamentar_list.html
  77. 28
      sigi/apps/parlamentares/templates/public/parlamentar_update.html
  78. 18
      sigi/apps/parlamentares/urls.py
  79. 77
      sigi/apps/parlamentares/views.py
  80. 1
      sigi/apps/servicos/management/commands/importa_servico.py
  81. 1
      sigi/apps/servidores/management/commands/migra.py
  82. 36
      sigi/apps/servidores/migrations/0011_add_servidor_sigi.py
  83. 9
      sigi/apps/utils/mixins.py
  84. 37
      sigi/menu_conf.yaml
  85. 7
      sigi/templates/admin/base_block.html
  86. 25
      sigi/templates/admin/base_site.html
  87. 4
      sigi/templates/material/admin/side_nav.html
  88. 18
      sigi/templates/pdf/base.html
  89. 69
      sigi/templates/public/base_site.html
  90. 83
      sigi/templates/registration/login.html
  91. 20
      sigi/templates/registration/logout.html
  92. 2
      sigi/templates/sigi/snippets/base_card.html
  93. 10
      sigi/urls.py
  94. 2
      templates/snippets/modules/charts-convenios.html

6
sigi/apps/casas/admin_urls.py

@ -0,0 +1,6 @@
from django.urls import path, include
from sigi.apps.casas import views
urlpatterns = [
path("carteira/", views.painel_relacionamento, name="casas_carteira"),
]

38
sigi/apps/casas/forms.py

@ -1,8 +1,8 @@
from django import forms from django import forms
from django.utils.translation import gettext as _ from django.utils.translation import gettext as _
from localflavor.br.forms import BRZipCodeField from localflavor.br.forms import BRZipCodeField
from material.admin.widgets import MaterialAdminTextareaWidget
from sigi.apps.casas.models import Orgao from sigi.apps.casas.models import Funcionario, Orgao
from sigi.apps.servidores.models import Servidor from sigi.apps.servidores.models import Servidor
@ -15,11 +15,6 @@ class AtualizaCasaForm(forms.Form):
class OrgaoForm(forms.ModelForm): class OrgaoForm(forms.ModelForm):
# cnpj = BRCNPJField(
# label=_('CNPJ'),
# required=False,
# help_text=_('Utilize o formato <em>XX.XXX.XXX/XXXX-XX</em> ou insira apenas os dígitos.')
# )
cep = BRZipCodeField( cep = BRZipCodeField(
label=_("CEP"), help_text=_("Formato") + ": <em>XXXXX-XXX</em>." label=_("CEP"), help_text=_("Formato") + ": <em>XXXXX-XXX</em>."
) )
@ -28,13 +23,6 @@ class OrgaoForm(forms.ModelForm):
model = Orgao model = Orgao
fields = "__all__" fields = "__all__"
# def clean(self):
# cleaned_data = super(OrgaoForm, self).clean()
# tipo = cleaned_data.get('tipo')
# municipio = cleaned_data.get('municipio')
# if tipo.legislativo:
# if Orgao.objects.filter(tipo=tipo)
class PortfolioForm(forms.Form): class PortfolioForm(forms.Form):
ACAO_CHOICES = (("ADD", _("Adicionar")), ("DEL", _("Remover"))) ACAO_CHOICES = (("ADD", _("Adicionar")), ("DEL", _("Remover")))
@ -52,3 +40,25 @@ class PortfolioForm(forms.Form):
def __init__(self, label=_("Atribuir para"), *args, **kwargs): def __init__(self, label=_("Atribuir para"), *args, **kwargs):
super(PortfolioForm, self).__init__(*args, **kwargs) super(PortfolioForm, self).__init__(*args, **kwargs)
self.fields["gerente"].label = label self.fields["gerente"].label = label
class FuncionarioForm(forms.ModelForm):
class Meta:
model = Funcionario
fields = [
"nome",
"cpf",
"identidade",
"sexo",
"data_nascimento",
"setor",
"cargo",
"funcao",
"tempo_de_servico",
"nota",
"email",
"redes_sociais",
]
widgets = {
"redes_sociais": MaterialAdminTextareaWidget,
}

37
sigi/apps/casas/templates/casas/casas_sem_convenio_pdf.html

@ -1,37 +0,0 @@
{% extends 'pdf/base_report.html' %}
{% load static i18n %}
{% block page_size %}A4 landscape{% endblock %}
{% block main_content %}
<table repeat="1">
<thead>
<tr>
<th style="width: 22.5%;">{% trans 'Casa' %}</th>
<th style="width: 12.5%;">{% trans 'Presidente' %}</th>
<th style="width: 5%;">{% trans 'Tipo' %}</th>
<th style="width: 18%;">{% trans 'Endereço' %}</th>
<th style="width: 10%;">{% trans 'Bairro' %}</th>
<th style="width: 7%;">{% trans 'CEP' %}</th>
<th style="width: 12.5%;">{% trans 'Telefone' %}</th>
<th style="width: 12.5%;">{% trans 'E-mail' %}</th>
</tr>
</thead>
{% for casa in casas %}
{% ifchanged casa.municipio.uf %}
<tr class="title_row"><td colspan="8"><h1>{{ casa.municipio.uf.nome }}</h1></td></tr>
{% endifchanged %}
<tr>
<td>{{ casa.nome }}</td>
<td>{{ casa.presidente }}</td>
<td>{{ casa.tipo.sigla }}</td>
<td>{{ casa.logradouro }}</td>
<td>{{ casa.bairro }}</td>
<td>{{ casa.cep }}</td>
<td>{{ casa.telefone }}</td>
<td>{{ casa.email }}</td>
</tr>
{% endfor %}
</table>
{% endblock main_content %}

10
sigi/apps/casas/templates/casas/lista_casas_carteira_snippet.html

@ -26,27 +26,27 @@
{% endif %} {% endif %}
</form> </form>
<ul class="nav nav-tabs" role="tablist"> <ul class="nav nav-tabs" role="tablist">
<li role="presentation"{% if not regiao %} class="active"{% endif %}><a href="{% url "casas-carteira" %}?snippet=lista&{{ qs_servidor }}&{{ qs_servico }}">{% trans "Todo o país" %}</a></li> <li role="presentation"{% if not regiao %} class="active"{% endif %}><a href="{% url "casas_carteira" %}?snippet=lista&{{ qs_servidor }}&{{ qs_servico }}">{% trans "Todo o país" %}</a></li>
{% for k, l in regioes %} {% for k, l in regioes %}
<li role="presentation" {% if regiao == k %} class="active"{% endif %}><a href="{% url "casas-carteira" %}?snippet=lista&{{ qs_servidor }}&{{ qs_servico }}&r={{ k }}">{{ l }}</a></li> <li role="presentation" {% if regiao == k %} class="active"{% endif %}><a href="{% url "casas_carteira" %}?snippet=lista&{{ qs_servidor }}&{{ qs_servico }}&r={{ k }}">{{ l }}</a></li>
{% endfor %} {% endfor %}
</ul> </ul>
<ul class="nav nav-pills"> <ul class="nav nav-pills">
{% for u in ufs %} {% for u in ufs %}
<li role="presentation" {% if u.pk == uf.pk %} class="active"{% endif %}><a href="{% url "casas-carteira" %}?snippet=lista&{{ qs_servidor }}&{{ qs_servico }}&uf={{ u.sigla }}" autocomplete="off">{{ u.nome }}</a></li> <li role="presentation" {% if u.pk == uf.pk %} class="active"{% endif %}><a href="{% url "casas_carteira" %}?snippet=lista&{{ qs_servidor }}&{{ qs_servico }}&uf={{ u.sigla }}" autocomplete="off">{{ u.nome }}</a></li>
{% endfor %} {% endfor %}
</ul> </ul>
<ul class="nav nav-pills"> <ul class="nav nav-pills">
{% for m in uf.mesorregiao_set.all %} {% for m in uf.mesorregiao_set.all %}
<li role="presentation" {% if m.pk == meso.pk %} class="active"{% endif %}><a href="{% url "casas-carteira" %}?snippet=lista&{{ qs_servidor }}&{{ qs_servico }}&meso={{ m.pk|safe }}" autocomplete="off">{{ m.nome }}</a></li> <li role="presentation" {% if m.pk == meso.pk %} class="active"{% endif %}><a href="{% url "casas_carteira" %}?snippet=lista&{{ qs_servidor }}&{{ qs_servico }}&meso={{ m.pk|safe }}" autocomplete="off">{{ m.nome }}</a></li>
{% endfor %} {% endfor %}
</ul> </ul>
<ul class="nav nav-pills"> <ul class="nav nav-pills">
{% for m in meso.microrregiao_set.all %} {% for m in meso.microrregiao_set.all %}
<li role="presentation" {% if m.pk == micro.pk %} class="active"{% endif %}><a href="{% url "casas-carteira" %}?snippet=lista&{{ qs_servidor }}&{{ qs_servico }}&micro={{ m.pk|safe }}" autocomplete="off">{{ m.nome }}</a></li> <li role="presentation" {% if m.pk == micro.pk %} class="active"{% endif %}><a href="{% url "casas_carteira" %}?snippet=lista&{{ qs_servidor }}&{{ qs_servico }}&micro={{ m.pk|safe }}" autocomplete="off">{{ m.nome }}</a></li>
{% endfor %} {% endfor %}
</ul> </ul>
</div> </div>

2
sigi/apps/casas/templates/casas/painel.html

@ -46,7 +46,7 @@ $(document).ready(function(){
function filter_list( e ) { function filter_list( e ) {
e.preventDefault(); e.preventDefault();
var form_data = $("form[name='servico-form']").serialize(); var form_data = $("form[name='servico-form']").serialize();
$("#lista").load("{% url "casas-carteira" %}?snippet=lista&"+form_data, listeners); $("#lista").load("{% url "casas_carteira" %}?snippet=lista&"+form_data, listeners);
} }
}); });
</script> </script>

4
sigi/apps/casas/templates/casas/resumo_carteira_snippet.html

@ -19,13 +19,13 @@
<div class="collapsible-body"> <div class="collapsible-body">
<ul> <ul>
<li> <li>
<a class="dashlink" href="{% url "casas-carteira" %}?servidor=_all&snippet={{ snippet }}&s={{ seletor }}" data-target="card-carteira"> <a class="dashlink" href="{% url "casas_carteira" %}?servidor=_all&snippet={{ snippet }}&s={{ seletor }}" data-target="card-carteira">
{% trans "Todo o Interlegis" %} {% trans "Todo o Interlegis" %}
</a> </a>
</li> </li>
{% for g in gerentes %} {% for g in gerentes %}
<li> <li>
<a class="dashlink" href="{% url "casas-carteira" %}?servidor={{ g.pk|safe }}&snippet={{ snippet }}&s={{ seletor }}" data-target="card-carteira"> <a class="dashlink" href="{% url "casas_carteira" %}?servidor={{ g.pk|safe }}&snippet={{ snippet }}&s={{ seletor }}" data-target="card-carteira">
{{g.nome_completo }} {{g.nome_completo }}
</a> </a>
</li> </li>

35
sigi/apps/casas/templates/public/casas/funcionario_delete.html

@ -0,0 +1,35 @@
{% extends 'public/base_site.html' %}
{% load i18n %}
{% block content %}
{{ block.super }}
<div class="row">
<div class="col s12">
<form method="post">{% csrf_token %}{{ form }}
<div class="card">
<div class="card-content">
<span class="card-title">{% blocktrans with name=object.nome %}Deseja excluir {{ name }}?{% endblocktrans %}</span>
<p>O funcionário {{ object.nome }} será permanentemente excluído da base de dados!</p>
{% if unico_login %}
<blockquote style="font-size: 1em;">
{% blocktrans with name=object.nome|upper casa=casa|upper %}
{{ name }} é o único funcionário da {{ casa }} que pode efetuar login neste sistema. Ao excluí-lo, ninguém mais poderá acessar o sistema. Para voltar a ter acesso, o Presidente deverá enviar um ofício assinado designando um novo Contato Interlegis.
{% endblocktrans %}
</blockquote>
{% endif %}
</div>
<div class="card-action">
<button class="btn waves-effect waves-light red" type="submit" name="action">
{% trans 'Delete' %}
<i class="material-icons right">delete_forever</i>
</button>
<a class="btn waves-effect waves-light white-text" href="{% url 'casas:funcionario_update' object.id %}">
{% trans 'Cancelar' %}
<i class="material-icons right">cancel</i>
</a>
</div>
</form>
</div>
</div>
</div>
{% endblock %}

67
sigi/apps/casas/templates/public/casas/funcionario_list.html

@ -0,0 +1,67 @@
{% extends 'public/base_site.html' %}
{% load i18n %}
{% block extrastyle %}
{{ block.super }}
<style>
.pagination span {
font-weight: bold;
}
.pagination i {
vertical-align: middle;
margin: 0 24px;
color: #000 !important;
}
</style>
{% endblock extrastyle %}
{% block content %}
{{ block.super }}
<div class="row">
<div class="col s12">
<div class="card">
<div class="card-content">
<table class="striped">
<tr>
<th>{% trans 'Setor' %}</th>
<th>{% trans 'Nome' %}</th>
<th>{% trans 'CPF' %}</th>
<th>{% trans 'Telefones' %}</th>
<th>{% trans 'E-mail' %}</th>
</tr>
{% for funcionario in object_list %}
<tr>
<td><a href="{% url 'casas:funcionario_update' funcionario.id %}">{{ funcionario.get_setor_display }}</a></td>
<td><a href="{% url 'casas:funcionario_update' funcionario.id %}">{{ funcionario.nome }}</a></td>
<td>{{ funcionario.cpf }}</td>
<td>{{ funcionario.nota }}</td>
<td>{{ funcionario.email }}</td>
</tr>
{% endfor %}
</table>
</div>
<div class="card-action">
<div class='pagination'>
{% if page_obj.has_previous %}
<a href='{% url "casas:funcionario_listview" %}?page={{ page_obj.previous_page_number }}{% if suplentes %}&suplentes=1{% endif %}'><i class="material-icons">skip_previous</i></a>
{% endif %}
{% if page_obj.paginator.num_pages > 1 %}
<span>
{% blocktranslate with number=page_obj.number num_pages=page_obj.paginator.num_pages %}
Página {{ number }} de {{ num_pages }}
{% endblocktranslate %}
</span>
{% endif %}
{% if page_obj.has_next %}
<a href='{% url "casas:funcionario_listview" %}?page={{ page_obj.next_page_number }}{% if suplentes %}&suplentes=1{% endif %}'><i class="material-icons">skip_next</i></a>
{% endif %}
<a class="btn waves-effect waves-light white-text" href="{% url 'casas:funcionario_create' %}">
{% trans 'Novo' %}
<i class="material-icons right">create</i>
</a>
</div>
</div>
</div>
</div>
</div>
{% endblock %}

34
sigi/apps/casas/templates/public/casas/funcionario_update.html

@ -0,0 +1,34 @@
{% extends 'public/base_site.html' %}
{% load i18n %}
{% block extrahead %}
{{ block.super }}
{{ form.media }}
{% endblock extrahead %}
{% block content %}
{{ block.super }}
<div class="row">
<div class="col s12">
<form method="post">{% csrf_token %}
<div class="card">
<div class="card-content">
{{ form }}
</div>
<div class="card-action">
<button class="btn waves-effect waves-light" type="submit" name="action">
{% trans 'Save' %}
<i class="material-icons right">save</i>
</button>
{% if object %}
<a class="btn waves-effect waves-light red white-text" href="{% url 'casas:funcionario_delete' object.id %}">
{% trans 'Delete' %}
<i class="material-icons right">delete_forever</i>
</a>
{% endif %}
</div>
</form>
</div>
</div>
</div>
{% endblock %}

28
sigi/apps/casas/templates/public/casas/orgao_update.html

@ -0,0 +1,28 @@
{% extends 'public/base_site.html' %}
{% load i18n static %}
{% block extrahead %}
{{ block.super }}
{{ form.media }}
{% endblock extrahead %}
{% block content %}
{{ block.super }}
<div class="row">
<div class="col s12">
<form method="post">{% csrf_token %}
<div class="card">
<div class="card-content">
{{ form }}
</div>
<div class="card-action">
<button class="btn waves-effect waves-light" type="submit" name="action">
{% trans 'Save' %}
<i class="material-icons right">save</i>
</button>
</div>
</form>
</div>
</div>
</div>
{% endblock %}

85
sigi/apps/casas/urls.py

@ -1,71 +1,28 @@
from django.urls import path, include from django.urls import path, include
from sigi.apps.casas import views from sigi.apps.casas import views
app_name = "casas"
urlpatterns = [ urlpatterns = [
path("orgao/update/", views.CasaUpdateView.as_view(), name="orgao_update"),
path(
"funcionario/",
views.FuncionarioListView.as_view(),
name="funcionario_listview",
),
path(
"funcionario/create/",
views.FuncionarioCreateView.as_view(),
name="funcionario_create",
),
path( path(
"orgao/casas_sem_convenio_report/", "funcionario/<int:pk>/",
views.CasasSemConvenioReport.as_view(), views.FuncionarioUpdateView.as_view(),
name="casas-sem-convenio-report", name="funcionario_update",
),
path(
"funcionario/<int:pk>/delete/",
views.FuncionarioDeleteView.as_view(),
name="funcionario_delete",
), ),
path("carteira/", views.painel_relacionamento, name="casas-carteira"),
] ]
"""
from django.conf.urls import patterns, url
from django.contrib.auth.decorators import login_required
from sigi.apps.casas.views import importa_casas
urlpatterns = patterns(
'sigi.apps.casas.views',
# Informacoes de uma casa legislativa
url(r'^orgao/report_complete/$', 'report_complete',
name='report-complete-all'),
url(r'^orgao/(?P<id>\w+)/report_complete/$', 'report_complete',
name='report-complete-id'),
# Reports Labels
url(r'^orgao/labels/$', 'labels_report', name='labels-report-all'),
url(r'^orgao/(?P<id>\w+)/labels/$', 'labels_report',
name='labels-report-id'),
# Reports Labels Parlamentar
url(r'^orgao/labels_parlamentar/$', 'labels_report_parlamentar',
name='lebels-report-parlamentar-all'),
url(r'^orgao/(?P<id>\w+)/labels_parlamentar/$', 'labels_report_parlamentar',
name='labels-report-parlamentar-id'),
# Reports labels sem presidente
url(r'^orgao/labels_sem_presidente/$', 'labels_report_sem_presidente',
name='labels-report-sem-presidente-all'),
url(r'^orgao/(?P<id>\w+)/labels_sem_presidente/$',
'labels_report_sem_presidente', name='labels-report-sem-presidente-id'),
# Reports casas sem convenio
url(r'^orgao/reports/$', 'report', name='casa-report'),
url(r'^orgao/casas_sem_convenio_report/$', 'casas_sem_convenio_report',
name='casas-sem-convenio-report'),
# CSV
url(r'^orgao/csv/$', 'export_csv', name='casa-export-csv'), # Error
# Carrinho
url(r'^orgao/carrinho/$', 'visualizar_carrinho',
name='visualizar-carrinho'),
url(r'^orgao/carrinho/excluir_carrinho/$', 'excluir_carrinho',
name='excluir-carrinho'), # Error
url(r'^orgao/carrinho/deleta_itens_carrinho$', 'deleta_itens_carrinho',
name='deleta-itens-carrinho'), # Error
url(r'^portfolio/$', 'portfolio', name='casas-portfolio'),
url(r'^carteira/$', 'painel_relacionamento', name='casas-carteira'),
# Atualização por CSV
url(r'^orgao/importa/$', login_required(importa_casas.as_view()),
name='importar-casas'),
url(r'^gerentes/$', 'gerentes_interlegis',
name='gerentes_interlegis'),
)
"""

1085
sigi/apps/casas/views.py

File diff suppressed because it is too large

8
sigi/apps/contatos/admin.py

@ -10,6 +10,7 @@ from sigi.apps.contatos.models import (
Telefone, Telefone,
Contato, Contato,
) )
from sigi.apps.parlamentares.models import Senador
from sigi.apps.utils import queryset_ascii from sigi.apps.utils import queryset_ascii
@ -21,6 +22,11 @@ class MicrorregiaoInline(admin.TabularInline):
model = Microrregiao model = Microrregiao
class SenadorInline(admin.StackedInline):
model = Senador
extra = 0
@admin.register(UnidadeFederativa) @admin.register(UnidadeFederativa)
class UnidadeFederativaAdmin(admin.ModelAdmin): class UnidadeFederativaAdmin(admin.ModelAdmin):
actions = None actions = None
@ -32,7 +38,7 @@ class UnidadeFederativaAdmin(admin.ModelAdmin):
) )
search_fields = ("search_text", "codigo_ibge", "sigla", "regiao") search_fields = ("search_text", "codigo_ibge", "sigla", "regiao")
get_queryset = queryset_ascii get_queryset = queryset_ascii
inlines = (MesorregiaoInline,) inlines = (SenadorInline, MesorregiaoInline)
@admin.register(Mesorregiao) @admin.register(Mesorregiao)

11
sigi/apps/convenios/urls.py

@ -9,14 +9,3 @@ urlpatterns = [
), ),
path("importar/", views.importar_gescon, name="importar-gescon"), path("importar/", views.importar_gescon, name="importar-gescon"),
] ]
# urlpatterns = patterns(
# 'sigi.apps.convenios.views',
# url(r'^convenio/reports/$', 'report', name='convenios-report'),
# url(r'^convenio/carrinho/$', 'visualizar_carrinho', name='visualizar-carrinho'),
# url(r'^convenio/carrinho/excluir_carrinho/$', 'excluir_carrinho', name='excluir-carrinho'), # tagerror
# url(r'^convenio/carrinho/deleta_itens_carrinho$', 'deleta_itens_carrinho', name='deleta-itens-carrinho'), # tagerror
# url(r'^convenio/csv/$', 'export_csv', name='convenios-csv'),
# url(r'^importar/$', 'importar_gescon', name='importar-gescon'),
# )

7
sigi/apps/convenios/views.py

@ -10,6 +10,7 @@ from django.http.response import HttpResponseForbidden
from django.shortcuts import render, get_list_or_404 from django.shortcuts import render, get_list_or_404
from django.template import Context, loader from django.template import Context, loader
from django.utils.translation import gettext as _ from django.utils.translation import gettext as _
from django.contrib.admin.views.decorators import staff_member_required
from django.contrib.auth.decorators import login_required from django.contrib.auth.decorators import login_required
from django_weasyprint.views import WeasyTemplateResponse from django_weasyprint.views import WeasyTemplateResponse
from sigi.apps.casas.models import Orgao from sigi.apps.casas.models import Orgao
@ -25,6 +26,7 @@ from sigi.apps.convenios.models import Convenio, Gescon, Projeto
@login_required @login_required
@staff_member_required
def report_regiao(request, regiao): def report_regiao(request, regiao):
REGIAO_CHOICES = dict(UnidadeFederativa.REGIAO_CHOICES) REGIAO_CHOICES = dict(UnidadeFederativa.REGIAO_CHOICES)
projetos = Projeto.objects.all() projetos = Projeto.objects.all()
@ -135,19 +137,18 @@ def casas_estado_to_tabela(casas, convenios, regiao):
@login_required @login_required
@staff_member_required
def importar_gescon(request): def importar_gescon(request):
if not request.user.is_superuser: if not request.user.is_superuser:
return HttpResponseForbidden() return HttpResponseForbidden()
context = admin.site.each_context(request)
action = request.GET.get("action", "") action = request.GET.get("action", "")
gescon = Gescon.load() gescon = Gescon.load()
if action == "importar": if action == "importar":
gescon.importa_contratos() gescon.importa_contratos()
context["gescon"] = gescon context = {"gescon": gescon}
return render(request, "convenios/importar_gescon.html", context) return render(request, "convenios/importar_gescon.html", context)

25
sigi/apps/eventos/admin.py

@ -3,6 +3,7 @@ from django.contrib import admin
from django.http import HttpResponseRedirect from django.http import HttpResponseRedirect
from django.shortcuts import get_object_or_404, render from django.shortcuts import get_object_or_404, render
from django.urls import path from django.urls import path
from django.utils.safestring import mark_safe
from django.utils.translation import gettext as _ from django.utils.translation import gettext as _
from django_weasyprint.views import WeasyTemplateResponse from django_weasyprint.views import WeasyTemplateResponse
from import_export.fields import Field from import_export.fields import Field
@ -118,8 +119,10 @@ class CronogramaInline(admin.StackedInline):
@admin.register(TipoEvento) @admin.register(TipoEvento)
class TipoEventAdmin(admin.ModelAdmin): class TipoEventoAdmin(admin.ModelAdmin):
search_fields = ("nome",) list_display = ["nome", "categoria"]
list_filter = ["categoria", "casa_solicita"]
search_fields = ["nome"]
inlines = [ChecklistInline] inlines = [ChecklistInline]
@ -147,9 +150,12 @@ class EventoAdmin(CartExportMixin, admin.ModelAdmin):
resource_class = EventoResource resource_class = EventoResource
date_hierarchy = "data_inicio" date_hierarchy = "data_inicio"
list_display = ( list_display = (
"get_banner",
"nome", "nome",
"tipo_evento", "tipo_evento",
"turma",
"status", "status",
"publicar",
"link_sigad", "link_sigad",
"data_inicio", "data_inicio",
"data_termino", "data_termino",
@ -157,8 +163,10 @@ class EventoAdmin(CartExportMixin, admin.ModelAdmin):
"solicitante", "solicitante",
"total_participantes", "total_participantes",
) )
list_display_links = ["get_banner", "nome"]
list_filter = ( list_filter = (
"status", "status",
"publicar",
("num_processo", EmptyFilter), ("num_processo", EmptyFilter),
"tipo_evento", "tipo_evento",
"tipo_evento__categoria", "tipo_evento__categoria",
@ -186,13 +194,20 @@ class EventoAdmin(CartExportMixin, admin.ModelAdmin):
) )
save_as = True save_as = True
@admin.display(description=_("número do processo SIGAD"))
def link_sigad(self, obj): def link_sigad(self, obj):
if obj.pk is None: if obj.pk is None:
return "" return ""
return obj.get_sigad_url() return mark_safe(obj.get_sigad_url())
link_sigad.short_description = _("número do processo SIGAD") @admin.display(description=_("banner"))
link_sigad.allow_tags = True def get_banner(self, obj):
if obj.banner:
return mark_safe(
f'<img src="{obj.banner.url}" width="60" height="60" />'
)
else:
return ""
def lookup_allowed(self, lookup, value): def lookup_allowed(self, lookup, value):
return super(EventoAdmin, self).lookup_allowed( return super(EventoAdmin, self).lookup_allowed(

14
sigi/apps/eventos/admin_urls.py

@ -0,0 +1,14 @@
from django.urls import path, include
from sigi.apps.eventos import views
urlpatterns = [
path("calendario/", views.calendario, name="eventos_calendario"),
path(
"alocacaoequipe/", views.alocacao_equipe, name="eventos_alocacaoequipe"
),
path(
"evento/<int:id>/declaracao/",
views.declaracao,
name="evento-declaracao",
),
]

7
sigi/apps/eventos/forms.py

@ -12,11 +12,13 @@ class EventoAdminForm(forms.ModelForm):
fields = ( fields = (
"tipo_evento", "tipo_evento",
"nome", "nome",
"turma",
"descricao", "descricao",
"virtual", "virtual",
"solicitante", "solicitante",
"num_processo", "num_processo",
"data_pedido", "data_pedido",
"solicitacao",
"data_inicio", "data_inicio",
"data_termino", "data_termino",
"carga_horaria", "carga_horaria",
@ -27,6 +29,11 @@ class EventoAdminForm(forms.ModelForm):
"publico_alvo", "publico_alvo",
"total_participantes", "total_participantes",
"status", "status",
"publicar",
"link_inscricao",
"contato",
"telefone",
"banner",
"data_cancelamento", "data_cancelamento",
"motivo_cancelamento", "motivo_cancelamento",
) )

38
sigi/apps/eventos/migrations/0024_evento_banner_evento_contato_evento_link_inscricao_and_more.py

@ -0,0 +1,38 @@
# Generated by Django 4.0.6 on 2022-07-19 02:08
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('eventos', '0023_cronograma_checklist'),
]
operations = [
migrations.AddField(
model_name='evento',
name='banner',
field=models.ImageField(blank=True, null=True, upload_to='', verbose_name='banner do evento'),
),
migrations.AddField(
model_name='evento',
name='contato',
field=models.CharField(blank=True, max_length=100, verbose_name='contato'),
),
migrations.AddField(
model_name='evento',
name='link_inscricao',
field=models.URLField(blank=True, verbose_name='link de inscrição'),
),
migrations.AddField(
model_name='evento',
name='publicar',
field=models.BooleanField(default=False, verbose_name='publicar no site'),
),
migrations.AddField(
model_name='evento',
name='telefone',
field=models.CharField(blank=True, max_length=30, verbose_name='tefone de contato'),
),
]

18
sigi/apps/eventos/migrations/0025_evento_turma.py

@ -0,0 +1,18 @@
# Generated by Django 4.1 on 2022-08-08 22:45
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("eventos", "0024_evento_banner_evento_contato_evento_link_inscricao_and_more"),
]
operations = [
migrations.AddField(
model_name="evento",
name="turma",
field=models.CharField(blank=True, max_length=100, verbose_name="turma"),
),
]

31
sigi/apps/eventos/migrations/0026_preenche_turma.py

@ -0,0 +1,31 @@
# Generated by Django 4.1 on 2022-08-08 22:46
from django.db import migrations
def separa_turma(apps, schema_editor):
Evento = apps.get_model("eventos", "Evento")
for evento in Evento.objects.filter(nome__icontains="Turma"):
split_name = evento.nome.rsplit("-", 1)
if len(split_name) == 2:
evento.nome = split_name[0].strip()
evento.turma = split_name[1].strip()
evento.save()
def junta_turma(apps, schema_editor):
Evento = apps.get_model("eventos", "Evento")
for evento in Evento.objects.exclude(turma=""):
evento.nome = evento.nome + " - " + evento.turma
evento.save()
class Migration(migrations.Migration):
dependencies = [
("eventos", "0025_evento_turma"),
]
operations = [
migrations.RunPython(separa_turma, junta_turma),
]

20
sigi/apps/eventos/migrations/0027_tipoevento_casa_solicita.py

@ -0,0 +1,20 @@
# Generated by Django 4.1 on 2022-08-08 22:50
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("eventos", "0026_preenche_turma"),
]
operations = [
migrations.AddField(
model_name="tipoevento",
name="casa_solicita",
field=models.BooleanField(
default=False, verbose_name="casa pode solicitar"
),
),
]

26
sigi/apps/eventos/migrations/0028_evento_solicitacao.py

@ -0,0 +1,26 @@
# Generated by Django 4.1 on 2022-08-28 15:56
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
("ocorrencias", "0011_alter_categoria_tipo"),
("eventos", "0027_tipoevento_casa_solicita"),
]
operations = [
migrations.AddField(
model_name="evento",
name="solicitacao",
field=models.ForeignKey(
blank=True,
null=True,
on_delete=django.db.models.deletion.SET_NULL,
to="ocorrencias.ocorrencia",
verbose_name="Solicitação de origem",
),
),
]

24
sigi/apps/eventos/models.py

@ -31,6 +31,7 @@ class TipoEvento(models.Model):
categoria = models.CharField( categoria = models.CharField(
_("Categoaria"), max_length=1, choices=CATEGORIA_CHOICES _("Categoaria"), max_length=1, choices=CATEGORIA_CHOICES
) )
casa_solicita = models.BooleanField(_("casa pode solicitar"), default=False)
class Meta: class Meta:
ordering = ("nome",) ordering = ("nome",)
@ -68,6 +69,7 @@ class Evento(models.Model):
on_delete=models.PROTECT, on_delete=models.PROTECT,
) )
nome = models.CharField(_("Nome do evento"), max_length=100) nome = models.CharField(_("Nome do evento"), max_length=100)
turma = models.CharField(_("turma"), max_length=100, blank=True)
descricao = models.TextField(_("Descrição do evento")) descricao = models.TextField(_("Descrição do evento"))
virtual = models.BooleanField(_("Virtual"), default=False) virtual = models.BooleanField(_("Virtual"), default=False)
solicitante = models.CharField(_("Solicitante"), max_length=100) solicitante = models.CharField(_("Solicitante"), max_length=100)
@ -83,6 +85,13 @@ class Evento(models.Model):
blank=True, blank=True,
help_text=_("Data em que o pedido do Gabinete chegou à COPERI"), help_text=_("Data em que o pedido do Gabinete chegou à COPERI"),
) )
solicitacao = models.ForeignKey(
"ocorrencias.Ocorrencia",
blank=True,
null=True,
verbose_name=_("Solicitação de origem"),
on_delete=models.SET_NULL,
)
data_inicio = models.DateTimeField( data_inicio = models.DateTimeField(
_("Data/hora do Início"), null=True, blank=True _("Data/hora do Início"), null=True, blank=True
) )
@ -111,6 +120,13 @@ class Evento(models.Model):
), ),
) )
status = models.CharField(_("Status"), max_length=1, choices=STATUS_CHOICES) status = models.CharField(_("Status"), max_length=1, choices=STATUS_CHOICES)
publicar = models.BooleanField(_("publicar no site"), default=False)
link_inscricao = models.URLField(_("link de inscrição"), blank=True)
contato = models.CharField(_("contato"), max_length=100, blank=True)
telefone = models.CharField(
_("tefone de contato"), max_length=30, blank=True
)
banner = models.ImageField(_("banner do evento"), blank=True, null=True)
data_cancelamento = models.DateField( data_cancelamento = models.DateField(
_("Data de cancelamento"), blank=True, null=True _("Data de cancelamento"), blank=True, null=True
) )
@ -156,10 +172,17 @@ class Evento(models.Model):
raise ValidationError( raise ValidationError(
_("Data de término deve ser posterior à data de início") _("Data de término deve ser posterior à data de início")
) )
super().save(*args, **kwargs)
save_again = False
total = self.convite_set.aggregate(total=Sum("qtde_participantes")) total = self.convite_set.aggregate(total=Sum("qtde_participantes"))
total = total["total"] total = total["total"]
if total and total > 0: if total and total > 0:
self.total_participantes = total self.total_participantes = total
super().save(*args, **kwargs)
if self.status in [ if self.status in [
Evento.STATUS_PLANEJAMENTO, Evento.STATUS_PLANEJAMENTO,
Evento.STATUS_AGUARDANDOSIGAD, Evento.STATUS_AGUARDANDOSIGAD,
@ -194,7 +217,6 @@ class Evento(models.Model):
self.calcula_datas(cronograma_list) self.calcula_datas(cronograma_list)
for item in cronograma_list: for item in cronograma_list:
item.save() item.save()
super().save(*args, **kwargs)
def calcula_datas(self, cronograma_list): def calcula_datas(self, cronograma_list):
def ajusta_data(elemento, data_termino): def ajusta_data(elemento, data_termino):

2
sigi/apps/eventos/templates/eventos/convida_casa.html

@ -125,7 +125,7 @@
$(`#id_contato-${campos[x][1]}`).val($(`#id_presidente-${campos[x][0]}`).val()); $(`#id_contato-${campos[x][1]}`).val($(`#id_presidente-${campos[x][0]}`).val());
} }
}); });
$.ajax("{% url 'parlamentar-json' casa.id %}", { $.ajax("{% url 'parlamentares:parlamentar_json' casa.id %}", {
dataType: 'json', dataType: 'json',
success: function(data) { success: function(data) {
function complete(nome) { function complete(nome) {

21
sigi/apps/eventos/templates/eventos/lista.html

@ -0,0 +1,21 @@
{% load i18n %}
<div class="row">
{% for evento in object_list %}
<div class="col-md-12">
<div style="padding: 24px;">
<h4 id="demo" style="margin-left:1em;">{{ evento.data_inicio|date:"SHORT_DATE_FORMAT" }}</h4>
</div>
<div class="col-md-2 hora">
<div class="box-hora">{{ evento.data_inicio|date:"G\hi" }}</div>
<br>
</div>
<div class="col-md-10">
<a style="color:#0095da;" href="#!">{{ evento.nome }}</a>
<div style="color:#666;">{% blocktrans with local=evento.local %}Local: {{ local }}{% endblocktrans %}</div>
<br>
</div>
</div>
{% empty %}
<div class="col-md-12">{% trans 'No events yet.' %}</div>
{% endfor %}
</div>

45
sigi/apps/eventos/urls.py

@ -1,47 +1,4 @@
from django.urls import path, include from django.urls import path, include
from sigi.apps.eventos import views from sigi.apps.eventos import views
urlpatterns = [ urlpatterns = []
path("calendario/", views.calendario, name="eventos-calendario"),
path(
"alocacaoequipe/", views.alocacao_equipe, name="eventos-alocacao-equipe"
),
path("evento/<int:id>/", views.evento, name="eventos-evento"),
path(
"evento/<int:evento_id>/convite/<casa_id>/",
views.convida_casa,
name="eventos-evento-convida",
),
path(
"evento/<int:id>/declaracao/",
views.declaracao,
name="evento-declaracao",
),
path(
"evento/presidente/<int:presidente_id>/",
views.presidente_form,
name="presidente-form-snippet",
),
]
# from django.conf.urls import patterns, url
# urlpatterns = patterns(
# 'sigi.apps.eventos.views',
# # Painel de ocorrencias
# url(r'^calendario/$', 'calendario', name='eventos-calendario'),
# url(r'^alocacaoequipe/$', 'alocacao_equipe', name='eventos-alocacaoequipe'),
# # Carrinho
# url(r'^evento/carrinho/$', 'visualizar_carrinho',
# name='visualizar-carrinho-evento'),
# url(r'^evento/carrinho/excluir_carrinho/$', 'excluir_carrinho',
# name='excluir-carrinho-evento'), # Error
# url(r'^evento/carrinho/deleta_itens_carrinho$', 'deleta_itens_carrinho',
# name='deleta-itens-carrinho-evento'), # Error
# url(r'^evento/csv/$', 'export_csv', name='evento-export-csv'), # Error
# url(r'^evento/(?P<id>\w+)/declaracao/$', 'declaracao',
# name='evento-declaracao'),
# )

224
sigi/apps/eventos/views.py

@ -5,8 +5,9 @@ from functools import reduce
from typing import OrderedDict from typing import OrderedDict
from django import forms from django import forms
from django.contrib import messages from django.contrib import messages
from django.contrib.admin.sites import site from django.contrib.admin.views.decorators import staff_member_required
from django.contrib.auth.decorators import login_required from django.contrib.auth.decorators import login_required
from django.core.paginator import Paginator
from django.http import HttpResponse from django.http import HttpResponse
from django.shortcuts import redirect, render, get_object_or_404 from django.shortcuts import redirect, render, get_object_or_404
from django.template import Template, Context from django.template import Template, Context
@ -19,6 +20,8 @@ from django.utils.translation import (
gettext as _, gettext as _,
) )
from django.urls import reverse from django.urls import reverse
from django.views.decorators.clickjacking import xframe_options_exempt
from django.views.generic import ListView
from django_weasyprint.utils import django_url_fetcher from django_weasyprint.utils import django_url_fetcher
from django_weasyprint.views import WeasyTemplateResponse from django_weasyprint.views import WeasyTemplateResponse
from weasyprint import HTML from weasyprint import HTML
@ -37,6 +40,7 @@ from sigi.apps.servidores.models import Servidor
@login_required @login_required
@staff_member_required
def calendario(request): def calendario(request):
mes_pesquisa = int(request.GET.get("mes", timezone.localdate().month)) mes_pesquisa = int(request.GET.get("mes", timezone.localdate().month))
ano_pesquisa = int(request.GET.get("ano", timezone.localdate().year)) ano_pesquisa = int(request.GET.get("ano", timezone.localdate().year))
@ -62,7 +66,7 @@ def calendario(request):
data_inicio__year=ano_pesquisa, data_inicio__month=mes_pesquisa data_inicio__year=ano_pesquisa, data_inicio__month=mes_pesquisa
) )
context = site.each_context(request) or {} context = {}
if formato == "cal" or pdf: if formato == "cal" or pdf:
semanas = calendar.Calendar().monthdatescalendar( semanas = calendar.Calendar().monthdatescalendar(
@ -111,6 +115,7 @@ def calendario(request):
@login_required @login_required
@staff_member_required
def declaracao(request, id): def declaracao(request, id):
if request.method == "POST": if request.method == "POST":
form = SelecionaModeloForm(request.POST) form = SelecionaModeloForm(request.POST)
@ -162,206 +167,33 @@ def declaracao(request, id):
else: else:
form = SelecionaModeloForm() form = SelecionaModeloForm()
context = site.each_context(request) context = {"form": form, "evento_id": id}
context["form"] = form
context["evento_id"] = id
return render(request, "eventos/seleciona_modelo.html", context) return render(request, "eventos/seleciona_modelo.html", context)
def evento(request, id): class eventoListView(ListView):
context = site.each_context(request) model = Evento
evento = get_object_or_404(Evento, id=id) paginate_by = 100
anexo_id = request.GET.getlist("anexo_id", None) template_name = "eventos/lista.html"
if anexo_id:
context["anexos"] = evento.anexo_set.filter(id__in=anexo_id)
context["active"] = "anexos"
else:
context["anexos"] = evento.anexo_set.all()
context["evento"] = evento
context["fields"] = [
"tipo_evento",
"descricao",
"virtual",
"publico_alvo",
"data_inicio",
"data_termino",
"carga_horaria",
"casa_anfitria",
"municipio",
"local",
]
context["convite_fields"] = [
"casa",
"servidor",
"data_convite",
"aceite",
"participou",
"nomes_participantes",
]
context["anexo_fields"] = ["descricao", "data_pub", "arquivo"]
return render(request, "eventos/evento.html", context)
def convida_casa(request, evento_id, casa_id):
if not request.user.servidor:
messages.error(
request, _("Você não é servidor, não pode registrar convites")
)
return redirect(reverse("eventos-evento", args=[evento_id]))
evento = get_object_or_404(Evento, id=evento_id)
casa = get_object_or_404(Orgao, id=casa_id)
projetos = Projeto.objects.exclude(modelo_minuta="")
if evento.convite_set.filter(casa=casa).exists():
convite = evento.convite_set.get(casa=casa)
else:
convite = Convite(
evento=evento,
casa=casa,
servidor=request.user.servidor,
data_convite=timezone.localdate(),
)
contato = casa.contato_interlegis or Funcionario(
casa_legislativa=casa, setor="contato_interlegis"
)
presidente = casa.presidente
parlamentares = casa.parlamentar_set.all()
if request.method == "POST":
id_presidente = request.POST.get("id_presidente", None)
if id_presidente is None:
messages.error(request, _("Presidente não foi identificado"))
return redirect(".")
presidente = get_object_or_404(Parlamentar, id=id_presidente)
form_convite = ConviteForm(request.POST, instance=convite)
form_casa = CasaForm(request.POST, request.FILES, instance=casa)
form_presidente = ParlamentarForm(
request.POST, instance=presidente, prefix="presidente"
)
form_contato = FuncionarioForm(
request.POST, instance=contato, prefix="contato"
)
if all(
[
form_convite.is_valid(),
form_casa.is_valid(),
form_presidente.is_valid(),
form_contato.is_valid(),
]
):
contato = form_contato.save(commit=False)
contato.setor = "contato_interlegis"
contato.save()
presidente = form_presidente.save(commit=False)
presidente.status_mandato = "E"
presidente.presidente = True
presidente.save()
casa = form_casa.save()
convite = form_convite.save()
proj_id = request.POST.get("save", "")
if proj_id:
convite.anexo_set.all().delete()
query_str = ""
projeto = get_object_or_404(Projeto, id=proj_id)
if projeto.texto_oficio:
oficio = Anexo(
evento=evento,
descricao=f"Ofício de solicitação de {projeto.sigla}",
)
sigla_casa = casa.sigla or "".join(
[
w[0].upper()
for w in casa.nome.replace("de", "").split()
]
)
oficio.arquivo.name = (
f"{Anexo.arquivo.field.upload_to}/"
f"oficio_{projeto.sigla}_{sigla_casa}.pdf"
)
projeto.gerar_oficio(
oficio.arquivo,
casa,
presidente,
contato,
request.build_absolute_uri("/"),
)
oficio.save()
query_str += f"anexo_id={oficio.id}&"
if projeto.modelo_minuta:
nome = f"Minuta de {projeto.sigla} da {casa.nome}"[:70]
minuta = Anexo(descricao=nome, evento=evento)
minuta.arquivo.name = (
f"{Anexo.arquivo.field.upload_to}/"
f"minuta_{projeto.sigla}_{sigla_casa}.docx"
)
projeto.gerar_minuta(
minuta.arquivo.path, casa, presidente, contato
)
minuta.save()
query_str += f"anexo_id={minuta.id}"
return redirect(evento.get_absolute_url() + "?" + query_str)
else:
return redirect(evento.get_absolute_url())
else:
messages.error(request, _("Preencha corretamente o convite"))
else:
form_convite = ConviteForm(instance=convite)
form_casa = CasaForm(instance=casa)
form_contato = FuncionarioForm(instance=contato, prefix="contato")
if presidente:
form_presidente = ParlamentarForm(
instance=presidente, prefix="presidente"
)
else:
form_presidente = ""
context = site.each_context(request) or {}
context.update(
{
"form_convite": form_convite,
"form_casa": form_casa,
"form_contato": form_contato,
"form_presidente": form_presidente,
"evento": evento,
"convite": convite,
"casa": casa,
"presidente": presidente,
"contato": contato,
"projetos": projetos,
"parlamentares": parlamentares,
}
)
return render(request, "eventos/convida_casa.html", context) def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context.update({"embed": bool(self.request.GET.get("embed", False))})
return context
def get_queryset(self):
queryset = super().get_queryset()
return queryset.filter(
status=Evento.STATUS_CONFIRMADO, publicar=True
).order_by("data_inicio")
@login_required @xframe_options_exempt
def presidente_form(request, presidente_id): def get(self, request, *args, **kwargs):
presidente = get_object_or_404(Parlamentar, pk=presidente_id) return super().get(request, *args, **kwargs)
form = ParlamentarForm(instance=presidente, prefix="presidente")
return render(
request,
"eventos/snippets/form_presidente_snippet.html",
{
"form_presidente": form,
"presidente": presidente,
},
)
@login_required @login_required
@staff_member_required
def alocacao_equipe(request): def alocacao_equipe(request):
ano_pesquisa = int(request.GET.get("ano", timezone.localdate().year)) ano_pesquisa = int(request.GET.get("ano", timezone.localdate().year))
mes_pesquisa = int(request.GET.get("mes", 0)) mes_pesquisa = int(request.GET.get("mes", 0))
@ -489,9 +321,7 @@ def alocacao_equipe(request):
] ]
) )
context = site.each_context(request) or {} context = {
context.update(
{
"anos": Evento.objects.exclude(data_inicio=None) "anos": Evento.objects.exclude(data_inicio=None)
.order_by("data_inicio__year") .order_by("data_inicio__year")
.distinct("data_inicio__year") .distinct("data_inicio__year")
@ -499,7 +329,7 @@ def alocacao_equipe(request):
"ano_pesquisa": ano_pesquisa, "ano_pesquisa": ano_pesquisa,
"linhas": linhas, "linhas": linhas,
} }
)
if mes_pesquisa > 0: if mes_pesquisa > 0:
context["mes_pesquisa"] = mes_pesquisa context["mes_pesquisa"] = mes_pesquisa
context["meses"] = meses context["meses"] = meses

37
sigi/apps/home/accounts_urls.py

@ -0,0 +1,37 @@
from django.urls import path
from sigi.apps.home import views
urlpatterns = [
path("login/", views.LoginView.as_view(), name="login"),
path("logout/", views.LogoutView.as_view(), name="logout"),
path(
"password_change/",
views.PasswordChangeView.as_view(),
name="password_change",
),
path(
"password_change/done/",
views.PasswordChangeDoneView.as_view(),
name="password_change_done",
),
path(
"password_reset/",
views.PasswordResetView.as_view(),
name="password_reset",
),
path(
"password_reset/done/",
views.PasswordResetDoneView.as_view(),
name="password_reset_done",
),
path(
"reset/<uidb64>/<token>/",
views.PasswordResetConfirmView.as_view(),
name="password_reset_confirm",
),
path(
"reset/done/",
views.PasswordResetCompleteView.as_view(),
name="password_reset_complete",
),
]

2
sigi/apps/home/fixtures/cards.json

@ -1 +1 @@
[{"model": "home.cards", "pk": 1, "fields": {"codigo": "resumoseit", "tipo": "T", "nome_url": "home_resumoseit", "query_string": "", "link_acao": false, "titulo": "Serviços hospedados no Interlegis (SEIT)", "descricao": "Tabela com os serviços criados no SEIT por mês", "categoria": "Serviços", "ordem": 1, "default": true}}, {"model": "home.cards", "pk": 2, "fields": {"codigo": "chartseit", "tipo": "C", "nome_url": "home_chartseit", "query_string": "", "link_acao": true, "titulo": "Sazonalidade da hospedagem de serviços", "descricao": "Gráfico com a sazonalidade das solicitações de serviços", "categoria": "Serviços", "ordem": 2, "default": true}}, {"model": "home.cards", "pk": 3, "fields": {"codigo": "carteira", "tipo": "T", "nome_url": "casas-carteira", "query_string": "snippet=resumo&s=sim", "link_acao": false, "titulo": "Resumo da carteira de relacionamentos", "descricao": "Tabela resumindo a carteira de gerência Interlegis", "categoria": "Gerente", "ordem": 1, "default": true}}, {"model": "home.cards", "pk": 4, "fields": {"codigo": "performance", "tipo": "C", "nome_url": "home_chartperformance", "query_string": "", "link_acao": true, "titulo": "Performance da gerência de carteiras", "descricao": "Performance da gerência de carteiras", "categoria": "Gerente", "ordem": 2, "default": true}}, {"model": "home.cards", "pk": 5, "fields": {"codigo": "chartcarteira", "tipo": "C", "nome_url": "home_chartcarteira", "query_string": "", "link_acao": false, "titulo": "Distribuição de Casas por Gerente", "descricao": "Distribuição de Casas por Gerente", "categoria": "Gerente", "ordem": 3, "default": true}}, {"model": "home.cards", "pk": 6, "fields": {"codigo": "resumoconvenios", "tipo": "T", "nome_url": "home_resumoconvenios", "query_string": "", "link_acao": false, "titulo": "Resumo de informações", "descricao": "Resumo de informações", "categoria": "Geral", "ordem": 1, "default": true}}, {"model": "home.cards", "pk": 7, "fields": {"codigo": "chartusoservico", "tipo": "C", "nome_url": "home_chartusoservico", "query_string": "", "link_acao": true, "titulo": "Uso dos serviços SEIT", "descricao": "Mostra como serviços SEIT estão sendo usados pelas Casas", "categoria": "Serviços", "ordem": 3, "default": true}}, {"model": "home.cards", "pk": 8, "fields": {"codigo": "chartatualizacao", "tipo": "C", "nome_url": "home_chartatualizacao", "query_string": "", "link_acao": false, "titulo": "Frequência de atualização", "descricao": "Mostra a frequência com que os portais são atualizados pelas Casas", "categoria": "Serviços", "ordem": 4, "default": true}}, {"model": "home.cards", "pk": 9, "fields": {"codigo": "eventosstatus", "tipo": "C", "nome_url": "eventos_status", "query_string": "", "link_acao": false, "titulo": "Eventos por status", "descricao": "Eventos por status", "categoria": "Eventos", "ordem": 1, "default": true}}, {"model": "home.cards", "pk": 10, "fields": {"codigo": "eventoscategoria", "tipo": "C", "nome_url": "eventos_categoria", "query_string": "", "link_acao": false, "titulo": "Eventos realizados por categoria", "descricao": "Eventos por categoria", "categoria": "Eventos", "ordem": 2, "default": true}}, {"model": "home.cards", "pk": 11, "fields": {"codigo": "eventosano", "tipo": "C", "nome_url": "eventos_ano", "query_string": "", "link_acao": true, "titulo": "Eventos dos últimos 12 meses", "descricao": "Eventos dos últimos 12 meses", "categoria": "Eventos", "ordem": 3, "default": true}}] [{"model": "home.cards", "pk": 1, "fields": {"codigo": "resumoseit", "tipo": "T", "nome_url": "home_resumoseit", "query_string": "", "link_acao": false, "titulo": "Serviços hospedados no Interlegis (SEIT)", "descricao": "Tabela com os serviços criados no SEIT por mês", "categoria": "Serviços", "ordem": 1, "default": true}}, {"model": "home.cards", "pk": 2, "fields": {"codigo": "chartseit", "tipo": "C", "nome_url": "home_chartseit", "query_string": "", "link_acao": true, "titulo": "Sazonalidade da hospedagem de serviços", "descricao": "Gráfico com a sazonalidade das solicitações de serviços", "categoria": "Serviços", "ordem": 2, "default": true}}, {"model": "home.cards", "pk": 3, "fields": {"codigo": "carteira", "tipo": "T", "nome_url": "casas_carteira", "query_string": "snippet=resumo&s=sim", "link_acao": false, "titulo": "Resumo da carteira de relacionamentos", "descricao": "Tabela resumindo a carteira de gerência Interlegis", "categoria": "Gerente", "ordem": 1, "default": true}}, {"model": "home.cards", "pk": 4, "fields": {"codigo": "performance", "tipo": "C", "nome_url": "home_chartperformance", "query_string": "", "link_acao": true, "titulo": "Performance da gerência de carteiras", "descricao": "Performance da gerência de carteiras", "categoria": "Gerente", "ordem": 2, "default": true}}, {"model": "home.cards", "pk": 5, "fields": {"codigo": "chartcarteira", "tipo": "C", "nome_url": "home_chartcarteira", "query_string": "", "link_acao": false, "titulo": "Distribuição de Casas por Gerente", "descricao": "Distribuição de Casas por Gerente", "categoria": "Gerente", "ordem": 3, "default": true}}, {"model": "home.cards", "pk": 6, "fields": {"codigo": "resumoconvenios", "tipo": "T", "nome_url": "home_resumoconvenios", "query_string": "", "link_acao": false, "titulo": "Resumo de informações", "descricao": "Resumo de informações", "categoria": "Geral", "ordem": 1, "default": true}}, {"model": "home.cards", "pk": 7, "fields": {"codigo": "chartusoservico", "tipo": "C", "nome_url": "home_chartusoservico", "query_string": "", "link_acao": true, "titulo": "Uso dos serviços SEIT", "descricao": "Mostra como serviços SEIT estão sendo usados pelas Casas", "categoria": "Serviços", "ordem": 3, "default": true}}, {"model": "home.cards", "pk": 8, "fields": {"codigo": "chartatualizacao", "tipo": "C", "nome_url": "home_chartatualizacao", "query_string": "", "link_acao": false, "titulo": "Frequência de atualização", "descricao": "Mostra a frequência com que os portais são atualizados pelas Casas", "categoria": "Serviços", "ordem": 4, "default": true}}, {"model": "home.cards", "pk": 9, "fields": {"codigo": "eventosstatus", "tipo": "C", "nome_url": "eventos_status", "query_string": "", "link_acao": false, "titulo": "Eventos por status", "descricao": "Eventos por status", "categoria": "Eventos", "ordem": 1, "default": true}}, {"model": "home.cards", "pk": 10, "fields": {"codigo": "eventoscategoria", "tipo": "C", "nome_url": "eventos_categoria", "query_string": "", "link_acao": false, "titulo": "Eventos realizados por categoria", "descricao": "Eventos por categoria", "categoria": "Eventos", "ordem": 2, "default": true}}, {"model": "home.cards", "pk": 11, "fields": {"codigo": "eventosano", "tipo": "C", "nome_url": "eventos_ano", "query_string": "", "link_acao": true, "titulo": "Eventos dos últimos 12 meses", "descricao": "Eventos dos últimos 12 meses", "categoria": "Eventos", "ordem": 3, "default": true}}]

6
sigi/apps/home/forms.py

@ -0,0 +1,6 @@
from django import forms
from django.utils.translation import gettext as _
from localflavor.br.forms import BRCNPJField, BRCPFField, BRZipCodeField
from material.admin.widgets import MaterialAdminTextareaWidget
from sigi.apps.casas.models import Funcionario, Orgao
from sigi.apps.parlamentares.models import Parlamentar

35
sigi/apps/home/mixins.py

@ -0,0 +1,35 @@
from django.shortcuts import get_object_or_404
from sigi.apps.casas.models import Orgao
class ContatoInterlegisViewMixin:
def get_casa(self):
user = self.request.user
if "casa_id" in self.request.session:
casa_id = int(self.request.session["casa_id"])
casa = Orgao.objects.filter(id=casa_id).first()
elif "casa_id" in self.request.GET:
casa_id = int(self.request.GET["casa_id"])
casa = Orgao.objects.filter(id=casa_id).first()
elif user.is_anonymous and hasattr(
self.get_object(), "casa_legislativa"
):
casa = self.get_object().casa_legislativa
else:
casa = Orgao.objects.filter(funcionario__email=user.email).first()
if casa:
self.request.session["casa_id"] = casa.id
return casa
def get_contato(self):
if self.request.user.is_anonymous:
return self.get_casa().contato_interlegis
return self.get_casa().funcionario_set.get(
email=self.request.user.email
)
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context["casa"] = self.get_casa()
return context

11
sigi/apps/home/templates/home/dashboard/card.html

@ -34,7 +34,16 @@
<body data-admin-utc-offset="{% now 'Z' %}"> <body data-admin-utc-offset="{% now 'Z' %}">
<div id="container"> <div id="container">
<div id="content" class="colM"> <div id="content" class="colM">
{% include 'sigi/snippets/dashboard.html' %} <div class="content-wrapper">
<div class="app-list">
{% url card.nome_url as source_url %}
{% if card.tipo == 'C' %}
{% include "sigi/snippets/base_card_chart.html" with card_title=card.titulo data_source=source_url|add:"?"|add:card.query_string chart_name=card.codigo has_action_links=card.link_acao %}
{% else %}
{% include "sigi/snippets/base_card_text.html" with card_title=card.titulo data_source=source_url|add:"?"|add:card.query_string card_name=card.codigo %}
{% endif %}
</div>
</div>
<br class="clear"> <br class="clear">
</div> </div>
<div id="footer"> <div id="footer">

18
sigi/apps/home/templates/home/openmap.html

@ -33,8 +33,22 @@
{% block usertools %} {% block usertools %}
<div id="user-tools"> <div id="user-tools">
<a href="{% url 'admin:index' %}">{% trans "Entrar" %}</a> {% if user.is_authenticated %}
<a href="{% url 'ocorrencias-seleciona-casa' %}">{% trans "Solicitar convênio" %}</a> {% if user.is_staff %}
{% url 'admin:index' as entry_page %}
{% else %}
{% url 'change_password' as entry_page %}
{% endif %}
<a href="{% url 'logout' %}">
{% trans 'Log out' %}
<i class="material-icons" aria-hidden="true">exit_to_app</i>
</a>
{% else %}
{% url 'login' as entry_page %}
{% endif %}
<a href="{{ entry_page }}">{% trans "Entrar" %}</a>
<a href="{% url 'ocorrencias:ocorrencia_convenio_seleciona_casa' %}">{% trans "Solicitar convênio" %}</a>
<a href="{% url 'ocorrencias:ocorrencia_oficina_seleciona_casa' %}">{% trans "Solicitar oficinas" %}</a>
</div> </div>
{% endblock %} {% endblock %}

63
sigi/apps/home/templates/home/public_site/index.html

@ -0,0 +1,63 @@
{% extends 'public/base_site.html' %}
{% load i18n %}
{% block content %}
{{ block.super }}
{% if ocorrencias.count > 0 %}
<div class="row">
<div class="col s12">
<div class="card">
<div class="card-content">
<span class="card-title">{% trans 'Últimas ocorrências' %}</span>
<ul class="collection">
{% for ocorrencia in ocorrencias %}
<li class="collection-item">
<span class="badge">{{ ocorrencia.comentarios.all|length }}</span>
<p><a href="{% url 'ocorrencias:ocorrencia_listview' %}#ocorrencia-{{ ocorrencia.id|safe }}">{{ ocorrencia.data_criacao|date:'SHORT_DATE_FORMAT' }} {{ ocorrencia.assunto }}</a></p>
</li>
{% endfor %}
</ul>
</div>
<div class="card-action">
<a href="{% url 'ocorrencias:ocorrencia_listview' %}">{% trans 'Ver todas' %}</a>
<a href="{% url 'ocorrencias:solicita_oficina_create' %}">{% trans "Solicitar treinamento" %}</a>
</div>
</div>
</div>
</div>
{% endif %}
{% if servicos.count > 0 %}
<div class="row">
<div class="col s12">
<div class="card">
<div class="card-content">
<span class="card-title">{% trans 'Servicos ativos' %}</span>
<table class="striped">
<tr>
<th>{% trans 'Serviço' %}</th>
<th>{% trans 'Endereço' %}</th>
<th>{% trans 'Ativado' %}</th>
<th>{% trans 'Verificado' %}</th>
<th>{% trans 'Resultado verificação' %}</th>
<th>{% trans 'Último uso' %}</th>
</tr>
{% for servico in servicos %}
<tr>
<td>{{ servico.tipo_servico }}</td>
<td>
<a href="{{ servico.url }}">{{ servico.url }}</a>
</td>
<td>{{ servico.data_ativacao|date:'SHORT_DATE_FORMAT' }}</td>
<td>{{ servico.data_verificacao|date:'SHORT_DATE_FORMAT' }}</td>
<td>{{ servico.get_resultado_verificacao_display }}</td>
<td>{{ servico.data_ultimo_uso|date:'SHORT_DATE_FORMAT' }}</td>
</tr>
{% endfor %}
</table>
</div>
</div>
</div>
</div>
{% endif %}
{% endblock %}

2
sigi/apps/home/urls.py

@ -2,6 +2,8 @@ from django.urls import path
from sigi.apps.home import views from sigi.apps.home import views
urlpatterns = [ urlpatterns = [
# Acesso público autenticado #
path("home/", views.HomeView.as_view(), name="home_index"),
# mapa # # mapa #
path("", views.openmap, name="openmap"), path("", views.openmap, name="openmap"),
path("openmapdata/", views.openmapdata, name="openmapdata"), path("openmapdata/", views.openmapdata, name="openmapdata"),

138
sigi/apps/home/views.py

@ -3,11 +3,14 @@ import csv
import datetime import datetime
from itertools import cycle from itertools import cycle
from random import randint, seed from random import randint, seed
from django import forms
from django.conf import settings
from django.contrib import messages from django.contrib import messages
from django.contrib.admin.sites import site from django.contrib.admin.sites import site
from django.contrib.auth import views as auth_views
from django.contrib.auth.decorators import login_required from django.contrib.auth.decorators import login_required
from django.contrib.auth.mixins import LoginRequiredMixin
from django.core.exceptions import PermissionDenied from django.core.exceptions import PermissionDenied
from django.db import models
from django.db.models import Q, Count from django.db.models import Q, Count
from django.http import ( from django.http import (
HttpResponse, HttpResponse,
@ -15,33 +18,33 @@ from django.http import (
HttpResponseRedirect, HttpResponseRedirect,
JsonResponse, JsonResponse,
) )
from django.shortcuts import render, get_object_or_404 from django.shortcuts import render, get_object_or_404, resolve_url
from django.template.loader import render_to_string from django.template.loader import render_to_string
from django.urls import reverse from django.urls import reverse, reverse_lazy
from django.utils import timezone from django.utils import timezone
from django.utils.text import slugify from django.utils.text import slugify
from django.utils.translation import gettext as _ from django.utils.translation import gettext as _
from django.views.decorators.cache import never_cache from django.views.decorators.cache import never_cache
from django.views.decorators.clickjacking import xframe_options_exempt
from django.views.generic import (
TemplateView,
UpdateView,
ListView,
DeleteView,
CreateView,
)
from django_weasyprint.views import WeasyTemplateResponse from django_weasyprint.views import WeasyTemplateResponse
from sigi.apps.casas.models import TipoOrgao, Orgao from sigi.apps.casas.models import Funcionario, TipoOrgao, Orgao
from sigi.apps.contatos.models import UnidadeFederativa from sigi.apps.contatos.models import UnidadeFederativa
from sigi.apps.convenios.models import Convenio, Projeto from sigi.apps.convenios.models import Convenio, Projeto
from sigi.apps.eventos.models import TipoEvento, Evento from sigi.apps.eventos.models import TipoEvento, Evento
from sigi.apps.home.models import Cards, Dashboard from sigi.apps.home.models import Cards, Dashboard
from sigi.apps.ocorrencias.models import Ocorrencia
from sigi.apps.parlamentares.models import Parlamentar
from sigi.apps.servicos.models import TipoServico, Servico from sigi.apps.servicos.models import TipoServico, Servico
from sigi.apps.servidores.models import Servidor from sigi.apps.servidores.models import Servidor
from sigi.apps.utils import to_ascii from sigi.apps.utils import to_ascii
# from django.shortcuts import render, get_object_or_404
# from sigi.apps.casas.models import Orgao
# from sigi.apps.diagnosticos.models import Diagnostico
# from sigi.apps.metas.models import Meta
# from sigi.apps.servicos.models import TipoServico
# from sigi.apps.servidores.models import Servidor
# from django.http.response import JsonResponse, HttpResponse
# from sigi.shortcuts import render_to_pdf
# import csv
getcolor = ( getcolor = (
lambda s=None: f"#{randint(32,255):02x}{randint(32,255):02x}" lambda s=None: f"#{randint(32,255):02x}{randint(32,255):02x}"
@ -50,6 +53,7 @@ getcolor = (
else f"{seed(s) or ''}#{randint(32,255):02x}{randint(32,255):02x}" else f"{seed(s) or ''}#{randint(32,255):02x}{randint(32,255):02x}"
f"{randint(32,255):02x}" f"{randint(32,255):02x}"
) )
gethighlight = ( gethighlight = (
lambda s=None: f"#{randint(32,255):02x}{randint(32,255):02x}" lambda s=None: f"#{randint(32,255):02x}{randint(32,255):02x}"
f"{randint(32,255):02x}c0" f"{randint(32,255):02x}c0"
@ -57,12 +61,100 @@ gethighlight = (
else f"{seed(s) or ''}#{randint(32,255):02x}{randint(32,255):02x}" else f"{seed(s) or ''}#{randint(32,255):02x}{randint(32,255):02x}"
f"{randint(32,255):02x}c0" f"{randint(32,255):02x}c0"
) )
################################################################################
# Views para controle de acesso
################################################################################
class LoginView(auth_views.LoginView):
template_name = "registration/login.html"
def get_default_redirect_url(self):
if self.request.user.is_staff:
login_redirect_url = reverse("admin:index")
else:
login_redirect_url = settings.LOGIN_REDIRECT_URL
return resolve_url(self.next_page or login_redirect_url)
class LogoutView(auth_views.LogoutView):
template_name = "registration/logout.html"
class PasswordChangeView(auth_views.PasswordChangeView):
template_name = "material/admin/password_change.html"
class PasswordChangeDoneView(auth_views.PasswordChangeDoneView):
pass
class PasswordResetView(auth_views.PasswordResetView):
pass
class PasswordResetDoneView(auth_views.PasswordResetDoneView):
pass
class PasswordResetConfirmView(auth_views.PasswordResetConfirmView):
pass
class PasswordResetCompleteView(auth_views.PasswordResetCompleteView):
pass
################################################################################
# Views para site público - acesso dos contatos Interlegis #
################################################################################
class HomeView(LoginRequiredMixin, TemplateView):
template_name = "home/public_site/index.html"
def get_context_data(self, **kwargs):
user = self.request.user
casa_id = self.request.GET.get(
"id", self.request.session.get("casa_id", None)
)
casas = {
c.id: c for c in Orgao.objects.filter(funcionario__email=user.email)
}
if casa_id and int(casa_id) in casas:
casa = casas[int(casa_id)]
else:
if casas:
casa = list(casas.values())[0]
else:
casa = None
if casa:
self.request.session["casa_id"] = casa.id
ocorrencias = casa.ocorrencia_set.filter(
status__in=[
Ocorrencia.STATUS_ABERTO,
Ocorrencia.STATUS_REABERTO,
]
)
servicos = casa.servico_set.filter(data_desativacao=None)
context = super().get_context_data(**kwargs)
context["casas"] = casas.values()
context["casa"] = casa
context["ocorrencias"] = ocorrencias[:5]
context["servicos"] = servicos
return context
################################################################################ ################################################################################
# Views e funções do mapa de atuação do Interlegis # Views e funções do mapa de atuação do Interlegis
################################################################################ ################################################################################
def openmap(request): def openmap(request):
reptype = request.GET.get("reptype", None) reptype = request.GET.get("reptype", None)
context = site.each_context(request) context = {}
if reptype is None: if reptype is None:
context["tipos_orgao"] = TipoOrgao.objects.filter(legislativo=True) context["tipos_orgao"] = TipoOrgao.objects.filter(legislativo=True)
@ -258,11 +350,14 @@ def openmapsearch(request):
################################################################################ ################################################################################
# Views de visualização e edição do dashboard # Views de visualização e edição do dashboard
################################################################################ ################################################################################
@xframe_options_exempt
def card_snippet(request, card_code): def card_snippet(request, card_code):
card = get_object_or_404(Cards, codigo=card_code) card = get_object_or_404(Cards, codigo=card_code)
if not card.default: if not card.default:
raise PermissionDenied() raise PermissionDenied()
return render(request, "home/dashboard/card.html", {"dash_cards": [card]}) return render(request, "home/dashboard/card.html", {"card": card})
@login_required @login_required
@ -351,7 +446,10 @@ def card_add(request):
# Cards do dashboard # Cards do dashboard
################################################################################ ################################################################################
# Geral ######################################################################## # Geral ########################################################################
@never_cache @never_cache
@login_required @login_required
def resumo_convenios(request): def resumo_convenios(request):
@ -360,6 +458,8 @@ def resumo_convenios(request):
# Serviços ##################################################################### # Serviços #####################################################################
@never_cache @never_cache
@login_required @login_required
def resumo_seit(request): def resumo_seit(request):
@ -531,6 +631,8 @@ def chart_atualizacao_servicos(request):
# Gerente ###################################################################### # Gerente ######################################################################
@never_cache @never_cache
@login_required @login_required
def chart_carteira(request): def chart_carteira(request):
@ -606,6 +708,8 @@ def chart_performance(request):
# Eventos ###################################################################### # Eventos ######################################################################
@never_cache @never_cache
@login_required @login_required
def eventos_status(request): def eventos_status(request):
@ -724,6 +828,8 @@ def eventos_ano(request):
################################################################################ ################################################################################
# Views de apoio e relatórios # Views de apoio e relatórios
################################################################################ ################################################################################
@never_cache @never_cache
@login_required @login_required
def report_sem_convenio(request): def report_sem_convenio(request):

18
sigi/apps/ocorrencias/admin_urls.py

@ -2,11 +2,19 @@ from django.urls import path
from sigi.apps.ocorrencias import views from sigi.apps.ocorrencias import views
urlpatterns = [ urlpatterns = [
path("painel/", views.painel_ocorrencias, name="painel-ocorrencias"),
path("convenio/painel/", views.painel_convenio, name="painel-convenio"),
path( path(
"convenio/painel/<int:ocorrencia_id>/", "painel/",
views.painel_convenio, views.PainelOcorrenciaView.as_view(),
name="painel-convenio", name="ocorrencias_painel",
),
path(
"painel/oficina/<int:pk>/",
views.OficinaChangeView.as_view(),
name="ocorrencias_painel_oficina",
),
path(
"painel/convenio/<int:pk>/",
views.ConvenioChangeView.as_view(),
name="ocorrencias_painel_convenio",
), ),
] ]

7
sigi/apps/ocorrencias/apps.py

@ -0,0 +1,7 @@
from django.apps import AppConfig
from django.utils.translation import gettext_lazy as _
class CasasConfig(AppConfig):
name = "sigi.apps.ocorrencias"
verbose_name = _("ocorrências")

98
sigi/apps/ocorrencias/forms.py

@ -10,9 +10,10 @@ from django.utils.safestring import mark_safe
from django.utils.translation import ngettext, gettext as _ from django.utils.translation import ngettext, gettext as _
from material.admin.widgets import MaterialAdminTextareaWidget from material.admin.widgets import MaterialAdminTextareaWidget
from sigi.apps.casas.models import Funcionario, Orgao from sigi.apps.casas.models import Funcionario, Orgao
from sigi.apps.eventos.models import TipoEvento
from sigi.apps.ocorrencias.models import Ocorrencia, Comentario, Anexo from sigi.apps.ocorrencias.models import Ocorrencia, Comentario, Anexo
from sigi.apps.servidores.models import Servico from sigi.apps.servidores.models import Servico
from sigi.apps.parlamentares.models import Parlamentar from sigi.apps.parlamentares.models import Parlamentar, Senador
class AjaxSelect(forms.TextInput): class AjaxSelect(forms.TextInput):
@ -56,11 +57,9 @@ class AnexoForm(forms.ModelForm):
class Meta: class Meta:
model = Anexo model = Anexo
fields = [ fields = [
"ocorrencia",
"descricao", "descricao",
"arquivo", "arquivo",
] ]
widgets = {"ocorrencia": forms.HiddenInput()}
class ComentarioForm(forms.ModelForm): class ComentarioForm(forms.ModelForm):
@ -89,16 +88,10 @@ class OcorrenciaForm(forms.ModelForm):
"ticket", "ticket",
"descricao", "descricao",
] ]
widgets = {
"casa_legislativa": AutocompleteSelect(
Ocorrencia.casa_legislativa.field, admin.site
)
}
# widgets = { # widgets = {
# 'casa_legislativa': AjaxSelect( # "casa_legislativa": AutocompleteSelect(
# url=reverse_lazy('painel-buscacasa'), # Ocorrencia.casa_legislativa.field, admin.site
# attrs={'size':100} # )
# ),
# } # }
@ -108,6 +101,32 @@ class OcorrenciaChangeForm(forms.ModelForm):
fields = ["prioridade", "processo_sigad"] fields = ["prioridade", "processo_sigad"]
class AutorizaOficinaForm(forms.ModelForm):
oficinas = forms.ModelMultipleChoiceField(
label=_("Oficinas"),
queryset=TipoEvento.objects.filter(casa_solicita=True),
required=True,
help_text=_("Selecione as oficinas que deseja autorizar."),
widget=forms.CheckboxSelectMultiple,
)
virtual = forms.BooleanField(label=_("Virtual"))
data_inicio = forms.DateField(label=_("Data de início"), required=True)
data_termino = forms.DateField(label=_("Data de término"), required=True)
class Meta:
model = Ocorrencia
fields = ["oficinas", "virtual", "data_inicio", "data_termino"]
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
autorizadas = self.instance.evento_set.values_list(
"tipo_evento_id", flat=True
)
self.fields["oficinas"].queryset = TipoEvento.objects.filter(
id__in=self.instance.infos["solicita_oficinas"]["oficinas"]
).exclude(id__in=autorizadas)
class CasaForm(forms.ModelForm): class CasaForm(forms.ModelForm):
class Meta: class Meta:
model = Orgao model = Orgao
@ -189,9 +208,64 @@ class ComentarioForm(forms.ModelForm):
class Meta: class Meta:
model = Comentario model = Comentario
fields = ["descricao"] fields = ["descricao"]
widgets = {"descricao": MaterialAdminTextareaWidget}
class ComentarioInternoForm(forms.ModelForm): class ComentarioInternoForm(forms.ModelForm):
class Meta: class Meta:
model = Comentario model = Comentario
fields = ["descricao", "interno", "novo_status"] fields = ["descricao", "interno", "novo_status"]
class SolicitaTreinamentoForm(forms.ModelForm):
MODALIDADE_CHOICES = (
("R", _("Remota")),
("P", _("Presencial")),
)
numero_oficio = forms.CharField(
max_length=50,
label=_("número do ofício"),
required=True,
help_text=_(
"Informe um número de ofício válido do protocoloco da sua "
"Casa Legislativa para ser impresso no ofício de solicitação."
),
)
modalidade = forms.ChoiceField(
label=_("modalidade"),
choices=MODALIDADE_CHOICES,
initial="R",
required=True,
widget=forms.RadioSelect,
)
oficinas = forms.ModelMultipleChoiceField(
label=_("Oficinas"),
queryset=TipoEvento.objects.filter(casa_solicita=True),
required=True,
help_text=_("Selecione as oficinas que deseja participar."),
widget=forms.CheckboxSelectMultiple,
)
senadores = forms.ModelMultipleChoiceField(
label=_("Senadores"),
queryset=Senador.objects.all(),
required=True,
widget=forms.CheckboxSelectMultiple,
help_text=_(
"O ofício de solicitação precisa passar pelo gabinete de "
"pelo menos um Senador, para que as oficinas sejam "
"autorizadas. Indique os Senadores para os quais deseja "
"enviar o ofício de solicitação, ou deixe todos marcados "
"para que o ofício seja encaminhado a todos os Senadores "
"do seu Estado."
),
)
class Meta:
model = Ocorrencia
fields = ["numero_oficio", "modalidade", "oficinas", "senadores"]
def __init__(self, *args, **kwargs):
senadores = kwargs.pop("senadores")
super().__init__(*args, **kwargs)
self.fields["senadores"].queryset = senadores

22
sigi/apps/ocorrencias/migrations/0010_alter_ocorrencia_options_ocorrencia_interno.py

@ -0,0 +1,22 @@
# Generated by Django 4.0.6 on 2022-08-02 17:34
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('ocorrencias', '0009_alter_comentario_options_categoria_projeto_and_more'),
]
operations = [
migrations.AlterModelOptions(
name='ocorrencia',
options={'ordering': ['prioridade', '-data_modificacao', '-data_criacao'], 'verbose_name': 'ocorrência', 'verbose_name_plural': 'ocorrências'},
),
migrations.AddField(
model_name='ocorrencia',
name='interno',
field=models.BooleanField(default=True, help_text='Se marcado, essa ocorrência será visível apenas para servidores do Interlegis', verbose_name='Interno'),
),
]

27
sigi/apps/ocorrencias/migrations/0011_alter_categoria_tipo.py

@ -0,0 +1,27 @@
# Generated by Django 4.1 on 2022-08-10 18:16
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("ocorrencias", "0010_alter_ocorrencia_options_ocorrencia_interno"),
]
operations = [
migrations.AlterField(
model_name="categoria",
name="tipo",
field=models.CharField(
choices=[
("C", "Solicitação de convênio (ACT)"),
("E", "Solicitação de evento (oficina)"),
("O", "Outras"),
],
default="O",
max_length=1,
verbose_name="Tipo de solicitação",
),
),
]

18
sigi/apps/ocorrencias/migrations/0012_alter_comentario_descricao.py

@ -0,0 +1,18 @@
# Generated by Django 4.1 on 2022-09-05 19:55
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("ocorrencias", "0011_alter_categoria_tipo"),
]
operations = [
migrations.AlterField(
model_name="comentario",
name="descricao",
field=models.TextField(blank=True, null=True, verbose_name="Comentário"),
),
]

58
sigi/apps/ocorrencias/models.py

@ -7,11 +7,14 @@ from django.utils.safestring import mark_safe
from django.core.serializers.json import DjangoJSONEncoder from django.core.serializers.json import DjangoJSONEncoder
from sigi.apps.convenios.models import Projeto from sigi.apps.convenios.models import Projeto
from sigi.apps.eventos.models import TipoEvento
from sigi.apps.parlamentares.models import Senador
class Categoria(models.Model): class Categoria(models.Model):
TIPO_CHOICES = ( TIPO_CHOICES = (
("C", _("Solicitação de convênio (ACT)")), ("C", _("Solicitação de convênio (ACT)")),
("E", _("Solicitação de evento (oficina)")),
("O", _("Outras")), ("O", _("Outras")),
) )
nome = models.CharField(_("Categoria"), max_length=50) nome = models.CharField(_("Categoria"), max_length=50)
@ -87,7 +90,7 @@ class Ocorrencia(models.Model):
(5, _("Baixíssimo")), (5, _("Baixíssimo")),
) )
INFO_KEYS = ( INFO_CONVENIO_KEYS = (
("casa_legislativa", _("Casa legislativa")), ("casa_legislativa", _("Casa legislativa")),
("presidente", _("Presidente")), ("presidente", _("Presidente")),
("contato", _("Contato Interlegis")), ("contato", _("Contato Interlegis")),
@ -116,6 +119,14 @@ class Ocorrencia(models.Model):
prioridade = models.IntegerField( prioridade = models.IntegerField(
_("Prioridade"), choices=PRIORITY_CHOICES, default=3 _("Prioridade"), choices=PRIORITY_CHOICES, default=3
) )
interno = models.BooleanField(
_("Interno"),
default=True,
help_text=_(
"Se marcado, essa ocorrência será visível apenas para servidores "
"do Interlegis"
),
)
descricao = models.TextField( descricao = models.TextField(
_("descrição"), _("descrição"),
blank=True, blank=True,
@ -165,8 +176,8 @@ class Ocorrencia(models.Model):
verbose_name_plural = _("ocorrências") verbose_name_plural = _("ocorrências")
ordering = [ ordering = [
"prioridade", "prioridade",
"data_modificacao", "-data_modificacao",
"data_criacao", "-data_criacao",
] ]
def __str__(self): def __str__(self):
@ -188,14 +199,49 @@ class Ocorrencia(models.Model):
) )
return super(Ocorrencia, self).clean() return super(Ocorrencia, self).clean()
def save(self, *args, **kwargs):
if self.id and self.processo_sigad:
self.evento_set.update(num_processo=self.processo_sigad)
return super().save(*args, **kwargs)
def get_ticket_url(self): def get_ticket_url(self):
return mark_safe(settings.OSTICKET_URL % self.ticket) return mark_safe(settings.OSTICKET_URL % self.ticket)
def get_infos_details(self): def get_infos_details(self):
infos = self.infos or {} if self.infos and "solicita_convenio" in self.infos:
infos = self.infos["solicita_convenio"]
else:
infos = {}
return OrderedDict( return OrderedDict(
{key: [key in infos, label] for key, label in Ocorrencia.INFO_KEYS} {
key: [key in infos, label]
for key, label in Ocorrencia.INFO_CONVENIO_KEYS
}
)
def get_infos_oficinas(self):
if (
self.infos
and "solicita_oficinas" in self.infos
and "oficinas" in self.infos["solicita_oficinas"]
):
return TipoEvento.objects.filter(
id__in=self.infos["solicita_oficinas"]["oficinas"]
)
else:
return TipoEvento.objects.none()
def get_infos_senadores(self):
if (
self.infos
and "solicita_oficinas" in self.infos
and "senadores" in self.infos["solicita_oficinas"]
):
return Senador.objects.filter(
id__in=self.infos["solicita_oficinas"]["senadores"]
) )
else:
return Senador.objects.none()
class Comentario(models.Model): class Comentario(models.Model):
@ -208,7 +254,7 @@ class Comentario(models.Model):
data_criacao = models.DateTimeField( data_criacao = models.DateTimeField(
_("Data de criação"), null=True, blank=True, auto_now_add=True _("Data de criação"), null=True, blank=True, auto_now_add=True
) )
descricao = models.TextField(_("Descrição"), blank=True, null=True) descricao = models.TextField(_("Comentário"), blank=True, null=True)
usuario = models.ForeignKey( usuario = models.ForeignKey(
"servidores.Servidor", "servidores.Servidor",
on_delete=models.PROTECT, on_delete=models.PROTECT,

65
sigi/apps/ocorrencias/static/ocorrencias/css/painel_ocorrencias.css

@ -0,0 +1,65 @@
#content {
display: block;
}
.user-image {
width: 64px;
height: 64px;
font-size: 64px !important;
}
commenter-image {
width: 32px;
height: 32px;
font-size: 32px !important;
}
.card-details,
.user-name {
font-size: 10px;
}
.priority {
background-color: grey;
}
.priority {
background-color: antiquewhite;
margin-left: 5px;
min-width: 60px;
}
.chip>img {
float: left;
margin: 0 8px 0 -12px;
height: 32px;
width: 32px;
border-radius: 50%;
}
.span-list {
padding: 2px 6px;
margin-left: 4px;
background-color: var(--selected-bg);
line-height: 24px;
border-radius: 12px;
white-space: nowrap;
}
.card-inbox {
width: 100%;
border: 1px solid var(--hairline-color);
padding: 12px;
border-radius: 12px;
}
.inbox-title {
font-weight: bold;
text-transform: uppercase;
font-size: smaller;
}
.strong {
font-weight: 800;
text-transform: uppercase;
}

5
sigi/apps/ocorrencias/static/ocorrencias/js/painel_ocorrencias.js

@ -0,0 +1,5 @@
$(document).ready(function () {
M.Dropdown.init($('.dropdown-trigger'));
M.Modal.init($(".modal"));
M.FloatingActionButton.init($(".fixed-action-btn"));
});

14
sigi/apps/ocorrencias/templates/ocorrencias/anexo_form.html

@ -1,14 +0,0 @@
{% extends "admin/base.html" %}
{% load i18n admin_static %}
{% load static from staticfiles %}
{% block content_title %}<h1>{% trans "Enviar novo arquivo" %}</h1>{% endblock %}
{% block content %}
<div class="small">
<form id="form_anexos_{{ ocorrencia.id|safe }}" action="" method="POST" enctype="multipart/form-data" >
{% csrf_token %}
{{ form.as_p }}
<input type="submit" name="Adicionar"/>
</form>
</div>
{% endblock %}

24
sigi/apps/ocorrencias/templates/ocorrencias/anexos_snippet.html

@ -1,24 +0,0 @@
{% load i18n admin_static %}
{% load static from staticfiles %}
{% if ocorrencia.anexo_set.exists %}
<table class="table">
<tr>
<th>{% trans "Descrição" %}</th>
<th>{% trans "Data de publicação" %}</th>
<th>&nbsp;</th>
</tr>
{% for anexo in ocorrencia.anexo_set.all %}
<tr>
<td><a href="{{ anexo.arquivo.url }}">{{ anexo.descricao }}</a></td>
<td>{{ anexo.data_pub }}</td>
<td><a href="{% url "ocorrencia-excluianexo" %}?anexo_id={{ anexo.id|safe }}"
data-ocorrencia-id="{{ ocorrencia.id|safe }}" onclick="return remove_anexo(this);">Excluir</a></td>
</tr>
{% endfor %}
</table>
{% endif %}
<a href="{% url 'ocorrencia-incluianexo' %}?ocorrencia_id={{ ocorrencia.id|safe }}" onclick="return showAddAnexoPopup(this);">
{% trans "Anexar novo arquivo" %}
</a>

53
sigi/apps/ocorrencias/templates/ocorrencias/convenio/atualiza_casa.html

@ -1,53 +0,0 @@
{% extends "ocorrencias/convenio/base_convenio.html" %}
{% load static i18n %}
{% block content %}
<div class="main-content">
<div class="row">
<div class="col s12">
<div class="card">
<div class="card-content">
<span class="card-title">{% trans "Solicitar convênio" %}</span>
{% blocktrans %}
<p>Para que uma Casa Legislativa possa utilizar, gratuitamente, os
serviços do Interlegis / Senado Federal, é necessário formalizar
um convênio, na forma de um Acordo de Cooperação Técnica (ACT),
na forma da lei <a href="http://www.planalto.gov.br/ccivil_03/_ato2019-2022/2021/lei/L14133.htm">Lei Nº 14.133/2021</a>
e da lei <a href="http://www.planalto.gov.br/ccivil_03/leis/l8666cons.htm">Lei Nº 8.666/1993</a>.
</p>
<p>Para solicitar o ACT, serão necessárias as seguintes informações:</p>
<ul class="browser-default">
<li>Dados cadastrais da Casa Legislativa, como CNPJ, endereço, e-mail, telefone.</li>
<li>Dados cadastrais do Presidente, como nome, CPF, identidade, e-mail, telefone, redes sociais.</li>
<li>Designação de um servidor como Contato Interlegis.</li>
</ul>
{% endblocktrans %}
</div>
</div>
</div>
</div>
<div class="row">
<div class="col s12">
<div class="card">
<div class="card-content">
<span class="card-title">{% trans "Identifique sua Casa Legislativa" %}</span>
<p>{% trans "Informe o nome do município ou Estado da sua Casa Legislativa" %}:</p>
<div class="input-field">
<i class="material-icons prefix">search</i>
<input type="text" class="search-text" placeholder="{% trans "Procurar" %}" aria-label="{% trans "Procurar" %}" data-source="{% url 'openmapsearch' %}" data-param="q">
<div class="search-result hide" data-item-click="seleciona_casa"></div>
</div>
</div>
</div>
</div>
</div>
{% endblock %}
{% block footer %}
{{ block.super }}
<script>
function seleciona_casa(data) {
$(location).attr("href", `{% url 'ocorrencias-seleciona-casa' %}?casa_id=${data.id}`);
}
</script>
{% endblock %}

4
sigi/apps/ocorrencias/templates/ocorrencias/convenio/ocorrencia.html

@ -202,7 +202,7 @@
$(document).ready(function() { $(document).ready(function() {
M.Tabs.init($('.tabs'), {swipeable: true}); M.Tabs.init($('.tabs'), {swipeable: true});
$("select#id_presidente-parlamentar").on("change", function() { $("select#id_presidente-parlamentar").on("change", function() {
$.get("{% url 'parlamentar-data' %}", `id=${this.value}`, function(data) { $.get("{% url 'parlamentares:parlamentar_data' %}", `id=${this.value}`, function(data) {
for(var campo of Object.keys(data[0].fields)) { for(var campo of Object.keys(data[0].fields)) {
$(`#id_presidente-${campo}`).val(data[0].fields[campo]); $(`#id_presidente-${campo}`).val(data[0].fields[campo]);
} }
@ -210,7 +210,7 @@
}) })
}); });
function seleciona_casa(data) { function seleciona_casa(data) {
$(location).attr("href", `{% url 'ocorrencias-seleciona-casa' %}?casa_id=${data.id}`); $(location).attr("href", `{% url 'ocorrencias:ocorrencia_convenio_seleciona_casa' %}?casa_id=${data.id}`);
} }
</script> </script>
{% endblock %} {% endblock %}

40
sigi/apps/ocorrencias/templates/ocorrencias/convenio/painel_convenio.html

@ -1,40 +0,0 @@
{% extends "admin/base_block.html" %}
{% load i18n %}
{% block content %}
<h4>{% trans "Solicitações de convenio" %}</h4>
<table class="striped">
<thead>
<tr>
<th>{% trans "Data abertura" %}</th>
<th>{% trans "Casa solicitante" %}</th>
<th>{% trans "Assunto" %}</th>
<th>{% trans "Comentários" %}
<th>{% trans "Situação" %}</th>
<th>{% trans "Detalhes" %}</th>
</tr>
</thead>
<tbody>
{% for ocorrencia in ocorrencias %}
<tr>
<td>{{ ocorrencia.data_criacao|date:"SHORT_DATE_FORMAT" }}</td>
<td>{{ ocorrencia.casa_legislativa }}</td>
<td>{{ ocorrencia.assunto }}</td>
<td><span class="badge">{{ ocorrencia.comentarios.count }}</span></td>
<td>
<ul>
{% for key, value in ocorrencia.get_infos_details.items %}
<li>
<i class="material-icons {% if value.0 %}green-text{% else %}red-text{% endif %}">{% if value.0 %}done{% else %}clear{% endif %}</i>
{{ value.1 }}
</li>
{% endfor %}
</ul>
</td>
<td>
<a href="{% url 'painel-convenio' ocorrencia.id %}"><i class="material-icons">details</i></a>
</td>
{% endfor %}
</tbody>
</table>
{% endblock %}

128
sigi/apps/ocorrencias/templates/ocorrencias/convenio/painel_convenio_detail.html

@ -1,39 +1,19 @@
{% extends "admin/base_block.html" %} {% extends "ocorrencias/ocorrencia_detail.html" %}
{% load i18n model_fields %} {% load i18n model_fields %}
{% block content %} {% block content_title %}
<h5>{% blocktrans with casa=ocorrencia.casa_legislativa.nome %}Solicitação de adesão da {{ casa }}{% endblocktrans %}</h5>
<h6>{% blocktrans with id=ocorrencia.id|safe%}Ocorrência #{{ id }}{% endblocktrans %}</h6>
{% endblock %}
{% block other_cards %}
<form action="{% if list_filter %}?list_filter={{ list_filter|urlencode }}{% endif %}" method="post">{% csrf_token %}
{% if infos.aplicados %}
<div class="row"> <div class="row">
<div class="col s12"> <div class="col s12">
<form action="" method="post" name="ocorrencia">
{% csrf_token %}
<div class="card"> <div class="card">
<div class="card-content"> <div class="card-content">
<span class="card-title">{% trans "Resumo da ocorrência" %}</span> <span class="card-title">{% trans "Alterações aplicadas" %}</span>
<table>
<tbody>
{% for campo in campos_ocorrencia %}
<tr>
<th>{{ ocorrencia|verbose_name:campo|capfirst }}</th>
<td>{{ ocorrencia|field_value:campo|default:"-" }}</td>
</tr>
{% endfor %}
</tbody>
</table>
{{ ocorrencia_form }}
</div>
<div class="card-action">
<button class="btn waves-effect waves-light" type="submit" name="salva_ocorrencia">
{% trans "Salvar" %}
<i class="material-icons left">save</i>
</button>
<a class="btn waves-effect waves-light white-text" href="{% url 'painel-convenio' %}">{% trans "Voltar ao painel" %}</a>
</div>
</div>
</form>
</div>
</div>
{% if infos.aplicados %}
{% if 'casa_legislativa' in infos.aplicados and 'presidente' in infos.aplicados and 'contato' in infos.aplicados %} {% if 'casa_legislativa' in infos.aplicados and 'presidente' in infos.aplicados and 'contato' in infos.aplicados %}
<p class=""> {% trans "Todas as alterações foram aplicadas" %}</p> <p class=""> {% trans "Todas as alterações foram aplicadas" %}</p>
{% else %} {% else %}
@ -49,6 +29,10 @@
{% endif %} {% endif %}
</ul> </ul>
{% endif %} {% endif %}
</div>
</div>
</div>
</div>
{% endif %} {% endif %}
{% if 'casa_legislativa' not in infos.aplicados %} {% if 'casa_legislativa' not in infos.aplicados %}
@ -87,7 +71,7 @@
</table> </table>
</div> </div>
<div class="card-action"> <div class="card-action">
<a class="btn waves-effect waves-light white-text" href="?apply=casa">{% trans "Aplicar mudanças na Casa Legislativa" %}</a> <button type="submit" class="btn waves-effect waves-light white-text" name="apply_casa">{% trans "Aplicar mudanças na Casa Legislativa" %}</button>
</div> </div>
</div> </div>
</div> </div>
@ -126,7 +110,7 @@
</table> </table>
</div> </div>
<div class="card-action"> <div class="card-action">
<a class="btn waves-effect waves-light white-text" href="?apply=presidente">{% trans "Aplicar mudanças no Parlamentar" %}</a> <button type="submit" class="btn waves-effect waves-light white-text" name="apply_presidente">{% trans "Aplicar mudanças no Parlamentar" %}</button>
</div> </div>
</div> </div>
</div> </div>
@ -159,87 +143,11 @@
</table> </table>
</div> </div>
<div class="card-action"> <div class="card-action">
<a class="btn waves-effect waves-light white-text" href="?apply=contato">{% trans "Aplicar mudanças no Contato Interlegis" %}</a> <button type="submit" class="btn waves-effect waves-light white-text" name="apply_contato">{% trans "Aplicar mudanças no Contato Interlegis" %}</button>
</div>
</div>
</div>
</div>
{% endif %}
<div class="row">
<div class="col s12">
<div class="card">
<div class="card-content">
<span class="card-title">{% trans "Anexos (documentos)" %}</span>
<table class="striped">
<thead>
<tr>
<th>{% trans "Data de inclusão" %}</th>
<th>{% trans "Descrição" %}</th>
<th>{% trans "Arquivo" %}</th>
</tr>
</thead>
<tbody>
{% for anexo in ocorrencia.anexo_set.all %}
<tr>
<th>{{ anexo.data_pub|date:"SHORT_DATE_FORMAT" }}</th>
<td>{{ anexo.descricao|default:"-" }}</td>
<td><a href="{{ anexo.arquivo.url }}">{{ anexo.arquivo.name }}</a></td>
</tr>
{% endfor %}
</tbody>
</table>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<div class="row">
<div class="col s12">
<div class="card">
<div class="card-content">
<span class="card-title">{% trans "Comentários" %}</span>
<table class="striped">
<thead>
<tr>
<th>{% trans "Data" %}</th>
<th>{% trans "Descrição" %}</th>
<th>{% trans "Servidor" %}</th>
<th>{% trans "Novo status" %}</th>
<th>{% trans "Visibilidade" %}</th>
</tr>
</thead>
<tbody>
{% for comentario in ocorrencia.comentarios.all %}
<tr>
<th>{{ comentario.data_criacao|date:"SHORT_DATETIME_FORMAT" }}</th>
<td>{{ comentario.descricao|default:"-" }}</td>
<td>{{ comentario.usuario.nome_completo|default:"-" }}</td>
<td>{{ comentario.get_novo_status_display|default:"-" }}</td>
<td>
{% if comentario.interno %}
<i class="material-icons green-text">visibility_off</i> Interno
{% else %}
<i class="material-icons red-text">visibility</i> Público
{% endif %} {% endif %}
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
<div class="card-action">
<form action="" method="post" name="comentario">
{% csrf_token %}
{{ comentario_form }}
<button class="btn waves-effect waves-light" type="submit" name="salva_comentario">
{% trans "Comentar" %}
<i class="material-icons left">comment</i>
</button>
</form> </form>
</div> {% endblock other_cards %}
</div>
</div>
</div>
{% endblock %}

2
sigi/apps/ocorrencias/templates/ocorrencias/convenio/seleciona_casa.html

@ -47,7 +47,7 @@
{{ block.super }} {{ block.super }}
<script> <script>
function seleciona_casa(data) { function seleciona_casa(data) {
$(location).attr("href", `{% url 'ocorrencias-seleciona-casa' %}?casa_id=${data.id}`); $(location).attr("href", `{% url 'ocorrencias:ocorrencia_convenio_seleciona_casa' %}?casa_id=${data.id}`);
} }
</script> </script>
{% endblock %} {% endblock %}

128
sigi/apps/ocorrencias/templates/ocorrencias/ocorrencia_detail.html

@ -0,0 +1,128 @@
{% extends "admin/base_block.html" %}
{% load i18n model_fields %}
{% block content_title %}
<h5>{% blocktrans with id=ocorrencia.id|safe%}Ocorrência #{{ id }}{% endblocktrans %}</h5>
{% endblock %}
{% block content %}
{% csrf_token %}
{% block ocorrencia_card %}
<div class="row">
<div class="col s12">
<form action="{% if list_filter %}?list_filter={{ list_filter|urlencode }}{% endif %}" method="post" name="ocorrencia">{% csrf_token %}
<div class="card">
<div class="card-content">
{% block card_title %}
<span class="card-title">{% trans "Resumo da ocorrência" %}</span>
{% endblock card_title %}
<table>
<tbody>
{% for campo in campos_ocorrencia %}
<tr>
<th>{{ ocorrencia|verbose_name:campo|capfirst }}</th>
<td>{{ ocorrencia|field_value:campo|default:"-" }}</td>
</tr>
{% endfor %}
</tbody>
</table>
{{ form }}
</div>
<div class="card-action">
{% block form_actions %}
<button class="btn waves-effect waves-light" type="submit" name="save_ocorrencia_form">
{% trans "Salvar" %}
<i class="material-icons left">save</i>
</button>
<a class="btn waves-effect waves-light white-text" href="{% url 'ocorrencias_painel' %}?{{ list_filter }}">{% trans "Voltar ao painel" %}</a>
{% endblock form_actions %}
</div>
</div>
</form>
</div>
</div>
{% endblock ocorrencia_card %}
{% block anexos_card %}
<div class="row">
<div class="col s12">
<div class="card">
<div class="card-content">
<span class="card-title">{% trans "Anexos (documentos)" %}</span>
<table class="striped">
<thead>
<tr>
<th>{% trans "Data de inclusão" %}</th>
<th>{% trans "Descrição" %}</th>
<th>{% trans "Arquivo" %}</th>
</tr>
</thead>
<tbody>
{% for anexo in ocorrencia.anexo_set.all %}
<tr>
<th>{{ anexo.data_pub|date:"SHORT_DATE_FORMAT" }}</th>
<td>{{ anexo.descricao|default:"-" }}</td>
<td><a href="{{ anexo.arquivo.url }}">{{ anexo.arquivo.name }}</a></td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
</div>
{% endblock anexos_card %}
{% block comentario_card %}
<div class="row">
<div class="col s12">
<form action="{% if list_filter %}?list_filter={{ list_filter|urlencode }}{% endif %}" method="post" name="comentario">{% csrf_token %}
<div class="card">
<div class="card-content">
<span class="card-title">{% trans "Comentários" %}</span>
<table class="striped">
<thead>
<tr>
<th>{% trans "Data" %}</th>
<th>{% trans "Descrição" %}</th>
<th>{% trans "Servidor" %}</th>
<th>{% trans "Novo status" %}</th>
<th>{% trans "Visibilidade" %}</th>
</tr>
</thead>
<tbody>
{% for comentario in ocorrencia.comentarios.all %}
<tr>
<th>{{ comentario.data_criacao|date:"SHORT_DATETIME_FORMAT" }}</th>
<td>{{ comentario.descricao|default:"-" }}</td>
<td>{{ comentario.usuario.nome_completo|default:"-" }}</td>
<td>{{ comentario.get_novo_status_display|default:"-" }}</td>
<td>
{% if comentario.interno %}
<i class="material-icons green-text">visibility_off</i> Interno
{% else %}
<i class="material-icons red-text">visibility</i> Público
{% endif %}
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
<div class="card-action">
{% csrf_token %}
{{ form_comentario }}
<button class="btn waves-effect waves-light" type="submit" name="save_comentario_form">
{% trans "Comentar" %}
<i class="material-icons left">comment</i>
</button>
</div>
</div>
</form>
</div>
</div>
{% endblock comentario_card %}
{% block other_cards %}{% endblock other_cards %}
{% endblock content %}

7
sigi/apps/ocorrencias/templates/ocorrencias/ocorrencia_form.html

@ -1,7 +0,0 @@
<div class="panel-body">
<form id="form_ocorrencia" action="{% url 'ocorrencia-incluiocorrencia' %}" method="post">
{% csrf_token %}
{{ ocorrencia_form.as_p }}
<input type="submit" value="Salvar"/>
</form>
</div>

113
sigi/apps/ocorrencias/templates/ocorrencias/ocorrencia_snippet.html

@ -1,113 +0,0 @@
{% load i18n admin_static %}
{% load static from staticfiles %}
{% load thumbnail %}
{% static 'ocorrencias/images/lid.png' as default_lid %}
{% static 'ocorrencias/images/mm.png' as default_mm %}
<div class="panel panel-default" id='ticket_{{ ocorrencia.id|safe }}'>
<div class="panel-heading">
<div class="media">
<div class="media-left">
<img class="media-object" src="{{ ocorrencia.casa_legislativa.foto|thumbnail_url:'thumb'|default:default_lid }}" alt=""/>
</div>
<div class="media-body">
<h4><a href="{{ url_painel }}?type=casa&id={{ ocorrencia.casa_legislativa_id|safe }}">
{{ ocorrencia.casa_legislativa.nome }}, {{ ocorrencia.casa_legislativa.municipio.uf.sigla }}</a></h4>
<p>
<a href="{% url "admin:ocorrencias_ocorrencia_change" ocorrencia.id %}" target="_blank">Ocorrência {{ ocorrencia.id|safe }}</a>:
{% blocktrans with data_criacao=ocorrencia.data_criacao tipo_contato=ocorrencia.tipo_contato categoria=ocorrencia.categoria id_setor=ocorrencia.setor_responsavel_id|safe setor=ocorrencia.setor_responsavel.sigla status=ocorrencia.get_status_display %}
Criado em {{ data_criacao }} via {{ tipo_contato }} solicitando {{ categoria }},
está no setor <a href="{{ url_painel }}?type=servico&id={{ id_setor }}">{{ setor }}</a>
com status {{ status }}
{% endblocktrans %}</p>
{% if ocorrencia.ticket %}
<p><a href="{{ ocorrencia.get_ticket_url }}" target="_blank">{% trans "Ticket no suporte #" %}{{ ocorrencia.ticket|safe }}</a></p>
{% endif %}
<p>{% trans "Gerentes Interlegis:" %}
{% for g in ocorrencia.casa_legislativa.gerentes_interlegis.all %}
<a href="{{ url_painel }}?type=servidor&id={{ g.id|safe }}">
{{ g.nome_completo }}</a>
{% if not forloop.last %}, {% endif %}
{% endfor %}
</p>
{% trans 'Prioridade' %}:
<div class="btn-group btn-group-xs" data-toggle="buttons" role="group" aria-label="...">
{% for id, name in PRIORITY_CHOICES %}
<label class="btn btn-primary {% if id == ocorrencia.prioridade %}active{% endif %}">
<input type="radio" name="ocorrencia-{{ ocorrencia.id|safe }}" value="{{ id|safe }}" autocomplete="off"{% if id == ocorrencia.prioridade %} checked {% endif %}>
{{ name }}
</label>
{% endfor %}
</div>
</div>
</div>
</div>
<div class="panel-body">
<div class="media">
<div class="media-left">
<img class="media-object" src="{{ ocorrencia.servidor_registro.foto|thumbnail_url:'icon'|default:default_mm }}" alt=""/>
</div>
<div class="media-body">
<p><a href="{{ url_painel }}?type=servidor&id={{ ocorrencia.servidor_registro_id|safe }}">
<strong>{{ ocorrencia.servidor_registro }}</strong></a>
{% trans 'comentou' %}:</p>
<p>{{ ocorrencia.descricao }}</p>
</div>
</div>
{% for comentario in ocorrencia.comentarios.all %}
<div class="media">
<div class="media-left">
<img class="media-object" src="{{ comentario.usuario.foto|thumbnail_url:'icon'|default:default_mm }}" alt=""/>
</div>
<div class="media-body">
<p><a href="{{ url_painel }}?type=servidor&id={{ comentario.usuario_id|safe }}">
<strong>{{ comentario.usuario.nome_completo }}</strong></a>
{% trans 'comentou' %}:</p>
<p>{{ comentario.descricao }}</p>
<p class="small">{% trans 'Em' %} {{ comentario.data_criacao }}
{% if comentarui.status %}
| {% trans 'novo status' %}: {{ comentario.get_novo_status_display }}
{% endif %}
{% if comentario.encaminhar_setor %}
| {% trans 'Encaminhado para' %} {{ comentario.encaminhar_setor.sigla }}
{% endif %}
</div>
</div>
{% endfor %}
<a id='link_comentar_{{ ocorrencia.id|safe }}' role="button" data-toggle="collapse" href="#comentario_{{ ocorrencia.id|safe }}" aria-expanded="false" aria-controls="comentario_{{ ocorrencia.id|safe }}">
{% trans "Comentar esta ocorrência" %}
</a>
<div class="collapse" id="comentario_{{ ocorrencia.id|safe }}">
<form id="comentar_ocorrencia_{{ ocorrencia.id|safe }}" action="{% url 'ocorrencia-incluicomentario' %}" method="post" data-ocorrencia-id="{{ ocorrencia.id|safe }}">
{% csrf_token %}
{{ comentario_form.non_field_errors }}
{% for field in comentario_form %}
<div class="fieldWrapper">
{% if field.name == 'ocorrencia' %}
<input type='hidden' name='ocorrencia' value='{{ ocorrencia.id|safe }}'/>
{% else %}
{{ field.errors }}
<p>{{ field.label_tag }} {{ field }}</p>
{% endif %}
</div>
{% endfor %}
<input type="submit" value="{% trans 'Comentar' %}">
</form>
</div>
</div>
<div class="panel-footer">
<a id='link_anexos_{{ ocorrencia.id|safe }}'role="button" data-toggle="collapse" href="#anexos_{{ ocorrencia.id|safe }}" aria-expanded="false" aria-controls="anexos_{{ ocorrencia.id|safe }}">
{% blocktrans count counter=ocorrencia.total_anexos %}
{{ counter }} arquivo anexo
{% plural %}
{{ counter }} arquivos anexos
{% endblocktrans %}
</a>
<div class="collapse" id="anexos_{{ ocorrencia.id|safe }}">
{% include 'ocorrencias/anexos_snippet.html' %}
</div>
</div>
</div>

12
sigi/apps/ocorrencias/templates/ocorrencias/oficina/email_senador.html

@ -0,0 +1,12 @@
<p>À Sua Excelência {{ senador.forma_tratamento }} {{ senado.nome_parlamentar }}.</p>
<p>ASSUNTO: <span style="font-weight: bold;">Solicitação de oficinas / encontros Interlegis.</span></p>
<br/>
<p>
Essa {{ casa.nome }} vem solicitar a Vossa Excelência apoio para a realização
de eventos Interlegis, conforme detalhado no ofício anexo, junto ao
Instituto Legislativo Brasileiro - ILB, órgão deste Senado Federal.
</p>
<br/>
<p>Respeitosamente,</p>
<p>{{ sender.nome }}</p>
<p>{{ sender.funcao }} da {{ casa.nome }}

90
sigi/apps/ocorrencias/templates/ocorrencias/oficina/painel_oficina_detail.html

@ -0,0 +1,90 @@
{% extends "ocorrencias/ocorrencia_detail.html" %}
{% load i18n model_fields %}
{% block content_title %}
<h5>{% blocktrans with casa=ocorrencia.casa_legislativa.nome %}Solicitação de oficinas da {{ casa }}{% endblocktrans %}
<h6>{% blocktrans with id=ocorrencia.id|safe%}Ocorrência #{{ id }}{% endblocktrans %}</h6>
{% endblock %}
{% block other_cards %}
<div class="row">
<div class="col s12">
<form action="{% if list_filter %}?list_filter={{ list_filter|urlencode }}{% endif %}" method="post" name="oficinas">{% csrf_token %}
<div class="card">
<div class="card-content">
<span class="card-title">{% trans "Solicitações" %}</span>
<blockquote>
<p>{% trans "Modalidade" %}: {% if ocorrencia.infos.solicita_oficinas.modalidade == 'P' %}{% trans "PRESENCIAL" %}{% else %}{% trans "REMOTA" %}{% endif %}</p>
<p>{% trans "Senadores" %}: {% for senador in senadores %}{{ senador.nome_completo|upper }}{% if not forloop.last %}, {% endif %}{% endfor %}</p>
</blockquote>
<p>{{ form_oficina }}</p>
</div>
<div class="card-action">
<button class="btn waves-effect waves-light" type="submit" name="save_oficina_form">
{% trans "Autorizar eventos selecionados" %}
<i class="material-icons left">save</i>
</button>
</div>
</div>
</form>
</div>
</div>
<div class="row">
<div class="col s12">
<div class="card">
<div class="card-content">
<span class="card-title">{% trans "Oficinas autorizadas" %}</span>
<table class="striped">
<thead>
<tr>
<th>{% trans "Nome" %}</th>
<th>{% trans "Turma" %}</th>
<th>{% trans "Status" %}</th>
<th>{% trans "Virtual" %}</th>
<th>{% trans "Data início" %}</th>
<th>{% trans "Data término" %}</th>
<th>{% trans "Equipe" %}</th>
</tr>
</thead>
<tbody>
{% for evento in ocorrencia.evento_set.all %}
<tr>
<th>
<a href="{% url 'admin:eventos_evento_change' evento.id %}" target="_blank">
{{ evento.nome }}
</a>
</th>
<td>{{ evento.turma }}</td>
<td>{{ evento.get_status_display }}</td>
<td>
{% if evento.virtual %}
<i class="material-icons green-color medium-icon">check_circle</i>
{% else %}
<i class="material-icons red-color medium-icon">highlight_off</i>
{% endif %}
</td>
<td>{{ evento.data_inicio|date:"SHORT_DATE_FORMAT" }}</td>
<td>{{ evento.data_termino|date:"SHORT_DATE_FORMAT" }}</td>
<td>
<ul class="collection">
{% for membro in evento.equipe_set.all %}
<li class="collection-item avatar">
{% if membro.membro.foto %}
<img src="{{ membro.membro.foto.url }}" class="circle"/>
{% endif %}
{{ membro.membro.get_apelido }} ({{ m.funcao.nome }})
</li>
{% endfor %}
</ul>
</td>
</tr>
{% empty %}
<tr><td colspan="6">{% trans "Nenhuma oficina autorizada ainda" %}</td></tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
</div>
{% endblock other_cards %}

198
sigi/apps/ocorrencias/templates/ocorrencias/painel-old.html

@ -1,198 +0,0 @@
{% extends "admin/base_site.html" %}
{% load i18n admin_static %}
{% load static from staticfiles %}
{% load thumbnail %}
{% block extrastyle %}
{{ block.super }}
<link rel="stylesheet" type="text/css" href="{% static 'ocorrencias/css/jquery-ui.min.css' %}"/>
{% endblock %}
{% block extrahead %}
{{ block.super }}
<script type="text/javascript" src="{% static 'admin/js/core.js' %}" ></script>
<script type="text/javascript" src="{% static 'admin/js/jquery.min.js' %}" ></script>
<script type="text/javascript" src="{% static 'admin/js/jquery.init.js' %}" ></script>
<script type="text/javascript" src="{% static 'ocorrencias/js/jquery-ui.min.js' %}" ></script>
{% endblock %}
{% block coltype %}colMS{% endblock %}
{% block content_title %}<h1>{{ panel_title }}</h1>{% endblock %}
{% block content %}
{% url 'painel-ocorrencias' as url_painel %}
<div id="content-main" class="container-fluid">
<div class="form-group">
<div class="input-group">
<input type="text" class="form-control" id="q" placeholder="{% trans 'Visitar o painel de' %}">
<span class="input-group-btn">
<button class="btn btn-default" type="button" onclick="window.location.href='{{ url_painel }}'">{% trans 'Meu painel' %}</button>
</span>
</div>
</div>
<div class="nav nav-pills">
<span class="glyphicon glyphicon-plus"></span>
<a role="button" data-toggle="collapse" href="#form_ocorrencia_panel" aria-expanded="false" aria-controls="form_ocorrencia_panel">
{% trans "Registrar nova ocorrência" %}
</a>
</div>
<div class="collapse panel panel-default" id='form_ocorrencia_panel'>
{% include 'ocorrencias/ocorrencia_form.html' %}
</div>
{% if paineis %}
<ul class="nav nav-pills">
{% for k, v in paineis.iteritems %}
<li role="presentation" class="{% if k == painel %}active{% endif %}">
<a href="{{ url_painel }}?type=servidor&id={{ servidor.id }}&painel={{ k }}">
{{ v }}</a></li>
{% endfor %}
</ul>
{% endif %}
<div class="row">
<div id="ocorrencias_display" class="col-md-12">
{% for ocorrencia in ocorrencias %}
{% include 'ocorrencias/ocorrencia_snippet.html' %}
{% empty %}
<div class="panel panel-default">
<div class="panel-body">
<p>{% trans 'Nenhuma ocorrência encontrada.' %}</p>
</div>
</div>
{% endfor %}
</div>
</div>
</div>
<script type="text/javascript">
$( document ).ready(function() {
$.ajaxSetup({
beforeSend: function(xhr, settings) {
if (!(/^(GET|HEAD|OPTIONS|TRACE)$/.test(settings.type)) && !this.crossDomain) {
var cookieValue = null, name = 'csrftoken';
if (document.cookie && document.cookie != '') {
var cookies = document.cookie.split(';');
for (var i = 0; i < cookies.length; i++) {
var cookie = jQuery.trim(cookies[i]);
if (cookie.substring(0, name.length + 1) == (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
xhr.setRequestHeader("X-CSRFToken", cookieValue);
}
}
});
$("#q").autocomplete({
source: "{% url 'painel-buscanominal' %}",
select: function(event, ui) {
window.location.replace("{{ url_painel }}?type="+ui.item.origin+"&id="+ui.item.value);
ui.item.value = ui.item.label
}
})
$('input[name^=ocorrencia-]').on('change', function() {
var $this = $(this),
data = {'id_ocorrencia': $this.attr('name').split('-')[1],
'prioridade': $this.attr('value')};
$.post('{% url "ocorrencia-mudaprioridade" %}', data, function(result) {
if (result.result == 'error') {
alert(result.message);
$this.reset();
}
});
})
function inclui_comentario( event ) {
event.preventDefault()
var $this = $(this);
$.post($this.attr('action'), $this.serialize(), function( result ) {
$('div[id=ticket_'+result.ocorrencia_id+']').html(result.ocorrencia_panel);
$('form[id^=comentar_ocorrencia_').on('submit', inclui_comentario);
});
}
function inclui_ocorrencia( event ) {
event.preventDefault()
var $this = $(this);
$.post($this.attr('action'), $this.serialize(), function( result ) {
$("#form_ocorrencia_panel").html(result.ocorrencia_form);
if (result.result == 'success') {
$("#form_ocorrencia_panel").collapse('hide');
$("#ocorrencias_display").prepend(result.ocorrencia_panel);
$('form[id^=comentar_ocorrencia_').on('submit', inclui_comentario);
}
$('#form_ocorrencia').on('submit', inclui_ocorrencia);
});
}
$('form[id^=comentar_ocorrencia_').on('submit', inclui_comentario);
$('#form_ocorrencia').on('submit', inclui_ocorrencia);
});
function remove_anexo(link) {
var $this = $(link),
url = $this.attr('href'),
div = $("div#anexos_"+$this.attr('data-ocorrencia-id')),
link = $("a#link_anexos_"+$this.attr('data-ocorrencia-id'));
$( 'body' ).append('<div id="dialog-confirm" title="{% trans "Excluir anexo?" %}"><p><span class="glyphicon glyphicon-alert" style="float:left; margin:0 7px 20px 0;"></span>{% trans "Este anexo será definitivamente excluído e não poderá ser recuperado. Você confirma a exclusão?" %}</p></div>');
var dialog = $("#dialog-confirm");
dialog.dialog({
resizable: true,
modal: true,
buttons: {
"{% trans 'Excluir' %}": function() {
$.get(url, function(result) {
if (result.result == 'error') {
alert(result.message);
}
if (result.result == 'success') {
div.html(result.anexos_panel);
link.html(result.link_label);
}
});
dialog.dialog( 'destroy' );
},
"{% trans 'Cancelar' %}": function() {
dialog.dialog( 'destroy' );
}
}
});
return false;
}
function dismissAddAnexoPopup(win, ocorrencia_id) {
var div = $("div#anexos_"+ocorrencia_id),
link = $("a#link_anexos_"+ocorrencia_id);
win.close();
$.get('{% url "ocorrencia-anexosnippet" %}?ocorrencia_id='+ocorrencia_id, function( result ) {
div.html(result);
});
}
function showAddAnexoPopup(link) {
var $this = $(link),
href = $this.attr('href'),
win = window.open(href, '', 'height=500,width=800,resizable=yes,scrollbars=yes');
win.focus();
return false;
}
</script>
{% endblock %}

252
sigi/apps/ocorrencias/templates/ocorrencias/painel.html

@ -1,211 +1,99 @@
{% extends "admin/base_site.html" %} {% extends "admin/base_block.html" %}
{% load i18n static admin_urls %} {% load i18n static admin_urls %}
{% block extrastyle %} {% block extrastyle %}
{{ block.super }} {{ block.super }}
<style> <link rel="stylesheet" href="{% static 'ocorrencias/css/painel_ocorrencias.css' %}">
#content {
display: block;
}
.user-image {
width: 64px;
height: 64px;
font-size: 64px !important;
}
commenter-image {
width: 32px;
height: 32px;
font-size: 32px !important;
}
.card-details, .user-name {
font-size: 10px;
}
.priority {
background-color: grey;
}
.priority {
background-color: antiquewhite;
margin-left: 5px;
min-width: 60px;
}
.chip>img {
float: left;
margin: 0 8px 0 -12px;
height: 32px;
width: 32px;
border-radius: 50%;
}
</style>
{% endblock %} {% endblock %}
{% block breadcrumbs %}{% endblock %}
{% block content %} {% block content_title %}
<div class="row"> <h5>{{ panel_title }}</h5>
<div class="col s12"><h1>{{ panel_title }}</h1></div> {% if panel_subtitles %}
</div> <blockquote>
<div class="row"> <h6>{% trans "Filter" %}:</h6>
<div class="col s12"> {% for subt in panel_subtitles %}
{% for id, text in paineis.items %} <h6>{{ subt }}</h6>
<a class="waves-effect waves-light btn-small{% if id != painel %} btn-flat{% endif %}" href="?painel={{ id }}">{{ text }}</a>
{% endfor %} {% endfor %}
{% endif %}
</blockquote>
{% endblock content_title %}
{% block content %}
{% block object-tools %}
<div class="fixed-action-btn">
<a class="btn-floating btn-large">
<i class="large material-icons">build</i>
</a>
<ul>
{% block object-tools-items %}
<li>
<a href="#float-filter" class="btn-floating tooltipped waves-effect waves-light modal-trigger" data-position="left" data-tooltip="{% trans 'Filter' %}">
<i class="material-icons" aria-hidden="true">filter_list</i>
</a>
</li>
{% if has_add_permission %}
<li>
<a href="{% url 'admin:ocorrencias_ocorrencia_add' %}" class="btn-floating tooltipped waves-effect waves-light" data-position="left" data-tooltip="{% trans 'Add' %}">
<i class="material-icons" aria-hidden="true">add</i>
</a>
</li>
{% endif %}
{% endblock %}
</ul>
</div> </div>
</div> <div id="float-filter" class="modal">
<form id="filter-form" method="get">
<div id="side-wrapper" class="modal-content">
{% block filters %}
{% if filter %}
<h4>{% trans 'Filter' %}</h4>
<div class="row"> <div class="row">
<div class="col s12"> <div class="col s12">
<button class="waves-effect waves-light btn-small btn-flat modal-trigger" href="#nova_ocorrencia">{% trans "Nova ocorrência" %}</button> <a href="?">{% trans "Clear all filters" %}</a>
</div>
</div>
<div id="nova_ocorrencia" class="modal">
<div class="modal-content">
<h4>{% trans "Nova ocorrência" %}</h4>
{{ ocorrencia_form }}
</div> </div>
<div class="modal-footer">
<a href="#!" class="modal-close waves-effect waves-green btn-flat">Agree</a>
</div>
</div>
{% for ocorrencia in ocorrencias %}
<div class="row">
<div class="col s12">
<div class="card hoverable">
<div class="card-content">
<span class="card-title">
<a href="{% url "admin:ocorrencias_ocorrencia_change" ocorrencia.id %}"><i class="material-icons right">edit</i></a>
{{ ocorrencia.casa_legislativa.nome }}, {{ ocorrencia.casa_legislativa.municipio.uf.sigla }}
<p class="card-details">
{% blocktrans with data_criacao=ocorrencia.data_criacao tipo_contato=ocorrencia.tipo_contato categoria=ocorrencia.categoria status=ocorrencia.get_status_display %}
Criado em {{ data_criacao }} via {{ tipo_contato }} solicitando {{ categoria }}, com status {{ status }}
{% endblocktrans %}
</p>
<p class="card-details">
<strong>{% trans "Gerentes" %}:</strong>
{% for gerente in ocorrencia.casa_legislativa.gerentes_interlegis.all %}
<div class="chip">
{% if gerente.foto %}
<img src="{{ gerente.foto.url }}">
{% endif %}
<a href="./">{{ gerente.get_apelido }}</a>
</div> </div>
{% endfor %}
</p>
</span>
<div class="row"> <div class="row">
<div class="col s3 m1 center-align"> {{ filter.form }}
<a href="./">
{% if ocorrencia.servidor_registro.foto %}
<img class="circle user-image" src="{{ MEDIA_URL }}{{ ocorrencia.servidor_registro.foto }}"/>
{% else %}
<i class="material-icons circle user-image">account_circle</i>
{% endif %}
</a>
<span class="user-name">{{ ocorrencia.servidor_registro.get_apelido }}</span>
</div> </div>
<div class="col s9 m11">
<p>{{ ocorrencia.descricao }}</p>
<div>
{% trans "Prioridade" %}: <a class='dropdown-trigger btn-small btn-flat' href='#' data-target='prioridade-{{ ocorrencia.id }}'>{{ ocorrencia.get_prioridade_display }}</a>
<ul id='prioridade-{{ ocorrencia.id }}' class='dropdown-content'>
{% for key, name in PRIORITY_CHOICES %}
{% if key != ocorrencia.prioridade %}
<li><a href="#!">{{ name }}</a></li>
{% endif %} {% endif %}
{% endfor %} {% endblock %}
</ul>
<a class="waves-effect waves-light btn-small btn-flat right modal-trigger" href="#modal{{ ocorrencia.id}}">{% blocktranslate count counter=ocorrencia.anexo_set.count %}Um anexo{% plural %}{{ counter }} anexos{% endblocktranslate %}</a>
<div id="modal{{ ocorrencia.id}}" class="modal">
<div class="modal-content">
<h4>Anexos</h4>
<ul class="collection">
{% for anexo in ocorrencia.anexo_set.all %}
<li class="collection-item">
<div>
<a href="{{ anexo.arquivo.url }}" download>{{ anexo.data_pub|date:"SHORT_DATE_FORMAT" }} | {{ anexo.descricao }}</a>
<a href="#!" class="secondary-content"><i class="material-icons">delete_forever</i></a>
</div>
</li>
{% endfor %}
</ul>
</div> </div>
<div class="modal-footer"> <div class="modal-footer">
<a href="#!" class="modal-close waves-effect waves-green btn-flat">Agree</a> <a href="#!" class="modal-close waves-effect waves-green btn-flat">{% trans "Close" %}</a>
</div> <button id="apply-filters" type="submit" class="waves-effect waves-green btn-flat">{% trans 'Filtrar' %}</button>
</div>
</div>
</div>
</div> </div>
</form>
</div> </div>
<div class="card-content"> {% endblock %}
<ul class="collection">
<li class="collection-item avatar"> {% block ocorrencia_cards %}
{% if usuario.foto %} {% for ocorrencia in ocorrencias %}
<img class="circle commenter-image" src="{{ MEDIA_URL }}{{ servidor_registro.foto }}"/> {% include 'ocorrencias/painel_snippet.html' %}
{% else %}
<i class="material-icons circle">account_circle</i>
{% endif %}
<form class="row" id="comentar_ocorrencia_{{ ocorrencia.id|safe }}" action="#!" method="post" data-ocorrencia-id="{{ ocorrencia.id|safe }}">
{% csrf_token %}
<p>{% trans "Comentar" %}:</p>
{% for field in comentario_form %}
{% if field.name == 'ocorrencia' %}
<input type='hidden' name='ocorrencia' value='{{ ocorrencia.id|safe }}'/>
{% elif field.name == 'novo_status' %}
<div class="input-field col m4 s12">
<select name="novo_status" id="id_novo_status_{{ ocorrencia.id|safe }}" class="browser-default">
{% for value, label in field.field.widget.choices %}
{% if value == '' %}
<option value="{{ value|stringformat:'s' }}">{{ label }}</option>
{% elif value != 1 %}
{% if ocorrencia.status < 3 and value > 2 %}
<option value="{{ value|stringformat:'s' }}">{{ label }}</option>
{% endif %}
{% if ocorrencia.status > 2 and value == 2 %}
<option value="{{ value|stringformat:'s' }}">{{ label }}</option>
{% endif %}
{% endif %}
{% endfor %} {% endfor %}
</select> {% endblock ocorrencia_cards %}
</div>
{% block paginator %}
{% if is_paginated %}
<ul class="pagination">
{% if page_obj.has_previous %}
<li class="waves-effect"><a href="?{{ filter.preserve_filter }}&page={{ page_obj.previous_page_number }}"><i class="material-icons">chevron_left</i></a></li>
{% else %} {% else %}
<div class="input-field col m8 s12"> <li class="disabled"><a href="?{{ filter.preserve_filter }}"><i class="material-icons">chevron_left</i></a></li>
{{ field }}
</div>
{% endif %} {% endif %}
{% for page_number in page_obj.paginator.page_range %}
<li class=" {% if page_number == page_obj.number %}active{% else %}waves-effect{% endif %}"><a href="?{{ filter.preserve_filter }}&page={{ page_number }}">{{ page_number }}</a></li>
{% endfor %} {% endfor %}
<button type="submit" class="secondary-content"><i class="material-icons">send</i></button> {% if page_obj.has_next %}
</form> <li class="waves-effect"><a href="?{{ filter.preserve_filter }}&page={{ page_obj.next_page_number }}"><i class="material-icons">chevron_right</i></a></li>
</li>
{% for comentario in ocorrencia.comentarios.all %}
<li class="collection-item avatar">
{% if comentario.usuario.foto %}
<img class="circle" src="{{ MEDIA_URL }}{{ comentario.usuario.foto }}"/>
{% else %} {% else %}
<i class="material-icons circle ">account_circle</i> <li class="disabled"><a href="?{{ filter.preserve_filter }}"><i class="material-icons">chevron_right</i></a></li>
{% endif %}
<p>{% blocktranslate with data=comentario.data_criacao nome=comentario.usuario.get_apelido %}
Em {{ data }}, {{ nome }} disse:
{% endblocktranslate %}</p>
<span class="title">{{ comentario.descricao }}</span>
{% if comentario.novo_status %}
<p>{% blocktranslate with status=comentario.get_novo_status_display|default:"-" %}
Status: {{ status }}
{% endblocktranslate %}</p>
{% endif %} {% endif %}
</li>
{% endfor %}
</ul> </ul>
</div> {% endif %}
</div> {% endblock paginator %}
</div>
</div>
{% endfor %}
{% endblock %} {% endblock %}
{% block footer %} {% block footer %}
{{ block.super }} {{ block.super }}
<script> <script type="text/javascript" src="{% static 'ocorrencias/js/painel_ocorrencias.js' %}"></script>
$(document).ready(function(){
var elems = document.querySelectorAll('.dropdown-trigger');
var instances = M.Dropdown.init(elems, {});
var elems = document.querySelectorAll('.modal');
var instances = M.Modal.init(elems, {});
});
</script>
{% endblock %} {% endblock %}

153
sigi/apps/ocorrencias/templates/ocorrencias/painel_snippet.html

@ -0,0 +1,153 @@
{% load i18n %}
<div id="ocorrencia-{{ ocorrencia.id|safe }}" class="row">
<div class="col s12">
<div class="card hoverable">
<div class="card-content">
<span class="card-title">
{% block edit_link %}
{% if user.is_staff %}
{% if has_change_permission %}
<a href="{% url "admin:ocorrencias_ocorrencia_change" ocorrencia.id %}"><i class="material-icons right">edit</i></a>
{% endif %}
{{ ocorrencia.casa_legislativa.nome }}, {{ ocorrencia.casa_legislativa.municipio.uf.sigla }}
{% else %}
{{ ocorrencia.assunto }}
{% endif %}
{% endblock edit_link %}
<p class="card-details">
{% blocktrans with data_criacao=ocorrencia.data_criacao|date:"SHORT_DATE_FORMAT" tipo_contato=ocorrencia.tipo_contato categoria=ocorrencia.categoria status=ocorrencia.get_status_display prioridade=ocorrencia.get_prioridade_display %}
Criado em {{ data_criacao }} via {{ tipo_contato }} solicitando {{ categoria }}, com status {{ status }}. Prioridade: {{ prioridade }}
{% endblocktrans %}
</p>
</span>
<div class="row">
<div class="col s3 m1 center-align">
{% if ocorrencia.servidor_registro.foto %}
<img class="circle user-image" src="{{ MEDIA_URL }}{{ ocorrencia.servidor_registro.foto }}"/>
{% else %}
<i class="material-icons circle user-image">account_circle</i>
{% endif %}
<span class="user-name">{{ ocorrencia.servidor_registro.get_apelido }}</span>
</div>
<div class="col s9 m11">
<p>{{ ocorrencia.descricao }}</p>
</div>
</div>
{% block card-adesao %}
{% if 'solicita_convenio' in ocorrencia.infos %}
<div class="row card-inbox">
<span class="inbox-title">{% trans "Solicitação de convênio" %}</span>
{% if user.is_staff %}
<a class="default waves-effect waves-light btn-small right" href="{% url 'ocorrencias_painel_convenio' ocorrencia.id %}{% if filter.preserve_filter %}?list_filter={{ filter.preserve_filter|urlencode }}{% endif %}">Gerenciar</a>
{% endif %}
<p>
{% for key, value in ocorrencia.get_infos_details.items %}
<span class="span-list">
<i class="material-icons {% if value.0 %}green-text{% else %}red-text{% endif %}">{% if value.0 %}done{% else %}clear{% endif %}</i>
{{ value.1 }}
</span>
{% endfor %}
</p>
</div>
{% endif %}
{% endblock card-adesao %}
{% block card-oficina %}
{% if 'solicita_oficinas' in ocorrencia.infos %}
<div class="row card-inbox">
<span class="inbox-title">{% trans "Solicitação de oficinas" %}</span>
{% if user.is_staff %}
<a class="default waves-effect waves-light btn-small right" href="{% url 'ocorrencias_painel_oficina' ocorrencia.id %}{% if filter.preserve_filter %}?list_filter={{ filter.preserve_filter|urlencode }}{% endif %}">Gerenciar</a>
{% endif %}
<p>
<span class="strong">{% trans "Oficinas solicitadas:" %}</span>
{% for oficina in ocorrencia.get_infos_oficinas %}
<span class="span-list">{{ oficina.nome }}</span>
{% endfor %}
</p>
<p>
<span class="strong">{% trans "Senadores selecionados:" %}</span>
{% for senador in ocorrencia.get_infos_senadores %}
<span class="span-list">{{ senador.nome_completo }} ({{ senador.partido.sigla }})</span>
{% endfor %}
</p>
</div>
{% endif %}
{% endblock card-oficina %}
{% block card-anexos %}
<div class="row card-inbox">
<span class="inbox-title">{% trans "Anexos" %}</span>
<table class="striped">
<thead>
<tr>
<th>{% trans "Data de publicação" %}</th>
<th>{% trans "Descrição" %}</th>
<th>{% trans "Arquivo" %}</th>
</tr>
</thead>
<tbody>
{% for anexo in ocorrencia.anexo_set.all %}
<tr>
<td>{{ anexo.data_pub|date:"SHORT_DATE_FORMAT" }}</td>
<td>{{ anexo.descricao }}</td>
<td><a href="{{ anexo.arquivo.url }}" download><i class="material-icons">file_download</i></a></td>
</tr>
{% empty %}
<tr><td colspan="3">{% trans "Nenhum anexo" %}</td></tr>
{% endfor %}
</tbody>
</table>
{% if anexo_form %}
<form action="" method="post" enctype="multipart/form-data">{% csrf_token %}
<button type="submit" name="anexo_save" class="right waves-effect waves-light btn-small"><i class="material-icons left">send</i></button>
{{ anexo_form }}
<input type="hidden" name="ocorrencia_id" value="{{ ocorrencia.id|safe }}"/>
</form>
{% endif %}
</div>
{% endblock card-anexos %}
{% block card-comentarios %}
<div class="row card-inbox">
<span class="inbox-title">{% trans "Comentários" %}</span>
<ul class="collection">
{% for comentario in ocorrencia.comentarios.all %}
{% if user.is_staff or comentario.interno == False %}
<li class="collection-item avatar">
{% if comentario.usuario.foto %}
<img class="circle" src="{{ comentario.usuario.foto.url }}"/>
{% else %}
<i class="material-icons circle ">account_circle</i>
{% endif %}
<p>{% blocktranslate with data=comentario.data_criacao nome=comentario.usuario.get_apelido %}
Em {{ data }}, {{ nome }} disse:
{% endblocktranslate %}</p>
<span class="title">{{ comentario.descricao }}</span>
{% if comentario.novo_status %}
<p>{% blocktranslate with status=comentario.get_novo_status_display|default:"-" %}
Status: {{ status }}
{% endblocktranslate %}</p>
{% endif %}
</li>
{% endif %}
{% empty %}
<li class="collection-item">{% trans "Nenhum comentário" %}</li>
{% endfor %}
{% if comentario_form %}
<li class="collection-item">
<form action="" method="post">{% csrf_token %}
<button type="submit" name="comentario_save" class="right waves-effect waves-light btn-small"><i class="material-icons left">send</i></button>
{{ comentario_form }}
<input type="hidden" name="ocorrencia_id" value="{{ ocorrencia.id|safe }}"/>
</form>
</li>
{% endif %}
</ul>
</div>
{% endblock card-comentarios %}
</div>
</div>
</div>
</div>

44
sigi/apps/ocorrencias/templates/public/ocorrencias/ocorrencia_list.html

@ -0,0 +1,44 @@
{% extends 'public/base_site.html' %}
{% load i18n static %}
{% block extrastyle %}
{{ block.super }}
<link rel="stylesheet" href="{% static 'ocorrencias/css/painel_ocorrencias.css' %}">
<style>
.pagination span {
font-weight: bold;
}
.pagination i {
vertical-align: middle;
margin: 0 24px;
color: #000 !important;
}
</style>
{% endblock extrastyle %}
{% block content %}
{{ block.super }}
<div class="breadcrumbs">
{% for status_code, status_label in statuses %}
{% if status_code in selected_status %}
<a class="waves-effect waves-light btn-small" href="{% url 'ocorrencias:ocorrencia_listview' %}?{% for s in selected_status %}{%if s != status_code %}status={{ s }}&{% endif %}{% endfor %}">
<i class="material-icons left">checked</i>
{{ status_label }}
</a>
{% else %}
<a class="waves-effect waves-light btn-small" href="{% url 'ocorrencias:ocorrencia_listview' %}?status={{ selected_status|join:'&status=' }}&status={{ status_code }}">
{{ status_label }}
</a>
{% endif %}
{% endfor %}
</div>
{% for ocorrencia in object_list %}
{% include 'ocorrencias/painel_snippet.html' %}
{% endfor %}
{% endblock %}
{% block footer %}
{{ block.super }}
<script type="text/javascript" src="{% static 'ocorrencias/js/painel_ocorrencias.js' %}"></script>
{% endblock %}

61
sigi/apps/ocorrencias/templates/public/ocorrencias/oficio_oficina_pdf.html

@ -0,0 +1,61 @@
{% extends 'convenios/oficio_padrao.html' %}
{% load i18n %}
{% block text_body %}
<p>
{% trans "OFÍCIO Nº:" %} {{ ocorrencia.infos.solicita_oficinas.numero_oficio }}
<span class="right">{{ casa.municipio.nome }}, {{ casa.municipio.uf.sigla }}, {% now "DATE_FORMAT" %}.</p>
</p>
<br/>
<p>{% trans "À Sua Excelência o(a) Sr(a). Senador(a)." %}</p>
<p>{% trans "ASSUNTO:" %}<strong> {% trans "Solicitação de oficinas/encontros Interlegis." %}</strong></p>
<br/>
<p>{% trans "Excelentíssimo(a) Sr(a). Senador(a)," %}</p>
<p class="justify-align">{% blocktranslate %}
É do conhecimento desta Câmara Municipal que o ILB-Instituto Legislativo
Brasileiro, gestor do programa Interlegis, tornou-se há muito a referência
nacional de instrumento de apoio no processo de modernização e integração
do Poder Legislativo brasileiro. Indubitavelmente, colabora de maneira
efetiva no cumprimento da Lei no. 12.527, de 2011 (sobre Acesso à
Informação), da Lei no. 13.709, de 2018 (sobre Proteção de Dados), e da Lei
Complementar no. 101, de 2000 (sobre Responsabilidade Fiscal e Transparência
na Gestão Pública), bem como auxilia na aderência aos marcos jurídicos
municipais.{% endblocktranslate %}
</p>
<p class="justify-align">{% blocktranslate %}
Da mesma forma, esta Casa reconhece que o Interlegis realiza sua missão,
em grande parte, com a transferência de tecnologia (disponibilização de
ferramentas tecnológicas para as Câmaras) e as ações de capacitação
(conhecidas como Oficinas e Encontros Interlegis), sem ônus direto e por
meio da colaboração de seus servidores especializados.{% endblocktranslate %}
</p>
<p class="justify-align">{% blocktranslate %}
Também temos ciência de que a solicitação de Oficinas e Encontros deve
observar as condições físicas, operacionais e de pessoal das Casas
legislativas.{% endblocktranslate %}
</p>
<p class="justify-align">{% blocktranslate %}
Assim, vimos solicitar a Vossa Excelência apoio para a realização dos
eventos a seguir, com o objetivo de habilitar os servidores desta Casa
legislativa e das Câmaras Municipais vizinhas para o uso dos produtos e
serviços do Programa Interlegis:{% endblocktranslate %}
</p>
<p><strong>{% trans "Na modalidade:" %}</strong>{% if ocorrencia.infos.solicita_oficinas.modalidade == 'R' %}{% trans "REMOTA (videoconferência)" %}{% else %}{% trans "PRESENCIAL" %}{% endif %}</p>
<p><strong>{% blocktranslate count counter=oficinas|length %}A seguinte oficina:{% plural %}As seguintes oficinas:{% endblocktranslate %}</strong></p>
<ul>{% for oficina in oficinas %}
<li>{{ oficina }}</li>
{% endfor %}</ul>
<p class="justify-align">{% blocktranslate %}
Confiamos também que o atendimento a esta solicitação permitirá, além da
qualificação técnica dos servidores, uma economia significativa de recursos
financeiros, tanto na área de Tecnologia da Informação quanto na capacitação
de Recursos Humanos.{% endblocktranslate %}
</p>
<br/>
<p>{% trans "Respeitosamente," %}</p>
<br/><br/><br/>
<p class="center-align">_______________________________________________</p>
<p class="center-align"><strong>{{ casa.presidente.nome_completo|upper }}</strong></p>
<p class="center-align">{% trans "Presidente" %}</p>
{% endblock %}

57
sigi/apps/ocorrencias/templates/public/ocorrencias/seleciona_casa.html

@ -0,0 +1,57 @@
{% extends "public/base_site.html" %}
{% load static i18n %}
{% block extrastyle %}
{{ block.super }}
<link rel="stylesheet" href="https://code.jquery.com/ui/1.12.0/themes/smoothness/jquery-ui.css" />
<link rel="stylesheet" href="{% static "admin/css/changelists.css" %}" type="text/css" />
<link rel="stylesheet" href="{% static 'ocorrencias/css/ocorrencia.css' %}" type="text/css" />
{% endblock %}
{% block usertools %}
<div id="user-tools">
<a href="/">{% trans "Início" %}</a>
<a href="{% url 'home_index' %}">{% trans "Entrar" %}</a>
</div>
{% endblock %}
{% block side_nav %}{% endblock %}
{% block content %}
{{ block.super }}
<div class="row">
<div class="col s12">
<div class="card">
<div class="card-content">
<span class="card-title">{{ title }}</span>
<p>{{ summary|safe }}</p>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col s12">
<div class="card">
<div class="card-content">
<span class="card-title">{% trans "Identifique sua Casa Legislativa" %}</span>
<p>{% trans "Informe o nome do município ou Estado da sua Casa Legislativa" %}:</p>
<div class="input-field">
<i class="material-icons prefix">search</i>
<input type="text" class="search-text" placeholder="{% trans "Procurar" %}" aria-label="{% trans "Procurar" %}" data-source="{% url 'openmapsearch' %}" data-param="q">
<div class="search-result hide" data-item-click="seleciona_casa"></div>
</div>
</div>
</div>
</div>
</div>
{% endblock %}
{% block footer %}
{{ block.super }}
<script type="text/javascript" src="{% static 'js/search.js' %}"></script>
<script>
function seleciona_casa(data) {
$(location).attr("href", `{{ success_url }}?{{ parameter_name }}=${data.id}`);
}
</script>
{% endblock %}

252
sigi/apps/ocorrencias/templates/public/ocorrencias/solicita_convenio_create.html

@ -0,0 +1,252 @@
{% extends "public/base_site.html" %}
{% load static i18n %}
{% block content %}
{{ block.super }}
<div class="row">
<div class="col s12">
<div class="card">
<div class="card-content">
<span class="card-title">{{ ocorrencia.assunto }} # {{ ocorrencia.id|safe }}</span>
<p>
{% blocktrans with name=ocorrencia.casa_legislativa.nome %}
A solicitação da {{ name }} está na nossa base de dados
{% endblocktrans %}
</p>
</div>
<div class="card-tabs">
<ul class="tabs tabs-fixed-width">
{% if not 'aplicados' in infos or 'casa_legislativa' not in infos.aplicados %}
<li class="tab">
<a {% if tab_name == 'casa' %}class="active" {% endif %}href="{% url 'ocorrencias:solicita_convenio' pk=ocorrencia.id tab='casa' %}">{% trans "Casa legislativa" %}</a>
</li>
{% endif %}
{% if not 'aplicados' in infos or 'presidente' not in infos.aplicados %}
<li class="tab">
<a {% if tab_name == 'presidente' %}class="active" {% endif %}href="{% url 'ocorrencias:solicita_convenio' pk=ocorrencia.id tab='presidente' %}">{% trans "Presidente" %}</a>
</li>
{% endif %}
{% if not 'aplicados' in infos or 'contato' not in infos.aplicados %}
<li class="tab">
<a {% if tab_name == 'contato' %}class="active" {% endif %}href="{% url 'ocorrencias:solicita_convenio' pk=ocorrencia.id tab='contato' %}">{% trans "Contato Interlegis" %}</a>
</li>
{% endif %}
{% if not 'aplicados' in infos %}
<li class="tab">
<a {% if tab_name == 'documentos' %}class="active" {% endif %}href="{% url 'ocorrencias:solicita_convenio' pk=ocorrencia.id tab='documentos' %}">{% trans "Documentos" %}</a>
</li>
{% endif %}
<li class="tab">
<a {% if tab_name == 'resumo' %}class="active" {% endif %}href="{% url 'ocorrencias:solicita_convenio' pk=ocorrencia.id tab='resumo' %}">{% trans "Resumo" %}</a>
</li>
</ul>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col s12">
</div>
{% if tab_name == 'casa' %}
{% if not 'aplicados' in infos or 'casa_legislativa' not in infos.aplicados %}
<div id="casa" class="col s12">
<div class="tab-panel">
<div class="tab-content">
<form action="" method="post" name="casa_legislativa" enctype="multipart/form-data">
{% csrf_token %}
<div class="card">
<div class="card-content">
<span class="card-title">
{% trans "Atualizar as informações cadastrais da Casa" %}
</span>
{{ form }}
<div class="card-action">
<button class="btn waves-effect waves-light" type="submit" name="tab" value="casa">
{% trans "Save" %}
<i class="material-icons right">send</i>
</button>
</div>
</div>
</div>
</form>
</div>
</div>
</div>
{% endif %}
{% endif %}
{% if tab_name == 'presidente' %}
{% if not 'aplicados' in infos or 'presidente' not in infos.aplicados %}
<div id="presidente" class="col s12">
<div class="tab-panel">
<div class="tab-content">
<form action="" method="post" name="presidente">
{% csrf_token %}
<div class="card">
<div class="card-content">
<span class="card-title">
{% trans "Selecionar e atualizar o presidente" %}
</span>
{{ form }}
<div class="card-action">
<button class="btn waves-effect waves-light" type="submit" name="tab" value="presidente">
{% trans "Save" %}
<i class="material-icons right">send</i>
</button>
</div>
</div>
</div>
</form>
</div>
</div>
</div>
{% endif %}
{% endif %}
{% if tab_name == 'contato' %}
{% if not 'aplicados' in infos or 'contato' not in infos.aplicados %}
<div id="contato" class="col s12 tabpanel">
<div class="tab-panel">
<div class="tab-content">
<form action="" method="post" name="contato">
{% csrf_token %}
<div class="card">
<div class="card-content">
<span class="card-title">{% trans "Contato Interlegis" %}</span>
<p>Designe um servidor da Casa Legislativa para ser o contato técnico junto ao Interlegis.</p>
<p>Este servidor será o responsável por acompanhar a formalização do ACT, prestar informações e esclarecimentos, e solicitar a instalação de produtos e serviços ao Interlegis.</p>
{{ form }}
<div class="card-action">
<button class="btn waves-effect waves-light" type="submit" name="tab" value="contato">
{% trans "Save" %}
<i class="material-icons right">send</i>
</button>
</div>
</div>
</div>
</form>
</div>
</div>
</div>
{% endif %}
{% endif %}
{% if tab_name == "documentos" %}
<div id="documentos" class="col s12 tabpanel">
<div class="tab-panel">
<div class="tab-content">
<form action="" method="post" name="documentos" enctype="multipart/form-data">
{% csrf_token %}
<div class="card">
<div class="card-content">
<span class="card-title">{% trans "Documentos de formalização" %}</span>
<p>Os documentos para formalização do convênio foram gerados e estão disponíveis abaixo.</p>
<p>Você precisa realizar os seguintes passos para que possamos dar prosseguimento ao processo:</p>
<ul>
<li>Baixe (dowload) o ofício de solicitação do convênio.</li>
<li>Providencie que o ofício de solicitação seja assinado pelo Presidente da Casa. Se for possível, assine o PDF com uma assinatura digital. Se o Presidente não possui uma assinatura digital válida, pode-se imprimir o documento, assinar com caneta azul, e escanear o documento assinado.</li>
<li>Suba (upload) o ofício assinado no campo Arquivo, abaixo, em formato PDF</li>
<li>O documento Minuta de ACT é a minuta do convênio que tramitará no Senado e está disponível para consulta e avaliação da consultoria jurídica da sua Casa Legislativa. Após assinatura do ACt pela diretoria do Senado, a cópia definitiva será enviada à sua Casa para colher também a assinatura do Presidente.</p>
</ul>
<p>Assim que recebermos o ofício devidamente assinado, iniciaremos o procedimento burocrático para formalização do convênio. Você poderá acompanhar a evolução deste processo nesta tela, na aba RESUMO</p>
<table class="striped">
<thead>
<caption>Arquivos do processo</caption>
<tr>
<th>Descrição</th><th>Arquivo</th>
</tr>
</thead>
<tbody>
{% for anexo in ocorrencia.anexo_set.all %}
<tr>
<td>{{ anexo.descricao }}</td>
<td><a href="{{ anexo.arquivo.url }}">{{ anexo.arquivo.name }}</a></td>
</tr>
{% endfor %}
</tbody>
</table>
{{ form }}
<div class="card-action">
<button class="btn waves-effect waves-light" type="submit" name="tab" value="documentos">
{% trans "Save" %}
<i class="material-icons right">send</i>
</button>
</div>
</div>
</div>
</form>
</div>
</div>
</div>
{% endif %}
{% if tab_name == "resumo" %}
<div id="resumo" class="col s12 tabpanel">
<div class="tab-panel">
<div class="tab-content">
<form action="" method="post" name="comentario">
{% csrf_token %}
<div class="card">
<div class="card-content">
<table>
<tr>
<th>{% trans "Casa legislativa" %}</th><td>{{ ocorrencia.casa_legislativa.nome }}</td>
<th>{% trans "Descrição" %}</th><td>{{ ocorrencia.descricao }}</td>
<th>{% trans "Solicitado em" %}</th><td>{{ ocorrencia.data_criacao|date:"DATE_FORMAT" }}</td>
</tr>
<tr>
<th>{% trans "Situação" %}</th><td>{{ ocorrencia.get_status_display }}</td>
<th>{% trans "Prioridade" %}</th><td>{{ ocorrencia.get_prioridade_display }}</td>
<th>{% trans "Última atualização" %}</th><td>{{ ocorrencia.data_modificacao|date:"DATE_FORMAT" }}</td>
</tr>
</table>
<table>
<thead>
<caption><span class="card-title">{% trans "Progresso do processo" %}</span></caption>
<tr><th>{% trans "Data" %}</th><th>{% trans "Descrição" %}</th><th>{% trans "Novo status" %}</th><th>{% trans "Registrado por" %}</th></tr>
</thead>
<tbody>
{% for comentario in ocorrencia.comentarios.all %}
{% if not comentario.interno %}
<tr>
<td>{{ comentario.data_criacao|date:"SHORT_DATE_FORMAT" }}</td>
<td>{{ comentario.descricao }}</td>
<td>{{ comentario.get_novo_status_display|default:"-" }}</td>
<td>{{ comentario.usuario }}</td>
</tr>
{% endif %}
{% empty %}
<tr><td colspan="4">{% trans "Aguardando andamento no Senado" %}</td></tr>
{% endfor %}
</tbody>
</table>
{{ form }}
<div class="card-action">
<button class="btn waves-effect waves-light" type="submit" name="tab" value="resumo">
{% trans "Comentar" %}
<i class="material-icons left">comment</i>
</button>
</div>
</div>
</div>
</form>
</div>
</div>
</div>
{% endif %}
</div>
{% endblock %}
{% block footer %}
{{ block.super }}
<script>
$(document).ready(function() {
$("select#id_presidente-parlamentar").on("change", function() {
$.get("{% url 'parlamentares:parlamentar_data' %}", `id=${this.value}`, function(data) {
for(var campo of Object.keys(data[0].fields)) {
$(`#id_presidente-${campo}`).val(data[0].fields[campo]);
}
})
})
});
function seleciona_casa(data) {
$(location).attr("href", `{% url 'ocorrencias:ocorrencia_convenio_seleciona_casa' %}?casa_id=${data.id}`);
}
</script>
{% endblock %}

24
sigi/apps/ocorrencias/templates/public/ocorrencias/solicita_treinamento_create.html

@ -0,0 +1,24 @@
{% extends 'public/base_site.html' %}
{% load i18n %}
{% block content %}
{{ block.super }}
<div class="row">
<div class="col s12">
<form method="post">{% csrf_token %}
<div class="card">
<div class="card-content">
<span class="card-title">{% trans "Solicitação de treinamentos" %}</span>
{{ form }}
</div>
<div class="card-action">
<button class="btn waves-effect waves-light" type="submit" name="action">
{% trans 'Solicitar' %}
<i class="material-icons right">save</i>
</button>
</div>
</form>
</div>
</div>
</div>
{% endblock %}

67
sigi/apps/ocorrencias/templates/public/ocorrencias/solicita_treinamento_view.html

@ -0,0 +1,67 @@
{% extends 'public/base_site.html' %}
{% load i18n %}
{% block extrahead %}
{{ block.super }}
{{ form.media }}
{% endblock extrahead %}
{% block content %}
{{ block.super }}
<div class="row">
<div class="col s12">
<form method="post" enctype="multipart/form-data">{% csrf_token %}
<div class="card">
<div class="card-content">
<span class="card-title">{% blocktranslate with id=ocorrencia.id|safe %}Solicitação de treinamento #{{ id }}{% endblocktranslate %}</span>
<blockquote><h6>O ofício de solicitação de oficinas foi gerado e está disponível abaixo.</h6></blockquote>
<table>
<thead><caption>Resumo da ocorrência</caption></thead>
<tbody>
<tr>
<th colspan="2">{% trans "Descrição" %}</th><td>{{ ocorrencia.descricao }}</td>
<th>{% trans "Solicitado em" %}</th><td>{{ ocorrencia.data_criacao|date:"DATE_FORMAT" }}</td>
</tr>
<tr>
<th>{% trans "Situação" %}</th><td>{{ ocorrencia.get_status_display }}</td>
<th>{% trans "Prioridade" %}</th><td>{{ ocorrencia.get_prioridade_display }}</td>
<th>{% trans "Última atualização" %}</th><td>{{ ocorrencia.data_modificacao|date:"DATE_FORMAT" }}</td>
</tr>
</tbody>
</table>
<table class="striped">
<thead>
<caption>Arquivos do processo</caption>
<tr>
<th>Descrição</th><th>Arquivo</th>
</tr>
</thead>
<tbody>
{% for anexo in ocorrencia.anexo_set.all %}
<tr>
<td>{{ anexo.descricao }}</td>
<td><a href="{{ anexo.arquivo.url }}">{{ anexo.arquivo.name }}</a></td>
</tr>
{% endfor %}
</tbody>
</table>
<blockquote><h6>Você precisa realizar os seguintes passos para que possamos dar prosseguimento ao processo:</h6></blockquote>
<ul class="collection">
<li class="collection-item">Baixe (dowload) o ofício de solicitação de oficinas.</li>
<li class="collection-item">Providencie que o ofício de solicitação seja assinado pelo Presidente da Casa. Se for possível, assine o PDF com uma assinatura digital. Se o Presidente não possui uma assinatura digital válida, pode-se imprimir o documento, assinar com caneta azul, e escanear o documento assinado.</li>
<li class="collection-item">Suba (upload) o ofício assinado no campo Arquivo, abaixo, em formato PDF</li>
</ul>
<blockquote><h6>Assim que recebermos o ofício devidamente assinado, iniciaremos o procedimento burocrático para realização da(s) oficina(s).</h6></blockquote>
{{ form }}
</div>
<div class="card-action">
<button class="btn waves-effect waves-light" type="submit">
{% trans "Save" %}
<i class="material-icons right">send</i>
</button>
</div>
</form>
</div>
</div>
</div>
{% endblock %}

67
sigi/apps/ocorrencias/urls.py

@ -1,32 +1,47 @@
from django.urls import path from django.urls import path, re_path
from sigi.apps.ocorrencias import views from sigi.apps.ocorrencias import views
app_name = "ocorrencias"
urlpatterns = [ urlpatterns = [
path("convenio/", views.seleciona_casa, name="ocorrencias-seleciona-casa"),
path( path(
"ocorrencia/<int:ocorrencia_id>", "ocorrencia/",
views.ocorrencia, views.OcorrenciaListView.as_view(),
name="ocorrencias_ocorrencia", name="ocorrencia_listview",
),
path(
"ocorrencia/oficina/casa/",
views.OficinaSelecionaCasaView.as_view(),
name="ocorrencia_oficina_seleciona_casa",
),
path(
"ocorrencia/oficina/create/",
views.SolicitaOficinaCreateView.as_view(),
name="solicita_oficina_create",
),
path(
"ocorrencia/<int:pk>/oficina/",
views.SolicitaOficinaView.as_view(),
name="solicita_oficina_view",
),
path(
"ocorrencia/convenio/casa/",
views.ConvenioSelecionaCasaView.as_view(),
name="ocorrencia_convenio_seleciona_casa",
),
path(
"ocorrencia/convenio/create/",
views.SolicitaConvenioCreateView.as_view(),
name="solicita_convenio",
),
path(
"ocorrencia/<int:pk>/convenio/",
views.SolicitaConvenioCreateView.as_view(),
name="solicita_convenio",
),
re_path(
"ocorrencia/(?P<pk>\d+)/convenio/(?P<tab>casa|presidente|contato|documentos|resumo)/",
views.SolicitaConvenioCreateView.as_view(),
name="solicita_convenio",
), ),
] ]
# # coding: utf-8
# from django.conf.urls import patterns, url
# urlpatterns = patterns(
# 'sigi.apps.ocorrencias.views',
# # Painel de ocorrencias
# url(r'^painel/$', 'painel_ocorrencias', name='painel-ocorrencias'),
# url(r'^painel/buscanominal/$', 'busca_nominal', {"origin": "tudo"}, name='painel-buscanominal'),
# url(r'^painel/buscanominal/casa/$', 'busca_nominal', {"origin": "casa"}, name='painel-buscacasa'),
# url(r'^painel/buscanominal/servidor/$', 'busca_nominal', {"origin": "servidor"}, name='painel-buscaservidor'),
# url(r'^painel/buscanominal/servico/$', 'busca_nominal', {"origin": "servico"}, name='painel-buscaservico'),
# url(r'^mudaprioridade/$', 'muda_prioridade', name='ocorrencia-mudaprioridade'),
# url(r'^excluianexo/$', 'exclui_anexo', name='ocorrencia-excluianexo'),
# url(r'^incluianexo/$', 'inclui_anexo', name='ocorrencia-incluianexo'),
# url(r'^anexosnippet/$', 'anexo_snippet', name='ocorrencia-anexosnippet'),
# url(r'^incluicomentario/$', 'inclui_comentario', name='ocorrencia-incluicomentario'),
# url(r'^incluiocorrencia/$', 'inclui_ocorrencia', name='ocorrencia-incluiocorrencia'),
# )

1456
sigi/apps/ocorrencias/views.py

File diff suppressed because it is too large

132
sigi/apps/parlamentares/admin.py

@ -1,20 +1,18 @@
import csv
import json import json
from django.db import transaction import tablib
from django.db.models import Q
from django.contrib import admin from django.contrib import admin
from django.contrib import messages
from django.contrib.contenttypes.admin import GenericTabularInline
from django.core.files.temp import NamedTemporaryFile
from django.http import HttpResponseRedirect, HttpResponse
from django.shortcuts import redirect, render from django.shortcuts import redirect, render
from django.urls import path, reverse from django.urls import path, reverse
from django.utils import timezone from django.utils import timezone
from django.utils.html import escape, escapejs
from django.utils.safestring import mark_safe from django.utils.safestring import mark_safe
from django.utils.translation import gettext as _ from django.utils.translation import gettext as _
from sigi.apps.casas.models import Orgao from import_export import resources
from import_export.admin import ImportMixin
from import_export.formats.base_formats import CSV
from sigi.apps.contatos.models import UnidadeFederativa
from sigi.apps.parlamentares.jobs import import_path, json_path from sigi.apps.parlamentares.jobs import import_path, json_path
from sigi.apps.parlamentares.models import Partido, Parlamentar from sigi.apps.parlamentares.models import Partido, Parlamentar, Senador
from sigi.apps.parlamentares.forms import ImportForm from sigi.apps.parlamentares.forms import ImportForm
from sigi.apps.utils.filters import AlphabeticFilter from sigi.apps.utils.filters import AlphabeticFilter
from sigi.apps.utils.mixins import ( from sigi.apps.utils.mixins import (
@ -48,6 +46,92 @@ class ParlamentarResource(LabeledResourse):
export_order = fields export_order = fields
class SenadorImportResource(resources.ModelResource):
uf = resources.Field(
attribute="uf",
column_name="/ListaParlamentarEmExercicio/Parlamentares/Parlamentar/IdentificacaoParlamentar/UfParlamentar",
)
partido = resources.Field(
attribute="partido",
column_name="/ListaParlamentarEmExercicio/Parlamentares/Parlamentar/IdentificacaoParlamentar/SiglaPartidoParlamentar",
)
codigo = resources.Field(
attribute="codigo",
column_name="/ListaParlamentarEmExercicio/Parlamentares/Parlamentar/IdentificacaoParlamentar/CodigoParlamentar",
)
nome_parlamentar = resources.Field(
attribute="nome_parlamentar",
column_name="/ListaParlamentarEmExercicio/Parlamentares/Parlamentar/IdentificacaoParlamentar/NomeParlamentar",
)
nome_completo = resources.Field(
attribute="nome_completo",
column_name="/ListaParlamentarEmExercicio/Parlamentares/Parlamentar/IdentificacaoParlamentar/NomeCompletoParlamentar",
)
sexo = resources.Field(
attribute="sexo",
column_name="/ListaParlamentarEmExercicio/Parlamentares/Parlamentar/IdentificacaoParlamentar/SexoParlamentar",
)
forma_tratamento = resources.Field(
attribute="forma_tratamento",
column_name="/ListaParlamentarEmExercicio/Parlamentares/Parlamentar/IdentificacaoParlamentar/FormaTratamento",
)
email = resources.Field(
attribute="email",
column_name="/ListaParlamentarEmExercicio/Parlamentares/Parlamentar/IdentificacaoParlamentar/EmailParlamentar",
)
class Meta:
import_id_fields = ["codigo"]
model = Senador
fields = (
"uf",
"partido",
"codigo",
"nome_parlamentar",
"nome_completo",
"sexo",
"forma_tratamento",
"email",
)
report_skipped = False
skip_unchanged = True
def __init__(self):
super().__init__()
self.partidos = {p.sigla.upper(): p for p in Partido.objects.all()}
self.partidos.update({p.nome.upper(): p for p in Partido.objects.all()})
self.ufs = {uf.sigla: uf for uf in UnidadeFederativa.objects.all()}
def before_import_row(self, row, row_number=None, **kwargs):
uf = self.fields["uf"].column_name
partido = self.fields["partido"].column_name
sexo = self.fields["sexo"].column_name
if sexo in row:
row[sexo] = row.get(sexo)[0]
if uf in row and row.get(uf) != "":
row[uf] = self.ufs.get(row.get(uf, "").upper())
if partido in row and row.get(partido) != "":
sigla_partido = row.get(partido, "")
if sigla_partido == "S/Partido":
sigla_partido = "SEM PARTIDO"
row[partido] = self.partidos.get(sigla_partido.upper())
return row
def skip_row(self, instance, original):
result = (
not hasattr(instance, "uf") or not hasattr(instance, "email")
) or super().skip_row(instance, original)
return result
class SemicolonCSV(CSV):
def get_title(self):
return "CSV do Senado"
def create_dataset(self, in_stream, **kwargs):
return tablib.import_set(in_stream, format="csv", delimiter=";")
class ParlamentarNomeCompletoFilter(AlphabeticFilter): class ParlamentarNomeCompletoFilter(AlphabeticFilter):
title = _("Inicial do Nome Completo") title = _("Inicial do Nome Completo")
parameter_name = "nome_completo" parameter_name = "nome_completo"
@ -161,10 +245,11 @@ class ParlamentarAdmin(CartExportMixin, admin.ModelAdmin):
dst_file.flush() dst_file.flush()
form = ImportForm(request.POST, request.FILES) form = ImportForm(request.POST, request.FILES)
context = admin.site.each_context(request) or {} context = {
context["opts"] = self.model._meta "opts": self.model._meta,
context["form"] = form "form": form,
context["last_result"] = import_path / "result.html" "last_result": import_path / "result.html",
}
if request.method == "POST" and form.is_valid(): if request.method == "POST" and form.is_valid():
json_data = { json_data = {
"upload_time": timezone.localtime(), "upload_time": timezone.localtime(),
@ -192,6 +277,23 @@ class ParlamentarAdmin(CartExportMixin, admin.ModelAdmin):
return render(request, "parlamentares/import.html", context) return render(request, "parlamentares/import.html", context)
def result_import_action(self, request, *args, **kwargs): def result_import_action(self, request, *args, **kwargs):
context = admin.site.each_context(request) or {} context = {"opts": self.model._meta}
context["opts"] = self.model._meta
return render(request, "parlamentares/import_result.html", context) return render(request, "parlamentares/import_result.html", context)
@admin.register(Senador)
class SenadorAdmin(ImportMixin, admin.ModelAdmin):
resource_class = SenadorImportResource
list_display = ("nome_parlamentar", "uf", "partido")
list_filter = ("uf", "partido", "sexo")
search_fields = (
"nome_parlamentar",
"nome",
"uf__sigla",
"uf__nome",
"partido__sigla",
"partido__nome",
)
def get_import_formats(self):
return [SemicolonCSV]

2
sigi/apps/parlamentares/apps.py

@ -2,6 +2,6 @@ from django.apps import AppConfig
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
class CasasConfig(AppConfig): class ParlamentaresConfig(AppConfig):
name = "sigi.apps.parlamentares" name = "sigi.apps.parlamentares"
verbose_name = _("parlamentares") verbose_name = _("parlamentares")

25
sigi/apps/parlamentares/forms.py

@ -1,7 +1,9 @@
from requests import options from requests import options
from django import forms from django import forms
from django.utils.translation import gettext as _ from django.utils.translation import gettext as _
from material.admin.widgets import MaterialAdminTextareaWidget
from sigi.apps.contatos.models import UnidadeFederativa from sigi.apps.contatos.models import UnidadeFederativa
from sigi.apps.parlamentares.models import Parlamentar
class ImportForm(forms.Form): class ImportForm(forms.Form):
@ -39,3 +41,26 @@ class ImportForm(forms.Form):
self.fields["uf_importar"].choices = [ self.fields["uf_importar"].choices = [
("BR", _("Todo o Brasil")), ("BR", _("Todo o Brasil")),
] + [(uf.sigla, uf.nome) for uf in UnidadeFederativa.objects.all()] ] + [(uf.sigla, uf.nome) for uf in UnidadeFederativa.objects.all()]
class ParlamentarForm(forms.ModelForm):
class Meta:
model = Parlamentar
fields = [
"foto",
"nome_completo",
"nome_parlamentar",
"partido",
"ano_eleicao",
"status_mandato",
"presidente",
"data_nascimento",
"cpf",
"identidade",
"telefones",
"email",
"redes_sociais",
]
widgets = {
"redes_sociais": MaterialAdminTextareaWidget,
}

17
sigi/apps/parlamentares/migrations/0011_alter_parlamentar_options.py

@ -0,0 +1,17 @@
# Generated by Django 4.0.6 on 2022-08-02 17:34
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('parlamentares', '0010_alter_parlamentar_options'),
]
operations = [
migrations.AlterModelOptions(
name='parlamentar',
options={'ordering': ('status_mandato', '-presidente', 'nome_completo'), 'verbose_name_plural': 'parlamentares'},
),
]

77
sigi/apps/parlamentares/migrations/0012_senador.py

@ -0,0 +1,77 @@
# Generated by Django 4.1 on 2022-08-19 02:27
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
(
"contatos",
"0005_alter_mesorregiao_options_alter_microrregiao_options_and_more",
),
("parlamentares", "0011_alter_parlamentar_options"),
]
operations = [
migrations.CreateModel(
name="Senador",
fields=[
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
("codigo", models.IntegerField(unique=True, verbose_name="código")),
(
"nome_parlamentar",
models.CharField(max_length=100, verbose_name="nome parlamentar"),
),
(
"nome_completo",
models.CharField(max_length=100, verbose_name="nome completo"),
),
(
"sexo",
models.CharField(
choices=[("M", "Masculino"), ("F", "Feminino")],
max_length=1,
verbose_name="sexo",
),
),
(
"forma_tratamento",
models.CharField(max_length=50, verbose_name="forma de tratamento"),
),
("email", models.EmailField(max_length=254, verbose_name="e-mail")),
(
"partido",
models.ForeignKey(
blank=True,
null=True,
on_delete=django.db.models.deletion.CASCADE,
to="parlamentares.partido",
verbose_name="partido",
),
),
(
"uf",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
to="contatos.unidadefederativa",
verbose_name="UF",
),
),
],
options={
"verbose_name": "senador",
"verbose_name_plural": "senadores",
"ordering": ("uf", "nome_parlamentar"),
},
),
]

39
sigi/apps/parlamentares/models.py

@ -1,6 +1,7 @@
from django.db import models from django.db import models
from django.utils.translation import gettext as _ from django.utils.translation import gettext as _
from sigi.apps.casas.models import Orgao from sigi.apps.casas.models import Orgao
from sigi.apps.contatos.models import UnidadeFederativa
class Partido(models.Model): class Partido(models.Model):
@ -86,7 +87,7 @@ class Parlamentar(models.Model):
class Meta: class Meta:
ordering = ( ordering = (
"status_mandato", "status_mandato",
"presidente", "-presidente",
"nome_completo", "nome_completo",
) )
verbose_name_plural = _("parlamentares") verbose_name_plural = _("parlamentares")
@ -100,3 +101,39 @@ class Parlamentar(models.Model):
presidente=True presidente=True
).update(presidente=False) ).update(presidente=False)
return super().save(*args, **kwargs) return super().save(*args, **kwargs)
class Senador(models.Model):
SEXO_MASCULINO = "M"
SEXO_FEMININO = "F"
SEXO_CHOICES = (
(SEXO_MASCULINO, _("Masculino")),
(SEXO_FEMININO, _("Feminino")),
)
uf = models.ForeignKey(
UnidadeFederativa, verbose_name=_("UF"), on_delete=models.CASCADE
)
partido = models.ForeignKey(
Partido,
verbose_name=_("partido"),
blank=True,
null=True,
on_delete=models.CASCADE,
)
codigo = models.IntegerField(_("código"), unique=True)
nome_parlamentar = models.CharField(_("nome parlamentar"), max_length=100)
nome_completo = models.CharField(_("nome completo"), max_length=100)
sexo = models.CharField(_("sexo"), max_length=1, choices=SEXO_CHOICES)
forma_tratamento = models.CharField(_("forma de tratamento"), max_length=50)
email = models.EmailField(_("e-mail"))
class Meta:
ordering = (
"uf",
"nome_parlamentar",
)
verbose_name = _("senador")
verbose_name_plural = _("senadores")
def __str__(self):
return self.nome_parlamentar

84
sigi/apps/parlamentares/templates/public/parlamentar_list.html

@ -0,0 +1,84 @@
{% extends 'public/base_site.html' %}
{% load i18n %}
{% block extrastyle %}
{{ block.super }}
<style>
.pagination span {
font-weight: bold;
}
.pagination i {
vertical-align: middle;
margin: 0 24px;
color: #000 !important;
}
</style>
{% endblock extrastyle %}
{% block content %}
{{ block.super }}
<div class="breadcrumbs">
{% if suplentes %}
<a class="waves-effect waves-light btn-small" href="{% url "parlamentares:parlamentar_listview" %}">{% trans 'Ocultar suplentes' %}</a>
{% else %}
<a class="waves-effect waves-light btn-small" href="{% url "parlamentares:parlamentar_listview" %}?suplentes=1">{% trans 'Mostrar suplentes' %}</a>
{% endif %}
</div>
<div class="row">
<div class="col s12">
<div class="card">
<div class="card-content">
<table class="striped">
<tr>
<th>{% trans 'Foto' %}</th>
<th>{% trans 'Nome' %}</th>
<th>{% trans 'CPF' %}</th>
<th>{% trans 'Partido' %}</th>
<th>{% trans 'Ano eleição' %}</th>
<th>{% trans 'Status mandato' %}</th>
<th>{% trans 'Presidente' %}</th>
</tr>
{% for parlamentar in object_list %}
<tr>
<td>
{% if parlamentar.foto %}
<a href="{% url 'parlamentares:parlamentar_update' parlamentar.id %}"><img class="circle responsive-img" src="{{ parlamentar.foto.url }}" width="33"></a>
{% endif %}
</td>
<td><a href="{% url 'parlamentares:parlamentar_update' parlamentar.id %}">{{ parlamentar.nome_completo }}</a></td>
<td>{{ parlamentar.cpf }}</td>
<td>{{ parlamentar.partido.nome }}</td>
<td>{{ parlamentar.ano_eleicao|safe }}</td>
<td>{{ parlamentar.get_status_mandato_display }}</td>
<td>
{% if parlamentar.presidente %}
<i class="material-icons small green-text">check</i>
{% else %}
<i class="material-icons tiny grey-text">highlight_off</i>
{% endif %}
</td>
</tr>
{% endfor %}
</table>
</div>
<div class="card-action">
<div class='pagination'>
{% if page_obj.has_previous %}
<a href='{% url "parlamentares:parlamentar_listview" %}?page={{ page_obj.previous_page_number }}{% if suplentes %}&suplentes=1{% endif %}'><i class="material-icons">skip_previous</i></a>
{% endif %}
{% if page_obj.paginator.num_pages > 1 %}
<span>
{% blocktranslate with number=page_obj.number num_pages=page_obj.paginator.num_pages %}
Página {{ number }} de {{ num_pages }}
{% endblocktranslate %}
</span>
{% endif %}
{% if page_obj.has_next %}
<a href='{% url "parlamentares:parlamentar_listview" %}?page={{ page_obj.next_page_number }}{% if suplentes %}&suplentes=1{% endif %}'><i class="material-icons">skip_next</i></a>
{% endif %}
</div>
</div>
</div>
</div>
</div>
{% endblock %}

28
sigi/apps/parlamentares/templates/public/parlamentar_update.html

@ -0,0 +1,28 @@
{% extends 'public/base_site.html' %}
{% load i18n %}
{% block extrahead %}
{{ block.super }}
{{ form.media }}
{% endblock extrahead %}
{% block content %}
{{ block.super }}
<div class="row">
<div class="col s12">
<form method="post" enctype="multipart/form-data">{% csrf_token %}
<div class="card">
<div class="card-content">
{{ form }}
</div>
<div class="card-action">
<button class="btn waves-effect waves-light" type="submit" name="action">
{% trans 'Save' %}
<i class="material-icons right">save</i>
</button>
</div>
</form>
</div>
</div>
</div>
{% endblock %}

18
sigi/apps/parlamentares/urls.py

@ -1,11 +1,23 @@
from django.urls import path, include from django.urls import path, include
from sigi.apps.parlamentares import views from sigi.apps.parlamentares import views
app_name = "parlamentares"
urlpatterns = [ urlpatterns = [
path( path(
"parlamentarjson/<int:casa_id>/", "parlamentar/",
views.ParlamentarListView.as_view(),
name="parlamentar_listview",
),
path(
"parlamentar/<int:pk>/",
views.ParlamentarUpdateView.as_view(),
name="parlamentar_update",
),
path(
"parlamentar/<int:casa_id>/json/",
views.parlamentares_casa, views.parlamentares_casa,
name="parlamentar-json", name="parlamentar_json",
), ),
path("parlamentardata/", views.parlamentar_data, name="parlamentar-data"), path("parlamentar/data/", views.parlamentar_data, name="parlamentar_data"),
] ]

77
sigi/apps/parlamentares/views.py

@ -1,12 +1,11 @@
from django.conf import settings from django.contrib.admin.sites import site
from django.contrib.auth.decorators import login_required from django.contrib.auth.mixins import LoginRequiredMixin
from django.core.paginator import Paginator, InvalidPage, EmptyPage
from django.core.serializers import serialize from django.core.serializers import serialize
from django.http import HttpResponse, HttpResponseRedirect, JsonResponse from django.http import HttpResponse, JsonResponse
from django.shortcuts import render, get_list_or_404 from django.urls import reverse_lazy
from django.template import Context, loader, RequestContext from django.views.generic import UpdateView, ListView
from django.views.decorators.csrf import csrf_protect
from sigi.apps.casas.models import Orgao from sigi.apps.casas.models import Orgao
from sigi.apps.parlamentares.forms import ParlamentarForm
from sigi.apps.parlamentares.models import Parlamentar from sigi.apps.parlamentares.models import Parlamentar
@ -29,3 +28,67 @@ def parlamentar_data(request):
), ),
content_type="application/json", content_type="application/json",
) )
################################################################################
# Views para site público - acesso dos contatos Interlegis #
################################################################################
class ParlamentarListView(LoginRequiredMixin, ListView):
model = Parlamentar
paginate_by = 100
template_name = "public/parlamentar_list.html"
def get_object(self):
casa_id = self.request.session.get("casa_id", None)
if casa_id:
casa = Orgao.objects.filter(id=casa_id).first()
else:
casa = Orgao.objects.filter(
funcionario__email=self.request.user.email
).first()
return casa
def get_queryset(self):
casa = self.get_object()
if casa:
if self.request.GET.get("suplentes", 0):
return casa.parlamentar_set.all()
else:
return casa.parlamentar_set.exclude(status_mandato="S")
else:
return Parlamentar.objects.none()
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context["casa"] = self.get_object()
if self.request.GET.get("suplentes", 0):
context["suplentes"] = True
return context
class ParlamentarUpdateView(LoginRequiredMixin, UpdateView):
model = Parlamentar
form_class = ParlamentarForm
template_name = "public/parlamentar_update.html"
success_url = reverse_lazy("parlamentares:parlamentar_listview")
def get_casa(self):
casa_id = self.request.session.get("casa_id", None)
if casa_id:
casa = Orgao.objects.filter(id=casa_id).first()
else:
casa = Orgao.objects.filter(
funcionario__email=self.request.user.email
).first()
return casa
def get_object(self, queryset=None):
casa = self.get_casa()
return super().get_object(casa.parlamentar_set.all())
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context["casa"] = self.get_casa()
return context

1
sigi/apps/servicos/management/commands/importa_servico.py

@ -31,7 +31,6 @@ Importa dados de serviços de arquivos TXT gerados pela COTIN.
or not "NAME" in reader.fieldnames or not "NAME" in reader.fieldnames
or not "COD_ORGAO" in reader.fieldnames or not "COD_ORGAO" in reader.fieldnames
): ):
print(reader.fieldnames)
raise CommandError("Formato inválido do arquivo.") raise CommandError("Formato inválido do arquivo.")
self.stdout.write("Estrutura parece ok.") self.stdout.write("Estrutura parece ok.")
self.stdout.write("Preparando dados...") self.stdout.write("Preparando dados...")

1
sigi/apps/servidores/management/commands/migra.py

@ -106,7 +106,6 @@ class Command(BaseCommand):
nome_completo="%s %s" % (user.first_name, user.last_name), nome_completo="%s %s" % (user.first_name, user.last_name),
) )
except MigrationError as e: except MigrationError as e:
print(", ".join(row))
continue continue
# mapeando dados simples # mapeando dados simples

36
sigi/apps/servidores/migrations/0011_add_servidor_sigi.py

@ -0,0 +1,36 @@
# Generated by Django 4.1 on 2022-08-17 15:18
from django.db import migrations
def forwards_migration(apps, schema_editor):
Servidor = apps.get_model("servidores", "Servidor")
Servico = apps.get_model("servidores", "Servico")
ilb = Servico.objects.filter(subordinado=None).first()
if ilb is None:
return
sigi = {
"apelido": "SIGI",
"cargo": "Usuário do sistema",
"nome_completo": "SIGI - Sistema de Informações do Interlegis",
"servico": ilb,
}
Servidor.objects.update_or_create(defaults=sigi, sigi=True)
def reverse_migration(apps, schema_editor):
Servidor = apps.get_model("servidores", "Servidor")
Servidor.objects.filter(sigi=True).delete()
class Migration(migrations.Migration):
dependencies = [
("servidores", "0010_servidor_sigi"),
]
operations = [
migrations.RunPython(forwards_migration, reverse_migration),
]

9
sigi/apps/utils/mixins.py

@ -99,6 +99,8 @@ class CartExportMixin(ExportMixin):
else: else:
if self.actions is None: if self.actions is None:
self.actions = [] self.actions = []
else:
self.actions = list(self.actions)
self.actions.append("add_to_cart") self.actions.append("add_to_cart")
return super(CartExportMixin, self).get_actions(request) return super(CartExportMixin, self).get_actions(request)
@ -121,9 +123,7 @@ class CartExportMixin(ExportMixin):
if self._cart_viewing_name in request.session: if self._cart_viewing_name in request.session:
extra_context["viewing_cart"] = True extra_context["viewing_cart"] = True
return super(CartExportMixin, self).changelist_view( return super().changelist_view(request, extra_context)
request, extra_context
)
def get_urls(self): def get_urls(self):
urls = super().get_urls() urls = super().get_urls()
@ -233,9 +233,6 @@ class CartExportMixin(ExportMixin):
return response return response
context = self.get_export_context_data() context = self.get_export_context_data()
context.update(self.admin_site.each_context(request))
context["title"] = _("Export") context["title"] = _("Export")
context["form"] = form context["form"] = form
context["opts"] = self.model._meta context["opts"] = self.model._meta

37
sigi/menu_conf.yaml

@ -52,6 +52,9 @@ main_menu:
children: children:
- title: Convênios - title: Convênios
view_name: admin:convenios_convenio_changelist view_name: admin:convenios_convenio_changelist
- title: Solicitações de convênio
view_name: ocorrencias_painel
querystr: tipo_categoria=C&status=1&status=2
- title: Serviços SEIT - title: Serviços SEIT
icon: cloud_done icon: cloud_done
children: children:
@ -60,13 +63,12 @@ main_menu:
- title: Ocorrências - title: Ocorrências
icon: comment icon: comment
children: children:
- title: Painel de ocorrências
view_name: painel-ocorrencias
- title: Registro de ocorrências - title: Registro de ocorrências
view_name: admin:ocorrencias_ocorrencia_changelist view_name: admin:ocorrencia_view_changelist
querystr: minhas=S&status__in=1,2 querystr: minhas=S&status__in=1,2
- title: Solicitações de convênio - title: Painel de ocorrências
view_name: painel-convenio view_name: ocorrencias_painel
querystr: status=1&status=2
- title: Eventos - title: Eventos
icon: school icon: school
children: children:
@ -88,9 +90,12 @@ main_menu:
view_name: admin:eventos_evento_changelist view_name: admin:eventos_evento_changelist
querystr: tipo_evento__categoria__exact=V querystr: tipo_evento__categoria__exact=V
- title: Calendário mensal - title: Calendário mensal
view_name: eventos-calendario view_name: eventos_calendario
- title: Alocação de equipe - title: Alocação de equipe
view_name: eventos-alocacao-equipe view_name: eventos_alocacaoequipe
- title: Solicitações de eventos
view_name: ocorrencias_painel
querystr: tipo_categoria=E&status=1&status=2
- title: Servidores - title: Servidores
icon: account_circle icon: account_circle
children: children:
@ -121,3 +126,21 @@ main_menu:
view_name: admin:eventos_modelodeclaracao_changelist view_name: admin:eventos_modelodeclaracao_changelist
- title: Partidos políticos - title: Partidos políticos
view_name: admin:parlamentares_partido_changelist view_name: admin:parlamentares_partido_changelist
contato_menu:
- title: Casa legislativa
icon: account_balance
children:
- title: Dados cadastrais
view_name: casas:orgao_update
- title: Parlamentares
view_name: parlamentares:parlamentar_listview
- title: Contatos
view_name: casas:funcionario_listview
- title: Informações Interlegis
icon: cloud_done
children:
- title: Solicitar treinamentos
view_name: ocorrencias:solicita_oficina_create
- title: Ver ocorrências
view_name: ocorrencias:ocorrencia_listview

7
sigi/templates/admin/base_block.html

@ -5,3 +5,10 @@
{{ block.super }} {{ block.super }}
<link rel="stylesheet" type="text/css" href="{% static 'css/base_block.css' %}"> <link rel="stylesheet" type="text/css" href="{% static 'css/base_block.css' %}">
{% endblock %} {% endblock %}
{% block usertools %}
<div id="user-tools">
{% block welcome-msg %}{{ block.super }}{% endblock %}
{% block userlinks %}{{ block.super }}{% endblock %}
</div>
{% endblock %}

25
sigi/templates/admin/base_site.html

@ -7,6 +7,25 @@
<link rel="stylesheet" type="text/css" href="{% static 'css/materialize-adjusts.css' %}"> <link rel="stylesheet" type="text/css" href="{% static 'css/materialize-adjusts.css' %}">
{% endblock %} {% endblock %}
{% block branding %}
{% if user.is_staff %}
{% url 'admin:index' as header_url %}
{% else %}
{% url 'home_index' as header_url %}
{% endif %}
<nav class="nav-extended">
<div class="nav-wrapper">
<h1 id="site-name">
<a href="{{ header_url }}">
<strong>
{{ site_header }}
</strong>
</a>
</h1>
</div>
</nav>
{% endblock %}
{% block breadcrumbs %}{% endblock %} {% block breadcrumbs %}{% endblock %}
{% block userlinks %} {% block userlinks %}
@ -21,14 +40,16 @@
{% endif %} {% endif %}
{% endif %} {% endif %}
{% if user.has_usable_password %} {% if user.has_usable_password %}
<a href="{% url 'admin:password_change' %}"> <a href="{% url 'password_change' %}">
{% trans 'Change password' %} {% trans 'Change password' %}
</a> </a>
{% endif %} {% endif %}
<a href="{% url 'admin:logout' %}"> {% if not user.is_anonymous %}
<a href="{% url 'logout' %}">
{% trans 'Log out' %} {% trans 'Log out' %}
<i class="material-icons" aria-hidden="true">exit_to_app</i> <i class="material-icons" aria-hidden="true">exit_to_app</i>
</a> </a>
{% endif %}
{% endblock %} {% endblock %}
{% block footer %} {% block footer %}

4
sigi/templates/material/admin/side_nav.html

@ -19,6 +19,10 @@
{% if user.is_superuser %} {% if user.is_superuser %}
{% show_menu 'admin_menu' %} {% show_menu 'admin_menu' %}
{% endif %} {% endif %}
{% if user.is_staff %}
{% show_menu 'main_menu' %} {% show_menu 'main_menu' %}
{% else %}
{% show_menu 'contato_menu' %}
{% endif %}
</ul> </ul>
</div> </div>

18
sigi/templates/pdf/base.html

@ -39,6 +39,24 @@
div.new-page { div.new-page {
break-before: always; break-before: always;
} }
.left-align {
text-align: left;
}
.right-align {
text-align: right;
}
.center-align {
text-align: center;
}
.justify-align {
text-align: justify;
}
.left {
float: left !important;
}
.right {
float: right !important;
}
{% block extra_style %}{% endblock extra_style %} {% block extra_style %}{% endblock extra_style %}
</style> </style>
{% block extra_head %}{% endblock extra_head %} {% block extra_head %}{% endblock extra_head %}

69
sigi/templates/public/base_site.html

@ -0,0 +1,69 @@
{% extends 'admin/base_block.html' %}
{% load i18n %}
{% block extrahead %}
{{ block.super }}
<style>
.input-field > label {
position: relative !important;
}
.tabs .tab a.active, .tabs .tab a:hover {
background-color: var(--selected-bg);
}
</style>
{% if form %}{{ form.media }}{% endif %}
{% endblock extrahead %}
{% block content %}
{% if casa %}
<div class="row">
<div class="col s12">
<div class="card horizontal">
{% if casa %}
{% if casa.foto %}
<div class="card-image">
<img src="{{ casa.foto.url }}" />
</div>
{% endif %}
<div class="card-stacked">
<div class="card-content">
<span class="card-title">{{ casa.nome }}</span>
<p>{{ casa.logradouro }}, {{ casa.bairro }}</p>
<p>{{ casa.cep }} - {{ casa.municipio }}</p>
<p>{{ casa.telefone_geral }} - {{ casa.email }} - {{ casa.pagina_web }}</p>
</div>
{% if casas %}
<div class="card-action">
<span>Alternar para:</span>
{% for c in casas %}
{% if c.id != casa.id %}
<a href="?id={{ c.id|safe }}">{{ c }}</a>
{% endif %}
{% endfor %}
</div>
{% endif %}
</div>
{% else %}
<div class="card-stacked">
<div class="card-content">
<span class="card-title">{% trans 'Você não é contato de nenhuma Casa Legislativa' %}</span>
</div>
</div>
{% endif %}
</div>
</div>
</div>
{% endif %}
{% endblock %}
{% block side_nav %}
{% if user.is_anonymous %}
<style>
#container.indent {
padding-left: 0 !important;
}
</style>
{% else %}
{{ block.super }}
{% endif %}
{% endblock %}

83
sigi/templates/registration/login.html

@ -0,0 +1,83 @@
{% extends 'material/admin/login.html' %}
{% load i18n %}
{% block content %}
<div id="layout-content">
<div class="text-content">
{% if form.errors and not form.non_field_errors %}
<p class="errornote">
{% if form.errors.items|length == 1 %}
{% trans "Please correct the error below." %}
{% else %}
{% trans "Please correct the errors below." %}
{% endif %}
</p>
{% endif %}
{% if form.non_field_errors %}
{% for error in form.non_field_errors %}
<p class="errornote">
{{ error }}
</p>
{% endfor %}
{% endif %}
{% if user.is_authenticated %}
<p class="errornote">
{% blocktrans trimmed %}
You are authenticated as {{ username }}, but are not authorized to
access this page. Would you like to login to a different account?
{% endblocktrans %}
</p>
{% endif %}
<form action="{{ app_path }}" method="post" id="login-form">{% csrf_token %}
<div class="row">
<div class="col s12">
<div class="row">
<div class="input-field {% if form.username.errors %}has-error{% endif %} col s12">
<i class="material-icons prefix" aria-hidden="true">person</i>
<input type="text" id="username-input" name="{{ form.username.name }}"
class="{% if form.username.errors %}invalid{% endif %}"
value="{{ form.username.value|default_if_none:'' }}" autofocus>
<label for="username-input">{{ form.username.label }}</label>
<div class="prefix-error">{{ form.username.errors }}</div>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col s12">
<div class="row">
<div class="input-field {% if form.password.errors %}has-error{% endif %} col s12">
<i class="material-icons prefix" aria-hidden="true">lock</i>
<input type="password" id="password-input" name="{{ form.password.name }}"
class="{% if form.password.errors %}invalid{% endif %}"
value="{{ form.password.value|default_if_none:'' }}">
<i id="visible-on" aria-hidden="true" class="material-icons prefix password-visible">visibility</i>
<i id="visible-off" aria-hidden="true" class="material-icons prefix password-visible hide">visibility_off</i>
<label for="password-input">{{ form.password.label }}</label>
<div class="prefix-error">{{ form.password.errors }}</div>
</div>
</div>
</div>
</div>
{% url 'password_reset' as password_reset_url %}
{% if password_reset_url %}
<div class="password-reset-link">
<a href="{{ password_reset_url }}">{% trans 'Forgotten your password or username?' %}</a>
</div>
{% endif %}
<div class="submit-row-btn">
<button class="btn waves-effect waves-light" type="submit" name="action">{% trans 'Log in' %}
<i class="material-icons right" aria-hidden="true">send</i>
</button>
</div>
</form>
</div>
<div class="side-bar">
{% include 'material/admin/includes/admin-out-bg.html' with current_theme=current_theme %}
</div>
</div>
{% endblock %}

20
sigi/templates/registration/logout.html

@ -0,0 +1,20 @@
{% extends 'material/admin/logout.html' %}
{% load i18n %}
{% block content %}
<div id="layout-content">
<div class="side-bar">
{% include 'material/admin/includes/admin-out-bg.html' with current_theme=current_theme %}
</div>
<div class="text-content">
<h2>{% trans "Logged out" %}</h2>
<p>{% trans "Thanks for spending some quality time with the Web site today." %}</p>
<p><a href="{% url 'openmap' %}">{% trans 'Voltar ao mapa' %}</a></p>
<p><a class="btn waves-effect white-text waves-light" href="{% url 'login' %}">{% trans 'Log in again' %}
<i class="material-icons right" aria-hidden="true">send</i>
</a></p>
</div>
</div>
{% endblock %}

2
sigi/templates/sigi/snippets/base_card.html

@ -21,7 +21,9 @@
<div class="card-title"> <div class="card-title">
<i class="material-icons left dash-control" style="cursor: move;">drag_handle</i> <i class="material-icons left dash-control" style="cursor: move;">drag_handle</i>
{% block card-title %}{% translate card_title|default:"" %}{% endblock %} {% block card-title %}{% translate card_title|default:"" %}{% endblock %}
{% if dash %}
<a href="{% url 'home_card_remove' dash.label card.codigo %}" class="dash-control remove-card" title="{% trans 'Remove este card' %}"><i class="material-icons right">close</i></a> <a href="{% url 'home_card_remove' dash.label card.codigo %}" class="dash-control remove-card" title="{% trans 'Remove este card' %}"><i class="material-icons right">close</i></a>
{% endif %}
</div> </div>
<div class="card-content-wrapper"> <div class="card-content-wrapper">
{% block card-content %}{% endblock card-content %} {% block card-content %}{% endblock card-content %}

10
sigi/urls.py

@ -19,14 +19,16 @@ from django.conf import settings
from django.conf.urls.static import static from django.conf.urls.static import static
urlpatterns = [ urlpatterns = [
path("admin/casas/", include("sigi.apps.casas.urls")), path("casas/", include("sigi.apps.casas.urls")),
path("admin/convenios/", include("sigi.apps.convenios.urls")),
path("admin/ocorrencias/", include("sigi.apps.ocorrencias.admin_urls")),
path("ocorrencias/", include("sigi.apps.ocorrencias.urls")), path("ocorrencias/", include("sigi.apps.ocorrencias.urls")),
path("eventos/", include("sigi.apps.eventos.urls")),
path("parlamentares/", include("sigi.apps.parlamentares.urls")), path("parlamentares/", include("sigi.apps.parlamentares.urls")),
path("admin/casas/", include("sigi.apps.casas.admin_urls")),
path("admin/eventos/", include("sigi.apps.eventos.admin_urls")),
path("admin/convenios/", include("sigi.apps.convenios.urls")),
path("admin/ocorrencias/", include("sigi.apps.ocorrencias.admin_urls")),
path("admin/", admin.site.urls), path("admin/", admin.site.urls),
path("tinymce/", include("tinymce.urls")), path("tinymce/", include("tinymce.urls")),
path("accounts/", include("sigi.apps.home.accounts_urls")),
path("", include("sigi.apps.home.urls")), path("", include("sigi.apps.home.urls")),
] ]

2
templates/snippets/modules/charts-convenios.html

@ -25,7 +25,7 @@
</div> </div>
<div class="row row-flex row-flex-wrap"> <div class="row row-flex row-flex-wrap">
<div id="resumo" class="col-md-6" data-source="{% url "casas-carteira" %}?snippet=resumo&s=sim"></div> <div id="resumo" class="col-md-6" data-source="{% url "casas_carteira" %}?snippet=resumo&s=sim"></div>
<div class="col-md-6"> <div class="col-md-6">
<div class="panel panel-primary flex-col"> <div class="panel panel-primary flex-col">
<div class="panel-heading">{% trans 'Performance da gerência de carteiras' %}</div> <div class="panel-heading">{% trans 'Performance da gerência de carteiras' %}</div>

Loading…
Cancel
Save