commit
12ecafb67a
37 changed files with 518 additions and 303 deletions
|
@ -170,7 +170,7 @@ GEM
|
||||||
coffee-script-source
|
coffee-script-source
|
||||||
execjs
|
execjs
|
||||||
coffee-script-source (1.12.2)
|
coffee-script-source (1.12.2)
|
||||||
concurrent-ruby (1.1.8)
|
concurrent-ruby (1.1.9)
|
||||||
connection_pool (2.2.3)
|
connection_pool (2.2.3)
|
||||||
crack (0.4.5)
|
crack (0.4.5)
|
||||||
rexml
|
rexml
|
||||||
|
@ -244,7 +244,7 @@ GEM
|
||||||
execjs (2.7.0)
|
execjs (2.7.0)
|
||||||
factory_bot (6.1.0)
|
factory_bot (6.1.0)
|
||||||
activesupport (>= 5.0.0)
|
activesupport (>= 5.0.0)
|
||||||
faraday (1.4.2)
|
faraday (1.4.3)
|
||||||
faraday-em_http (~> 1.0)
|
faraday-em_http (~> 1.0)
|
||||||
faraday-em_synchrony (~> 1.0)
|
faraday-em_synchrony (~> 1.0)
|
||||||
faraday-excon (~> 1.1)
|
faraday-excon (~> 1.1)
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
@import "colors";
|
@import "colors";
|
||||||
|
@import "constants";
|
||||||
|
|
||||||
.areas-title {
|
.areas-title {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
|
@ -38,6 +39,24 @@
|
||||||
left: 5px;
|
left: 5px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.map-style-panel {
|
||||||
|
z-index: 99;
|
||||||
|
padding: $default-spacer;
|
||||||
|
margin-bottom: $default-spacer;
|
||||||
|
|
||||||
|
ul {
|
||||||
|
list-style: none;
|
||||||
|
padding: $default-spacer;
|
||||||
|
padding-bottom: 0;
|
||||||
|
margin-bottom: -$default-spacer;
|
||||||
|
|
||||||
|
label {
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.cadastres-selection-control {
|
.cadastres-selection-control {
|
||||||
|
|
|
@ -1,11 +1,15 @@
|
||||||
@import "constants";
|
@import "constants";
|
||||||
|
|
||||||
|
.m-0 {
|
||||||
|
margin: 0px !important;
|
||||||
|
}
|
||||||
|
|
||||||
.mb-1 {
|
.mb-1 {
|
||||||
margin-bottom: $default-spacer;
|
margin-bottom: $default-spacer;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mr-1 {
|
.mr-1 {
|
||||||
margin-right: $default-spacer;
|
margin-right: $default-spacer !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mb-4 {
|
.mb-4 {
|
||||||
|
@ -20,6 +24,10 @@
|
||||||
padding-left: 0px !important;
|
padding-left: 0px !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.p-0 {
|
||||||
|
padding: 0px !important;
|
||||||
|
}
|
||||||
|
|
||||||
.bold {
|
.bold {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,7 @@ module Experts
|
||||||
|
|
||||||
before_action :authenticate_expert!, except: [:sign_up, :update_expert]
|
before_action :authenticate_expert!, except: [:sign_up, :update_expert]
|
||||||
before_action :check_if_avis_revoked, only: [:show]
|
before_action :check_if_avis_revoked, only: [:show]
|
||||||
before_action :redirect_if_no_sign_up_needed, only: [:sign_up]
|
before_action :redirect_if_no_sign_up_needed, only: [:sign_up, :update_expert]
|
||||||
before_action :set_avis_and_dossier, only: [:show, :instruction, :messagerie, :create_commentaire, :update]
|
before_action :set_avis_and_dossier, only: [:show, :instruction, :messagerie, :create_commentaire, :update]
|
||||||
|
|
||||||
A_DONNER_STATUS = 'a-donner'
|
A_DONNER_STATUS = 'a-donner'
|
||||||
|
@ -82,12 +82,11 @@ module Experts
|
||||||
email = params[:email]
|
email = params[:email]
|
||||||
password = params[:user][:password]
|
password = params[:user][:password]
|
||||||
|
|
||||||
# Not perfect because the password will not be changed if the user already exists
|
|
||||||
user = User.create_or_promote_to_expert(email, password)
|
user = User.create_or_promote_to_expert(email, password)
|
||||||
|
user.reset_password(password, password)
|
||||||
|
|
||||||
if user.valid?
|
if user.valid?
|
||||||
sign_in(user)
|
sign_in(user)
|
||||||
|
|
||||||
redirect_to url_for(expert_all_avis_path)
|
redirect_to url_for(expert_all_avis_path)
|
||||||
else
|
else
|
||||||
flash[:alert] = user.errors.full_messages
|
flash[:alert] = user.errors.full_messages
|
||||||
|
@ -128,11 +127,9 @@ module Experts
|
||||||
|
|
||||||
if current_expert.present?
|
if current_expert.present?
|
||||||
# an expert is authenticated ... lets see if it can view the dossier
|
# an expert is authenticated ... lets see if it can view the dossier
|
||||||
|
|
||||||
redirect_to expert_avis_url(avis.procedure, avis)
|
redirect_to expert_avis_url(avis.procedure, avis)
|
||||||
|
|
||||||
elsif avis.expert&.email == params[:email] && avis.expert.user.active?.present?
|
elsif avis.expert&.email == params[:email] && avis.expert.user.active?.present?
|
||||||
|
# The expert already used the sign-in page to change their password: ask them to sign-in instead.
|
||||||
redirect_to new_user_session_url
|
redirect_to new_user_session_url
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -7,7 +7,6 @@ module Instructeurs
|
||||||
@average_dossier_weight = procedure.average_dossier_weight
|
@average_dossier_weight = procedure.average_dossier_weight
|
||||||
|
|
||||||
@count_dossiers_termines_by_month = Traitement.count_dossiers_termines_by_month(groupe_instructeurs)
|
@count_dossiers_termines_by_month = Traitement.count_dossiers_termines_by_month(groupe_instructeurs)
|
||||||
@nb_dossiers_termines = @count_dossiers_termines_by_month.sum { |count_by_month| count_by_month["count"] }
|
|
||||||
|
|
||||||
@archives = Archive
|
@archives = Archive
|
||||||
.for_groupe_instructeur(groupe_instructeurs)
|
.for_groupe_instructeur(groupe_instructeurs)
|
||||||
|
|
|
@ -27,7 +27,7 @@ module NewAdministrateur
|
||||||
end
|
end
|
||||||
|
|
||||||
def reset_procedure
|
def reset_procedure
|
||||||
if @procedure.brouillon?
|
if @procedure.brouillon? || @procedure.draft_changed?
|
||||||
@procedure.reset!
|
@procedure.reset!
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -55,11 +55,8 @@ module NewAdministrateur
|
||||||
def show
|
def show
|
||||||
@procedure = current_administrateur.procedures.find(params[:id])
|
@procedure = current_administrateur.procedures.find(params[:id])
|
||||||
@current_administrateur = current_administrateur
|
@current_administrateur = current_administrateur
|
||||||
if @procedure.brouillon?
|
|
||||||
@procedure_lien = commencer_test_url(path: @procedure.path)
|
|
||||||
else
|
|
||||||
@procedure_lien = commencer_url(path: @procedure.path)
|
@procedure_lien = commencer_url(path: @procedure.path)
|
||||||
end
|
@procedure_lien_test = commencer_test_url(path: @procedure.path)
|
||||||
end
|
end
|
||||||
|
|
||||||
def edit
|
def edit
|
||||||
|
@ -142,11 +139,8 @@ module NewAdministrateur
|
||||||
end
|
end
|
||||||
|
|
||||||
def publication
|
def publication
|
||||||
if @procedure.brouillon?
|
|
||||||
@procedure_lien = commencer_test_url(path: @procedure.path)
|
|
||||||
else
|
|
||||||
@procedure_lien = commencer_url(path: @procedure.path)
|
@procedure_lien = commencer_url(path: @procedure.path)
|
||||||
end
|
@procedure_lien_test = commencer_test_url(path: @procedure.path)
|
||||||
@procedure.path = @procedure.suggested_path(current_administrateur)
|
@procedure.path = @procedure.suggested_path(current_administrateur)
|
||||||
@current_administrateur = current_administrateur
|
@current_administrateur = current_administrateur
|
||||||
end
|
end
|
||||||
|
|
|
@ -5,13 +5,15 @@ module Users
|
||||||
def commencer
|
def commencer
|
||||||
@procedure = retrieve_procedure
|
@procedure = retrieve_procedure
|
||||||
return procedure_not_found if @procedure.blank? || @procedure.brouillon?
|
return procedure_not_found if @procedure.blank? || @procedure.brouillon?
|
||||||
|
@revision = @procedure.published_revision
|
||||||
|
|
||||||
render 'commencer/show'
|
render 'commencer/show'
|
||||||
end
|
end
|
||||||
|
|
||||||
def commencer_test
|
def commencer_test
|
||||||
@procedure = retrieve_procedure
|
@procedure = retrieve_procedure
|
||||||
return procedure_not_found if @procedure.blank? || @procedure.publiee?
|
return procedure_not_found if @procedure.blank? || (@procedure.publiee? && !@procedure.draft_changed?)
|
||||||
|
@revision = @procedure.draft_revision
|
||||||
|
|
||||||
render 'commencer/show'
|
render 'commencer/show'
|
||||||
end
|
end
|
||||||
|
@ -20,14 +22,14 @@ module Users
|
||||||
@procedure = retrieve_procedure
|
@procedure = retrieve_procedure
|
||||||
return procedure_not_found if @procedure.blank? || @procedure.brouillon?
|
return procedure_not_found if @procedure.blank? || @procedure.brouillon?
|
||||||
|
|
||||||
generate_empty_pdf(@procedure)
|
generate_empty_pdf(@procedure.published_revision)
|
||||||
end
|
end
|
||||||
|
|
||||||
def dossier_vide_pdf_test
|
def dossier_vide_pdf_test
|
||||||
@procedure = retrieve_procedure
|
@procedure = retrieve_procedure
|
||||||
return procedure_not_found if @procedure.blank? || @procedure.publiee?
|
return procedure_not_found if @procedure.blank? || (@procedure.publiee? && !@procedure.draft_changed?)
|
||||||
|
|
||||||
generate_empty_pdf(@procedure)
|
generate_empty_pdf(@procedure.draft_revision)
|
||||||
end
|
end
|
||||||
|
|
||||||
def sign_in
|
def sign_in
|
||||||
|
@ -80,10 +82,10 @@ module Users
|
||||||
store_location_for(:user, helpers.procedure_lien(procedure))
|
store_location_for(:user, helpers.procedure_lien(procedure))
|
||||||
end
|
end
|
||||||
|
|
||||||
def generate_empty_pdf(procedure)
|
def generate_empty_pdf(revision)
|
||||||
@dossier = procedure.active_revision.new_dossier
|
@dossier = revision.new_dossier
|
||||||
s = render_to_string(template: 'dossiers/dossier_vide', formats: [:pdf])
|
s = render_to_string(template: 'dossiers/dossier_vide', formats: [:pdf])
|
||||||
send_data(s, :filename => "#{procedure.libelle}.pdf")
|
send_data(s, :filename => "#{revision.procedure.libelle}.pdf")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -242,18 +242,18 @@ module Users
|
||||||
erase_user_location!
|
erase_user_location!
|
||||||
|
|
||||||
begin
|
begin
|
||||||
if params[:brouillon]
|
procedure = if params[:brouillon]
|
||||||
procedure = Procedure.brouillon.find(params[:procedure_id])
|
Procedure.publiees.or(Procedure.brouillons).find(params[:procedure_id])
|
||||||
else
|
else
|
||||||
procedure = Procedure.publiees.find(params[:procedure_id])
|
Procedure.publiees.find(params[:procedure_id])
|
||||||
end
|
end
|
||||||
rescue ActiveRecord::RecordNotFound
|
rescue ActiveRecord::RecordNotFound
|
||||||
flash.alert = t('errors.messages.procedure_not_found')
|
flash.alert = t('errors.messages.procedure_not_found')
|
||||||
return redirect_to url_for dossiers_path
|
return redirect_to dossiers_path
|
||||||
end
|
end
|
||||||
|
|
||||||
dossier = Dossier.new(
|
dossier = Dossier.new(
|
||||||
revision: procedure.active_revision,
|
revision: params[:brouillon] ? procedure.draft_revision : procedure.active_revision,
|
||||||
groupe_instructeur: procedure.defaut_groupe_instructeur_for_new_dossier,
|
groupe_instructeur: procedure.defaut_groupe_instructeur_for_new_dossier,
|
||||||
user: current_user,
|
user: current_user,
|
||||||
state: Dossier.states.fetch(:brouillon)
|
state: Dossier.states.fetch(:brouillon)
|
||||||
|
@ -303,7 +303,7 @@ module Users
|
||||||
end
|
end
|
||||||
|
|
||||||
def show_demarche_en_test_banner
|
def show_demarche_en_test_banner
|
||||||
if @dossier.present? && @dossier.procedure.brouillon?
|
if @dossier.present? && @dossier.revision.draft?
|
||||||
flash.now.alert = "Ce dossier est déposé sur une démarche en test. Toute modification de la démarche par l'administrateur (ajout d’un champ, publication de la démarche...) entraînera sa suppression."
|
flash.now.alert = "Ce dossier est déposé sur une démarche en test. Toute modification de la démarche par l'administrateur (ajout d’un champ, publication de la démarche...) entraînera sa suppression."
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -25,12 +25,8 @@ module DossierHelper
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def url_for_new_dossier(procedure)
|
def url_for_new_dossier(revision)
|
||||||
if procedure.brouillon?
|
new_dossier_url(procedure_id: revision.procedure.id, brouillon: revision.draft? ? true : nil)
|
||||||
new_dossier_url(procedure_id: procedure.id, brouillon: true)
|
|
||||||
else
|
|
||||||
new_dossier_url(procedure_id: procedure.id)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def dossier_form_class(dossier)
|
def dossier_form_class(dossier)
|
||||||
|
|
|
@ -2,7 +2,7 @@ import React, { useState } from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import ReactMapboxGl, { ZoomControl } from 'react-mapbox-gl';
|
import ReactMapboxGl, { ZoomControl } from 'react-mapbox-gl';
|
||||||
import DrawControl from 'react-mapbox-gl-draw';
|
import DrawControl from 'react-mapbox-gl-draw';
|
||||||
import { MapIcon } from '@heroicons/react/outline';
|
import { CursorClickIcon } from '@heroicons/react/outline';
|
||||||
import 'mapbox-gl/dist/mapbox-gl.css';
|
import 'mapbox-gl/dist/mapbox-gl.css';
|
||||||
import '@mapbox/mapbox-gl-draw/dist/mapbox-gl-draw.css';
|
import '@mapbox/mapbox-gl-draw/dist/mapbox-gl-draw.css';
|
||||||
|
|
||||||
|
@ -36,7 +36,13 @@ function MapEditor({ featureCollection, url, options, preview }) {
|
||||||
enabled: !preview,
|
enabled: !preview,
|
||||||
cadastreEnabled
|
cadastreEnabled
|
||||||
});
|
});
|
||||||
const [style, setStyle] = useMapStyle(options.layers, {
|
const {
|
||||||
|
style,
|
||||||
|
layers,
|
||||||
|
setStyle,
|
||||||
|
setLayerEnabled,
|
||||||
|
setLayerOpacity
|
||||||
|
} = useMapStyle(options.layers, {
|
||||||
onStyleChange,
|
onStyleChange,
|
||||||
cadastreEnabled
|
cadastreEnabled
|
||||||
});
|
});
|
||||||
|
@ -133,7 +139,13 @@ function MapEditor({ featureCollection, url, options, preview }) {
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
<MapStyleControl style={style.id} setStyle={setStyle} />
|
<MapStyleControl
|
||||||
|
style={style.id}
|
||||||
|
layers={layers}
|
||||||
|
setStyle={setStyle}
|
||||||
|
setLayerEnabled={setLayerEnabled}
|
||||||
|
setLayerOpacity={setLayerOpacity}
|
||||||
|
/>
|
||||||
<ZoomControl />
|
<ZoomControl />
|
||||||
{options.layers.includes('cadastres') && (
|
{options.layers.includes('cadastres') && (
|
||||||
<div className="cadastres-selection-control mapboxgl-ctrl-group">
|
<div className="cadastres-selection-control mapboxgl-ctrl-group">
|
||||||
|
@ -145,7 +157,7 @@ function MapEditor({ featureCollection, url, options, preview }) {
|
||||||
title="Sélectionner les parcelles cadastrales"
|
title="Sélectionner les parcelles cadastrales"
|
||||||
className={cadastreEnabled ? 'on' : ''}
|
className={cadastreEnabled ? 'on' : ''}
|
||||||
>
|
>
|
||||||
<MapIcon className="icon-size" />
|
<CursorClickIcon className="icon-size" />
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
|
@ -20,7 +20,13 @@ const MapReader = ({ featureCollection, options }) => {
|
||||||
onMouseEnter,
|
onMouseEnter,
|
||||||
onMouseLeave
|
onMouseLeave
|
||||||
} = useMapbox(featureCollection);
|
} = useMapbox(featureCollection);
|
||||||
const [style, setStyle] = useMapStyle(options.layers, { onStyleChange });
|
const {
|
||||||
|
style,
|
||||||
|
layers,
|
||||||
|
setStyle,
|
||||||
|
setLayerEnabled,
|
||||||
|
setLayerOpacity
|
||||||
|
} = useMapStyle(options.layers, { onStyleChange });
|
||||||
|
|
||||||
if (!isSupported) {
|
if (!isSupported) {
|
||||||
return (
|
return (
|
||||||
|
@ -36,7 +42,7 @@ const MapReader = ({ featureCollection, options }) => {
|
||||||
<Mapbox
|
<Mapbox
|
||||||
onStyleLoad={(map) => onLoad(map)}
|
onStyleLoad={(map) => onLoad(map)}
|
||||||
style={style}
|
style={style}
|
||||||
containerStyle={{ height: '400px' }}
|
containerStyle={{ height: '500px' }}
|
||||||
>
|
>
|
||||||
<SelectionUtilisateurPolygonLayer
|
<SelectionUtilisateurPolygonLayer
|
||||||
featureCollection={featureCollection}
|
featureCollection={featureCollection}
|
||||||
|
@ -54,7 +60,13 @@ const MapReader = ({ featureCollection, options }) => {
|
||||||
onMouseLeave={onMouseLeave}
|
onMouseLeave={onMouseLeave}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<MapStyleControl style={style.id} setStyle={setStyle} />
|
<MapStyleControl
|
||||||
|
style={style.id}
|
||||||
|
layers={layers}
|
||||||
|
setStyle={setStyle}
|
||||||
|
setLayerEnabled={setLayerEnabled}
|
||||||
|
setLayerOpacity={setLayerOpacity}
|
||||||
|
/>
|
||||||
<ZoomControl />
|
<ZoomControl />
|
||||||
</Mapbox>
|
</Mapbox>
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,35 +1,28 @@
|
||||||
import React, { useMemo, useState, useEffect } from 'react';
|
import React, { useMemo, useState, useEffect } from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
|
import { Popover, RadioGroup } from '@headlessui/react';
|
||||||
|
import { usePopper } from 'react-popper';
|
||||||
|
import { MapIcon } from '@heroicons/react/outline';
|
||||||
|
import { Slider } from '@reach/slider';
|
||||||
|
import '@reach/slider/styles.css';
|
||||||
|
|
||||||
import { getMapStyle } from './styles';
|
import { getMapStyle, getLayerName, NBS } from './styles';
|
||||||
import ortho from './styles/images/preview-ortho.png';
|
|
||||||
import vector from './styles/images/preview-vector.png';
|
|
||||||
|
|
||||||
const STYLES = {
|
const STYLES = {
|
||||||
ortho: {
|
ortho: 'Satellite',
|
||||||
title: 'Satellite',
|
vector: 'Vectoriel',
|
||||||
preview: ortho,
|
ign: 'Carte IGN'
|
||||||
color: '#fff'
|
|
||||||
},
|
|
||||||
vector: {
|
|
||||||
title: 'Vectoriel',
|
|
||||||
preview: vector,
|
|
||||||
color: '#000'
|
|
||||||
},
|
|
||||||
ign: {
|
|
||||||
title: 'Carte IGN',
|
|
||||||
preview: vector,
|
|
||||||
color: '#000'
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
function getNextStyle(style) {
|
function optionalLayersMap(optionalLayers) {
|
||||||
const styleNames = Object.keys(STYLES);
|
return Object.fromEntries(
|
||||||
const index = styleNames.indexOf(style) + 1;
|
optionalLayers
|
||||||
if (index === styleNames.length) {
|
.filter((layer) => layer != 'cadastres')
|
||||||
return styleNames[0];
|
.map((layer) => [
|
||||||
}
|
layer,
|
||||||
return styleNames[index];
|
{ enabled: true, opacity: 70, name: getLayerName(layer) }
|
||||||
|
])
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function useMapStyle(
|
export function useMapStyle(
|
||||||
|
@ -37,33 +30,149 @@ export function useMapStyle(
|
||||||
{ onStyleChange, cadastreEnabled }
|
{ onStyleChange, cadastreEnabled }
|
||||||
) {
|
) {
|
||||||
const [styleId, setStyle] = useState('ortho');
|
const [styleId, setStyle] = useState('ortho');
|
||||||
const style = useMemo(() => getMapStyle(styleId, optionalLayers), [
|
const [layers, setLayers] = useState(() => optionalLayersMap(optionalLayers));
|
||||||
|
const setLayerEnabled = (layer, enabled) =>
|
||||||
|
setLayers((optionalLayers) => {
|
||||||
|
optionalLayers[layer].enabled = enabled;
|
||||||
|
return { ...optionalLayers };
|
||||||
|
});
|
||||||
|
const setLayerOpacity = (layer, opacity) =>
|
||||||
|
setLayers((optionalLayers) => {
|
||||||
|
optionalLayers[layer].opacity = opacity;
|
||||||
|
return { ...optionalLayers };
|
||||||
|
});
|
||||||
|
const enabledLayers = Object.entries(layers).filter(
|
||||||
|
([, { enabled }]) => enabled
|
||||||
|
);
|
||||||
|
const style = useMemo(
|
||||||
|
() =>
|
||||||
|
getMapStyle(
|
||||||
styleId,
|
styleId,
|
||||||
optionalLayers
|
enabledLayers.map(([layer]) => layer),
|
||||||
]);
|
Object.fromEntries(
|
||||||
|
enabledLayers.map(([layer, { opacity }]) => [layer, opacity])
|
||||||
|
)
|
||||||
|
),
|
||||||
|
[
|
||||||
|
styleId,
|
||||||
|
enabledLayers.map(([layer, { opacity }]) => `${layer}-${opacity}`)
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
useEffect(() => onStyleChange(), [styleId, cadastreEnabled]);
|
useEffect(() => onStyleChange(), [styleId, cadastreEnabled]);
|
||||||
|
|
||||||
return [style, setStyle];
|
return { style, layers, setStyle, setLayerEnabled, setLayerOpacity };
|
||||||
}
|
}
|
||||||
|
|
||||||
function MapStyleControl({ style, setStyle }) {
|
function MapStyleControl({
|
||||||
const nextStyle = getNextStyle(style);
|
style,
|
||||||
const { title, preview, color } = STYLES[nextStyle];
|
layers,
|
||||||
|
setStyle,
|
||||||
|
setLayerEnabled,
|
||||||
|
setLayerOpacity
|
||||||
|
}) {
|
||||||
|
const [buttonElement, setButtonElement] = useState();
|
||||||
|
const [panelElement, setPanelElement] = useState();
|
||||||
|
const { styles, attributes } = usePopper(buttonElement, panelElement, {
|
||||||
|
placement: 'bottom-end'
|
||||||
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="map-style-control">
|
<div className="form map-style-control mapboxgl-ctrl-group">
|
||||||
<button type="button" onClick={() => setStyle(nextStyle)}>
|
<Popover>
|
||||||
<img alt={title} src={preview} />
|
<Popover.Button
|
||||||
<div style={{ color }}>{title}</div>
|
ref={setButtonElement}
|
||||||
</button>
|
className="map-style-button"
|
||||||
|
title="Sélectionner les couches cartographiques"
|
||||||
|
>
|
||||||
|
<MapIcon className="icon-size" />
|
||||||
|
</Popover.Button>
|
||||||
|
<Popover.Panel
|
||||||
|
className="flex map-style-panel mapboxgl-ctrl-group"
|
||||||
|
ref={setPanelElement}
|
||||||
|
style={styles.popper}
|
||||||
|
{...attributes.popper}
|
||||||
|
>
|
||||||
|
<RadioGroup
|
||||||
|
value={style}
|
||||||
|
onChange={setStyle}
|
||||||
|
className="styles-list"
|
||||||
|
as="ul"
|
||||||
|
>
|
||||||
|
{Object.entries(STYLES).map(([style, title]) => (
|
||||||
|
<RadioGroup.Option
|
||||||
|
key={style}
|
||||||
|
value={style}
|
||||||
|
as="li"
|
||||||
|
className="flex"
|
||||||
|
>
|
||||||
|
{({ checked }) => (
|
||||||
|
<>
|
||||||
|
<input
|
||||||
|
type="radio"
|
||||||
|
key={`${style}-${checked}`}
|
||||||
|
defaultChecked={checked}
|
||||||
|
name="map-style"
|
||||||
|
className="m-0 p-0 mr-1"
|
||||||
|
/>
|
||||||
|
<RadioGroup.Label>
|
||||||
|
{title.replace(/\s/g, ' ')}
|
||||||
|
</RadioGroup.Label>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</RadioGroup.Option>
|
||||||
|
))}
|
||||||
|
</RadioGroup>
|
||||||
|
{Object.keys(layers).length ? (
|
||||||
|
<ul className="layers-list">
|
||||||
|
{Object.entries(layers).map(
|
||||||
|
([layer, { enabled, opacity, name }]) => (
|
||||||
|
<li key={layer}>
|
||||||
|
<div className="flex mb-1">
|
||||||
|
<input
|
||||||
|
className="m-0 p-0 mr-1"
|
||||||
|
type="checkbox"
|
||||||
|
checked={enabled}
|
||||||
|
onChange={(event) => {
|
||||||
|
setLayerEnabled(layer, event.target.checked);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<label className="m-0">{name}</label>
|
||||||
|
</div>
|
||||||
|
<Slider
|
||||||
|
min={10}
|
||||||
|
max={100}
|
||||||
|
step={5}
|
||||||
|
value={opacity}
|
||||||
|
onChange={(value) => {
|
||||||
|
setLayerOpacity(layer, value);
|
||||||
|
}}
|
||||||
|
className="mb-1"
|
||||||
|
title={`Réglage de l’opacité de la couche «${NBS}${name}${NBS}»`}
|
||||||
|
getAriaLabel={() =>
|
||||||
|
`Réglage de l’opacité de la couche «${NBS}${name}${NBS}»`
|
||||||
|
}
|
||||||
|
getAriaValueText={(value) =>
|
||||||
|
`L’opacité de la couche «${NBS}${name}${NBS}» est à ${value}${NBS}%`
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</li>
|
||||||
|
)
|
||||||
|
)}
|
||||||
|
</ul>
|
||||||
|
) : null}
|
||||||
|
</Popover.Panel>
|
||||||
|
</Popover>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
MapStyleControl.propTypes = {
|
MapStyleControl.propTypes = {
|
||||||
style: PropTypes.string,
|
style: PropTypes.string,
|
||||||
setStyle: PropTypes.func
|
layers: PropTypes.object,
|
||||||
|
setStyle: PropTypes.func,
|
||||||
|
setLayerEnabled: PropTypes.func,
|
||||||
|
setLayerOpacity: PropTypes.func
|
||||||
};
|
};
|
||||||
|
|
||||||
export default MapStyleControl;
|
export default MapStyleControl;
|
||||||
|
|
|
@ -119,9 +119,9 @@ const OPTIONAL_LAYERS = [
|
||||||
function buildSources() {
|
function buildSources() {
|
||||||
return Object.fromEntries(
|
return Object.fromEntries(
|
||||||
OPTIONAL_LAYERS.filter(({ id }) => id !== 'cadastres')
|
OPTIONAL_LAYERS.filter(({ id }) => id !== 'cadastres')
|
||||||
.flatMap(({ layers }) => layers)
|
.flatMap(({ layers }) => layers.map(([, code]) => code))
|
||||||
.map(([, code]) => [
|
.map((code) => [
|
||||||
code.toLowerCase().replace(/\./g, '-'),
|
getLayerCode(code),
|
||||||
rasterSource([ignServiceURL(code)], 'IGN-F/Géoportail/MNHN')
|
rasterSource([ignServiceURL(code)], 'IGN-F/Géoportail/MNHN')
|
||||||
])
|
])
|
||||||
);
|
);
|
||||||
|
@ -138,25 +138,40 @@ function rasterSource(tiles, attribution) {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function rasterLayer(source) {
|
function rasterLayer(source, opacity) {
|
||||||
return {
|
return {
|
||||||
id: source,
|
id: source,
|
||||||
source,
|
source,
|
||||||
type: 'raster',
|
type: 'raster',
|
||||||
paint: { 'raster-resampling': 'linear' }
|
paint: { 'raster-resampling': 'linear', 'raster-opacity': opacity }
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export function buildOptionalLayers(ids) {
|
export function buildOptionalLayers(ids, opacity) {
|
||||||
return OPTIONAL_LAYERS.filter(({ id }) => ids.includes(id))
|
return OPTIONAL_LAYERS.filter(({ id }) => ids.includes(id))
|
||||||
.flatMap(({ layers }) => layers)
|
.flatMap(({ layers, id }) =>
|
||||||
.flatMap(([, code]) =>
|
layers.map(([, code]) => [code, opacity[id] / 100])
|
||||||
|
)
|
||||||
|
.flatMap(([code, opacity]) =>
|
||||||
code === 'CADASTRE'
|
code === 'CADASTRE'
|
||||||
? cadastreLayers
|
? cadastreLayers
|
||||||
: [rasterLayer(code.toLowerCase().replace(/\./g, '-'))]
|
: [rasterLayer(getLayerCode(code), opacity)]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const NBS = ' ';
|
||||||
|
|
||||||
|
export function getLayerName(layer) {
|
||||||
|
return OPTIONAL_LAYERS.find(({ id }) => id == layer).label.replace(
|
||||||
|
/\s/g,
|
||||||
|
NBS
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getLayerCode(code) {
|
||||||
|
return code.toLowerCase().replace(/\./g, '-');
|
||||||
|
}
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
version: 8,
|
version: 8,
|
||||||
metadat: {
|
metadat: {
|
||||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 22 KiB |
Binary file not shown.
Before Width: | Height: | Size: 17 KiB |
|
@ -1,9 +1,11 @@
|
||||||
import baseStyle, { buildOptionalLayers } from './base';
|
import baseStyle, { buildOptionalLayers, getLayerName, NBS } from './base';
|
||||||
import orthoStyle from './layers/ortho';
|
import orthoStyle from './layers/ortho';
|
||||||
import vectorStyle from './layers/vector';
|
import vectorStyle from './layers/vector';
|
||||||
import ignLayers from './layers/ign';
|
import ignLayers from './layers/ign';
|
||||||
|
|
||||||
export function getMapStyle(id, optionalLayers) {
|
export { getLayerName, NBS };
|
||||||
|
|
||||||
|
export function getMapStyle(id, layers, opacity) {
|
||||||
const style = { ...baseStyle, id };
|
const style = { ...baseStyle, id };
|
||||||
|
|
||||||
switch (id) {
|
switch (id) {
|
||||||
|
@ -21,7 +23,7 @@ export function getMapStyle(id, optionalLayers) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
style.layers = style.layers.concat(buildOptionalLayers(optionalLayers));
|
style.layers = style.layers.concat(buildOptionalLayers(layers, opacity));
|
||||||
|
|
||||||
return style;
|
return style;
|
||||||
}
|
}
|
||||||
|
|
|
@ -307,9 +307,7 @@ class Procedure < ApplicationRecord
|
||||||
end
|
end
|
||||||
|
|
||||||
def reset!
|
def reset!
|
||||||
if locked?
|
if !locked? || draft_changed?
|
||||||
raise "Can not reset a locked procedure."
|
|
||||||
else
|
|
||||||
draft_revision.dossiers.destroy_all
|
draft_revision.dossiers.destroy_all
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -426,7 +424,9 @@ class Procedure < ApplicationRecord
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
include_list[:groupe_instructeurs] = :instructeurs if !is_different_admin
|
include_list[:groupe_instructeurs] = :instructeurs if !is_different_admin
|
||||||
procedure = self.deep_clone(include: include_list, &method(:clone_attachments))
|
procedure = self.deep_clone(include: include_list) do |original, kopy|
|
||||||
|
PiecesJustificativesService.clone_attachments(original, kopy)
|
||||||
|
end
|
||||||
procedure.path = SecureRandom.uuid
|
procedure.path = SecureRandom.uuid
|
||||||
procedure.aasm_state = :brouillon
|
procedure.aasm_state = :brouillon
|
||||||
procedure.closed_at = nil
|
procedure.closed_at = nil
|
||||||
|
@ -472,29 +472,6 @@ class Procedure < ApplicationRecord
|
||||||
procedure
|
procedure
|
||||||
end
|
end
|
||||||
|
|
||||||
def clone_attachments(original, kopy)
|
|
||||||
if original.is_a?(TypeDeChamp)
|
|
||||||
clone_attachment(:piece_justificative_template, original, kopy)
|
|
||||||
elsif original.is_a?(Procedure)
|
|
||||||
clone_attachment(:logo, original, kopy)
|
|
||||||
clone_attachment(:notice, original, kopy)
|
|
||||||
clone_attachment(:deliberation, original, kopy)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def clone_attachment(attribute, original, kopy)
|
|
||||||
original_attachment = original.send(attribute)
|
|
||||||
if original_attachment.attached?
|
|
||||||
kopy.send(attribute).attach({
|
|
||||||
io: StringIO.new(original_attachment.download),
|
|
||||||
filename: original_attachment.filename,
|
|
||||||
content_type: original_attachment.content_type,
|
|
||||||
# we don't want to run virus scanner on cloned file
|
|
||||||
metadata: { virus_scan_result: ActiveStorage::VirusScanner::SAFE }
|
|
||||||
})
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def whitelisted?
|
def whitelisted?
|
||||||
whitelisted_at.present?
|
whitelisted_at.present?
|
||||||
end
|
end
|
||||||
|
|
|
@ -249,7 +249,9 @@ class ProcedureRevision < ApplicationRecord
|
||||||
def revise_type_de_champ(type_de_champ)
|
def revise_type_de_champ(type_de_champ)
|
||||||
types_de_champ_association = type_de_champ.private? ? :revision_types_de_champ_private : :revision_types_de_champ
|
types_de_champ_association = type_de_champ.private? ? :revision_types_de_champ_private : :revision_types_de_champ
|
||||||
association = send(types_de_champ_association).find_by!(type_de_champ: type_de_champ)
|
association = send(types_de_champ_association).find_by!(type_de_champ: type_de_champ)
|
||||||
cloned_type_de_champ = type_de_champ.deep_clone(include: [:types_de_champ], &type_de_champ.method(:clone_attachments))
|
cloned_type_de_champ = type_de_champ.deep_clone(include: [:types_de_champ]) do |original, kopy|
|
||||||
|
PiecesJustificativesService.clone_attachments(original, kopy)
|
||||||
|
end
|
||||||
cloned_type_de_champ.revision = self
|
cloned_type_de_champ.revision = self
|
||||||
association.update!(type_de_champ: cloned_type_de_champ)
|
association.update!(type_de_champ: cloned_type_de_champ)
|
||||||
cloned_type_de_champ
|
cloned_type_de_champ
|
||||||
|
|
|
@ -369,23 +369,4 @@ class TypeDeChamp < ApplicationRecord
|
||||||
types_de_champ.destroy_all
|
types_de_champ.destroy_all
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def clone_attachments(original, kopy)
|
|
||||||
if original.is_a?(TypeDeChamp)
|
|
||||||
clone_attachment(:piece_justificative_template, original, kopy)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def clone_attachment(attribute, original, kopy)
|
|
||||||
original_attachment = original.send(attribute)
|
|
||||||
if original_attachment.attached?
|
|
||||||
kopy.send(attribute).attach({
|
|
||||||
io: StringIO.new(original_attachment.download),
|
|
||||||
filename: original_attachment.filename,
|
|
||||||
content_type: original_attachment.content_type,
|
|
||||||
# we don't want to run virus scanner on cloned file
|
|
||||||
metadata: { virus_scan_result: ActiveStorage::VirusScanner::SAFE }
|
|
||||||
})
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -49,6 +49,30 @@ class PiecesJustificativesService
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def self.clone_attachments(original, kopy)
|
||||||
|
if original.is_a?(TypeDeChamp)
|
||||||
|
clone_attachment(original.piece_justificative_template, kopy.piece_justificative_template)
|
||||||
|
elsif original.is_a?(Procedure)
|
||||||
|
clone_attachment(original.logo, kopy.logo)
|
||||||
|
clone_attachment(original.notice, kopy.notice)
|
||||||
|
clone_attachment(original.deliberation, kopy.deliberation)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.clone_attachment(original_attachment, copy_attachment)
|
||||||
|
if original_attachment.attached?
|
||||||
|
original_attachment.open do |tempfile|
|
||||||
|
copy_attachment.attach({
|
||||||
|
io: File.open(tempfile.path),
|
||||||
|
filename: original_attachment.filename,
|
||||||
|
content_type: original_attachment.content_type,
|
||||||
|
# we don't want to run virus scanner on cloned file
|
||||||
|
metadata: { virus_scan_result: ActiveStorage::VirusScanner::SAFE }
|
||||||
|
})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
class FakeAttachment < Hashie::Dash
|
class FakeAttachment < Hashie::Dash
|
||||||
property :filename
|
property :filename
|
||||||
property :name
|
property :name
|
||||||
|
|
|
@ -11,12 +11,12 @@
|
||||||
= link_to 'J’ai déjà un compte', commencer_sign_in_path(path: @procedure.path), class: ['button large expand']
|
= link_to 'J’ai déjà un compte', commencer_sign_in_path(path: @procedure.path), class: ['button large expand']
|
||||||
|
|
||||||
- else
|
- else
|
||||||
- dossiers = current_user.dossiers.where(revision: @procedure.revisions)
|
- dossiers = current_user.dossiers.where(revision: @revision.draft? ? @revision : @procedure.revisions.where.not(id: @procedure.draft_revision_id))
|
||||||
- drafts = dossiers.merge(Dossier.state_brouillon)
|
- drafts = dossiers.merge(Dossier.state_brouillon)
|
||||||
- not_drafts = dossiers.merge(Dossier.state_not_brouillon)
|
- not_drafts = dossiers.merge(Dossier.state_not_brouillon)
|
||||||
|
|
||||||
- if dossiers.count == 0
|
- if dossiers.count == 0
|
||||||
= link_to 'Commencer la démarche', url_for_new_dossier(@procedure), class: ['button large expand primary']
|
= link_to 'Commencer la démarche', url_for_new_dossier(@revision), class: ['button large expand primary']
|
||||||
|
|
||||||
- elsif drafts.count == 1 && not_drafts.count == 0
|
- elsif drafts.count == 1 && not_drafts.count == 0
|
||||||
- dossier = drafts.first
|
- dossier = drafts.first
|
||||||
|
@ -25,7 +25,7 @@
|
||||||
Il y a <strong>#{time_ago_in_words(dossier.created_at)}</strong>,
|
Il y a <strong>#{time_ago_in_words(dossier.created_at)}</strong>,
|
||||||
vous avez commencé à remplir un dossier sur la démarche « #{dossier.procedure.libelle} ».
|
vous avez commencé à remplir un dossier sur la démarche « #{dossier.procedure.libelle} ».
|
||||||
= link_to 'Continuer à remplir mon dossier', brouillon_dossier_path(dossier), class: ['button large expand primary']
|
= link_to 'Continuer à remplir mon dossier', brouillon_dossier_path(dossier), class: ['button large expand primary']
|
||||||
= link_to 'Commencer un nouveau dossier', url_for_new_dossier(@procedure), class: ['button large expand']
|
= link_to 'Commencer un nouveau dossier', url_for_new_dossier(@revision), class: ['button large expand']
|
||||||
|
|
||||||
- elsif not_drafts.count == 1
|
- elsif not_drafts.count == 1
|
||||||
- dossier = not_drafts.first
|
- dossier = not_drafts.first
|
||||||
|
@ -34,17 +34,15 @@
|
||||||
Il y a <strong>#{time_ago_in_words(dossier.en_construction_at)}</strong>,
|
Il y a <strong>#{time_ago_in_words(dossier.en_construction_at)}</strong>,
|
||||||
vous avez déposé un dossier sur la démarche « #{dossier.procedure.libelle} ».
|
vous avez déposé un dossier sur la démarche « #{dossier.procedure.libelle} ».
|
||||||
= link_to 'Voir mon dossier déposé', dossier_path(dossier), class: ['button large expand primary']
|
= link_to 'Voir mon dossier déposé', dossier_path(dossier), class: ['button large expand primary']
|
||||||
= link_to 'Commencer un nouveau dossier', url_for_new_dossier(@procedure), class: ['button large expand']
|
= link_to 'Commencer un nouveau dossier', url_for_new_dossier(@revision), class: ['button large expand']
|
||||||
|
|
||||||
- else
|
- else
|
||||||
%h2.huge-title Vous avez déjà des dossiers pour cette démarche
|
%h2.huge-title Vous avez déjà des dossiers pour cette démarche
|
||||||
= link_to 'Voir mes dossiers en cours', dossiers_path, class: ['button large expand primary']
|
= link_to 'Voir mes dossiers en cours', dossiers_path, class: ['button large expand primary']
|
||||||
= link_to 'Commencer un nouveau dossier', url_for_new_dossier(@procedure), class: ['button large expand']
|
= link_to 'Commencer un nouveau dossier', url_for_new_dossier(@revision), class: ['button large expand']
|
||||||
|
|
||||||
- if @procedure.feature_enabled?(:dossier_pdf_vide)
|
- if @procedure.feature_enabled?(:dossier_pdf_vide)
|
||||||
- pdf_link = commencer_dossier_vide_path(path: @procedure.path)
|
- pdf_link = @revision.draft? ? commencer_dossier_vide_test_path(path: @procedure.path) : commencer_dossier_vide_path(path: @procedure.path)
|
||||||
- if @procedure.brouillon?
|
|
||||||
- pdf_link = commencer_dossier_vide_test_path(path: @procedure.path)
|
|
||||||
%hr
|
%hr
|
||||||
%p
|
%p
|
||||||
Vous souhaitez effectuer une demande par papier ? Vous pouvez télécharger un dossier vide au format PDF,
|
Vous souhaitez effectuer une demande par papier ? Vous pouvez télécharger un dossier vide au format PDF,
|
||||||
|
|
|
@ -30,31 +30,6 @@
|
||||||
%th.center Télécharger
|
%th.center Télécharger
|
||||||
|
|
||||||
%tbody
|
%tbody
|
||||||
%tr
|
|
||||||
- matching_archive = @archives.find { |archive| archive.time_span_type == 'everything' }
|
|
||||||
- weight = estimate_weight(matching_archive, @nb_dossiers_termines, @average_dossier_weight)
|
|
||||||
%td
|
|
||||||
Tous les dossiers
|
|
||||||
%td.text-right
|
|
||||||
= @nb_dossiers_termines
|
|
||||||
%td.text-right
|
|
||||||
= number_to_human_size(weight)
|
|
||||||
%td.center
|
|
||||||
- if matching_archive.try(&:available?)
|
|
||||||
= link_to url_for(matching_archive.file), class: 'button primary' do
|
|
||||||
%span.icon.download-white
|
|
||||||
= t(:archive_ready_html, generated_period: time_ago_in_words(matching_archive.updated_at), scope: [:instructeurs, :procedure])
|
|
||||||
- elsif matching_archive.try(&:pending?)
|
|
||||||
%span.icon.retry
|
|
||||||
= t(:archive_pending_html, created_period: time_ago_in_words(matching_archive.created_at), scope: [:instructeurs, :procedure])
|
|
||||||
- elsif @nb_dossiers_termines == 0
|
|
||||||
Rien à télécharger !
|
|
||||||
- elsif weight < 1.gigabyte
|
|
||||||
= link_to instructeur_archives_path(@procedure, type: 'everything'), method: :post, class: "button" do
|
|
||||||
%span.icon.new-folder
|
|
||||||
Demander la création
|
|
||||||
- else
|
|
||||||
Archive trop volumineuse
|
|
||||||
- @count_dossiers_termines_by_month.each do |count_by_month|
|
- @count_dossiers_termines_by_month.each do |count_by_month|
|
||||||
- month = count_by_month["month"].to_date
|
- month = count_by_month["month"].to_date
|
||||||
- nb_dossiers_termines = count_by_month["count"]
|
- nb_dossiers_termines = count_by_month["count"]
|
||||||
|
|
|
@ -25,11 +25,7 @@
|
||||||
%li
|
%li
|
||||||
= active_link_to "Démarches", instructeur_procedures_path, active: ['dossiers','procedures'].include?(controller_name), class: 'tab-link'
|
= active_link_to "Démarches", instructeur_procedures_path, active: ['dossiers','procedures'].include?(controller_name), class: 'tab-link'
|
||||||
- if current_instructeur.user.expert && current_expert.avis_summary[:total] > 0
|
- if current_instructeur.user.expert && current_expert.avis_summary[:total] > 0
|
||||||
%li
|
= render partial: 'layouts/header/avis_tab', locals: { current_expert: current_expert }
|
||||||
= active_link_to expert_all_avis_path, active: controller_name == 'avis', class: 'tab-link' do
|
|
||||||
Avis
|
|
||||||
- if current_expert.avis_summary[:unanswered] > 0
|
|
||||||
%span.badge.warning= current_expert.avis_summary[:unanswered]
|
|
||||||
|
|
||||||
- if nav_bar_profile == :expert && expert_signed_in?
|
- if nav_bar_profile == :expert && expert_signed_in?
|
||||||
%ul.header-tabs
|
%ul.header-tabs
|
||||||
|
@ -38,16 +34,14 @@
|
||||||
= active_link_to "Démarches", instructeur_procedures_path, active: ['dossiers','procedures'].include?(controller_name), class: 'tab-link'
|
= active_link_to "Démarches", instructeur_procedures_path, active: ['dossiers','procedures'].include?(controller_name), class: 'tab-link'
|
||||||
|
|
||||||
- if current_expert.avis_summary[:total] > 0
|
- if current_expert.avis_summary[:total] > 0
|
||||||
%li
|
= render partial: 'layouts/header/avis_tab', locals: { current_expert: current_expert }
|
||||||
= active_link_to expert_all_avis_path, active: controller_name == 'avis', class: 'tab-link' do
|
|
||||||
Avis
|
|
||||||
- if current_expert.avis_summary[:unanswered] > 0
|
|
||||||
%span.badge.warning= current_expert.avis_summary[:unanswered]
|
|
||||||
|
|
||||||
- if nav_bar_profile == :user
|
- if nav_bar_profile == :user
|
||||||
%ul.header-tabs
|
%ul.header-tabs
|
||||||
%li
|
%li
|
||||||
= active_link_to "Dossiers", dossiers_path, active: :inclusive, class: 'tab-link'
|
= active_link_to "Dossiers", dossiers_path, active: :inclusive, class: 'tab-link'
|
||||||
|
- if current_user.expert && current_expert.avis_summary[:total] > 0
|
||||||
|
= render partial: 'layouts/header/avis_tab', locals: { current_expert: current_expert }
|
||||||
|
|
||||||
%ul.header-right-content
|
%ul.header-right-content
|
||||||
- if params[:controller] == 'recherche'
|
- if params[:controller] == 'recherche'
|
||||||
|
|
5
app/views/layouts/header/_avis_tab.html.haml
Normal file
5
app/views/layouts/header/_avis_tab.html.haml
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
%li
|
||||||
|
= active_link_to expert_all_avis_path, active: controller_name == 'avis', class: 'tab-link' do
|
||||||
|
Avis
|
||||||
|
- if current_expert.avis_summary[:unanswered] > 0
|
||||||
|
%span.badge.warning= current_expert.avis_summary[:unanswered]
|
|
@ -28,7 +28,7 @@
|
||||||
%p
|
%p
|
||||||
Cette démarche est actuellement <strong>en test</strong>,
|
Cette démarche est actuellement <strong>en test</strong>,
|
||||||
pour y accéder vous pouvez utiliser le lien :
|
pour y accéder vous pouvez utiliser le lien :
|
||||||
= link_to @procedure_lien, sanitize_url(@procedure_lien), target: :blank, rel: :noopener
|
= link_to @procedure_lien_test, sanitize_url(@procedure_lien_test), target: :blank, rel: :noopener
|
||||||
%p.mb-4
|
%p.mb-4
|
||||||
Toute personne ayant la connaissance de ce lien pourra ainsi remplir des dossiers de test sur votre démarche.
|
Toute personne ayant la connaissance de ce lien pourra ainsi remplir des dossiers de test sur votre démarche.
|
||||||
|
|
||||||
|
|
|
@ -8,8 +8,8 @@
|
||||||
%span.icon.preview
|
%span.icon.preview
|
||||||
Prévisualiser
|
Prévisualiser
|
||||||
|
|
||||||
- if @procedure.brouillon?
|
- if @procedure.brouillon? || @procedure.draft_changed?
|
||||||
= link_to sanitize_url(@procedure_lien), target: :blank, rel: :noopener, class: 'button' do
|
= link_to sanitize_url(@procedure_lien_test), target: :blank, rel: :noopener, class: 'button' do
|
||||||
%span.icon.in-progress
|
%span.icon.in-progress
|
||||||
Tester
|
Tester
|
||||||
|
|
||||||
|
|
|
@ -7,13 +7,5 @@ Sentry.init do |config|
|
||||||
config.enabled_environments = ['production', secrets[:environment].presence].compact
|
config.enabled_environments = ['production', secrets[:environment].presence].compact
|
||||||
config.breadcrumbs_logger = [:active_support_logger]
|
config.breadcrumbs_logger = [:active_support_logger]
|
||||||
config.traces_sample_rate = secrets[:enabled] ? 0.001 : nil
|
config.traces_sample_rate = secrets[:enabled] ? 0.001 : nil
|
||||||
config.excluded_exceptions += [
|
config.delayed_job.report_after_job_retries = true
|
||||||
# Ignore exceptions caught by ActiveJob.retry_on
|
|
||||||
# https://github.com/getsentry/sentry-ruby/issues/1347
|
|
||||||
'Excon::Error::BadRequest',
|
|
||||||
'ActiveStorage::IntegrityError',
|
|
||||||
'VirusScannerJob::FileNotAnalyzedYetError',
|
|
||||||
'TitreIdentiteWatermarkJob::WatermarkFileNotScannedYetError',
|
|
||||||
'APIEntreprise::API::Error::TimedOut'
|
|
||||||
]
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,13 +1,16 @@
|
||||||
{
|
{
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/preset-react": "^7.12.13",
|
"@babel/preset-react": "^7.12.13",
|
||||||
|
"@headlessui/react": "^1.3.0",
|
||||||
"@heroicons/react": "^1.0.1",
|
"@heroicons/react": "^1.0.1",
|
||||||
"@mapbox/mapbox-gl-draw": "^1.2.2",
|
"@mapbox/mapbox-gl-draw": "^1.2.2",
|
||||||
|
"@popperjs/core": "^2.9.2",
|
||||||
"@rails/actiontext": "^6.0.3",
|
"@rails/actiontext": "^6.0.3",
|
||||||
"@rails/activestorage": "^6.0.3",
|
"@rails/activestorage": "^6.0.3",
|
||||||
"@rails/ujs": "^6.0.3",
|
"@rails/ujs": "^6.0.3",
|
||||||
"@rails/webpacker": "5.1.1",
|
"@rails/webpacker": "5.1.1",
|
||||||
"@reach/combobox": "^0.13.0",
|
"@reach/combobox": "^0.13.0",
|
||||||
|
"@reach/slider": "^0.15.0",
|
||||||
"@sentry/browser": "^5.15.5",
|
"@sentry/browser": "^5.15.5",
|
||||||
"@tmcw/togeojson": "^4.3.0",
|
"@tmcw/togeojson": "^4.3.0",
|
||||||
"babel-plugin-macros": "^2.8.0",
|
"babel-plugin-macros": "^2.8.0",
|
||||||
|
@ -28,6 +31,7 @@
|
||||||
"react-intersection-observer": "^8.31.0",
|
"react-intersection-observer": "^8.31.0",
|
||||||
"react-mapbox-gl": "^5.1.1",
|
"react-mapbox-gl": "^5.1.1",
|
||||||
"react-mapbox-gl-draw": "^2.0.4",
|
"react-mapbox-gl-draw": "^2.0.4",
|
||||||
|
"react-popper": "^2.2.5",
|
||||||
"react-query": "^3.9.7",
|
"react-query": "^3.9.7",
|
||||||
"react-sortable-hoc": "^1.11.0",
|
"react-sortable-hoc": "^1.11.0",
|
||||||
"react_ujs": "^2.6.1",
|
"react_ujs": "^2.6.1",
|
||||||
|
|
104
public/422.html
104
public/422.html
|
@ -1,67 +1,59 @@
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html>
|
<html lang='fr'>
|
||||||
<head>
|
<head>
|
||||||
<title>The change you wanted was rejected (422)</title>
|
<meta content='text/html; charset=UTF-8' http-equiv='Content-Type'>
|
||||||
<meta name="viewport" content="width=device-width,initial-scale=1">
|
<meta content='IE=edge' http-equiv='X-UA-Compatible'>
|
||||||
|
<meta content='no-cache' name='turbolinks-cache-control'>
|
||||||
|
<meta content='width=device-width, initial-scale=1' name='viewport'>
|
||||||
|
<title>
|
||||||
|
Erreur 422 · demarches-simplifiees.fr
|
||||||
|
</title>
|
||||||
<style>
|
<style>
|
||||||
body {
|
html,body,div,span,h1,p,a,img,table,tbody,tfoot,thead,tr,th,td{margin:0;padding:0;border:0;font-size:100%;font:inherit;vertical-align:baseline;}
|
||||||
background-color: #EFEFEF;
|
html,body{height:100%;}
|
||||||
color: #2E2F30;
|
body{line-height:1;font-family:"Muli";color:#333333;font-size:16px;line-height:1.42857143;}
|
||||||
text-align: center;
|
html{box-sizing:border-box;}
|
||||||
font-family: arial, sans-serif;
|
*,*::before,*::after{box-sizing:inherit;}
|
||||||
margin: 0;
|
a{text-decoration:none;}
|
||||||
}
|
.page-wrapper{position:relative;min-height:100%;}
|
||||||
|
.container{padding-left:16px;padding-right:16px;max-width:700px;margin:0 auto;}
|
||||||
div.dialog {
|
.flex{display:flex;}
|
||||||
width: 95%;
|
.flex.align-center{align-items:center;}
|
||||||
max-width: 33em;
|
.header-inner-content{padding-left:16px;padding-right:16px;max-width:1072px;margin:0 auto;display:flex;justify-content:space-between;min-height:72px;}
|
||||||
margin: 4em auto 0;
|
.new-header{background-color:#FFFFFF;}
|
||||||
}
|
.new-header-with-border{border-bottom:1px solid #CCCCCC;}
|
||||||
|
.header-logo{display:inline-block;margin-right:32px;}
|
||||||
div.dialog > div {
|
.header-logo img{height:34px;}
|
||||||
border: 1px solid #CCC;
|
@media (max-width: 1040px){
|
||||||
border-right-color: #999;
|
.header-logo img{height:18px;}
|
||||||
border-left-color: #999;
|
|
||||||
border-bottom-color: #BBB;
|
|
||||||
border-top: #B00100 solid 4px;
|
|
||||||
border-top-left-radius: 9px;
|
|
||||||
border-top-right-radius: 9px;
|
|
||||||
background-color: white;
|
|
||||||
padding: 7px 12% 0;
|
|
||||||
box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
|
|
||||||
}
|
|
||||||
|
|
||||||
h1 {
|
|
||||||
font-size: 100%;
|
|
||||||
color: #730E15;
|
|
||||||
line-height: 1.5em;
|
|
||||||
}
|
|
||||||
|
|
||||||
div.dialog > p {
|
|
||||||
margin: 0 0 1em;
|
|
||||||
padding: 1em;
|
|
||||||
background-color: #F7F7F7;
|
|
||||||
border: 1px solid #CCC;
|
|
||||||
border-right-color: #999;
|
|
||||||
border-left-color: #999;
|
|
||||||
border-bottom-color: #999;
|
|
||||||
border-bottom-left-radius: 4px;
|
|
||||||
border-bottom-right-radius: 4px;
|
|
||||||
border-top-color: #DADADA;
|
|
||||||
color: #666;
|
|
||||||
box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
|
|
||||||
}
|
}
|
||||||
|
.new-h1{color:#333333;text-align:center;font-weight:bold;margin-bottom:60px;font-size:41px;margin-top:60px;}
|
||||||
|
.description{font-size: 18px; margin-bottom: 8px;}
|
||||||
|
/*! CSS Used fontfaces */
|
||||||
|
@font-face{font-family:"Muli";src:url(/fonts/muli/Muli-Regular.woff) format("woff");font-weight:normal;font-style:normal;}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<!-- This file lives in public/422.html -->
|
<div class='page-wrapper'>
|
||||||
<div class="dialog">
|
<div class='new-header new-header-with-border'>
|
||||||
<div>
|
<div class='header-inner-content'>
|
||||||
<h1>The change you wanted was rejected.</h1>
|
<div class='flex align-center'>
|
||||||
<p>Maybe you tried to change something you didn't have access to.</p>
|
<a class="header-logo" href="/"><img alt='demarches-simplifiees.fr' src='/logo-ds.svg'>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class='container'>
|
||||||
|
<h1 class='new-h1'>L’action demandée a été rejetée.</h1>
|
||||||
|
<p class='description'>
|
||||||
|
Pas de panique, c’est probablement temporaire.
|
||||||
|
</p>
|
||||||
|
<p class='description'>
|
||||||
|
Essayez de
|
||||||
|
<a href="javascript:window.location=document.referrer;">recharger la page précédente</a>,
|
||||||
|
et tout devrait rentrer dans l’ordre.
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<p>If you are the application owner check the logs for more information.</p>
|
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -300,55 +300,84 @@ describe Experts::AvisController, type: :controller do
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'without an expert signed in' do
|
context 'without an expert signed in' do
|
||||||
describe '#sign_up' do
|
|
||||||
let(:invited_email) { 'invited@avis.com' }
|
|
||||||
let(:claimant) { create(:instructeur) }
|
let(:claimant) { create(:instructeur) }
|
||||||
let(:expert) { create(:expert) }
|
let(:expert) { create(:expert) }
|
||||||
let(:experts_procedure) { create(:experts_procedure, expert: expert, procedure: procedure) }
|
let(:experts_procedure) { create(:experts_procedure, expert: expert, procedure: procedure) }
|
||||||
let(:dossier) { create(:dossier) }
|
let(:dossier) { create(:dossier) }
|
||||||
|
let(:avis) { create(:avis, dossier: dossier, experts_procedure: experts_procedure, claimant: claimant) }
|
||||||
let(:procedure) { dossier.procedure }
|
let(:procedure) { dossier.procedure }
|
||||||
let!(:avis) { create(:avis, experts_procedure: experts_procedure, claimant: claimant, dossier: dossier) }
|
|
||||||
let(:invitations_email) { true }
|
|
||||||
|
|
||||||
context 'when the expert has already signed up and belongs to the invitation' do
|
describe '#sign_up' do
|
||||||
let!(:avis) { create(:avis, dossier: dossier, experts_procedure: experts_procedure, claimant: claimant) }
|
subject do
|
||||||
|
|
||||||
context 'when the expert is authenticated' do
|
|
||||||
before do
|
|
||||||
sign_in(expert.user)
|
|
||||||
expert.user.update(last_sign_in_at: Time.zone.now)
|
|
||||||
expert.user.reload
|
|
||||||
get :sign_up, params: { id: avis.id, procedure_id: procedure.id, email: avis.expert.email }
|
get :sign_up, params: { id: avis.id, procedure_id: procedure.id, email: avis.expert.email }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context 'when the expert hasn’t signed up yet' do
|
||||||
|
before { expert.user.update(last_sign_in_at: nil) }
|
||||||
|
|
||||||
|
it { is_expected.to have_http_status(:success) }
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when the expert has already signed up' do
|
||||||
|
before { expert.user.update(last_sign_in_at: Time.zone.now) }
|
||||||
|
|
||||||
|
context 'and the expert belongs to the invitation' do
|
||||||
|
context 'and the expert is authenticated' do
|
||||||
|
before { sign_in(expert.user) }
|
||||||
|
|
||||||
it { is_expected.to redirect_to expert_avis_url(avis.procedure, avis) }
|
it { is_expected.to redirect_to expert_avis_url(avis.procedure, avis) }
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when the expert is not authenticated' do
|
context 'and the expert is not authenticated' do
|
||||||
before do
|
before { sign_out(expert.user) }
|
||||||
sign_in(expert.user)
|
|
||||||
expert.user.update(last_sign_in_at: Time.zone.now)
|
|
||||||
expert.user.reload
|
|
||||||
sign_out(expert.user)
|
|
||||||
get :sign_up, params: { id: avis.id, procedure_id: procedure.id, email: avis.expert.email }
|
|
||||||
end
|
|
||||||
|
|
||||||
it { is_expected.to redirect_to new_user_session_url }
|
it { is_expected.to redirect_to new_user_session_url }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when the expert has already signed up / is authenticated and does not belong to the invitation' do
|
context 'and the expert does not belong to the invitation' do
|
||||||
let(:expert) { create(:expert) }
|
let(:avis) { create(:avis, email: 'another_expert@avis.com', dossier: dossier, experts_procedure: experts_procedure) }
|
||||||
let!(:avis) { create(:avis, email: invited_email, dossier: dossier, experts_procedure: experts_procedure) }
|
|
||||||
|
|
||||||
before do
|
|
||||||
sign_in(expert.user)
|
|
||||||
get :sign_up, params: { id: avis.id, procedure_id: procedure.id, email: avis.expert.email }
|
|
||||||
end
|
|
||||||
|
|
||||||
|
before { sign_in(expert.user) }
|
||||||
# redirected to dossier but then the instructeur gonna be banished !
|
# redirected to dossier but then the instructeur gonna be banished !
|
||||||
it { is_expected.to redirect_to expert_avis_url(avis.procedure, avis) }
|
it { is_expected.to redirect_to expert_avis_url(avis.procedure, avis) }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe '#update_expert' do
|
||||||
|
subject do
|
||||||
|
post :update_expert, params: {
|
||||||
|
id: avis.id,
|
||||||
|
procedure_id: procedure.id,
|
||||||
|
email: avis.expert.email,
|
||||||
|
user: {
|
||||||
|
password: 'my-s3cure-p4ssword'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when the expert hasn’t signed up yet' do
|
||||||
|
before { expert.user.update(last_sign_in_at: nil) }
|
||||||
|
|
||||||
|
it 'saves the expert new password' do
|
||||||
|
subject
|
||||||
|
expect(expert.user.reload.valid_password?('my-s3cure-p4ssword')).to be true
|
||||||
|
end
|
||||||
|
|
||||||
|
it { is_expected.to redirect_to expert_all_avis_path }
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when the expert has already signed up' do
|
||||||
|
before { expert.user.update(last_sign_in_at: Time.zone.now) }
|
||||||
|
|
||||||
|
it 'doesn’t change the expert password' do
|
||||||
|
subject
|
||||||
|
expect(expert.user.reload.valid_password?('my-s3cure-p4ssword')).to be false
|
||||||
|
end
|
||||||
|
|
||||||
|
it { is_expected.to redirect_to new_user_session_url }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -25,7 +25,6 @@ describe Instructeurs::ArchivesController, type: :controller do
|
||||||
it 'displays archives' do
|
it 'displays archives' do
|
||||||
get :index, { params: { procedure_id: procedure1.id } }
|
get :index, { params: { procedure_id: procedure1.id } }
|
||||||
|
|
||||||
expect(assigns(:nb_dossiers_termines).size).to eq(8)
|
|
||||||
expect(assigns(:archives)).to eq([archive1])
|
expect(assigns(:archives)).to eq([archive1])
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -13,6 +13,7 @@ describe Users::CommencerController, type: :controller do
|
||||||
expect(subject.status).to eq(200)
|
expect(subject.status).to eq(200)
|
||||||
expect(subject).to render_template('show')
|
expect(subject).to render_template('show')
|
||||||
expect(assigns(:procedure)).to eq published_procedure
|
expect(assigns(:procedure)).to eq published_procedure
|
||||||
|
expect(assigns(:revision)).to eq published_procedure.published_revision
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -43,6 +44,7 @@ describe Users::CommencerController, type: :controller do
|
||||||
expect(subject.status).to eq(200)
|
expect(subject.status).to eq(200)
|
||||||
expect(subject).to render_template('show')
|
expect(subject).to render_template('show')
|
||||||
expect(assigns(:procedure)).to eq draft_procedure
|
expect(assigns(:procedure)).to eq draft_procedure
|
||||||
|
expect(assigns(:revision)).to eq draft_procedure.draft_revision
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -11,16 +11,30 @@ feature 'Inviting an expert:' do
|
||||||
let(:avis) { create(:avis, dossier: dossier, claimant: instructeur, experts_procedure: experts_procedure, confidentiel: true) }
|
let(:avis) { create(:avis, dossier: dossier, claimant: instructeur, experts_procedure: experts_procedure, confidentiel: true) }
|
||||||
|
|
||||||
context 'when I don’t already have an account' do
|
context 'when I don’t already have an account' do
|
||||||
scenario 'I can sign up' do
|
let(:password) { 'This is an expert password' }
|
||||||
|
|
||||||
|
before 'Signing up' do
|
||||||
visit sign_up_expert_avis_path(avis.dossier.procedure, avis, email: avis.expert.email)
|
visit sign_up_expert_avis_path(avis.dossier.procedure, avis, email: avis.expert.email)
|
||||||
|
|
||||||
expect(page).to have_field('Email', with: avis.expert.email, disabled: true)
|
expect(page).to have_field('Email', with: avis.expert.email, disabled: true)
|
||||||
fill_in 'Mot de passe', with: 'This is a very complicated password !'
|
fill_in 'Mot de passe', with: password
|
||||||
click_on 'Créer un compte'
|
click_on 'Créer un compte'
|
||||||
|
end
|
||||||
|
|
||||||
|
scenario 'I can see the avis after signing up' do
|
||||||
expect(page).to have_current_path(expert_all_avis_path)
|
expect(page).to have_current_path(expert_all_avis_path)
|
||||||
expect(page).to have_text('1 avis à donner')
|
expect(page).to have_text('1 avis à donner')
|
||||||
end
|
end
|
||||||
|
|
||||||
|
scenario 'I can sign-in again afterwards' do
|
||||||
|
click_on 'Se déconnecter'
|
||||||
|
|
||||||
|
visit new_user_session_path
|
||||||
|
sign_in_with avis.expert.email, password
|
||||||
|
|
||||||
|
expect(page).to have_content('Connecté(e).')
|
||||||
|
expect(page).to have_current_path(dossiers_path) # Ideally we'd want `expert_all_avis_path` instead
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when I already have an existing account' do
|
context 'when I already have an existing account' do
|
||||||
|
|
|
@ -5,6 +5,7 @@ RSpec.describe 'commencer/show.html.haml', type: :view do
|
||||||
|
|
||||||
before do
|
before do
|
||||||
assign(:procedure, procedure)
|
assign(:procedure, procedure)
|
||||||
|
assign(:revision, procedure.published_revision)
|
||||||
if user
|
if user
|
||||||
sign_in user
|
sign_in user
|
||||||
end
|
end
|
||||||
|
|
|
@ -5,6 +5,7 @@ describe 'new_administrateur/procedures/show.html.haml', type: :view do
|
||||||
before do
|
before do
|
||||||
assign(:procedure, procedure)
|
assign(:procedure, procedure)
|
||||||
assign(:procedure_lien, commencer_url(path: procedure.path))
|
assign(:procedure_lien, commencer_url(path: procedure.path))
|
||||||
|
assign(:procedure_lien_test, commencer_test_url(path: procedure.path))
|
||||||
allow(view).to receive(:current_administrateur).and_return(procedure.administrateurs.first)
|
allow(view).to receive(:current_administrateur).and_return(procedure.administrateurs.first)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
62
yarn.lock
62
yarn.lock
|
@ -1005,6 +1005,11 @@
|
||||||
enabled "2.0.x"
|
enabled "2.0.x"
|
||||||
kuler "^2.0.0"
|
kuler "^2.0.0"
|
||||||
|
|
||||||
|
"@headlessui/react@^1.3.0":
|
||||||
|
version "1.3.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@headlessui/react/-/react-1.3.0.tgz#62287c92604923e5dfb394483e5ec2463e1baea6"
|
||||||
|
integrity sha512-2gqTO6BQ3Jr8vDX1B67n1gl6MGKTt6DBmR+H0qxwj0gTMnR2+Qpktj8alRWxsZBODyOiBb77QSQpE/6gG3MX4Q==
|
||||||
|
|
||||||
"@heroicons/react@^1.0.1":
|
"@heroicons/react@^1.0.1":
|
||||||
version "1.0.1"
|
version "1.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/@heroicons/react/-/react-1.0.1.tgz#66d25f6441920bd5c2146ea27fd33995885452dd"
|
resolved "https://registry.yarnpkg.com/@heroicons/react/-/react-1.0.1.tgz#66d25f6441920bd5c2146ea27fd33995885452dd"
|
||||||
|
@ -1567,6 +1572,11 @@
|
||||||
dependencies:
|
dependencies:
|
||||||
"@types/node" ">= 8"
|
"@types/node" ">= 8"
|
||||||
|
|
||||||
|
"@popperjs/core@^2.9.2":
|
||||||
|
version "2.9.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/@popperjs/core/-/core-2.9.2.tgz#adea7b6953cbb34651766b0548468e743c6a2353"
|
||||||
|
integrity sha512-VZMYa7+fXHdwIq1TDhSXoVmSPEGM/aa+6Aiq3nVVJ9bXr24zScr+NlKFKC3iPljA7ho/GAZr+d2jOf5GIRC30Q==
|
||||||
|
|
||||||
"@rails/actiontext@^6.0.3":
|
"@rails/actiontext@^6.0.3":
|
||||||
version "6.0.3"
|
version "6.0.3"
|
||||||
resolved "https://registry.yarnpkg.com/@rails/actiontext/-/actiontext-6.0.3.tgz#71dacd49df7c16a363e20aa89a53efcad8fcecde"
|
resolved "https://registry.yarnpkg.com/@rails/actiontext/-/actiontext-6.0.3.tgz#71dacd49df7c16a363e20aa89a53efcad8fcecde"
|
||||||
|
@ -1638,6 +1648,14 @@
|
||||||
"@reach/utils" "0.13.0"
|
"@reach/utils" "0.13.0"
|
||||||
tslib "^2.0.0"
|
tslib "^2.0.0"
|
||||||
|
|
||||||
|
"@reach/auto-id@0.15.0":
|
||||||
|
version "0.15.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@reach/auto-id/-/auto-id-0.15.0.tgz#f46afebfc140b2099b95c7aec1f049d167d3833d"
|
||||||
|
integrity sha512-iACaCcZeqAhDf4OOwJpmHHS/LaRj9z3Ip8JmlhpCrFWV2YOIiiZk42amlBZX6CKH66Md+eriYZQk3TyAjk6Oxg==
|
||||||
|
dependencies:
|
||||||
|
"@reach/utils" "0.15.0"
|
||||||
|
tslib "^2.1.0"
|
||||||
|
|
||||||
"@reach/combobox@^0.13.0":
|
"@reach/combobox@^0.13.0":
|
||||||
version "0.13.0"
|
version "0.13.0"
|
||||||
resolved "https://registry.yarnpkg.com/@reach/combobox/-/combobox-0.13.0.tgz#16bbdae42fc84f28025e6aa8552f1035cb15a365"
|
resolved "https://registry.yarnpkg.com/@reach/combobox/-/combobox-0.13.0.tgz#16bbdae42fc84f28025e6aa8552f1035cb15a365"
|
||||||
|
@ -1694,6 +1712,17 @@
|
||||||
prop-types "^15.7.2"
|
prop-types "^15.7.2"
|
||||||
tslib "^2.0.0"
|
tslib "^2.0.0"
|
||||||
|
|
||||||
|
"@reach/slider@^0.15.0":
|
||||||
|
version "0.15.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@reach/slider/-/slider-0.15.0.tgz#6b871e913bf10aa8f1ee5a4090478deff71d9c39"
|
||||||
|
integrity sha512-8dYJiclMpjHJ/wc0pIUxbwf8d3oO9ojnbMO31HPdqCqa+2KK8MoYzVdD32VsEa+gznHjoG9c05PPsrAjQd1yYg==
|
||||||
|
dependencies:
|
||||||
|
"@reach/auto-id" "0.15.0"
|
||||||
|
"@reach/utils" "0.15.0"
|
||||||
|
prop-types "^15.7.2"
|
||||||
|
tiny-warning "^1.0.3"
|
||||||
|
tslib "^2.1.0"
|
||||||
|
|
||||||
"@reach/utils@0.13.0":
|
"@reach/utils@0.13.0":
|
||||||
version "0.13.0"
|
version "0.13.0"
|
||||||
resolved "https://registry.yarnpkg.com/@reach/utils/-/utils-0.13.0.tgz#2da775a910d8894bb34e1e94fe95842674f71844"
|
resolved "https://registry.yarnpkg.com/@reach/utils/-/utils-0.13.0.tgz#2da775a910d8894bb34e1e94fe95842674f71844"
|
||||||
|
@ -1703,6 +1732,14 @@
|
||||||
tslib "^2.0.0"
|
tslib "^2.0.0"
|
||||||
warning "^4.0.3"
|
warning "^4.0.3"
|
||||||
|
|
||||||
|
"@reach/utils@0.15.0":
|
||||||
|
version "0.15.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@reach/utils/-/utils-0.15.0.tgz#5b183d668f9bb900b2dec7a33c028a2a828d27b2"
|
||||||
|
integrity sha512-JHHN7T5ucFiuQbqkgv8ECbRWKfRiJxrO/xHR3fHf+f2C7mVs/KkJHhYtovS1iEapR4silygX9PY0+QUmHPOTYw==
|
||||||
|
dependencies:
|
||||||
|
tiny-warning "^1.0.3"
|
||||||
|
tslib "^2.1.0"
|
||||||
|
|
||||||
"@sentry/browser@^5.15.5":
|
"@sentry/browser@^5.15.5":
|
||||||
version "5.15.5"
|
version "5.15.5"
|
||||||
resolved "https://registry.yarnpkg.com/@sentry/browser/-/browser-5.15.5.tgz#d9a51f1388581067b50d30ed9b1aed2cbb333a36"
|
resolved "https://registry.yarnpkg.com/@sentry/browser/-/browser-5.15.5.tgz#d9a51f1388581067b50d30ed9b1aed2cbb333a36"
|
||||||
|
@ -10436,6 +10473,11 @@ react-dom@^17.0.1:
|
||||||
object-assign "^4.1.1"
|
object-assign "^4.1.1"
|
||||||
scheduler "^0.20.1"
|
scheduler "^0.20.1"
|
||||||
|
|
||||||
|
react-fast-compare@^3.0.1:
|
||||||
|
version "3.2.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/react-fast-compare/-/react-fast-compare-3.2.0.tgz#641a9da81b6a6320f270e89724fb45a0b39e43bb"
|
||||||
|
integrity sha512-rtGImPZ0YyLrscKI9xTpV8psd6I8VAtjKCzQDlzyDvqJA8XOW78TXYQwNRNd8g8JZnDu8q9Fu/1v4HPAVwVdHA==
|
||||||
|
|
||||||
react-intersection-observer@^8.31.0:
|
react-intersection-observer@^8.31.0:
|
||||||
version "8.31.0"
|
version "8.31.0"
|
||||||
resolved "https://registry.yarnpkg.com/react-intersection-observer/-/react-intersection-observer-8.31.0.tgz#0ed21aaf93c4c0475b22b0ccaba6169076d01605"
|
resolved "https://registry.yarnpkg.com/react-intersection-observer/-/react-intersection-observer-8.31.0.tgz#0ed21aaf93c4c0475b22b0ccaba6169076d01605"
|
||||||
|
@ -10462,6 +10504,14 @@ react-mapbox-gl@^5.1.1:
|
||||||
deep-equal "1.0.1"
|
deep-equal "1.0.1"
|
||||||
supercluster "^7.0.0"
|
supercluster "^7.0.0"
|
||||||
|
|
||||||
|
react-popper@^2.2.5:
|
||||||
|
version "2.2.5"
|
||||||
|
resolved "https://registry.yarnpkg.com/react-popper/-/react-popper-2.2.5.tgz#1214ef3cec86330a171671a4fbcbeeb65ee58e96"
|
||||||
|
integrity sha512-kxGkS80eQGtLl18+uig1UIf9MKixFSyPxglsgLBxlYnyDf65BiY9B3nZSc6C9XUNDgStROB0fMQlTEz1KxGddw==
|
||||||
|
dependencies:
|
||||||
|
react-fast-compare "^3.0.1"
|
||||||
|
warning "^4.0.2"
|
||||||
|
|
||||||
react-query@^3.9.7:
|
react-query@^3.9.7:
|
||||||
version "3.9.7"
|
version "3.9.7"
|
||||||
resolved "https://registry.yarnpkg.com/react-query/-/react-query-3.9.7.tgz#324c697f418827c129c8c126d233c6052bb1e35e"
|
resolved "https://registry.yarnpkg.com/react-query/-/react-query-3.9.7.tgz#324c697f418827c129c8c126d233c6052bb1e35e"
|
||||||
|
@ -12052,6 +12102,11 @@ timsort@^0.3.0:
|
||||||
resolved "https://registry.yarnpkg.com/timsort/-/timsort-0.3.0.tgz#405411a8e7e6339fe64db9a234de11dc31e02bd4"
|
resolved "https://registry.yarnpkg.com/timsort/-/timsort-0.3.0.tgz#405411a8e7e6339fe64db9a234de11dc31e02bd4"
|
||||||
integrity sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q=
|
integrity sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q=
|
||||||
|
|
||||||
|
tiny-warning@^1.0.3:
|
||||||
|
version "1.0.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/tiny-warning/-/tiny-warning-1.0.3.tgz#94a30db453df4c643d0fd566060d60a875d84754"
|
||||||
|
integrity sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==
|
||||||
|
|
||||||
tinyqueue@^2.0.3:
|
tinyqueue@^2.0.3:
|
||||||
version "2.0.3"
|
version "2.0.3"
|
||||||
resolved "https://registry.yarnpkg.com/tinyqueue/-/tinyqueue-2.0.3.tgz#64d8492ebf39e7801d7bd34062e29b45b2035f08"
|
resolved "https://registry.yarnpkg.com/tinyqueue/-/tinyqueue-2.0.3.tgz#64d8492ebf39e7801d7bd34062e29b45b2035f08"
|
||||||
|
@ -12208,6 +12263,11 @@ tslib@^2.0.0:
|
||||||
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.0.1.tgz#410eb0d113e5b6356490eec749603725b021b43e"
|
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.0.1.tgz#410eb0d113e5b6356490eec749603725b021b43e"
|
||||||
integrity sha512-SgIkNheinmEBgx1IUNirK0TUD4X9yjjBRTqqjggWCU3pUEqIk3/Uwl3yRixYKT6WjQuGiwDv4NomL3wqRCj+CQ==
|
integrity sha512-SgIkNheinmEBgx1IUNirK0TUD4X9yjjBRTqqjggWCU3pUEqIk3/Uwl3yRixYKT6WjQuGiwDv4NomL3wqRCj+CQ==
|
||||||
|
|
||||||
|
tslib@^2.1.0:
|
||||||
|
version "2.3.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.3.0.tgz#803b8cdab3e12ba581a4ca41c8839bbb0dacb09e"
|
||||||
|
integrity sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==
|
||||||
|
|
||||||
tsutils@^3.17.1:
|
tsutils@^3.17.1:
|
||||||
version "3.17.1"
|
version "3.17.1"
|
||||||
resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.17.1.tgz#ed719917f11ca0dee586272b2ac49e015a2dd759"
|
resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.17.1.tgz#ed719917f11ca0dee586272b2ac49e015a2dd759"
|
||||||
|
@ -12680,7 +12740,7 @@ wait-port@^0.2.2:
|
||||||
commander "^3.0.2"
|
commander "^3.0.2"
|
||||||
debug "^4.1.1"
|
debug "^4.1.1"
|
||||||
|
|
||||||
warning@^4.0.3:
|
warning@^4.0.2, warning@^4.0.3:
|
||||||
version "4.0.3"
|
version "4.0.3"
|
||||||
resolved "https://registry.yarnpkg.com/warning/-/warning-4.0.3.tgz#16e9e077eb8a86d6af7d64aa1e05fd85b4678ca3"
|
resolved "https://registry.yarnpkg.com/warning/-/warning-4.0.3.tgz#16e9e077eb8a86d6af7d64aa1e05fd85b4678ca3"
|
||||||
integrity sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==
|
integrity sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==
|
||||||
|
|
Loading…
Add table
Reference in a new issue