Merge pull request #2799 from tchak/refactor-carto

Refactor carto to rely on ujs and some UX fixes
This commit is contained in:
Paul Chavard 2018-10-14 21:02:26 +02:00 committed by GitHub
commit 48de67b6c9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
23 changed files with 318 additions and 516 deletions

View file

@ -6,10 +6,10 @@
#carte-page { #carte-page {
#map { #map {
height: 600px; height: 600px;
z-index: 0;
} }
#map.qp, #map.edit {
#map.cadastre {
width: 70%; width: 70%;
} }
@ -30,13 +30,6 @@
cursor: url("/assets/edit.png"), default !important; cursor: url("/assets/edit.png"), default !important;
} }
#infos-dossiers {
#map.mini {
height: 300px;
width: 100%;
}
}
#map.mode-create { #map.mode-create {
cursor: url("/assets/pencil.png"), crosshair !important; cursor: url("/assets/pencil.png"), crosshair !important;
} }
@ -47,18 +40,18 @@
stroke-opacity: 1; stroke-opacity: 1;
stroke: #D7217E; stroke: #D7217E;
position: absolute; position: absolute;
z-index: 1001; z-index: 100;
fill: #D7217E; fill: #D7217E;
fill-opacity: 0.75; fill-opacity: 0.75;
} }
#map.mode-delete path { #map.mode-delete path.leaflet-polygon {
cursor: no-drop !important; cursor: no-drop !important;
}
#map.mode-delete path:hover { &:hover {
fill: #4D4D4D !important; fill: #4D4D4D !important;
} }
}
#map div.leaflet-edge { #map div.leaflet-edge {
box-shadow: 0 0 0 2px #FFFFFF, 0 0 10px rgba(0, 0, 0, 0.35); box-shadow: 0 0 0 2px #FFFFFF, 0 0 10px rgba(0, 0, 0, 0.35);

View file

@ -129,25 +129,6 @@ module NewGestionnaire
end end
end end
def position
etablissement = dossier.etablissement
if etablissement.present?
point = Carto::Geocodeur.convert_adresse_to_point(etablissement.geo_adresse)
end
lon = "2.428462"
lat = "46.538192"
zoom = "13"
if point.present?
lon = point.x.to_s
lat = point.y.to_s
end
render json: { lon: lon, lat: lat, zoom: zoom, dossier_id: params[:dossier_id] }
end
def create_avis def create_avis
@avis = Avis.new(avis_params.merge(claimant: current_gestionnaire, dossier: dossier)) @avis = Avis.new(avis_params.merge(claimant: current_gestionnaire, dossier: dossier))
if @avis.save if @avis.save

View file

@ -12,51 +12,43 @@ class Users::CarteController < UsersController
end end
def save def save
safe_json_latlngs = clean_json_latlngs(params[:json_latlngs]) geo_json = clean_json_latlngs(params[:selection])
dossier = current_user_dossier dossier = current_user_dossier
dossier.quartier_prioritaires.each(&:destroy) dossier.quartier_prioritaires.each(&:destroy)
dossier.cadastres.each(&:destroy) dossier.cadastres.each(&:destroy)
if safe_json_latlngs.present? if geo_json.present?
ModuleApiCartoService.save_qp! dossier, safe_json_latlngs ModuleApiCartoService.save_qp! dossier, geo_json
ModuleApiCartoService.save_cadastre! dossier, safe_json_latlngs ModuleApiCartoService.save_cadastre! dossier, geo_json
end end
dossier.update(json_latlngs: safe_json_latlngs) dossier.update!(json_latlngs: geo_json)
redirect_to brouillon_dossier_path(dossier) redirect_to brouillon_dossier_path(dossier)
end end
def get_position def zones
begin @dossier = current_user_dossier
etablissement = current_user_dossier.etablissement @data = {}
rescue ActiveRecord::RecordNotFound
etablissement = nil geo_json = JSON.parse(params.required(:selection))
if geo_json.first == ["error", "TooManyPolygons"]
@error = true
else
if @dossier.procedure.module_api_carto.quartiers_prioritaires?
quartiers_prioritaires = ModuleApiCartoService.generate_qp(geo_json).values
@dossier.quartier_prioritaires.build(quartiers_prioritaires)
@data[:quartiersPrioritaires] = quartiers_prioritaires
end end
if etablissement.present? if @dossier.procedure.module_api_carto.cadastre?
point = Carto::Geocodeur.convert_adresse_to_point(etablissement.geo_adresse) cadastres = ModuleApiCartoService.generate_cadastre(geo_json)
@dossier.cadastres.build(cadastres)
@data[:cadastres] = cadastres
end end
lon = '2.428462'
lat = '46.538192'
zoom = '13'
if point.present?
lon = point.x.to_s
lat = point.y.to_s
end end
render json: { lon: lon, lat: lat, zoom: zoom, dossier_id: params[:dossier_id] }
end
def get_qp
render json: { quartier_prioritaires: ModuleApiCartoService.generate_qp(JSON.parse(params[:coordinates])) }
end
def get_cadastre
render json: { cadastres: ModuleApiCartoService.generate_cadastre(JSON.parse(params[:coordinates])) }
end end
def self.route_authorization def self.route_authorization

