diff --git a/app/views/layouts/nav/sidebar/_project_menus.html.haml b/app/views/layouts/nav/sidebar/_project_menus.html.haml deleted file mode 100644 index 719f3a3de3368208b725b1a6b41d13f1d2478777..0000000000000000000000000000000000000000 --- a/app/views/layouts/nav/sidebar/_project_menus.html.haml +++ /dev/null @@ -1,34 +0,0 @@ --# Shortcut to Project > Activity -%li.hidden - = link_to activity_project_path(@project), title: _('Activity'), class: 'shortcuts-project-activity' do - %span - = _('Activity') - --# Shortcut to Repository > Graph (formerly, Network) -- if project_nav_tab? :network - %li.hidden - = link_to project_network_path(@project, current_ref), title: _('Network'), class: 'shortcuts-network' do - = _('Graph') - --# Shortcut to Issues > New Issue -- if project_nav_tab?(:issues) - %li.hidden - = link_to new_project_issue_path(@project), class: 'shortcuts-new-issue' do - = _('Create a new issue') - --# Shortcut to Pipelines > Jobs -- if project_nav_tab? :builds - %li.hidden - = link_to project_jobs_path(@project), title: _('Jobs'), class: 'shortcuts-builds' do - = _('Jobs') - --# Shortcut to commits page -- if project_nav_tab? :commits - %li.hidden - = link_to project_commits_path(@project), title: _('Commits'), class: 'shortcuts-commits' do - = _('Commits') - --# Shortcut to issue boards -- if project_nav_tab?(:issues) - %li.hidden - = link_to _('Issue Boards'), project_boards_path(@project), title: _('Issue Boards'), class: 'shortcuts-issue-boards' diff --git a/app/views/shared/nav/_sidebar.html.haml b/app/views/shared/nav/_sidebar.html.haml index 1c06fc9eebf868d1cecde21fc2c649641503f1f6..8e388f2826d5b4b6b0dcd63297002790571ea8b7 100644 --- a/app/views/shared/nav/_sidebar.html.haml +++ b/app/views/shared/nav/_sidebar.html.haml @@ -11,4 +11,5 @@ - if sidebar.render_raw_menus_partial = render sidebar.render_raw_menus_partial + = render partial: 'shared/nav/sidebar_hidden_menu_item', collection: sidebar.hidden_menu&.items = render 'shared/sidebar_toggle_button' diff --git a/app/views/shared/nav/_sidebar_hidden_menu_item.html.haml b/app/views/shared/nav/_sidebar_hidden_menu_item.html.haml new file mode 100644 index 0000000000000000000000000000000000000000..953f7a8ae60c49c9f25ae09494afa65718e9e9ca --- /dev/null +++ b/app/views/shared/nav/_sidebar_hidden_menu_item.html.haml @@ -0,0 +1,3 @@ +%li.hidden + = link_to sidebar_hidden_menu_item.link, **sidebar_hidden_menu_item.container_html_options do + = sidebar_hidden_menu_item.title diff --git a/lib/sidebars/projects/menus/hidden_menu.rb b/lib/sidebars/projects/menus/hidden_menu.rb new file mode 100644 index 0000000000000000000000000000000000000000..19c77c67e1aa9a28697296e9406500844761c0ce --- /dev/null +++ b/lib/sidebars/projects/menus/hidden_menu.rb @@ -0,0 +1,95 @@ +# frozen_string_literal: true + +module Sidebars + module Projects + module Menus + class HiddenMenu < ::Sidebars::Menu + override :configure_menu_items + def configure_menu_items + add_item(activity_menu_item) + add_item(graph_menu_item) + add_item(new_issue_menu_item) + add_item(jobs_menu_item) + add_item(commits_menu_item) + add_item(issue_boards_menu_item) + + true + end + + private + + def activity_menu_item + ::Sidebars::MenuItem.new( + title: _('Activity'), + link: activity_project_path(context.project), + active_routes: {}, + container_html_options: { class: 'shortcuts-project-activity' }, + item_id: :activity + ) + end + + def graph_menu_item + return unless can?(context.current_user, :download_code, context.project) + return if context.project.empty_repo? + + ::Sidebars::MenuItem.new( + title: _('Graph'), + link: project_network_path(context.project, context.current_ref), + active_routes: {}, + container_html_options: { class: 'shortcuts-network' }, + item_id: :graph + ) + end + + def new_issue_menu_item + return unless can?(context.current_user, :read_issue, context.project) + + ::Sidebars::MenuItem.new( + title: _('Create a new issue'), + link: new_project_issue_path(context.project), + active_routes: {}, + container_html_options: { class: 'shortcuts-new-issue' }, + item_id: :new_issue + ) + end + + def jobs_menu_item + return unless can?(context.current_user, :read_build, context.project) + + ::Sidebars::MenuItem.new( + title: _('Jobs'), + link: project_jobs_path(context.project), + active_routes: {}, + container_html_options: { class: 'shortcuts-builds' }, + item_id: :jobs + ) + end + + def commits_menu_item + return unless can?(context.current_user, :download_code, context.project) + return if context.project.empty_repo? + + ::Sidebars::MenuItem.new( + title: _('Commits'), + link: project_commits_path(context.project), + active_routes: {}, + container_html_options: { class: 'shortcuts-commits' }, + item_id: :commits + ) + end + + def issue_boards_menu_item + return unless can?(context.current_user, :read_issue, context.project) + + ::Sidebars::MenuItem.new( + title: _('Issue Boards'), + link: project_boards_path(context.project), + active_routes: {}, + container_html_options: { class: 'shortcuts-issue-boards' }, + item_id: :issue_boards + ) + end + end + end + end +end diff --git a/lib/sidebars/projects/panel.rb b/lib/sidebars/projects/panel.rb index dbf2977df013b1904c9b9b7c88d89a75ec300989..7a35c224cbfde71d7b248ed4e23ebf904fc64201 100644 --- a/lib/sidebars/projects/panel.rb +++ b/lib/sidebars/projects/panel.rb @@ -6,6 +6,7 @@ class Panel < ::Sidebars::Panel override :configure_menus def configure_menus set_scope_menu(Sidebars::Projects::Menus::ScopeMenu.new(context)) + set_hidden_menu(Sidebars::Projects::Menus::HiddenMenu.new(context)) add_menu(Sidebars::Projects::Menus::ProjectInformationMenu.new(context)) add_menu(Sidebars::Projects::Menus::LearnGitlabMenu.new(context)) @@ -27,11 +28,6 @@ def configure_menus add_menu(Sidebars::Projects::Menus::SettingsMenu.new(context)) end - override :render_raw_menus_partial - def render_raw_menus_partial - 'layouts/nav/sidebar/project_menus' - end - override :aria_label def aria_label _('Project navigation') diff --git a/spec/lib/sidebars/projects/menus/hidden_menu_spec.rb b/spec/lib/sidebars/projects/menus/hidden_menu_spec.rb new file mode 100644 index 0000000000000000000000000000000000000000..f7cb0adbb66d058b583e97a29f21c4959c4c3386 --- /dev/null +++ b/spec/lib/sidebars/projects/menus/hidden_menu_spec.rb @@ -0,0 +1,102 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Sidebars::Projects::Menus::HiddenMenu do + let_it_be(:project) { create(:project, :repository) } + + let(:user) { project.owner } + let(:context) { Sidebars::Projects::Context.new(current_user: user, container: project, current_ref: project.repository.root_ref) } + + describe '#render?' do + subject { described_class.new(context) } + + context 'when menu does not have any menu items' do + it 'returns false' do + allow(subject).to receive(:has_items?).and_return(false) + + expect(subject.render?).to be false + end + end + + context 'when menu has menu items' do + it 'returns true' do + expect(subject.render?).to be true + end + end + end + + describe 'Menu items' do + subject { described_class.new(context).items.index { |e| e.item_id == item_id } } + + shared_examples 'access rights checks' do + specify { is_expected.not_to be_nil } + + describe 'when the user does not have access' do + let(:user) { nil } + + specify { is_expected.to be_nil } + end + end + + describe 'Activity' do + let(:item_id) { :activity } + + context 'when user has access to the project' do + specify { is_expected.not_to be_nil } + + describe 'when the user is not present' do + let(:user) { nil } + + specify { is_expected.not_to be_nil } + end + end + end + + describe 'Graph' do + let(:item_id) { :graph } + + context 'when project repository is empty' do + before do + allow(project).to receive(:empty_repo?).and_return(true) + end + + specify { is_expected.to be_nil } + end + + it_behaves_like 'access rights checks' + end + + describe 'New Issue' do + let(:item_id) { :new_issue } + + it_behaves_like 'access rights checks' + end + + describe 'Jobs' do + let(:item_id) { :jobs } + + it_behaves_like 'access rights checks' + end + + describe 'Commits' do + let(:item_id) { :commits } + + context 'when project repository is empty' do + before do + allow(project).to receive(:empty_repo?).and_return(true) + end + + specify { is_expected.to be_nil } + end + + it_behaves_like 'access rights checks' + end + + describe 'Issue Boards' do + let(:item_id) { :issue_boards } + + it_behaves_like 'access rights checks' + end + end +end diff --git a/spec/views/layouts/nav/sidebar/_project.html.haml_spec.rb b/spec/views/layouts/nav/sidebar/_project.html.haml_spec.rb index 11bb81bcd40e629363456c6ee41c40f272dd121c..fafd5777f93b7e53666abeecb67f5932604c796b 100644 --- a/spec/views/layouts/nav/sidebar/_project.html.haml_spec.rb +++ b/spec/views/layouts/nav/sidebar/_project.html.haml_spec.rb @@ -1090,5 +1090,43 @@ end end + describe 'Hidden menus' do + it 'has a link to the Activity page' do + render + + expect(rendered).to have_link('Activity', href: activity_project_path(project), class: 'shortcuts-project-activity', visible: false) + end + + it 'has a link to the Graph page' do + render + + expect(rendered).to have_link('Graph', href: project_network_path(project, current_ref), class: 'shortcuts-network', visible: false) + end + + it 'has a link to the New Issue page' do + render + + expect(rendered).to have_link('Create a new issue', href: new_project_issue_path(project), class: 'shortcuts-new-issue', visible: false) + end + + it 'has a link to the Jobs page' do + render + + expect(rendered).to have_link('Jobs', href: project_jobs_path(project), class: 'shortcuts-builds', visible: false) + end + + it 'has a link to the Commits page' do + render + + expect(rendered).to have_link('Commits', href: project_commits_path(project), class: 'shortcuts-commits', visible: false) + end + + it 'has a link to the Issue Boards page' do + render + + expect(rendered).to have_link('Issue Boards', href: project_boards_path(project), class: 'shortcuts-issue-boards', visible: false) + end + end + it_behaves_like 'sidebar includes snowplow attributes', 'render', 'projects_side_navigation', 'projects_side_navigation' end