Browse Source

Implementa gerador de minutas e ofícios

pull/159/head
Sesostris Vieira 3 years ago
parent
commit
bef6ad85b3
  1. 5
      sigi/apps/casas/admin.py
  2. 28
      sigi/apps/casas/migrations/0022_orgao_brasao_orgao_brasao_altura_and_more.py
  3. 23
      sigi/apps/casas/migrations/0023_funcionario_cpf_funcionario_identidade.py
  4. 19
      sigi/apps/casas/models.py
  5. 11
      sigi/apps/convenios/admin.py
  6. 24
      sigi/apps/convenios/migrations/0021_projeto_texto_minuta_projeto_texto_oficio.py
  7. 15
      sigi/apps/convenios/models.py
  8. 35
      sigi/apps/eventos/forms.py
  9. 4
      sigi/apps/eventos/models.py
  10. 75
      sigi/apps/eventos/templates/eventos/convida_casa.html
  11. 134
      sigi/apps/eventos/templates/eventos/evento.html
  12. 77
      sigi/apps/eventos/templates/eventos/minuta_pdf.html
  13. 79
      sigi/apps/eventos/templates/eventos/oficio_padrao.html
  14. 6
      sigi/apps/eventos/urls.py
  15. 201
      sigi/apps/eventos/views.py
  16. 300
      sigi/apps/home/templates/home/mapfilter.html
  17. 444
      sigi/apps/home/templates/home/openmap.html
  18. 18
      sigi/apps/servidores/templates/admin/widgets/clearable_file_input.html
  19. 15
      sigi/apps/utils/templatetags/model_fields.py
  20. 9
      sigi/apps/utils/templatetags/pdf.py
  21. BIN
      sigi/static/img/brasil-barra.jpg
  22. 39
      sigi/static/js/search.js
  23. 19
      sigi/templates/admin/widgets/clearable_file_input.html
  24. 1
      sigi/templates/django/forms/default.html
  25. 22
      sigi/templates/django/forms/material_form.html
  26. 27
      sigi/templates/django/forms/widgets/clearable_file_input.html
  27. 4
      sigi/templates/pdf/base.html
  28. 2
      sigi/urls.py

5
sigi/apps/casas/admin.py

@ -81,6 +81,8 @@ class PresidenteInline(admin.StackedInline):
"nome", "nome",
"sexo", "sexo",
"data_nascimento", "data_nascimento",
"cpf",
"identidade",
"nota", "nota",
"email", "email",
"tempo_de_servico", "tempo_de_servico",
@ -113,6 +115,8 @@ class ContatoInterlegisInline(admin.StackedInline):
"nome", "nome",
"sexo", "sexo",
"data_nascimento", "data_nascimento",
"cpf",
"identidade",
"nota", "nota",
"email", "email",
"cargo", "cargo",
@ -459,6 +463,7 @@ class OrgaoAdmin(CartExportReportMixin, admin.ModelAdmin):
"observacoes", "observacoes",
"horario_funcionamento", "horario_funcionamento",
"foto", "foto",
"brasao",
), ),
}, },
), ),

28
sigi/apps/casas/migrations/0022_orgao_brasao_orgao_brasao_altura_and_more.py

@ -0,0 +1,28 @@
# Generated by Django 4.0.4 on 2022-04-24 17:31
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('casas', '0021_alter_orgao_options_remove_orgao_recorte_and_more'),
]
operations = [
migrations.AddField(
model_name='orgao',
name='brasao',
field=models.ImageField(blank=True, height_field='brasao_altura', help_text='Trate a imagem para que ela fique com cerca de 120x120 pixels', upload_to='imagens/casas/brasao', verbose_name='brasão', width_field='brasao_largura'),
),
migrations.AddField(
model_name='orgao',
name='brasao_altura',
field=models.SmallIntegerField(editable=False, null=True),
),
migrations.AddField(
model_name='orgao',
name='brasao_largura',
field=models.SmallIntegerField(editable=False, null=True),
),
]

23
sigi/apps/casas/migrations/0023_funcionario_cpf_funcionario_identidade.py

@ -0,0 +1,23 @@
# Generated by Django 4.0.4 on 2022-04-25 21:46
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('casas', '0022_orgao_brasao_orgao_brasao_altura_and_more'),
]
operations = [
migrations.AddField(
model_name='funcionario',
name='cpf',
field=models.CharField(blank=True, max_length=20, verbose_name='CPF'),
),
migrations.AddField(
model_name='funcionario',
name='identidade',
field=models.CharField(blank=True, help_text='Informe o RG e o órgão emissor.', max_length=30, verbose_name='Identidade (RG)'),
),
]

19
sigi/apps/casas/models.py

@ -113,6 +113,18 @@ class Orgao(models.Model):
data_instalacao = models.DateField( data_instalacao = models.DateField(
_("data de instalação da Casa Legislativa"), null=True, blank=True _("data de instalação da Casa Legislativa"), null=True, blank=True
) )
brasao = models.ImageField(
_("brasão"),
upload_to="imagens/casas/brasao",
width_field="brasao_largura",
height_field="brasao_altura",
blank=True,
help_text=_(
"Trate a imagem para que ela fique com cerca de 120x120 pixels"
),
)
brasao_largura = models.SmallIntegerField(editable=False, null=True)
brasao_altura = models.SmallIntegerField(editable=False, null=True)
class Meta: class Meta:
ordering = ("nome",) ordering = ("nome",)
@ -354,6 +366,13 @@ class Funcionario(models.Model):
data_nascimento = models.DateField( data_nascimento = models.DateField(
_("data de nascimento"), blank=True, null=True _("data de nascimento"), blank=True, null=True
) )
cpf = models.CharField(_("CPF"), max_length=20, blank=True)
identidade = models.CharField(
_("Identidade (RG)"),
max_length=30,
blank=True,
help_text=_("Informe o RG e o órgão emissor."),
)
nota = models.CharField( nota = models.CharField(
_("telefones"), max_length=250, null=True, blank=True _("telefones"), max_length=250, null=True, blank=True
) )

11
sigi/apps/convenios/admin.py

