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
# 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.
> - 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,
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
To create a requirement:
1. In a project, go to **Requirements**.
1. In a project, go to **Issues > Requirements**.
1. Select **New 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
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 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.
......@@ -222,7 +226,7 @@ Before you import your file:
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
top right.
- 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
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}**).
A confirmation modal appears.
......
......@@ -12,6 +12,7 @@ module EE
return false unless super
add_item(iterations_menu_item)
add_item(requirements_menu_item)
true
end
......@@ -34,6 +35,20 @@ module EE
item_id: :iterations
)
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
......
......@@ -13,8 +13,6 @@ module EE
if jira_menu.render?
replace_menu(::Sidebars::Projects::Menus::ExternalIssueTrackerMenu, jira_menu)
end
insert_menu_after(::Sidebars::Projects::Menus::MergeRequestsMenu, ::Sidebars::Projects::Menus::RequirementsMenu.new(context))
end
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
it_behaves_like 'verified navigation bar'
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
......@@ -41,7 +41,7 @@ RSpec.describe 'Requirements list', :js do
end
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
it 'shows requirements tabs for each status type' do
......
......@@ -38,4 +38,36 @@ RSpec.describe Sidebars::Projects::Menus::IssuesMenu do
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
# 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