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
]
end
def sidebar_projects_paths
%w[
projects#show
projects#activity
releases#index
]
end
def sidebar_settings_paths
%w[
projects#edit
......
......@@ -17,6 +17,13 @@ module Sidebars
{}
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
raise NotImplementedError
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
override :configure_menus
def configure_menus
set_scope_menu(Sidebars::Projects::Menus::Scope::Menu.new(context))
add_menu(Sidebars::Projects::Menus::ProjectOverview::Menu.new(context))
end
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
= nav_link(controller: :learn_gitlab, html_options: { class: 'home' }) do
= link_to project_learn_gitlab_path(@project) do
......
......@@ -6,6 +6,8 @@
= render sidebar.render_raw_scope_menu_partial
%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
= 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
include SubMenus::Packages
view 'app/views/layouts/nav/sidebar/_project_menus.html.haml' do
element :activity_link
element :merge_requests_link
element :snippets_link
element :members_link
......@@ -24,6 +23,10 @@ module QA
element :wiki_link
end
view 'app/views/shared/nav/_sidebar_menu_item.html.haml' do
element :sidebar_menu_item_link
end
def click_merge_requests
within_sidebar do
click_element(:merge_requests_link)
......@@ -38,7 +41,7 @@ module QA
def click_activity
within_sidebar do
click_element(:activity_link)
click_element(:sidebar_menu_item_link, menu_item: 'Activity')
end
end
......
......@@ -13,8 +13,8 @@ module QA
base.class_eval do
include QA::Page::Project::SubMenus::Common
view 'app/views/layouts/nav/sidebar/_project_menus.html.haml' do
element :project_link
view 'app/views/shared/nav/_sidebar_menu.html.haml' do
element :sidebar_menu_link
end
end
end
......@@ -22,7 +22,7 @@ module QA
def click_project
retry_on_exception do
within_sidebar do
click_element(:project_link)
click_element(:sidebar_menu_link, menu_item: 'Project overview')
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'
RSpec.describe 'layouts/nav/sidebar/_project' do
let_it_be_with_reload(:project) { create(:project, :repository) }
let(:user) { project.owner }
before do
assign(:project, project)
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(:current_user).and_return(user)
end
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
it 'has board tab' do
render
......@@ -99,19 +134,11 @@ RSpec.describe 'layouts/nav/sidebar/_project' do
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
let(:can_read_wiki) { true }
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
describe 'when wiki is enabled' do
......@@ -299,7 +326,7 @@ RSpec.describe 'layouts/nav/sidebar/_project' do
let(:read_cycle_analytics) { true }
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
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