Skip to content

Commit 974c8ba

Browse files
committed
[#10788] In instructeur view add a autocomplete select to navigate to a procedure
1 parent bf04e15 commit 974c8ba

File tree

11 files changed

+116
-4
lines changed

11 files changed

+116
-4
lines changed
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# frozen_string_literal: true
2+
3+
class Instructeurs::SelectProcedureDropDownListComponent < Dsfr::InputComponent
4+
def initialize(procedures:)
5+
@procedures = procedures
6+
end
7+
8+
def react_props
9+
{
10+
items:,
11+
placeholder: t('.placeholder'),
12+
name: "procedure_id",
13+
id: 'select-procedure-drop-down-list',
14+
'aria-describedby': 'select-procedure-drop-down-list-label',
15+
form: 'select-procedure-drop-down-list-component',
16+
data: { no_autosubmit: 'input blur', no_autosubmit_on_empty: 'true', autosubmit_target: 'input' }
17+
}
18+
end
19+
20+
def items
21+
@procedures.map { ["n°#{_1.id} - #{_1.libelle}", _1.id] }
22+
end
23+
end
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
---
2+
en:
3+
label: Direct access
4+
placeholder: Select a procedure
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
---
2+
fr:
3+
label: Accès direct
4+
placeholder: Sélectionner une démarche
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
= form_with url: url_for([:select_procedure, :instructeur, :procedures]),
2+
class: 'ml-auto',
3+
id: 'select-procedure-drop-down-list-component',
4+
data: { turbo: true, controller: 'autosubmit' } do
5+
6+
.flex.align-center
7+
= label_tag :procedure_id, t('.label'), class: 'fr-label font-weight-bold fr-mr-2w', id: 'select-procedure-drop-down-list-label', for: 'select-procedure-drop-down-list'
8+
%react-fragment
9+
= render ReactComponent.new "ComboBox/SingleComboBox", **react_props
10+
11+
%input.hidden{
12+
type: 'submit',
13+
formmethod: 'get',
14+
formaction: url_for([:select_procedure, :instructeur, :procedures]),
15+
formnovalidate: 'true',
16+
data: { autosubmit_target: 'submitter' }
17+
}

app/controllers/instructeurs/procedures_controller.rb

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,12 @@ def update_order_positions
7474
redirect_to instructeur_procedures_path, notice: "L'ordre des démarches a été mis à jour."
7575
end
7676

77+
def select_procedure
78+
return redirect_to instructeur_procedure_path(procedure_id: params[:procedure_id]) if params[:procedure_id].present?
79+
80+
redirect_to instructeur_procedures_path
81+
end
82+
7783
def show
7884
@procedure = procedure
7985
# Technically, procedure_presentation already sets the attribute.

app/javascript/components/ComboBox.tsx

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,12 @@ export function ComboBox({
4141
description,
4242
className,
4343
inputRef,
44+
placeholder,
4445
...props
45-
}: ComboBoxProps & { inputRef?: RefObject<HTMLInputElement> }) {
46+
}: ComboBoxProps & {
47+
inputRef?: RefObject<HTMLInputElement>;
48+
placeholder?: string;
49+
}) {
4650
return (
4751
<AriaComboBox
4852
{...props}
@@ -60,7 +64,11 @@ export function ComboBox({
6064
</Label>
6165
) : null}
6266
<div className="fr-ds-combobox__input" style={{ position: 'relative' }}>
63-
<Input className="fr-select fr-autocomplete" ref={inputRef} />
67+
<Input
68+
className="fr-select fr-autocomplete"
69+
ref={inputRef}
70+
placeholder={placeholder || undefined}
71+
/>
6472
<Button
6573
aria-haspopup="false"
6674
aria-label=""
@@ -97,6 +105,7 @@ export function SingleComboBox({
97105
const {
98106
items: defaultItems,
99107
selectedKey: defaultSelectedKey,
108+
placeholder,
100109
emptyFilterKey,
101110
name,
102111
formValue,
@@ -116,7 +125,12 @@ export function SingleComboBox({
116125

117126
return (
118127
<>
119-
<ComboBox menuTrigger="focus" {...comboBoxProps} {...props}>
128+
<ComboBox
129+
menuTrigger="focus"
130+
placeholder={placeholder}
131+
{...comboBoxProps}
132+
{...props}
133+
>
120134
{(item) => <ComboBoxItem id={item.value}>{item.label}</ComboBoxItem>}
121135
</ComboBox>
122136
{children || name ? (

app/javascript/components/react-aria/props.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,8 @@ export const SingleComboBoxProps = s.assign(
4646
s.partial(
4747
s.object({
4848
selectedKey: s.nullable(s.string()),
49-
emptyFilterKey: s.nullable(s.string())
49+
emptyFilterKey: s.nullable(s.string()),
50+
placeholder: s.string()
5051
})
5152
)
5253
);

app/views/instructeurs/procedures/index.html.haml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
.flex.fr-mb-2v
66
%h1.fr-h3.fr-mb-0 Démarches
77
= render Instructeurs::TabsExplanationsComponent.new
8+
= render Instructeurs::SelectProcedureDropDownListComponent.new(procedures: @procedures)
89
= render partial: 'instructeurs/procedures/synthese', locals: { procedures: @procedures, all_dossiers_counts: @all_dossiers_counts }
910

1011
%nav.fr-tabs{ role: 'navigation', 'aria-label': t('views.users.dossiers.secondary_menu') }

config/routes.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -464,6 +464,7 @@
464464
collection do
465465
get 'order_positions'
466466
patch 'update_order_positions'
467+
get 'select_procedure'
467468
end
468469
end
469470

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
# frozen_string_literal: true
2+
3+
require "rails_helper"
4+
5+
RSpec.describe Instructeurs::SelectProcedureDropDownListComponent, type: :component do
6+
subject do
7+
render_inline(described_class.new(procedures:))
8+
end
9+
10+
let(:procedures) {
11+
[
12+
create(:procedure, libelle: "Procedure importante", id: 1001),
13+
create(:procedure, libelle: "Procedure facile", id: 1002),
14+
create(:procedure, libelle: "Procedure terminée", id: 1003)
15+
]
16+
}
17+
18+
it "renders the label" do
19+
expect(subject).to have_text("Accès direct")
20+
end
21+
22+
let(:react_component) { page.find('react-component') }
23+
let(:react_props_items) { JSON.parse(react_component['props']) }
24+
25+
it "renders the procedures" do
26+
subject
27+
expect(react_props_items["items"]).to eq([
28+
["n°1001 - Procedure importante", 1001],
29+
["n°1002 - Procedure facile", 1002],
30+
["n°1003 - Procedure terminée", 1003]
31+
])
32+
end
33+
end

0 commit comments

Comments
 (0)