@ -2,6 +2,9 @@ from django.contrib import admin
from django.http import HttpResponse, HttpResponseRedirect from django.http import HttpResponse, HttpResponseRedirect
from django.utils.translation import gettext as _ from django.utils.translation import gettext as _
from django.utils.safestring import mark_safe from django.utils.safestring import mark_safe
from django_weasyprint.views import WeasyTemplateResponse
from tinymce.models import HTMLField
from tinymce.widgets import AdminTinyMCE
from sigi.apps.convenios.models import ( from sigi.apps.convenios.models import (
Projeto, Projeto,
StatusConvenio, StatusConvenio,
@ -16,7 +19,6 @@ from sigi.apps.utils import queryset_ascii
from sigi.apps.servidores.models import Servidor from sigi.apps.servidores.models import Servidor
from sigi.apps.casas.admin import ConveniosInline, GerentesInterlegisFilter from sigi.apps.casas.admin import ConveniosInline, GerentesInterlegisFilter
from sigi.apps.utils.mixins import CartExportReportMixin, LabeledResourse from sigi.apps.utils.mixins import CartExportReportMixin, LabeledResourse
from django_weasyprint.views import WeasyTemplateResponse
from sigi.apps.utils.filters import DateRangeFilter from sigi.apps.utils.filters import DateRangeFilter
@ -80,6 +82,12 @@ class AcompanhaFilter(admin.filters.RelatedFieldListFilter):
self.lookup_choices = [(x.id, x) for x in servidores] self.lookup_choices = [(x.id, x) for x in servidores]
@admin.register(Projeto)
class ProjetoAdmin(admin.ModelAdmin):
list_display = ("sigla", "nome")
formfield_overrides = {HTMLField: {"widget": AdminTinyMCE}}
@admin.register(Convenio) @admin.register(Convenio)
class ConvenioAdmin(CartExportReportMixin, admin.ModelAdmin): class ConvenioAdmin(CartExportReportMixin, admin.ModelAdmin):
fieldsets = ( fieldsets = (
@ -339,6 +347,5 @@ class GesconAdmin(admin.ModelAdmin):
] ]
admin.site.register(Projeto)
admin.site.register(StatusConvenio) admin.site.register(StatusConvenio)
admin.site.register(TipoSolicitacao) admin.site.register(TipoSolicitacao)

24
sigi/apps/convenios/migrations/0021_projeto_texto_minuta_projeto_texto_oficio.py

@ -0,0 +1,24 @@
# Generated by Django 4.0.4 on 2022-04-25 19:45
from django.db import migrations
import tinymce.models
class Migration(migrations.Migration):
dependencies = [
('convenios', '0020_gescon_orgaos_gestores'),
]
operations = [
migrations.AddField(
model_name='projeto',
name='texto_minuta',
field=tinymce.models.HTMLField(blank=True, help_text='Use as seguintes marcações:<ul><li>{{ casa.nome }} para o nome da Casa Legislativa / órgão</li><li>{{ casa.municipio.uf.sigla }} para a sigla da UF da Casa legislativa</li><li>{{ presidente.nome }} para o nome do presidente</li><li>{{ contato.nome }} para o nome do contato Interlegis</li></ul>', verbose_name='texto da minuta'),
),
migrations.AddField(
model_name='projeto',
name='texto_oficio',
field=tinymce.models.HTMLField(blank=True, help_text='Use as seguintes marcações:<ul><li>{{ casa.nome }} para o nome da Casa Legislativa / órgão</li><li>{{ casa.municipio.uf.sigla }} para a sigla da UF da Casa legislativa</li><li>{{ presidente.nome }} para o nome do presidente</li><li>{{ contato.nome }} para o nome do contato Interlegis</li></ul>', verbose_name='texto do ofício'),
),
]

15
sigi/apps/convenios/models.py

@ -7,14 +7,29 @@ from django.core.mail import send_mail
from django.urls import reverse from django.urls import reverse
from django.utils.formats import date_format from django.utils.formats import date_format
from django.utils.translation import gettext as _ from django.utils.translation import gettext as _
from tinymce.models import HTMLField
from sigi.apps.utils import to_ascii from sigi.apps.utils import to_ascii
from sigi.apps.casas.models import Orgao from sigi.apps.casas.models import Orgao
from sigi.apps.servidores.models import Servidor, Servico from sigi.apps.servidores.models import Servidor, Servico
class Projeto(models.Model): class Projeto(models.Model):
MARKUP_HELP = _(
"Use as seguintes marcações:<ul><li>{{ casa.nome }} para o"
" nome da Casa Legislativa / órgão</li>"
"<li>{{ casa.municipio.uf.sigla }} para a sigla da UF da "
"Casa legislativa</li><li>{{ presidente.nome }} "
"para o nome do presidente</li><li>{{ contato.nome }} para o nome "
"do contato Interlegis</li></ul>"
)
nome = models.CharField(max_length=50) nome = models.CharField(max_length=50)
sigla = models.CharField(max_length=10) sigla = models.CharField(max_length=10)
texto_oficio = HTMLField(
_("texto do ofício"), blank=True, help_text=MARKUP_HELP
)
texto_minuta = HTMLField(
_("texto da minuta"), blank=True, help_text=MARKUP_HELP
)
def __str__(self): def __str__(self):
return self.sigla return self.sigla

35
sigi/apps/eventos/forms.py

@ -1,6 +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 sigi.apps.eventos.models import ModeloDeclaracao, Evento from material.admin.widgets import MaterialAdminTextareaWidget
from sigi.apps.casas.models import Funcionario, Orgao
from sigi.apps.eventos.models import Convite, ModeloDeclaracao, Evento
class EventoAdminForm(forms.ModelForm): class EventoAdminForm(forms.ModelForm):
@ -46,3 +48,34 @@ class SelecionaModeloForm(forms.Form):
required=True, required=True,
label=_("Modelo de declaração"), label=_("Modelo de declaração"),
) )
class ConviteForm(forms.ModelForm):
class Meta:
model = Convite
fields = ["nomes_participantes"]
widgets = {"nomes_participantes": MaterialAdminTextareaWidget}
class CasaForm(forms.ModelForm):
class Meta:
model = Orgao
fields = ["cnpj", "logradouro", "bairro", "cep", "email", "brasao"]
class FuncionarioForm(forms.ModelForm):
class Meta:
model = Funcionario
fields = [
"nome",
"sexo",
"cpf",
"identidade",
"nota",
"email",
"redes_sociais",
]
widgets = {
"nota": MaterialAdminTextareaWidget,
"redes_sociais": MaterialAdminTextareaWidget,
}

4
sigi/apps/eventos/models.py

