diff --git a/app/assets/stylesheets/carte.scss b/app/assets/stylesheets/carte.scss index a4613ecb8..b0e5134e7 100644 --- a/app/assets/stylesheets/carte.scss +++ b/app/assets/stylesheets/carte.scss @@ -6,10 +6,10 @@ #carte-page { #map { height: 600px; + z-index: 0; } - #map.qp, - #map.cadastre { + #map.edit { width: 70%; } @@ -30,13 +30,6 @@ cursor: url("/assets/edit.png"), default !important; } -#infos-dossiers { - #map.mini { - height: 300px; - width: 100%; - } -} - #map.mode-create { cursor: url("/assets/pencil.png"), crosshair !important; } @@ -47,17 +40,17 @@ stroke-opacity: 1; stroke: #D7217E; position: absolute; - z-index: 1001; + z-index: 100; fill: #D7217E; fill-opacity: 0.75; } -#map.mode-delete path { +#map.mode-delete path.leaflet-polygon { cursor: no-drop !important; -} -#map.mode-delete path:hover { - fill: #4D4D4D !important; + &:hover { + fill: #4D4D4D !important; + } } #map div.leaflet-edge { diff --git a/app/controllers/new_gestionnaire/dossiers_controller.rb b/app/controllers/new_gestionnaire/dossiers_controller.rb index 1b90932ba..ce56a4617 100644 --- a/app/controllers/new_gestionnaire/dossiers_controller.rb +++ b/app/controllers/new_gestionnaire/dossiers_controller.rb @@ -129,25 +129,6 @@ module NewGestionnaire 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 @avis = Avis.new(avis_params.merge(claimant: current_gestionnaire, dossier: dossier)) if @avis.save diff --git a/app/controllers/users/carte_controller.rb b/app/controllers/users/carte_controller.rb index 1e277dd06..8e556cf7f 100644 --- a/app/controllers/users/carte_controller.rb +++ b/app/controllers/users/carte_controller.rb @@ -12,51 +12,43 @@ class Users::CarteController < UsersController end def save - safe_json_latlngs = clean_json_latlngs(params[:json_latlngs]) + geo_json = clean_json_latlngs(params[:selection]) dossier = current_user_dossier dossier.quartier_prioritaires.each(&:destroy) dossier.cadastres.each(&:destroy) - if safe_json_latlngs.present? - ModuleApiCartoService.save_qp! dossier, safe_json_latlngs - ModuleApiCartoService.save_cadastre! dossier, safe_json_latlngs + if geo_json.present? + ModuleApiCartoService.save_qp! dossier, geo_json + ModuleApiCartoService.save_cadastre! dossier, geo_json end - dossier.update(json_latlngs: safe_json_latlngs) + dossier.update!(json_latlngs: geo_json) redirect_to brouillon_dossier_path(dossier) end - def get_position - begin - etablissement = current_user_dossier.etablissement - rescue ActiveRecord::RecordNotFound - etablissement = nil + def zones + @dossier = current_user_dossier + @data = {} + + 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 + + if @dossier.procedure.module_api_carto.cadastre? + cadastres = ModuleApiCartoService.generate_cadastre(geo_json) + @dossier.cadastres.build(cadastres) + @data[:cadastres] = cadastres + end end - - 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 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 def self.route_authorization diff --git a/app/javascript/new_design/carto.js b/app/javascript/new_design/carto.js index 895a613ba..3cf8a57a5 100644 --- a/app/javascript/new_design/carto.js +++ b/app/javascript/new_design/carto.js @@ -1,9 +1,5 @@ -import L from 'leaflet'; -import { getJSON } from '@utils'; - import { getData } from '../shared/data'; -import { DEFAULT_POSITION } from '../shared/carto'; - +import { initMap } from '../shared/carto'; import { drawCadastre, drawQuartiersPrioritaires, @@ -12,31 +8,17 @@ import { function initialize() { if (document.getElementById('map')) { - getJSON(getData('carto').getPositionUrl).then( - position => initializeWithPosition(position), - () => initializeWithPosition(DEFAULT_POSITION) - ); + const position = getData('carto').position; + const map = initMap(position); + const data = getData('carto'); + + // draw external polygons + drawCadastre(map, data); + drawQuartiersPrioritaires(map, data); + + // draw user polygon + drawUserSelection(map, data); } } 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: - '© OpenStreetMap contributors' - }).addTo(map); - - const data = getData('carto'); - - // draw external polygons - drawCadastre(map, data); - drawQuartiersPrioritaires(map, data); - - // draw user polygon - drawUserSelection(map, data); -} diff --git a/app/javascript/new_design/carto/draw.js b/app/javascript/new_design/carto/draw.js index 1eee603f1..1e84c0a71 100644 --- a/app/javascript/new_design/carto/draw.js +++ b/app/javascript/new_design/carto/draw.js @@ -1,45 +1,32 @@ import L from 'leaflet'; +import { + drawLayer, + noEditStyle, + CADASTRE_POLYGON_STYLE, + QP_POLYGON_STYLE +} from '../../shared/carto'; -function drawLayerWithItems(map, items, style) { - if (Array.isArray(items) && items.length > 0) { - const layer = new L.GeoJSON(); - - items.forEach(function(item) { - layer.addData(item.geometry); - }); - - layer.setStyle(style).addTo(map); - } +export function drawCadastre(map, data) { + drawLayer( + map, + data.cadastres, + noEditStyle(CADASTRE_POLYGON_STYLE), + 'cadastres' + ); } -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, data) { + drawLayer( + map, + data.quartiersPrioritaires, + noEditStyle(QP_POLYGON_STYLE), + 'quartiersPrioritaires' + ); } -export function drawQuartiersPrioritaires( - map, - { dossierQuartiersPrioritaires } -) { - drawLayerWithItems(map, dossierQuartiersPrioritaires, { - fillColor: '#31708F', - weight: 2, - opacity: 0.7, - color: '#31708F', - dashArray: '3', - fillOpacity: 0.5 - }); -} - -export function drawUserSelection(map, { dossierJsonLatLngs }) { - if (dossierJsonLatLngs.length > 0) { - const polygon = L.polygon(dossierJsonLatLngs, { +export function drawUserSelection(map, data) { + if (data.selection.length > 0) { + const polygon = L.polygon(data.selection, { color: 'red', zIndex: 3 }).addTo(map); diff --git a/app/javascript/old_design/carto.js b/app/javascript/old_design/carto.js index 670833b51..d1a7dafa7 100644 --- a/app/javascript/old_design/carto.js +++ b/app/javascript/old_design/carto.js @@ -1,142 +1,69 @@ import L from 'leaflet'; -import area from '@turf/area'; -import FreeDraw, { NONE, EDIT, CREATE, DELETE } from 'leaflet-freedraw'; -import $ from 'jquery'; + +import FreeDraw, { NONE, CREATE } from 'leaflet-freedraw'; +import { fire, on, getJSON } from '@utils'; import { getData } from '../shared/data'; -import { DEFAULT_POSITION, LAT, LON } from '../shared/carto'; -import { qpActive, displayQP, getQP } from './carto/qp'; -import { cadastreActive, displayCadastre, getCadastre } from './carto/cadastre'; +import { initMap } from '../shared/carto'; + +import polygonArea from './carto/polygon_area'; +import drawFactory from './carto/draw'; function initialize() { - if ($('#map').length > 0) { - getPosition(getData('carto').dossierId).then( - position => initializeWithPosition(position), - () => initializeWithPosition(DEFAULT_POSITION) - ); + if (document.getElementById('map')) { + const data = getData('carto'); + const position = data.position; + + const map = initMap(position); + const freeDraw = new FreeDraw({ + mode: NONE, + smoothFactor: 4, + mergePolygons: false + }); + + map.addLayer(freeDraw); + + addEventFreeDraw(freeDraw); + addEventSearchAddress(map); + + const cartoDrawZones = drawFactory(map, freeDraw); + window.DS = { cartoDrawZones }; + + cartoDrawZones(data); + + if (freeDraw.polygons[0]) { + map.setZoom(18); + map.fitBounds(freeDraw.polygons[0].getBounds()); + } } } addEventListener('turbolinks:load', initialize); -function initializeWithPosition(position) { - const OSM = L.tileLayer( - 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', - { - attribution: - '© OpenStreetMap' - } - ); - - 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 freeDraw = new FreeDraw({ - mode: NONE, - smoothFactor: 4, - mergePolygons: false - }); - - map.addLayer(freeDraw); - - const latLngs = getJsonValue('#json_latlngs'); - - 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); -} - -function getExternalData(map, latLngs) { - const { dossierId } = getData('carto'); - - if (qpActive()) { - getQP(dossierId, latLngs).then(qps => displayQP(map, qps)); - } - - if (cadastreActive()) { - const polygons = { type: 'FeatureCollection', features: [] }; - - 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) { - return { - type: 'Feature', - properties: {}, - geometry: { - type: 'Polygon', - coordinates: [JSON.parse(getJsonPolygons([coordinates]))['latLngs']] - } - }; -} - -function addEventFreeDraw(map, freeDraw) { +function addEventFreeDraw(freeDraw) { 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); }); - $('#new').on('click', () => { + on('#new', 'click', () => { 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) { - $.get('/ban/address_point', { request }).then(data => { + getJSON('/ban/address_point', { request }).then(data => { if (data.lat !== null) { map.setView(new L.LatLng(data.lat, data.lon), data.zoom); } @@ -144,34 +71,11 @@ function getAddressPoint(map, request) { } function addEventSearchAddress(map) { - $("#search-by-address input[type='address']").on( + on( + '#search-by-address input[type=address]', 'autocomplete:select', (_, seggestion) => { 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; -} diff --git a/app/javascript/old_design/carto/cadastre.js b/app/javascript/old_design/carto/cadastre.js deleted file mode 100644 index 55b7a1a6e..000000000 --- a/app/javascript/old_design/carto/cadastre.js +++ /dev/null @@ -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( - '
  • Merci de dessiner une surface plus petite afin de récupérer les parcelles cadastrales.
  • ' - ); - } else if (cadastres.length > 0) { - cadastres.forEach(function(cadastre) { - $('#cadastre.list ul').append( - '
  • Parcelle nº ' + - cadastre.numero + - ' - Feuille ' + - cadastre.code_arr + - ' ' + - cadastre.section + - ' ' + - cadastre.feuille + - '
  • ' - ); - - 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('
  • AUCUN
  • '); - } -} - -function newCadastreLayer(map) { - if (cadastreItems) { - map.removeLayer(cadastreItems); - } - - cadastreItems = new L.GeoJSON(); - cadastreItems.addTo(map); -} diff --git a/app/javascript/old_design/carto/draw.js b/app/javascript/old_design/carto/draw.js new file mode 100644 index 000000000..46dc47575 --- /dev/null +++ b/app/javascript/old_design/carto/draw.js @@ -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); + }); +} diff --git a/app/javascript/old_design/carto/polygon_area.js b/app/javascript/old_design/carto/polygon_area.js new file mode 100644 index 000000000..d0384a310 --- /dev/null +++ b/app/javascript/old_design/carto/polygon_area.js @@ -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])] + } + }; +} diff --git a/app/javascript/old_design/carto/qp.js b/app/javascript/old_design/carto/qp.js deleted file mode 100644 index b1acddc6a..000000000 --- a/app/javascript/old_design/carto/qp.js +++ /dev/null @@ -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('
  • ' + qp.commune + ' : ' + qp.nom + '
  • '); - - 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('
  • AUCUN
  • '); - } -} - -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]); -} diff --git a/app/javascript/shared/carto.js b/app/javascript/shared/carto.js index 361a971c0..1b96ef7af 100644 --- a/app/javascript/shared/carto.js +++ b/app/javascript/shared/carto.js @@ -1,5 +1,71 @@ -const LON = '2.428462'; -const LAT = '46.538192'; -const DEFAULT_POSITION = { lon: LON, lat: LAT, zoom: 5 }; +import L from 'leaflet'; -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: + '© OpenStreetMap 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); + } +} diff --git a/app/models/dossier.rb b/app/models/dossier.rb index a13f01e50..e5d832151 100644 --- a/app/models/dossier.rb +++ b/app/models/dossier.rb @@ -241,6 +241,23 @@ class Dossier < ApplicationRecord 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 attestation_template = procedure.attestation_template diff --git a/app/views/shared/champs/carto/_init.html.haml b/app/views/shared/champs/carto/_init.html.haml new file mode 100644 index 000000000..049256589 --- /dev/null +++ b/app/views/shared/champs/carto/_init.html.haml @@ -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)} + } + }); diff --git a/app/views/shared/dossiers/_map.html.haml b/app/views/shared/dossiers/_map.html.haml index c20fe4bbb..e110b0268 100644 --- a/app/views/shared/dossiers/_map.html.haml +++ b/app/views/shared/dossiers/_map.html.haml @@ -16,12 +16,4 @@ %li = "Parcelle n° #{p.numero} - Feuille #{p.code_arr} #{p.section} #{p.feuille}" - :javascript - 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))} - } - }); + = render partial: 'shared/champs/carto/init', locals: { dossier: dossier } diff --git a/app/views/users/carte/_init_carto.html.haml b/app/views/users/carte/_init_carto.html.haml deleted file mode 100644 index 8cd9c2882..000000000 --- a/app/views/users/carte/_init_carto.html.haml +++ /dev/null @@ -1,6 +0,0 @@ -:javascript - DATA.push({ - carto: { - dossierId: #{dossier.id} - } - }); diff --git a/app/views/users/carte/_map.html.haml b/app/views/users/carte/_map.html.haml index 513836a13..7fc00020e 100644 --- a/app/views/users/carte/_map.html.haml +++ b/app/views/users/carte/_map.html.haml @@ -1,13 +1,8 @@ #carte-page.row .col-md-12.col-lg-12 - #map{ class: dossier.procedure.module_api_carto.classes } + #map.edit - - 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 + %span.zones + = render partial: 'zones', locals: { dossier: dossier, error: @error } - - if dossier.procedure.module_api_carto.cadastre - .col-md-9.col-lg-9#cadastre.col-md-3.col-lg-3.list - %h3.text-warning Cadastres - %ul += render partial: 'shared/champs/carto/init', locals: { dossier: dossier } diff --git a/app/views/users/carte/_zones.html.haml b/app/views/users/carte/_zones.html.haml new file mode 100644 index 000000000..d100a6977 --- /dev/null +++ b/app/views/users/carte/_zones.html.haml @@ -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. diff --git a/app/views/users/carte/show.html.haml b/app/views/users/carte/show.html.haml index 723e05947..d536f03e2 100644 --- a/app/views/users/carte/show.html.haml +++ b/app/views/users/carte/show.html.haml @@ -20,13 +20,9 @@ = form_tag(url_for({ controller: :carte, action: :save, dossier_id: @dossier.id }), class: 'form-inline', method: 'POST') do %br - %input#json_latlngs{ type: 'hidden', value: "#{@dossier.json_latlngs}", name: 'json_latlngs' } - %input#quartier_prioritaires{ type: 'hidden', value: "#{@dossier.quartier_prioritaires.to_json}" } - %input#cadastres{ type: 'hidden', value: "#{@dossier.cadastres.to_json}" } + %input{ type: 'hidden', value: "#{@dossier.json_latlngs}", name: 'selection', data: { remote: true, url: users_dossier_carte_zones_path(@dossier), method: 'POST' } } - if @dossier.brouillon? = render partial: '/layouts/etape_suivante' - else = render partial: '/layouts/modifications_terminees' - - = render partial: 'users/carte/init_carto', locals: { dossier: @dossier } diff --git a/app/views/users/carte/zones.js.erb b/app/views/users/carte/zones.js.erb new file mode 100644 index 000000000..34fdb41a0 --- /dev/null +++ b/app/views/users/carte/zones.js.erb @@ -0,0 +1,2 @@ +DS.cartoDrawZones(<%= raw(@data.to_json) %>); +<%= render_to_element('.zones', partial: 'zones', locals: { dossier: @dossier, error: @error }) %> diff --git a/config/routes.rb b/config/routes.rb index 8bb7fb13b..1a479b23e 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -152,10 +152,7 @@ Rails.application.routes.draw do resources :dossiers do get '/add_siret' => 'dossiers/add_siret#show' - get '/carte/position' => 'carte#get_position' - post '/carte/qp' => 'carte#get_qp' - post '/carte/cadastre' => 'carte#get_cadastre' - + post '/carte/zones' => 'carte#zones' get '/carte' => 'carte#show' post '/carte' => 'carte#save' @@ -333,9 +330,6 @@ Rails.application.routes.draw do post 'repasser-en-construction' => 'dossiers#repasser_en_construction' post 'terminer' post 'send-to-instructeurs' => 'dossiers#send_to_instructeurs' - scope :carte do - get 'position' - end post 'avis' => 'dossiers#create_avis' get 'print' => 'dossiers#print' end diff --git a/spec/controllers/users/carte_controller_shared_example.rb b/spec/controllers/users/carte_controller_shared_example.rb index 14be73f2c..3446d6826 100644 --- a/spec/controllers/users/carte_controller_shared_example.rb +++ b/spec/controllers/users/carte_controller_shared_example.rb @@ -64,7 +64,7 @@ shared_examples 'carte_controller_spec' do let(:json_latlngs) { multipolygon.to_json } 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 end @@ -101,7 +101,7 @@ shared_examples 'carte_controller_spec' do context 'En train de modifier la localisation' do let(:dossier) { create(:dossier, state: Dossier.states.fetch(:en_construction)) } before do - post :save, params: { dossier_id: dossier.id, json_latlngs: '' } + post :save, params: { dossier_id: dossier.id, selection: '' } end it 'Redirection vers le formulaire de la procedure' do @@ -117,7 +117,7 @@ shared_examples 'carte_controller_spec' do .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]]]] } } }) - post :save, params: { dossier_id: dossier.id, json_latlngs: json_latlngs } + post :save, params: { dossier_id: dossier.id, selection: json_latlngs } end context 'when json_latlngs params is empty' do @@ -164,7 +164,7 @@ shared_examples 'carte_controller_spec' do .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]]]] } }]) - post :save, params: { dossier_id: dossier.id, json_latlngs: json_latlngs } + post :save, params: { dossier_id: dossier.id, selection: json_latlngs } end context 'when json_latlngs params is empty' do @@ -210,96 +210,33 @@ shared_examples 'carte_controller_spec' do end end - describe '#get_position' do - context 'when etablissement is nil' do - before do - dossier.update etablissement: nil + describe 'POST #zones' do + let(:module_api_carto) { create(:module_api_carto, :with_quartiers_prioritaires) } + render_views - 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 allow_any_instance_of(CARTO::SGMAP::QuartiersPrioritaires::Adapter) .to receive(:to_params) .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 context 'when coordinates are empty' do - let(:coordinates) { '[]' } - - subject { JSON.parse(response.body) } + let(:json_latlngs) { [] } it 'Quartier Prioritaire Adapter does not call' do - expect(subject['quartier_prioritaires']).to eq({}) + expect(response.body).to include("DS.cartoDrawZones({\"quartiersPrioritaires\":[]});") end end 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(subject).not_to be_nil } - it { expect(subject['QPCODE1234']['code']).to eq('QPCODE1234') } - it { expect(subject['QPCODE1234']['geometry']['type']).to eq('MultiPolygon') } - it { expect(subject['QPCODE1234']['geometry']['coordinates']).to eq([[[[2.38715792094576, 48.8723062632126], [2.38724851642619, 48.8721392348061]]]]) } + it { expect(response.body).not_to be_nil } + it { expect(response.body).to include('QPCODE1234') } + it { expect(response.body).to include('MultiPolygon') } + it { expect(response.body).to include('[2.38715792094576,48.8723062632126]') } end end end diff --git a/spec/views/shared/dossiers/_map_spec.rb b/spec/views/shared/dossiers/_map_spec.rb index 9e3d05c48..250a1fb8d 100644 --- a/spec/views/shared/dossiers/_map_spec.rb +++ b/spec/views/shared/dossiers/_map_spec.rb @@ -6,14 +6,14 @@ describe 'shared/dossiers/map.html.haml', type: :view do end 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 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 } - 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 context 'without a correct json' do @@ -21,7 +21,7 @@ describe 'shared/dossiers/map.html.haml', type: :view do before { subject } - it { expect(rendered).to have_content('dossierJsonLatLngs: {},') } + it { expect(rendered).to have_content('selection: {},') } end end end diff --git a/spec/views/users/carte/show.html.haml_spec.rb b/spec/views/users/carte/show.html.haml_spec.rb index d30f8c13c..6aa85457f 100644 --- a/spec/views/users/carte/show.html.haml_spec.rb +++ b/spec/views/users/carte/show.html.haml_spec.rb @@ -23,7 +23,7 @@ describe 'users/carte/show.html.haml', type: :view do context 'présence des inputs hidden' 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