Commit daabf092 authored by Robert Speicher's avatar Robert Speicher

Merge branch 'left-nav-requirements' into 'master'

Move Requirements under Issue top level nav item

See merge request gitlab-org/gitlab!70748
parents ba24ccf6 980456b7
...@@ -7,8 +7,12 @@ info: To determine the technical writer assigned to the Stage/Group associated w ...@@ -7,8 +7,12 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Requirements Management **(ULTIMATE)** # Requirements Management **(ULTIMATE)**
NOTE:
In 14.4, Requirements was moved under **Issues**.
> - [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/2703) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 12.10. > - [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/2703) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 12.10.
> - The ability to add and edit a requirement's long description [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/224622) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 13.5. > - The ability to add and edit a requirement's long description [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/224622) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 13.5.
> - [Moved under Issues](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/70748) in 14.4
With requirements, you can set criteria to check your products against. They can be based on users, With requirements, you can set criteria to check your products against. They can be based on users,
stakeholders, system, software, or anything else you find important to capture. stakeholders, system, software, or anything else you find important to capture.
...@@ -38,7 +42,7 @@ Users with Reporter or higher [permissions](../../permissions.md) can create req ...@@ -38,7 +42,7 @@ Users with Reporter or higher [permissions](../../permissions.md) can create req
To create a requirement: To create a requirement:
1. In a project, go to **Requirements**. 1. In a project, go to **Issues > Requirements**.
1. Select **New requirement**. 1. Select **New requirement**.
1. Enter a title and description and select **Create requirement**. 1. Enter a title and description and select **Create requirement**.
...@@ -107,7 +111,7 @@ You can search for a requirement from the requirements list page based on the fo ...@@ -107,7 +111,7 @@ You can search for a requirement from the requirements list page based on the fo
To search for a requirement: To search for a requirement:
1. In a project, go to **Requirements > List**. 1. In a project, go to **Issues > Requirements > List**.
1. Select the **Search or filter results** field. A dropdown menu appears. 1. Select the **Search or filter results** field. A dropdown menu appears.
1. Select the requirement author or status from the dropdown or enter plain text to search by requirement title. 1. Select the requirement author or status from the dropdown or enter plain text to search by requirement title.
1. Press <kbd>Enter</kbd> on your keyboard to filter the list. 1. Press <kbd>Enter</kbd> on your keyboard to filter the list.
...@@ -222,7 +226,7 @@ Before you import your file: ...@@ -222,7 +226,7 @@ Before you import your file:
To import requirements: To import requirements:
1. In a project, go to **Requirements**. 1. In a project, go to **Issues > Requirements**.
- If the project already has existing requirements, select the import icon (**{import}**) in the - If the project already has existing requirements, select the import icon (**{import}**) in the
top right. top right.
- For a project without any requirements, select **Import CSV** in the middle of the page. - For a project without any requirements, select **Import CSV** in the middle of the page.
...@@ -281,7 +285,7 @@ Users with Reporter or higher [permissions](../../permissions.md) can export req ...@@ -281,7 +285,7 @@ Users with Reporter or higher [permissions](../../permissions.md) can export req
To export requirements: To export requirements:
1. In a project, go to **Requirements**. 1. In a project, go to **Issues > Requirements**.
1. In the top right, select the **Export as CSV** icon (**{export}**). 1. In the top right, select the **Export as CSV** icon (**{export}**).
A confirmation modal appears. A confirmation modal appears.
......
...@@ -12,6 +12,7 @@ module EE ...@@ -12,6 +12,7 @@ module EE
return false unless super return false unless super
add_item(iterations_menu_item) add_item(iterations_menu_item)
add_item(requirements_menu_item)
true true
end end
...@@ -34,6 +35,20 @@ module EE ...@@ -34,6 +35,20 @@ module EE
item_id: :iterations item_id: :iterations
) )
end end
def requirements_menu_item
if !context.project.licensed_feature_available?(:requirements) ||
!can?(context.current_user, :read_requirement, context.project)
return ::Sidebars::NilMenuItem.new(item_id: :requirements)
end
::Sidebars::MenuItem.new(
title: _('Requirements'),
link: project_requirements_management_requirements_path(context.project),
active_routes: { path: 'requirements#index' },
item_id: :requirements
)
end
end end
end end
end end
......
...@@ -13,8 +13,6 @@ module EE ...@@ -13,8 +13,6 @@ module EE
if jira_menu.render? if jira_menu.render?
replace_menu(::Sidebars::Projects::Menus::ExternalIssueTrackerMenu, jira_menu) replace_menu(::Sidebars::Projects::Menus::ExternalIssueTrackerMenu, jira_menu)
end end
insert_menu_after(::Sidebars::Projects::Menus::MergeRequestsMenu, ::Sidebars::Projects::Menus::RequirementsMenu.new(context))
end end
private private
......
# frozen_string_literal: true
module Sidebars
module Projects
module Menus
class RequirementsMenu < ::Sidebars::Menu
override :link
def link
project_requirements_management_requirements_path(context.project)
end
override :render?
def render?
can?(context.current_user, :read_requirement, context.project)
end
override :title
def title
_('Requirements')
end
override :sprite_icon
def sprite_icon
'requirements'
end
override :active_routes
def active_routes
{ path: 'requirements#index' }
end
end
end
end
end
...@@ -80,21 +80,4 @@ RSpec.describe 'Project navbar' do ...@@ -80,21 +80,4 @@ RSpec.describe 'Project navbar' do
it_behaves_like 'verified navigation bar' it_behaves_like 'verified navigation bar'
end end
end end
context 'when requirements is available' do
before do
stub_licensed_features(requirements: true)
insert_after_nav_item(
_('Merge requests'),
new_nav_item: {
nav_item: _('Requirements'),
nav_sub_items: []
}
)
visit project_path(project)
end
it_behaves_like 'verified navigation bar'
end
end end
...@@ -41,7 +41,7 @@ RSpec.describe 'Requirements list', :js do ...@@ -41,7 +41,7 @@ RSpec.describe 'Requirements list', :js do
end end
it 'shows the requirements in the navigation sidebar' do it 'shows the requirements in the navigation sidebar' do
expect(first('.nav-sidebar .active a .nav-item-name')).to have_content('Requirements') expect(first('.nav-sidebar .active .sidebar-sub-level-items')).to have_content('Requirements')
end end
it 'shows requirements tabs for each status type' do it 'shows requirements tabs for each status type' do
......
...@@ -38,4 +38,36 @@ RSpec.describe Sidebars::Projects::Menus::IssuesMenu do ...@@ -38,4 +38,36 @@ RSpec.describe Sidebars::Projects::Menus::IssuesMenu do
end end
end end
end end
describe 'Requirements' do
subject { described_class.new(context).renderable_items.any? { |e| e.item_id == :requirements} }
context 'when licensed feature requirements is not enabled' do
it 'does not include requirements menu item' do
stub_licensed_features(requirements: false)
is_expected.to be_falsy
end
end
context 'when licensed feature requirements is enabled' do
before do
stub_licensed_features(requirements: true)
end
context 'when user can read requirements' do
it 'includes requirements menu item' do
is_expected.to be_truthy
end
end
context 'when user cannot read requirements' do
let(:user) { nil }
it 'does not include requirements menu item' do
is_expected.to be_falsy
end
end
end
end
end end
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Sidebars::Projects::Menus::RequirementsMenu do
let(:project) { build(:project) }
let(:user) { project.owner }
let(:context) { Sidebars::Projects::Context.new(current_user: user, container: project) }
subject { described_class.new(context) }
before do
stub_licensed_features(requirements: true)
end
describe '#render?' do
context 'when user cannot read requirements' do
let(:user) { nil }
it 'returns false' do
expect(subject.render?).to eq false
end
end
context 'when user can read requirements' do
it 'returns true' do
expect(subject.render?).to eq true
end
it 'does not contain any menu item' do
expect(subject.renderable_items).to be_empty
end
end
end
end
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