commit
aef465f908
88 changed files with 3139 additions and 2424 deletions
|
@ -59,8 +59,7 @@ module NewAdministrateur
|
||||||
:drop_down_list_value,
|
:drop_down_list_value,
|
||||||
:piece_justificative_template_filename,
|
:piece_justificative_template_filename,
|
||||||
:piece_justificative_template_url,
|
:piece_justificative_template_url,
|
||||||
:cadastres,
|
:editable_options
|
||||||
:mnhn
|
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -75,8 +74,18 @@ module NewAdministrateur
|
||||||
:private,
|
:private,
|
||||||
:drop_down_list_value,
|
:drop_down_list_value,
|
||||||
:piece_justificative_template,
|
:piece_justificative_template,
|
||||||
:cadastres,
|
editable_options: [
|
||||||
:mnhn)
|
:cadastres,
|
||||||
|
:unesco,
|
||||||
|
:arretes_protection,
|
||||||
|
:conservatoire_littoral,
|
||||||
|
:reserves_chasse_faune_sauvage,
|
||||||
|
:reserves_biologiques,
|
||||||
|
:reserves_naturelles,
|
||||||
|
:natura_2000,
|
||||||
|
:zones_humides,
|
||||||
|
:znieff
|
||||||
|
])
|
||||||
end
|
end
|
||||||
|
|
||||||
def type_de_champ_update_params
|
def type_de_champ_update_params
|
||||||
|
@ -86,8 +95,18 @@ module NewAdministrateur
|
||||||
:mandatory,
|
:mandatory,
|
||||||
:drop_down_list_value,
|
:drop_down_list_value,
|
||||||
:piece_justificative_template,
|
:piece_justificative_template,
|
||||||
:cadastres,
|
editable_options: [
|
||||||
:mnhn)
|
:cadastres,
|
||||||
|
:unesco,
|
||||||
|
:arretes_protection,
|
||||||
|
:conservatoire_littoral,
|
||||||
|
:reserves_chasse_faune_sauvage,
|
||||||
|
:reserves_biologiques,
|
||||||
|
:reserves_naturelles,
|
||||||
|
:natura_2000,
|
||||||
|
:zones_humides,
|
||||||
|
:znieff
|
||||||
|
])
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -51,7 +51,6 @@ class Api::V2::Schema < GraphQL::Schema
|
||||||
Types::Champs::SiretChampType,
|
Types::Champs::SiretChampType,
|
||||||
Types::Champs::TextChampType,
|
Types::Champs::TextChampType,
|
||||||
Types::GeoAreas::ParcelleCadastraleType,
|
Types::GeoAreas::ParcelleCadastraleType,
|
||||||
Types::GeoAreas::QuartierPrioritaireType,
|
|
||||||
Types::GeoAreas::SelectionUtilisateurType,
|
Types::GeoAreas::SelectionUtilisateurType,
|
||||||
Types::PersonneMoraleType,
|
Types::PersonneMoraleType,
|
||||||
Types::PersonnePhysiqueType
|
Types::PersonnePhysiqueType
|
||||||
|
|
|
@ -1,16 +1,27 @@
|
||||||
module Mutations
|
module Mutations
|
||||||
class BaseMutation < GraphQL::Schema::RelayClassicMutation
|
class BaseMutation < GraphQL::Schema::RelayClassicMutation
|
||||||
|
private
|
||||||
|
|
||||||
def validate_blob(blob_id)
|
def validate_blob(blob_id)
|
||||||
if blob_id.present?
|
begin
|
||||||
begin
|
blob = ActiveStorage::Blob.find_signed(blob_id)
|
||||||
blob = ActiveStorage::Blob.find_signed(blob_id)
|
# open downloads the file and checks its hash
|
||||||
blob.identify
|
blob.open { |f| }
|
||||||
nil
|
true
|
||||||
rescue ActiveStorage::FileNotFoundError
|
rescue ActiveStorage::FileNotFoundError
|
||||||
return { errors: ['Le fichier n’a pas été correctement téléversé sur le serveur de stockage'] }
|
return false, { errors: ['Le fichier n’a pas été correctement téléversé sur le serveur de stockage'] }
|
||||||
rescue ActiveSupport::MessageVerifier::InvalidSignature
|
rescue ActiveSupport::MessageVerifier::InvalidSignature
|
||||||
return { errors: ['L’identifiant du fichier téléversé est invalide'] }
|
return false, { errors: ['L’identifiant du fichier téléversé est invalide'] }
|
||||||
end
|
rescue ActiveStorage::IntegrityError
|
||||||
|
return false, { errors: ['Le hash du fichier téléversé est invalide'] }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def dossier_authorized_for?(dossier, instructeur)
|
||||||
|
if instructeur.is_a?(Instructeur) && instructeur.dossiers.exists?(id: dossier.id)
|
||||||
|
true
|
||||||
|
else
|
||||||
|
return false, { errors: ['L’instructeur n’a pas les droits d’accès à ce dossier'] }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -13,21 +13,25 @@ module Mutations
|
||||||
field :errors, [Types::ValidationErrorType], null: true
|
field :errors, [Types::ValidationErrorType], null: true
|
||||||
|
|
||||||
def resolve(dossier:, instructeur:, motivation: nil, justificatif: nil)
|
def resolve(dossier:, instructeur:, motivation: nil, justificatif: nil)
|
||||||
if dossier.en_instruction?
|
dossier.accepter!(instructeur, motivation, justificatif)
|
||||||
errors = validate_blob(justificatif)
|
|
||||||
if errors
|
|
||||||
return errors
|
|
||||||
end
|
|
||||||
dossier.accepter!(instructeur, motivation, justificatif)
|
|
||||||
|
|
||||||
{ dossier: dossier }
|
{ dossier: dossier }
|
||||||
|
end
|
||||||
|
|
||||||
|
def ready?(justificatif: nil, **args)
|
||||||
|
if justificatif.present?
|
||||||
|
validate_blob(justificatif)
|
||||||
else
|
else
|
||||||
{ errors: ["Le dossier est déjà #{dossier_display_state(dossier, lower: true)}"] }
|
true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def authorized?(dossier:, instructeur:, motivation: nil, justificatif: nil)
|
def authorized?(dossier:, instructeur:, **args)
|
||||||
instructeur.is_a?(Instructeur) && instructeur.dossiers.exists?(id: dossier.id)
|
if !dossier.en_instruction?
|
||||||
|
return false, { errors: ["Le dossier est déjà #{dossier_display_state(dossier, lower: true)}"] }
|
||||||
|
end
|
||||||
|
|
||||||
|
dossier_authorized_for?(dossier, instructeur)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -9,17 +9,17 @@ module Mutations
|
||||||
field :errors, [Types::ValidationErrorType], null: true
|
field :errors, [Types::ValidationErrorType], null: true
|
||||||
|
|
||||||
def resolve(dossier:, instructeur:)
|
def resolve(dossier:, instructeur:)
|
||||||
if dossier.termine?
|
dossier.archiver!(instructeur)
|
||||||
dossier.archiver!(instructeur)
|
|
||||||
|
|
||||||
{ dossier: dossier }
|
{ dossier: dossier }
|
||||||
else
|
|
||||||
{ errors: ["Un dossier ne peut être archivé qu’une fois le traitement terminé"] }
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def authorized?(dossier:, instructeur:)
|
def authorized?(dossier:, instructeur:)
|
||||||
instructeur.is_a?(Instructeur) && instructeur.dossiers.exists?(id: dossier.id)
|
if !dossier.termine?
|
||||||
|
return false, { errors: ["Un dossier ne peut être archivé qu’une fois le traitement terminé"] }
|
||||||
|
end
|
||||||
|
|
||||||
|
dossier_authorized_for?(dossier, instructeur)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -11,16 +11,19 @@ module Mutations
|
||||||
field :errors, [Types::ValidationErrorType], null: true
|
field :errors, [Types::ValidationErrorType], null: true
|
||||||
|
|
||||||
def resolve(dossier:, groupe_instructeur:)
|
def resolve(dossier:, groupe_instructeur:)
|
||||||
if dossier.groupe_instructeur == groupe_instructeur
|
dossier.update!(groupe_instructeur: groupe_instructeur)
|
||||||
{ errors: ["Le dossier est déjà avec le grope instructeur: '#{groupe_instructeur.label}'"] }
|
|
||||||
else
|
{ dossier: dossier }
|
||||||
dossier.update!(groupe_instructeur: groupe_instructeur)
|
|
||||||
{ dossier: dossier }
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def authorized?(dossier:, groupe_instructeur:)
|
def authorized?(dossier:, groupe_instructeur:)
|
||||||
dossier.groupe_instructeur.procedure == groupe_instructeur.procedure
|
if dossier.groupe_instructeur == groupe_instructeur
|
||||||
|
return false, { errors: ["Le dossier est déjà avec le grope instructeur: '#{groupe_instructeur.label}'"] }
|
||||||
|
elsif dossier.groupe_instructeur.procedure != groupe_instructeur.procedure
|
||||||
|
return false, { errors: ["Le groupe instructeur '#{groupe_instructeur.label}' n’appartient pas à la même démarche que le dossier"] }
|
||||||
|
else
|
||||||
|
true
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -13,21 +13,24 @@ module Mutations
|
||||||
field :errors, [Types::ValidationErrorType], null: true
|
field :errors, [Types::ValidationErrorType], null: true
|
||||||
|
|
||||||
def resolve(dossier:, instructeur:, motivation:, justificatif: nil)
|
def resolve(dossier:, instructeur:, motivation:, justificatif: nil)
|
||||||
if dossier.en_instruction?
|
dossier.classer_sans_suite!(instructeur, motivation, justificatif)
|
||||||
errors = validate_blob(justificatif)
|
|
||||||
if errors
|
|
||||||
return errors
|
|
||||||
end
|
|
||||||
dossier.classer_sans_suite!(instructeur, motivation, justificatif)
|
|
||||||
|
|
||||||
{ dossier: dossier }
|
{ dossier: dossier }
|
||||||
|
end
|
||||||
|
|
||||||
|
def ready?(justificatif: nil, **args)
|
||||||
|
if justificatif.present?
|
||||||
|
validate_blob(justificatif)
|
||||||
else
|
else
|
||||||
{ errors: ["Le dossier est déjà #{dossier_display_state(dossier, lower: true)}"] }
|
true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def authorized?(dossier:, instructeur:, motivation:, justificatif: nil)
|
def authorized?(dossier:, instructeur:, **args)
|
||||||
instructeur.is_a?(Instructeur) && instructeur.dossiers.exists?(id: dossier.id)
|
if !dossier.en_instruction?
|
||||||
|
return false, { errors: ["Le dossier est déjà #{dossier_display_state(dossier, lower: true)}"] }
|
||||||
|
end
|
||||||
|
dossier_authorized_for?(dossier, instructeur)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -11,10 +11,6 @@ module Mutations
|
||||||
field :errors, [Types::ValidationErrorType], null: true
|
field :errors, [Types::ValidationErrorType], null: true
|
||||||
|
|
||||||
def resolve(dossier:, instructeur:, body:, attachment: nil)
|
def resolve(dossier:, instructeur:, body:, attachment: nil)
|
||||||
errors = validate_blob(attachment)
|
|
||||||
if errors
|
|
||||||
return errors
|
|
||||||
end
|
|
||||||
message = CommentaireService.build(instructeur, dossier, body: body, piece_jointe: attachment)
|
message = CommentaireService.build(instructeur, dossier, body: body, piece_jointe: attachment)
|
||||||
|
|
||||||
if message.save
|
if message.save
|
||||||
|
@ -24,8 +20,16 @@ module Mutations
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def authorized?(dossier:, instructeur:, body:, attachment: nil)
|
def ready?(attachment: nil, **args)
|
||||||
instructeur.is_a?(Instructeur) && instructeur.dossiers.exists?(id: dossier.id)
|
if attachment.present?
|
||||||
|
validate_blob(attachment)
|
||||||
|
else
|
||||||
|
true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def authorized?(dossier:, instructeur:, **args)
|
||||||
|
dossier_authorized_for?(dossier, instructeur)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -11,17 +11,16 @@ module Mutations
|
||||||
field :errors, [Types::ValidationErrorType], null: true
|
field :errors, [Types::ValidationErrorType], null: true
|
||||||
|
|
||||||
def resolve(dossier:, instructeur:)
|
def resolve(dossier:, instructeur:)
|
||||||
if dossier.en_construction?
|
dossier.passer_en_instruction!(instructeur)
|
||||||
dossier.passer_en_instruction!(instructeur)
|
|
||||||
|
|
||||||
{ dossier: dossier }
|
{ dossier: dossier }
|
||||||
else
|
|
||||||
{ errors: ["Le dossier est déjà #{dossier_display_state(dossier, lower: true)}"] }
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def authorized?(dossier:, instructeur:)
|
def authorized?(dossier:, instructeur:)
|
||||||
instructeur.is_a?(Instructeur) && instructeur.dossiers.exists?(id: dossier.id)
|
if !dossier.en_construction?
|
||||||
|
return false, { errors: ["Le dossier est déjà #{dossier_display_state(dossier, lower: true)}"] }
|
||||||
|
end
|
||||||
|
dossier_authorized_for?(dossier, instructeur)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -13,21 +13,24 @@ module Mutations
|
||||||
field :errors, [Types::ValidationErrorType], null: true
|
field :errors, [Types::ValidationErrorType], null: true
|
||||||
|
|
||||||
def resolve(dossier:, instructeur:, motivation:, justificatif: nil)
|
def resolve(dossier:, instructeur:, motivation:, justificatif: nil)
|
||||||
if dossier.en_instruction?
|
dossier.refuser!(instructeur, motivation, justificatif)
|
||||||
errors = validate_blob(justificatif)
|
|
||||||
if errors
|
|
||||||
return errors
|
|
||||||
end
|
|
||||||
dossier.refuser!(instructeur, motivation, justificatif)
|
|
||||||
|
|
||||||
{ dossier: dossier }
|
{ dossier: dossier }
|
||||||
|
end
|
||||||
|
|
||||||
|
def ready?(justificatif: nil, **args)
|
||||||
|
if justificatif.present?
|
||||||
|
validate_blob(justificatif)
|
||||||
else
|
else
|
||||||
{ errors: ["Le dossier est déjà #{dossier_display_state(dossier, lower: true)}"] }
|
true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def authorized?(dossier:, instructeur:, motivation:, justificatif: nil)
|
def authorized?(dossier:, instructeur:, **args)
|
||||||
instructeur.is_a?(Instructeur) && instructeur.dossiers.exists?(id: dossier.id)
|
if !dossier.en_instruction?
|
||||||
|
return false, { errors: ["Le dossier est déjà #{dossier_display_state(dossier, lower: true)}"] }
|
||||||
|
end
|
||||||
|
dossier_authorized_for?(dossier, instructeur)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -809,11 +809,6 @@ enum GeoAreaSource {
|
||||||
"""
|
"""
|
||||||
cadastre
|
cadastre
|
||||||
|
|
||||||
"""
|
|
||||||
Quartier prioritaire
|
|
||||||
"""
|
|
||||||
quartier_prioritaire
|
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Sélection utilisateur
|
Sélection utilisateur
|
||||||
"""
|
"""
|
||||||
|
@ -1101,15 +1096,6 @@ type Profile {
|
||||||
id: ID!
|
id: ID!
|
||||||
}
|
}
|
||||||
|
|
||||||
type QuartierPrioritaire implements GeoArea {
|
|
||||||
code: String!
|
|
||||||
commune: String!
|
|
||||||
geometry: GeoJSON!
|
|
||||||
id: ID!
|
|
||||||
nom: String!
|
|
||||||
source: GeoAreaSource!
|
|
||||||
}
|
|
||||||
|
|
||||||
type Query {
|
type Query {
|
||||||
"""
|
"""
|
||||||
Informations concernant une démarche.
|
Informations concernant une démarche.
|
||||||
|
|
|
@ -4,11 +4,9 @@ module Types
|
||||||
|
|
||||||
class GeoAreaSource < Types::BaseEnum
|
class GeoAreaSource < Types::BaseEnum
|
||||||
GeoArea.sources.each do |symbol_name, string_name|
|
GeoArea.sources.each do |symbol_name, string_name|
|
||||||
if string_name != "parcelle_agricole"
|
value(string_name,
|
||||||
value(string_name,
|
I18n.t(symbol_name, scope: [:activerecord, :attributes, :geo_area, :source]),
|
||||||
I18n.t(symbol_name, scope: [:activerecord, :attributes, :geo_area, :source]),
|
value: symbol_name)
|
||||||
value: symbol_name)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -21,8 +19,6 @@ module Types
|
||||||
case object.source
|
case object.source
|
||||||
when GeoArea.sources.fetch(:cadastre)
|
when GeoArea.sources.fetch(:cadastre)
|
||||||
Types::GeoAreas::ParcelleCadastraleType
|
Types::GeoAreas::ParcelleCadastraleType
|
||||||
when GeoArea.sources.fetch(:quartier_prioritaire)
|
|
||||||
Types::GeoAreas::QuartierPrioritaireType
|
|
||||||
when GeoArea.sources.fetch(:selection_utilisateur)
|
when GeoArea.sources.fetch(:selection_utilisateur)
|
||||||
Types::GeoAreas::SelectionUtilisateurType
|
Types::GeoAreas::SelectionUtilisateurType
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,9 +0,0 @@
|
||||||
module Types::GeoAreas
|
|
||||||
class QuartierPrioritaireType < Types::BaseObject
|
|
||||||
implements Types::GeoAreaType
|
|
||||||
|
|
||||||
field :code, String, null: false
|
|
||||||
field :nom, String, null: false
|
|
||||||
field :commune, String, null: false
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -39,10 +39,6 @@ module ChampHelper
|
||||||
concat "Parcelle n° #{geo_area.numero} - Feuille #{geo_area.code_arr} #{geo_area.section} #{geo_area.feuille} - #{geo_area.surface_parcelle.round} m"
|
concat "Parcelle n° #{geo_area.numero} - Feuille #{geo_area.code_arr} #{geo_area.section} #{geo_area.feuille} - #{geo_area.surface_parcelle.round} m"
|
||||||
concat tag.sup("2")
|
concat tag.sup("2")
|
||||||
end
|
end
|
||||||
when GeoArea.sources.fetch(:quartier_prioritaire)
|
|
||||||
"#{geo_area.commune} : #{geo_area.nom}"
|
|
||||||
when GeoArea.sources.fetch(:parcelle_agricole)
|
|
||||||
"Culture : #{geo_area.culture} - Surface : #{geo_area.surface} ha"
|
|
||||||
when GeoArea.sources.fetch(:selection_utilisateur)
|
when GeoArea.sources.fetch(:selection_utilisateur)
|
||||||
if geo_area.polygon?
|
if geo_area.polygon?
|
||||||
if geo_area.area.present?
|
if geo_area.area.present?
|
||||||
|
|
|
@ -1,13 +1,15 @@
|
||||||
import React, { useState, useCallback, useRef, useMemo } from 'react';
|
import React, { useState, useCallback, useRef, useMemo } from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import mapboxgl from 'mapbox-gl';
|
import mapboxgl from 'mapbox-gl';
|
||||||
import ReactMapboxGl, { GeoJSONLayer, ZoomControl } from 'react-mapbox-gl';
|
import { GeoJSONLayer, ZoomControl } from 'react-mapbox-gl';
|
||||||
import DrawControl from 'react-mapbox-gl-draw';
|
import DrawControl from 'react-mapbox-gl-draw';
|
||||||
import '@mapbox/mapbox-gl-draw/dist/mapbox-gl-draw.css';
|
import '@mapbox/mapbox-gl-draw/dist/mapbox-gl-draw.css';
|
||||||
|
|
||||||
import { getJSON, ajax, fire } from '@utils';
|
import { getJSON, ajax, fire } from '@utils';
|
||||||
|
|
||||||
import { getMapStyle, SwitchMapStyle } from '../MapStyles';
|
import Mapbox from '../shared/mapbox/Mapbox';
|
||||||
|
import { getMapStyle } from '../shared/mapbox/styles';
|
||||||
|
import SwitchMapStyle from '../shared/mapbox/SwitchMapStyle';
|
||||||
|
|
||||||
import ComboAdresseSearch from '../ComboAdresseSearch';
|
import ComboAdresseSearch from '../ComboAdresseSearch';
|
||||||
import {
|
import {
|
||||||
|
@ -22,9 +24,7 @@ import {
|
||||||
generateId,
|
generateId,
|
||||||
useEvent,
|
useEvent,
|
||||||
findFeature
|
findFeature
|
||||||
} from '../shared/map';
|
} from '../shared/mapbox/utils';
|
||||||
|
|
||||||
const Map = ReactMapboxGl({});
|
|
||||||
|
|
||||||
function MapEditor({ featureCollection, url, preview, options }) {
|
function MapEditor({ featureCollection, url, preview, options }) {
|
||||||
const drawControl = useRef(null);
|
const drawControl = useRef(null);
|
||||||
|
@ -38,10 +38,11 @@ function MapEditor({ featureCollection, url, preview, options }) {
|
||||||
const [cadastresFeatureCollection, setCadastresFeatureCollection] = useState(
|
const [cadastresFeatureCollection, setCadastresFeatureCollection] = useState(
|
||||||
filterFeatureCollection(featureCollection, 'cadastre')
|
filterFeatureCollection(featureCollection, 'cadastre')
|
||||||
);
|
);
|
||||||
const mapStyle = useMemo(
|
const mapStyle = useMemo(() => getMapStyle(style, options.layers), [
|
||||||
() => getMapStyle(style, options.cadastres, options.mnhn),
|
style,
|
||||||
[style, options]
|
options
|
||||||
);
|
]);
|
||||||
|
const hasCadastres = useMemo(() => options.layers.includes('cadastres'));
|
||||||
|
|
||||||
const translations = [
|
const translations = [
|
||||||
['.mapbox-gl-draw_line', 'Tracer une ligne'],
|
['.mapbox-gl-draw_line', 'Tracer une ligne'],
|
||||||
|
@ -288,7 +289,7 @@ function MapEditor({ featureCollection, url, preview, options }) {
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<Map
|
<Mapbox
|
||||||
onStyleLoad={(map) => onMapLoad(map)}
|
onStyleLoad={(map) => onMapLoad(map)}
|
||||||
fitBounds={bbox}
|
fitBounds={bbox}
|
||||||
fitBoundsOptions={{ padding: 100 }}
|
fitBoundsOptions={{ padding: 100 }}
|
||||||
|
@ -299,7 +300,7 @@ function MapEditor({ featureCollection, url, preview, options }) {
|
||||||
height: '500px'
|
height: '500px'
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{options.cadastres ? (
|
{hasCadastres ? (
|
||||||
<GeoJSONLayer
|
<GeoJSONLayer
|
||||||
data={cadastresFeatureCollection}
|
data={cadastresFeatureCollection}
|
||||||
fillPaint={polygonCadastresFill}
|
fillPaint={polygonCadastresFill}
|
||||||
|
@ -321,7 +322,7 @@ function MapEditor({ featureCollection, url, preview, options }) {
|
||||||
/>
|
/>
|
||||||
<SwitchMapStyle style={style} setStyle={setStyle} ign={options.ign} />
|
<SwitchMapStyle style={style} setStyle={setStyle} ign={options.ign} />
|
||||||
<ZoomControl />
|
<ZoomControl />
|
||||||
</Map>
|
</Mapbox>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -335,8 +336,7 @@ MapEditor.propTypes = {
|
||||||
url: PropTypes.string,
|
url: PropTypes.string,
|
||||||
preview: PropTypes.bool,
|
preview: PropTypes.bool,
|
||||||
options: PropTypes.shape({
|
options: PropTypes.shape({
|
||||||
cadastres: PropTypes.bool,
|
layers: PropTypes.array,
|
||||||
mnhn: PropTypes.bool,
|
|
||||||
ign: PropTypes.bool
|
ign: PropTypes.bool
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
import React, { useState, useCallback, useMemo } from 'react';
|
import React, { useState, useCallback, useMemo } from 'react';
|
||||||
import ReactMapboxGl, { ZoomControl, GeoJSONLayer } from 'react-mapbox-gl';
|
import { ZoomControl, GeoJSONLayer } from 'react-mapbox-gl';
|
||||||
import mapboxgl, { Popup } from 'mapbox-gl';
|
import mapboxgl, { Popup } from 'mapbox-gl';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
|
|
||||||
import { getMapStyle, SwitchMapStyle } from '../MapStyles';
|
import Mapbox from '../shared/mapbox/Mapbox';
|
||||||
|
import { getMapStyle } from '../shared/mapbox/styles';
|
||||||
|
import SwitchMapStyle from '../shared/mapbox/SwitchMapStyle';
|
||||||
import {
|
import {
|
||||||
filterFeatureCollection,
|
filterFeatureCollection,
|
||||||
filterFeatureCollectionByGeometryType,
|
filterFeatureCollectionByGeometryType,
|
||||||
|
@ -12,9 +13,7 @@ import {
|
||||||
findFeature,
|
findFeature,
|
||||||
fitBounds,
|
fitBounds,
|
||||||
getCenter
|
getCenter
|
||||||
} from '../shared/map';
|
} from '../shared/mapbox/utils';
|
||||||
|
|
||||||
const Map = ReactMapboxGl({});
|
|
||||||
|
|
||||||
const MapReader = ({ featureCollection, options }) => {
|
const MapReader = ({ featureCollection, options }) => {
|
||||||
const [currentMap, setCurrentMap] = useState(null);
|
const [currentMap, setCurrentMap] = useState(null);
|
||||||
|
@ -51,11 +50,11 @@ const MapReader = ({ featureCollection, options }) => {
|
||||||
),
|
),
|
||||||
[selectionsUtilisateurFeatureCollection]
|
[selectionsUtilisateurFeatureCollection]
|
||||||
);
|
);
|
||||||
const hasCadastres = !!cadastresFeatureCollection.length;
|
const hasCadastres = useMemo(() => options.layers.includes('cadastres'));
|
||||||
const mapStyle = useMemo(
|
const mapStyle = useMemo(() => getMapStyle(style, options.layers), [
|
||||||
() => getMapStyle(style, hasCadastres, options.mnhn),
|
style,
|
||||||
[style, options, cadastresFeatureCollection]
|
options
|
||||||
);
|
]);
|
||||||
const popup = useMemo(
|
const popup = useMemo(
|
||||||
() =>
|
() =>
|
||||||
new Popup({
|
new Popup({
|
||||||
|
@ -147,7 +146,7 @@ const MapReader = ({ featureCollection, options }) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Map
|
<Mapbox
|
||||||
onStyleLoad={(map) => onMapLoad(map)}
|
onStyleLoad={(map) => onMapLoad(map)}
|
||||||
fitBounds={boundData}
|
fitBounds={boundData}
|
||||||
fitBoundsOptions={{ padding: 100 }}
|
fitBoundsOptions={{ padding: 100 }}
|
||||||
|
@ -186,7 +185,7 @@ const MapReader = ({ featureCollection, options }) => {
|
||||||
|
|
||||||
<SwitchMapStyle style={style} setStyle={setStyle} ign={options.ign} />
|
<SwitchMapStyle style={style} setStyle={setStyle} ign={options.ign} />
|
||||||
<ZoomControl />
|
<ZoomControl />
|
||||||
</Map>
|
</Mapbox>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -197,8 +196,8 @@ MapReader.propTypes = {
|
||||||
features: PropTypes.array
|
features: PropTypes.array
|
||||||
}),
|
}),
|
||||||
options: PropTypes.shape({
|
options: PropTypes.shape({
|
||||||
ign: PropTypes.bool,
|
layers: PropTypes.array,
|
||||||
mnhn: PropTypes.bool
|
ign: PropTypes.bool
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,96 +0,0 @@
|
||||||
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' }
|
|
||||||
},
|
|
||||||
'mapbox:type': 'template',
|
|
||||||
'openmaptiles:mapbox:owner': 'openmaptiles',
|
|
||||||
'openmaptiles:mapbox:source:url': 'mapbox://openmaptiles.4qljc88t',
|
|
||||||
'openmaptiles:version': '3.x',
|
|
||||||
'maputnik:renderer': 'mbgljs'
|
|
||||||
},
|
|
||||||
center: [0, 0],
|
|
||||||
zoom: 1,
|
|
||||||
bearing: 0,
|
|
||||||
pitch: 0,
|
|
||||||
sources: {
|
|
||||||
'decoupage-administratif': {
|
|
||||||
type: 'vector',
|
|
||||||
url:
|
|
||||||
'https://openmaptiles.geo.data.gouv.fr/data/decoupage-administratif.json'
|
|
||||||
},
|
|
||||||
openmaptiles: {
|
|
||||||
type: 'vector',
|
|
||||||
url: 'https://openmaptiles.geo.data.gouv.fr/data/france-vector.json'
|
|
||||||
},
|
|
||||||
'photographies-aeriennes': {
|
|
||||||
type: 'raster',
|
|
||||||
tiles: [
|
|
||||||
'https://tiles.geo.api.gouv.fr/photographies-aeriennes/tiles/{z}/{x}/{y}'
|
|
||||||
],
|
|
||||||
tileSize: 256,
|
|
||||||
attribution: 'Images aériennes © IGN',
|
|
||||||
minzoom: 0,
|
|
||||||
maxzoom: 19
|
|
||||||
},
|
|
||||||
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'
|
|
||||||
};
|
|
|
@ -1,55 +0,0 @@
|
||||||
import baseStyle from './base-style';
|
|
||||||
import cadastre from './cadastre';
|
|
||||||
import orthoStyle from './ortho-style';
|
|
||||||
import vectorStyle from './vector-style';
|
|
||||||
|
|
||||||
function rasterStyle(source) {
|
|
||||||
return {
|
|
||||||
id: source,
|
|
||||||
source,
|
|
||||||
type: 'raster',
|
|
||||||
paint: { 'raster-resampling': 'linear' }
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getMapStyle(style, hasCadastres, hasMNHN) {
|
|
||||||
const mapStyle = { ...baseStyle };
|
|
||||||
|
|
||||||
switch (style) {
|
|
||||||
case 'ortho':
|
|
||||||
mapStyle.layers = orthoStyle;
|
|
||||||
mapStyle.id = 'ortho';
|
|
||||||
mapStyle.name = 'Photographies aériennes';
|
|
||||||
break;
|
|
||||||
case 'vector':
|
|
||||||
mapStyle.layers = vectorStyle;
|
|
||||||
mapStyle.id = 'vector';
|
|
||||||
mapStyle.name = 'Carte OSM';
|
|
||||||
break;
|
|
||||||
case 'ign':
|
|
||||||
mapStyle.layers = [rasterStyle('plan-ign')];
|
|
||||||
mapStyle.id = 'ign';
|
|
||||||
mapStyle.name = 'Carte IGN';
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hasCadastres) {
|
|
||||||
mapStyle.layers = mapStyle.layers.concat(cadastre);
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
export { SwitchMapStyle } from './SwitchMapStyle';
|
|
|
@ -137,14 +137,13 @@ const TypeDeChamp = sortableElement(
|
||||||
url={typeDeChamp.piece_justificative_template_url}
|
url={typeDeChamp.piece_justificative_template_url}
|
||||||
/>
|
/>
|
||||||
<TypeDeChampCarteOptions isVisible={isCarte}>
|
<TypeDeChampCarteOptions isVisible={isCarte}>
|
||||||
<TypeDeChampCarteOption
|
{Object.entries(OPTIONS_FIELDS).map(([field, label]) => (
|
||||||
label="Cadastres"
|
<TypeDeChampCarteOption
|
||||||
handler={updateHandlers.cadastres}
|
key={field}
|
||||||
/>
|
label={label}
|
||||||
<TypeDeChampCarteOption
|
handler={updateHandlers[field]}
|
||||||
label="Zones naturelles protégées"
|
/>
|
||||||
handler={updateHandlers.mnhn}
|
))}
|
||||||
/>
|
|
||||||
</TypeDeChampCarteOptions>
|
</TypeDeChampCarteOptions>
|
||||||
<TypeDeChampRepetitionOptions
|
<TypeDeChampRepetitionOptions
|
||||||
isVisible={isRepetition}
|
isVisible={isRepetition}
|
||||||
|
@ -182,7 +181,7 @@ function createUpdateHandler(dispatch, typeDeChamp, field, index, prefix) {
|
||||||
return {
|
return {
|
||||||
id: `${prefix ? `${prefix}-` : ''}champ-${index}-${field}`,
|
id: `${prefix ? `${prefix}-` : ''}champ-${index}-${field}`,
|
||||||
name: field,
|
name: field,
|
||||||
value: typeDeChamp[field],
|
value: getValue(typeDeChamp, field),
|
||||||
onChange: ({ target }) =>
|
onChange: ({ target }) =>
|
||||||
dispatch({
|
dispatch({
|
||||||
type: 'updateTypeDeChamp',
|
type: 'updateTypeDeChamp',
|
||||||
|
@ -196,6 +195,14 @@ function createUpdateHandler(dispatch, typeDeChamp, field, index, prefix) {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getValue(obj, path) {
|
||||||
|
const [, optionsPath] = path.split('.');
|
||||||
|
if (optionsPath) {
|
||||||
|
return (obj.editable_options || {})[optionsPath];
|
||||||
|
}
|
||||||
|
return obj[path];
|
||||||
|
}
|
||||||
|
|
||||||
function createUpdateHandlers(dispatch, typeDeChamp, index, prefix) {
|
function createUpdateHandlers(dispatch, typeDeChamp, index, prefix) {
|
||||||
return FIELDS.reduce((handlers, field) => {
|
return FIELDS.reduce((handlers, field) => {
|
||||||
handlers[field] = createUpdateHandler(
|
handlers[field] = createUpdateHandler(
|
||||||
|
@ -209,19 +216,30 @@ function createUpdateHandlers(dispatch, typeDeChamp, index, prefix) {
|
||||||
}, {});
|
}, {});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const OPTIONS_FIELDS = {
|
||||||
|
'options.cadastres': 'Cadastres',
|
||||||
|
'options.unesco': 'UNESCO',
|
||||||
|
'options.arretes_protection': 'Arrêtés de protection',
|
||||||
|
'options.conservatoire_littoral': 'Conservatoire du Littoral',
|
||||||
|
'options.reserves_chasse_faune_sauvage':
|
||||||
|
'Réserves nationales de chasse et de faune sauvage',
|
||||||
|
'options.reserves_biologiques': 'Réserves biologiques',
|
||||||
|
'options.reserves_naturelles': 'Réserves naturelles',
|
||||||
|
'options.natura_2000': 'Natura 2000',
|
||||||
|
'options.zones_humides': 'Zones humides d’importance internationale',
|
||||||
|
'options.znieff': 'ZNIEFF'
|
||||||
|
};
|
||||||
|
|
||||||
export const FIELDS = [
|
export const FIELDS = [
|
||||||
'cadastres',
|
|
||||||
'mnhn',
|
|
||||||
'description',
|
'description',
|
||||||
'drop_down_list_value',
|
'drop_down_list_value',
|
||||||
'libelle',
|
'libelle',
|
||||||
'mandatory',
|
'mandatory',
|
||||||
'parcelles_agricoles',
|
|
||||||
'parent_id',
|
'parent_id',
|
||||||
'piece_justificative_template',
|
'piece_justificative_template',
|
||||||
'private',
|
'private',
|
||||||
'quartiers_prioritaires',
|
'type_champ',
|
||||||
'type_champ'
|
...Object.keys(OPTIONS_FIELDS)
|
||||||
];
|
];
|
||||||
|
|
||||||
function readValue(input) {
|
function readValue(input) {
|
||||||
|
|
|
@ -113,7 +113,13 @@ function updateTypeDeChamp(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
typeDeChamp[field] = value;
|
if (field.startsWith('options.')) {
|
||||||
|
const [, optionsField] = field.split('.');
|
||||||
|
typeDeChamp.editable_options = typeDeChamp.editable_options || {};
|
||||||
|
typeDeChamp.editable_options[optionsField] = value;
|
||||||
|
} else {
|
||||||
|
typeDeChamp[field] = value;
|
||||||
|
}
|
||||||
|
|
||||||
getUpdateHandler(typeDeChamp, state)(done);
|
getUpdateHandler(typeDeChamp, state)(done);
|
||||||
|
|
||||||
|
|
3
app/javascript/components/shared/mapbox/Mapbox.js
Normal file
3
app/javascript/components/shared/mapbox/Mapbox.js
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
import ReactMapboxGl from 'react-mapbox-gl';
|
||||||
|
|
||||||
|
export default ReactMapboxGl({});
|
|
@ -1,8 +1,9 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import ortho from './images/preview-ortho.png';
|
|
||||||
import vector from './images/preview-vector.png';
|
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
|
|
||||||
|
import ortho from './styles/images/preview-ortho.png';
|
||||||
|
import vector from './styles/images/preview-vector.png';
|
||||||
|
|
||||||
const STYLES = {
|
const STYLES = {
|
||||||
ortho: {
|
ortho: {
|
||||||
title: 'Satellite',
|
title: 'Satellite',
|
||||||
|
@ -34,7 +35,7 @@ function getNextStyle(style, ign) {
|
||||||
return styles[index];
|
return styles[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
export const SwitchMapStyle = ({ style, setStyle, ign }) => {
|
function SwitchMapStyle({ style, setStyle, ign }) {
|
||||||
const nextStyle = getNextStyle(style, ign);
|
const nextStyle = getNextStyle(style, ign);
|
||||||
const { title, preview, color } = (ign ? IGN_STYLES : STYLES)[nextStyle];
|
const { title, preview, color } = (ign ? IGN_STYLES : STYLES)[nextStyle];
|
||||||
|
|
||||||
|
@ -69,10 +70,12 @@ export const SwitchMapStyle = ({ style, setStyle, ign }) => {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
}
|
||||||
|
|
||||||
SwitchMapStyle.propTypes = {
|
SwitchMapStyle.propTypes = {
|
||||||
style: PropTypes.string,
|
style: PropTypes.string,
|
||||||
setStyle: PropTypes.func,
|
setStyle: PropTypes.func,
|
||||||
ign: PropTypes.bool
|
ign: PropTypes.bool
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export default SwitchMapStyle;
|
213
app/javascript/components/shared/mapbox/styles/base.js
Normal file
213
app/javascript/components/shared/mapbox/styles/base.js
Normal file
|
@ -0,0 +1,213 @@
|
||||||
|
import cadastreLayers from './cadastre-layers';
|
||||||
|
|
||||||
|
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}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
const OPTIONAL_LAYERS = [
|
||||||
|
{
|
||||||
|
label: 'UNESCO',
|
||||||
|
id: 'unesco',
|
||||||
|
layers: [
|
||||||
|
['Aires protégées Géoparcs', 'PROTECTEDAREAS.GP'],
|
||||||
|
['Réserves de biosphère', 'PROTECTEDAREAS.BIOS']
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Arrêtés de protection',
|
||||||
|
id: 'arretes_protection',
|
||||||
|
layers: [
|
||||||
|
['Arrêtés de protection de biotope', 'PROTECTEDAREAS.APB'],
|
||||||
|
['Arrêtés de protection de géotope', 'PROTECTEDAREAS.APG']
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Conservatoire du Littoral',
|
||||||
|
id: 'conservatoire_littoral',
|
||||||
|
layers: [
|
||||||
|
[
|
||||||
|
'Conservatoire du littoral : parcelles protégées',
|
||||||
|
'PROTECTEDAREAS.MNHN.CDL.PARCELS'
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'Conservatoire du littoral : périmètres d’intervention',
|
||||||
|
'PROTECTEDAREAS.MNHN.CDL.PERIMETER'
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Réserves nationales de chasse et de faune sauvage',
|
||||||
|
id: 'reserves_chasse_faune_sauvage',
|
||||||
|
layers: [
|
||||||
|
[
|
||||||
|
'Réserves nationales de chasse et de faune sauvage',
|
||||||
|
'PROTECTEDAREAS.RNCF'
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Réserves biologiques',
|
||||||
|
id: 'reserves_biologiques',
|
||||||
|
layers: [['Réserves biologiques', 'PROTECTEDAREAS.RB']]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Réserves naturelles',
|
||||||
|
id: 'reserves_naturelles',
|
||||||
|
layers: [
|
||||||
|
['Réserves naturelles nationales', 'PROTECTEDAREAS.RN'],
|
||||||
|
[
|
||||||
|
'Périmètres de protection de réserves naturelles',
|
||||||
|
'PROTECTEDAREAS.MNHN.RN.PERIMETER'
|
||||||
|
],
|
||||||
|
['Réserves naturelles de Corse', 'PROTECTEDAREAS.RNC'],
|
||||||
|
[
|
||||||
|
'Réserves naturelles régionales',
|
||||||
|
'PROTECTEDSITES.MNHN.RESERVES-REGIONALES'
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Natura 2000',
|
||||||
|
id: 'natura_2000',
|
||||||
|
layers: [
|
||||||
|
['Sites Natura 2000 (Directive Habitats)', 'PROTECTEDAREAS.SIC'],
|
||||||
|
['Sites Natura 2000 (Directive Oiseaux)', 'PROTECTEDAREAS.ZPS']
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Zones humides d’importance internationale',
|
||||||
|
id: 'zones_humides',
|
||||||
|
layers: [
|
||||||
|
['Zones humides d’importance internationale', 'PROTECTEDAREAS.RAMSAR']
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'ZNIEFF',
|
||||||
|
id: 'znieff',
|
||||||
|
layers: [
|
||||||
|
[
|
||||||
|
'Zones naturelles d’intérêt écologique faunistique et floristique de type 1 (ZNIEFF 1 mer)',
|
||||||
|
'PROTECTEDAREAS.ZNIEFF1.SEA'
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'Zones naturelles d’intérêt écologique faunistique et floristique de type 1 (ZNIEFF 1)',
|
||||||
|
'PROTECTEDAREAS.ZNIEFF1'
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'Zones naturelles d’intérêt écologique faunistique et floristique de type 2 (ZNIEFF 2 mer)',
|
||||||
|
'PROTECTEDAREAS.ZNIEFF2.SEA'
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'Zones naturelles d’intérêt écologique faunistique et floristique de type 2 (ZNIEFF 2)',
|
||||||
|
'PROTECTEDAREAS.ZNIEFF2'
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Cadastre',
|
||||||
|
id: 'cadastres',
|
||||||
|
layers: [['Cadastre', 'CADASTRE']]
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
function buildSources() {
|
||||||
|
return Object.fromEntries(
|
||||||
|
OPTIONAL_LAYERS.flatMap(({ layers }) => layers).map(([, code]) => [
|
||||||
|
code.toLowerCase().replace(/\./g, '-'),
|
||||||
|
rasterSource([ignServiceURL(code)], 'IGN-F/Géoportail/MNHN')
|
||||||
|
])
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function rasterSource(tiles, attribution) {
|
||||||
|
return {
|
||||||
|
type: 'raster',
|
||||||
|
tiles,
|
||||||
|
tileSize: 256,
|
||||||
|
attribution,
|
||||||
|
minzoom: 0,
|
||||||
|
maxzoom: 18
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function buildLayers(ids) {
|
||||||
|
return OPTIONAL_LAYERS.filter(({ id }) => ids.includes(id))
|
||||||
|
.flatMap(({ layers }) => layers)
|
||||||
|
.map(([, code]) =>
|
||||||
|
code === 'CADASTRE'
|
||||||
|
? cadastreLayers
|
||||||
|
: rasterLayer(code.toLowerCase().replace(/\./g, '-'))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function rasterLayer(source) {
|
||||||
|
return {
|
||||||
|
id: source,
|
||||||
|
source,
|
||||||
|
type: 'raster',
|
||||||
|
paint: { 'raster-resampling': 'linear' }
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
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' }
|
||||||
|
},
|
||||||
|
'mapbox:type': 'template',
|
||||||
|
'openmaptiles:mapbox:owner': 'openmaptiles',
|
||||||
|
'openmaptiles:mapbox:source:url': 'mapbox://openmaptiles.4qljc88t',
|
||||||
|
'openmaptiles:version': '3.x',
|
||||||
|
'maputnik:renderer': 'mbgljs'
|
||||||
|
},
|
||||||
|
center: [0, 0],
|
||||||
|
zoom: 1,
|
||||||
|
bearing: 0,
|
||||||
|
pitch: 0,
|
||||||
|
sources: {
|
||||||
|
'decoupage-administratif': {
|
||||||
|
type: 'vector',
|
||||||
|
url:
|
||||||
|
'https://openmaptiles.geo.data.gouv.fr/data/decoupage-administratif.json'
|
||||||
|
},
|
||||||
|
openmaptiles: {
|
||||||
|
type: 'vector',
|
||||||
|
url: 'https://openmaptiles.geo.data.gouv.fr/data/france-vector.json'
|
||||||
|
},
|
||||||
|
'photographies-aeriennes': {
|
||||||
|
type: 'raster',
|
||||||
|
tiles: [
|
||||||
|
'https://tiles.geo.api.gouv.fr/photographies-aeriennes/tiles/{z}/{x}/{y}'
|
||||||
|
],
|
||||||
|
tileSize: 256,
|
||||||
|
attribution: 'Images aériennes © IGN',
|
||||||
|
minzoom: 0,
|
||||||
|
maxzoom: 19
|
||||||
|
},
|
||||||
|
cadastre: {
|
||||||
|
type: 'vector',
|
||||||
|
url: 'https://openmaptiles.geo.data.gouv.fr/data/cadastre.json'
|
||||||
|
},
|
||||||
|
'plan-ign': rasterSource(
|
||||||
|
[ignServiceURL('GEOGRAPHICALGRIDSYSTEMS.PLANIGNV2')],
|
||||||
|
'IGN-F/Géoportail'
|
||||||
|
),
|
||||||
|
...buildSources()
|
||||||
|
},
|
||||||
|
sprite: 'https://openmaptiles.github.io/osm-bright-gl-style/sprite',
|
||||||
|
glyphs: 'https://openmaptiles.geo.data.gouv.fr/fonts/{fontstack}/{range}.pbf'
|
||||||
|
};
|
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 22 KiB |
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 17 KiB |
29
app/javascript/components/shared/mapbox/styles/index.js
Normal file
29
app/javascript/components/shared/mapbox/styles/index.js
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
import baseStyle, { rasterLayer, buildLayers } from './base';
|
||||||
|
import orthoStyle from './ortho-style';
|
||||||
|
import vectorStyle from './vector-style';
|
||||||
|
|
||||||
|
export function getMapStyle(style, optionalLayers) {
|
||||||
|
const mapStyle = { ...baseStyle };
|
||||||
|
|
||||||
|
switch (style) {
|
||||||
|
case 'ortho':
|
||||||
|
mapStyle.layers = orthoStyle;
|
||||||
|
mapStyle.id = 'ortho';
|
||||||
|
mapStyle.name = 'Photographies aériennes';
|
||||||
|
break;
|
||||||
|
case 'vector':
|
||||||
|
mapStyle.layers = vectorStyle;
|
||||||
|
mapStyle.id = 'vector';
|
||||||
|
mapStyle.name = 'Carte OSM';
|
||||||
|
break;
|
||||||
|
case 'ign':
|
||||||
|
mapStyle.layers = [rasterLayer('plan-ign')];
|
||||||
|
mapStyle.id = 'ign';
|
||||||
|
mapStyle.name = 'Carte IGN';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
mapStyle.layers = mapStyle.layers.concat(buildLayers(optionalLayers));
|
||||||
|
|
||||||
|
return mapStyle;
|
||||||
|
}
|
|
@ -1,6 +1,4 @@
|
||||||
class TitreIdentiteWatermarkJob < ApplicationJob
|
class TitreIdentiteWatermarkJob < ApplicationJob
|
||||||
queue_as :active_storage_watermark
|
|
||||||
|
|
||||||
MAX_IMAGE_SIZE = 1500
|
MAX_IMAGE_SIZE = 1500
|
||||||
SCALE = 0.9
|
SCALE = 0.9
|
||||||
WATERMARK = Rails.root.join("app/assets/images/#{WATERMARK_FILE}")
|
WATERMARK = Rails.root.join("app/assets/images/#{WATERMARK_FILE}")
|
||||||
|
|
|
@ -59,8 +59,9 @@ class ApiEntreprise::API
|
||||||
private
|
private
|
||||||
|
|
||||||
def self.call_with_token(resource_name, token)
|
def self.call_with_token(resource_name, token)
|
||||||
url = "#{API_ENTREPRISE_URL}/privileges?token=#{token}"
|
url = "#{API_ENTREPRISE_URL}/#{resource_name}"
|
||||||
response = Typhoeus.get(url,
|
response = Typhoeus.get(url,
|
||||||
|
headers: { Authorization: "Bearer #{token}" },
|
||||||
timeout: TIMEOUT)
|
timeout: TIMEOUT)
|
||||||
|
|
||||||
if response.success?
|
if response.success?
|
||||||
|
@ -76,6 +77,7 @@ class ApiEntreprise::API
|
||||||
params = params(siret_or_siren, procedure_id, user_id)
|
params = params(siret_or_siren, procedure_id, user_id)
|
||||||
|
|
||||||
response = Typhoeus.get(url,
|
response = Typhoeus.get(url,
|
||||||
|
headers: { Authorization: "Bearer #{token_for_procedure(procedure_id)}" },
|
||||||
params: params,
|
params: params,
|
||||||
timeout: TIMEOUT)
|
timeout: TIMEOUT)
|
||||||
|
|
||||||
|
@ -112,8 +114,7 @@ class ApiEntreprise::API
|
||||||
context: "demarches-simplifiees.fr",
|
context: "demarches-simplifiees.fr",
|
||||||
recipient: siret_or_siren,
|
recipient: siret_or_siren,
|
||||||
object: "procedure_id: #{procedure_id}",
|
object: "procedure_id: #{procedure_id}",
|
||||||
non_diffusables: true,
|
non_diffusables: true
|
||||||
token: token_for_procedure(procedure_id)
|
|
||||||
}
|
}
|
||||||
# rubocop:enable DS/ApplicationName
|
# rubocop:enable DS/ApplicationName
|
||||||
params[:user_id] = user_id if user_id.present?
|
params[:user_id] = user_id if user_id.present?
|
||||||
|
|
|
@ -41,6 +41,7 @@ class Champ < ApplicationRecord
|
||||||
:exclude_from_view?,
|
:exclude_from_view?,
|
||||||
:repetition?,
|
:repetition?,
|
||||||
:dossier_link?,
|
:dossier_link?,
|
||||||
|
:titre_identite?,
|
||||||
to: :type_de_champ
|
to: :type_de_champ
|
||||||
|
|
||||||
scope :updated_since?, -> (date) { where('champs.updated_at > ?', date) }
|
scope :updated_since?, -> (date) { where('champs.updated_at > ?', date) }
|
||||||
|
|
|
@ -27,45 +27,41 @@ class Champs::CarteChamp < Champ
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def quartiers_prioritaires
|
|
||||||
geo_areas.filter do |area|
|
|
||||||
area.source == GeoArea.sources.fetch(:quartier_prioritaire)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def parcelles_agricoles
|
|
||||||
geo_areas.filter do |area|
|
|
||||||
area.source == GeoArea.sources.fetch(:parcelle_agricole)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def selections_utilisateur
|
def selections_utilisateur
|
||||||
geo_areas.filter do |area|
|
geo_areas.filter do |area|
|
||||||
area.source == GeoArea.sources.fetch(:selection_utilisateur)
|
area.source == GeoArea.sources.fetch(:selection_utilisateur)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def layer_enabled?(layer)
|
||||||
|
type_de_champ.options[layer] && type_de_champ.options[layer] != '0'
|
||||||
|
end
|
||||||
|
|
||||||
def cadastres?
|
def cadastres?
|
||||||
type_de_champ&.cadastres && type_de_champ.cadastres != '0'
|
layer_enabled?(:cadastres)
|
||||||
end
|
end
|
||||||
|
|
||||||
def quartiers_prioritaires?
|
def optional_layers
|
||||||
type_de_champ&.quartiers_prioritaires && type_de_champ.quartiers_prioritaires != '0'
|
[
|
||||||
end
|
:unesco,
|
||||||
|
:arretes_protection,
|
||||||
def parcelles_agricoles?
|
:conservatoire_littoral,
|
||||||
type_de_champ&.parcelles_agricoles && type_de_champ.parcelles_agricoles != '0'
|
:reserves_chasse_faune_sauvage,
|
||||||
end
|
:reserves_biologiques,
|
||||||
|
:reserves_naturelles,
|
||||||
def mnhn?
|
:natura_2000,
|
||||||
type_de_champ&.mnhn && type_de_champ.mnhn != '0'
|
:zones_humides,
|
||||||
|
:znieff,
|
||||||
|
:cadastres
|
||||||
|
].map do |layer|
|
||||||
|
layer_enabled?(layer) ? layer : nil
|
||||||
|
end.compact
|
||||||
end
|
end
|
||||||
|
|
||||||
def render_options
|
def render_options
|
||||||
{
|
{
|
||||||
ign: Flipper.enabled?(:carte_ign, procedure),
|
ign: Flipper.enabled?(:carte_ign, procedure),
|
||||||
mnhn: mnhn?,
|
layers: optional_layers
|
||||||
cadastres: cadastres?
|
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -5,18 +5,22 @@ module BlobTitreIdentiteWatermarkConcern
|
||||||
after_update_commit :enqueue_watermark_job
|
after_update_commit :enqueue_watermark_job
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def watermark_pending?
|
||||||
|
watermark_required? && !watermark_done?
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def titre_identite?
|
def watermark_required?
|
||||||
attachments.find { |attachment| attachment.record.class.name == 'Champs::TitreIdentiteChamp' }
|
attachments.find { |attachment| attachment.record.class.name == 'Champs::TitreIdentiteChamp' }
|
||||||
end
|
end
|
||||||
|
|
||||||
def watermarked?
|
def watermark_done?
|
||||||
metadata[:watermark]
|
metadata[:watermark]
|
||||||
end
|
end
|
||||||
|
|
||||||
def enqueue_watermark_job
|
def enqueue_watermark_job
|
||||||
if titre_identite? && !watermarked? && analyzed? && virus_scanner.done? && Flipper.enabled?(:titre_identite_watermark)
|
if analyzed? && virus_scanner.done? && watermark_pending?
|
||||||
TitreIdentiteWatermarkJob.perform_later(self)
|
TitreIdentiteWatermarkJob.perform_later(self)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -591,6 +591,7 @@ class Dossier < ApplicationRecord
|
||||||
end
|
end
|
||||||
|
|
||||||
save!
|
save!
|
||||||
|
remove_titres_identite!
|
||||||
NotificationMailer.send_closed_notification(self).deliver_later
|
NotificationMailer.send_closed_notification(self).deliver_later
|
||||||
log_dossier_operation(instructeur, :accepter, self)
|
log_dossier_operation(instructeur, :accepter, self)
|
||||||
end
|
end
|
||||||
|
@ -604,6 +605,7 @@ class Dossier < ApplicationRecord
|
||||||
end
|
end
|
||||||
|
|
||||||
save!
|
save!
|
||||||
|
remove_titres_identite!
|
||||||
NotificationMailer.send_closed_notification(self).deliver_later
|
NotificationMailer.send_closed_notification(self).deliver_later
|
||||||
log_automatic_dossier_operation(:accepter, self)
|
log_automatic_dossier_operation(:accepter, self)
|
||||||
end
|
end
|
||||||
|
@ -616,6 +618,7 @@ class Dossier < ApplicationRecord
|
||||||
end
|
end
|
||||||
|
|
||||||
save!
|
save!
|
||||||
|
remove_titres_identite!
|
||||||
NotificationMailer.send_refused_notification(self).deliver_later
|
NotificationMailer.send_refused_notification(self).deliver_later
|
||||||
log_dossier_operation(instructeur, :refuser, self)
|
log_dossier_operation(instructeur, :refuser, self)
|
||||||
end
|
end
|
||||||
|
@ -628,10 +631,15 @@ class Dossier < ApplicationRecord
|
||||||
end
|
end
|
||||||
|
|
||||||
save!
|
save!
|
||||||
|
remove_titres_identite!
|
||||||
NotificationMailer.send_without_continuation_notification(self).deliver_later
|
NotificationMailer.send_without_continuation_notification(self).deliver_later
|
||||||
log_dossier_operation(instructeur, :classer_sans_suite, self)
|
log_dossier_operation(instructeur, :classer_sans_suite, self)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def remove_titres_identite!
|
||||||
|
champs.filter(&:titre_identite?).map(&:piece_justificative_file).each(&:purge_later)
|
||||||
|
end
|
||||||
|
|
||||||
def check_mandatory_champs
|
def check_mandatory_champs
|
||||||
(champs + champs.filter(&:repetition?).flat_map(&:champs))
|
(champs + champs.filter(&:repetition?).flat_map(&:champs))
|
||||||
.filter(&:mandatory_and_blank?)
|
.filter(&:mandatory_and_blank?)
|
||||||
|
|
|
@ -35,16 +35,12 @@ class GeoArea < ApplicationRecord
|
||||||
]
|
]
|
||||||
|
|
||||||
enum source: {
|
enum source: {
|
||||||
quartier_prioritaire: 'quartier_prioritaire',
|
|
||||||
cadastre: 'cadastre',
|
cadastre: 'cadastre',
|
||||||
parcelle_agricole: 'parcelle_agricole',
|
|
||||||
selection_utilisateur: 'selection_utilisateur'
|
selection_utilisateur: 'selection_utilisateur'
|
||||||
}
|
}
|
||||||
|
|
||||||
scope :selections_utilisateur, -> { where(source: sources.fetch(:selection_utilisateur)) }
|
scope :selections_utilisateur, -> { where(source: sources.fetch(:selection_utilisateur)) }
|
||||||
scope :quartiers_prioritaires, -> { where(source: sources.fetch(:quartier_prioritaire)) }
|
|
||||||
scope :cadastres, -> { where(source: sources.fetch(:cadastre)) }
|
scope :cadastres, -> { where(source: sources.fetch(:cadastre)) }
|
||||||
scope :parcelles_agricoles, -> { where(source: sources.fetch(:parcelle_agricole)) }
|
|
||||||
|
|
||||||
def to_feature
|
def to_feature
|
||||||
{
|
{
|
||||||
|
|
|
@ -19,7 +19,7 @@ class Individual < ApplicationRecord
|
||||||
validates :nom, presence: true, allow_blank: false, allow_nil: false, on: :update
|
validates :nom, presence: true, allow_blank: false, allow_nil: false, on: :update
|
||||||
validates :prenom, presence: true, allow_blank: false, allow_nil: false, on: :update
|
validates :prenom, presence: true, allow_blank: false, allow_nil: false, on: :update
|
||||||
|
|
||||||
GENDER_MALE = 'M.'
|
GENDER_MALE = "M."
|
||||||
GENDER_FEMALE = 'Mme'
|
GENDER_FEMALE = 'Mme'
|
||||||
|
|
||||||
def self.from_france_connect(fc_information)
|
def self.from_france_connect(fc_information)
|
||||||
|
|
|
@ -56,7 +56,7 @@ class TypeDeChamp < ApplicationRecord
|
||||||
belongs_to :parent, class_name: 'TypeDeChamp', optional: true
|
belongs_to :parent, class_name: 'TypeDeChamp', optional: true
|
||||||
has_many :types_de_champ, -> { ordered }, foreign_key: :parent_id, class_name: 'TypeDeChamp', inverse_of: :parent, dependent: :destroy
|
has_many :types_de_champ, -> { ordered }, foreign_key: :parent_id, class_name: 'TypeDeChamp', inverse_of: :parent, dependent: :destroy
|
||||||
|
|
||||||
store_accessor :options, :cadastres, :quartiers_prioritaires, :parcelles_agricoles, :mnhn, :old_pj, :drop_down_options, :skip_pj_validation
|
store_accessor :options, :cadastres, :old_pj, :drop_down_options, :skip_pj_validation
|
||||||
has_many :revision_types_de_champ, class_name: 'ProcedureRevisionTypeDeChamp', dependent: :destroy, inverse_of: :type_de_champ
|
has_many :revision_types_de_champ, class_name: 'ProcedureRevisionTypeDeChamp', dependent: :destroy, inverse_of: :type_de_champ
|
||||||
has_many :revisions, through: :revision_types_de_champ
|
has_many :revisions, through: :revision_types_de_champ
|
||||||
|
|
||||||
|
@ -197,6 +197,10 @@ class TypeDeChamp < ApplicationRecord
|
||||||
type_champ == TypeDeChamp.type_champs.fetch(:number)
|
type_champ == TypeDeChamp.type_champs.fetch(:number)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def titre_identite?
|
||||||
|
type_champ == TypeDeChamp.type_champs.fetch(:titre_identite)
|
||||||
|
end
|
||||||
|
|
||||||
def public?
|
def public?
|
||||||
!private?
|
!private?
|
||||||
end
|
end
|
||||||
|
@ -253,6 +257,23 @@ class TypeDeChamp < ApplicationRecord
|
||||||
GraphQL::Schema::UniqueWithinType.encode('Champ', stable_id)
|
GraphQL::Schema::UniqueWithinType.encode('Champ', stable_id)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def editable_options=(options)
|
||||||
|
self.options.merge!(options)
|
||||||
|
end
|
||||||
|
|
||||||
|
def editable_options
|
||||||
|
options.slice(:cadastres,
|
||||||
|
:unesco,
|
||||||
|
:arretes_protection,
|
||||||
|
:conservatoire_littoral,
|
||||||
|
:reserves_chasse_faune_sauvage,
|
||||||
|
:reserves_biologiques,
|
||||||
|
:reserves_naturelles,
|
||||||
|
:natura_2000,
|
||||||
|
:zones_humides,
|
||||||
|
:znieff)
|
||||||
|
end
|
||||||
|
|
||||||
FEATURE_FLAGS = {}
|
FEATURE_FLAGS = {}
|
||||||
|
|
||||||
def self.type_de_champ_types_for(procedure, user)
|
def self.type_de_champ_types_for(procedure, user)
|
||||||
|
@ -287,8 +308,7 @@ class TypeDeChamp < ApplicationRecord
|
||||||
:drop_down_list_value,
|
:drop_down_list_value,
|
||||||
:piece_justificative_template_filename,
|
:piece_justificative_template_filename,
|
||||||
:piece_justificative_template_url,
|
:piece_justificative_template_url,
|
||||||
:cadastres,
|
:editable_options
|
||||||
:mnhn
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
TYPES_DE_CHAMP = TYPES_DE_CHAMP_BASE
|
TYPES_DE_CHAMP = TYPES_DE_CHAMP_BASE
|
||||||
|
|
|
@ -11,15 +11,6 @@ class GeoAreaSerializer < ActiveModel::Serializer
|
||||||
attribute :code_com, if: :include_cadastre?
|
attribute :code_com, if: :include_cadastre?
|
||||||
attribute :code_arr, if: :include_cadastre?
|
attribute :code_arr, if: :include_cadastre?
|
||||||
|
|
||||||
attribute :code, if: :include_quartier_prioritaire?
|
|
||||||
attribute :nom, if: :include_quartier_prioritaire?
|
|
||||||
attribute :commune, if: :include_quartier_prioritaire?
|
|
||||||
|
|
||||||
attribute :culture, if: :include_parcelle_agricole?
|
|
||||||
attribute :code_culture, if: :include_parcelle_agricole?
|
|
||||||
attribute :surface, if: :include_parcelle_agricole?
|
|
||||||
attribute :bio, if: :include_parcelle_agricole?
|
|
||||||
|
|
||||||
def geometry
|
def geometry
|
||||||
object.safe_geometry
|
object.safe_geometry
|
||||||
end
|
end
|
||||||
|
@ -27,12 +18,4 @@ class GeoAreaSerializer < ActiveModel::Serializer
|
||||||
def include_cadastre?
|
def include_cadastre?
|
||||||
object.source == GeoArea.sources.fetch(:cadastre)
|
object.source == GeoArea.sources.fetch(:cadastre)
|
||||||
end
|
end
|
||||||
|
|
||||||
def include_quartier_prioritaire?
|
|
||||||
object.source == GeoArea.sources.fetch(:quartier_prioritaire)
|
|
||||||
end
|
|
||||||
|
|
||||||
def include_parcelle_agricole?
|
|
||||||
object.source == GeoArea.sources.fetch(:parcelle_agricole)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
class ModuleApiCartoSerializer < ActiveModel::Serializer
|
class ModuleApiCartoSerializer < ActiveModel::Serializer
|
||||||
attributes :use_api_carto,
|
attributes :use_api_carto, :cadastre
|
||||||
:quartiers_prioritaires,
|
|
||||||
:cadastre
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -3,6 +3,6 @@
|
||||||
outer: true,
|
outer: true,
|
||||||
locals: { attachment: @attachment, user_can_upload: @user_can_upload }) %>
|
locals: { attachment: @attachment, user_can_upload: @user_can_upload }) %>
|
||||||
|
|
||||||
<% if @attachment.virus_scanner.pending? %>
|
<% if @attachment.virus_scanner.pending? || @attachment.watermark_pending? %>
|
||||||
<%= fire_event('attachment:update', { url: attachment_url(@attachment.id, { signed_id: @attachment.blob.signed_id, user_can_upload: @user_can_upload }) }.to_json ) %>
|
<%= fire_event('attachment:update', { url: attachment_url(@attachment.id, { signed_id: @attachment.blob.signed_id, user_can_upload: @user_can_upload }) }.to_json ) %>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
- else
|
- else
|
||||||
- root_profile_link, root_profile_libelle = root_path_info_for_profile(nav_bar_profile)
|
- root_profile_link, root_profile_libelle = root_path_info_for_profile(nav_bar_profile)
|
||||||
= link_to root_profile_link, class: 'header-logo justify-center', title: root_profile_libelle do
|
= link_to root_profile_link, class: 'header-logo justify-center', title: root_profile_libelle do
|
||||||
= image_tag 'marianne.png', alt: 'Liberté, égalité, fraternité', width: '65', height: 56, loading: 'lazy'
|
= image_tag HEADER_LOGO_SRC, alt: HEADER_LOGO_ALT, width: HEADER_LOGO_WIDTH, height: HEADER_LOGO_HEIGHT, loading: 'lazy'
|
||||||
%span.big.site-title>
|
%span.big.site-title>
|
||||||
= APPLICATION_NAME
|
= APPLICATION_NAME
|
||||||
%span.small.site-title>
|
%span.small.site-title>
|
||||||
|
|
|
@ -9,9 +9,9 @@
|
||||||
%title
|
%title
|
||||||
= content_for?(:title) ? "#{yield(:title)} · #{APPLICATION_NAME}" : APPLICATION_NAME
|
= content_for?(:title) ? "#{yield(:title)} · #{APPLICATION_NAME}" : APPLICATION_NAME
|
||||||
|
|
||||||
= favicon_link_tag(image_url("favicons/16x16.png"), type: "image/png", sizes: "16x16")
|
= favicon_link_tag(image_url("#{FAVICON_16PX_SRC}"), type: "image/png", sizes: "16x16")
|
||||||
= favicon_link_tag(image_url("favicons/32x32.png"), type: "image/png", sizes: "32x32")
|
= favicon_link_tag(image_url("#{FAVICON_32PX_SRC}"), type: "image/png", sizes: "32x32")
|
||||||
= favicon_link_tag(image_url("favicons/96x96.png"), type: "image/png", sizes: "96x96")
|
= favicon_link_tag(image_url("#{FAVICON_96PX_SRC}"), type: "image/png", sizes: "96x96")
|
||||||
|
|
||||||
- packs = ['application', 'track', administrateur_signed_in? ? 'track-admin' : nil].compact
|
- packs = ['application', 'track', administrateur_signed_in? ? 'track-admin' : nil].compact
|
||||||
= javascript_packs_with_chunks_tag *packs, defer: true
|
= javascript_packs_with_chunks_tag *packs, defer: true
|
||||||
|
|
|
@ -5,9 +5,9 @@
|
||||||
= t('dynamics.page_title')
|
= t('dynamics.page_title')
|
||||||
%meta{ 'http-equiv' => "X-UA-Compatible", :content => "IE=edge" }
|
%meta{ 'http-equiv' => "X-UA-Compatible", :content => "IE=edge" }
|
||||||
|
|
||||||
= favicon_link_tag(image_url("favicons/16x16.png"), type: "image/png", sizes: "16x16")
|
= favicon_link_tag(image_url("#{FAVICON_16PX_SRC}"), type: "image/png", sizes: "16x16")
|
||||||
= favicon_link_tag(image_url("favicons/32x32.png"), type: "image/png", sizes: "32x32")
|
= favicon_link_tag(image_url("#{FAVICON_32PX_SRC}"), type: "image/png", sizes: "32x32")
|
||||||
= favicon_link_tag(image_url("favicons/96x96.png"), type: "image/png", sizes: "96x96")
|
= favicon_link_tag(image_url("#{FAVICON_96PX_SRC}"), type: "image/png", sizes: "96x96")
|
||||||
|
|
||||||
= stylesheet_link_tag 'application', media: 'all'
|
= stylesheet_link_tag 'application', media: 'all'
|
||||||
= stylesheet_link_tag 'print', media: 'print'
|
= stylesheet_link_tag 'print', media: 'print'
|
||||||
|
|
|
@ -50,7 +50,7 @@
|
||||||
<tr>
|
<tr>
|
||||||
<td style="word-wrap:break-word;font-size:0px;padding:0;padding-top:0px;padding-bottom:0px;" align="left">
|
<td style="word-wrap:break-word;font-size:0px;padding:0;padding-top:0px;padding-bottom:0px;" align="left">
|
||||||
<div class="" style="cursor:auto;color:#55575d;font-family:Helvetica, Arial, sans-serif;font-size:11px;text-align:left;">
|
<div class="" style="cursor:auto;color:#55575d;font-family:Helvetica, Arial, sans-serif;font-size:11px;text-align:left;">
|
||||||
<img align="middle" alt="Logo <%= "#{APPLICATION_NAME}" %>" src="<%= image_url('mailer/instructeur_mailer/logo.png') %>" style="max-width=600px; padding=30px 0; display=inline !important; vertical-align=bottom; border=0; height=auto; outline=none; text-decoration=none; -ms-interpolation-mode=bicubic;" />
|
<img align="middle" alt="Logo <%= "#{APPLICATION_NAME}" %>" src="<%= image_url("#{MAILER_LOGO_SRC}") %>" style="max-width=600px; padding=30px 0; display=inline !important; vertical-align=bottom; border=0; height=auto; outline=none; text-decoration=none; -ms-interpolation-mode=bicubic;" />
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
|
@ -8,9 +8,9 @@
|
||||||
%title
|
%title
|
||||||
= t("dynamics.page_title")
|
= t("dynamics.page_title")
|
||||||
|
|
||||||
= favicon_link_tag(image_url("favicons/16x16.png"), type: "image/png", sizes: "16x16")
|
= favicon_link_tag(image_url("#{FAVICON_16PX_SRC}"), type: "image/png", sizes: "16x16")
|
||||||
= favicon_link_tag(image_url("favicons/32x32.png"), type: "image/png", sizes: "32x32")
|
= favicon_link_tag(image_url("#{FAVICON_32PX_SRC}"), type: "image/png", sizes: "32x32")
|
||||||
= favicon_link_tag(image_url("favicons/96x96.png"), type: "image/png", sizes: "96x96")
|
= favicon_link_tag(image_url("#{FAVICON_96PX_SRC}"), type: "image/png", sizes: "96x96")
|
||||||
|
|
||||||
= stylesheet_link_tag "new_design/print", media: "all"
|
= stylesheet_link_tag "new_design/print", media: "all"
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
- should_display_link = attachment.virus_scanner.safe? || !attachment.virus_scanner.started?
|
- should_display_link = (attachment.virus_scanner.safe? || !attachment.virus_scanner.started?) && !attachment.watermark_pending?
|
||||||
- user_can_upload = defined?(user_can_upload) ? user_can_upload : false
|
- user_can_upload = defined?(user_can_upload) ? user_can_upload : false
|
||||||
- if should_display_link
|
- if should_display_link
|
||||||
- attachment_check_url = false
|
- attachment_check_url = false
|
||||||
|
@ -19,6 +19,10 @@
|
||||||
(analyse antivirus en cours
|
(analyse antivirus en cours
|
||||||
= link_to "rafraichir", request.path, data: { 'attachment-refresh': true }
|
= link_to "rafraichir", request.path, data: { 'attachment-refresh': true }
|
||||||
)
|
)
|
||||||
|
- elsif attachment.watermark_pending?
|
||||||
|
(traitement de la pièce en cours
|
||||||
|
= link_to "rafraichir", request.path, data: { 'attachment-refresh': true }
|
||||||
|
)
|
||||||
- elsif attachment.virus_scanner.infected?
|
- elsif attachment.virus_scanner.infected?
|
||||||
- if user_can_upload
|
- if user_can_upload
|
||||||
(virus détecté, merci d’envoyer un autre fichier)
|
(virus détecté, merci d’envoyer un autre fichier)
|
||||||
|
|
|
@ -2,9 +2,9 @@
|
||||||
%legend.mandatory-explanation
|
%legend.mandatory-explanation
|
||||||
Sélectionnez une des valeurs
|
Sélectionnez une des valeurs
|
||||||
%label
|
%label
|
||||||
= form.radio_button :value, Individual::GENDER_MALE
|
= form.radio_button :value, Individual::GENDER_FEMALE
|
||||||
Monsieur
|
= t(Individual::GENDER_FEMALE, scope: 'activerecord.attributes.individual.gender_options')
|
||||||
|
|
||||||
%label
|
%label
|
||||||
= form.radio_button :value, Individual::GENDER_FEMALE
|
= form.radio_button :value, Individual::GENDER_MALE
|
||||||
Madame
|
= t('activerecord.attributes.individual.gender_options')[Individual::GENDER_MALE.to_sym] # GENDER_MALE contains a point letter
|
||||||
|
|
|
@ -12,12 +12,12 @@
|
||||||
%legend
|
%legend
|
||||||
= f.label :gender
|
= f.label :gender
|
||||||
.radios
|
.radios
|
||||||
%label
|
|
||||||
= f.radio_button :gender, Individual::GENDER_MALE, required: true
|
|
||||||
= Individual::GENDER_MALE
|
|
||||||
%label
|
%label
|
||||||
= f.radio_button :gender, Individual::GENDER_FEMALE, required: true
|
= f.radio_button :gender, Individual::GENDER_FEMALE, required: true
|
||||||
= Individual::GENDER_FEMALE
|
= t(Individual::GENDER_FEMALE, scope: 'activerecord.attributes.individual.gender_options')
|
||||||
|
%label
|
||||||
|
= f.radio_button :gender, Individual::GENDER_MALE, required: true
|
||||||
|
= t('activerecord.attributes.individual.gender_options')[Individual::GENDER_MALE.to_sym] # GENDER_MALE contains a point letter
|
||||||
|
|
||||||
.flex
|
.flex
|
||||||
.inline-champ
|
.inline-champ
|
||||||
|
|
|
@ -3,6 +3,7 @@ require 'mina/git'
|
||||||
require 'mina/rails'
|
require 'mina/rails'
|
||||||
require 'mina/rbenv'
|
require 'mina/rbenv'
|
||||||
|
|
||||||
|
SHARED_WORKER_FILE_NAME = 'i_am_a_worker'
|
||||||
# Basic settings:
|
# Basic settings:
|
||||||
# domain - The hostname to SSH to.
|
# domain - The hostname to SSH to.
|
||||||
# deploy_to - Path to deploy into.
|
# deploy_to - Path to deploy into.
|
||||||
|
@ -95,9 +96,13 @@ namespace :service do
|
||||||
|
|
||||||
desc "Restart delayed_job"
|
desc "Restart delayed_job"
|
||||||
task :restart_delayed_job do
|
task :restart_delayed_job do
|
||||||
|
worker_file_path = File.join(deploy_to, 'shared', SHARED_WORKER_FILE_NAME)
|
||||||
|
|
||||||
command %{
|
command %{
|
||||||
echo "-----> Restarting delayed_job service"
|
echo "-----> Restarting delayed_job service"
|
||||||
#{echo_cmd %[sudo systemctl restart delayed_job]}
|
#{echo_cmd %[test -f #{worker_file_path} && echo 'it is a worker marchine, restarting delayed_job']}
|
||||||
|
#{echo_cmd %[test -f #{worker_file_path} && sudo systemctl restart delayed_job]}
|
||||||
|
#{echo_cmd %[test -f #{worker_file_path} || echo "it is not a worker marchine, #{worker_file_path} is absent"]}
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -21,8 +21,25 @@ APPLICATION_BASE_URL="https://www.demarches-simplifiees.fr"
|
||||||
# OLD_CONTACT_EMAIL=""
|
# OLD_CONTACT_EMAIL=""
|
||||||
# CONTACT_PHONE=""
|
# CONTACT_PHONE=""
|
||||||
|
|
||||||
|
# Personnalisation d'instance - URL pour la création de compte administrateur sur l'instance
|
||||||
|
# DEMANDE_INSCRIPTION_ADMIN_PAGE_URL=""
|
||||||
|
|
||||||
# Personnalisation d'instance - Page externe "Disponibilité" (status page)
|
# Personnalisation d'instance - Page externe "Disponibilité" (status page)
|
||||||
# STATUS_PAGE_URL=""
|
# STATUS_PAGE_URL=""
|
||||||
|
|
||||||
|
# Personnalisation d'instance - Favicons ---> à placer dans "app/assets/images"
|
||||||
|
# FAVICON_16PX_SRC="favicons/16x16.png"
|
||||||
|
# FAVICON_32PX_SRC="favicons/32x32.png"
|
||||||
|
# FAVICON_96PX_SRC="favicons/96x96.png"
|
||||||
|
|
||||||
|
# Personnalisation d'instance - Logo de l'application ---> à placer dans "app/assets/images"
|
||||||
|
# HEADER_LOGO_SRC="marianne.png"
|
||||||
|
# HEADER_LOGO_ALT=""
|
||||||
|
# HEADER_LOGO_WIDTH="65"
|
||||||
|
# HEADER_LOGO_HEIGHT="56"
|
||||||
|
|
||||||
|
# Personnalisation d'instance - Logo dans l'entête des emails ---> à placer dans "app/assets/images"
|
||||||
|
# MAILER_LOGO_SRC="mailer/instructeur_mailer/logo.png"
|
||||||
|
|
||||||
# Personnalisation d'instance - fichier utilisé pour poser un filigrane sur les pièces d'identité
|
# Personnalisation d'instance - fichier utilisé pour poser un filigrane sur les pièces d'identité
|
||||||
# WATERMARK_FILE=""
|
# WATERMARK_FILE=""
|
||||||
|
|
|
@ -32,8 +32,7 @@ features = [
|
||||||
:mini_profiler,
|
:mini_profiler,
|
||||||
:xray,
|
:xray,
|
||||||
:carte_ign,
|
:carte_ign,
|
||||||
:localization,
|
:localization
|
||||||
:titre_identite_watermark
|
|
||||||
]
|
]
|
||||||
|
|
||||||
def database_exists?
|
def database_exists?
|
||||||
|
|
13
config/initializers/images.rb
Normal file
13
config/initializers/images.rb
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
# Favicons
|
||||||
|
FAVICON_16PX_SRC = ENV.fetch("FAVICON_16PX_SRC", "favicons/16x16.png")
|
||||||
|
FAVICON_32PX_SRC = ENV.fetch("FAVICON_32PX_SRC", "favicons/32x32.png")
|
||||||
|
FAVICON_96PX_SRC = ENV.fetch("FAVICON_96PX_SRC", "favicons/96x96.png")
|
||||||
|
|
||||||
|
# Header logo
|
||||||
|
HEADER_LOGO_SRC = ENV.fetch("HEADER_LOGO_SRC", "marianne.png")
|
||||||
|
HEADER_LOGO_ALT = ENV.fetch("HEADER_LOGO_ALT", "Liberté, égalité, fraternité")
|
||||||
|
HEADER_LOGO_WIDTH = ENV.fetch("HEADER_LOGO_WIDTH", "65")
|
||||||
|
HEADER_LOGO_HEIGHT = ENV.fetch("HEADER_LOGO_HEIGHT", "56")
|
||||||
|
|
||||||
|
# Mailer logo
|
||||||
|
MAILER_LOGO_SRC = ENV.fetch("MAILER_LOGO_SRC", "mailer/instructeur_mailer/logo.png")
|
|
@ -6,3 +6,6 @@ fr:
|
||||||
nom: Nom
|
nom: Nom
|
||||||
prenom: Prénom
|
prenom: Prénom
|
||||||
birthdate: Date de naissance
|
birthdate: Date de naissance
|
||||||
|
gender_options:
|
||||||
|
"Mme": "Madame"
|
||||||
|
"M." : "Monsieur"
|
||||||
|
|
|
@ -3,6 +3,5 @@ task :lint do
|
||||||
sh "bundle exec haml-lint app/views/"
|
sh "bundle exec haml-lint app/views/"
|
||||||
sh "bundle exec scss-lint app/assets/stylesheets/"
|
sh "bundle exec scss-lint app/assets/stylesheets/"
|
||||||
sh "bundle exec brakeman --no-pager"
|
sh "bundle exec brakeman --no-pager"
|
||||||
sh "yarn lint:ec"
|
|
||||||
sh "yarn lint:js"
|
sh "yarn lint:js"
|
||||||
end
|
end
|
||||||
|
|
42
package.json
42
package.json
|
@ -1,21 +1,21 @@
|
||||||
{
|
{
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/preset-react": "^7.10.4",
|
"@babel/preset-react": "^7.12.10",
|
||||||
"@fortawesome/fontawesome-svg-core": "^1.2.28",
|
"@fortawesome/fontawesome-svg-core": "^1.2.32",
|
||||||
"@fortawesome/free-solid-svg-icons": "^5.13.0",
|
"@fortawesome/free-solid-svg-icons": "^5.15.1",
|
||||||
"@fortawesome/react-fontawesome": "^0.1.9",
|
"@fortawesome/react-fontawesome": "^0.1.13",
|
||||||
"@mapbox/mapbox-gl-draw": "^1.2.0",
|
"@mapbox/mapbox-gl-draw": "^1.2.0",
|
||||||
"@rails/actiontext": "^6.0.3",
|
"@rails/actiontext": "^6.1.0",
|
||||||
"@rails/activestorage": "^6.0.3",
|
"@rails/activestorage": "^6.1.0",
|
||||||
"@rails/ujs": "^6.0.3",
|
"@rails/ujs": "^6.1.0",
|
||||||
"@rails/webpacker": "5.1.1",
|
"@rails/webpacker": "5.2.1",
|
||||||
"@reach/combobox": "^0.10.2",
|
"@reach/combobox": "^0.10.2",
|
||||||
"@sentry/browser": "^5.15.5",
|
"@sentry/browser": "^5.29.0",
|
||||||
"@tmcw/togeojson": "^4.0.0",
|
"@tmcw/togeojson": "^4.0.0",
|
||||||
"babel-plugin-macros": "^2.8.0",
|
"babel-plugin-macros": "^2.8.0",
|
||||||
"babel-plugin-transform-react-remove-prop-types": "^0.4.24",
|
"babel-plugin-transform-react-remove-prop-types": "^0.4.24",
|
||||||
"chartkick": "^3.2.0",
|
"chartkick": "^3.2.0",
|
||||||
"core-js": "^3.6.5",
|
"core-js": "^3.8.1",
|
||||||
"debounce": "^1.2.0",
|
"debounce": "^1.2.0",
|
||||||
"dom4": "^2.1.5",
|
"dom4": "^2.1.5",
|
||||||
"email-butler": "^1.0.13",
|
"email-butler": "^1.0.13",
|
||||||
|
@ -30,31 +30,29 @@
|
||||||
"react-intersection-observer": "^8.26.2",
|
"react-intersection-observer": "^8.26.2",
|
||||||
"react-mapbox-gl": "^4.8.6",
|
"react-mapbox-gl": "^4.8.6",
|
||||||
"react-mapbox-gl-draw": "^2.0.4",
|
"react-mapbox-gl-draw": "^2.0.4",
|
||||||
"react-query": "^2.23.1",
|
"react-query": "^2.26.4",
|
||||||
"react-scroll-to-component": "^1.0.2",
|
"react-scroll-to-component": "^1.0.2",
|
||||||
"react-sortable-hoc": "^1.11.0",
|
"react-sortable-hoc": "^1.11.0",
|
||||||
"react-use": "^15.3.4",
|
"react-use": "^15.3.4",
|
||||||
"react_ujs": "^2.6.1",
|
"react_ujs": "^2.6.1",
|
||||||
"select2": "^4.0.13",
|
"select2": "^4.0.13",
|
||||||
"trix": "^1.2.3",
|
"trix": "^1.2.3",
|
||||||
"whatwg-fetch": "^3.0.0"
|
"whatwg-fetch": "^3.5.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@2fd/graphdoc": "^2.4.0",
|
"@2fd/graphdoc": "^2.4.0",
|
||||||
"babel-eslint": "^10.1.0",
|
"babel-eslint": "^10.1.0",
|
||||||
"eclint": "^2.8.1",
|
"eslint": "^7.15.0",
|
||||||
"eslint": "^7.0.0",
|
"eslint-config-prettier": "^7.0.0",
|
||||||
"eslint-config-prettier": "^6.11.0",
|
"eslint-plugin-prettier": "^3.2.0",
|
||||||
"eslint-plugin-prettier": "^3.1.3",
|
"eslint-plugin-react": "^7.21.5",
|
||||||
"eslint-plugin-react": "^7.20.0",
|
"eslint-plugin-react-hooks": "^4.2.0",
|
||||||
"eslint-plugin-react-hooks": "^4.0.2",
|
"netlify-cli": "^2.69.4",
|
||||||
"netlify-cli": "^2.61.2",
|
"prettier": "^2.2.1",
|
||||||
"prettier": "^2.0.5",
|
"webpack-bundle-analyzer": "^4.2.0",
|
||||||
"webpack-bundle-analyzer": "^3.7.0",
|
|
||||||
"webpack-dev-server": "^3.11.0"
|
"webpack-dev-server": "^3.11.0"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"lint:ec": "eclint check $({ git ls-files | grep -v app/graphql/schema.graphql ; find vendor -type f ; echo 'db/schema.rb' ; } | sort | uniq -u)",
|
|
||||||
"lint:js": "eslint ./app/javascript ./app/assets/javascripts ./config/webpack",
|
"lint:js": "eslint ./app/javascript ./app/assets/javascripts ./config/webpack",
|
||||||
"webpack:build": "NODE_ENV=production bin/webpack",
|
"webpack:build": "NODE_ENV=production bin/webpack",
|
||||||
"graphql:docs:build": "graphdoc --force",
|
"graphql:docs:build": "graphdoc --force",
|
||||||
|
|
|
@ -636,11 +636,12 @@ describe API::V2::GraphqlController do
|
||||||
|
|
||||||
describe 'dossierPasserEnInstruction' do
|
describe 'dossierPasserEnInstruction' do
|
||||||
let(:dossier) { create(:dossier, :en_construction, :with_individual, procedure: procedure) }
|
let(:dossier) { create(:dossier, :en_construction, :with_individual, procedure: procedure) }
|
||||||
|
let(:instructeur_id) { instructeur.to_typed_id }
|
||||||
let(:query) do
|
let(:query) do
|
||||||
"mutation {
|
"mutation {
|
||||||
dossierPasserEnInstruction(input: {
|
dossierPasserEnInstruction(input: {
|
||||||
dossierId: \"#{dossier.to_typed_id}\",
|
dossierId: \"#{dossier.to_typed_id}\",
|
||||||
instructeurId: \"#{instructeur.to_typed_id}\"
|
instructeurId: \"#{instructeur_id}\"
|
||||||
}) {
|
}) {
|
||||||
dossier {
|
dossier {
|
||||||
id
|
id
|
||||||
|
@ -680,6 +681,18 @@ describe API::V2::GraphqlController do
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context 'instructeur error' do
|
||||||
|
let(:instructeur_id) { create(:instructeur).to_typed_id }
|
||||||
|
|
||||||
|
it "should fail" do
|
||||||
|
expect(gql_errors).to eq(nil)
|
||||||
|
expect(gql_data).to eq(dossierPasserEnInstruction: {
|
||||||
|
errors: [{ message: 'L’instructeur n’a pas les droits d’accès à ce dossier' }],
|
||||||
|
dossier: nil
|
||||||
|
})
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe 'dossierClasserSansSuite' do
|
describe 'dossierClasserSansSuite' do
|
||||||
|
@ -885,6 +898,29 @@ describe API::V2::GraphqlController do
|
||||||
}"
|
}"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
let(:attach_query) do
|
||||||
|
"mutation {
|
||||||
|
dossierEnvoyerMessage(input: {
|
||||||
|
dossierId: \"#{dossier.to_typed_id}\",
|
||||||
|
instructeurId: \"#{instructeur.to_typed_id}\",
|
||||||
|
body: \"Hello world\",
|
||||||
|
attachment: \"#{direct_upload_blob_id}\"
|
||||||
|
}) {
|
||||||
|
message {
|
||||||
|
body
|
||||||
|
}
|
||||||
|
errors {
|
||||||
|
message
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
end
|
||||||
|
let(:attach_query_exec) { post :execute, params: { query: attach_query } }
|
||||||
|
let(:attach_query_body) { JSON.parse(attach_query_exec.body, symbolize_names: true) }
|
||||||
|
let(:attach_query_data) { attach_query_body[:data] }
|
||||||
|
let(:direct_upload_data) { gql_data[:createDirectUpload][:directUpload] }
|
||||||
|
let(:direct_upload_blob_id) { direct_upload_data[:signedBlobId] }
|
||||||
|
|
||||||
it "should initiate a direct upload" do
|
it "should initiate a direct upload" do
|
||||||
expect(gql_errors).to eq(nil)
|
expect(gql_errors).to eq(nil)
|
||||||
|
|
||||||
|
@ -894,6 +930,15 @@ describe API::V2::GraphqlController do
|
||||||
expect(data[:blobId]).not_to be_nil
|
expect(data[:blobId]).not_to be_nil
|
||||||
expect(data[:signedBlobId]).not_to be_nil
|
expect(data[:signedBlobId]).not_to be_nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it "wrong hash error" do
|
||||||
|
blob = ActiveStorage::Blob.find direct_upload_data[:blobId]
|
||||||
|
blob.service.upload blob.key, StringIO.new('toto')
|
||||||
|
expect(attach_query_data).to eq(dossierEnvoyerMessage: {
|
||||||
|
errors: [{ message: "Le hash du fichier téléversé est invalide" }],
|
||||||
|
message: nil
|
||||||
|
})
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe 'dossierChangerGroupeInstructeur' do
|
describe 'dossierChangerGroupeInstructeur' do
|
||||||
|
|
|
@ -30,7 +30,7 @@ describe Champs::SiretController, type: :controller do
|
||||||
|
|
||||||
before do
|
before do
|
||||||
sign_in user
|
sign_in user
|
||||||
stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/etablissements\/#{siret}?.*token=/)
|
stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/etablissements\/#{siret}/)
|
||||||
.to_return(status: api_etablissement_status, body: api_etablissement_body)
|
.to_return(status: api_etablissement_status, body: api_etablissement_body)
|
||||||
allow_any_instance_of(ApiEntrepriseToken).to receive(:roles)
|
allow_any_instance_of(ApiEntrepriseToken).to receive(:roles)
|
||||||
.and_return(["attestations_fiscales", "attestations_sociales", "bilans_entreprise_bdf"])
|
.and_return(["attestations_fiscales", "attestations_sociales", "bilans_entreprise_bdf"])
|
||||||
|
|
|
@ -206,7 +206,7 @@ describe Users::DossiersController, type: :controller do
|
||||||
|
|
||||||
before do
|
before do
|
||||||
sign_in(user)
|
sign_in(user)
|
||||||
stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/etablissements\/#{siret}?.*token=/)
|
stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/etablissements\/#{siret}/)
|
||||||
.to_return(status: api_etablissement_status, body: api_etablissement_body)
|
.to_return(status: api_etablissement_status, body: api_etablissement_body)
|
||||||
allow_any_instance_of(ApiEntrepriseToken).to receive(:roles)
|
allow_any_instance_of(ApiEntrepriseToken).to receive(:roles)
|
||||||
.and_return(["attestations_fiscales", "attestations_sociales", "bilans_entreprise_bdf"])
|
.and_return(["attestations_fiscales", "attestations_sociales", "bilans_entreprise_bdf"])
|
||||||
|
|
|
@ -57,7 +57,7 @@ FactoryBot.define do
|
||||||
|
|
||||||
factory :champ_civilite, class: 'Champs::CiviliteChamp' do
|
factory :champ_civilite, class: 'Champs::CiviliteChamp' do
|
||||||
type_de_champ { association :type_de_champ_civilite, procedure: dossier.procedure }
|
type_de_champ { association :type_de_champ_civilite, procedure: dossier.procedure }
|
||||||
value { 'M.' }
|
value { 'Monsieur' }
|
||||||
end
|
end
|
||||||
|
|
||||||
factory :champ_email, class: 'Champs::EmailChamp' do
|
factory :champ_email, class: 'Champs::EmailChamp' do
|
||||||
|
|
|
@ -57,7 +57,7 @@ feature 'wcag rules for usager', js: true do
|
||||||
scenario "dépot d'un dossier" do
|
scenario "dépot d'un dossier" do
|
||||||
click_on 'Commencer la démarche'
|
click_on 'Commencer la démarche'
|
||||||
|
|
||||||
choose 'M.'
|
choose 'Monsieur'
|
||||||
fill_in('individual_prenom', with: 'prenom')
|
fill_in('individual_prenom', with: 'prenom')
|
||||||
fill_in('individual_nom', with: 'nom')
|
fill_in('individual_nom', with: 'nom')
|
||||||
click_on 'Continuer'
|
click_on 'Continuer'
|
||||||
|
|
|
@ -185,7 +185,7 @@ feature 'The routing', js: true do
|
||||||
visit commencer_path(path: procedure.reload.path)
|
visit commencer_path(path: procedure.reload.path)
|
||||||
click_on 'Commencer la démarche'
|
click_on 'Commencer la démarche'
|
||||||
|
|
||||||
choose 'M.'
|
choose 'Monsieur'
|
||||||
fill_in 'individual_nom', with: 'Nom'
|
fill_in 'individual_nom', with: 'Nom'
|
||||||
fill_in 'individual_prenom', with: 'Prenom'
|
fill_in 'individual_prenom', with: 'Prenom'
|
||||||
click_button('Continuer')
|
click_button('Continuer')
|
||||||
|
|
|
@ -329,7 +329,7 @@ feature 'The user' do
|
||||||
end
|
end
|
||||||
|
|
||||||
def fill_individual
|
def fill_individual
|
||||||
choose 'M.'
|
choose 'Monsieur'
|
||||||
fill_in('individual_prenom', with: 'prenom')
|
fill_in('individual_prenom', with: 'prenom')
|
||||||
fill_in('individual_nom', with: 'nom')
|
fill_in('individual_nom', with: 'nom')
|
||||||
click_on 'Continuer'
|
click_on 'Continuer'
|
||||||
|
|
|
@ -20,7 +20,7 @@ feature 'Creating a new dossier:' do
|
||||||
expect(page).to have_current_path identite_dossier_path(user.reload.dossiers.last)
|
expect(page).to have_current_path identite_dossier_path(user.reload.dossiers.last)
|
||||||
expect(page).to have_procedure_description(procedure)
|
expect(page).to have_procedure_description(procedure)
|
||||||
|
|
||||||
choose 'M.'
|
choose 'Monsieur'
|
||||||
fill_in 'individual_nom', with: 'Nom'
|
fill_in 'individual_nom', with: 'Nom'
|
||||||
fill_in 'individual_prenom', with: 'Prenom'
|
fill_in 'individual_prenom', with: 'Prenom'
|
||||||
end
|
end
|
||||||
|
@ -66,17 +66,17 @@ feature 'Creating a new dossier:' do
|
||||||
let(:dossier) { procedure.dossiers.last }
|
let(:dossier) { procedure.dossiers.last }
|
||||||
|
|
||||||
before do
|
before do
|
||||||
stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/etablissements\/#{siret}?.*token=/)
|
stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/etablissements\/#{siret}/)
|
||||||
.to_return(status: 200, body: File.read('spec/fixtures/files/api_entreprise/etablissements.json'))
|
.to_return(status: 200, body: File.read('spec/fixtures/files/api_entreprise/etablissements.json'))
|
||||||
stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/entreprises\/#{siren}?.*token=/)
|
stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/entreprises\/#{siren}/)
|
||||||
.to_return(status: 200, body: File.read('spec/fixtures/files/api_entreprise/entreprises.json'))
|
.to_return(status: 200, body: File.read('spec/fixtures/files/api_entreprise/entreprises.json'))
|
||||||
stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/exercices\/#{siret}?.*token=/)
|
stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/exercices\/#{siret}/)
|
||||||
.to_return(status: 200, body: File.read('spec/fixtures/files/api_entreprise/exercices.json'))
|
.to_return(status: 200, body: File.read('spec/fixtures/files/api_entreprise/exercices.json'))
|
||||||
stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/associations\/#{siret}?.*token=/)
|
stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/associations\/#{siret}/)
|
||||||
.to_return(status: 404, body: '')
|
.to_return(status: 404, body: '')
|
||||||
stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/effectifs_mensuels_acoss_covid\/2020\/02\/entreprise\/#{siren}?.*token=/)
|
stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/effectifs_mensuels_acoss_covid\/2020\/02\/entreprise\/#{siren}/)
|
||||||
.to_return(status: 404, body: '')
|
.to_return(status: 404, body: '')
|
||||||
stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/effectifs_annuels_acoss_covid\/#{siren}?.*token=/)
|
stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/effectifs_annuels_acoss_covid\/#{siren}/)
|
||||||
.to_return(status: 404, body: '')
|
.to_return(status: 404, body: '')
|
||||||
allow_any_instance_of(ApiEntrepriseToken).to receive(:roles).and_return([])
|
allow_any_instance_of(ApiEntrepriseToken).to receive(:roles).and_return([])
|
||||||
allow_any_instance_of(ApiEntrepriseToken).to receive(:expired?).and_return(false)
|
allow_any_instance_of(ApiEntrepriseToken).to receive(:expired?).and_return(false)
|
||||||
|
|
|
@ -57,7 +57,7 @@ feature 'linked dropdown lists' do
|
||||||
end
|
end
|
||||||
|
|
||||||
def fill_individual
|
def fill_individual
|
||||||
choose 'M.'
|
choose 'Monsieur'
|
||||||
fill_in('individual_prenom', with: 'prenom')
|
fill_in('individual_prenom', with: 'prenom')
|
||||||
fill_in('individual_nom', with: 'nom')
|
fill_in('individual_nom', with: 'nom')
|
||||||
click_on 'Continuer'
|
click_on 'Continuer'
|
||||||
|
|
|
@ -7,7 +7,7 @@ RSpec.describe ApiEntreprise::AssociationJob, type: :job do
|
||||||
let(:status) { 200 }
|
let(:status) { 200 }
|
||||||
|
|
||||||
before do
|
before do
|
||||||
stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/associations\/.*token=/)
|
stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/associations\//)
|
||||||
.to_return(body: body, status: status)
|
.to_return(body: body, status: status)
|
||||||
allow_any_instance_of(ApiEntrepriseToken).to receive(:expired?).and_return(false)
|
allow_any_instance_of(ApiEntrepriseToken).to receive(:expired?).and_return(false)
|
||||||
end
|
end
|
||||||
|
|
|
@ -8,7 +8,7 @@ RSpec.describe ApiEntreprise::AttestationFiscaleJob, type: :job do
|
||||||
let(:status) { 200 }
|
let(:status) { 200 }
|
||||||
|
|
||||||
before do
|
before do
|
||||||
stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/attestations_fiscales_dgfip\/#{siren}\?.*token=/)
|
stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/attestations_fiscales_dgfip\/#{siren}/)
|
||||||
.to_return(body: body, status: status)
|
.to_return(body: body, status: status)
|
||||||
stub_request(:get, "https://storage.entreprise.api.gouv.fr/siade/1569156756-f6b7779f99fa95cd60dc03c04fcb-attestation_fiscale_dgfip.pdf")
|
stub_request(:get, "https://storage.entreprise.api.gouv.fr/siade/1569156756-f6b7779f99fa95cd60dc03c04fcb-attestation_fiscale_dgfip.pdf")
|
||||||
.to_return(body: "body attestation", status: 200)
|
.to_return(body: "body attestation", status: 200)
|
||||||
|
|
|
@ -9,7 +9,7 @@ RSpec.describe ApiEntreprise::AttestationSocialeJob, type: :job do
|
||||||
let(:status) { 200 }
|
let(:status) { 200 }
|
||||||
|
|
||||||
before do
|
before do
|
||||||
stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/attestations_sociales_acoss\/#{siren}\?.*token=/)
|
stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/attestations_sociales_acoss\/#{siren}/)
|
||||||
.to_return(body: body, status: status)
|
.to_return(body: body, status: status)
|
||||||
stub_request(:get, "https://storage.entreprise.api.gouv.fr/siade/1569156881-f749d75e2bfd443316e2e02d59015f-attestation_vigilance_acoss.pdf")
|
stub_request(:get, "https://storage.entreprise.api.gouv.fr/siade/1569156881-f749d75e2bfd443316e2e02d59015f-attestation_vigilance_acoss.pdf")
|
||||||
.to_return(body: "body attestation", status: 200)
|
.to_return(body: "body attestation", status: 200)
|
||||||
|
|
|
@ -9,7 +9,7 @@ RSpec.describe ApiEntreprise::BilansBdfJob, type: :job do
|
||||||
let(:bilans_bdf) { JSON.parse(body)["bilans"] }
|
let(:bilans_bdf) { JSON.parse(body)["bilans"] }
|
||||||
|
|
||||||
before do
|
before do
|
||||||
stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/bilans_entreprises_bdf\/#{siren}\?.*token=/)
|
stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/bilans_entreprises_bdf\/#{siren}/)
|
||||||
.to_return(body: body, status: status)
|
.to_return(body: body, status: status)
|
||||||
allow_any_instance_of(ApiEntrepriseToken).to receive(:roles).and_return(["bilans_entreprise_bdf"])
|
allow_any_instance_of(ApiEntrepriseToken).to receive(:roles).and_return(["bilans_entreprise_bdf"])
|
||||||
allow_any_instance_of(ApiEntrepriseToken).to receive(:expired?).and_return(false)
|
allow_any_instance_of(ApiEntrepriseToken).to receive(:expired?).and_return(false)
|
||||||
|
|
|
@ -8,7 +8,7 @@ RSpec.describe ApiEntreprise::EffectifsAnnuelsJob, type: :job do
|
||||||
let(:status) { 200 }
|
let(:status) { 200 }
|
||||||
|
|
||||||
before do
|
before do
|
||||||
stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/effectifs_annuels_acoss_covid\/#{siren}\?.*token=/)
|
stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/effectifs_annuels_acoss_covid\/#{siren}/)
|
||||||
.to_return(body: body, status: status)
|
.to_return(body: body, status: status)
|
||||||
allow_any_instance_of(ApiEntrepriseToken).to receive(:expired?).and_return(false)
|
allow_any_instance_of(ApiEntrepriseToken).to receive(:expired?).and_return(false)
|
||||||
end
|
end
|
||||||
|
|
|
@ -11,7 +11,7 @@ RSpec.describe ApiEntreprise::EffectifsJob, type: :job do
|
||||||
let(:status) { 200 }
|
let(:status) { 200 }
|
||||||
|
|
||||||
before do
|
before do
|
||||||
stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/effectifs_mensuels_acoss_covid\/#{annee}\/#{mois}\/entreprise\/#{siren}\?.*token=/)
|
stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/effectifs_mensuels_acoss_covid\/#{annee}\/#{mois}\/entreprise\/#{siren}/)
|
||||||
.to_return(body: body, status: status)
|
.to_return(body: body, status: status)
|
||||||
allow_any_instance_of(ApiEntrepriseToken).to receive(:expired?).and_return(false)
|
allow_any_instance_of(ApiEntrepriseToken).to receive(:expired?).and_return(false)
|
||||||
end
|
end
|
||||||
|
|
|
@ -8,7 +8,7 @@ RSpec.describe ApiEntreprise::EntrepriseJob, type: :job do
|
||||||
let(:status) { 200 }
|
let(:status) { 200 }
|
||||||
|
|
||||||
before do
|
before do
|
||||||
stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/entreprises\/#{siren}?.*token=/)
|
stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/entreprises\/#{siren}/)
|
||||||
.to_return(body: body, status: status)
|
.to_return(body: body, status: status)
|
||||||
allow_any_instance_of(ApiEntrepriseToken).to receive(:expired?).and_return(false)
|
allow_any_instance_of(ApiEntrepriseToken).to receive(:expired?).and_return(false)
|
||||||
end
|
end
|
||||||
|
|
|
@ -6,7 +6,7 @@ RSpec.describe ApiEntreprise::ExercicesJob, type: :job do
|
||||||
let(:status) { 200 }
|
let(:status) { 200 }
|
||||||
|
|
||||||
before do
|
before do
|
||||||
stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/exercices\/.*token=/)
|
stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/exercices\//)
|
||||||
.to_return(body: body, status: status)
|
.to_return(body: body, status: status)
|
||||||
allow_any_instance_of(ApiEntrepriseToken).to receive(:expired?).and_return(false)
|
allow_any_instance_of(ApiEntrepriseToken).to receive(:expired?).and_return(false)
|
||||||
end
|
end
|
||||||
|
|
|
@ -7,7 +7,7 @@ describe ApiEntreprise::API do
|
||||||
subject { described_class.entreprise(siren, procedure_id) }
|
subject { described_class.entreprise(siren, procedure_id) }
|
||||||
|
|
||||||
before do
|
before do
|
||||||
stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/entreprises\/#{siren}?.*token=#{token}/)
|
stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/entreprises\/#{siren}/)
|
||||||
.to_return(status: status, body: body)
|
.to_return(status: status, body: body)
|
||||||
allow_any_instance_of(ApiEntrepriseToken).to receive(:expired?).and_return(false)
|
allow_any_instance_of(ApiEntrepriseToken).to receive(:expired?).and_return(false)
|
||||||
end
|
end
|
||||||
|
@ -68,7 +68,7 @@ describe ApiEntreprise::API do
|
||||||
|
|
||||||
it 'call api-entreprise with specfic token' do
|
it 'call api-entreprise with specfic token' do
|
||||||
subject
|
subject
|
||||||
expect(WebMock).to have_requested(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/entreprises\/#{siren}?.*token=#{token}/)
|
expect(WebMock).to have_requested(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/entreprises\/#{siren}/)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -78,7 +78,7 @@ describe ApiEntreprise::API do
|
||||||
|
|
||||||
it 'call api-entreprise with specfic token' do
|
it 'call api-entreprise with specfic token' do
|
||||||
subject
|
subject
|
||||||
expect(WebMock).to have_requested(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/entreprises\/#{siren}?.*token=#{token}/)
|
expect(WebMock).to have_requested(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/entreprises\/#{siren}/)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -87,7 +87,7 @@ describe ApiEntreprise::API do
|
||||||
describe '.etablissement' do
|
describe '.etablissement' do
|
||||||
subject { described_class.etablissement(siret, procedure_id) }
|
subject { described_class.etablissement(siret, procedure_id) }
|
||||||
before do
|
before do
|
||||||
stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/etablissements\/#{siret}?.*non_diffusables=true&.*token=/)
|
stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/etablissements\/#{siret}?.*non_diffusables=true/)
|
||||||
.to_return(status: status, body: body)
|
.to_return(status: status, body: body)
|
||||||
allow_any_instance_of(ApiEntrepriseToken).to receive(:expired?).and_return(false)
|
allow_any_instance_of(ApiEntrepriseToken).to receive(:expired?).and_return(false)
|
||||||
end
|
end
|
||||||
|
@ -115,7 +115,7 @@ describe ApiEntreprise::API do
|
||||||
|
|
||||||
describe '.exercices' do
|
describe '.exercices' do
|
||||||
before do
|
before do
|
||||||
stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/exercices\/.*token=/)
|
stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/exercices\//)
|
||||||
.to_return(status: status, body: body)
|
.to_return(status: status, body: body)
|
||||||
allow_any_instance_of(ApiEntrepriseToken).to receive(:expired?).and_return(false)
|
allow_any_instance_of(ApiEntrepriseToken).to receive(:expired?).and_return(false)
|
||||||
end
|
end
|
||||||
|
@ -147,7 +147,7 @@ describe ApiEntreprise::API do
|
||||||
|
|
||||||
describe '.rna' do
|
describe '.rna' do
|
||||||
before do
|
before do
|
||||||
stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/associations\/.*token=/)
|
stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/associations\//)
|
||||||
.to_return(status: status, body: body)
|
.to_return(status: status, body: body)
|
||||||
allow_any_instance_of(ApiEntrepriseToken).to receive(:expired?).and_return(false)
|
allow_any_instance_of(ApiEntrepriseToken).to receive(:expired?).and_return(false)
|
||||||
end
|
end
|
||||||
|
@ -182,7 +182,7 @@ describe ApiEntreprise::API do
|
||||||
before do
|
before do
|
||||||
allow_any_instance_of(ApiEntrepriseToken).to receive(:roles).and_return(roles)
|
allow_any_instance_of(ApiEntrepriseToken).to receive(:roles).and_return(roles)
|
||||||
allow_any_instance_of(ApiEntrepriseToken).to receive(:expired?).and_return(false)
|
allow_any_instance_of(ApiEntrepriseToken).to receive(:expired?).and_return(false)
|
||||||
stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/attestations_sociales_acoss\/#{siren}?.*token=/)
|
stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/attestations_sociales_acoss\/#{siren}/)
|
||||||
.to_return(body: body, status: status)
|
.to_return(body: body, status: status)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -211,7 +211,7 @@ describe ApiEntreprise::API do
|
||||||
before do
|
before do
|
||||||
allow_any_instance_of(ApiEntrepriseToken).to receive(:roles).and_return(roles)
|
allow_any_instance_of(ApiEntrepriseToken).to receive(:roles).and_return(roles)
|
||||||
allow_any_instance_of(ApiEntrepriseToken).to receive(:expired?).and_return(false)
|
allow_any_instance_of(ApiEntrepriseToken).to receive(:expired?).and_return(false)
|
||||||
stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/attestations_fiscales_dgfip\/#{siren}?.*token=#{token}&user_id=#{user_id}/)
|
stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/attestations_fiscales_dgfip\/#{siren}/)
|
||||||
.to_return(body: body, status: status)
|
.to_return(body: body, status: status)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -239,7 +239,7 @@ describe ApiEntreprise::API do
|
||||||
before do
|
before do
|
||||||
allow_any_instance_of(ApiEntrepriseToken).to receive(:roles).and_return(roles)
|
allow_any_instance_of(ApiEntrepriseToken).to receive(:roles).and_return(roles)
|
||||||
allow_any_instance_of(ApiEntrepriseToken).to receive(:expired?).and_return(false)
|
allow_any_instance_of(ApiEntrepriseToken).to receive(:expired?).and_return(false)
|
||||||
stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/bilans_entreprises_bdf\/#{siren}?.*token=#{token}/)
|
stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/bilans_entreprises_bdf\/#{siren}/)
|
||||||
.to_return(body: body, status: status)
|
.to_return(body: body, status: status)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -268,7 +268,7 @@ describe ApiEntreprise::API do
|
||||||
|
|
||||||
it 'makes no call to api-entreprise' do
|
it 'makes no call to api-entreprise' do
|
||||||
subject
|
subject
|
||||||
expect(WebMock).not_to have_requested(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/entreprises\/#{siren}?.*token=#{token}/)
|
expect(WebMock).not_to have_requested(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/entreprises\/#{siren}/)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -7,7 +7,7 @@ describe ApiEntreprise::AttestationFiscaleAdapter do
|
||||||
subject { adapter.to_params }
|
subject { adapter.to_params }
|
||||||
|
|
||||||
before do
|
before do
|
||||||
stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/attestations_fiscales_dgfip\/#{siren}\?.*token=/)
|
stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/attestations_fiscales_dgfip\/#{siren}/)
|
||||||
.to_return(body: body, status: status)
|
.to_return(body: body, status: status)
|
||||||
allow_any_instance_of(ApiEntrepriseToken).to receive(:roles).and_return(["attestations_fiscales"])
|
allow_any_instance_of(ApiEntrepriseToken).to receive(:roles).and_return(["attestations_fiscales"])
|
||||||
allow_any_instance_of(ApiEntrepriseToken).to receive(:expired?).and_return(false)
|
allow_any_instance_of(ApiEntrepriseToken).to receive(:expired?).and_return(false)
|
||||||
|
|
|
@ -6,7 +6,7 @@ describe ApiEntreprise::AttestationSocialeAdapter do
|
||||||
subject { adapter.to_params }
|
subject { adapter.to_params }
|
||||||
|
|
||||||
before do
|
before do
|
||||||
stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/attestations_sociales_acoss\/#{siren}\?.*token=/)
|
stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/attestations_sociales_acoss\/#{siren}/)
|
||||||
.to_return(body: body, status: status)
|
.to_return(body: body, status: status)
|
||||||
allow_any_instance_of(ApiEntrepriseToken).to receive(:roles).and_return(["attestations_sociales"])
|
allow_any_instance_of(ApiEntrepriseToken).to receive(:roles).and_return(["attestations_sociales"])
|
||||||
allow_any_instance_of(ApiEntrepriseToken).to receive(:expired?).and_return(false)
|
allow_any_instance_of(ApiEntrepriseToken).to receive(:expired?).and_return(false)
|
||||||
|
|
|
@ -7,7 +7,7 @@ describe ApiEntreprise::BilansBdfAdapter do
|
||||||
subject { adapter.to_params }
|
subject { adapter.to_params }
|
||||||
|
|
||||||
before do
|
before do
|
||||||
stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/bilans_entreprises_bdf\/#{siren}\?.*token=/)
|
stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/bilans_entreprises_bdf\/#{siren}/)
|
||||||
.to_return(body: body, status: status)
|
.to_return(body: body, status: status)
|
||||||
allow_any_instance_of(ApiEntrepriseToken).to receive(:roles).and_return(["bilans_entreprise_bdf"])
|
allow_any_instance_of(ApiEntrepriseToken).to receive(:roles).and_return(["bilans_entreprise_bdf"])
|
||||||
allow_any_instance_of(ApiEntrepriseToken).to receive(:expired?).and_return(false)
|
allow_any_instance_of(ApiEntrepriseToken).to receive(:expired?).and_return(false)
|
||||||
|
|
|
@ -9,7 +9,7 @@ describe ApiEntreprise::EffectifsAdapter do
|
||||||
subject { adapter.to_params }
|
subject { adapter.to_params }
|
||||||
|
|
||||||
before do
|
before do
|
||||||
stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/effectifs_mensuels_acoss_covid\/#{annee}\/#{mois}\/entreprise\/#{siren}\?.*token=/)
|
stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/effectifs_mensuels_acoss_covid\/#{annee}\/#{mois}\/entreprise\/#{siren}/)
|
||||||
.to_return(body: body, status: status)
|
.to_return(body: body, status: status)
|
||||||
allow_any_instance_of(ApiEntrepriseToken).to receive(:expired?).and_return(false)
|
allow_any_instance_of(ApiEntrepriseToken).to receive(:expired?).and_return(false)
|
||||||
end
|
end
|
||||||
|
|
|
@ -7,7 +7,7 @@ describe ApiEntreprise::EffectifsAnnuelsAdapter do
|
||||||
subject { adapter.to_params }
|
subject { adapter.to_params }
|
||||||
|
|
||||||
before do
|
before do
|
||||||
stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/effectifs_annuels_acoss_covid\/#{siren}\?.*token=/)
|
stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/effectifs_annuels_acoss_covid\/#{siren}/)
|
||||||
.to_return(body: body, status: status)
|
.to_return(body: body, status: status)
|
||||||
allow_any_instance_of(ApiEntrepriseToken).to receive(:expired?).and_return(false)
|
allow_any_instance_of(ApiEntrepriseToken).to receive(:expired?).and_return(false)
|
||||||
end
|
end
|
||||||
|
|
|
@ -6,7 +6,7 @@ describe ApiEntreprise::EntrepriseAdapter do
|
||||||
subject { adapter.to_params }
|
subject { adapter.to_params }
|
||||||
|
|
||||||
before do
|
before do
|
||||||
stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/entreprises\/#{siren}?.*token=/)
|
stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/entreprises\/#{siren}/)
|
||||||
.to_return(body: body, status: status)
|
.to_return(body: body, status: status)
|
||||||
allow_any_instance_of(ApiEntrepriseToken).to receive(:expired?).and_return(false)
|
allow_any_instance_of(ApiEntrepriseToken).to receive(:expired?).and_return(false)
|
||||||
end
|
end
|
||||||
|
|
|
@ -12,7 +12,7 @@ describe ApiEntreprise::EtablissementAdapter do
|
||||||
subject { described_class.new(siret, procedure_id).to_params }
|
subject { described_class.new(siret, procedure_id).to_params }
|
||||||
|
|
||||||
before do
|
before do
|
||||||
stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/etablissements\/#{siret}?.*token=/)
|
stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/etablissements\/#{siret}/)
|
||||||
.to_return(body: File.read(fixture, status: 200))
|
.to_return(body: File.read(fixture, status: 200))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -99,7 +99,7 @@ describe ApiEntreprise::EtablissementAdapter do
|
||||||
subject { described_class.new(siret, procedure_id).to_params }
|
subject { described_class.new(siret, procedure_id).to_params }
|
||||||
|
|
||||||
before do
|
before do
|
||||||
stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/etablissements\/#{siret}?.*token=/)
|
stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/etablissements\/#{siret}/)
|
||||||
.to_return(body: File.read('spec/fixtures/files/api_entreprise/etablissements_private.json', status: 200))
|
.to_return(body: File.read('spec/fixtures/files/api_entreprise/etablissements_private.json', status: 200))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -113,7 +113,7 @@ describe ApiEntreprise::EtablissementAdapter do
|
||||||
subject { described_class.new(bad_siret, procedure_id).to_params }
|
subject { described_class.new(bad_siret, procedure_id).to_params }
|
||||||
|
|
||||||
before do
|
before do
|
||||||
stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/etablissements\/#{bad_siret}?.*token=/)
|
stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/etablissements\/#{bad_siret}/)
|
||||||
.to_return(body: 'Fake body', status: 404)
|
.to_return(body: 'Fake body', status: 404)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@ describe ApiEntreprise::ExercicesAdapter do
|
||||||
subject { described_class.new(siret, procedure.id).to_params }
|
subject { described_class.new(siret, procedure.id).to_params }
|
||||||
|
|
||||||
before do
|
before do
|
||||||
stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/exercices\/.*token=/)
|
stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/exercices\//)
|
||||||
.to_return(body: File.read('spec/fixtures/files/api_entreprise/exercices.json', status: 200))
|
.to_return(body: File.read('spec/fixtures/files/api_entreprise/exercices.json', status: 200))
|
||||||
allow_any_instance_of(ApiEntrepriseToken).to receive(:expired?).and_return(false)
|
allow_any_instance_of(ApiEntrepriseToken).to receive(:expired?).and_return(false)
|
||||||
end
|
end
|
||||||
|
|
|
@ -9,7 +9,7 @@ describe ApiEntreprise::RNAAdapter do
|
||||||
subject { adapter.to_params }
|
subject { adapter.to_params }
|
||||||
|
|
||||||
before do
|
before do
|
||||||
stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/associations\/.*token=/)
|
stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/associations\//)
|
||||||
.to_return(body: body, status: status)
|
.to_return(body: body, status: status)
|
||||||
allow_any_instance_of(ApiEntrepriseToken).to receive(:expired?).and_return(false)
|
allow_any_instance_of(ApiEntrepriseToken).to receive(:expired?).and_return(false)
|
||||||
end
|
end
|
||||||
|
|
|
@ -1370,4 +1370,58 @@ describe Dossier do
|
||||||
expect(dossier.champs_for_export(dossier.procedure.types_de_champ_for_export)).to eq(dossier_second_revision.champs_for_export(dossier_second_revision.procedure.types_de_champ_for_export))
|
expect(dossier.champs_for_export(dossier.procedure.types_de_champ_for_export)).to eq(dossier_second_revision.champs_for_export(dossier_second_revision.procedure.types_de_champ_for_export))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe "remove_titres_identite!" do
|
||||||
|
let(:dossier) { create(:dossier, :en_instruction, :followed) }
|
||||||
|
let(:type_de_champ_titre_identite) { create(:type_de_champ_titre_identite, procedure: dossier.procedure) }
|
||||||
|
let(:champ_titre_identite) { create(:champ_titre_identite, type_de_champ: type_de_champ_titre_identite) }
|
||||||
|
let(:type_de_champ_titre_identite_vide) { create(:type_de_champ_titre_identite, procedure: dossier.procedure) }
|
||||||
|
let(:champ_titre_identite_vide) { create(:champ_titre_identite, type_de_champ: type_de_champ_titre_identite_vide) }
|
||||||
|
|
||||||
|
before do
|
||||||
|
champ_titre_identite_vide.piece_justificative_file.purge
|
||||||
|
dossier.champs << champ_titre_identite
|
||||||
|
dossier.champs << champ_titre_identite_vide
|
||||||
|
end
|
||||||
|
|
||||||
|
it "clean up titres identite on accepter" do
|
||||||
|
expect(champ_titre_identite.piece_justificative_file.attached?).to be_truthy
|
||||||
|
expect(champ_titre_identite_vide.piece_justificative_file.attached?).to be_falsey
|
||||||
|
perform_enqueued_jobs do
|
||||||
|
dossier.accepter!(dossier.followers_instructeurs.first, "yolo!")
|
||||||
|
end
|
||||||
|
expect(champ_titre_identite.piece_justificative_file.attached?).to be_falsey
|
||||||
|
end
|
||||||
|
|
||||||
|
it "clean up titres identite on refuser" do
|
||||||
|
expect(champ_titre_identite.piece_justificative_file.attached?).to be_truthy
|
||||||
|
expect(champ_titre_identite_vide.piece_justificative_file.attached?).to be_falsey
|
||||||
|
perform_enqueued_jobs do
|
||||||
|
dossier.refuser!(dossier.followers_instructeurs.first, "yolo!")
|
||||||
|
end
|
||||||
|
expect(champ_titre_identite.piece_justificative_file.attached?).to be_falsey
|
||||||
|
end
|
||||||
|
|
||||||
|
it "clean up titres identite on classer_sans_suite" do
|
||||||
|
expect(champ_titre_identite.piece_justificative_file.attached?).to be_truthy
|
||||||
|
expect(champ_titre_identite_vide.piece_justificative_file.attached?).to be_falsey
|
||||||
|
perform_enqueued_jobs do
|
||||||
|
dossier.classer_sans_suite!(dossier.followers_instructeurs.first, "yolo!")
|
||||||
|
end
|
||||||
|
expect(champ_titre_identite.piece_justificative_file.attached?).to be_falsey
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'en_construction' do
|
||||||
|
let(:dossier) { create(:dossier, :en_construction, :followed) }
|
||||||
|
|
||||||
|
it "clean up titres identite on accepter_automatiquement" do
|
||||||
|
expect(champ_titre_identite.piece_justificative_file.attached?).to be_truthy
|
||||||
|
expect(champ_titre_identite_vide.piece_justificative_file.attached?).to be_falsey
|
||||||
|
perform_enqueued_jobs do
|
||||||
|
dossier.accepter_automatiquement!
|
||||||
|
end
|
||||||
|
expect(champ_titre_identite.piece_justificative_file.attached?).to be_falsey
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
describe ApiEntrepriseService do
|
describe ApiEntrepriseService do
|
||||||
describe '#create_etablissement' do
|
describe '#create_etablissement' do
|
||||||
before do
|
before do
|
||||||
stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/etablissements\/#{siret}?.*token=/)
|
stub_request(:get, /https:\/\/entreprise.api.gouv.fr\/v2\/etablissements\/#{siret}/)
|
||||||
.to_return(body: etablissements_body, status: etablissements_status)
|
.to_return(body: etablissements_body, status: etablissements_status)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -27,6 +27,17 @@ describe 'shared/attachment/_show.html.haml', type: :view do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context 'when watermark is pending' do
|
||||||
|
let(:champ) { create(:champ_titre_identite) }
|
||||||
|
|
||||||
|
it 'displays the filename, but doesn’t allow to download the file' do
|
||||||
|
pp champ.piece_justificative_file.attachment.watermark_pending?
|
||||||
|
expect(subject).to have_text(champ.piece_justificative_file.filename.to_s)
|
||||||
|
expect(subject).not_to have_link(champ.piece_justificative_file.filename.to_s)
|
||||||
|
expect(subject).to have_text('traitement de la pièce en cours')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
context 'when the file is scanned and safe' do
|
context 'when the file is scanned and safe' do
|
||||||
let(:virus_scan_result) { ActiveStorage::VirusScanner::SAFE }
|
let(:virus_scan_result) { ActiveStorage::VirusScanner::SAFE }
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue