Browse Source

Novo mapa usando leaflet e openstreetmap

pull/66/head
Sesostris Vieira 4 years ago
parent
commit
1f84e0077a
  1. 306
      sigi/apps/metas/templates/metas/openmap.html
  2. 23
      sigi/apps/metas/templates/metas/openmapdetail.html
  3. 5
      sigi/apps/metas/urls.py
  4. 72
      sigi/apps/metas/views.py

306
sigi/apps/metas/templates/metas/openmap.html

@ -0,0 +1,306 @@
{% load admin_static bootstrapped_goodies_tags %}
{% load i18n %}
<!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>
<title>{% trans 'SIGI' %}</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<meta http-equiv="Content-Type" content="text/xhtml; charset=UTF-8" />
<link href="{% static "bootstrap/css/bootstrap.min.css" %}" rel="stylesheet"/>
<link href="{% static "bootstrap/css/bootstrap-theme.min.css" %}" rel="stylesheet"/>
<script type="text/javascript">
//<![CDATA[
window.__admin_media_prefix__ = "{% filter escapejs %}{% static "admin/" %}{% endfilter %}";
//]]>
</script>
<script src="{% static "admin/js/jquery-1.9.1.min.js" %}"></script>
<script src="{% static "admin/js/jquery-migrate-1.2.1.min.js" %}"></script>
<script src="{% static "bootstrap/js/bootstrap.min.js" %}"></script>
<meta name="robots" content="NONE,NOARCHIVE" />
<script type="text/javascript">
//<![CDATA[
(function($) {
$(document).ready(function() {
$('input[type="submit"]').addClass('btn');
$('[title]').tooltip();
});
}(jQuery));
//]]>
</script>
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.7.1/dist/leaflet.css" integrity="sha512-xodZBNTC5n17Xt2atTPuE1HxjVMSvLVW9ocqUKLsCC5CXdbqCmblAshOMAS6/keqq/sMZMZ19scR4PsZChSR7A==" crossorigin=""/>
<script src="https://unpkg.com/leaflet@1.7.1/dist/leaflet.js" integrity="sha512-XQoYMqMTK8LvdxXYG3nZ448hOEQiglfqkJs1NOQV44cWnUrBc8PkAOcXy20w0vlaXaVUearIOBhiXZ5V3ynxwA==" crossorigin=""></script>
<link rel="stylesheet" type="text/css" href="{% static "admin/css/changelists.css" %}" />
<script type="text/javascript" src="{% static "admin/js/core.js" %}"></script>
<script type="text/javascript" src="{% static "admin/js/jquery.min.js" %}"></script>
<script type="text/javascript" src="{% static "admin/js/jquery.init.js" %}"></script>
<style>
.totalizador {
float:right;
}
#filter_form {
padding: 10px;
}
body, html, .mapbox, #map {
height: 100%;
}
.filterwrap {
background-color: rgba(255,255,255,0.5);
position: absolute;
top: 0;
left: 0;
z-index: 314159;
max-height: 100%;
overflow-y: auto;
}
.region-ufs {
margin-left: 15px;
}
</style>
</head>
<body>
<div class="mapbox">
<div class="container-fluid filterwrap panel panel-body">
<a href="#" id="options-toggler" type="button" data-toggle="collapse" data-target="#filterbox" aria-expanded="false" aria-controls="collapseExample">
Opções <span class="glyphicon glyphicon-chevron-right"></span>
</a>
<div class="collapse" id="filterbox">
<input type="text" class="form-control" placeholder="Procurar" aria-label="Procurar" aria-describedby="basic-addon2">
<div class="accordion" id="accordionExample">
<form id="filterForm" action="" method="get" >
<h4>Filtros</h4>
<small><strong>Total de Órgãos selecionados: </strong><span id="totalOrgao" class="badge">-</span></small>
<div class="card">
<div class="card-header" id="orgao-filter">
<a href="#" class="collapsed" type="button" data-toggle="collapse" data-target="#collapse-orgao-filter" aria-expanded="true" aria-controls="collapse-orgao-filter">
Por Tipo de órgão
</a>
</div>
<div id="collapse-orgao-filter" class="collapse" aria-labelledby="orgao-filter" data-parent="#accordionExample">
<div class="card-body">
{% for o in tipos_orgao %}
<div class="form-check">
<input type="checkbox" id="tipo_orgao_{{ o.sigla }}" name="tipo_orgao" value="{{ o.sigla }}" checked/>
<label for="tipo_orgao_{{ o.sigla }}" class="form-check-label">{{ o.nome }}</label>
</div>
{% endfor %}
</div>
</div>
</div>
<div class="card">
<div class="card-header" id="servico-filter">
<a href="#" class="collapsed" type="button" data-toggle="collapse" data-target="#collapse-servico-filter" aria-expanded="false" aria-controls="collapse-servico-filter">
Por Tipo de serviço
</a>
</div>
<div id="collapse-servico-filter" class="collapse" aria-labelledby="servico-filter" data-parent="#accordionExample">
<div class="card-body">
<div class="form-check">
<input type="checkbox" id="tipo_servico_none" name="tipo_servico" value="none"/>
<label for="tipo_servico_none" class="form-check-label">Nenhum serviço</label>
</div>
{% for s in tipos_servico %}
<div class="form-check">
<input type="checkbox" id="tipo_servico_{{ s.sigla }}" name="tipo_servico" value="{{ s.sigla }}" checked/>
<label for="tipo_servico_{{ s.sigla }}" class="form-check-label">{{ s.nome }}</label>
</div>
{% endfor %}
</div>
</div>
</div>
<div class="card">
<div class="card-header" id="convenio-filter">
<a href="#" class="collapsed" type="button" data-toggle="collapse" data-target="#collapse-convenio-filter" aria-expanded="false" aria-controls="collapse-convenio-filter">
Por convênio
</a>
</div>
<div id="collapse-convenio-filter" class="collapse" aria-labelledby="convenio-filter" data-parent="#accordionExample">
<div class="card-body">
<div class="form-check">
<input type="checkbox" id="tipo_convenio_none" name="tipo_convenio" value="none"/>
<label for="tipo_convenio_none" class="form-check-label">Sem convênio</label>
</div>
{% for c in tipos_convenio %}
<div class="form-check">
<input type="checkbox" id="tipo_convenio_{{ c.sigla }}" name="tipo_convenio" value="{{ c.sigla }}" checked/>
<label for="tipo_convenio_{{ c.sigla }}" class="form-check-label">{{ c.nome }}</label>
</div>
{% endfor %}
</div>
</div>
</div>
<div class="card">
<div class="card-header" id="regiao-filter">
<a href="#" class="collapsed" type="button" data-toggle="collapse" data-target="#collapse-regiao-filter" aria-expanded="false" aria-controls="collapse-regiao-filter">
Por região/estado
</a>
</div>
<div id="collapse-regiao-filter" class="collapse" aria-labelledby="regiao-filter" data-parent="#accordionExample">
<div class="card-body">
{% for s, n, ufs in regioes %}
<div class="form-check">
<input type="checkbox" id="regiao_{{ s }}" name="regiao" value="{{ s }}"/>
<label for="regiao_{{ s }}" class="form-check-label">{{ n }}</label>
</div>
<div class="region-ufs">
{% for uf in ufs %}
<div class="form-check">
<input type="checkbox" id="uf_{{ uf.sigla }}" name="uf" value="{{ uf.sigla }}" data-regiao="{{ s }}" />
<label for="uf_{{ uf.sigla }}" class="form-check-label">{{ uf.nome }}</label>
</div>
{% endfor %}
</div>
{% endfor %}
</div>
</div>
</div>
<div class="card">
<div class="card-header" id="gerente-filter">
<a href="#" class="collapsed" type="button" data-toggle="collapse" data-target="#collapse-gerente-filter" aria-expanded="false" aria-controls="collapse-gerente-filter">
Por gerente Interlegis
</a>
</div>
<div id="collapse-gerente-filter" class="collapse" aria-labelledby="gerente-filter" data-parent="#accordionExample">
<div class="card-body">
<div class="form-check">
<input type="checkbox" id="gerente_none" name="gerente" value="none"/>
<label for="gerente_none" class="form-check-label">Sem gerente</label>
</div>
{% for g in gerentes %}
<div class="form-check">
<input type="checkbox" id="gerente_{{ g.id }}" name="gerente" value="{{ g.id }}" checked/>
<label for="gerente_{{ g.id }}" class="form-check-label">{{ g.nome_completo }}</label>
</div>
{% endfor %}
</div>
</div>
</div>
{% comment %} <hr/>
<div class="card">
<div class="card-body">
<button class="btn btn-default" type="submit" name="reptype" value="resumo"><span class="glyphicon glyphicon-print"></span> Resumo</a>
<button class="btn btn-default" type="submit" name="reptype" value="lista"><span class="glyphicon glyphicon-print"></span> Listagem</a>
<button class="btn btn-default" type="submit" name="reptype" value="exporta"><span class="glyphicon glyphicon-export"></span>Exportar</a>
</div>
</div> {% endcomment %}
</form>
</div>
</div>
</div>
<div id="map">
<!-- open street map -->
</div>
</div>
<script>
$(document).ready(function(){
$("#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);
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");
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);
})
})
filtra();
function filtra() {
var name = $(this).attr("name"),
value = $(this).attr("value"),
checked = $(this).prop("checked");
console.log(name, value, 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') {
$("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);
} else {
$(regiao).prop("indeterminate", true)
}
}
var formData = $("#filterForm").serializeArray();
var options = {color: 'blue', fillColor: 'red', fillOpacity: 0.4, radius: 500};
mymap.eachLayer(function(layer) {
if (layer instanceof L.Circle) {
mymap.removeLayer(layer);
}
})
$.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>

23
sigi/apps/metas/templates/metas/openmapdetail.html

@ -0,0 +1,23 @@
<div class="card">
<div class="card-header">
<strong>{{ orgao.nome }}</strong> <a href="{% url "admin:casas_orgao_change" orgao.id %}" title="Editar" target="_blank"><span class="glyphicon glyphicon-edit"></span></a>
</div>
<div class="card-body">
<table class="table-condensed">
<tr><th>CNPJ</th><td>{{ orgao.cnpj }}</td></tr>
{% if orgao.data_instalacao %}<tr><th>Data de instalação</th><td>{{ orgao.data_instalacao }}</td></tr>{% endif %}
<tr><th>Endereço</th><td><address>{{ orgao.logradouro }}, {{ orgao.bairro }}, {{ orgao.municipio.nome }}, {{ orgao.municipio.uf.sigla }}, CEP: {{ orgao.cep }}</address></td></tr>
{% if orgao.telefones.all %}<tr><th>Telefones</th><td>{% for telefone in orgao.telefones.all %}<a href="tel:{{ telefone.numero }}">{{ telefone.numero }}</a>{% if not forloop.last %}, {% endif %}{% endfor %}</td></tr>{% endif %}
{% if orgao.email %}<tr><th>E-mail</th><td><a href="mailto:{{ orgao.email }}">{{ orgao.email }}</a></td></tr>{% endif %}
{% if orgao.convenio_set.all %}
<tr><th>Convênios</th><td>{% for c in orgao.convenio_set.all %}<a href="{% url 'admin:convenios_convenio_change' c.id %}" target="_blank">{{ c }}</a>{% if not forloop.last %}, {% endif %}{% endfor %}</td></tr>
{% endif %}
{% if orgao.servico_set.all %}
<tr><th>Serviços</th><td>{% for s in orgao.servico_set.all %}{% if s.url %}<a href="{{ s.url }}" target="_blank">{{ s }}</a>{% else %}{{ s }}{% endif %}{% if not forloop.last %}, {% endif %}{% endfor %}</td></tr>
{% endif %}
{% if orgao.gerentes_interlegis.all %}
<tr><th>Gerentes</th><td>{% for g in orgao.gerentes_interlegis.all %}{{ g.nome_completo }}{% if not forloop.last %}, {% endif %} {% endfor %}</td></tr>
{% endif %}
</table>
</div>
</div>

5
sigi/apps/metas/urls.py

@ -1,11 +1,14 @@
# coding: utf-8 # coding: utf-8
from django.conf.urls import patterns, url from django.conf.urls import patterns, url
from django.views.generic import TemplateView
urlpatterns = patterns( urlpatterns = patterns(
'sigi.apps.metas.views', 'sigi.apps.metas.views',
url(r'^$', 'dashboard', name='metas-dashboardsss'), # tagerror url(r'^$', 'dashboard', name='metas-dashboardsss'), # tagerror
url(r'^openmap/$', 'openmap', name='openmap'),
url(r'^openmapdata/$', 'openmapdata', name='openmapdata'),
url(r'^openmapdetail/(?P<orgao_id>\w+)/$', 'openmapdetail', name='openmapdetail'),
url(r'^mapa/$', 'mapa', name='metas-mapa'), # tagerror url(r'^mapa/$', 'mapa', name='metas-mapa'), # tagerror
url(r'^mapdata/$', 'map_data', name='metas-map_data'), url(r'^mapdata/$', 'map_data', name='metas-map_data'),
url(r'^mapsearch/$', 'map_search', name='metas-map_search'), url(r'^mapsearch/$', 'map_search', name='metas-map_search'),

72
sigi/apps/metas/views.py

@ -6,20 +6,21 @@ import time
from functools import reduce from functools import reduce
from django.contrib.auth.decorators import login_required from django.contrib.auth.decorators import login_required
from django.core import serializers
from django.core.exceptions import PermissionDenied from django.core.exceptions import PermissionDenied
from django.db.models import Q from django.db.models import Q
from django.db.models.aggregates import Sum from django.db.models.aggregates import Sum
from django.http import HttpResponse from django.http import HttpResponse, JsonResponse
from django.shortcuts import render, render_to_response from django.shortcuts import get_object_or_404, render, render_to_response
from django.template import RequestContext from django.template import RequestContext
from django.utils.datastructures import SortedDict from django.utils.datastructures import SortedDict
from django.utils.translation import ugettext as _ from django.utils.translation import ugettext as _
from django.views.decorators.cache import cache_page from django.views.decorators.cache import cache_page
from easy_thumbnails.templatetags.thumbnail import thumbnail_url from easy_thumbnails.templatetags.thumbnail import thumbnail_url
from sigi.apps.casas.models import Orgao from sigi.apps.casas.models import Orgao, TipoOrgao
from sigi.apps.contatos.models import UnidadeFederativa from sigi.apps.contatos.models import UnidadeFederativa
from sigi.apps.convenios.models import Projeto from sigi.apps.convenios.models import Convenio, Projeto
from sigi.apps.financeiro.models import Desembolso from sigi.apps.financeiro.models import Desembolso
from sigi.apps.servicos.models import TipoServico from sigi.apps.servicos.models import TipoServico
from sigi.apps.utils import to_ascii from sigi.apps.utils import to_ascii
@ -62,6 +63,69 @@ def dashboard(request):
extra_context = {'desembolsos': matriz, 'desembolsos_max': desembolsos_max, 'meses': meses, 'colors': ','.join(colors[:len(matriz)])} extra_context = {'desembolsos': matriz, 'desembolsos_max': desembolsos_max, 'meses': meses, 'colors': ','.join(colors[:len(matriz)])}
return render_to_response('metas/dashboard.html', extra_context, context_instance=RequestContext(request)) return render_to_response('metas/dashboard.html', extra_context, context_instance=RequestContext(request))
def openmap(request):
context = {
'tipos_orgao': TipoOrgao.objects.filter(legislativo=True),
'tipos_servico': TipoServico.objects.all(),
'tipos_convenio': Projeto.objects.all(),
'gerentes': Servidor.objects.exclude(casas_que_gerencia=None),
'regioes': [(s, n, UnidadeFederativa.objects.filter(regiao=s))
for s, n in UnidadeFederativa.REGIAO_CHOICES],
}
return render(request, 'metas/openmap.html', context)
def openmapdata(request):
tipos_orgao = request.GET.getlist('tipo_orgao', None)
tipos_servico = request.GET.getlist('tipo_servico', None)
tipos_convenio = request.GET.getlist('tipo_convenio', None)
ufs = request.GET.getlist('uf', None)
gerentes = request.GET.getlist('gerente', None)
reptype = request.GET.get('reptype', None)
print reptype
print request.GET
dados = Orgao.objects.all()
if tipos_orgao:
dados = dados.filter(tipo__sigla__in=tipos_orgao)
else:
dados = dados.filter(tipo__legislativo=True)
if tipos_servico:
if "none" in tipos_servico:
dados = dados.filter(servico=None)
else:
dados = dados.filter(servico__tipo_servico__sigla__in=tipos_servico)
if tipos_convenio:
if "none" in tipos_convenio:
dados = dados.filter(convenio=None)
else:
dados = dados.filter(convenio__projeto__sigla__in=tipos_convenio)
if ufs:
dados = dados.filter(municipio__uf__sigla__in=ufs)
if gerentes:
if "none" in gerentes:
dados = dados.filter(gerentes_interlegis=None)
else:
dados = dados.filter(gerentes_interlegis__id__in=gerentes)
dados = dados.distinct("nome")
if not reptype:
dados = dados.values_list("id", "nome", "municipio__latitude",
"municipio__longitude")
return JsonResponse(list(dados), safe=False)
else:
return JsonResponse({'result': 'todo-feature'})
def openmapdetail(request, orgao_id):
orgao = get_object_or_404(Orgao, id=orgao_id)
return render(request, "metas/openmapdetail.html", {'orgao': orgao})
def mapa(request): def mapa(request):
""" """

Loading…
Cancel
Save