Commit 23e27944 authored by Arturo Herrero's avatar Arturo Herrero

Merge branch '326345-fj-add-project-overview-menu' into 'master'

Add `Project overview` menu to the project sidebar

See merge request gitlab-org/gitlab!59007
parents 9c6e38c4 629521e5
...@@ -729,14 +729,6 @@ module ProjectsHelper ...@@ -729,14 +729,6 @@ module ProjectsHelper
] ]
end end
def sidebar_projects_paths
%w[
projects#show
projects#activity
releases#index
]
end
def sidebar_settings_paths def sidebar_settings_paths
%w[ %w[
projects#edit projects#edit
......
...@@ -17,6 +17,13 @@ module Sidebars ...@@ -17,6 +17,13 @@ module Sidebars
{} {}
end end
# Attributes to pass to the html_options attribute
# in the helper method that sets the active class
# on each element.
def nav_link_html_options
{}
end
def title def title
raise NotImplementedError raise NotImplementedError
end end
......
# frozen_string_literal: true
module Sidebars
module Projects
module Menus
module ProjectOverview
class Menu < ::Sidebars::Menu
override :configure_menu_items
def configure_menu_items
add_item(MenuItems::Details.new(context))
add_item(MenuItems::Activity.new(context))
add_item(MenuItems::Releases.new(context))
end
override :link
def link
project_path(context.project)
end
override :extra_container_html_options
def extra_container_html_options
{
class: 'shortcuts-project rspec-project-link'
}
end
override :extra_container_html_options
def nav_link_html_options
{ class: 'home' }
end
override :title
def title
_('Project overview')
end
override :sprite_icon
def sprite_icon
'home'
end
end
end
end
end
end
# frozen_string_literal: true
module Sidebars
module Projects
module Menus
module ProjectOverview
module MenuItems
class Activity < ::Sidebars::MenuItem
override :link
def link
activity_project_path(context.project)
end
override :extra_container_html_options
def extra_container_html_options
{
class: 'shortcuts-project-activity'
}
end
override :active_routes
def active_routes
{ path: 'projects#activity' }
end
override :title
def title
_('Activity')
end
end
end
end
end
end
end
# frozen_string_literal: true
module Sidebars
module Projects
module Menus
module ProjectOverview
module MenuItems
class Details < ::Sidebars::MenuItem
override :link
def link
project_path(context.project)
end
override :extra_container_html_options
def extra_container_html_options
{
title: _('Project details'),
class: 'shortcuts-project'
}
end
override :active_routes
def active_routes
{ path: 'projects#show' }
end
override :title
def title
_('Details')
end
end
end
end
end
end
end
# frozen_string_literal: true
module Sidebars
module Projects
module Menus
module ProjectOverview
module MenuItems
class Releases < ::Sidebars::MenuItem
override :link
def link
project_releases_path(context.project)
end
override :extra_container_html_options
def extra_container_html_options
{
class: 'shortcuts-project-releases'
}
end
override :render?
def render?
can?(context.current_user, :read_release, context.project) && !context.project.empty_repo?
end
override :active_routes
def active_routes
{ controller: :releases }
end
override :title
def title
_('Releases')
end
end
end
end
end
end
end
...@@ -6,6 +6,8 @@ module Sidebars ...@@ -6,6 +6,8 @@ module Sidebars
override :configure_menus override :configure_menus
def configure_menus def configure_menus
set_scope_menu(Sidebars::Projects::Menus::Scope::Menu.new(context)) set_scope_menu(Sidebars::Projects::Menus::Scope::Menu.new(context))
add_menu(Sidebars::Projects::Menus::ProjectOverview::Menu.new(context))
end end
override :render_raw_menus_partial override :render_raw_menus_partial
......
= nav_link(path: sidebar_projects_paths, html_options: { class: 'home' }) do
= link_to project_path(@project), class: 'shortcuts-project rspec-project-link', data: { qa_selector: 'project_link' } do
.nav-icon-container
= sprite_icon('home')
%span.nav-item-name
= _('Project overview')
%ul.sidebar-sub-level-items
= nav_link(path: 'projects#show', html_options: { class: "fly-out-top-item" } ) do
= link_to project_path(@project) do
%strong.fly-out-top-item-name
= _('Project overview')
%li.divider.fly-out-top-item
= nav_link(path: 'projects#show') do
= link_to project_path(@project), title: _('Project details'), class: 'shortcuts-project' do
%span= _('Details')
= nav_link(path: 'projects#activity') do
= link_to activity_project_path(@project), title: _('Activity'), class: 'shortcuts-project-activity', data: { qa_selector: 'activity_link' } do
%span= _('Activity')
- if project_nav_tab?(:releases)
= nav_link(controller: :releases) do
= link_to project_releases_path(@project), title: _('Releases'), class: 'shortcuts-project-releases' do
%span= _('Releases')
- if project_nav_tab? :learn_gitlab - if project_nav_tab? :learn_gitlab
= nav_link(controller: :learn_gitlab, html_options: { class: 'home' }) do = nav_link(controller: :learn_gitlab, html_options: { class: 'home' }) do
= link_to project_learn_gitlab_path(@project) do = link_to project_learn_gitlab_path(@project) do
......
...@@ -6,6 +6,8 @@ ...@@ -6,6 +6,8 @@
= render sidebar.render_raw_scope_menu_partial = render sidebar.render_raw_scope_menu_partial
%ul.sidebar-top-level-items.qa-project-sidebar %ul.sidebar-top-level-items.qa-project-sidebar
- if sidebar.renderable_menus.any?
= render partial: 'shared/nav/sidebar_menu', collection: sidebar.renderable_menus
- if sidebar.render_raw_menus_partial - if sidebar.render_raw_menus_partial
= render sidebar.render_raw_menus_partial = render sidebar.render_raw_menus_partial
......
= nav_link(**sidebar_menu.all_active_routes, html_options: sidebar_menu.nav_link_html_options) do
= link_to sidebar_menu.link, **sidebar_menu.container_html_options, data: { qa_selector: 'sidebar_menu_link', qa_menu_item: sidebar_menu.title } do
- if sidebar_menu.icon_or_image?
.nav-icon-container
- if sidebar_menu.image_path
= image_tag(sidebar_menu.image_path, **sidebar_menu.image_html_options)
- elsif sidebar_menu.sprite_icon
= sprite_icon(sidebar_menu.sprite_icon, **sidebar_menu.sprite_icon_html_options)
%span.nav-item-name{ **sidebar_menu.title_html_options }
= sidebar_menu.title
- if sidebar_menu.has_pill?
%span.badge.badge-pill.count{ **sidebar_menu.pill_html_options }
= number_with_delimiter(sidebar_menu.pill_count)
%ul.sidebar-sub-level-items{ class: ('is-fly-out-only' unless sidebar_menu.has_items?) }
= nav_link(**sidebar_menu.all_active_routes, html_options: { class: 'fly-out-top-item' } ) do
= link_to sidebar_menu.link, title: sidebar_menu.title do
%strong.fly-out-top-item-name
= sidebar_menu.title
- if sidebar_menu.has_pill?
%span.badge.badge-pill.count.fly-out-badge{ **sidebar_menu.pill_html_options }
= number_with_delimiter(sidebar_menu.pill_count)
- if sidebar_menu.has_renderable_items?
%li.divider.fly-out-top-item
= render partial: 'shared/nav/sidebar_menu_item', collection: sidebar_menu.renderable_items
= nav_link(**sidebar_menu_item.active_routes) do
= link_to sidebar_menu_item.link, **sidebar_menu_item.container_html_options, data: { qa_selector: 'sidebar_menu_item_link', qa_menu_item: sidebar_menu_item.title } do
%span
= sidebar_menu_item.title
- if sidebar_menu_item.sprite_icon
= sprite_icon(sidebar_menu_item.sprite_icon, **sidebar_menu_item.sprite_icon_html_options)
- if sidebar_menu_item.show_hint?
.js-feature-highlight{ **sidebar_menu_item.hint_html_options }
...@@ -14,7 +14,6 @@ module QA ...@@ -14,7 +14,6 @@ module QA
include SubMenus::Packages include SubMenus::Packages
view 'app/views/layouts/nav/sidebar/_project_menus.html.haml' do view 'app/views/layouts/nav/sidebar/_project_menus.html.haml' do
element :activity_link
element :merge_requests_link element :merge_requests_link
element :snippets_link element :snippets_link
element :members_link element :members_link
...@@ -24,6 +23,10 @@ module QA ...@@ -24,6 +23,10 @@ module QA
element :wiki_link element :wiki_link
end end
view 'app/views/shared/nav/_sidebar_menu_item.html.haml' do
element :sidebar_menu_item_link
end
def click_merge_requests def click_merge_requests
within_sidebar do within_sidebar do
click_element(:merge_requests_link) click_element(:merge_requests_link)
...@@ -38,7 +41,7 @@ module QA ...@@ -38,7 +41,7 @@ module QA
def click_activity def click_activity
within_sidebar do within_sidebar do
click_element(:activity_link) click_element(:sidebar_menu_item_link, menu_item: 'Activity')
end end
end end
......
...@@ -13,8 +13,8 @@ module QA ...@@ -13,8 +13,8 @@ module QA
base.class_eval do base.class_eval do
include QA::Page::Project::SubMenus::Common include QA::Page::Project::SubMenus::Common
view 'app/views/layouts/nav/sidebar/_project_menus.html.haml' do view 'app/views/shared/nav/_sidebar_menu.html.haml' do
element :project_link element :sidebar_menu_link
end end
end end
end end
...@@ -22,7 +22,7 @@ module QA ...@@ -22,7 +22,7 @@ module QA
def click_project def click_project
retry_on_exception do retry_on_exception do
within_sidebar do within_sidebar do
click_element(:project_link) click_element(:sidebar_menu_link, menu_item: 'Project overview')
end end
end end
end end
......
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Sidebars::Projects::Menus::ProjectOverview::MenuItems::Releases do
let_it_be(:project) { create(:project, :repository) }
let(:user) { project.owner }
let(:context) { Sidebars::Projects::Context.new(current_user: user, container: project) }
subject { described_class.new(context) }
describe '#render?' do
context 'when project repository is empty' do
it 'returns false' do
allow(project).to receive(:empty_repo?).and_return(true)
expect(subject.render?).to eq false
end
end
context 'when project repository is not empty' do
context 'when user can read releases' do
it 'returns true' do
expect(subject.render?).to eq true
end
end
context 'when user cannot read releases' do
let(:user) { nil }
it 'returns false' do
expect(subject.render?).to eq false
end
end
end
end
end
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Sidebars::Projects::Menus::ProjectOverview::Menu do
let(:project) { build(:project) }
let(:context) { Sidebars::Projects::Context.new(current_user: nil, container: project) }
subject { described_class.new(context) }
it 'has the required items' do
items = subject.instance_variable_get(:@items)
expect(items[0]).to be_a(Sidebars::Projects::Menus::ProjectOverview::MenuItems::Details)
expect(items[1]).to be_a(Sidebars::Projects::Menus::ProjectOverview::MenuItems::Activity)
expect(items[2]).to be_a(Sidebars::Projects::Menus::ProjectOverview::MenuItems::Releases)
end
end
...@@ -5,16 +5,51 @@ require 'spec_helper' ...@@ -5,16 +5,51 @@ require 'spec_helper'
RSpec.describe 'layouts/nav/sidebar/_project' do RSpec.describe 'layouts/nav/sidebar/_project' do
let_it_be_with_reload(:project) { create(:project, :repository) } let_it_be_with_reload(:project) { create(:project, :repository) }
let(:user) { project.owner }
before do before do
assign(:project, project) assign(:project, project)
assign(:repository, project.repository) assign(:repository, project.repository)
allow(view).to receive(:current_ref).and_return('master')
allow(view).to receive(:current_ref).and_return('master')
allow(view).to receive(:can?).and_return(true) allow(view).to receive(:can?).and_return(true)
allow(view).to receive(:current_user).and_return(user)
end end
it_behaves_like 'has nav sidebar' it_behaves_like 'has nav sidebar'
describe 'Project Overview' do
it 'has a link to the project path' do
render
expect(rendered).to have_link('Project overview', href: project_path(project), class: %w(shortcuts-project rspec-project-link))
end
describe 'Details' do
it 'has a link to the projects path' do
render
expect(rendered).to have_link('Details', href: project_path(project), class: 'shortcuts-project')
end
end
describe 'Activity' do
it 'has a link to the project activity path' do
render
expect(rendered).to have_link('Activity', href: activity_project_path(project), class: 'shortcuts-project-activity')
end
end
describe 'Releases' do
it 'has a link to the project releases path' do
render
expect(rendered).to have_link('Releases', href: project_releases_path(project), class: 'shortcuts-project-releases')
end
end
end
describe 'issue boards' do describe 'issue boards' do
it 'has board tab' do it 'has board tab' do
render render
...@@ -99,19 +134,11 @@ RSpec.describe 'layouts/nav/sidebar/_project' do ...@@ -99,19 +134,11 @@ RSpec.describe 'layouts/nav/sidebar/_project' do
end end
end end
describe 'releases entry' do
it 'renders releases link' do
render
expect(rendered).to have_link('Releases', href: project_releases_path(project))
end
end
describe 'wiki entry tab' do describe 'wiki entry tab' do
let(:can_read_wiki) { true } let(:can_read_wiki) { true }
before do before do
allow(view).to receive(:can?).with(nil, :read_wiki, project).and_return(can_read_wiki) allow(view).to receive(:can?).with(user, :read_wiki, project).and_return(can_read_wiki)
end end
describe 'when wiki is enabled' do describe 'when wiki is enabled' do
...@@ -299,7 +326,7 @@ RSpec.describe 'layouts/nav/sidebar/_project' do ...@@ -299,7 +326,7 @@ RSpec.describe 'layouts/nav/sidebar/_project' do
let(:read_cycle_analytics) { true } let(:read_cycle_analytics) { true }
before do before do
allow(view).to receive(:can?).with(nil, :read_cycle_analytics, project).and_return(read_cycle_analytics) allow(view).to receive(:can?).with(user, :read_cycle_analytics, project).and_return(read_cycle_analytics)
end end
describe 'when value stream analytics is enabled' do describe 'when value stream analytics is enabled' do
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment