refactor(nav): organize main navigation logic across profiles
This commit is contained in:
parent
cdef5d8942
commit
a41c8f73ad
14 changed files with 185 additions and 69 deletions
|
@ -0,0 +1,26 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class MainNavigation::InstructeurExpertNavigationComponent < ApplicationComponent
|
||||
def instructeur?
|
||||
helpers.instructeur_signed_in?
|
||||
end
|
||||
|
||||
def expert?
|
||||
helpers.expert_signed_in?
|
||||
end
|
||||
|
||||
def aria_current_for(page)
|
||||
{ current: page == current_page ? :page : nil }
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def current_page
|
||||
case controller_name
|
||||
when 'avis'
|
||||
:avis
|
||||
when 'procedures', 'dossiers'
|
||||
:procedure
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,12 @@
|
|||
%nav#header-navigation.fr-nav{ role: :navigation, "aria-label" => t('main_menu', scope: [:layouts, :header]) }
|
||||
%ul.fr-nav__list
|
||||
- if instructeur?
|
||||
%li.fr-nav__item
|
||||
= link_to Procedure.model_name.human(count: 10), instructeur_procedures_path, class: 'fr-nav__link', aria: aria_current_for(:procedure)
|
||||
|
||||
- if expert?
|
||||
%li.fr-nav__item
|
||||
= link_to expert_all_avis_path, class: 'fr-nav__link', aria: aria_current_for(:avis) do
|
||||
= Avis.model_name.human(count: 10)
|
||||
- if helpers.current_expert.avis_summary[:unanswered] > 0
|
||||
%span.badge.warning= helpers.current_expert.avis_summary[:unanswered]
|
5
app/views/administrateurs/_main_navigation.html.haml
Normal file
5
app/views/administrateurs/_main_navigation.html.haml
Normal file
|
@ -0,0 +1,5 @@
|
|||
%nav#header-navigation.fr-nav{ role: 'navigation', 'aria-label': 'Menu principal administrateur' }
|
||||
%ul.fr-nav__list
|
||||
%li.fr-nav__item= link_to 'Mes démarches', admin_procedures_path, class:'fr-nav__link', 'aria-current': current_page?(controller: 'administrateurs/procedures', action: :index) ? 'true' : nil
|
||||
- if Rails.application.config.ds_zonage_enabled
|
||||
%li.fr-nav__item= link_to 'Toutes les démarches', all_admin_procedures_path(zone_ids: current_administrateur.zones), class:'fr-nav__link', 'aria-current': current_page?(all_admin_procedures_path) ? 'page' : nil
|
|
@ -1,6 +0,0 @@
|
|||
.fr-container
|
||||
%nav#header-navigation.fr-nav{ role: 'navigation', 'aria-label': 'Menu principal administrateur' }
|
||||
%ul.fr-nav__list
|
||||
%li.fr-nav__item= link_to 'Mes démarches', admin_procedures_path, class:'fr-nav__link', 'aria-current': current_page?(controller: 'procedures', action: :index) ? 'true' : nil
|
||||
- if Rails.application.config.ds_zonage_enabled
|
||||
%li.fr-nav__item= link_to 'Toutes les démarches', all_admin_procedures_path(zone_ids: current_administrateur.zones), class:'fr-nav__link', 'aria-current': current_page?(all_admin_procedures_path) ? 'page' : nil
|
|
@ -1,5 +1,3 @@
|
|||
= render 'main_menu'
|
||||
|
||||
.sub-header
|
||||
.procedure-admin-listing-container
|
||||
= link_to "Nouvelle Démarche", new_from_existing_admin_procedures_path, id: 'new-procedure', class: 'fr-btn'
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
- dossier = controller.try(:dossier_for_help)
|
||||
- procedure = controller.try(:procedure_for_help)
|
||||
- is_instructeur_context = nav_bar_profile == :instructeur && instructeur_signed_in?
|
||||
- is_administrateur_context = nav_bar_profile == :administrateur && administrateur_signed_in?
|
||||
- is_expert_context = nav_bar_profile == :expert && expert_signed_in?
|
||||
- is_user_context = nav_bar_profile == :user
|
||||
- is_search_enabled = [params[:controller] == 'recherche', is_instructeur_context, is_expert_context, is_user_context && current_user.dossiers.count].any?
|
||||
|
@ -20,7 +21,7 @@
|
|||
.fr-header__navbar
|
||||
- if is_search_enabled
|
||||
%button.fr-btn--search.fr-btn{ "aria-controls" => "search-modal", "data-fr-opened" => "false", :title => t('views.users.dossiers.search.search_file') }= t('views.users.dossiers.search.search_file')
|
||||
%button.fr-btn--menu.fr-btn{ "aria-controls" => "burger-menu", "aria-haspopup" => "menu", "data-fr-opened" => "false", :title => "Menu" } Menu
|
||||
%button#navbar-burger-button.fr-btn--menu.fr-btn{ "aria-controls" => "modal-header__menu", "aria-haspopup" => "menu", "data-fr-opened" => "false", title: "Menu" } Menu
|
||||
.fr-header__service
|
||||
- root_profile_link, root_profile_libelle = root_path_info_for_profile(nav_bar_profile)
|
||||
|
||||
|
@ -68,39 +69,20 @@
|
|||
- if is_expert_context
|
||||
= render partial: 'layouts/search_dossiers_form'
|
||||
|
||||
- has_header = [is_instructeur_context, is_expert_context, is_user_context]
|
||||
#burger-menu.fr-header__menu.fr-modal
|
||||
#modal-header__menu.fr-header__menu.fr-modal{ "aria-labelledby": "navbar-burger-button" }
|
||||
.fr-container
|
||||
%button#burger_button.fr-btn--close.fr-btn{ "aria-controls" => "burger-menu", :title => t('close_modal', scope: [:layouts, :header]) }= t('close_modal', scope: [:layouts, :header])
|
||||
%button.fr-btn--close.fr-btn{ "aria-controls" => "modal-header__menu", title: t('close_modal', scope: [:layouts, :header]) }= t('close_modal', scope: [:layouts, :header])
|
||||
.fr-header__menu-links
|
||||
%nav#navigation-478.fr-nav{ "aria-label" => t('main_menu', scope: [:layouts, :header]) , :role => "navigation" }
|
||||
%ul.fr-nav__list
|
||||
-# Questionner UX pour un back JS
|
||||
- if params[:controller] == 'users/commencer'
|
||||
%li.fr-nav__item
|
||||
= link_to t('back', scope: [:layouts, :header]), url_for(:back), title: t('back_title', scope: [:layouts, :header]), class: 'fr-nav__link'
|
||||
-# populated by dsfr js
|
||||
|
||||
- if is_instructeur_context
|
||||
- if current_instructeur.procedures.any?
|
||||
- current_url = request.path_info
|
||||
%li.fr-nav__item
|
||||
= active_link_to t('utils.procedure'), instructeur_procedures_path, active: ['dossiers','procedures'].include?(controller_name), class: 'fr-nav__link', aria: { current: current_url == instructeur_procedures_path ? 'page' : true }
|
||||
- if current_instructeur.user.expert && current_expert.avis_summary[:total] > 0
|
||||
= render partial: 'layouts/header/avis_tab', locals: { current_expert: current_expert }
|
||||
- if content_for?(:main_navigation)
|
||||
= yield(:main_navigation)
|
||||
- elsif is_administrateur_context
|
||||
= render 'administrateurs/main_navigation'
|
||||
- elsif is_instructeur_context || is_expert_context
|
||||
= render MainNavigation::InstructeurExpertNavigationComponent.new
|
||||
- elsif is_user_context
|
||||
= render 'users/main_navigation'
|
||||
|
||||
- if is_expert_context
|
||||
- if current_expert.user.instructeur && current_instructeur.procedures.any?
|
||||
%li.fr-nav__item= active_link_to t('utils.procedure'), instructeur_procedures_path, active: ['dossiers','procedures'].include?(controller_name), class: 'fr-nav__link', aria: { current: true }
|
||||
- if current_expert.avis_summary[:total] > 0
|
||||
= render partial: 'layouts/header/avis_tab', locals: { current_expert: current_expert }
|
||||
|
||||
- if is_user_context
|
||||
%li.fr-nav__item= active_link_to t('.files'), dossiers_path, active: :inclusive, class: 'fr-nav__link', aria: { current: true }
|
||||
- if current_user.expert && current_expert.avis_summary[:total] > 0
|
||||
= render partial: 'layouts/header/avis_tab', locals: { current_expert: current_expert }
|
||||
|
||||
- if content_for?(:navigation_principale)
|
||||
.fr-container
|
||||
= yield(:navigation_principale)
|
||||
|
||||
= yield(:notice_info)
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
- content_for(:main_navigation) do
|
||||
= render 'administrateurs/main_navigation'
|
||||
|
||||
- content_for :content do
|
||||
= render 'main_menu'
|
||||
.fr-container
|
||||
%h1.fr-my-4w Toutes les démarches
|
||||
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
%li.fr-nav__item
|
||||
= active_link_to expert_all_avis_path, active: controller_name == 'avis', class: 'fr-nav__link' do
|
||||
Avis
|
||||
- if current_expert.avis_summary[:unanswered] > 0
|
||||
%span.badge.warning= current_expert.avis_summary[:unanswered]
|
|
@ -1,17 +1,16 @@
|
|||
- content_for(:navigation_principale) do
|
||||
.fr-container
|
||||
%nav.fr-nav#header-navigation{ role: "navigation", aria: { label: 'Menu principal annonces' } }
|
||||
%ul.fr-nav__list
|
||||
- content_for(:main_navigation) do
|
||||
%nav.fr-nav#header-navigation{ role: "navigation", aria: { label: 'Menu principal annonces' } }
|
||||
%ul.fr-nav__list
|
||||
%li.fr-nav__item
|
||||
= link_to "Toutes les annonces", super_admins_release_notes_path, class: "fr-nav__link", target: "_self", aria: { current: action == :index ? "page" : nil }
|
||||
|
||||
%li.fr-nav__item
|
||||
= link_to("Nouvelle annonce", new_super_admins_release_note_path(date: @release_note&.released_on), class: "fr-nav__link", target: "_self", aria: { current: action == :new ? "page" : nil })
|
||||
|
||||
- if action == :edit
|
||||
%li.fr-nav__item
|
||||
= link_to "Toutes les annonces", super_admins_release_notes_path, class: "fr-nav__link", target: "_self", aria: { current: action == :index ? "page" : nil }
|
||||
= link_to "Annonce", '', class: "fr-nav__link", target: "_self", aria: { current: "page" }
|
||||
|
||||
%li.fr-nav__item
|
||||
= link_to("Nouvelle annonce", new_super_admins_release_note_path(date: @release_note&.released_on), class: "fr-nav__link", target: "_self", aria: { current: action == :new ? "page" : nil })
|
||||
|
||||
- if action == :edit
|
||||
%li.fr-nav__item
|
||||
= link_to "Annonce", '', class: "fr-nav__link", target: "_self", aria: { current: "page" }
|
||||
|
||||
%li.fr-nav__item
|
||||
= link_to "Annonces publiées", release_notes_path, class: "fr-nav__link", target: "_self"
|
||||
%li.fr-nav__item
|
||||
= link_to "Annonces publiées", release_notes_path, class: "fr-nav__link", target: "_self"
|
||||
|
||||
|
|
8
app/views/users/_main_navigation.html.haml
Normal file
8
app/views/users/_main_navigation.html.haml
Normal file
|
@ -0,0 +1,8 @@
|
|||
%nav#header-navigation.fr-nav{ role: :navigation, "aria-label" => t('main_menu', scope: [:layouts, :header]) }
|
||||
%ul.fr-nav__list
|
||||
- if params[:controller] == 'users/commencer'
|
||||
%li.fr-nav__item
|
||||
= link_to t('back', scope: [:layouts, :header]), url_for(:back), title: t('back_title', scope: [:layouts, :header]), class: 'fr-nav__link', "aria-controls" => "modal-header__menu"
|
||||
|
||||
%li.fr-nav__item
|
||||
= link_to t('files', scope: [:layouts, :header]), dossiers_path, class: 'fr-nav__link', aria: { current: current_page?(dossiers_path) ? 'page' : nil, controls: "modal-header__menu" }
|
|
@ -56,7 +56,6 @@ en:
|
|||
subject: Subject
|
||||
message: Message
|
||||
send_mail: Send message
|
||||
procedure: Procedures
|
||||
new_tab: New tab
|
||||
helpers:
|
||||
procedure:
|
||||
|
|
|
@ -47,7 +47,6 @@ fr:
|
|||
subject: Sujet
|
||||
message: Message
|
||||
send_mail: Envoyer le message
|
||||
procedure: Démarches
|
||||
new_tab: "Nouvel onglet"
|
||||
helpers:
|
||||
procedure:
|
||||
|
|
|
@ -0,0 +1,85 @@
|
|||
describe MainNavigation::InstructeurExpertNavigationComponent, type: :component do
|
||||
let(:component) { described_class.new }
|
||||
let(:as_instructeur) { true }
|
||||
let(:as_expert) { false }
|
||||
let(:controller_name) { 'dossiers' }
|
||||
let(:user) { build(:user) }
|
||||
|
||||
subject { render_inline(component) }
|
||||
|
||||
before do
|
||||
if as_instructeur
|
||||
user.build_instructeur
|
||||
end
|
||||
|
||||
if as_expert
|
||||
user.build_expert
|
||||
end
|
||||
|
||||
allow_any_instance_of(ApplicationController).to receive(:current_user).and_return(user)
|
||||
allow_any_instance_of(ApplicationController).to receive(:administrateur_signed_in?).and_return(false)
|
||||
allow_any_instance_of(ApplicationController).to receive(:controller_name).and_return(controller_name)
|
||||
end
|
||||
|
||||
describe 'when instructor is signed in' do
|
||||
it 'renders a link to instructeur procedures with current page class' do
|
||||
expect(subject).to have_link('Démarches', href: component.helpers.instructeur_procedures_path)
|
||||
expect(subject).to have_selector('a[aria-current="page"]', text: 'Démarches')
|
||||
end
|
||||
|
||||
it 'does not have Avis' do
|
||||
expect(subject).not_to have_link('Avis')
|
||||
end
|
||||
|
||||
context 'when instructor is also an expert' do
|
||||
let(:as_expert) { true }
|
||||
before do
|
||||
allow(user.expert).to receive(:avis_summary).and_return({ unanswered: 0 })
|
||||
end
|
||||
|
||||
it 'render have Avis link' do
|
||||
expect(subject).to have_link('Avis', href: component.helpers.expert_all_avis_path)
|
||||
expect(subject).not_to have_selector('a[aria-current="page"]', text: 'Avis')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'when expert is signed in' do
|
||||
let(:as_instructeur) { false }
|
||||
let(:as_expert) { true }
|
||||
|
||||
let(:unanswered) { 0 }
|
||||
let(:controller_name) { 'avis' }
|
||||
|
||||
before do
|
||||
allow(user.expert).to receive(:avis_summary).and_return({ unanswered: })
|
||||
end
|
||||
|
||||
it 'renders a link to expert all avis with current page class' do
|
||||
expect(subject).to have_link('Avis', href: component.helpers.expert_all_avis_path)
|
||||
expect(subject).to have_selector('a[aria-current="page"]', text: 'Avis')
|
||||
expect(subject).not_to have_selector('span.badge')
|
||||
end
|
||||
|
||||
it 'does not have Démarches link' do
|
||||
expect(subject).not_to have_link('Démarches')
|
||||
end
|
||||
|
||||
context 'when there are unanswered avis' do
|
||||
let(:unanswered) { 2 }
|
||||
|
||||
it 'renders an unanswered avis badge for the expert' do
|
||||
expect(subject).to have_selector('span.badge.warning', text: '2')
|
||||
end
|
||||
end
|
||||
|
||||
context 'when expert is also instructor' do
|
||||
let(:as_instructeur) { true }
|
||||
|
||||
it 'render have Démarches link' do
|
||||
expect(subject).to have_link('Démarches', href: component.helpers.instructeur_procedures_path)
|
||||
expect(subject).not_to have_selector('a[aria-current="page"]', text: 'Démarches')
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -27,6 +27,18 @@ describe 'wcag rules for usager', js: true do
|
|||
end
|
||||
end
|
||||
|
||||
def expect_axe_clean_without_main_navigation
|
||||
# On page without main navigation content (like anonymous home page),
|
||||
# there are either a bug in axe, either dsfr markup is not conform to wcag2a.
|
||||
# There is no issue on pages having a child navigation.
|
||||
expect(page).to be_axe_clean.excluding("#modal-header__menu")
|
||||
expect(page).to be_axe_clean.within("#modal-header__menu").skipping("aria-prohibited-attr")
|
||||
end
|
||||
|
||||
shared_examples "axe clean without main navigation" do
|
||||
it { expect_axe_clean_without_main_navigation }
|
||||
end
|
||||
|
||||
context 'pages without the need to be logged in' do
|
||||
before do
|
||||
visit path
|
||||
|
@ -34,14 +46,14 @@ describe 'wcag rules for usager', js: true do
|
|||
|
||||
context 'homepage' do
|
||||
let(:path) { root_path }
|
||||
it { expect(page).to be_axe_clean }
|
||||
it_behaves_like "axe clean without main navigation"
|
||||
it_behaves_like "external links have title says it opens in a new tab"
|
||||
it_behaves_like "aria-label do not mix with title attribute"
|
||||
end
|
||||
|
||||
context 'sign_up page' do
|
||||
let(:path) { new_user_registration_path }
|
||||
it { expect(page).to be_axe_clean }
|
||||
it_behaves_like "axe clean without main navigation"
|
||||
it_behaves_like "external links have title says it opens in a new tab"
|
||||
it_behaves_like "aria-label do not mix with title attribute"
|
||||
end
|
||||
|
@ -54,11 +66,11 @@ describe 'wcag rules for usager', js: true do
|
|||
|
||||
perform_enqueued_jobs do
|
||||
click_button 'Créer un compte'
|
||||
expect(page).to be_axe_clean
|
||||
expect_axe_clean_without_main_navigation
|
||||
end
|
||||
end
|
||||
|
||||
context 'sign_upc confirmation' do
|
||||
context 'sign_up confirmation' do
|
||||
let(:path) { user_confirmation_path("user[email]" => "some@email.com") }
|
||||
|
||||
it_behaves_like "external links have title says it opens in a new tab"
|
||||
|
@ -67,21 +79,21 @@ describe 'wcag rules for usager', js: true do
|
|||
|
||||
context 'sign_in page' do
|
||||
let(:path) { new_user_session_path }
|
||||
it { expect(page).to be_axe_clean.excluding '#user_email' }
|
||||
it_behaves_like "axe clean without main navigation"
|
||||
it_behaves_like "external links have title says it opens in a new tab"
|
||||
it_behaves_like "aria-label do not mix with title attribute"
|
||||
end
|
||||
|
||||
context 'contact page' do
|
||||
let(:path) { contact_path }
|
||||
it { expect(page).to be_axe_clean }
|
||||
it_behaves_like "axe clean without main navigation"
|
||||
it_behaves_like "external links have title says it opens in a new tab"
|
||||
it_behaves_like "aria-label do not mix with title attribute"
|
||||
end
|
||||
|
||||
context 'commencer page' do
|
||||
let(:path) { commencer_path(path: procedure.path) }
|
||||
it { expect(page).to be_axe_clean }
|
||||
it_behaves_like "axe clean without main navigation"
|
||||
it_behaves_like "external links have title says it opens in a new tab"
|
||||
it_behaves_like "aria-label do not mix with title attribute"
|
||||
end
|
||||
|
@ -90,7 +102,7 @@ describe 'wcag rules for usager', js: true do
|
|||
visit commencer_path(path: procedure.reload.path)
|
||||
|
||||
page.find("#help-menu_button").click
|
||||
expect(page).to be_axe_clean
|
||||
expect_axe_clean_without_main_navigation
|
||||
end
|
||||
end
|
||||
|
||||
|
|
Loading…
Reference in a new issue