View file

@ -1,9 +1,5 @@
import L from 'leaflet';
import { getJSON } from '@utils';
import { getData } from '../shared/data'; import { getData } from '../shared/data';
import { DEFAULT_POSITION } from '../shared/carto'; import { initMap } from '../shared/carto';
import { import {
drawCadastre, drawCadastre,
drawQuartiersPrioritaires, drawQuartiersPrioritaires,
@ -12,25 +8,8 @@ import {
function initialize() { function initialize() {
if (document.getElementById('map')) { if (document.getElementById('map')) {
getJSON(getData('carto').getPositionUrl).then( const position = getData('carto').position;
position => initializeWithPosition(position), const map = initMap(position);
() => initializeWithPosition(DEFAULT_POSITION)
);
}
}
addEventListener('turbolinks:load', initialize);
function initializeWithPosition(position) {
const map = L.map('map', {
scrollWheelZoom: false
}).setView([position.lat, position.lon], position.zoom);
L.tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution:
'&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
}).addTo(map);
const data = getData('carto'); const data = getData('carto');
// draw external polygons // draw external polygons
@ -40,3 +19,6 @@ function initializeWithPosition(position) {
// draw user polygon // draw user polygon
drawUserSelection(map, data); drawUserSelection(map, data);
} }
}
addEventListener('turbolinks:load', initialize);

View file

@ -1,45 +1,32 @@
import L from 'leaflet'; import L from 'leaflet';
import {
drawLayer,
noEditStyle,
CADASTRE_POLYGON_STYLE,
QP_POLYGON_STYLE
} from '../../shared/carto';
function drawLayerWithItems(map, items, style) { export function drawCadastre(map, data) {
if (Array.isArray(items) && items.length > 0) { drawLayer(
const layer = new L.GeoJSON();
items.forEach(function(item) {
layer.addData(item.geometry);
});
layer.setStyle(style).addTo(map);
}
}
export function drawCadastre(map, { dossierCadastres }) {
drawLayerWithItems(map, dossierCadastres, {
fillColor: '#8A6D3B',
weight: 2,
opacity: 0.7,
color: '#8A6D3B',
dashArray: '3',
fillOpacity: 0.5
});
}
export function drawQuartiersPrioritaires(
map, map,
{ dossierQuartiersPrioritaires } data.cadastres,
) { noEditStyle(CADASTRE_POLYGON_STYLE),
drawLayerWithItems(map, dossierQuartiersPrioritaires, { 'cadastres'
fillColor: '#31708F', );
weight: 2,
opacity: 0.7,
color: '#31708F',
dashArray: '3',
fillOpacity: 0.5
});
} }
export function drawUserSelection(map, { dossierJsonLatLngs }) { export function drawQuartiersPrioritaires(map, data) {
if (dossierJsonLatLngs.length > 0) { drawLayer(
const polygon = L.polygon(dossierJsonLatLngs, { map,
data.quartiersPrioritaires,
noEditStyle(QP_POLYGON_STYLE),
'quartiersPrioritaires'
);
}
export function drawUserSelection(map, data) {
if (data.selection.length > 0) {
const polygon = L.polygon(data.selection, {
color: 'red', color: 'red',
zIndex: 3 zIndex: 3
}).addTo(map); }).addTo(map);

View file

@ -1,48 +1,20 @@
import L from 'leaflet'; import L from 'leaflet';
import area from '@turf/area';
import FreeDraw, { NONE, EDIT, CREATE, DELETE } from 'leaflet-freedraw'; import FreeDraw, { NONE, CREATE } from 'leaflet-freedraw';
import $ from 'jquery'; import { fire, on, getJSON } from '@utils';
import { getData } from '../shared/data'; import { getData } from '../shared/data';
import { DEFAULT_POSITION, LAT, LON } from '../shared/carto'; import { initMap } from '../shared/carto';
import { qpActive, displayQP, getQP } from './carto/qp';
import { cadastreActive, displayCadastre, getCadastre } from './carto/cadastre'; import polygonArea from './carto/polygon_area';
import drawFactory from './carto/draw';
function initialize() { function initialize() {
if ($('#map').length > 0) { if (document.getElementById('map')) {
getPosition(getData('carto').dossierId).then( const data = getData('carto');
position => initializeWithPosition(position), const position = data.position;
() => initializeWithPosition(DEFAULT_POSITION)
);
}
}
addEventListener('turbolinks:load', initialize);
function initializeWithPosition(position) {
const OSM = L.tileLayer(
'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',
{
attribution:
'&copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>'
}
);
const map = L.map('map', {
center: new L.LatLng(position.lat, position.lon),
zoom: position.zoom,
layers: [OSM],
scrollWheelZoom: false
});
if (qpActive()) {
displayQP(map, getJsonValue('#quartier_prioritaires'));
}
if (cadastreActive()) {
displayCadastre(map, getJsonValue('#cadastres'));
}
const map = initMap(position);
const freeDraw = new FreeDraw({ const freeDraw = new FreeDraw({
mode: NONE, mode: NONE,
smoothFactor: 4, smoothFactor: 4,
@ -51,92 +23,47 @@ function initializeWithPosition(position) {
map.addLayer(freeDraw); map.addLayer(freeDraw);
const latLngs = getJsonValue('#json_latlngs'); addEventFreeDraw(freeDraw);
if (latLngs.length) {
map.setZoom(18);
for (let polygon of latLngs) {
freeDraw.createPolygon(polygon);
}
map.fitBounds(freeDraw.polygons[0].getBounds());
} else if (position.lat == LAT && position.lon == LON) {
map.setView(new L.LatLng(position.lat, position.lon), position.zoom);
}
addEventFreeDraw(map, freeDraw);
addEventSearchAddress(map); addEventSearchAddress(map);
}
function getExternalData(map, latLngs) { const cartoDrawZones = drawFactory(map, freeDraw);
const { dossierId } = getData('carto'); window.DS = { cartoDrawZones };
if (qpActive()) { cartoDrawZones(data);
getQP(dossierId, latLngs).then(qps => displayQP(map, qps));
}
if (cadastreActive()) { if (freeDraw.polygons[0]) {
const polygons = { type: 'FeatureCollection', features: [] }; map.setZoom(18);
map.fitBounds(freeDraw.polygons[0].getBounds());
for (let i = 0; i < latLngs.length; i++) {
polygons.features.push(featurePolygonLatLngs(latLngs[i]));
}
if (area(polygons) < 300000) {
getCadastre(dossierId, latLngs).then(cadastres =>
displayCadastre(map, cadastres)
);
} else {
displayCadastre(map, [{ zoom_error: true }]);
} }
} }
} }
function featurePolygonLatLngs(coordinates) { addEventListener('turbolinks:load', initialize);
return {
type: 'Feature',
properties: {},
geometry: {
type: 'Polygon',
coordinates: [JSON.parse(getJsonPolygons([coordinates]))['latLngs']]
}
};
}
function addEventFreeDraw(map, freeDraw) { function addEventFreeDraw(freeDraw) {
freeDraw.on('markers', ({ latLngs }) => { freeDraw.on('markers', ({ latLngs }) => {
$('#json_latlngs').val(JSON.stringify(latLngs)); const input = document.querySelector('input[name=selection]');
addEventEdit(freeDraw); if (polygonArea(latLngs) < 300000) {
input.value = JSON.stringify(latLngs);
} else {
input.value = '{ "error": "TooManyPolygons" }';
}
getExternalData(map, latLngs); fire(input, 'change');
}); });
$('#map').on('click', () => { on('#map', 'click', () => {
freeDraw.mode(NONE); freeDraw.mode(NONE);
}); });
$('#new').on('click', () => { on('#new', 'click', () => {
freeDraw.mode(CREATE); freeDraw.mode(CREATE);
}); });
} }
function addEventEdit(freeDraw) {
$('.leaflet-container svg').removeAttr('pointer-events');
$('.leaflet-container g path').on('click', () => {
setTimeout(function() {
freeDraw.mode(EDIT | DELETE);
}, 50);
});
}
function getPosition(dossierId) {
return $.getJSON(`/users/dossiers/${dossierId}/carte/position`);
}
function getAddressPoint(map, request) { function getAddressPoint(map, request) {
$.get('/ban/address_point', { request }).then(data => { getJSON('/ban/address_point', { request }).then(data => {
if (data.lat !== null) { if (data.lat !== null) {
map.setView(new L.LatLng(data.lat, data.lon), data.zoom); map.setView(new L.LatLng(data.lat, data.lon), data.zoom);
} }
@ -144,34 +71,11 @@ function getAddressPoint(map, request) {
} }
function addEventSearchAddress(map) { function addEventSearchAddress(map) {
$("#search-by-address input[type='address']").on( on(
'#search-by-address input[type=address]',
'autocomplete:select', 'autocomplete:select',
(_, seggestion) => { (_, seggestion) => {
getAddressPoint(map, seggestion['label']); getAddressPoint(map, seggestion['label']);
} }
); );
} }
function getJsonValue(selector) {
let data = document.querySelector(selector).value;
if (data && data !== '[]') {
return JSON.parse(data);
}
return [];
}
function getJsonPolygons(latLngGroups) {
var groups = [];
latLngGroups.forEach(function forEach(latLngs) {
var group = [];
latLngs.forEach(function forEach(latLng) {
group.push('[' + latLng.lng + ', ' + latLng.lat + ']');
});
groups.push('{ "latLngs": [' + group.join(', ') + '] }');
});
return groups;
}

View file

@ -1,66 +0,0 @@
import L from 'leaflet';
import $ from 'jquery';
export function cadastreActive() {
return $('#map.cadastre').length > 0;
}
export function getCadastre(dossierId, coordinates) {
return $.ajax({
method: 'post',
url: `/users/dossiers/${dossierId}/carte/cadastre`,
data: { coordinates: JSON.stringify(coordinates) },
dataType: 'json'
}).then(({ cadastres }) => cadastres);
}
let cadastreItems;
export function displayCadastre(map, cadastres) {
if (!cadastreActive()) return;
$('#cadastre.list ul').html('');
newCadastreLayer(map);
if (cadastres.length == 1 && cadastres[0]['zoom_error']) {
$('#cadastre.list ul').html(
'<li><b>Merci de dessiner une surface plus petite afin de récupérer les parcelles cadastrales.</b></li>'
);
} else if (cadastres.length > 0) {
cadastres.forEach(function(cadastre) {
$('#cadastre.list ul').append(
'<li> Parcelle nº ' +
cadastre.numero +
' - Feuille ' +
cadastre.code_arr +
' ' +
cadastre.section +
' ' +
cadastre.feuille +
'</li>'
);
cadastreItems.addData(cadastre.geometry);
});
cadastreItems.setStyle({
fillColor: '#8a6d3b',
weight: 2,
opacity: 0.3,
color: 'white',
dashArray: '3',
fillOpacity: 0.7
});
} else {
$('#cadastre.list ul').html('<li>AUCUN</li>');
}
}
function newCadastreLayer(map) {
if (cadastreItems) {
map.removeLayer(cadastreItems);
}
cadastreItems = new L.GeoJSON();
cadastreItems.addTo(map);
}

View file

@ -0,0 +1,45 @@
import { EDIT, DELETE } from 'leaflet-freedraw';
import { on } from '@utils';
import {
drawLayer,
CADASTRE_POLYGON_STYLE,
QP_POLYGON_STYLE
} from '../../shared/carto';
const SOURCES = {
cadastres: CADASTRE_POLYGON_STYLE,
quartiersPrioritaires: QP_POLYGON_STYLE
};
export default function draw(map, freeDraw) {
return data => {
if (data.selection) {
drawSelection(freeDraw, data.selection);
}
for (let source of Object.keys(SOURCES)) {
if (data[source]) {
drawLayer(map, data[source], SOURCES[source], source);
}
}
addEventEdit(freeDraw);
};
}
function drawSelection(selection, freeDraw) {
for (let polygon of selection) {
freeDraw.createPolygon(polygon);
}
}
function addEventEdit(freeDraw) {
document
.querySelector('.leaflet-container svg')
.removeAttribute('pointer-events');
on('.leaflet-container g path', 'click', () => {
setTimeout(() => {
freeDraw.mode(EDIT | DELETE);
}, 50);
});
}

View file

@ -0,0 +1,19 @@
import area from '@turf/area';
export default function polygonArea(latLngs) {
return area({
type: 'FeatureCollection',
features: latLngs.map(featurePolygonLatLngs)
});
}
function featurePolygonLatLngs(latLngs) {
return {
type: 'Feature',
properties: {},
geometry: {
type: 'Polygon',
coordinates: [latLngs.map(({ lng, lat }) => [lng, lat])]
}
};
}

View file

@ -1,56 +0,0 @@
import L from 'leaflet';
import $ from 'jquery';
export function qpActive() {
return $('#map.qp').length > 0;
}
export function getQP(dossierId, coordinates) {
return $.ajax({
method: 'post',
url: `/users/dossiers/${dossierId}/carte/qp`,
data: { coordinates: JSON.stringify(coordinates) },
dataType: 'json'
}).done(({ quartier_prioritaires }) => values(quartier_prioritaires));
}
let qpItems;
export function displayQP(map, qps) {
if (!qpActive()) return;
$('#qp.list ul').html('');
newQPLayer(map);
if (qps.length > 0) {
qps.forEach(function(qp) {
$('#qp.list ul').append('<li>' + qp.commune + ' : ' + qp.nom + '</li>');
qpItems.addData(qp.geometry);
});
qpItems.setStyle({
fillColor: '#31708f',
weight: 2,
opacity: 0.3,
color: 'white',
dashArray: '3',
fillOpacity: 0.7
});
} else {
$('#qp.list ul').html('<li>AUCUN</li>');
}
}
function newQPLayer(map) {
if (qpItems) {
map.removeLayer(qpItems);
}
qpItems = new L.GeoJSON();
qpItems.addTo(map);
}
function values(obj) {
return Object.keys(obj).map(v => obj[v]);
}

View file

@ -1,5 +1,71 @@
const LON = '2.428462'; import L from 'leaflet';
const LAT = '46.538192';
const DEFAULT_POSITION = { lon: LON, lat: LAT, zoom: 5 };
export { DEFAULT_POSITION, LAT, LON }; const LAYERS = {};
export function initMap(position) {
const map = L.map('map', {
scrollWheelZoom: false
}).setView([position.lat, position.lon], position.zoom);
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution:
'&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
}).addTo(map);
return map;
}
export function drawLayer(map, data, style, layerName = 'default') {
removeLayer(map, layerName);
if (Array.isArray(data) && data.length > 0) {
const layer = createLayer(map, layerName);
data.forEach(function(item) {
layer.addData(item.geometry);
});
layer.setStyle(style).addTo(map);
}
}
export function noEditStyle(style) {
return Object.assign({}, style, {
opacity: 0.7,
fillOpacity: 0.5,
color: style.fillColor
});
}
const POLYGON_STYLE = {
weight: 2,
opacity: 0.3,
color: 'white',
dashArray: '3',
fillOpacity: 0.7
};
export const CADASTRE_POLYGON_STYLE = Object.assign({}, POLYGON_STYLE, {
fillColor: '#8a6d3b'
});
export const QP_POLYGON_STYLE = Object.assign({}, POLYGON_STYLE, {
fillColor: '#31708f'
});
function createLayer(map, layerName) {
const layer = (LAYERS[layerName] = new L.GeoJSON(undefined, {
interactive: false
}));
layer.addTo(map);
return layer;
}
function removeLayer(map, layerName) {
const layer = LAYERS[layerName];
if (layer) {
delete LAYERS[layerName];
map.removeLayer(layer);
}
}

View file

@ -241,6 +241,23 @@ class Dossier < ApplicationRecord
end end
end end
def geo_position
if etablissement.present?
point = Carto::Geocodeur.convert_adresse_to_point(etablissement.geo_adresse)
end
lon = "2.428462"
lat = "46.538192"
zoom = "13"
if point.present?
lon = point.x.to_s
lat = point.y.to_s
end
{ lon: lon, lat: lat, zoom: zoom }
end
def unspecified_attestation_champs def unspecified_attestation_champs
attestation_template = procedure.attestation_template attestation_template = procedure.attestation_template

View file

@ -0,0 +1,9 @@
:javascript
DATA.push({
carto: {
position: #{raw(dossier.geo_position.to_json)},
selection: #{raw(ensure_safe_json(dossier.json_latlngs))},
cadastres: #{raw(dossier.cadastres.to_json)},
quartiersPrioritaires: #{raw(dossier.quartier_prioritaires.to_json)}
}
});

View file

@ -16,12 +16,4 @@
%li %li
= "Parcelle n° #{p.numero} - Feuille #{p.code_arr} #{p.section} #{p.feuille}" = "Parcelle n° #{p.numero} - Feuille #{p.code_arr} #{p.section} #{p.feuille}"
:javascript = render partial: 'shared/champs/carto/init', locals: { dossier: dossier }
DATA.push({
carto: {
getPositionUrl: "#{position_gestionnaire_dossier_path(dossier.procedure, dossier)}",
dossierJsonLatLngs: #{raw(ensure_safe_json(dossier.json_latlngs))},
dossierCadastres: #{raw(ensure_safe_json(dossier.cadastres.to_json))},
dossierQuartiersPrioritaires: #{raw(ensure_safe_json(dossier.quartier_prioritaires.to_json))}
}
});

View file

@ -1,6 +0,0 @@
:javascript
DATA.push({
carto: {
dossierId: #{dossier.id}
}
});

View file

@ -1,13 +1,8 @@
#carte-page.row #carte-page.row
.col-md-12.col-lg-12 .col-md-12.col-lg-12
#map{ class: dossier.procedure.module_api_carto.classes } #map.edit
- if dossier.procedure.module_api_carto.quartiers_prioritaires %span.zones
.col-md-9.col-lg-9#qp.col-md-3.col-lg-3.list = render partial: 'zones', locals: { dossier: dossier, error: @error }
%h3.text-info Quartiers prioritaires
%ul
- if dossier.procedure.module_api_carto.cadastre = render partial: 'shared/champs/carto/init', locals: { dossier: dossier }
.col-md-9.col-lg-9#cadastre.col-md-3.col-lg-3.list
%h3.text-warning Cadastres
%ul

View file

@ -0,0 +1,19 @@
- if dossier.procedure.module_api_carto.quartiers_prioritaires?
.col-md-9.col-lg-9#qp.col-md-3.col-lg-3.list
%h3.text-info Quartiers prioritaires
%ul
- dossier.quartier_prioritaires.each do |qp|
%li #{qp.commune} : #{qp.nom}
- if error.present?
%b Merci de dessiner une surface plus petite afin de récupérer les quartiers prioritaires.
- if dossier.procedure.module_api_carto.cadastre?
.col-md-9.col-lg-9#cadastre.col-md-3.col-lg-3.list
%h3.text-warning Parcelles cadastrales
%ul
- dossier.cadastres.each do |cadastre|
%li Parcelle nº #{cadastre.numero} - Feuille #{cadastre.code_arr} #{cadastre.section} #{cadastre.feuille}
- if error.present?
%b Merci de dessiner une surface plus petite afin de récupérer les parcelles cadastrales.

View file

@ -20,13 +20,9 @@
= form_tag(url_for({ controller: :carte, action: :save, dossier_id: @dossier.id }), class: 'form-inline', method: 'POST') do = form_tag(url_for({ controller: :carte, action: :save, dossier_id: @dossier.id }), class: 'form-inline', method: 'POST') do
%br %br
%input#json_latlngs{ type: 'hidden', value: "#{@dossier.json_latlngs}", name: 'json_latlngs' } %input{ type: 'hidden', value: "#{@dossier.json_latlngs}", name: 'selection', data: { remote: true, url: users_dossier_carte_zones_path(@dossier), method: 'POST' } }
%input#quartier_prioritaires{ type: 'hidden', value: "#{@dossier.quartier_prioritaires.to_json}" }
%input#cadastres{ type: 'hidden', value: "#{@dossier.cadastres.to_json}" }
- if @dossier.brouillon? - if @dossier.brouillon?
= render partial: '/layouts/etape_suivante' = render partial: '/layouts/etape_suivante'
- else - else
= render partial: '/layouts/modifications_terminees' = render partial: '/layouts/modifications_terminees'
= render partial: 'users/carte/init_carto', locals: { dossier: @dossier }

View file

@ -0,0 +1,2 @@
DS.cartoDrawZones(<%= raw(@data.to_json) %>);
<%= render_to_element('.zones', partial: 'zones', locals: { dossier: @dossier, error: @error }) %>

View file

@ -152,10 +152,7 @@ Rails.application.routes.draw do
resources :dossiers do resources :dossiers do
get '/add_siret' => 'dossiers/add_siret#show' get '/add_siret' => 'dossiers/add_siret#show'
get '/carte/position' => 'carte#get_position' post '/carte/zones' => 'carte#zones'
post '/carte/qp' => 'carte#get_qp'
post '/carte/cadastre' => 'carte#get_cadastre'
get '/carte' => 'carte#show' get '/carte' => 'carte#show'
post '/carte' => 'carte#save' post '/carte' => 'carte#save'
@ -333,9 +330,6 @@ Rails.application.routes.draw do
post 'repasser-en-construction' => 'dossiers#repasser_en_construction' post 'repasser-en-construction' => 'dossiers#repasser_en_construction'
post 'terminer' post 'terminer'
post 'send-to-instructeurs' => 'dossiers#send_to_instructeurs' post 'send-to-instructeurs' => 'dossiers#send_to_instructeurs'
scope :carte do
get 'position'
end
post 'avis' => 'dossiers#create_avis' post 'avis' => 'dossiers#create_avis'
get 'print' => 'dossiers#print' get 'print' => 'dossiers#print'
end end

View file

@ -64,7 +64,7 @@ shared_examples 'carte_controller_spec' do
let(:json_latlngs) { multipolygon.to_json } let(:json_latlngs) { multipolygon.to_json }
before do before do
post :save, params: { dossier_id: dossier.id, json_latlngs: json_latlngs } post :save, params: { dossier_id: dossier.id, selection: json_latlngs }
dossier.reload dossier.reload
end end
@ -101,7 +101,7 @@ shared_examples 'carte_controller_spec' do
context 'En train de modifier la localisation' do context 'En train de modifier la localisation' do
let(:dossier) { create(:dossier, state: Dossier.states.fetch(:en_construction)) } let(:dossier) { create(:dossier, state: Dossier.states.fetch(:en_construction)) }
before do before do
post :save, params: { dossier_id: dossier.id, json_latlngs: '' } post :save, params: { dossier_id: dossier.id, selection: '' }
end end
it 'Redirection vers le formulaire de la procedure' do it 'Redirection vers le formulaire de la procedure' do
@ -117,7 +117,7 @@ shared_examples 'carte_controller_spec' do
.to receive(:to_params) .to receive(:to_params)
.and_return({ "QPCODE1234" => { :code => "QPCODE1234", :nom => "QP de test", :commune => "Paris", :geometry => { :type => "MultiPolygon", :coordinates => [[[[2.38715792094576, 48.8723062632126], [2.38724851642619, 48.8721392348061]]]] } } }) .and_return({ "QPCODE1234" => { :code => "QPCODE1234", :nom => "QP de test", :commune => "Paris", :geometry => { :type => "MultiPolygon", :coordinates => [[[[2.38715792094576, 48.8723062632126], [2.38724851642619, 48.8721392348061]]]] } } })
post :save, params: { dossier_id: dossier.id, json_latlngs: json_latlngs } post :save, params: { dossier_id: dossier.id, selection: json_latlngs }
end end
context 'when json_latlngs params is empty' do context 'when json_latlngs params is empty' do
@ -164,7 +164,7 @@ shared_examples 'carte_controller_spec' do
.to receive(:to_params) .to receive(:to_params)
.and_return([{ :surface_intersection => "0.0006", :surface_parcelle => 11252.692583090324, :numero => "0013", :feuille => 1, :section => "CD", :code_dep => "30", :nom_com => "Le Grau-du-Roi", :code_com => "133", :code_arr => "000", :geometry => { :type => "MultiPolygon", :coordinates => [[[[4.134084, 43.5209193], [4.1346615, 43.5212035], [4.1346984, 43.521189], [4.135096, 43.5213848], [4.1350839, 43.5214122], [4.1352697, 43.521505], [4.1356278, 43.5211065], [4.1357402, 43.5207188], [4.1350935, 43.5203936], [4.135002, 43.5204366], [4.1346051, 43.5202412], [4.134584, 43.5202472], [4.1345572, 43.5202551], [4.134356, 43.5203137], [4.1342488, 43.5203448], [4.134084, 43.5209193]]]] } }]) .and_return([{ :surface_intersection => "0.0006", :surface_parcelle => 11252.692583090324, :numero => "0013", :feuille => 1, :section => "CD", :code_dep => "30", :nom_com => "Le Grau-du-Roi", :code_com => "133", :code_arr => "000", :geometry => { :type => "MultiPolygon", :coordinates => [[[[4.134084, 43.5209193], [4.1346615, 43.5212035], [4.1346984, 43.521189], [4.135096, 43.5213848], [4.1350839, 43.5214122], [4.1352697, 43.521505], [4.1356278, 43.5211065], [4.1357402, 43.5207188], [4.1350935, 43.5203936], [4.135002, 43.5204366], [4.1346051, 43.5202412], [4.134584, 43.5202472], [4.1345572, 43.5202551], [4.134356, 43.5203137], [4.1342488, 43.5203448], [4.134084, 43.5209193]]]] } }])
post :save, params: { dossier_id: dossier.id, json_latlngs: json_latlngs } post :save, params: { dossier_id: dossier.id, selection: json_latlngs }
end end
context 'when json_latlngs params is empty' do context 'when json_latlngs params is empty' do
@ -210,96 +210,33 @@ shared_examples 'carte_controller_spec' do
end end
end end
describe '#get_position' do describe 'POST #zones' do
context 'when etablissement is nil' do let(:module_api_carto) { create(:module_api_carto, :with_quartiers_prioritaires) }
before do render_views
dossier.update etablissement: nil
stub_request(:get, /http:\/\/api-adresse[.]data[.]gouv[.]fr\/search[?]limit=1&q=/)
.to_return(status: 200, body: '{"query": "babouba", "version": "draft", "licence": "ODbL 1.0", "features": [], "type": "FeatureCollection", "attribution": "BAN"}', headers: {})
get :get_position, params: { dossier_id: dossier.id }
end
subject { JSON.parse(response.body) }
it 'on enregistre des coordonnées lat et lon avec les valeurs par defaut' do
expect(subject['lat']).to eq('46.538192')
expect(subject['lon']).to eq('2.428462')
end
end
context 'Geocodeur renvoie les positions par defaut' do
let(:etablissement) { create(:etablissement, adresse: bad_adresse, numero_voie: 'dzj', type_voie: 'fzjfk', nom_voie: 'hdidjkz', complement_adresse: 'fjef', code_postal: 'fjeiefk', localite: 'zjfkfz') }
let(:dossier) { create(:dossier, etablissement: etablissement) }
before do
stub_request(:get, /http:\/\/api-adresse[.]data[.]gouv[.]fr\/search[?]limit=1&q=/)
.to_return(status: 200, body: '{"query": "babouba", "version": "draft", "licence": "ODbL 1.0", "features": [], "type": "FeatureCollection", "attribution": "BAN"}', headers: {})
get :get_position, params: { dossier_id: dossier.id }
end
subject { JSON.parse(response.body) }
it 'on enregistre des coordonnées lat et lon avec les valeurs par defaut' do
expect(subject['lat']).to eq('46.538192')
expect(subject['lon']).to eq('2.428462')
end
end
context 'retour d\'un fichier JSON avec 3 attributs' do
before do
stub_request(:get, "http://api-adresse.data.gouv.fr/search?limit=1&q=#{adresse}")
.to_return(status: 200, body: '{"query": "50 avenue des champs u00e9lysu00e9es Paris 75008", "version": "draft", "licence": "ODbL 1.0", "features": [{"geometry": {"coordinates": [2.306888, 48.870374], "type": "Point"}, "type": "Feature", "properties": {"city": "Paris", "label": "50 Avenue des Champs u00c9lysu00e9es 75008 Paris", "housenumber": "50", "id": "ADRNIVX_0000000270748251", "postcode": "75008", "name": "50 Avenue des Champs u00c9lysu00e9es", "citycode": "75108", "context": "75, u00cele-de-France", "score": 0.9054545454545454, "type": "housenumber"}}], "type": "FeatureCollection", "attribution": "BAN"}', headers: {})
get :get_position, params: { dossier_id: dossier.id }
end
subject { JSON.parse(response.body) }
it 'format JSON valide' do
expect(response.content_type).to eq('application/json')
end
it 'latitude' do
expect(subject['lat']).to eq('48.870374')
end
it 'longitude' do
expect(subject['lon']).to eq('2.306888')
end
it 'dossier_id' do
expect(subject['dossier_id']).to eq(dossier.id.to_s)
end
end
end
describe 'POST #get_qp' do
before do before do
allow_any_instance_of(CARTO::SGMAP::QuartiersPrioritaires::Adapter) allow_any_instance_of(CARTO::SGMAP::QuartiersPrioritaires::Adapter)
.to receive(:to_params) .to receive(:to_params)
.and_return({ "QPCODE1234" => { :code => "QPCODE1234", :geometry => { :type => "MultiPolygon", :coordinates => [[[[2.38715792094576, 48.8723062632126], [2.38724851642619, 48.8721392348061]]]] } } }) .and_return({ "QPCODE1234" => { :code => "QPCODE1234", :geometry => { :type => "MultiPolygon", :coordinates => [[[[2.38715792094576, 48.8723062632126], [2.38724851642619, 48.8721392348061]]]] } } })
post :get_qp, params: { dossier_id: dossier.id, coordinates: coordinates } post :zones, params: { dossier_id: dossier.id, selection: json_latlngs.to_json }, format: 'js'
end end
context 'when coordinates are empty' do context 'when coordinates are empty' do
let(:coordinates) { '[]' } let(:json_latlngs) { [] }
subject { JSON.parse(response.body) }
it 'Quartier Prioritaire Adapter does not call' do it 'Quartier Prioritaire Adapter does not call' do
expect(subject['quartier_prioritaires']).to eq({}) expect(response.body).to include("DS.cartoDrawZones({\"quartiersPrioritaires\":[]});")
end end
end end
context 'when coordinates are informed' do context 'when coordinates are informed' do
let(:coordinates) { '[[{"lat":48.87442541960633,"lng":2.3859214782714844},{"lat":48.87273183590832,"lng":2.3850631713867183},{"lat":48.87081237174292,"lng":2.3809432983398438},{"lat":48.8712640169951,"lng":2.377510070800781},{"lat":48.87510283703279,"lng":2.3778533935546875},{"lat":48.87544154230615,"lng":2.382831573486328},{"lat":48.87442541960633,"lng":2.3859214782714844}]]' } let(:json_latlngs) { [[{ "lat": 48.87442541960633, "lng": 2.3859214782714844 }, { "lat": 48.87273183590832, "lng": 2.3850631713867183 }, { "lat": 48.87081237174292, "lng": 2.3809432983398438 }, { "lat": 48.8712640169951, "lng": 2.377510070800781 }, { "lat": 48.87510283703279, "lng": 2.3778533935546875 }, { "lat": 48.87544154230615, "lng": 2.382831573486328 }, { "lat": 48.87442541960633, "lng": 2.3859214782714844 }]] }
subject { JSON.parse(response.body)['quartier_prioritaires'] } it { expect(response.body).not_to be_nil }
it { expect(subject).not_to be_nil } it { expect(response.body).to include('QPCODE1234') }
it { expect(subject['QPCODE1234']['code']).to eq('QPCODE1234') } it { expect(response.body).to include('MultiPolygon') }
it { expect(subject['QPCODE1234']['geometry']['type']).to eq('MultiPolygon') } it { expect(response.body).to include('[2.38715792094576,48.8723062632126]') }
it { expect(subject['QPCODE1234']['geometry']['coordinates']).to eq([[[[2.38715792094576, 48.8723062632126], [2.38724851642619, 48.8721392348061]]]]) }
end end
end end
end end

View file

@ -6,14 +6,14 @@ describe 'shared/dossiers/map.html.haml', type: :view do
end end
describe "javascript variables printing" do describe "javascript variables printing" do
let(:dossier) { create(:dossier, :with_entreprise, json_latlngs: json_latlngs) } let(:dossier) { create(:dossier, json_latlngs: json_latlngs) }
context 'with a correct json' do context 'with a correct json' do
let(:json_latlngs) { "[[{\"lat\":50.659255436656736,\"lng\":3.080635070800781},{\"lat\":50.659255436656736,\"lng\":3.079690933227539},{\"lat\":50.659962770886516,\"lng\":3.0800342559814453},{\"lat\":50.659962770886516,\"lng\":3.0811500549316406},{\"lat\":50.659255436656736,\"lng\":3.080635070800781}]]" } let(:json_latlngs) { "[[{\"lat\":50.659255436656736,\"lng\":3.080635070800781},{\"lat\":50.659255436656736,\"lng\":3.079690933227539},{\"lat\":50.659962770886516,\"lng\":3.0800342559814453},{\"lat\":50.659962770886516,\"lng\":3.0811500549316406},{\"lat\":50.659255436656736,\"lng\":3.080635070800781}]]" }
before { subject } before { subject }
it { expect(rendered).to have_content('dossierJsonLatLngs: [[{"lat":50.659255436656736,"lng":3.080635070800781},{"lat":50.659255436656736,"lng":3.079690933227539},{"lat":50.659962770886516,"lng":3.0800342559814453},{"lat":50.659962770886516,"lng":3.0811500549316406},{"lat":50.659255436656736,"lng":3.080635070800781}]],') } it { expect(rendered).to have_content('selection: [[{"lat":50.659255436656736,"lng":3.080635070800781},{"lat":50.659255436656736,"lng":3.079690933227539},{"lat":50.659962770886516,"lng":3.0800342559814453},{"lat":50.659962770886516,"lng":3.0811500549316406},{"lat":50.659255436656736,"lng":3.080635070800781}]],') }
end end
context 'without a correct json' do context 'without a correct json' do
@ -21,7 +21,7 @@ describe 'shared/dossiers/map.html.haml', type: :view do
before { subject } before { subject }
it { expect(rendered).to have_content('dossierJsonLatLngs: {},') } it { expect(rendered).to have_content('selection: {},') }
end end
end end
end end

View file

@ -23,7 +23,7 @@ describe 'users/carte/show.html.haml', type: :view do
context 'présence des inputs hidden' do context 'présence des inputs hidden' do
it 'stockage du json des polygons dessinés' do it 'stockage du json des polygons dessinés' do
expect(rendered).to have_selector('input[type=hidden][id=json_latlngs][name=json_latlngs]', visible: false) expect(rendered).to have_selector('input[type=hidden][name=selection]', visible: false)
end end
end end