@ -2,6 +2,7 @@ import re
from datetime import datetime from datetime import datetime
from django.db import models from django.db import models
from django.db.models import Sum from django.db.models import Sum
from django.urls import reverse
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 Municipio from sigi.apps.contatos.models import Municipio
@ -110,6 +111,9 @@ class Evento(models.Model):
f"de {self.data_inicio} a {self.data_termino}" f"de {self.data_inicio} a {self.data_termino}"
) )
def get_absolute_url(self):
return reverse("eventos-evento", args=[self.id])
def get_sigad_url(self): def get_sigad_url(self):
m = re.match( m = re.match(
"(?P<orgao>00100|00200)\.(?P<sequencial>\d{6})/(?P<ano>" "(?P<orgao>00100|00200)\.(?P<sequencial>\d{6})/(?P<ano>"

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

@ -0,0 +1,75 @@
{% extends "admin/base_site.html" %}
{% load i18n static %}
{% block content %}
{{ block.super }}
<form action="" method="post" name="convite" enctype="multipart/form-data">{% csrf_token %}
<div class="row">
<div class="col s12">
<h5>
{% blocktranslate with casa_nome=casa.nome evento_nome=evento.nome %}
Convidar {{ casa_nome }} para {{ evento_nome }}
{% endblocktranslate %}
</h5>
</div>
</div>
<div class="row">
<div class="col s12">
<div class="card">
<div class="card-content">
<span class="card-title">{% trans "Convite" %}</span>
{{ form_convite }}
</div>
</div>
</div>
</div>
<div class="row">
<div class="col s12">
<div class="card">
<div class="card-content">
<span class="card-title">{% trans "Casa" %}</span>
{{ form_casa }}
</div>
</div>
</div>
</div>
<div class="row">
<div class="col s12">
<div class="card">
<div class="card-content">
<span class="card-title">{% trans "Dados do presidente" %}</span>
{{ form_presidente }}
</div>
</div>
</div>
</div>
<div class="row">
<div class="col s12">
<div class="card">
<div class="card-content">
<span class="card-title">{% trans "Dados do contato Interlegis" %}</span>
{{ form_contato }}
</div>
</div>
</div>
</div>
<div class="row">
<div class="col s12">
<div class="card">
<div class="card-action">
<button class="btn waves-effect waves-light" type="submit" name="save">
{% trans "Save" %}
<i class="material-icons right">send</i>
</button>
{% for proj in projetos %}
<button class="btn waves-effect waves-light" type="submit" name="save" value="{{ proj.id }}">
{% blocktrans with sigla=proj.sigla %}Gerar minuta de {{ sigla}}{% endblocktrans %}
<i class="material-icons right">picture_as_pdf</i>
</button>
{% endfor %}
</div>
</div>
</div>
</div>
</form>
{% endblock %}

134
sigi/apps/eventos/templates/eventos/evento.html

@ -0,0 +1,134 @@
{% extends "admin/base_site.html" %}
{% load i18n static model_fields %}
{% block extrastyle %}
{{ block.super }}
<style>
.search-result-item {
display: list-item;
list-style: none;
padding-left: 15px;
font-weight: bold;
}
</style>
{% endblock %}
{% block content %}
{{ block.super }}
<div class="">
<div class="row">
<div class="col s12">
<h4>{{ evento.nome }}</h4>
</div>
</div>
<div class="row">
<div class="col s12">
<ul class="tabs">
<li class="tab col s4"><a{% if not active %} class="active"{% endif %} href="#base">{% trans "Dados básicos" %}</a></li>
<li class="tab col s4"><a href="#convites">{% trans "Casas convidadas" %}</a></li>
<li class="tab col s4"><a{% if active %} class="active"{% endif %} href="#anexos">{% trans "Anexos" %}</a></li>
</ul>
</div>
<div id="base" class="col s12">
<div class="card">
<div class="card-content">
<table class="responsive-table striped">
{% for field_name in fields %}
<tr>
<th>{{ evento|verbose_name:field_name|title }}</th>
<td>{{ evento|field_value:field_name }}</td>
</tr>
{% endfor %}
</table>
</div>
</div>
</div>
<div id="convites" class="col s12">
<div class="card">
<div class="card-content">
<div class="input-field">
<input id="search-text" class="search-text" type="text" data-source="{% url 'openmapsearch' %}"
data-param="q" />
<label for="search">{% trans "Convidar" %}</label>
</div>
<div id="search-result" class="search-result" data-item-click="convida_casa"></div>
{% if evento.convite_set.count == 0 %}
<span class="card-title">{% trans "Nenhum convite registrado" %}</span>
{% else %}
<table class="responsive-table striped">
<thead>
<tr>
{% for field_name in convite_fields %}
<th>{{ evento.convite_set.first|verbose_name:field_name|title }}</th>
{% endfor %}
</tr>
</thead>
<tbody>
{% for convite in evento.convite_set.all %}
<tr>
{% for field_name in convite_fields %}
<td>{{ convite|field_value:field_name }}</td>
{% endfor %}
</tr>
{% endfor %}
</tbody>
</table>
{% endif %}
</div>
</div>
</div>
<div id="anexos" class="col s12">
<div class="card">
<div class="card-content">
{% if anexos.count == 0 %}
<span class="card-title">{% trans "Nenhum anexo registrado" %}</span>
{% else %}
{% if active %}
<span class="card-title">
{% trans "Mostrando apenas anexos recem-criados" %}
</span>
<a href="{% url 'eventos-evento' evento.id %}#anexos">{% trans "Ver todos" %}</a>
{% endif %}
<table class="responsive-table striped">
<thead>
<tr>
{% with anexos.first as anexo %}
<th>{{ anexo|verbose_name:"descricao"|title }}</th>
<th>{{ anexo|verbose_name:"data_pub"|title }}</th>
<th>{{ anexo|verbose_name:"arquivo"|title }}</th>
{% endwith %}
</tr>
</thead>
<tbody>
{% for anexo in anexos.all %}
<tr>
<td>{{ anexo.descricao }}</td>
<td>{{ anexo.data_pub|date:"SHORT_DATE_FORMAT" }}</td>
<td>
<a href="{{ anexo.arquivo.url }}" target="_blank">
<i class="material-icons">picture_as_pdf</i>
</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endif %}
</div>
</div>
</div>
</div>
</div>
{% endblock %}
{% block footer %}
{{ block.super }}
<script type="text/javascript" src="{% static 'js/search.js' %}"></script>
<script>
function convida_casa(obj) {
window.location.assign("{% url 'eventos-evento-convida' evento.id 'casa_id' %}".replace('casa_id', obj.id));
}
$(document).ready(function () {
M.Tabs.init($('.tabs'), { swipeable: true });
});
</script>
{% endblock %}

77
sigi/apps/eventos/templates/eventos/minuta_pdf.html

@ -0,0 +1,77 @@
{% extends 'pdf/base_report.html' %}
{% load i18n static %}
{% block page_margin %}4cm 2cm{% endblock page_margin %}
{% block page-header-settings %}
@top-center { content: element(header);}
{% endblock %}
{% block page-footer-settings %}
@bottom-center { content: element(footer); }
{% endblock %}
{% block extra_style %}
h1 {font-size: 1.2em;}
h2 {font-size: 1.1em;}
h3,h4,h5,h6 {font-size: 1em;}
header {
font-size: 1em;
text-align: center;
}
header p {
margin: 0 0 5px 0;
}
.strong {
font-weight: bold;
}
.header-title {
font-weight: bold;
font-size: 1.2em;
}
.header-subtitle {
font-weight: bold;
font-size: 1em;
}
.content {
font-size: 1.2em;
line-height: 1.4em;
padding-bottom: 5px;
}
footer {
width: 100%;
text-align: center;
}
.barra {
height: 15px;
}
{% endblock %}
{% block header %}
<img src="{% static 'img/logo-senado.png' %}">
<p class="header-title">SENADO FEDERAL</p>
<p class="header-subtitle">Instituto Legislativo Brasileiro - ILB</p>
<p class="header-subtitle">Programa Interlegis</p>
{% endblock %}
{% block main_content %}
<div class="content">
{% block text_body %}{% endblock %}
</div>
{% endblock %}
{% block footer %}
<img class="barra" src="{% static 'img/brasil-barra.jpg' %}"/>
<p>Instituto Legislativo Brasileiro - ILB - Av. N2 - Bloco 12 - CEP 70165-900 – Brasília DF</p>
<p>Telefone: +55 (61) 3303-2599 – interlegis@senado.leg.br – www.interlegis.leg.br</p>
<p class="strong">MINUTA-PADRÃO aprovada pela Diretoria-Geral do Senado Federal em 01/setembro/2021, conforme processo 00200.006818/2021-12.</p>
{% endblock %}

79
sigi/apps/eventos/templates/eventos/oficio_padrao.html

@ -0,0 +1,79 @@
{% extends 'pdf/base_report.html' %}
{% load i18n %}
{% block page_margin %}4cm 2cm{% endblock page_margin %}
{% block page-header-settings %}
@top-left { content: element(logo);}
@top-center { content: element(header);}
{% endblock %}
{% block page-footer-settings %}
@bottom-center { content: element(footer); }
{% endblock %}
{% block extra_style %}
@media print {
.logo {position: running(logo);}
}
.logo-image {
display: block;
max-width: 120px;
max-height: 120px;
}
header {
font-size: 1em;
text-align: left;
}
header p {
margin: 5px 15px;
}
header h1 {
margin: 0 0 5px 0;
}
.strong {
font-weight: bold;
}
.content {
font-size: 1.2em;
line-height: 1.4em;
padding-bottom: 5px;
}
footer {
width: 100%;
text-align: center;
}
{% endblock %}
{% block body_content %}
<div id="logo" class="logo">
<img src="{{ casa.brasao.url }}" class="logo-image">
</div>
{{ block.super }}
{% endblock %}
{% block header %}
<h1>{{ casa.nome }}</h1>
<p class="strong">CNPJ: {{ casa.cnpj }}</p>
<p>{{ casa.logradouro }}, {{ casa.bairro }}</p>
<p>{{ casa.cep }} - {{ casa.municipio.nome }} - {{ casa.municipio.uf.nome }}</p>
{% endblock %}
{% block main_content %}
<div class="content">
{% block text_body %}{% endblock %}
</div>
{% endblock %}
{% block footer %}
<p class="strong">{{ casa.nome }} - {{ casa.logradouro }} - {{ casa.bairro }}</p>
<p>{{ casa.cep }} - {{ casa.municipio.nome }}, {{ casa.municipio.uf.sigla }}</p>
{% endblock %}

6
sigi/apps/eventos/urls.py

@ -3,6 +3,12 @@ from sigi.apps.eventos import views
urlpatterns = [ urlpatterns = [
path("calendario/", views.calendario, name="eventos-calendario"), path("calendario/", views.calendario, name="eventos-calendario"),
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( path(
"evento/<int:id>/declaracao/", "evento/<int:id>/declaracao/",
views.declaracao, views.declaracao,

201
sigi/apps/eventos/views.py

@ -1,16 +1,26 @@
import calendar import calendar
import datetime import datetime
import locale import locale
from django.contrib import messages
from django.contrib.admin.sites import site from django.contrib.admin.sites import site
from django.contrib.auth.decorators import login_required from django.contrib.auth.decorators import login_required
from django.http import HttpResponse from django.http import HttpResponse
from django.shortcuts import 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
from django.utils.text import slugify
from django.utils.translation import to_locale, get_language, gettext as _ from django.utils.translation import to_locale, get_language, gettext as _
from django.urls import reverse
from django_weasyprint.utils import django_url_fetcher from django_weasyprint.utils import django_url_fetcher
from weasyprint import HTML from weasyprint import HTML
from sigi.apps.eventos.models import Evento, Equipe, Convite, Modulo from sigi.apps.casas.models import Funcionario, Orgao, Presidente
from sigi.apps.eventos.forms import SelecionaModeloForm from sigi.apps.convenios.models import Projeto
from sigi.apps.eventos.models import Evento, Equipe, Convite, Modulo, Anexo
from sigi.apps.eventos.forms import (
SelecionaModeloForm,
ConviteForm,
CasaForm,
FuncionarioForm,
)
from sigi.apps.servidores.models import Servidor from sigi.apps.servidores.models import Servidor
@ -46,6 +56,191 @@ def calendario(request):
return render(request, "eventos/calendario.html", context) return render(request, "eventos/calendario.html", context)
def evento(request, id):
context = site.each_context(request)
evento = get_object_or_404(Evento, id=id)
anexo_id = request.GET.getlist("anexo_id", None)
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(evento)
evento = get_object_or_404(Evento, id=evento_id)
casa = get_object_or_404(Orgao, id=casa_id)
projetos = Projeto.objects.exclude(texto_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=datetime.date.today(),
)
presidente = casa.presidente or Funcionario(
casa_legislativa=casa, setor="presidente"
)
contato = casa.contato_interlegis or Funcionario(
casa_legislativa=casa, setor="contato_interlegis"
)
if request.method == "POST":
form_convite = ConviteForm(request.POST, instance=convite)
form_casa = CasaForm(request.POST, request.FILES, instance=casa)
form_presidente = FuncionarioForm(
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()
presidente = form_presidente.save()
casa = form_casa.save()
convite = form_convite.save()
proj_id = request.POST.get("save", "")
if proj_id:
query_str = ""
projeto = get_object_or_404(Projeto, id=proj_id)
if projeto.texto_oficio:
oficio = gerar_anexo(
casa,
presidente,
contato,
path=request.build_absolute_uri("/"),
nome=f"Ofício de solicitação de {projeto.sigla}",
modelo="oficio_padrao.html",
texto=projeto.texto_oficio,
)
oficio.evento = evento
oficio.save()
query_str += f"anexo_id={oficio.id}&"
if projeto.texto_minuta:
minuta = gerar_anexo(
casa,
presidente,
contato,
path=request.build_absolute_uri("/"),
nome=f"Minuta de {projeto.sigla}",
modelo="minuta_pdf.html",
texto=projeto.texto_minuta,
)
minuta.evento = evento
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(_("Preencha corretamente o convite"))
else:
form_convite = ConviteForm(instance=convite)
form_casa = CasaForm(instance=casa)
form_presidente = FuncionarioForm(
instance=presidente, prefix="presidente"
)
form_contato = FuncionarioForm(instance=contato, prefix="contato")
context = site.each_context(request)
context.update(
{
"form_convite": form_convite,
"form_casa": form_casa,
"form_presidente": form_presidente,
"form_contato": form_contato,
"evento": evento,
"convite": convite,
"casa": casa,
"presidente": presidente,
"contato": contato,
"projetos": projetos,
}
)
return render(request, "eventos/convida_casa.html", context)
def gerar_anexo(casa, presidente, contato, path, modelo, nome, texto):
template_string = (
f'{{% extends "eventos/{modelo}" %}}'
"{% load pdf %}"
f"{{% block text_body %}}{texto}{{% endblock %}}"
)
context = Context(
{
"evento": evento,
"casa": casa,
"presidente": presidente,
"contato": contato,
"data": datetime.date.today(),
"doravante": casa.tipo.nome.split(" ")[0],
}
)
string = Template(template_string).render(context)
pdf = HTML(
string=string,
url_fetcher=django_url_fetcher,
encoding="utf-8",
base_url=path,
)
nome = (nome + f" da {casa.nome}")[:70]
anexo = Anexo(descricao=nome)
anexo.arquivo.name = slugify(nome) + ".pdf"
f = anexo.arquivo.open("wb")
pdf.write_pdf(target=f)
f.flush()
f.close()
return anexo
# @login_required # @login_required
# def calendario(request): # def calendario(request):
# mes_pesquisa = int(request.GET.get('mes', datetime.date.today().month)) # mes_pesquisa = int(request.GET.get('mes', datetime.date.today().month))

300
sigi/apps/home/templates/home/mapfilter.html

@ -4,7 +4,7 @@
{% if not mobile %} {% if not mobile %}
<i class="material-icons minimize nav-bar" aria-hidden="true" title="{% trans 'Minimize' %}">close</i> <i class="material-icons minimize nav-bar" aria-hidden="true" title="{% trans 'Minimize' %}">close</i>
{% endif %} {% endif %}
<form id="filterForm" action="" method="get" > <form id="filterForm" action="" method="get">
{{ csrftoken }} {{ csrftoken }}
</form> </form>
<ul class="collapsible"> <ul class="collapsible">
@ -12,9 +12,9 @@
<div class="card"> <div class="card">
<div class="card-image"> <div class="card-image">
{% if 'profile/user_picture.html'|template_exists %} {% if 'profile/user_picture.html'|template_exists %}
{% include 'profile/user_picture.html' %} {% include 'profile/user_picture.html' %}
{% else %} {% else %}
{% include 'material/admin/user_picture.html' %} {% include 'material/admin/user_picture.html' %}
{% endif %} {% endif %}
</div> </div>
</div> </div>
@ -25,151 +25,165 @@
<form id="searchform" class="form-inline ui-front"> <form id="searchform" class="form-inline ui-front">
<div class="input-field"> <div class="input-field">
<i class="material-icons prefix">search</i> <i class="material-icons prefix">search</i>
<input type="text" class="search-text" placeholder="{% trans "Procurar" %}" aria-label="{% trans "Procurar" %}"> <input type="text" class="search-text" placeholder="{% trans "Procurar" %}"
<div class="search-result hide"></div> aria-label="{% trans "Procurar" %}" data-source="{% url 'openmapsearch' %}" data-param="q">
<div class="search-result hide" data-item-click="map_fly_to"></div>
</form> </form>
</div>
</div> </div>
</div> </div>
<small><strong>Total de Órgãos selecionados: </strong><span id="totalOrgao">-</span></small> </div>
</li> <small><strong>Total de Órgãos selecionados: </strong><span id="totalOrgao">-</span></small>
<li> </li>
<div class="collapsible-header">{% trans "Por Tipo de órgão" %}</div> <li>
<div class="collapsible-body"> <div class="collapsible-header">{% trans "Por Tipo de órgão" %}</div>
{% for o in tipos_orgao %} <div class="collapsible-body">
<p> {% for o in tipos_orgao %}
<label> <p>
<input type="checkbox" form="filterForm" id="tipo_orgao_{{ o.sigla }}" name="tipo_orgao" value="{{ o.sigla }}" checked/> <label>
<span>{{ o.nome }}</span> <input type="checkbox" form="filterForm" id="tipo_orgao_{{ o.sigla }}" name="tipo_orgao" value="{{ o.sigla }}"
</label> checked />
</p> <span>{{ o.nome }}</span>
{% endfor %} </label>
</div> </p>
</li> {% endfor %}
<li> </div>
<div class="collapsible-header">{% trans "Por Tipo de serviço" %}</div> </li>
<div class="collapsible-body"> <li>
<p> <div class="collapsible-header">{% trans "Por Tipo de serviço" %}</div>
<label> <div class="collapsible-body">
<input type="checkbox" form="filterForm" id="tipo_servico_ignore" name="ignore_tipo_servico" value="ignore" data-controls="tipo_servico" /> <p>
<span>{% trans "Ignorar" %} <label>
</label> <input type="checkbox" form="filterForm" id="tipo_servico_ignore" name="ignore_tipo_servico" value="ignore"
</p> data-controls="tipo_servico" />
<p> <span>{% trans "Ignorar" %}
<label> </label>
<input type="checkbox" form="filterForm" id="tipo_servico_none" name="tipo_servico" value="none"/> </p>
<span>{% trans "Nenhum serviço" %}</span> <p>
</label> <label>
</p> <input type="checkbox" form="filterForm" id="tipo_servico_none" name="tipo_servico" value="none" />
{% for s in tipos_servico %} <span>{% trans "Nenhum serviço" %}</span>
<p> </label>
<label> </p>
<input type="checkbox" form="filterForm" id="tipo_servico_{{ s.sigla }}" name="tipo_servico" value="{{ s.sigla }}" checked/> {% for s in tipos_servico %}
<span>{{ s.nome }}</span> <p>
</label> <label>
</p> <input type="checkbox" form="filterForm" id="tipo_servico_{{ s.sigla }}" name="tipo_servico"
{% endfor %} value="{{ s.sigla }}" checked />
</div> <span>{{ s.nome }}</span>
</li> </label>
</p>
{% endfor %}
</div>
</li>
<li> <li>
<div class="collapsible-header">{% trans "Por convênio" %}</div> <div class="collapsible-header">{% trans "Por convênio" %}</div>
<div class="collapsible-body"> <div class="collapsible-body">
<p> <p>
<label> <label>
<input type="checkbox" form="filterForm" id="tipo_convenio_ignore" name="ignore_tipo_convenio" value="ignore" data-controls="tipo_convenio" /> <input type="checkbox" form="filterForm" id="tipo_convenio_ignore" name="ignore_tipo_convenio" value="ignore"
<span>{% trans "Ignorar" %}</span> data-controls="tipo_convenio" />
</label> <span>{% trans "Ignorar" %}</span>
</p> </label>
<p> </p>
<label> <p>
<input type="checkbox" form="filterForm" id="tipo_convenio_none" name="tipo_convenio" value="none"/> <label>
<span>{% trans "Sem convênio" %}</span> <input type="checkbox" form="filterForm" id="tipo_convenio_none" name="tipo_convenio" value="none" />
</label> <span>{% trans "Sem convênio" %}</span>
</p> </label>
{% for c in tipos_convenio %} </p>
<p> {% for c in tipos_convenio %}
<label> <p>
<input type="checkbox" form="filterForm" id="tipo_convenio_{{ c.sigla }}" name="tipo_convenio" value="{{ c.sigla }}" checked/> <label>
<span>{{ c.nome }}</span> <input type="checkbox" form="filterForm" id="tipo_convenio_{{ c.sigla }}" name="tipo_convenio"
</label> value="{{ c.sigla }}" checked />
</p> <span>{{ c.nome }}</span>
{% endfor %} </label>
</div> </p>
</li> {% endfor %}
<li> </div>
<div class="collapsible-header">{% trans "Por região/estado" %}</div> </li>
<div class="collapsible-body"> <li>
{% for s, n, ufs in regioes %} <div class="collapsible-header">{% trans "Por região/estado" %}</div>
<p> <div class="collapsible-body">
<label> {% for s, n, ufs in regioes %}
<input type="checkbox" form="filterForm" id="regiao_{{ s }}" name="regiao" value="{{ s }}"/> <p>
<span>{{ n }}</span> <label>
</label> <input type="checkbox" form="filterForm" id="regiao_{{ s }}" name="regiao" value="{{ s }}" />
</p> <span>{{ n }}</span>
<div class="region-ufs"> </label>
{% for uf in ufs %} </p>
<p> <div class="region-ufs">
<label> {% for uf in ufs %}
<input type="checkbox" form="filterForm" id="uf_{{ uf.sigla }}" name="uf" value="{{ uf.sigla }}" data-regiao="{{ s }}" /> <p>
<span>{{ uf.nome }}</span> <label>
</label> <input type="checkbox" form="filterForm" id="uf_{{ uf.sigla }}" name="uf" value="{{ uf.sigla }}"
</p> data-regiao="{{ s }}" />
{% endfor %} <span>{{ uf.nome }}</span>
</div> </label>
{% endfor %} </p>
</div> {% endfor %}
</li> </div>
{% endfor %}
</div>
</li>
<li> <li>
<div class="collapsible-header">{% trans "Por gerente Interlegis" %}</div> <div class="collapsible-header">{% trans "Por gerente Interlegis" %}</div>
<div class="collapsible-body"> <div class="collapsible-body">
<p> <p>
<label> <label>
<input type="checkbox" form="filterForm" id="gerente_ignore" name="gerente_ignore" value="ignore" data-controls="gerente" /> <input type="checkbox" form="filterForm" id="gerente_ignore" name="gerente_ignore" value="ignore"
<span>{% trans "Ignorar" %}</span> data-controls="gerente" />
</label> <span>{% trans "Ignorar" %}</span>
</p> </label>
<p> </p>
<label> <p>
<input type="checkbox" form="filterForm" id="gerente_none" name="gerente" value="none"/> <label>
<span>{% trans "Sem gerente" %}</span> <input type="checkbox" form="filterForm" id="gerente_none" name="gerente" value="none" />
</label> <span>{% trans "Sem gerente" %}</span>
</p> </label>
{% for g in gerentes %} </p>
<p> {% for g in gerentes %}
<label> <p>
<input type="checkbox" form="filterForm" id="gerente_{{ g.id|stringformat:"s" }}" name="gerente" value="{{ g.id|stringformat:"s" }}" checked/> <label>
<span>{{ g.nome_completo }}</span> <input type="checkbox" form="filterForm" id="gerente_{{ g.id|stringformat:"s" }}" name="gerente"
</label> value="{{ g.id|stringformat:"s" }}" checked />
</p> <span>{{ g.nome_completo }}</span>
{% endfor %} </label>
</div> </p>
</li> {% endfor %}
{% if not user.is_anonymous %} </div>
<li> </li>
<div class="collapsible-header">{% trans "Exportação de dados" %}</div> {% if not user.is_anonymous %}
<div class="collapsible-body"> <li>
<button class="waves-effect waves-light btn-small btn-flat" name="reptype" value="lista" type="submit" form="filterForm"> <div class="collapsible-header">{% trans "Exportação de dados" %}</div>
<i class="material-icons">picture_as_pdf</i> <div class="collapsible-body">
Listagem <button class="waves-effect waves-light btn-small btn-flat" name="reptype" value="lista" type="submit"
</button> form="filterForm">
<button class="waves-effect waves-light btn-small btn-flat" name="reptype" value="exporta" type="submit" form="filterForm"> <i class="material-icons">picture_as_pdf</i>
Exportação completa Listagem
</button> </button>
<button class="waves-effect waves-light btn-small btn-flat" name="reptype" value="exporta_servico" type="submit" form="filterForm"> <button class="waves-effect waves-light btn-small btn-flat" name="reptype" value="exporta" type="submit"
Exportar serviços form="filterForm">
</button> Exportação completa
<button class="waves-effect waves-light btn-small btn-flat" name="reptype" value="exporta_convenio" type="submit" form="filterForm"> </button>
Exportar convênios <button class="waves-effect waves-light btn-small btn-flat" name="reptype" value="exporta_servico" type="submit"
</button> form="filterForm">
<button class="waves-effect waves-light btn-small btn-flat" name="reptype" value="exporta_contato" type="submit" form="filterForm"> Exportar serviços
Exportar contatos </button>
</button> <button class="waves-effect waves-light btn-small btn-flat" name="reptype" value="exporta_convenio" type="submit"
</div> form="filterForm">
</li> Exportar convênios
{% endif %} </button>
<button class="waves-effect waves-light btn-small btn-flat" name="reptype" value="exporta_contato" type="submit"
form="filterForm">
Exportar contatos
</button>
</div>
</li>
{% endif %}
</ul> </ul>
</div> </div>

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

@ -3,44 +3,49 @@
{% load i18n %} {% load i18n %}
{% block extrastyle %} {% block extrastyle %}
{{ block.super }} {{ block.super }}
<link rel="stylesheet" href="https://code.jquery.com/ui/1.12.0/themes/smoothness/jquery-ui.css" /> <link rel="stylesheet" href="https://code.jquery.com/ui/1.12.0/themes/smoothness/jquery-ui.css" />
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.7.1/dist/leaflet.css" integrity="sha512-xodZBNTC5n17Xt2atTPuE1HxjVMSvLVW9ocqUKLsCC5CXdbqCmblAshOMAS6/keqq/sMZMZ19scR4PsZChSR7A==" crossorigin=""/> <link rel="stylesheet" href="https://unpkg.com/leaflet@1.7.1/dist/leaflet.css"
<link rel="stylesheet" href="{% static 'home/css/openmap.css' %}" /> integrity="sha512-xodZBNTC5n17Xt2atTPuE1HxjVMSvLVW9ocqUKLsCC5CXdbqCmblAshOMAS6/keqq/sMZMZ19scR4PsZChSR7A=="
<link rel="stylesheet" href="{% static "admin/css/changelists.css" %}" type="text/css"/> crossorigin="" />
<link rel="stylesheet" href="{% static 'home/css/openmap.css' %}" />
<link rel="stylesheet" href="{% static "admin/css/changelists.css" %}" type="text/css" />
{% endblock %} {% endblock %}
{% block extrahead %} {% block extrahead %}
{{ block.super }} {{ block.super }}
<meta name="viewport" content="width=device-width, initial-scale=1.0"/> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="Content-Type" content="text/xhtml; charset=UTF-8" /> <meta http-equiv="Content-Type" content="text/xhtml; charset=UTF-8" />
<meta name="robots" content="NONE,NOARCHIVE" /> <meta name="robots" content="NONE,NOARCHIVE" />
<script type="text/javascript"> <script type="text/javascript">
//<![CDATA[ //<![CDATA[
window.__admin_media_prefix__ = "{% filter escapejs %}{% static "admin/" %}{% endfilter %}"; window.__admin_media_prefix__ = "{% filter escapejs %}{% static "admin / " %}{% endfilter %}";
//]]> //]]>
</script> </script>
<script src="https://code.jquery.com/jquery-3.6.0.min.js" integrity="sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4=" crossorigin="anonymous"></script> <script src="https://code.jquery.com/jquery-3.6.0.min.js"
<!-- script src="https://code.jquery.com/ui/1.13.1/jquery-ui.min.js" integrity="sha256-eTyxS0rkjpLEo16uXTS0uVCS4815lc40K2iVpWDvdSY=" crossorigin="anonymous"></script --> integrity="sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4=" crossorigin="anonymous"></script>
<script src="https://unpkg.com/leaflet@1.7.1/dist/leaflet.js" integrity="sha512-XQoYMqMTK8LvdxXYG3nZ448hOEQiglfqkJs1NOQV44cWnUrBc8PkAOcXy20w0vlaXaVUearIOBhiXZ5V3ynxwA==" crossorigin=""></script> <!-- script src="https://code.jquery.com/ui/1.13.1/jquery-ui.min.js" integrity="sha256-eTyxS0rkjpLEo16uXTS0uVCS4815lc40K2iVpWDvdSY=" crossorigin="anonymous"></script -->
<script type="text/javascript" src="{% static "admin/js/core.js" %}"></script> <script src="https://unpkg.com/leaflet@1.7.1/dist/leaflet.js"
integrity="sha512-XQoYMqMTK8LvdxXYG3nZ448hOEQiglfqkJs1NOQV44cWnUrBc8PkAOcXy20w0vlaXaVUearIOBhiXZ5V3ynxwA=="
crossorigin=""></script>
<script type="text/javascript" src="{% static "admin/js/core.js" %}"></script>
{% endblock %} {% endblock %}
{% block usertools %} {% block usertools %}
<div id="user-tools"> <div id="user-tools">
<a href="{% url 'admin:index' %}">{% trans "Entrar" %}</a> <a href="{% url 'admin:index' %}">{% trans "Entrar" %}</a>
</div> </div>
{% endblock %} {% endblock %}
{% block side_nav %} {% block side_nav %}
{% if not nav_bar_minimized %} {% if not nav_bar_minimized %}
<div id="side-bar" class="hide-on-med-and-down"> <div id="side-bar" class="hide-on-med-and-down">
{% include 'home/mapfilter.html' %} {% include 'home/mapfilter.html' %}
</div> </div>
{% endif %} {% endif %}
<div id="mobile-demo" class="sidenav"> <div id="mobile-demo" class="sidenav">
{% include 'home/mapfilter.html' with mobile=True %} {% include 'home/mapfilter.html' with mobile=True %}
</div> </div>
{% endblock %} {% endblock %}
{% block content %} {% block content %}
@ -53,61 +58,16 @@
{% block footer %} {% block footer %}
{{ block.super }} {{ block.super }}
<script type="text/javascript" src="{% static 'js/search.js' %}"></script>
<script> <script>
$(document).ready(function(){ var mymap;
var options = {color: 'blue', fillColor: 'red', fillOpacity: 0.4, radius: 500}; $(document).ready(function () {
var unfiltred_options = {color: 'red', fillColor: 'red', fillOpacity: 0, radius: 1000}; var options = { color: 'blue', fillColor: 'red', fillOpacity: 0.4, radius: 500 };
var unfiltred_options = { color: 'red', fillColor: 'red', fillOpacity: 0, radius: 1000 };
$(".search-text").on("input change", function() {
$resultbox = $(".search-result");
var $this = $(this);
var term = $this.val();
if (term.length < 3) {
$resultbox.html("");
$resultbox.addClass("hide");
return;
}
$.get("{% url "openmapsearch" %}", {"q": term}, function(data) {
$resultbox.html("");
for (i in data) {
var plain = JSON.stringify(data[i]);
var $item = $(`<a href="#" class="search-result-item" data-orgao='${plain}'></a>`);
$item.html(data[i].label);
$item.prop("data_item", data[i]);
$resultbox.append($item);
}
$resultbox.removeClass("hide");
$(".search-result-item").on("click", function() {
var plain = $(this).attr("data-orgao");
var result = JSON.parse(plain);
console.log(result);
$this.val(result.label);
$resultbox.html("").addClass("hide");
mymap.flyTo([result.lat, result.lng], 8.5);
var encontrado = false;
mymap.eachLayer(function(layer) {
if (layer instanceof L.Circle) {
if (layer.orgao_id == result.id) {
layer.openPopup();
encontrado = true;
}
}
});
if (!encontrado) {
var mark = L.circle([result.lat, result.lng], unfiltred_options).bindTooltip(result.label).bindPopup("").addTo(mymap);
mark.orgao_id = result.id
mark.openPopup();
}
});
});
});
$("input[type=checkbox]").change(filtra); $("input[type=checkbox]").change(filtra);
var mymap = L.map('map', {zoomSnap: 0.01}).setView([-14.235004, -51.92528], 4.5); mymap = L.map('map', { zoomSnap: 0.01 }).setView([-14.235004, -51.92528], 4.5);
mymap.zoomControl.options.zoomInTitle = "{% trans 'Aproximar' %}"; mymap.zoomControl.options.zoomInTitle = "{% trans 'Aproximar' %}";
mymap.zoomControl.options.zoomOutTitle = "{% trans 'Afastar' %}"; mymap.zoomControl.options.zoomOutTitle = "{% trans 'Afastar' %}";
@ -116,20 +76,20 @@
L.tileLayer('https://api.mapbox.com/styles/v1/{id}/tiles/{z}/{x}/{y}?access_token=pk.eyJ1IjoibWFwYm94IiwiYSI6ImNpejY4NXVycTA2emYycXBndHRqcmZ3N3gifQ.rJcFIG214AriISLbB6B5aw', { L.tileLayer('https://api.mapbox.com/styles/v1/{id}/tiles/{z}/{x}/{y}?access_token=pk.eyJ1IjoibWFwYm94IiwiYSI6ImNpejY4NXVycTA2emYycXBndHRqcmZ3N3gifQ.rJcFIG214AriISLbB6B5aw', {
maxZoom: 18, maxZoom: 18,
attribution: 'Map data &copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors, ' + attribution: 'Map data &copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors, ' +
'Imagery © <a href="https://www.mapbox.com/">Mapbox</a>', 'Imagery © <a href="https://www.mapbox.com/">Mapbox</a>',
id: 'mapbox/streets-v11', id: 'mapbox/streets-v11',
tileSize: 512, tileSize: 512,
zoomOffset: -1 zoomOffset: -1
}).addTo(mymap); }).addTo(mymap);
mymap.on("popupopen", function(e) { mymap.on("popupopen", function (e) {
var popup = e.popup; var popup = e.popup;
mark = popup._source; mark = popup._source;
$.ajax({ $.ajax({
type: "GET", type: "GET",
url: "{% url "openmapdetail" "orgao_id" %}".replace("orgao_id", mark.orgao_id), url: "{% url "openmapdetail" "orgao_id" %}".replace("orgao_id", mark.orgao_id),
encode: true encode: true
}).done(function(content) { }).done(function (content) {
popup.setContent(content); popup.setContent(content);
}) })
}) })
@ -138,8 +98,8 @@
function filtra() { function filtra() {
var name = $(this).attr("name"), var name = $(this).attr("name"),
value = $(this).attr("value"), value = $(this).attr("value"),
checked = $(this).prop("checked"); checked = $(this).prop("checked");
if (name) { if (name) {
$(`input[type=checkbox][name=${name}][value=${value}]`).prop("checked", checked); $(`input[type=checkbox][name=${name}][value=${value}]`).prop("checked", checked);
@ -147,27 +107,27 @@
if (value == "ignore") { if (value == "ignore") {
controls = $(this).attr("data-controls"); controls = $(this).attr("data-controls");
$("input[type=checkbox][name='"+controls+"']").prop("disabled", checked); $("input[type=checkbox][name='" + controls + "']").prop("disabled", checked);
} }
if (value=="none") { if (value == "none") {
$("input[type=checkbox][name='" + name +"'][value!='none']").prop("checked", !checked); $("input[type=checkbox][name='" + name + "'][value!='none']").prop("checked", !checked);
} else { } else {
if (checked) { if (checked) {
$("input[type=checkbox][name='" + name +"'][value='none']").prop("checked", false); $("input[type=checkbox][name='" + name + "'][value='none']").prop("checked", false);
} }
} }
if (name=='regiao') { if (name == 'regiao') {
$("input[type=checkbox][name='uf'][data-regiao='"+value+"']").prop('checked', checked); $("input[type=checkbox][name='uf'][data-regiao='" + value + "']").prop('checked', checked);
} }
if (name=='uf') { if (name == 'uf') {
var sigla_regiao = $(this).attr('data-regiao'), var sigla_regiao = $(this).attr('data-regiao'),
regiao = $("input[type=checkbox][value='"+sigla_regiao+"']"); regiao = $("input[type=checkbox][value='" + sigla_regiao + "']");
if ($("input[type=checkbox][name='uf'][data-regiao='"+sigla_regiao+"']:checked").length == 0) { if ($("input[type=checkbox][name='uf'][data-regiao='" + sigla_regiao + "']:checked").length == 0) {
$(regiao).prop('checked', false).prop("indeterminate", false); $(regiao).prop('checked', false).prop("indeterminate", false);
} else if ($("input[type=checkbox][name='uf'][data-regiao='"+sigla_regiao+"']:not(:checked)").length == 0) { } else if ($("input[type=checkbox][name='uf'][data-regiao='" + sigla_regiao + "']:not(:checked)").length == 0) {
$(regiao).prop('checked', true).prop("indeterminate", false); $(regiao).prop('checked', true).prop("indeterminate", false);
} else { } else {
$(regiao).prop("indeterminate", true) $(regiao).prop("indeterminate", true)
@ -176,7 +136,7 @@
var formData = $("#filterForm").serializeArray(); var formData = $("#filterForm").serializeArray();
mymap.eachLayer(function(layer) { mymap.eachLayer(function (layer) {
if (layer instanceof L.Circle) { if (layer instanceof L.Circle) {
mymap.removeLayer(layer); mymap.removeLayer(layer);
} }
@ -188,11 +148,11 @@
data: formData, data: formData,
dataType: "json", dataType: "json",
encode: true, encode: true,
}).done(function(returnedData) { }).done(function (returnedData) {
$("#totalOrgao").text(returnedData.length); $("#totalOrgao").text(returnedData.length);
returnedData.forEach(function(casa) { returnedData.forEach(function (casa) {
if (casa[2] === null || casa[3] === null) { if (casa[2] === null || casa[3] === null) {
alert(casa[1]+" está sem coordenadas geográficas e não será plotada"); alert(casa[1] + " está sem coordenadas geográficas e não será plotada");
} else { } else {
var mark = L.circle([casa[2], casa[3]], options).bindTooltip(casa[1]).bindPopup('<div class="preloader-wrapper small active"><div class="spinner-layer spinner-green-only"><div class="circle-clipper left"><div class="circle"></div></div><div class="gap-patch"><div class="circle"></div></div><div class="circle-clipper right"><div class="circle"></div></div></div></div>').addTo(mymap); var mark = L.circle([casa[2], casa[3]], options).bindTooltip(casa[1]).bindPopup('<div class="preloader-wrapper small active"><div class="spinner-layer spinner-green-only"><div class="circle-clipper left"><div class="circle"></div></div><div class="gap-patch"><div class="circle"></div></div><div class="circle-clipper right"><div class="circle"></div></div></div></div>').addTo(mymap);
mark.orgao_id = casa[0] mark.orgao_id = casa[0]
@ -200,175 +160,197 @@
}) })
}) })
} }
})
});
function map_fly_to(obj) {
mymap.flyTo([obj.lat, obj.lng], 8.5);
var encontrado = false;
mymap.eachLayer(function (layer) {
if (layer instanceof L.Circle) {
if (layer.orgao_id == obj.id) {
layer.openPopup();
encontrado = true;
}
}
});
if (!encontrado) {
var mark = L.circle([result.lat, result.lng], unfiltred_options).bindTooltip(result.label).bindPopup("").addTo(mymap);
mark.orgao_id = result.id
mark.openPopup();
}
}
</script> </script>
{% endblock %} {% endblock %}
{% comment %} {% comment %}
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="{{ LANGUAGE_CODE|default:"en-us" }}" {% if LANGUAGE_BIDI %}dir="rtl"{% endif %}> <html xmlns="http://www.w3.org/1999/xhtml" lang="{{ LANGUAGE_CODE|default:"en-us" }}" {% if LANGUAGE_BIDI %}dir="rtl"
<head> {% endif %}>
<head>
<title>{% trans 'SIGI' %}</title> <title>{% trans 'SIGI' %}</title>
</head> </head>
<body>
<div class="mapbox"> <body>
<div class="sigi-logo"> <div class="mapbox">
<div> <div class="sigi-logo">
<img src="{% static 'img/interlegis_60x60.png' %}" class='img-circle'/> <div>
<img src="{% static 'img/interlegis_60x60.png' %}" class='img-circle' />
</div>
<div>
<h3>Interlegis</h3>
<a href="{% url 'admin:index' %}">Voltar ao SIGI</a>
</div>
</div> </div>
<div> <div id="map">
<h3>Interlegis</h3> <!-- open street map -->
<a href="{% url 'admin:index' %}">Voltar ao SIGI</a>
</div> </div>
</div>
<div id="map">
<!-- open street map -->
</div>
</div>
<script>
$(document).ready(function(){
var options = {color: 'blue', fillColor: 'red', fillOpacity: 0.4, radius: 500};
var unfiltred_options = {color: 'red', fillColor: 'red', fillOpacity: 0, radius: 1000};
$("#search-text").autocomplete({ </div>
minLength: 3, <script>
source: function(request, response) { $(document).ready(function () {
$.ajax({ var options = { color: 'blue', fillColor: 'red', fillOpacity: 0.4, radius: 500 };
url: "{% url "openmapsearch" %}", var unfiltred_options = { color: 'red', fillColor: 'red', fillOpacity: 0, radius: 1000 };
data: {q: request.term },
dataType: "json", $("#search-text").autocomplete({
appendTo: "#searchform", minLength: 3,
success: function(data) { source: function (request, response) {
console.log(data); $.ajax({
response(data); url: "{% url "openmapsearch" %}",
}, data: { q: request.term },
}) dataType: "json",
}, appendTo: "#searchform",
select: function( event, ui ) { success: function (data) {
mymap.flyTo([ui.item.lat, ui.item.lng], 8.5); console.log(data);
var encontrado = false; response(data);
mymap.eachLayer(function(layer) { },
if (layer instanceof L.Circle) { })
if (layer.orgao_id == ui.item.id) { },
layer.openPopup(); select: function (event, ui) {
encontrado = true; mymap.flyTo([ui.item.lat, ui.item.lng], 8.5);
var encontrado = false;
mymap.eachLayer(function (layer) {
if (layer instanceof L.Circle) {
if (layer.orgao_id == ui.item.id) {
layer.openPopup();
encontrado = true;
}
} }
} })
}) if (!encontrado) {
if (!encontrado) {
var mark = L.circle([ui.item.lat, ui.item.lng], unfiltred_options).bindTooltip(ui.item.label).bindPopup("").addTo(mymap); var mark = L.circle([ui.item.lat, ui.item.lng], unfiltred_options).bindTooltip(ui.item.label).bindPopup("").addTo(mymap);
mark.orgao_id = ui.item.id mark.orgao_id = ui.item.id
mark.openPopup(); mark.openPopup();
} }
console.log(ui); console.log(ui);
} }
}); });
$("#filterbox").on("shown.bs.collapse", function() { $("#filterbox").on("shown.bs.collapse", function () {
$("#options-toggler span").removeClass("glyphicon-chevron-right").addClass("glyphicon-chevron-left") $("#options-toggler span").removeClass("glyphicon-chevron-right").addClass("glyphicon-chevron-left")
}) })
$("#filterbox").on("hidden.bs.collapse", function() { $("#filterbox").on("hidden.bs.collapse", function () {
$("#options-toggler span").removeClass("glyphicon-chevron-left").addClass("glyphicon-chevron-right") $("#options-toggler span").removeClass("glyphicon-chevron-left").addClass("glyphicon-chevron-right")
}) })
$("input[type=checkbox]").change(filtra); $("input[type=checkbox]").change(filtra);
var mymap = L.map('map', {zoomSnap: 0.01}).setView([-14.235004, -51.92528], 4.5); var mymap = L.map('map', { zoomSnap: 0.01 }).setView([-14.235004, -51.92528], 4.5);
mymap.zoomControl.options.zoomInTitle = "{% trans 'Aproximar' %}"; mymap.zoomControl.options.zoomInTitle = "{% trans 'Aproximar' %}";
mymap.zoomControl.options.zoomOutTitle = "{% trans 'Afastar' %}"; mymap.zoomControl.options.zoomOutTitle = "{% trans 'Afastar' %}";
mymap.zoomControl.setPosition("bottomright"); mymap.zoomControl.setPosition("bottomright");
L.tileLayer('https://api.mapbox.com/styles/v1/{id}/tiles/{z}/{x}/{y}?access_token=pk.eyJ1IjoibWFwYm94IiwiYSI6ImNpejY4NXVycTA2emYycXBndHRqcmZ3N3gifQ.rJcFIG214AriISLbB6B5aw', { L.tileLayer('https://api.mapbox.com/styles/v1/{id}/tiles/{z}/{x}/{y}?access_token=pk.eyJ1IjoibWFwYm94IiwiYSI6ImNpejY4NXVycTA2emYycXBndHRqcmZ3N3gifQ.rJcFIG214AriISLbB6B5aw', {
maxZoom: 18, maxZoom: 18,
attribution: 'Map data &copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors, ' + attribution: 'Map data &copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors, ' +
'Imagery © <a href="https://www.mapbox.com/">Mapbox</a>', 'Imagery © <a href="https://www.mapbox.com/">Mapbox</a>',
id: 'mapbox/streets-v11', id: 'mapbox/streets-v11',
tileSize: 512, tileSize: 512,
zoomOffset: -1 zoomOffset: -1
}).addTo(mymap); }).addTo(mymap);
mymap.on("popupopen", function(e) { mymap.on("popupopen", function (e) {
var popup = e.popup; var popup = e.popup;
mark = popup._source; mark = popup._source;
$.ajax({ $.ajax({
type: "GET", type: "GET",
url: "{% url "openmapdetail" 'orgao_id' %}".replace("orgao_id", mark.orgao_id), url: "{% url "openmapdetail" 'orgao_id' %}".replace("orgao_id", mark.orgao_id),
encode: true encode: true
}).done(function(content) { }).done(function (content) {
popup.setContent(content); popup.setContent(content);
})
}) })
})
filtra(); filtra();
function filtra() { function filtra() {
var name = $(this).attr("name"), var name = $(this).attr("name"),
value = $(this).attr("value"), value = $(this).attr("value"),
checked = $(this).prop("checked"); checked = $(this).prop("checked");
if (value == "ignore") { if (value == "ignore") {
controls = $(this).attr("data-controls"); controls = $(this).attr("data-controls");
$("input[type=checkbox][name='"+controls+"']").prop("disabled", checked); $("input[type=checkbox][name='" + controls + "']").prop("disabled", checked);
}
if (value=="none") {
$("input[type=checkbox][name='" + name +"'][value!='none']").prop("checked", !checked);
} else {
if (checked) {
$("input[type=checkbox][name='" + name +"'][value='none']").prop("checked", false);
} }
}
if (name='regiao') { if (value == "none") {
$("input[type=checkbox][name='uf'][data-regiao='"+value+"']").prop('checked', checked); $("input[type=checkbox][name='" + name + "'][value!='none']").prop("checked", !checked);
}
if (name='uf') {
var sigla_regiao = $(this).attr('data-regiao'),
regiao = $("input[type=checkbox][value='"+sigla_regiao+"']");
if ($("input[type=checkbox][name='uf'][data-regiao='"+sigla_regiao+"']:checked").length == 0) {
$(regiao).prop('checked', false).prop("indeterminate", false);
} else if ($("input[type=checkbox][name='uf'][data-regiao='"+sigla_regiao+"']:not(:checked)").length == 0) {
$(regiao).prop('checked', true).prop("indeterminate", false);
} else { } else {
$(regiao).prop("indeterminate", true) if (checked) {
$("input[type=checkbox][name='" + name + "'][value='none']").prop("checked", false);
}
} }
}
var formData = $("#filterForm").serializeArray();
mymap.eachLayer(function(layer) { if (name = 'regiao') {
if (layer instanceof L.Circle) { $("input[type=checkbox][name='uf'][data-regiao='" + value + "']").prop('checked', checked);
mymap.removeLayer(layer);
} }
})
$.ajax({ if (name = 'uf') {
type: "GET", var sigla_regiao = $(this).attr('data-regiao'),
url: "{% url "openmapdata" %}", regiao = $("input[type=checkbox][value='" + sigla_regiao + "']");
data: formData, if ($("input[type=checkbox][name='uf'][data-regiao='" + sigla_regiao + "']:checked").length == 0) {
dataType: "json", $(regiao).prop('checked', false).prop("indeterminate", false);
encode: true, } else if ($("input[type=checkbox][name='uf'][data-regiao='" + sigla_regiao + "']:not(:checked)").length == 0) {
}).done(function(returnedData) { $(regiao).prop('checked', true).prop("indeterminate", false);
$("#totalOrgao").text(returnedData.length);
returnedData.forEach(function(casa) {
if (casa[2] === null || casa[3] === null) {
alert(casa[1]+" está sem coordenadas geográficas e não será plotada");
} else { } else {
var mark = L.circle([casa[2], casa[3]], options).bindTooltip(casa[1]).bindPopup("").addTo(mymap); $(regiao).prop("indeterminate", true)
mark.orgao_id = casa[0] }
}
var formData = $("#filterForm").serializeArray();
mymap.eachLayer(function (layer) {
if (layer instanceof L.Circle) {
mymap.removeLayer(layer);
} }
}) })
})
}
})
</script>
</body>
</html>
{% endcomment %} $.ajax({
type: "GET",
url: "{% url "openmapdata" %}",
data: formData,
dataType: "json",
encode: true,
}).done(function (returnedData) {
$("#totalOrgao").text(returnedData.length);
returnedData.forEach(function (casa) {
if (casa[2] === null || casa[3] === null) {
alert(casa[1] + " está sem coordenadas geográficas e não será plotada");
} else {
var mark = L.circle([casa[2], casa[3]], options).bindTooltip(casa[1]).bindPopup("").addTo(mymap);
mark.orgao_id = casa[0]
}
})
})
}
})
</script>
</body>
</html>
{% endcomment %}

18
sigi/apps/servidores/templates/admin/widgets/clearable_file_input.html

@ -1,18 +0,0 @@
<a href="{{ widget.value.url }}"><img src="{{ widget.value.url }}"/></a>
{% if widget.is_initial %}
<p class="file-upload">
{{ widget.initial_text }}:
<a href="{{ widget.value.url }}">{{ widget.value }}</a>
{% if not widget.required %}
<span class="clearable-file-input">
<input type="checkbox" name="{{ widget.checkbox_name }}" id="{{ widget.checkbox_id }}"{% if widget.attrs.disabled %} disabled{% endif %}>
<label for="{{ widget.checkbox_id }}">{{ widget.clear_checkbox_label }}</label>
</span>
{% endif %}
<br>
{{ widget.input_text }}:
{% endif %}
<input type="{{ widget.type }}" name="{{ widget.name }}"{% include "django/forms/widgets/attrs.html" %}>
{% if widget.is_initial %}
</p>
{% endif %}

15
sigi/apps/utils/templatetags/model_fields.py

@ -0,0 +1,15 @@
from django import template
register = template.Library()
@register.filter
def verbose_name(instance, field_name=""):
if field_name == "":
return ""
return instance._meta.get_field(field_name).verbose_name
@register.filter
def field_value(instance, field_name=""):
return getattr(instance, field_name, "")

9
sigi/apps/utils/templatetags/pdf.py

@ -0,0 +1,9 @@
from django import template
from django.utils.safestring import mark_safe
register = template.Library()
@register.simple_tag
def page_break():
return mark_safe('<div class="new-page"></div>')

BIN
sigi/static/img/brasil-barra.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

39
sigi/static/js/search.js

@ -0,0 +1,39 @@
$(document).ready(function () {
$(".search-text").on("input change", function () {
var $resultbox = $(".search-result");
var $this = $(this);
var term = $this.val();
var url = $this.attr("data-source");
var param_name = $this.attr("data-param");
var item_click = $resultbox.attr("data-item-click");
var callback = window[item_click];
var query_param = {};
query_param[param_name] = term;
if (term.length < 3) {
$resultbox.html("");
$resultbox.addClass("hide");
return;
}
$.get(url, query_param, function (data) {
$resultbox.html("");
for (i in data) {
var plain = JSON.stringify(data[i]);
var $item = $(`<a href="#" class="search-result-item" data-retrieved='${plain}'></a>`);
$item.html(data[i].label);
$resultbox.append($item);
}
$resultbox.removeClass("hide");
$(".search-result-item").on("click", function () {
var plain = $(this).attr("data-retrieved");
var obj = JSON.parse(plain);
$this.val(obj.label);
$resultbox.html("").addClass("hide");
callback(obj);
});
});
});
});

19
sigi/templates/admin/widgets/clearable_file_input.html

@ -0,0 +1,19 @@
<a href="{{ widget.value.url }}"><img src="{{ widget.value.url }}" /></a>
{% if widget.is_initial %}
<p class="file-upload">
{{ widget.initial_text }}:
<a href="{{ widget.value.url }}">{{ widget.value }}</a>
{% if not widget.required %}
<span class="clearable-file-input">
<input type="checkbox" name="{{ widget.checkbox_name }}" id="{{ widget.checkbox_id }}"
{% if widget.attrs.disabled %} disabled{% endif %}>
<label for="{{ widget.checkbox_id }}">{{ widget.clear_checkbox_label }}</label>
</span>
{% endif %}
<br>
{{ widget.input_text }}:
{% endif %}
<input type="{{ widget.type }}" name="{{ widget.name }}" {% include "django/forms/widgets/attrs.html" %}>
{% if widget.is_initial %}
</p>
{% endif %}

1
sigi/templates/django/forms/default.html

@ -0,0 +1 @@
{% include "django/forms/material_form.html" %}

22
sigi/templates/django/forms/material_form.html

@ -0,0 +1,22 @@
{{ errors }}
{% if errors and not fields %}
<p>{% for field in hidden_fields %}{{ field }}{% endfor %}</p>
{% endif %}
{% for field, errors in fields %}
<div{% with classes=field.css_classes %} class="{% if field.widget_type != 'clearablefile' %}input-field {% endif %}{{ classes }}" {% endwith %}>
<small class="error">
{{ errors }}
</small>
{% if field.label %}{{ field.label_tag }}{% endif %}
{{ field }}
{% if field.help_text %}
<small class="helptext">{{ field.help_text|safe }}</small>
{% endif %}
{% if forloop.last %}
{% for field in hidden_fields %}{{ field }}{% endfor %}
{% endif %}
</div>
{% endfor %}
{% if not fields and not errors %}
{% for field in hidden_fields %}{{ field }}{% endfor %}
{% endif %}

27
sigi/templates/django/forms/widgets/clearable_file_input.html

@ -0,0 +1,27 @@
{% load i18n %}
<div class="file-field input-field">
{% if widget.is_initial %}
<div class="left" style="padding: 5px;">
<a href="{{ widget.value.url }}">
<img src="{{ widget.value.url }}" alt="{{ widget.value }}" height="60" width="60"/>
</a>
</div>
{% endif %}
<div class="btn">
<span>{% trans "File" %}</span>
<input type="{{ widget.type }}" name="{{ widget.name }}" {% include "django/forms/widgets/attrs.html" %}>
</div>
<div class="file-path-wrapper">
<input class="file-path validate" type="text" value="{{ widget.value }}">
</div>
</div>
{% if widget.is_initial %}
{% if not widget.required %}
<p>
<label>
<input type="checkbox" name="{{ widget.checkbox_name }}" id="{{ widget.checkbox_id }}" {% if widget.attrs.disabled %}disabled{% endif %}>
<span>{{ widget.clear_checkbox_label }}</span>
</label>
</p>
{% endif %}
{% endif %}

4
sigi/templates/pdf/base.html

@ -11,11 +11,15 @@
margin: {% block page_margin %}3cm 2cm 2cm 2cm{% endblock page_margin %}; margin: {% block page_margin %}3cm 2cm 2cm 2cm{% endblock page_margin %};
font-family: "Helvetica, Arial, sans-serif"; font-family: "Helvetica, Arial, sans-serif";
font-size: 10px; font-size: 10px;
{% block page-header-settings %}
@top-right { content: url("{% static 'img/logo-interlegis.png' %}");} @top-right { content: url("{% static 'img/logo-interlegis.png' %}");}
@top-left {content: url("{% static 'img/logo-senado.png' %}");} @top-left {content: url("{% static 'img/logo-senado.png' %}");}
@top-center { content: element(header); } @top-center { content: element(header); }
{% endblock %}
{% block page-footer-settings %}
@bottom-center { content: element(footer); } @bottom-center { content: element(footer); }
@bottom-right { content: "{% trans "Página: " %}" counter(page); } @bottom-right { content: "{% trans "Página: " %}" counter(page); }
{% endblock %}
{% block extra_page_settings %}{% endblock extra_page_settings %} {% block extra_page_settings %}{% endblock extra_page_settings %}
} }
h1 { bookmark-level: 1 } h1 { bookmark-level: 1 }

2
sigi/urls.py

@ -22,7 +22,7 @@ urlpatterns = [
path("admin/casas/", include("sigi.apps.casas.urls")), path("admin/casas/", include("sigi.apps.casas.urls")),
path("admin/convenios/", include("sigi.apps.convenios.urls")), path("admin/convenios/", include("sigi.apps.convenios.urls")),
path("admin/ocorrencias/", include("sigi.apps.ocorrencias.urls")), path("admin/ocorrencias/", include("sigi.apps.ocorrencias.urls")),
path("admin/eventos/", include("sigi.apps.eventos.urls")), path("eventos/", include("sigi.apps.eventos.urls")),
path("admin/", admin.site.urls), path("admin/", admin.site.urls),
path("tinymce/", include("tinymce.urls")), path("tinymce/", include("tinymce.urls")),
path("", include("sigi.apps.home.urls")), path("", include("sigi.apps.home.urls")),

Loading…
Cancel
Save