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",
"sexo",
"data_nascimento",
"cpf",
"identidade",
"nota",
"email",
"tempo_de_servico",
@ -113,6 +115,8 @@ class ContatoInterlegisInline(admin.StackedInline):
"nome",
"sexo",
"data_nascimento",
"cpf",
"identidade",
"nota",
"email",
"cargo",
@ -459,6 +463,7 @@ class OrgaoAdmin(CartExportReportMixin, admin.ModelAdmin):
"observacoes",
"horario_funcionamento",
"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 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:
ordering = ("nome",)
@ -354,6 +366,13 @@ class Funcionario(models.Model):
data_nascimento = models.DateField(
_("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(
_("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.utils.translation import gettext as _
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 (
Projeto,
StatusConvenio,
@ -16,7 +19,6 @@ from sigi.apps.utils import queryset_ascii
from sigi.apps.servidores.models import Servidor
from sigi.apps.casas.admin import ConveniosInline, GerentesInterlegisFilter
from sigi.apps.utils.mixins import CartExportReportMixin, LabeledResourse
from django_weasyprint.views import WeasyTemplateResponse
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]
@admin.register(Projeto)
class ProjetoAdmin(admin.ModelAdmin):
list_display = ("sigla", "nome")
formfield_overrides = {HTMLField: {"widget": AdminTinyMCE}}
@admin.register(Convenio)
class ConvenioAdmin(CartExportReportMixin, admin.ModelAdmin):
fieldsets = (
@ -339,6 +347,5 @@ class GesconAdmin(admin.ModelAdmin):
]
admin.site.register(Projeto)
admin.site.register(StatusConvenio)
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.utils.formats import date_format
from django.utils.translation import gettext as _
from tinymce.models import HTMLField
from sigi.apps.utils import to_ascii
from sigi.apps.casas.models import Orgao
from sigi.apps.servidores.models import Servidor, Servico
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)
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):
return self.sigla

35
sigi/apps/eventos/forms.py

@ -1,6 +1,8 @@
from django import forms
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):
@ -46,3 +48,34 @@ class SelecionaModeloForm(forms.Form):
required=True,
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 django.db import models
from django.db.models import Sum
from django.urls import reverse
from django.utils.translation import gettext as _
from sigi.apps.casas.models import Orgao
from sigi.apps.contatos.models import Municipio
@ -110,6 +111,9 @@ class Evento(models.Model):
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):
m = re.match(
"(?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 = [
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(
"evento/<int:id>/declaracao/",
views.declaracao,

201
sigi/apps/eventos/views.py

@ -1,16 +1,26 @@
import calendar
import datetime
import locale
from django.contrib import messages
from django.contrib.admin.sites import site
from django.contrib.auth.decorators import login_required
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.utils.text import slugify
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 weasyprint import HTML
from sigi.apps.eventos.models import Evento, Equipe, Convite, Modulo
from sigi.apps.eventos.forms import SelecionaModeloForm
from sigi.apps.casas.models import Funcionario, Orgao, Presidente
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
@ -46,6 +56,191 @@ def calendario(request):
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
# def calendario(request):
# 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 %}
<i class="material-icons minimize nav-bar" aria-hidden="true" title="{% trans 'Minimize' %}">close</i>
{% endif %}
<form id="filterForm" action="" method="get" >
<form id="filterForm" action="" method="get">
{{ csrftoken }}
</form>
<ul class="collapsible">
@ -12,9 +12,9 @@
<div class="card">
<div class="card-image">
{% if 'profile/user_picture.html'|template_exists %}
{% include 'profile/user_picture.html' %}
{% include 'profile/user_picture.html' %}
{% else %}
{% include 'material/admin/user_picture.html' %}
{% include 'material/admin/user_picture.html' %}
{% endif %}
</div>
</div>
@ -25,151 +25,165 @@
<form id="searchform" class="form-inline ui-front">
<div class="input-field">
<i class="material-icons prefix">search</i>
<input type="text" class="search-text" placeholder="{% trans "Procurar" %}" aria-label="{% trans "Procurar" %}">
<div class="search-result hide"></div>
<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="map_fly_to"></div>
</form>
</div>
</div>
</div>
<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>
<div class="collapsible-body">
{% for o in tipos_orgao %}
<p>
<label>
<input type="checkbox" form="filterForm" id="tipo_orgao_{{ o.sigla }}" name="tipo_orgao" value="{{ o.sigla }}" checked/>
<span>{{ o.nome }}</span>
</label>
</p>
{% endfor %}
</div>
</li>
<li>
<div class="collapsible-header">{% trans "Por Tipo de serviço" %}</div>
<div class="collapsible-body">
<p>
<label>
<input type="checkbox" form="filterForm" id="tipo_servico_ignore" name="ignore_tipo_servico" value="ignore" data-controls="tipo_servico" />
<span>{% trans "Ignorar" %}
</label>
</p>
<p>
<label>
<input type="checkbox" form="filterForm" id="tipo_servico_none" name="tipo_servico" value="none"/>
<span>{% trans "Nenhum serviço" %}</span>
</label>
</p>
{% for s in tipos_servico %}
<p>
<label>
<input type="checkbox" form="filterForm" id="tipo_servico_{{ s.sigla }}" name="tipo_servico" value="{{ s.sigla }}" checked/>
<span>{{ s.nome }}</span>
</label>
</p>
{% endfor %}
</div>
</li>
</div>
<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>
<div class="collapsible-body">
{% for o in tipos_orgao %}
<p>
<label>
<input type="checkbox" form="filterForm" id="tipo_orgao_{{ o.sigla }}" name="tipo_orgao" value="{{ o.sigla }}"
checked />
<span>{{ o.nome }}</span>
</label>
</p>
{% endfor %}
</div>
</li>
<li>
<div class="collapsible-header">{% trans "Por Tipo de serviço" %}</div>
<div class="collapsible-body">
<p>
<label>
<input type="checkbox" form="filterForm" id="tipo_servico_ignore" name="ignore_tipo_servico" value="ignore"
data-controls="tipo_servico" />
<span>{% trans "Ignorar" %}
</label>
</p>
<p>
<label>
<input type="checkbox" form="filterForm" id="tipo_servico_none" name="tipo_servico" value="none" />
<span>{% trans "Nenhum serviço" %}</span>
</label>
</p>
{% for s in tipos_servico %}
<p>
<label>
<input type="checkbox" form="filterForm" id="tipo_servico_{{ s.sigla }}" name="tipo_servico"
value="{{ s.sigla }}" checked />
<span>{{ s.nome }}</span>
</label>
</p>
{% endfor %}
</div>
</li>
<li>
<div class="collapsible-header">{% trans "Por convênio" %}</div>
<div class="collapsible-body">
<p>
<label>
<input type="checkbox" form="filterForm" id="tipo_convenio_ignore" name="ignore_tipo_convenio" value="ignore" data-controls="tipo_convenio" />
<span>{% trans "Ignorar" %}</span>
</label>
</p>
<p>
<label>
<input type="checkbox" form="filterForm" id="tipo_convenio_none" name="tipo_convenio" value="none"/>
<span>{% trans "Sem convênio" %}</span>
</label>
</p>
{% for c in tipos_convenio %}
<p>
<label>
<input type="checkbox" form="filterForm" id="tipo_convenio_{{ c.sigla }}" name="tipo_convenio" value="{{ c.sigla }}" checked/>
<span>{{ c.nome }}</span>
</label>
</p>
{% endfor %}
</div>
</li>
<li>
<div class="collapsible-header">{% trans "Por região/estado" %}</div>
<div class="collapsible-body">
{% for s, n, ufs in regioes %}
<p>
<label>
<input type="checkbox" form="filterForm" id="regiao_{{ s }}" name="regiao" value="{{ s }}"/>
<span>{{ n }}</span>
</label>
</p>
<div class="region-ufs">
{% for uf in ufs %}
<p>
<label>
<input type="checkbox" form="filterForm" id="uf_{{ uf.sigla }}" name="uf" value="{{ uf.sigla }}" data-regiao="{{ s }}" />
<span>{{ uf.nome }}</span>
</label>
</p>
{% endfor %}
</div>
{% endfor %}
</div>
</li>
<li>
<div class="collapsible-header">{% trans "Por convênio" %}</div>
<div class="collapsible-body">
<p>
<label>
<input type="checkbox" form="filterForm" id="tipo_convenio_ignore" name="ignore_tipo_convenio" value="ignore"
data-controls="tipo_convenio" />
<span>{% trans "Ignorar" %}</span>
</label>
</p>
<p>
<label>
<input type="checkbox" form="filterForm" id="tipo_convenio_none" name="tipo_convenio" value="none" />
<span>{% trans "Sem convênio" %}</span>
</label>
</p>
{% for c in tipos_convenio %}
<p>
<label>
<input type="checkbox" form="filterForm" id="tipo_convenio_{{ c.sigla }}" name="tipo_convenio"
value="{{ c.sigla }}" checked />
<span>{{ c.nome }}</span>
</label>
</p>
{% endfor %}
</div>
</li>
<li>
<div class="collapsible-header">{% trans "Por região/estado" %}</div>
<div class="collapsible-body">
{% for s, n, ufs in regioes %}
<p>
<label>
<input type="checkbox" form="filterForm" id="regiao_{{ s }}" name="regiao" value="{{ s }}" />
<span>{{ n }}</span>
</label>
</p>
<div class="region-ufs">
{% for uf in ufs %}
<p>
<label>
<input type="checkbox" form="filterForm" id="uf_{{ uf.sigla }}" name="uf" value="{{ uf.sigla }}"
data-regiao="{{ s }}" />
<span>{{ uf.nome }}</span>
</label>
</p>
{% endfor %}
</div>
{% endfor %}
</div>
</li>
<li>
<div class="collapsible-header">{% trans "Por gerente Interlegis" %}</div>
<div class="collapsible-body">
<p>
<label>
<input type="checkbox" form="filterForm" id="gerente_ignore" name="gerente_ignore" value="ignore" data-controls="gerente" />
<span>{% trans "Ignorar" %}</span>
</label>
</p>
<p>
<label>
<input type="checkbox" form="filterForm" id="gerente_none" name="gerente" value="none"/>
<span>{% trans "Sem gerente" %}</span>
</label>
</p>
{% for g in gerentes %}
<p>
<label>
<input type="checkbox" form="filterForm" id="gerente_{{ g.id|stringformat:"s" }}" name="gerente" value="{{ g.id|stringformat:"s" }}" checked/>
<span>{{ g.nome_completo }}</span>
</label>
</p>
{% endfor %}
</div>
</li>
{% if not user.is_anonymous %}
<li>
<div class="collapsible-header">{% trans "Exportação de dados" %}</div>
<div class="collapsible-body">
<button class="waves-effect waves-light btn-small btn-flat" name="reptype" value="lista" type="submit" form="filterForm">
<i class="material-icons">picture_as_pdf</i>
Listagem
</button>
<button class="waves-effect waves-light btn-small btn-flat" name="reptype" value="exporta" type="submit" form="filterForm">
Exportação completa
</button>
<button class="waves-effect waves-light btn-small btn-flat" name="reptype" value="exporta_servico" type="submit" form="filterForm">
Exportar serviços
</button>
<button class="waves-effect waves-light btn-small btn-flat" name="reptype" value="exporta_convenio" type="submit" form="filterForm">
Exportar convênios
</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 %}
<li>
<div class="collapsible-header">{% trans "Por gerente Interlegis" %}</div>
<div class="collapsible-body">
<p>
<label>
<input type="checkbox" form="filterForm" id="gerente_ignore" name="gerente_ignore" value="ignore"
data-controls="gerente" />
<span>{% trans "Ignorar" %}</span>
</label>
</p>
<p>
<label>
<input type="checkbox" form="filterForm" id="gerente_none" name="gerente" value="none" />
<span>{% trans "Sem gerente" %}</span>
</label>
</p>
{% for g in gerentes %}
<p>
<label>
<input type="checkbox" form="filterForm" id="gerente_{{ g.id|stringformat:"s" }}" name="gerente"
value="{{ g.id|stringformat:"s" }}" checked />
<span>{{ g.nome_completo }}</span>
</label>
</p>
{% endfor %}
</div>
</li>
{% if not user.is_anonymous %}
<li>
<div class="collapsible-header">{% trans "Exportação de dados" %}</div>
<div class="collapsible-body">
<button class="waves-effect waves-light btn-small btn-flat" name="reptype" value="lista" type="submit"
form="filterForm">
<i class="material-icons">picture_as_pdf</i>
Listagem
</button>
<button class="waves-effect waves-light btn-small btn-flat" name="reptype" value="exporta" type="submit"
form="filterForm">
Exportação completa
</button>
<button class="waves-effect waves-light btn-small btn-flat" name="reptype" value="exporta_servico" type="submit"
form="filterForm">
Exportar serviços
</button>
<button class="waves-effect waves-light btn-small btn-flat" name="reptype" value="exporta_convenio" type="submit"
form="filterForm">
Exportar convênios
</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>

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

@ -3,44 +3,49 @@
{% load 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="https://unpkg.com/leaflet@1.7.1/dist/leaflet.css" integrity="sha512-xodZBNTC5n17Xt2atTPuE1HxjVMSvLVW9ocqUKLsCC5CXdbqCmblAshOMAS6/keqq/sMZMZ19scR4PsZChSR7A==" crossorigin=""/>
<link rel="stylesheet" href="{% static 'home/css/openmap.css' %}" />
<link rel="stylesheet" href="{% static "admin/css/changelists.css" %}" type="text/css"/>
{{ block.super }}
<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="{% static 'home/css/openmap.css' %}" />
<link rel="stylesheet" href="{% static "admin/css/changelists.css" %}" type="text/css" />
{% endblock %}
{% block extrahead %}
{{ block.super }}
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<meta http-equiv="Content-Type" content="text/xhtml; charset=UTF-8" />
<meta name="robots" content="NONE,NOARCHIVE" />
<script type="text/javascript">
//<![CDATA[
window.__admin_media_prefix__ = "{% filter escapejs %}{% static "admin/" %}{% endfilter %}";
{{ block.super }}
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="Content-Type" content="text/xhtml; charset=UTF-8" />
<meta name="robots" content="NONE,NOARCHIVE" />
<script type="text/javascript">
//<![CDATA[
window.__admin_media_prefix__ = "{% filter escapejs %}{% static "admin / " %}{% endfilter %}";
//]]>
</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/ui/1.13.1/jquery-ui.min.js" integrity="sha256-eTyxS0rkjpLEo16uXTS0uVCS4815lc40K2iVpWDvdSY=" crossorigin="anonymous"></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>
</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/ui/1.13.1/jquery-ui.min.js" integrity="sha256-eTyxS0rkjpLEo16uXTS0uVCS4815lc40K2iVpWDvdSY=" crossorigin="anonymous"></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 %}
{% block usertools %}
<div id="user-tools">
<a href="{% url 'admin:index' %}">{% trans "Entrar" %}</a>
</div>
<div id="user-tools">
<a href="{% url 'admin:index' %}">{% trans "Entrar" %}</a>
</div>
{% endblock %}
{% block side_nav %}
{% if not nav_bar_minimized %}
<div id="side-bar" class="hide-on-med-and-down">
{% include 'home/mapfilter.html' %}
</div>
{% endif %}
<div id="mobile-demo" class="sidenav">
{% if not nav_bar_minimized %}
<div id="side-bar" class="hide-on-med-and-down">
{% include 'home/mapfilter.html' %}
</div>
{% endif %}
<div id="mobile-demo" class="sidenav">
{% include 'home/mapfilter.html' with mobile=True %}
</div>
</div>
{% endblock %}
{% block content %}
@ -53,61 +58,16 @@
{% block footer %}
{{ block.super }}
<script type="text/javascript" src="{% static 'js/search.js' %}"></script>
<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").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();
}
});
});
});
var mymap;
$(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 };
$("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.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', {
maxZoom: 18,
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',
tileSize: 512,
zoomOffset: -1
}).addTo(mymap);
mymap.on("popupopen", function(e) {
mymap.on("popupopen", function (e) {
var popup = e.popup;
mark = popup._source;
mark = popup._source;
$.ajax({
type: "GET",
url: "{% url "openmapdetail" "orgao_id" %}".replace("orgao_id", mark.orgao_id),
encode: true
}).done(function(content) {
}).done(function (content) {
popup.setContent(content);
})
})
@ -138,8 +98,8 @@
function filtra() {
var name = $(this).attr("name"),
value = $(this).attr("value"),
checked = $(this).prop("checked");
value = $(this).attr("value"),
checked = $(this).prop("checked");
if (name) {
$(`input[type=checkbox][name=${name}][value=${value}]`).prop("checked", checked);
@ -147,27 +107,27 @@
if (value == "ignore") {
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);
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);
$("input[type=checkbox][name='" + name + "'][value='none']").prop("checked", false);
}
}
if (name=='regiao') {
$("input[type=checkbox][name='uf'][data-regiao='"+value+"']").prop('checked', checked);
if (name == 'regiao') {
$("input[type=checkbox][name='uf'][data-regiao='" + value + "']").prop('checked', checked);
}
if (name=='uf') {
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 = $("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) {
} else if ($("input[type=checkbox][name='uf'][data-regiao='" + sigla_regiao + "']:not(:checked)").length == 0) {
$(regiao).prop('checked', true).prop("indeterminate", false);
} else {
$(regiao).prop("indeterminate", true)
@ -176,7 +136,7 @@
var formData = $("#filterForm").serializeArray();
mymap.eachLayer(function(layer) {
mymap.eachLayer(function (layer) {
if (layer instanceof L.Circle) {
mymap.removeLayer(layer);
}
@ -188,11 +148,11 @@
data: formData,
dataType: "json",
encode: true,
}).done(function(returnedData) {
}).done(function (returnedData) {
$("#totalOrgao").text(returnedData.length);
returnedData.forEach(function(casa) {
returnedData.forEach(function (casa) {
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 {
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]
@ -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>
{% endblock %}
{% comment %}
<!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 %}>
<head>
<html xmlns="http://www.w3.org/1999/xhtml" lang="{{ LANGUAGE_CODE|default:"en-us" }}" {% if LANGUAGE_BIDI %}dir="rtl"
{% endif %}>
<head>
<title>{% trans 'SIGI' %}</title>
</head>
<body>
<div class="mapbox">
<div class="sigi-logo">
<div>
<img src="{% static 'img/interlegis_60x60.png' %}" class='img-circle'/>
</head>
<body>
<div class="mapbox">
<div class="sigi-logo">
<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>
<h3>Interlegis</h3>
<a href="{% url 'admin:index' %}">Voltar ao SIGI</a>
<div id="map">
<!-- open street map -->
</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({
minLength: 3,
source: function(request, response) {
$.ajax({
url: "{% url "openmapsearch" %}",
data: {q: request.term },
dataType: "json",
appendTo: "#searchform",
success: function(data) {
console.log(data);
response(data);
},
})
},
select: function( event, ui ) {
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;
</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({
minLength: 3,
source: function (request, response) {
$.ajax({
url: "{% url "openmapsearch" %}",
data: { q: request.term },
dataType: "json",
appendTo: "#searchform",
success: function (data) {
console.log(data);
response(data);
},
})
},
select: function (event, ui) {
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);
mark.orgao_id = ui.item.id
mark.openPopup();
}
}
console.log(ui);
}
});
$("#filterbox").on("shown.bs.collapse", function() {
$("#options-toggler span").removeClass("glyphicon-chevron-right").addClass("glyphicon-chevron-left")
})
$("#filterbox").on("hidden.bs.collapse", function() {
$("#options-toggler span").removeClass("glyphicon-chevron-left").addClass("glyphicon-chevron-right")
})
console.log(ui);
}
});
$("#filterbox").on("shown.bs.collapse", function () {
$("#options-toggler span").removeClass("glyphicon-chevron-right").addClass("glyphicon-chevron-left")
})
$("#filterbox").on("hidden.bs.collapse", function () {
$("#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.zoomOutTitle = "{% trans 'Afastar' %}";
mymap.zoomControl.setPosition("bottomright");
mymap.zoomControl.options.zoomInTitle = "{% trans 'Aproximar' %}";
mymap.zoomControl.options.zoomOutTitle = "{% trans 'Afastar' %}";
mymap.zoomControl.setPosition("bottomright");
L.tileLayer('https://api.mapbox.com/styles/v1/{id}/tiles/{z}/{x}/{y}?access_token=pk.eyJ1IjoibWFwYm94IiwiYSI6ImNpejY4NXVycTA2emYycXBndHRqcmZ3N3gifQ.rJcFIG214AriISLbB6B5aw', {
maxZoom: 18,
attribution: 'Map data &copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors, ' +
L.tileLayer('https://api.mapbox.com/styles/v1/{id}/tiles/{z}/{x}/{y}?access_token=pk.eyJ1IjoibWFwYm94IiwiYSI6ImNpejY4NXVycTA2emYycXBndHRqcmZ3N3gifQ.rJcFIG214AriISLbB6B5aw', {
maxZoom: 18,
attribution: 'Map data &copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors, ' +
'Imagery © <a href="https://www.mapbox.com/">Mapbox</a>',
id: 'mapbox/streets-v11',
tileSize: 512,
zoomOffset: -1
}).addTo(mymap);
mymap.on("popupopen", function(e) {
var popup = e.popup;
mark = popup._source;
$.ajax({
type: "GET",
url: "{% url "openmapdetail" 'orgao_id' %}".replace("orgao_id", mark.orgao_id),
encode: true
}).done(function(content) {
popup.setContent(content);
id: 'mapbox/streets-v11',
tileSize: 512,
zoomOffset: -1
}).addTo(mymap);
mymap.on("popupopen", function (e) {
var popup = e.popup;
mark = popup._source;
$.ajax({
type: "GET",
url: "{% url "openmapdetail" 'orgao_id' %}".replace("orgao_id", mark.orgao_id),
encode: true
}).done(function (content) {
popup.setContent(content);
})
})
})
filtra();
filtra();
function filtra() {
var name = $(this).attr("name"),
function filtra() {
var name = $(this).attr("name"),
value = $(this).attr("value"),
checked = $(this).prop("checked");
if (value == "ignore") {
controls = $(this).attr("data-controls");
$("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 (value == "ignore") {
controls = $(this).attr("data-controls");
$("input[type=checkbox][name='" + controls + "']").prop("disabled", checked);
}
}
if (name='regiao') {
$("input[type=checkbox][name='uf'][data-regiao='"+value+"']").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);
if (value == "none") {
$("input[type=checkbox][name='" + name + "'][value!='none']").prop("checked", !checked);
} 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 (layer instanceof L.Circle) {
mymap.removeLayer(layer);
if (name = 'regiao') {
$("input[type=checkbox][name='uf'][data-regiao='" + value + "']").prop('checked', checked);
}
})
$.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");
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 {
var mark = L.circle([casa[2], casa[3]], options).bindTooltip(casa[1]).bindPopup("").addTo(mymap);
mark.orgao_id = casa[0]
$(regiao).prop("indeterminate", true)
}
}
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 %};
font-family: "Helvetica, Arial, sans-serif";
font-size: 10px;
{% block page-header-settings %}
@top-right { content: url("{% static 'img/logo-interlegis.png' %}");}
@top-left {content: url("{% static 'img/logo-senado.png' %}");}
@top-center { content: element(header); }
{% endblock %}
{% block page-footer-settings %}
@bottom-center { content: element(footer); }
@bottom-right { content: "{% trans "Página: " %}" counter(page); }
{% endblock %}
{% block extra_page_settings %}{% endblock extra_page_settings %}
}
h1 { bookmark-level: 1 }

2
sigi/urls.py

@ -22,7 +22,7 @@ urlpatterns = [
path("admin/casas/", include("sigi.apps.casas.urls")),
path("admin/convenios/", include("sigi.apps.convenios.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("tinymce/", include("tinymce.urls")),
path("", include("sigi.apps.home.urls")),

Loading…
Cancel
Save