From 05e408225b29b221cee5a05e078b7d44ae3b91be Mon Sep 17 00:00:00 2001 From: Paul Chavard Date: Tue, 5 May 2020 15:09:29 +0200 Subject: [PATCH 1/8] Implement atomic operations on MapEditor --- app/controllers/champs/carte_controller.rb | 71 +++++++++ .../components/MapEditor/MapEditor.js | 148 ++++++++---------- app/javascript/components/MapEditor/utils.js | 8 - app/javascript/shared/utils.js | 2 +- app/views/champs/carte/index.js.erb | 9 ++ app/views/champs/carte/show.js.erb | 6 +- .../dossiers/editable_champs/_carte.html.haml | 10 +- config/routes.rb | 6 + .../champs/carte_controller_spec.rb | 99 ++++++++++++ 9 files changed, 258 insertions(+), 101 deletions(-) create mode 100644 app/views/champs/carte/index.js.erb diff --git a/app/controllers/champs/carte_controller.rb b/app/controllers/champs/carte_controller.rb index 9a22d821a..6004c2676 100644 --- a/app/controllers/champs/carte_controller.rb +++ b/app/controllers/champs/carte_controller.rb @@ -40,6 +40,44 @@ class Champs::CarteController < ApplicationController response.status = 503 end + def index + @selector = ".carte-#{params[:champ_id]}" + @champ = policy_scope(Champ).find(params[:champ_id]) + @update_cadastres = params[:cadastres] + + if @champ.cadastres? && @update_cadastres + @champ.geo_areas.cadastres.destroy_all + @champ.geo_areas += GeoArea.from_feature_collection(cadastres_features_collection(@champ.to_feature_collection)) + @champ.save! + end + rescue ApiCarto::API::ResourceNotFound + flash.alert = 'Les données cartographiques sont temporairement indisponibles. Réessayez dans un instant.' + response.status = 503 + end + + def create + champ = policy_scope(Champ).find(params[:champ_id]) + geo_area = champ.geo_areas.selections_utilisateur.new + save_geometry!(geo_area) + + render json: { feature: geo_area.to_feature }, status: :created + end + + def update + champ = policy_scope(Champ).find(params[:champ_id]) + geo_area = champ.geo_areas.selections_utilisateur.find(params[:id]) + save_geometry!(geo_area) + + head :no_content + end + + def destroy + champ = policy_scope(Champ).find(params[:champ_id]) + champ.geo_areas.selections_utilisateur.find(params[:id]).destroy! + + head :no_content + end + private def populate_cadastres(feature_collection) @@ -61,4 +99,37 @@ class Champs::CarteController < ApplicationController end end end + + def save_geometry!(geo_area) + geo_area.geometry = params[:feature][:geometry] + geo_area.save! + end + + def cadastres_features_collection(feature_collection) + coordinates = feature_collection[:features].filter do |feature| + feature[:properties][:source] == GeoArea.sources.fetch(:selection_utilisateur) && 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) + + { + type: 'FeatureCollection', + features: cadastres.map do |cadastre| + { + type: 'Feature', + geometry: cadastre.delete(:geometry), + properties: cadastre.merge(source: GeoArea.sources.fetch(:cadastre)) + } + end + } + else + { + type: 'FeatureCollection', + features: [] + } + end + end end diff --git a/app/javascript/components/MapEditor/MapEditor.js b/app/javascript/components/MapEditor/MapEditor.js index 6a219fa62..56b33d08f 100644 --- a/app/javascript/components/MapEditor/MapEditor.js +++ b/app/javascript/components/MapEditor/MapEditor.js @@ -3,116 +3,99 @@ import PropTypes from 'prop-types'; import mapboxgl from 'mapbox-gl'; import ReactMapboxGl, { GeoJSONLayer, ZoomControl } from 'react-mapbox-gl'; import DrawControl from 'react-mapbox-gl-draw'; -import area from '@turf/area'; import SwitchMapStyle from './SwitchMapStyle'; import SearchInput from './SearchInput'; -import { fire } from '@utils'; +import { getJSON, ajax } from '@utils'; import ortho from './styles/ortho.json'; import vector from './styles/vector.json'; -import { - createFeatureCollection, - polygonCadastresFill, - polygonCadastresLine, - ERROR_GEO_JSON -} from './utils'; +import { polygonCadastresFill, polygonCadastresLine } from './utils'; import '@mapbox/mapbox-gl-draw/dist/mapbox-gl-draw.css'; const Map = ReactMapboxGl({}); -const MapEditor = ({ featureCollection: { features, bbox, id } }) => { +function filterFeatureCollection(featureCollection, source) { + return { + type: 'FeatureCollection', + features: featureCollection.features.filter( + feature => feature.properties.source === source + ) + }; +} + +const MapEditor = ({ featureCollection, url }) => { const drawControl = useRef(null); const [style, setStyle] = useState('ortho'); const [coords, setCoords] = useState([1.7, 46.9]); const [zoom, setZoom] = useState([5]); const [currentMap, setCurrentMap] = useState({}); - let input = document.querySelector( - `input[data-feature-collection-id="${id}"]` - ); - - let userSelections = features.filter( - feature => feature.properties.source === 'selection_utilisateur' - ); - - let cadastresFeatureCollection = { - type: 'FeatureCollection', - features: [] - }; - - const constructCadastresFeatureCollection = features => { - for (let feature of features) { - switch (feature.properties.source) { - case 'cadastre': - cadastresFeatureCollection.features.push(feature); - break; - } - } - }; - constructCadastresFeatureCollection(features); const mapStyle = style === 'ortho' ? ortho : vector; + const bbox = featureCollection.bbox; + const cadastresFeatureCollection = filterFeatureCollection( + featureCollection, + 'cadastre' + ); - const saveFeatureCollection = featuresToSave => { - const featuresCollection = createFeatureCollection(featuresToSave); - if (area(featuresCollection) < 300000) { - input.value = JSON.stringify(featuresCollection); - } else { - input.value = ERROR_GEO_JSON; - } - fire(input, 'change'); - }; - - const onDrawCreate = ({ features }) => { - const draw = drawControl.current.draw; - const featureId = features[0].id; - draw.setFeatureProperty(featureId, 'id', featureId); - draw.setFeatureProperty(featureId, 'source', 'selection_utilisateur'); - userSelections.push(draw.get(featureId)); - saveFeatureCollection(userSelections); - }; - - const onDrawUpdate = ({ features }) => { - let featureId = features[0].properties.id; - userSelections = userSelections.map(selection => { - if (selection.properties.id === featureId) { - selection = features[0]; - } - return selection; - }); - saveFeatureCollection(userSelections); - }; - - const onDrawDelete = ({ features }) => { - userSelections = userSelections.filter( - selection => selection.properties.id !== features[0].properties.id + function updateFeaturesList(features) { + const cadastres = features.find( + ({ geometry }) => geometry.type === 'Polygon' ); - saveFeatureCollection(userSelections); - }; + ajax({ url, type: 'get', data: cadastres ? 'cadastres=update' : '' }); + } + + function setFeatureId(lid, feature) { + const draw = drawControl.current.draw; + draw.setFeatureProperty(lid, 'id', feature.properties.id); + } + + async function onDrawCreate({ features }) { + for (const feature of features) { + const data = await getJSON(url, { feature }, 'post'); + setFeatureId(feature.id, data.feature); + } + + updateFeaturesList(features); + } + + async function onDrawUpdate({ features }) { + for (const feature of features) { + let { id } = feature.properties; + await getJSON(`${url}/${id}`, { feature }, 'patch'); + } + + updateFeaturesList(features); + } + + async function onDrawDelete({ features }) { + for (const feature of features) { + const { id } = feature.properties; + await getJSON(`${url}/${id}`, null, 'delete'); + } + + updateFeaturesList(features); + } const onMapLoad = map => { setCurrentMap(map); - if (userSelections.length > 0) { - userSelections.map((selection, index) => { - selection.properties.id = index + 1; - drawControl.current.draw.add(selection); - }); - } + + drawControl.current.draw.set( + filterFeatureCollection(featureCollection, 'selection_utilisateur') + ); }; - const onMapUpdate = evt => { + const onCadastresUpdate = evt => { if (currentMap) { - cadastresFeatureCollection.features = []; - constructCadastresFeatureCollection( - evt.detail.featureCollection.features - ); currentMap .getSource('cadastres-layer') - .setData(cadastresFeatureCollection); + .setData( + filterFeatureCollection(evt.detail.featureCollection, 'cadastre') + ); } }; useEffect(() => { - addEventListener('map:update', onMapUpdate); - return () => removeEventListener('map:update', onMapUpdate); + addEventListener('cadastres:update', onCadastresUpdate); + return () => removeEventListener('cadastres:update', onCadastresUpdate); }); if (!mapboxgl.supported()) { @@ -193,7 +176,8 @@ MapEditor.propTypes = { bbox: PropTypes.array, features: PropTypes.array, id: PropTypes.number - }) + }), + url: PropTypes.string }; export default MapEditor; diff --git a/app/javascript/components/MapEditor/utils.js b/app/javascript/components/MapEditor/utils.js index 9be234855..30311a836 100644 --- a/app/javascript/components/MapEditor/utils.js +++ b/app/javascript/components/MapEditor/utils.js @@ -1,11 +1,3 @@ -export const ERROR_GEO_JSON = ''; -export const createFeatureCollection = selectionsUtilisateur => { - return { - type: 'FeatureCollection', - features: selectionsUtilisateur - }; -}; - export const polygonCadastresFill = { 'fill-color': '#EC3323', 'fill-opacity': 0.3 diff --git a/app/javascript/shared/utils.js b/app/javascript/shared/utils.js index d360af45f..ac1d3246f 100644 --- a/app/javascript/shared/utils.js +++ b/app/javascript/shared/utils.js @@ -68,7 +68,7 @@ export function ajax(options) { } export function getJSON(url, data, method = 'get') { - data = method !== 'get' ? JSON.stringify(data) : data; + data = method !== 'get' && data ? JSON.stringify(data) : data; return Promise.resolve( $.ajax({ method, diff --git a/app/views/champs/carte/index.js.erb b/app/views/champs/carte/index.js.erb new file mode 100644 index 000000000..43157bbf2 --- /dev/null +++ b/app/views/champs/carte/index.js.erb @@ -0,0 +1,9 @@ +<%= render_flash(timeout: 5000, fixed: true) %> + +<%= render_to_element("#{@selector} + .geo-areas", + partial: 'shared/champs/carte/geo_areas', + locals: { champ: @champ, error: @error }) %> + +<% if @update_cadastres %> + <%= fire_event('cadastres:update', { featureCollection: @champ.to_feature_collection }.to_json) %> +<% end %> diff --git a/app/views/champs/carte/show.js.erb b/app/views/champs/carte/show.js.erb index f36252efc..7b80491fe 100644 --- a/app/views/champs/carte/show.js.erb +++ b/app/views/champs/carte/show.js.erb @@ -4,8 +4,4 @@ partial: 'shared/champs/carte/geo_areas', locals: { champ: @champ, error: @error }) %> -<% if feature_enabled?(:new_map_editor) %> - <%= fire_event('map:update', { featureCollection: @champ.to_feature_collection }.to_json) %> -<% else %> - <%= fire_event('carte:update', { selector: @selector, data: @champ.to_render_data }.to_json) %> -<% end %> +<%= fire_event('carte:update', { selector: @selector, data: @champ.to_render_data }.to_json) %> diff --git a/app/views/shared/dossiers/editable_champs/_carte.html.haml b/app/views/shared/dossiers/editable_champs/_carte.html.haml index c7c058056..4464306f9 100644 --- a/app/views/shared/dossiers/editable_champs/_carte.html.haml +++ b/app/views/shared/dossiers/editable_champs/_carte.html.haml @@ -1,13 +1,13 @@ - - if feature_enabled?(:new_map_editor) - = react_component("MapEditor", { featureCollection: champ.to_feature_collection }, class: "carte-#{form.index}") + = react_component("MapEditor", { featureCollection: champ.to_feature_collection, url: champs_carte_features_path(champ) }, class: "carte-#{champ.id}") - else .toolbar %button.button.primary.new-area Ajouter une zone %select.select2.adresse{ data: { address: true }, placeholder: 'Saisissez une adresse ou positionner la carte' } .carte.edit{ data: { geo: geo_data(champ) }, class: "carte-#{form.index}" } + + = form.hidden_field :value, + data: { remote: true, feature_collection_id: champ.stable_id, url: champs_carte_path(form.index), params: champ_carte_params(champ).to_query, method: 'post' } + .geo-areas = render partial: 'shared/champs/carte/geo_areas', locals: { champ: champ, error: false } - -= form.hidden_field :value, - data: { remote: true, feature_collection_id: champ.stable_id, url: champs_carte_path(form.index), params: champ_carte_params(champ).to_query, method: 'post' } diff --git a/config/routes.rb b/config/routes.rb index c84893b20..0595c6014 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -120,6 +120,12 @@ Rails.application.routes.draw do get ':position/siret', to: 'siret#show', as: :siret get ':position/dossier_link', to: 'dossier_link#show', as: :dossier_link post ':position/carte', to: 'carte#show', as: :carte + + get ':champ_id/carte/features', to: 'carte#index', as: :carte_features + post ':champ_id/carte/features', to: 'carte#create' + patch ':champ_id/carte/features/:id', to: 'carte#update' + delete ':champ_id/carte/features/:id', to: 'carte#destroy' + post ':position/repetition', to: 'repetition#show', as: :repetition put 'piece_justificative/:champ_id', to: 'piece_justificative#update', as: :piece_justificative end diff --git a/spec/controllers/champs/carte_controller_spec.rb b/spec/controllers/champs/carte_controller_spec.rb index 69493fd05..14173e150 100644 --- a/spec/controllers/champs/carte_controller_spec.rb +++ b/spec/controllers/champs/carte_controller_spec.rb @@ -18,6 +18,105 @@ describe Champs::CarteController, type: :controller do cadastres: true }).champ.create(dossier: dossier) end + describe 'features' do + let(:feature) { attributes_for(:geo_area, :polygon) } + let(:geo_area) { create(:geo_area, :selection_utilisateur, :polygon, champ: champ) } + let(:params) do + { + champ_id: champ.id, + feature: feature + } + end + + before do + sign_in user + request.accept = "application/json" + request.content_type = "application/json" + end + + describe 'POST #create' do + before do + post :create, params: params + end + + it { expect(response.status).to eq 201 } + end + + describe 'PATCH #update' do + let(:params) do + { + champ_id: champ.id, + id: geo_area.id, + feature: feature + } + end + + before do + patch :update, params: params + end + + it { expect(response.status).to eq 204 } + end + + describe 'DELETE #destroy' do + let(:params) do + { + champ_id: champ.id, + id: geo_area.id + } + end + + before do + delete :destroy, params: params + end + + it { expect(response.status).to eq 204 } + end + + describe 'GET #index' do + render_views + + before do + request.accept = "application/javascript" + request.content_type = "application/javascript" + end + + context 'with cadastres update' do + let(:params) do + { + champ_id: champ.id, + cadastres: 'update' + } + end + + before do + get :index, params: params + end + + it { + expect(response.status).to eq 200 + expect(response.body).to include("DS.fire('cadastres:update'") + } + end + + context 'without cadastres update' do + let(:params) do + { + champ_id: champ.id + } + end + + before do + get :index, params: params + end + + it { + expect(response.status).to eq 200 + expect(response.body).not_to include("DS.fire('cadastres:update'") + } + end + end + end describe 'POST #show' do render_views From 10a21f9010f5e5b5c008992c591430c67f09ec86 Mon Sep 17 00:00:00 2001 From: Christophe Robillard Date: Wed, 6 May 2020 15:06:04 +0200 Subject: [PATCH 2/8] expose attestationSocialeAttachment and attestationFiscaleAttachment --- app/graphql/schema.graphql | 2 ++ app/graphql/types/personne_morale_type.rb | 19 +++++++++++++++++++ app/models/entreprise.rb | 1 + app/models/etablissement.rb | 1 + 4 files changed, 23 insertions(+) diff --git a/app/graphql/schema.graphql b/app/graphql/schema.graphql index c1dea88f4..6106c8107 100644 --- a/app/graphql/schema.graphql +++ b/app/graphql/schema.graphql @@ -692,6 +692,8 @@ type Effectif { } type Entreprise { + attestationFiscaleAttachment: File + attestationSocialeAttachment: File capitalSocial: BigInt! codeEffectifEntreprise: String! dateCreation: ISO8601Date! diff --git a/app/graphql/types/personne_morale_type.rb b/app/graphql/types/personne_morale_type.rb index 627145cb0..769554ce6 100644 --- a/app/graphql/types/personne_morale_type.rb +++ b/app/graphql/types/personne_morale_type.rb @@ -21,6 +21,16 @@ module Types field :nom, String, null: false field :prenom, String, null: false field :inline_adresse, String, null: false + field :attestation_sociale_attachment, Types::File, null: true + field :attestation_fiscale_attachment, Types::File, null: true + + def attestation_sociale_attachment + load_attachment_for(:entreprise_attestation_sociale_attachment) + end + + def attestation_fiscale_attachment + load_attachment_for(:entreprise_attestation_fiscale_attachment) + end def effectif_mensuel if object.effectif_mensuel.present? @@ -39,6 +49,15 @@ module Types } end end + + private + + def load_attachment_for(key) + Loaders::Association.for( + Etablissement, + key => :blob + ).load(object.etablissement) + end end class AssociationType < Types::BaseObject diff --git a/app/models/entreprise.rb b/app/models/entreprise.rb index 5808b91e9..3b471cbaf 100644 --- a/app/models/entreprise.rb +++ b/app/models/entreprise.rb @@ -3,6 +3,7 @@ class Entreprise < Hashie::Dash self[attribute] end + property :etablissement property :siren property :capital_social property :numero_tva_intracommunautaire diff --git a/app/models/etablissement.rb b/app/models/etablissement.rb index 50585c6a2..8dce7b4fa 100644 --- a/app/models/etablissement.rb +++ b/app/models/etablissement.rb @@ -96,6 +96,7 @@ class Etablissement < ApplicationRecord def entreprise Entreprise.new( + etablissement: self, siren: entreprise_siren, capital_social: entreprise_capital_social, numero_tva_intracommunautaire: entreprise_numero_tva_intracommunautaire, From 5a27629ee91c47c1a3b15dca64debcc67d0dc431 Mon Sep 17 00:00:00 2001 From: Christophe Robillard Date: Wed, 6 May 2020 17:09:48 +0200 Subject: [PATCH 3/8] add effectifs in instructeur dossier pdf export --- app/views/dossiers/show.pdf.prawn | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/app/views/dossiers/show.pdf.prawn b/app/views/dossiers/show.pdf.prawn index 29343bb26..50f9b7431 100644 --- a/app/views/dossiers/show.pdf.prawn +++ b/app/views/dossiers/show.pdf.prawn @@ -57,7 +57,11 @@ def render_identite_etablissement(pdf, etablissement) pdf.text " - Libellé NAF : #{etablissement.libelle_naf}" pdf.text " - Code NAF : #{etablissement.naf}" pdf.text " - Date de création : #{try_format_date(etablissement.entreprise.date_creation)}" - pdf.text " - Effectif de l'organisation : #{effectif(etablissement)}" + if @include_infos_administration + pdf.text " - Effectif mensuel #{try_format_mois_effectif(etablissement)} (URSSAF) : #{etablissement.entreprise_effectif_mensuel}" + pdf.text " - Effectif moyen annuel #{etablissement.entreprise_effectif_annuel_annee} (URSSAF) : #{etablissement.entreprise_effectif_annuel}" + end + pdf.text " - Effectif de l'organisation (INSEE) : #{effectif(etablissement)}" pdf.text " - Code effectif : #{etablissement.entreprise.code_effectif_entreprise}" pdf.text " - Numéro de TVA intracommunautaire : #{etablissement.entreprise.numero_tva_intracommunautaire}" pdf.text " - Adresse : #{etablissement.adresse}" From 36f381a743ca2c04535cc4cd8e5f4bf1868d5453 Mon Sep 17 00:00:00 2001 From: clemkeirua Date: Thu, 7 May 2020 10:19:57 +0200 Subject: [PATCH 4/8] fix flacky test --- spec/services/dossier_search_service_spec.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spec/services/dossier_search_service_spec.rb b/spec/services/dossier_search_service_spec.rb index 16d613acc..52f855c27 100644 --- a/spec/services/dossier_search_service_spec.rb +++ b/spec/services/dossier_search_service_spec.rb @@ -133,13 +133,13 @@ describe DossierSearchService do context 'when the user owns the dossier' do let(:terms) { dossier_0.id.to_s } - it { expect(subject.size).to eq(1) } + it { expect(subject.map(&:id)).to include(dossier_0.id) } end context 'when the user does not own the dossier' do let(:terms) { dossier_0b.id.to_s } - it { expect(subject.size).to eq(0) } + it { expect(subject.map(&:id)).not_to include(dossier_0b.id) } end end From 4f2e504cc2ceb3526a3b00e3a5ed9630f9444727 Mon Sep 17 00:00:00 2001 From: Paul Chavard Date: Thu, 7 May 2020 12:06:42 +0200 Subject: [PATCH 5/8] Add carto import api takes a FeatureCollection to import and returns an augmented champ FeatureCollection --- app/controllers/champs/carte_controller.rb | 26 ++++++++++++++++--- config/routes.rb | 1 + .../champs/carte_controller_spec.rb | 22 ++++++++++++++++ 3 files changed, 45 insertions(+), 4 deletions(-) diff --git a/app/controllers/champs/carte_controller.rb b/app/controllers/champs/carte_controller.rb index 6004c2676..1ff5980c6 100644 --- a/app/controllers/champs/carte_controller.rb +++ b/app/controllers/champs/carte_controller.rb @@ -58,7 +58,7 @@ class Champs::CarteController < ApplicationController def create champ = policy_scope(Champ).find(params[:champ_id]) geo_area = champ.geo_areas.selections_utilisateur.new - save_geometry!(geo_area) + save_geometry!(geo_area, params_feature) render json: { feature: geo_area.to_feature }, status: :created end @@ -66,7 +66,7 @@ class Champs::CarteController < ApplicationController def update champ = policy_scope(Champ).find(params[:champ_id]) geo_area = champ.geo_areas.selections_utilisateur.find(params[:id]) - save_geometry!(geo_area) + save_geometry!(geo_area, params_feature) head :no_content end @@ -78,6 +78,16 @@ class Champs::CarteController < ApplicationController head :no_content end + def import + champ = policy_scope(Champ).find(params[:champ_id]) + params_features.each do |feature| + geo_area = champ.geo_areas.selections_utilisateur.new + save_geometry!(geo_area, feature) + end + + render json: champ.to_feature_collection, status: :created + end + private def populate_cadastres(feature_collection) @@ -100,8 +110,16 @@ class Champs::CarteController < ApplicationController end end - def save_geometry!(geo_area) - geo_area.geometry = params[:feature][:geometry] + def params_feature + params[:feature] + end + + def params_features + params[:feature_collection][:features] + end + + def save_geometry!(geo_area, feature) + geo_area.geometry = feature[:geometry] geo_area.save! end diff --git a/config/routes.rb b/config/routes.rb index 0595c6014..b77856f98 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -123,6 +123,7 @@ Rails.application.routes.draw do get ':champ_id/carte/features', to: 'carte#index', as: :carte_features post ':champ_id/carte/features', to: 'carte#create' + post ':champ_id/carte/features/import', to: 'carte#import' patch ':champ_id/carte/features/:id', to: 'carte#update' delete ':champ_id/carte/features/:id', to: 'carte#destroy' diff --git a/spec/controllers/champs/carte_controller_spec.rb b/spec/controllers/champs/carte_controller_spec.rb index 14173e150..2e39bc637 100644 --- a/spec/controllers/champs/carte_controller_spec.rb +++ b/spec/controllers/champs/carte_controller_spec.rb @@ -73,6 +73,28 @@ describe Champs::CarteController, type: :controller do it { expect(response.status).to eq 204 } end + describe 'POST #import' do + render_views + + let(:params) do + { + champ_id: champ.id, + feature_collection: { + features: [feature] + } + } + end + + before do + post :import, params: params + end + + it { + expect(response.status).to eq 201 + expect(response.body).to include("bbox") + } + end + describe 'GET #index' do render_views From 1cc04092f489c390217c7c0c5a35e8a720301123 Mon Sep 17 00:00:00 2001 From: kara Diaby Date: Thu, 7 May 2020 18:30:19 +0200 Subject: [PATCH 6/8] import GPX file in browser [Carto] --- app/controllers/champs/carte_controller.rb | 2 +- .../components/MapEditor/MapEditor.js | 37 ++++++++++++++++++- .../components/MapEditor/SearchInput.js | 2 +- package.json | 1 + .../champs/carte_controller_spec.rb | 5 +-- yarn.lock | 5 +++ 6 files changed, 45 insertions(+), 7 deletions(-) diff --git a/app/controllers/champs/carte_controller.rb b/app/controllers/champs/carte_controller.rb index 1ff5980c6..84f5de313 100644 --- a/app/controllers/champs/carte_controller.rb +++ b/app/controllers/champs/carte_controller.rb @@ -115,7 +115,7 @@ class Champs::CarteController < ApplicationController end def params_features - params[:feature_collection][:features] + params[:features] end def save_geometry!(geo_area, feature) diff --git a/app/javascript/components/MapEditor/MapEditor.js b/app/javascript/components/MapEditor/MapEditor.js index 56b33d08f..904cb8c05 100644 --- a/app/javascript/components/MapEditor/MapEditor.js +++ b/app/javascript/components/MapEditor/MapEditor.js @@ -6,6 +6,7 @@ import DrawControl from 'react-mapbox-gl-draw'; import SwitchMapStyle from './SwitchMapStyle'; import SearchInput from './SearchInput'; import { getJSON, ajax } from '@utils'; +import { gpx } from '@tmcw/togeojson/dist/togeojson.es.js'; import ortho from './styles/ortho.json'; import vector from './styles/vector.json'; import { polygonCadastresFill, polygonCadastresLine } from './utils'; @@ -28,9 +29,8 @@ const MapEditor = ({ featureCollection, url }) => { const [coords, setCoords] = useState([1.7, 46.9]); const [zoom, setZoom] = useState([5]); const [currentMap, setCurrentMap] = useState({}); - + const [bbox, setBbox] = useState(featureCollection.bbox); const mapStyle = style === 'ortho' ? ortho : vector; - const bbox = featureCollection.bbox; const cadastresFeatureCollection = filterFeatureCollection( featureCollection, 'cadastre' @@ -93,6 +93,29 @@ const MapEditor = ({ featureCollection, url }) => { } }; + const onGpxImport = e => { + let reader = new FileReader(); + reader.readAsText(e.target.files[0], 'UTF-8'); + reader.onload = async event => { + const featureCollection = gpx( + new DOMParser().parseFromString(event.target.result, 'text/xml') + ); + const resultFeatureCollection = await getJSON( + `${url}/import`, + featureCollection, + 'post' + ); + drawControl.current.draw.set( + filterFeatureCollection( + resultFeatureCollection, + 'selection_utilisateur' + ) + ); + updateFeaturesList(resultFeatureCollection.features); + setBbox(resultFeatureCollection.bbox); + }; + }; + useEffect(() => { addEventListener('cadastres:update', onCadastresUpdate); return () => removeEventListener('cadastres:update', onCadastresUpdate); @@ -110,6 +133,16 @@ const MapEditor = ({ featureCollection, url }) => { return ( <> +
+
+

+ Importer un fichier GPX +

+
+
+ +
+
{ return ( Date: Mon, 11 May 2020 10:27:09 +0200 Subject: [PATCH 7/8] fix bilans bdf link --- app/views/shared/dossiers/_identite_entreprise.html.haml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/shared/dossiers/_identite_entreprise.html.haml b/app/views/shared/dossiers/_identite_entreprise.html.haml index 714769597..298123b86 100644 --- a/app/views/shared/dossiers/_identite_entreprise.html.haml +++ b/app/views/shared/dossiers/_identite_entreprise.html.haml @@ -83,7 +83,7 @@ %th.libelle Bilans Banque de France = "en #{etablissement.entreprise_bilans_bdf_monnaie}" - %td= link_to "Consulter les bilans", bilans_bdf_instructeur_dossier_path + %td= link_to "Consulter les bilans", bilans_bdf_instructeur_dossier_path(procedure_id: @dossier.procedure.id, dossier_id: @dossier.id) - if etablissement.association? %tr From aab4bb81ee87ae1cd0d6854c4b7dc201983ba387 Mon Sep 17 00:00:00 2001 From: Christophe Robillard Date: Mon, 11 May 2020 12:55:59 +0200 Subject: [PATCH 8/8] return bilan bdf csv for expert --- app/controllers/instructeurs/avis_controller.rb | 8 ++++++++ app/views/shared/dossiers/_identite_entreprise.html.haml | 5 ++++- config/routes.rb | 1 + spec/controllers/instructeurs/avis_controller_spec.rb | 6 ++++++ 4 files changed, 19 insertions(+), 1 deletion(-) diff --git a/app/controllers/instructeurs/avis_controller.rb b/app/controllers/instructeurs/avis_controller.rb index 5e2e0c8a8..d213beac7 100644 --- a/app/controllers/instructeurs/avis_controller.rb +++ b/app/controllers/instructeurs/avis_controller.rb @@ -72,6 +72,14 @@ module Instructeurs end end + def bilans_bdf + if avis.dossier.etablissement&.entreprise_bilans_bdf_to_csv.present? + render csv: avis.dossier.etablissement.entreprise_bilans_bdf_to_csv + else + redirect_to instructeur_avis_path(avis) + end + end + def sign_up @email = params[:email] @dossier = Avis.includes(:dossier).find(params[:id]).dossier diff --git a/app/views/shared/dossiers/_identite_entreprise.html.haml b/app/views/shared/dossiers/_identite_entreprise.html.haml index 298123b86..b22f27335 100644 --- a/app/views/shared/dossiers/_identite_entreprise.html.haml +++ b/app/views/shared/dossiers/_identite_entreprise.html.haml @@ -83,7 +83,10 @@ %th.libelle Bilans Banque de France = "en #{etablissement.entreprise_bilans_bdf_monnaie}" - %td= link_to "Consulter les bilans", bilans_bdf_instructeur_dossier_path(procedure_id: @dossier.procedure.id, dossier_id: @dossier.id) + - if controller.is_a?(Instructeurs::AvisController) + %td= link_to "Consulter les bilans", bilans_bdf_instructeur_avis_path(@avis.id) + - else + %td= link_to "Consulter les bilans", bilans_bdf_instructeur_dossier_path(procedure_id: @dossier.procedure.id, dossier_id: @dossier.id) - if etablissement.association? %tr diff --git a/config/routes.rb b/config/routes.rb index b77856f98..bdbcc31a3 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -354,6 +354,7 @@ Rails.application.routes.draw do get 'messagerie' post 'commentaire' => 'avis#create_commentaire' post 'avis' => 'avis#create_avis' + get 'bilans_bdf' get 'sign_up/email/:email' => 'avis#sign_up', constraints: { email: /.*/ }, as: 'sign_up' post 'sign_up/email/:email' => 'avis#create_instructeur', constraints: { email: /.*/ } diff --git a/spec/controllers/instructeurs/avis_controller_spec.rb b/spec/controllers/instructeurs/avis_controller_spec.rb index 52c1f5d5d..c4d4462cb 100644 --- a/spec/controllers/instructeurs/avis_controller_spec.rb +++ b/spec/controllers/instructeurs/avis_controller_spec.rb @@ -50,6 +50,12 @@ describe Instructeurs::AvisController, type: :controller do it { expect(assigns(:dossier)).to eq(dossier) } end + describe '#bilans_bdf' do + before { get :bilans_bdf, params: { id: avis_without_answer.id } } + + it { expect(response).to redirect_to(instructeur_avis_path(avis_without_answer)) } + end + describe '#update' do describe 'without attachment' do before do