Merge pull request #6273 from betagouv/main
This commit is contained in:
commit
bcb787c5ac
27 changed files with 196 additions and 132 deletions
|
@ -9,6 +9,7 @@ inherit_gem:
|
|||
- config/rails.yml
|
||||
|
||||
AllCops:
|
||||
TargetRubyVersion: 2.7
|
||||
Exclude:
|
||||
- "db/schema.rb"
|
||||
- "db/migrate/20190730153555_recreate_structure.rb"
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
@import "constants";
|
||||
|
||||
.card-admin {
|
||||
color: $black;
|
||||
padding-top: 10px;
|
||||
padding-bottom: 10px;
|
||||
width: 236px;
|
||||
|
@ -35,6 +36,18 @@
|
|||
.card-admin-action {
|
||||
margin-top: auto;
|
||||
}
|
||||
|
||||
.button {
|
||||
margin: auto auto 0 auto;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
color: $blue;
|
||||
|
||||
.button {
|
||||
color: $blue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 600px) {
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
font-size: 14px;
|
||||
|
||||
th {
|
||||
vertical-align: middle;
|
||||
vertical-align: top;
|
||||
padding: (2 * $default-spacer) $default-spacer;
|
||||
}
|
||||
|
||||
|
|
|
@ -289,7 +289,7 @@ class StatsController < ApplicationController
|
|||
dossiers_grouped_by_groupe_instructeur = dossier_plucks.group_by { |(groupe_instructeur_id, *_)| groupe_instructeur_id }
|
||||
|
||||
# Compute the mean time for this procedure
|
||||
procedure_processing_times = dossiers_grouped_by_groupe_instructeur.map do |groupe_instructeur_id, procedure_dossiers|
|
||||
procedure_processing_times = dossiers_grouped_by_groupe_instructeur.filter_map do |groupe_instructeur_id, procedure_dossiers|
|
||||
procedure_fields_count = groupe_instructeur_id_type_de_champs_count[groupe_instructeur_id]
|
||||
|
||||
if (procedure_fields_count == 0 || procedure_fields_count.nil?)
|
||||
|
@ -302,7 +302,6 @@ class StatsController < ApplicationController
|
|||
# We normalize the data for 24 fields
|
||||
procedure_mean * (MEAN_NUMBER_OF_CHAMPS_IN_A_FORM / procedure_fields_count)
|
||||
end
|
||||
.compact
|
||||
|
||||
# Compute the average mean time for all the procedures of this month
|
||||
month_average = mean(procedure_processing_times)
|
||||
|
|
|
@ -30,7 +30,8 @@ module ProcedureHelper
|
|||
typeDeChampsTypes: TypeDeChamp.type_de_champ_types_for(procedure, current_user),
|
||||
typeDeChamps: (procedure.draft_revision ? procedure.draft_revision : procedure).types_de_champ.as_json_for_editor,
|
||||
baseUrl: admin_procedure_types_de_champ_path(procedure),
|
||||
directUploadUrl: rails_direct_uploads_url
|
||||
directUploadUrl: rails_direct_uploads_url,
|
||||
continuerUrl: admin_procedure_path(procedure)
|
||||
}
|
||||
end
|
||||
|
||||
|
@ -40,7 +41,8 @@ module ProcedureHelper
|
|||
typeDeChampsTypes: TypeDeChamp.type_de_champ_types_for(procedure, current_user),
|
||||
typeDeChamps: (procedure.draft_revision ? procedure.draft_revision : procedure).types_de_champ_private.as_json_for_editor,
|
||||
baseUrl: admin_procedure_types_de_champ_path(procedure),
|
||||
directUploadUrl: rails_direct_uploads_url
|
||||
directUploadUrl: rails_direct_uploads_url,
|
||||
continuerUrl: admin_procedure_path(procedure)
|
||||
}
|
||||
end
|
||||
|
||||
|
|
|
@ -21,6 +21,8 @@ import { fire } from '@utils';
|
|||
import { XIcon } from '@heroicons/react/outline';
|
||||
import isHotkey from 'is-hotkey';
|
||||
|
||||
import { useDeferredSubmit } from './shared/hooks';
|
||||
|
||||
const Context = createContext();
|
||||
|
||||
function ComboMultipleDropdownList({
|
||||
|
@ -78,39 +80,12 @@ function ComboMultipleDropdownList({
|
|||
() => document.querySelector(`input[data-uuid="${hiddenFieldId}"]`),
|
||||
[hiddenFieldId]
|
||||
);
|
||||
const awaitFormSubmit = useDeferredSubmit(hiddenField);
|
||||
|
||||
const handleChange = (event) => {
|
||||
setTerm(event.target.value);
|
||||
};
|
||||
|
||||
const onKeyDown = (event) => {
|
||||
if (
|
||||
isHotkey('enter', event) ||
|
||||
isHotkey(' ', event) ||
|
||||
isHotkey(',', event) ||
|
||||
isHotkey(';', event)
|
||||
) {
|
||||
if (
|
||||
term &&
|
||||
[...extraOptions, ...options].map(([label]) => label).includes(term)
|
||||
) {
|
||||
event.preventDefault();
|
||||
return onSelect(term);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const onBlur = (event) => {
|
||||
if (
|
||||
acceptNewValues &&
|
||||
term &&
|
||||
[...extraOptions, ...options].map(([label]) => label).includes(term)
|
||||
) {
|
||||
event.preventDefault();
|
||||
return onSelect(term);
|
||||
}
|
||||
};
|
||||
|
||||
const saveSelection = (fn) => {
|
||||
setSelections((selections) => {
|
||||
selections = fn(selections);
|
||||
|
@ -138,6 +113,7 @@ function ComboMultipleDropdownList({
|
|||
saveSelection((selections) => [...selections, selectedValue]);
|
||||
}
|
||||
setTerm('');
|
||||
awaitFormSubmit.done();
|
||||
};
|
||||
|
||||
const onRemove = (label) => {
|
||||
|
@ -153,6 +129,34 @@ function ComboMultipleDropdownList({
|
|||
inputRef.current.focus();
|
||||
};
|
||||
|
||||
const onKeyDown = (event) => {
|
||||
if (
|
||||
isHotkey('enter', event) ||
|
||||
isHotkey(' ', event) ||
|
||||
isHotkey(',', event) ||
|
||||
isHotkey(';', event)
|
||||
) {
|
||||
if (
|
||||
term &&
|
||||
[...extraOptions, ...options].map(([label]) => label).includes(term)
|
||||
) {
|
||||
event.preventDefault();
|
||||
onSelect(term);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const onBlur = () => {
|
||||
if (
|
||||
term &&
|
||||
[...extraOptions, ...options].map(([label]) => label).includes(term)
|
||||
) {
|
||||
awaitFormSubmit(() => {
|
||||
onSelect(term);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Combobox openOnFocus={true} onSelect={onSelect} aria-label={label}>
|
||||
<ComboboxTokenLabel onRemove={onRemove}>
|
||||
|
|
|
@ -12,6 +12,8 @@ import {
|
|||
import '@reach/combobox/styles.css';
|
||||
import { fire } from '@utils';
|
||||
|
||||
import { useDeferredSubmit } from './shared/hooks';
|
||||
|
||||
function defaultTransformResults(_, results) {
|
||||
return results;
|
||||
}
|
||||
|
@ -45,17 +47,23 @@ function ComboSearch({
|
|||
const [debouncedSearchTerm] = useDebounce(searchTerm, 300);
|
||||
const [value, setValue] = useState(initialValue);
|
||||
const resultsMap = useRef({});
|
||||
const setExternalValue = useCallback((value) => {
|
||||
if (hiddenValueField) {
|
||||
hiddenValueField.setAttribute('value', value);
|
||||
fire(hiddenValueField, 'autosave:trigger');
|
||||
}
|
||||
});
|
||||
const setExternalId = useCallback((key) => {
|
||||
if (hiddenIdField) {
|
||||
hiddenIdField.setAttribute('value', key);
|
||||
}
|
||||
});
|
||||
const setExternalValue = useCallback(
|
||||
(value) => {
|
||||
if (hiddenValueField) {
|
||||
hiddenValueField.setAttribute('value', value);
|
||||
fire(hiddenValueField, 'autosave:trigger');
|
||||
}
|
||||
},
|
||||
[hiddenValueField]
|
||||
);
|
||||
const setExternalId = useCallback(
|
||||
(key) => {
|
||||
if (hiddenIdField) {
|
||||
hiddenIdField.setAttribute('value', key);
|
||||
}
|
||||
},
|
||||
[hiddenIdField]
|
||||
);
|
||||
const setExternalValueAndId = useCallback((value) => {
|
||||
const [key, result] = resultsMap.current[value];
|
||||
setExternalId(key);
|
||||
|
@ -63,7 +71,8 @@ function ComboSearch({
|
|||
if (onChange) {
|
||||
onChange(value, result);
|
||||
}
|
||||
});
|
||||
}, []);
|
||||
const awaitFormSubmit = useDeferredSubmit(hiddenValueField);
|
||||
|
||||
const handleOnChange = useCallback(
|
||||
({ target: { value } }) => {
|
||||
|
@ -82,7 +91,9 @@ function ComboSearch({
|
|||
const handleOnSelect = useCallback((value) => {
|
||||
setExternalValueAndId(value);
|
||||
setValue(value);
|
||||
});
|
||||
setSearchTerm('');
|
||||
awaitFormSubmit.done();
|
||||
}, []);
|
||||
|
||||
const { isSuccess, data } = useQuery([scope, debouncedSearchTerm], {
|
||||
enabled: !!debouncedSearchTerm,
|
||||
|
@ -91,12 +102,22 @@ function ComboSearch({
|
|||
});
|
||||
const results = isSuccess ? transformResults(debouncedSearchTerm, data) : [];
|
||||
|
||||
const onBlur = useCallback(() => {
|
||||
if (!allowInputValues && isSuccess && results[0]) {
|
||||
const [, value] = transformResult(results[0]);
|
||||
awaitFormSubmit(() => {
|
||||
handleOnSelect(value);
|
||||
});
|
||||
}
|
||||
}, [data]);
|
||||
|
||||
return (
|
||||
<Combobox aria-label={label} onSelect={handleOnSelect}>
|
||||
<ComboboxInput
|
||||
className={className}
|
||||
placeholder={placeholder}
|
||||
onChange={handleOnChange}
|
||||
onBlur={onBlur}
|
||||
value={value}
|
||||
required={required}
|
||||
/>
|
||||
|
|
|
@ -60,12 +60,9 @@ function TypeDeChamps({ state: rootState, typeDeChamps }) {
|
|||
|
||||
{addChampLabel(state.isAnnotation)}
|
||||
</button>
|
||||
<button
|
||||
className="button primary"
|
||||
onClick={() => state.flash.success()}
|
||||
>
|
||||
Enregistrer
|
||||
</button>
|
||||
<a className="button accepted" href={state.continuerUrl}>
|
||||
Continuer >
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -22,7 +22,8 @@ class TypesDeChampEditor extends Component {
|
|||
defaultTypeDeChampAttributes,
|
||||
typeDeChampsTypes: props.typeDeChampsTypes,
|
||||
directUploadUrl: props.directUploadUrl,
|
||||
isAnnotation: props.isAnnotation
|
||||
isAnnotation: props.isAnnotation,
|
||||
continuerUrl: props.continuerUrl
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -35,6 +36,7 @@ class TypesDeChampEditor extends Component {
|
|||
|
||||
TypesDeChampEditor.propTypes = {
|
||||
baseUrl: PropTypes.string,
|
||||
continuerUrl: PropTypes.string,
|
||||
directUploadUrl: PropTypes.string,
|
||||
isAnnotation: PropTypes.bool,
|
||||
typeDeChamps: PropTypes.array,
|
||||
|
|
33
app/javascript/components/shared/hooks.js
Normal file
33
app/javascript/components/shared/hooks.js
Normal file
|
@ -0,0 +1,33 @@
|
|||
import { useRef, useCallback } from 'react';
|
||||
|
||||
export function useDeferredSubmit(input) {
|
||||
const calledRef = useRef(false);
|
||||
const awaitFormSubmit = useCallback(
|
||||
(callback) => {
|
||||
const form = input.form;
|
||||
if (!form) {
|
||||
return;
|
||||
}
|
||||
const interceptFormSubmit = (event) => {
|
||||
event.preventDefault();
|
||||
runCallback();
|
||||
form.submit();
|
||||
};
|
||||
calledRef.current = false;
|
||||
form.addEventListener('submit', interceptFormSubmit);
|
||||
const runCallback = () => {
|
||||
form.removeEventListener('submit', interceptFormSubmit);
|
||||
clearTimeout(timer);
|
||||
if (!calledRef.current) {
|
||||
callback();
|
||||
}
|
||||
};
|
||||
const timer = setTimeout(runCallback, 400);
|
||||
},
|
||||
[input]
|
||||
);
|
||||
awaitFormSubmit.done = () => {
|
||||
calledRef.current = true;
|
||||
};
|
||||
return awaitFormSubmit;
|
||||
}
|
|
@ -45,13 +45,13 @@ class AttestationTemplate < ApplicationRecord
|
|||
acc
|
||||
end
|
||||
|
||||
used_tags.map do |used_tag|
|
||||
used_tags.filter_map do |used_tag|
|
||||
corresponding_champ = all_champs_with_libelle_index[used_tag]
|
||||
|
||||
if corresponding_champ && corresponding_champ.value.blank?
|
||||
corresponding_champ
|
||||
end
|
||||
end.compact
|
||||
end
|
||||
end
|
||||
|
||||
def dup
|
||||
|
|
|
@ -56,9 +56,9 @@ class Champs::CarteChamp < Champ
|
|||
:zones_humides,
|
||||
:znieff,
|
||||
:cadastres
|
||||
].map do |layer|
|
||||
].filter_map do |layer|
|
||||
layer_enabled?(layer) ? layer : nil
|
||||
end.compact
|
||||
end
|
||||
end
|
||||
|
||||
def render_options
|
||||
|
@ -82,7 +82,7 @@ class Champs::CarteChamp < Champ
|
|||
bounding_box = RGeo::Cartesian::BoundingBox.new(factory)
|
||||
|
||||
if geo_areas.present?
|
||||
geo_areas.map(&:rgeo_geometry).compact.each do |geometry|
|
||||
geo_areas.filter_map(&:rgeo_geometry).each do |geometry|
|
||||
bounding_box.add(geometry)
|
||||
end
|
||||
elsif dossier.present?
|
||||
|
|
|
@ -24,4 +24,8 @@ class Champs::PhoneChamp < Champs::TextChamp
|
|||
allow_blank: true,
|
||||
message: I18n.t(:not_a_phone, scope: 'activerecord.errors.messages')
|
||||
}, unless: -> { Phonelib.valid_for_country?(value, :pf) }
|
||||
|
||||
def to_s
|
||||
value.present? ? Phonelib.parse(value).full_national : ''
|
||||
end
|
||||
end
|
||||
|
|
|
@ -879,7 +879,7 @@ class Dossier < ApplicationRecord
|
|||
end
|
||||
|
||||
def linked_dossiers_for(instructeur_or_expert)
|
||||
dossier_ids = champs.filter(&:dossier_link?).map(&:value).compact
|
||||
dossier_ids = champs.filter(&:dossier_link?).filter_map(&:value)
|
||||
instructeur_or_expert.dossiers.where(id: dossier_ids)
|
||||
end
|
||||
|
||||
|
@ -920,7 +920,7 @@ class Dossier < ApplicationRecord
|
|||
factory = RGeo::Geographic.simple_mercator_factory
|
||||
bounding_box = RGeo::Cartesian::BoundingBox.new(factory)
|
||||
|
||||
geo_areas.map(&:rgeo_geometry).compact.each do |geometry|
|
||||
geo_areas.filter_map(&:rgeo_geometry).each do |geometry|
|
||||
bounding_box.add(geometry)
|
||||
end
|
||||
|
||||
|
|
|
@ -135,8 +135,8 @@ class ProcedurePresentation < ApplicationRecord
|
|||
case table
|
||||
when 'self'
|
||||
dates = values
|
||||
.map { |v| Time.zone.parse(v).beginning_of_day rescue nil }
|
||||
.compact
|
||||
.filter_map { |v| Time.zone.parse(v).beginning_of_day rescue nil }
|
||||
|
||||
dossiers.filter_by_datetimes(column, dates)
|
||||
when TYPE_DE_CHAMP
|
||||
dossiers.with_type_de_champ(column)
|
||||
|
@ -147,8 +147,8 @@ class ProcedurePresentation < ApplicationRecord
|
|||
when 'etablissement'
|
||||
if column == 'entreprise_date_creation'
|
||||
dates = values
|
||||
.map { |v| v.to_date rescue nil }
|
||||
.compact
|
||||
.filter_map { |v| v.to_date rescue nil }
|
||||
|
||||
dossiers
|
||||
.includes(table)
|
||||
.where(table.pluralize => { column => dates })
|
||||
|
|
|
@ -81,6 +81,7 @@ class DossierProjectionService
|
|||
.pluck(:id, *fields.map { |f| f[COLUMN].to_sym })
|
||||
.each { |id, *columns| fields.zip(columns).each { |field, value| field[:id_value_h][id] = value } }
|
||||
when 'followers_instructeurs'
|
||||
# rubocop:disable Style/HashTransformValues
|
||||
fields[0][:id_value_h] = Follow
|
||||
.active
|
||||
.joins(instructeur: :user)
|
||||
|
@ -88,6 +89,7 @@ class DossierProjectionService
|
|||
.pluck('dossier_id, users.email')
|
||||
.group_by { |dossier_id, _| dossier_id }
|
||||
.to_h { |dossier_id, dossier_id_emails| [dossier_id, dossier_id_emails.sort.map { |_, email| email }&.join(', ')] }
|
||||
# rubocop:enable Style/HashTransformValues
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -12,8 +12,8 @@ class IPService
|
|||
if ENV['TRUSTED_NETWORKS'].present?
|
||||
ENV['TRUSTED_NETWORKS']
|
||||
.split
|
||||
.map { |string| parse_address(string) }
|
||||
.compact
|
||||
.filter_map { |string| parse_address(string) }
|
||||
|
||||
else
|
||||
[]
|
||||
end
|
||||
|
|
|
@ -81,7 +81,7 @@ class PiecesJustificativesService
|
|||
end
|
||||
|
||||
def self.pjs_for_dossier(dossier)
|
||||
bill_signatures = dossier.dossier_operation_logs.map(&:bill_signature).compact.uniq
|
||||
bill_signatures = dossier.dossier_operation_logs.filter_map(&:bill_signature).uniq
|
||||
|
||||
[
|
||||
dossier.justificatif_motivation,
|
||||
|
|
|
@ -32,7 +32,7 @@ class ProcedureExportService
|
|||
[dossier.champs, dossier.champs_private]
|
||||
.flatten
|
||||
.filter { |champ| champ.is_a?(Champs::SiretChamp) }
|
||||
end.map(&:etablissement).compact + dossiers.map(&:etablissement).compact
|
||||
end.filter_map(&:etablissement) + dossiers.filter_map(&:etablissement)
|
||||
end
|
||||
|
||||
def avis
|
||||
|
|
|
@ -4,8 +4,9 @@
|
|||
- steps.each do |step|
|
||||
%li= step
|
||||
- if defined?(preview) && preview
|
||||
= link_to "Prévisualiser le formulaire", apercu_admin_procedure_path(@procedure), target: "_blank", rel: "noopener", class: 'button'
|
||||
= link_to "Continuer >", admin_procedure_path(@procedure), title: 'Vous pourrez revenir ici par la suite', class: 'button accepted'
|
||||
.mb-2
|
||||
= link_to "Prévisualiser le formulaire", apercu_admin_procedure_path(@procedure), target: "_blank", rel: "noopener", class: 'button'
|
||||
= link_to "Continuer >", admin_procedure_path(@procedure), title: 'Vous pourrez revenir ici par la suite', class: 'button accepted'
|
||||
- if defined?(metadatas)
|
||||
%ul.admin-metadata
|
||||
- metadatas.each do |metadata|
|
||||
|
|
|
@ -32,18 +32,17 @@
|
|||
.container
|
||||
%h2.procedure-admin-explanation Indispensable avant publication
|
||||
.procedure-grid
|
||||
.card-admin
|
||||
= link_to edit_admin_procedure_path(@procedure), id: 'presentation', class: 'card-admin' do
|
||||
%div
|
||||
%span.icon.accept
|
||||
%p.card-admin-status-accept Validé
|
||||
%div
|
||||
%p.card-admin-title Présentation
|
||||
%p.card-admin-subtitle Logo, nom, description
|
||||
.card-admin-action
|
||||
= link_to 'Modifier', edit_admin_procedure_path(@procedure), class: 'button', id: "presentation"
|
||||
%p.button Modifier
|
||||
|
||||
- if !@procedure.locked?
|
||||
.card-admin
|
||||
= link_to champs_admin_procedure_path(@procedure), class: 'card-admin' do
|
||||
- if @procedure.draft_types_de_champ.count > 0
|
||||
%div
|
||||
%span.icon.accept
|
||||
|
@ -57,10 +56,19 @@
|
|||
%span.badge.baseline= @procedure.draft_types_de_champ.count
|
||||
Champs du formulaire
|
||||
%p.card-admin-subtitle À remplir par les usagers
|
||||
.card-admin-action
|
||||
= link_to 'Modifier', champs_admin_procedure_path(@procedure), class: 'button'
|
||||
%p.button Modifier
|
||||
|
||||
.card-admin
|
||||
- if @procedure.service.present?
|
||||
- service_link = edit_admin_service_path(@procedure.service, procedure_id: @procedure.id)
|
||||
- service_button_text = 'Modifier'
|
||||
- elsif current_administrateur.services.present?
|
||||
- service_link = admin_services_path(procedure_id: @procedure.id)
|
||||
- service_button_text = 'Choisir'
|
||||
- else
|
||||
- service_link = new_admin_service_path(procedure_id: @procedure.id)
|
||||
- service_button_text = 'Remplir'
|
||||
|
||||
= link_to service_link, class: 'card-admin' do
|
||||
- if @procedure.service_id.present?
|
||||
%div
|
||||
%span.icon.accept
|
||||
|
@ -76,15 +84,9 @@
|
|||
= @procedure.service.nom
|
||||
- else
|
||||
Choix du service administratif
|
||||
.card-admin-action
|
||||
- if @procedure.service.present?
|
||||
= link_to 'Modifier', edit_admin_service_path(@procedure.service, procedure_id: @procedure.id), class: 'button'
|
||||
- elsif current_administrateur.services.present?
|
||||
= link_to 'Choisir', admin_services_path(procedure_id: @procedure.id), class: 'button'
|
||||
- else
|
||||
= link_to 'Remplir', new_admin_service_path(procedure_id: @procedure.id), class: 'button'
|
||||
%p.button= service_button_text
|
||||
|
||||
.card-admin
|
||||
= link_to admin_procedure_administrateurs_path(@procedure), id: 'administrateurs', class: 'card-admin' do
|
||||
%div
|
||||
%span.icon.accept
|
||||
%p.card-admin-status-accept Validé
|
||||
|
@ -92,17 +94,17 @@
|
|||
%p.card-admin-title
|
||||
%span.badge.baseline= @procedure.administrateurs.count
|
||||
#{"Administrateur".pluralize(@procedure.administrateurs.count)}
|
||||
|
||||
%p.card-admin-subtitle Gestion de la démarche
|
||||
.card-admin-action
|
||||
= link_to 'Modifier', admin_procedure_administrateurs_path(@procedure), class: 'button', id: "administrateurs"
|
||||
%p.button Modifier
|
||||
|
||||
.card-admin
|
||||
- if feature_enabled?(:administrateur_routage)
|
||||
%div
|
||||
%span.icon.accept
|
||||
%p.card-admin-status-accept Validé
|
||||
- elsif @procedure.instructeurs.count > 1
|
||||
|
||||
- if feature_enabled?(:administrateur_routage)
|
||||
- instructeur_link = admin_procedure_groupe_instructeurs_path(@procedure)
|
||||
- else
|
||||
- instructeur_link = admin_procedure_groupe_instructeur_path(@procedure, @procedure.defaut_groupe_instructeur)
|
||||
|
||||
= link_to instructeur_link, id: 'groupe-instructeurs', class: 'card-admin' do
|
||||
- if feature_enabled?(:administrateur_routage) || @procedure.instructeurs.count > 1
|
||||
%div
|
||||
%span.icon.accept
|
||||
%p.card-admin-status-accept Validé
|
||||
|
@ -119,15 +121,12 @@
|
|||
|
||||
= feature_enabled?(:administrateur_routage) ? "Groupe Instructeurs" : "#{"Instructeur".pluralize(@procedure.instructeurs.count)}"
|
||||
%p.card-admin-subtitle Suivi des dossiers
|
||||
.card-admin-action
|
||||
- if feature_enabled?(:administrateur_routage)
|
||||
= link_to 'Modifier', admin_procedure_groupe_instructeurs_path(@procedure), class: 'button', id: "groupe-instructeurs"
|
||||
- else
|
||||
= link_to 'Modifier', admin_procedure_groupe_instructeur_path(@procedure, @procedure.defaut_groupe_instructeur), class: 'button', id: "instructeurs"
|
||||
%p.button Modifier
|
||||
|
||||
%h2.procedure-admin-explanation Pour aller plus loin
|
||||
.procedure-grid
|
||||
.card-admin
|
||||
|
||||
= link_to edit_admin_procedure_attestation_template_path(@procedure), class: 'card-admin' do
|
||||
- if @procedure.attestation_template.present? && @procedure.attestation_template.activated
|
||||
%div
|
||||
%span.icon.accept
|
||||
|
@ -139,34 +138,29 @@
|
|||
%div
|
||||
%p.card-admin-title Attestation
|
||||
%p.card-admin-subtitle Délivrance automatique pour les dossiers acceptés
|
||||
.card-admin-action
|
||||
= link_to 'Modifier', edit_admin_procedure_attestation_template_path(@procedure), class: 'button'
|
||||
%p.button Modifier
|
||||
|
||||
.card-admin
|
||||
= link_to admin_procedure_experts_path(@procedure), class: 'card-admin' do
|
||||
%div
|
||||
%span.icon.preview
|
||||
%p.card-admin-status-todo À configurer
|
||||
|
||||
%div
|
||||
%p.card-admin-title Avis externes
|
||||
%p.card-admin-subtitle Gérer les avis des experts invités
|
||||
|
||||
.card-admin-action
|
||||
= link_to "Modifier", admin_procedure_experts_path(@procedure), class: 'button'
|
||||
%p.button Modifier
|
||||
|
||||
|
||||
.card-admin
|
||||
= link_to admin_procedure_mail_templates_path(@procedure), class: 'card-admin' do
|
||||
%div
|
||||
%span.icon.clock
|
||||
%p.card-admin-status-todo À configurer
|
||||
%div
|
||||
%p.card-admin-title Configuration des emails
|
||||
%p.card-admin-subtitle Notifications automatiques
|
||||
.card-admin-action
|
||||
= link_to 'Modifier', admin_procedure_mail_templates_path(@procedure), class: 'button'
|
||||
%p.button Modifier
|
||||
|
||||
- if !@procedure.locked?
|
||||
.card-admin
|
||||
= link_to annotations_admin_procedure_path(@procedure), class: 'card-admin' do
|
||||
- if @procedure.draft_types_de_champ_private.present?
|
||||
%div
|
||||
%span.icon.accept
|
||||
|
@ -178,10 +172,9 @@
|
|||
%div
|
||||
%p.card-admin-title Annotations privées
|
||||
%p.card-admin-subtitle Champs à remplir par l’administration
|
||||
.card-admin-action
|
||||
= link_to 'Modifier', annotations_admin_procedure_path(@procedure), class: 'button'
|
||||
%p.button Modifier
|
||||
|
||||
.card-admin
|
||||
= link_to jeton_admin_procedure_path(@procedure), class: 'card-admin' do
|
||||
- if @procedure.api_entreprise_token.present?
|
||||
%div
|
||||
%span.icon.accept
|
||||
|
@ -193,10 +186,9 @@
|
|||
%div
|
||||
%p.card-admin-title Jeton
|
||||
%p.card-admin-subtitle Configurer le jeton API entreprise
|
||||
.card-admin-action
|
||||
= link_to 'Modifier', jeton_admin_procedure_path(@procedure), class: 'button'
|
||||
%p.button Modifier
|
||||
|
||||
.card-admin
|
||||
= link_to monavis_admin_procedure_path(@procedure), class: 'card-admin' do
|
||||
- if @procedure.monavis_embed.present?
|
||||
%div
|
||||
%span.icon.accept
|
||||
|
@ -208,5 +200,4 @@
|
|||
%div
|
||||
%p.card-admin-title MonAvis
|
||||
%p.card-admin-subtitle Avis des usagers sur votre démarche
|
||||
.card-admin-action
|
||||
= link_to 'Modifier', monavis_admin_procedure_path(@procedure), class: 'button'
|
||||
%p.button Modifier
|
||||
|
|
|
@ -272,7 +272,7 @@ describe Experts::AvisController, type: :controller do
|
|||
context 'when the expert also shares the linked dossiers' do
|
||||
context 'and the expert can access the linked dossiers' do
|
||||
let(:created_avis) { create(:avis, dossier: dossier, claimant: claimant, email: "toto3@gmail.com") }
|
||||
let(:linked_dossier) { Dossier.find_by(id: dossier.reload.champs.filter(&:dossier_link?).map(&:value).compact) }
|
||||
let(:linked_dossier) { Dossier.find_by(id: dossier.reload.champs.filter(&:dossier_link?).filter_map(&:value)) }
|
||||
let(:linked_avis) { create(:avis, dossier: linked_dossier, claimant: claimant) }
|
||||
let(:invite_linked_dossiers) { true }
|
||||
|
||||
|
|
|
@ -520,7 +520,7 @@ describe Instructeurs::DossiersController, type: :controller do
|
|||
context 'and the expert can access the linked dossiers' do
|
||||
let(:saved_avis) { Avis.last(2).first }
|
||||
let(:linked_avis) { Avis.last }
|
||||
let(:linked_dossier) { Dossier.find_by(id: dossier.reload.champs.filter(&:dossier_link?).map(&:value).compact) }
|
||||
let(:linked_dossier) { Dossier.find_by(id: dossier.reload.champs.filter(&:dossier_link?).filter_map(&:value)) }
|
||||
let(:invite_linked_dossiers) do
|
||||
instructeur.assign_to_procedure(linked_dossier.procedure)
|
||||
true
|
||||
|
|
|
@ -8,7 +8,7 @@ feature 'Inviting an expert:', js: true do
|
|||
let(:expert_password) { 'mot de passe d’expert' }
|
||||
let(:procedure) { create(:procedure, :published, instructeurs: [instructeur]) }
|
||||
let(:dossier) { create(:dossier, :en_construction, :with_dossier_link, procedure: procedure) }
|
||||
let(:linked_dossier) { Dossier.find_by(id: dossier.reload.champs.filter(&:dossier_link?).map(&:value).compact) }
|
||||
let(:linked_dossier) { Dossier.find_by(id: dossier.reload.champs.filter(&:dossier_link?).filter_map(&:value)) }
|
||||
|
||||
context 'as an Instructeur' do
|
||||
scenario 'I can invite an expert' do
|
||||
|
|
|
@ -13,12 +13,6 @@ feature 'As an administrateur I can edit types de champ', js: true do
|
|||
fill_in 'champ-0-libelle', with: 'libellé de champ'
|
||||
blur
|
||||
expect(page).to have_content('Formulaire enregistré')
|
||||
|
||||
page.refresh
|
||||
within '.buttons' do
|
||||
click_on 'Enregistrer'
|
||||
end
|
||||
expect(page).to have_content('Formulaire enregistré')
|
||||
end
|
||||
|
||||
it "Add multiple champs" do
|
||||
|
|
|
@ -328,7 +328,7 @@ describe Champ do
|
|||
|
||||
context 'for phone champ' do
|
||||
let(:type_de_champ) { build(:type_de_champ_phone) }
|
||||
let(:value) { "0606060606" }
|
||||
let(:value) { "06 06 06 06 06" }
|
||||
|
||||
it { is_expected.to eq([value]) }
|
||||
end
|
||||
|
|
|
@ -13039,9 +13039,9 @@ write@1.0.3:
|
|||
mkdirp "^0.5.1"
|
||||
|
||||
ws@^6.0.0, ws@^6.2.1:
|
||||
version "6.2.1"
|
||||
resolved "https://registry.yarnpkg.com/ws/-/ws-6.2.1.tgz#442fdf0a47ed64f59b6a5d8ff130f4748ed524fb"
|
||||
integrity sha512-GIyAXC2cB7LjvpgMt9EKS2ldqr0MTrORaleiOno6TweZ6r3TKtoFQWay/2PceJ3RuBasOHzXNn5Lrw1X0bEjqA==
|
||||
version "6.2.2"
|
||||
resolved "https://registry.yarnpkg.com/ws/-/ws-6.2.2.tgz#dd5cdbd57a9979916097652d78f1cc5faea0c32e"
|
||||
integrity sha512-zmhltoSR8u1cnDsD43TX59mzoMZsLKqUweyYBAIvTngR3shc0W6aOZylZmq/7hqyVxPdi+5Ud2QInblgyE72fw==
|
||||
dependencies:
|
||||
async-limiter "~1.0.0"
|
||||
|
||||
|
|
Loading…
Reference in a new issue