diff --git a/app/controllers/new_administrateur/types_de_champ_controller.rb b/app/controllers/new_administrateur/types_de_champ_controller.rb index ea7023757..655950b0a 100644 --- a/app/controllers/new_administrateur/types_de_champ_controller.rb +++ b/app/controllers/new_administrateur/types_de_champ_controller.rb @@ -56,30 +56,27 @@ module NewAdministrateur :updated_at ], methods: [ - :cadastres, :drop_down_list_value, - :parcelles_agricoles, :piece_justificative_template_filename, :piece_justificative_template_url, - :quartiers_prioritaires + :cadastres, + :mnhn ] ) } end def type_de_champ_create_params - type_de_champ_params = params.required(:type_de_champ).permit(:cadastres, - :description, - :drop_down_list_value, + type_de_champ_params = params.required(:type_de_champ).permit(:type_champ, :libelle, + :description, :mandatory, - :order_place, - :parcelles_agricoles, :parent_id, - :piece_justificative_template, :private, - :quartiers_prioritaires, - :type_champ) + :drop_down_list_value, + :piece_justificative_template, + :cadastres, + :mnhn) if type_de_champ_params[:parent_id].present? type_de_champ_params[:parent_id] = TypeDeChamp.to_stable_id(type_de_champ_params[:parent_id]) @@ -89,15 +86,14 @@ module NewAdministrateur end def type_de_champ_update_params - params.required(:type_de_champ).permit(:cadastres, - :description, - :drop_down_list_value, + params.required(:type_de_champ).permit(:type_champ, :libelle, + :description, :mandatory, - :parcelles_agricoles, + :drop_down_list_value, :piece_justificative_template, - :quartiers_prioritaires, - :type_champ) + :cadastres, + :mnhn) end end end diff --git a/app/javascript/components/MapEditor/index.js b/app/javascript/components/MapEditor/index.js index c8bb44555..c025f5fb3 100644 --- a/app/javascript/components/MapEditor/index.js +++ b/app/javascript/components/MapEditor/index.js @@ -23,7 +23,7 @@ import { const Map = ReactMapboxGl({}); -function MapEditor({ featureCollection, url, preview, hasCadastres, ign }) { +function MapEditor({ featureCollection, url, preview, options }) { const drawControl = useRef(null); const [currentMap, setCurrentMap] = useState(null); @@ -35,10 +35,10 @@ function MapEditor({ featureCollection, url, preview, hasCadastres, ign }) { const [cadastresFeatureCollection, setCadastresFeatureCollection] = useState( filterFeatureCollection(featureCollection, 'cadastre') ); - const mapStyle = useMemo(() => getMapStyle(style, hasCadastres), [ - style, - hasCadastres - ]); + const mapStyle = useMemo( + () => getMapStyle(style, options.cadastres, options.mnhn), + [style, options] + ); const translations = [ ['.mapbox-gl-draw_line', 'Tracer une ligne'], @@ -306,7 +306,7 @@ function MapEditor({ featureCollection, url, preview, hasCadastres, ign }) { height: '500px' }} > - {hasCadastres ? ( + {options.cadastres ? ( - + @@ -341,8 +341,11 @@ MapEditor.propTypes = { }), url: PropTypes.string, preview: PropTypes.bool, - hasCadastres: PropTypes.bool, - ign: PropTypes.bool + options: PropTypes.shape({ + cadastres: PropTypes.bool, + mnhn: PropTypes.bool, + ign: PropTypes.bool + }) }; export default MapEditor; diff --git a/app/javascript/components/MapReader/index.js b/app/javascript/components/MapReader/index.js index 4386ba77f..48c86a7ef 100644 --- a/app/javascript/components/MapReader/index.js +++ b/app/javascript/components/MapReader/index.js @@ -16,7 +16,7 @@ import { const Map = ReactMapboxGl({}); -const MapReader = ({ featureCollection, ign }) => { +const MapReader = ({ featureCollection, options }) => { const [currentMap, setCurrentMap] = useState(null); const [style, setStyle] = useState('ortho'); const cadastresFeatureCollection = useMemo( @@ -52,10 +52,10 @@ const MapReader = ({ featureCollection, ign }) => { [selectionsUtilisateurFeatureCollection] ); const hasCadastres = !!cadastresFeatureCollection.length; - const mapStyle = useMemo(() => getMapStyle(style, hasCadastres), [ - style, - cadastresFeatureCollection - ]); + const mapStyle = useMemo( + () => getMapStyle(style, hasCadastres, options.mnhn), + [style, options, cadastresFeatureCollection] + ); const popup = useMemo( () => new Popup({ @@ -184,7 +184,7 @@ const MapReader = ({ featureCollection, ign }) => { /> ) : null} - + ); @@ -196,7 +196,10 @@ MapReader.propTypes = { bbox: PropTypes.array, features: PropTypes.array }), - ign: PropTypes.bool + options: PropTypes.shape({ + ign: PropTypes.bool, + mnhn: PropTypes.bool + }) }; export default MapReader; diff --git a/app/javascript/components/MapStyles/base-style.js b/app/javascript/components/MapStyles/base-style.js index 8a8ab876c..1443e4500 100644 --- a/app/javascript/components/MapStyles/base-style.js +++ b/app/javascript/components/MapStyles/base-style.js @@ -1,15 +1,36 @@ +const IGN_TOKEN = 'rc1egnbeoss72hxvd143tbyk'; + +function ignServiceURL(layer, format = 'image/png') { + const url = `https://wxs.ign.fr/${IGN_TOKEN}/geoportail/wmts`; + const query = + 'service=WMTS&request=GetTile&version=1.0.0&tilematrixset=PM&tilematrix={z}&tilecol={x}&tilerow={y}&style=normal'; + + return `${url}?${query}&layer=${layer}&format=${format}`; +} + +function rasterSource(tiles, attribution) { + return { + type: 'raster', + tiles, + tileSize: 256, + attribution, + minzoom: 0, + maxzoom: 18 + }; +} + export default { version: 8, metadat: { 'mapbox:autocomposite': false, 'mapbox:groups': { - '1444849242106.713': { collapsed: false, name: 'Places' }, - '1444849334699.1902': { collapsed: true, name: 'Bridges' }, - '1444849345966.4436': { collapsed: false, name: 'Roads' }, - '1444849354174.1904': { collapsed: true, name: 'Tunnels' }, - '1444849364238.8171': { collapsed: false, name: 'Buildings' }, - '1444849382550.77': { collapsed: false, name: 'Water' }, - '1444849388993.3071': { collapsed: false, name: 'Land' } + 1444849242106.713: { collapsed: false, name: 'Places' }, + 1444849334699.1902: { collapsed: true, name: 'Bridges' }, + 1444849345966.4436: { collapsed: false, name: 'Roads' }, + 1444849354174.1904: { collapsed: true, name: 'Tunnels' }, + 1444849364238.8171: { collapsed: false, name: 'Buildings' }, + 1444849382550.77: { collapsed: false, name: 'Water' }, + 1444849388993.3071: { collapsed: false, name: 'Land' } }, 'mapbox:type': 'template', 'openmaptiles:mapbox:owner': 'openmaptiles', @@ -41,20 +62,34 @@ export default { minzoom: 0, maxzoom: 19 }, - 'carte-ign': { - type: 'raster', - tiles: [ - 'https://wxs.ign.fr/rc1egnbeoss72hxvd143tbyk/geoportail/wmts?service=WMTS&request=GetTile&version=1.0.0&tilematrixset=PM&tilematrix={z}&tilecol={x}&tilerow={y}&layer=GEOGRAPHICALGRIDSYSTEMS.MAPS&format=image/jpeg&style=normal' - ], - tileSize: 256, - attribution: 'IGN-F/Géoportail', - minzoom: 0, - maxzoom: 18 - }, cadastre: { type: 'vector', url: 'https://openmaptiles.geo.data.gouv.fr/data/cadastre.json' - } + }, + 'plan-ign': rasterSource( + [ignServiceURL('GEOGRAPHICALGRIDSYSTEMS.PLANIGNV2')], + 'IGN-F/Géoportail' + ), + 'protectedareas-gp': rasterSource( + [ignServiceURL('PROTECTEDAREAS.GP')], + 'IGN-F/Géoportail/MNHN' + ), + 'protectedareas-pn': rasterSource( + [ignServiceURL('PROTECTEDAREAS.PN')], + 'IGN-F/Géoportail/MNHN' + ), + 'protectedareas-pnr': rasterSource( + [ignServiceURL('PROTECTEDAREAS.PNR')], + 'IGN-F/Géoportail/MNHN' + ), + 'protectedareas-sic': rasterSource( + [ignServiceURL('PROTECTEDAREAS.SIC')], + 'IGN-F/Géoportail/MNHN' + ), + 'protectedareas-zps': rasterSource( + [ignServiceURL('PROTECTEDAREAS.ZPS')], + 'IGN-F/Géoportail/MNHN' + ) }, sprite: 'https://openmaptiles.github.io/osm-bright-gl-style/sprite', glyphs: 'https://openmaptiles.geo.data.gouv.fr/fonts/{fontstack}/{range}.pbf' diff --git a/app/javascript/components/MapStyles/index.js b/app/javascript/components/MapStyles/index.js index 68298a73e..4122f0ef5 100644 --- a/app/javascript/components/MapStyles/index.js +++ b/app/javascript/components/MapStyles/index.js @@ -3,16 +3,16 @@ import cadastre from './cadastre'; import orthoStyle from './ortho-style'; import vectorStyle from './vector-style'; -const ignStyle = [ - { - id: 'carte-ign', +function rasterStyle(source) { + return { + id: source, + source, type: 'raster', - source: 'carte-ign', paint: { 'raster-resampling': 'linear' } - } -]; + }; +} -export function getMapStyle(style, hasCadastres) { +export function getMapStyle(style, hasCadastres, hasMNHN) { const mapStyle = { ...baseStyle }; switch (style) { @@ -27,7 +27,7 @@ export function getMapStyle(style, hasCadastres) { mapStyle.name = 'Carte OSM'; break; case 'ign': - mapStyle.layers = ignStyle; + mapStyle.layers = [rasterStyle('plan-ign')]; mapStyle.id = 'ign'; mapStyle.name = 'Carte IGN'; break; @@ -38,6 +38,17 @@ export function getMapStyle(style, hasCadastres) { mapStyle.id += '-cadastre'; } + if (hasMNHN) { + mapStyle.layers = mapStyle.layers.concat([ + rasterStyle('protectedareas-gp'), + rasterStyle('protectedareas-pn'), + rasterStyle('protectedareas-pnr'), + rasterStyle('protectedareas-sic'), + rasterStyle('protectedareas-zps') + ]); + mapStyle.id += '-mnhn'; + } + return mapStyle; } diff --git a/app/javascript/components/TypesDeChampEditor/components/TypeDeChamp.js b/app/javascript/components/TypesDeChampEditor/components/TypeDeChamp.js index 6d68ffbe1..57131402b 100644 --- a/app/javascript/components/TypesDeChampEditor/components/TypeDeChamp.js +++ b/app/javascript/components/TypesDeChampEditor/components/TypeDeChamp.js @@ -140,6 +140,10 @@ const TypeDeChamp = sortableElement( label="Cadastres" handler={updateHandlers.cadastres} /> + { ordered }, foreign_key: :parent_id, class_name: 'TypeDeChamp', inverse_of: :parent, dependent: :destroy - store_accessor :options, :cadastres, :quartiers_prioritaires, :parcelles_agricoles, :old_pj, :drop_down_options, :skip_pj_validation + store_accessor :options, :cadastres, :quartiers_prioritaires, :parcelles_agricoles, :mnhn, :old_pj, :drop_down_options, :skip_pj_validation has_many :revision_types_de_champ, class_name: 'ProcedureRevisionTypeDeChamp', dependent: :destroy, inverse_of: :type_de_champ delegate :tags_for_template, to: :dynamic_type @@ -286,12 +286,11 @@ class TypeDeChamp < ApplicationRecord :updated_at ], methods: [ - :cadastres, :drop_down_list_value, - :parcelles_agricoles, :piece_justificative_template_filename, :piece_justificative_template_url, - :quartiers_prioritaires + :cadastres, + :mnhn ] } TYPES_DE_CHAMP = TYPES_DE_CHAMP_BASE diff --git a/app/views/shared/champs/carte/_show.html.haml b/app/views/shared/champs/carte/_show.html.haml index b3f2a50d0..a4fbda3eb 100644 --- a/app/views/shared/champs/carte/_show.html.haml +++ b/app/views/shared/champs/carte/_show.html.haml @@ -1,4 +1,4 @@ - if champ.geometry? - = react_component("MapReader", { featureCollection: champ.to_feature_collection, ign: feature_enabled_for?(:carte_ign, champ.procedure) } ) + = react_component("MapReader", { featureCollection: champ.to_feature_collection, options: champ.render_options } ) .geo-areas = render partial: 'shared/champs/carte/geo_areas', locals: { champ: champ, editing: false } diff --git a/app/views/shared/dossiers/editable_champs/_carte.html.haml b/app/views/shared/dossiers/editable_champs/_carte.html.haml index 720ecde88..6865a8dd1 100644 --- a/app/views/shared/dossiers/editable_champs/_carte.html.haml +++ b/app/views/shared/dossiers/editable_champs/_carte.html.haml @@ -1,5 +1,6 @@ - preview = !champ.persisted? -= react_component("MapEditor", { featureCollection: champ.to_feature_collection, url: champs_carte_features_path(preview ? 'preview' : champ), preview: preview, hasCadastres: !!champ.cadastres?, ign: feature_enabled_for?(:carte_ign, champ.procedure) }, class: "carte-#{champ.id}") +- url = champs_carte_features_path(preview ? 'preview' : champ) += react_component("MapEditor", { featureCollection: champ.to_feature_collection, url: url, preview: preview, options: champ.render_options }, class: "carte-#{champ.id}") .geo-areas = render partial: 'shared/champs/carte/geo_areas', locals: { champ: champ, editing: true }