Merge pull request #5048 from tchak/cart-editor-write
Carte Editor sends FeatureCollection to the server
This commit is contained in:
commit
fcfb3cb835
8 changed files with 98 additions and 55 deletions
|
@ -1,16 +1,15 @@
|
|||
class Champs::CarteController < ApplicationController
|
||||
before_action :authenticate_logged_user!
|
||||
|
||||
EMPTY_GEO_JSON = '[]'
|
||||
ERROR_GEO_JSON = ''
|
||||
|
||||
def show
|
||||
@selector = ".carte-#{params[:position]}"
|
||||
|
||||
if params[:dossier].key?(:champs_attributes)
|
||||
coordinates = params[:dossier][:champs_attributes][params[:position]][:value]
|
||||
feature_collection = if params[:dossier].key?(:champs_attributes)
|
||||
params[:dossier][:champs_attributes][params[:position]][:value]
|
||||
else
|
||||
coordinates = params[:dossier][:champs_private_attributes][params[:position]][:value]
|
||||
params[:dossier][:champs_private_attributes][params[:position]][:value]
|
||||
end
|
||||
|
||||
@champ = if params[:champ_id].present?
|
||||
|
@ -21,40 +20,21 @@ class Champs::CarteController < ApplicationController
|
|||
|
||||
geo_areas = []
|
||||
|
||||
if coordinates == EMPTY_GEO_JSON
|
||||
@champ.value = nil
|
||||
@champ.geo_areas = []
|
||||
elsif coordinates == ERROR_GEO_JSON
|
||||
if feature_collection == ERROR_GEO_JSON
|
||||
@error = true
|
||||
@champ.value = nil
|
||||
@champ.geo_areas = []
|
||||
else
|
||||
coordinates = JSON.parse(coordinates)
|
||||
feature_collection = JSON.parse(feature_collection, symbolize_names: true)
|
||||
|
||||
if @champ.cadastres?
|
||||
cadastres = ApiCartoService.generate_cadastre(coordinates)
|
||||
geo_areas += cadastres.map do |cadastre|
|
||||
cadastre[:source] = GeoArea.sources.fetch(:cadastre)
|
||||
cadastre
|
||||
end
|
||||
populate_cadastres(feature_collection)
|
||||
end
|
||||
|
||||
selections_utilisateur = legacy_selections_utilisateur_to_polygons(coordinates)
|
||||
geo_areas += selections_utilisateur.map do |selection_utilisateur|
|
||||
selection_utilisateur.merge(source: GeoArea.sources.fetch(:selection_utilisateur))
|
||||
end
|
||||
|
||||
@champ.geo_areas = geo_areas.map do |geo_area|
|
||||
GeoArea.new(geo_area)
|
||||
end
|
||||
|
||||
@champ.value = coordinates.to_json
|
||||
geo_areas = GeoArea.from_feature_collection(feature_collection)
|
||||
end
|
||||
|
||||
if @champ.persisted?
|
||||
@champ.save
|
||||
@champ.update(value: nil, geo_areas: geo_areas)
|
||||
end
|
||||
|
||||
rescue ApiCarto::API::ResourceNotFound
|
||||
flash.alert = 'Les données cartographiques sont temporairement indisponibles. Réessayez dans un instant.'
|
||||
response.status = 503
|
||||
|
@ -62,14 +42,23 @@ class Champs::CarteController < ApplicationController
|
|||
|
||||
private
|
||||
|
||||
def legacy_selections_utilisateur_to_polygons(coordinates)
|
||||
coordinates.map do |lat_longs|
|
||||
{
|
||||
geometry: {
|
||||
type: 'Polygon',
|
||||
coordinates: [lat_longs.map { |lat_long| [lat_long['lng'], lat_long['lat']] }]
|
||||
def populate_cadastres(feature_collection)
|
||||
coordinates = feature_collection[:features].filter do |feature|
|
||||
feature[:geometry][:type] == 'Polygon'
|
||||
end.map do |feature|
|
||||
feature[:geometry][:coordinates][0].map { |(lng, lat)| { 'lng' => lng, 'lat' => lat } }
|
||||
end
|
||||
|
||||
if coordinates.present?
|
||||
cadastres = ApiCartoService.generate_cadastre(coordinates)
|
||||
|
||||
feature_collection[:features] += cadastres.map do |cadastre|
|
||||
{
|
||||
type: 'Feature',
|
||||
geometry: cadastre.delete(:geometry),
|
||||
properties: cadastre.merge(source: GeoArea.sources.fetch(:cadastre))
|
||||
}
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
import L from 'leaflet';
|
||||
import FreeDraw from 'leaflet-freedraw';
|
||||
import area from '@turf/area';
|
||||
import { fire, delegate } from '@utils';
|
||||
import $ from 'jquery';
|
||||
|
||||
import polygonArea from './polygon_area';
|
||||
import createFeatureCollection from './create-feature-collection';
|
||||
|
||||
const MAPS = new WeakMap();
|
||||
|
||||
|
@ -81,13 +82,18 @@ function drawUserSelectionEditor(map, { selection }) {
|
|||
|
||||
export function addFreeDrawEvents(map, selector) {
|
||||
const input = findInput(selector);
|
||||
|
||||
map.freeDraw.on('markers', ({ latLngs }) => {
|
||||
if (latLngs.length === 0) {
|
||||
input.value = EMPTY_GEO_JSON;
|
||||
} else if (polygonArea(latLngs) < 300000) {
|
||||
input.value = JSON.stringify(latLngs);
|
||||
} else {
|
||||
input.value = ERROR_GEO_JSON;
|
||||
const featureCollection = createFeatureCollection(latLngs);
|
||||
|
||||
if (area(featureCollection) < 300000) {
|
||||
input.value = JSON.stringify(featureCollection);
|
||||
} else {
|
||||
input.value = ERROR_GEO_JSON;
|
||||
}
|
||||
}
|
||||
|
||||
fire(input, 'change');
|
||||
|
@ -121,7 +127,7 @@ function getCurrentMap(element) {
|
|||
}
|
||||
}
|
||||
|
||||
const EMPTY_GEO_JSON = '[]';
|
||||
const EMPTY_GEO_JSON = '{ "type": "FeatureCollection", "features": [] }';
|
||||
const ERROR_GEO_JSON = '';
|
||||
|
||||
function findInput(selector) {
|
||||
|
|
|
@ -1,16 +1,16 @@
|
|||
import area from '@turf/area';
|
||||
|
||||
export default function polygonArea(latLngs) {
|
||||
return area({
|
||||
export default function createFeatureCollection(latLngs) {
|
||||
return {
|
||||
type: 'FeatureCollection',
|
||||
features: latLngs.map(featurePolygonLatLngs)
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
function featurePolygonLatLngs(latLngs) {
|
||||
return {
|
||||
type: 'Feature',
|
||||
properties: {},
|
||||
properties: {
|
||||
source: 'selection_utilisateur'
|
||||
},
|
||||
geometry: {
|
||||
type: 'Polygon',
|
||||
coordinates: [latLngs.map(({ lng, lat }) => [lng, lat])]
|
|
@ -74,6 +74,7 @@ class Champs::CarteChamp < Champ
|
|||
def to_feature_collection
|
||||
{
|
||||
type: 'FeatureCollection',
|
||||
id: type_de_champ.stable_id,
|
||||
bbox: bounding_box,
|
||||
features: (legacy_selections_utilisateur + except_selections_utilisateur).map(&:to_feature)
|
||||
}
|
||||
|
|
|
@ -43,4 +43,14 @@ class GeoArea < ApplicationRecord
|
|||
def rgeo_geometry
|
||||
RGeo::GeoJSON.decode(geometry.to_json, geo_factory: RGeo::Geographic.simple_mercator_factory)
|
||||
end
|
||||
|
||||
def self.from_feature_collection(feature_collection)
|
||||
feature_collection[:features].map do |feature|
|
||||
GeoArea.new(
|
||||
source: feature[:properties].delete(:source),
|
||||
properties: feature[:properties],
|
||||
geometry: feature[:geometry]
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -5,3 +5,4 @@
|
|||
locals: { champ: @champ, error: @error }) %>
|
||||
|
||||
<%= fire_event('carte:update', { selector: @selector, data: @champ.to_render_data }.to_json) %>
|
||||
<%= fire_event('map:update', { featureCollection: @champ.to_feature_collection }.to_json) %>
|
||||
|
|
|
@ -36,7 +36,12 @@ describe Champs::CarteController, type: :controller do
|
|||
end
|
||||
|
||||
context 'when coordinates are empty' do
|
||||
let(:value) { '[]' }
|
||||
let(:value) do
|
||||
{
|
||||
type: 'FeatureCollection',
|
||||
features: []
|
||||
}.to_json
|
||||
end
|
||||
|
||||
it {
|
||||
expect(assigns(:error)).to eq(nil)
|
||||
|
@ -47,11 +52,26 @@ describe Champs::CarteController, type: :controller do
|
|||
end
|
||||
|
||||
context 'when coordinates are informed' do
|
||||
let(:value) { [[{ "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 }]].to_json }
|
||||
let(:value) do
|
||||
{
|
||||
type: 'FeatureCollection',
|
||||
features: [
|
||||
{
|
||||
type: 'Feature',
|
||||
properties: {
|
||||
source: 'selection_utilisateur'
|
||||
},
|
||||
geometry: { type: 'Polygon', coordinates: [[[2.3859214782714844, 48.87442541960633], [2.3850631713867183, 48.87273183590832], [2.3809432983398438, 48.87081237174292], [2.377510070800781, 48.8712640169951], [2.3859214782714844, 48.87442541960633]]] }
|
||||
}
|
||||
]
|
||||
}.to_json
|
||||
end
|
||||
|
||||
it { expect(response.body).not_to be_nil }
|
||||
it { expect(response.body).to include('MultiPolygon') }
|
||||
it { expect(response.body).to include('[2.38715792094576,48.8723062632126]') }
|
||||
it {
|
||||
expect(response.body).not_to be_nil
|
||||
expect(response.body).to include('MultiPolygon')
|
||||
expect(response.body).to include('[2.38715792094576,48.8723062632126]')
|
||||
}
|
||||
end
|
||||
|
||||
context 'when error' do
|
||||
|
@ -76,10 +96,25 @@ describe Champs::CarteController, type: :controller do
|
|||
post :show, params: params, format: 'js'
|
||||
end
|
||||
|
||||
let(:value) { [[{ "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 }]].to_json }
|
||||
let(:value) do
|
||||
{
|
||||
type: 'FeatureCollection',
|
||||
features: [
|
||||
{
|
||||
type: 'Feature',
|
||||
properties: {
|
||||
source: 'selection_utilisateur'
|
||||
},
|
||||
geometry: { type: 'Polygon', coordinates: [[[2.3859214782714844, 48.87442541960633], [2.3850631713867183, 48.87273183590832], [2.3809432983398438, 48.87081237174292], [2.377510070800781, 48.8712640169951], [2.3859214782714844, 48.87442541960633]]] }
|
||||
}
|
||||
]
|
||||
}.to_json
|
||||
end
|
||||
|
||||
it { expect(response.status).to eq 503 }
|
||||
it { expect(response.body).to include('Les données cartographiques sont temporairement indisponibles') }
|
||||
it {
|
||||
expect(response.status).to eq 503
|
||||
expect(response.body).to include('Les données cartographiques sont temporairement indisponibles')
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
describe Champs::CarteChamp do
|
||||
let(:champ) { Champs::CarteChamp.new(geo_areas: geo_areas) }
|
||||
let(:champ) { Champs::CarteChamp.new(geo_areas: geo_areas, type_de_champ: create(:type_de_champ_carte)) }
|
||||
let(:value) { '' }
|
||||
let(:coordinates) { [[2.3859214782714844, 48.87442541960633], [2.3850631713867183, 48.87273183590832], [2.3809432983398438, 48.87081237174292], [2.3859214782714844, 48.87442541960633]] }
|
||||
let(:geo_json) do
|
||||
|
@ -49,6 +49,7 @@ describe Champs::CarteChamp do
|
|||
let(:feature_collection) {
|
||||
{
|
||||
type: 'FeatureCollection',
|
||||
id: champ.type_de_champ.stable_id,
|
||||
bbox: champ.bounding_box,
|
||||
features: features
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue