Commit 46614d75 authored by Nick Thomas's avatar Nick Thomas

Merge branch '7287-epic-references' into 'master'

Support short reference to epics from project entities

Closes #7287

See merge request gitlab-org/gitlab-ee!7475
parents 1afc21c9 78347c0e
...@@ -42,7 +42,7 @@ discussions, and descriptions: ...@@ -42,7 +42,7 @@ discussions, and descriptions:
| `/remove_due_date` | Remove due date | ✓ | | | `/remove_due_date` | Remove due date | ✓ | |
| `/weight 0,1,2, ...` | Set weight **[STARTER]** | ✓ | | | `/weight 0,1,2, ...` | Set weight **[STARTER]** | ✓ | |
| `/clear_weight` | Clears weight **[STARTER]** | ✓ | | | `/clear_weight` | Clears weight **[STARTER]** | ✓ | |
| `/epic <group&epic &#124; Epic URL>` | Add to epic **[ULTIMATE]** | ✓ | | | `/epic <&epic &#124; group&epic &#124; Epic URL>` | Add to epic **[ULTIMATE]** | ✓ | |
| `/remove_epic` | Removes from epic **[ULTIMATE]** | ✓ | | | `/remove_epic` | Removes from epic **[ULTIMATE]** | ✓ | |
| `/confidential` | Make confidential | ✓ | | | `/confidential` | Make confidential | ✓ | |
| `/duplicate #issue` | Mark this issue as a duplicate of another issue | ✓ | | `/duplicate #issue` | Mark this issue as a duplicate of another issue | ✓ |
......
...@@ -194,7 +194,7 @@ module EE ...@@ -194,7 +194,7 @@ module EE
def to_reference(from = nil, full: false) def to_reference(from = nil, full: false)
reference = "#{self.class.reference_prefix}#{iid}" reference = "#{self.class.reference_prefix}#{iid}"
return reference unless cross_reference?(from) || full return reference unless (cross_reference?(from) && !group.projects.include?(from)) || full
"#{group.full_path}#{reference}" "#{group.full_path}#{reference}"
end end
......
...@@ -55,7 +55,7 @@ module EE ...@@ -55,7 +55,7 @@ module EE
issuable.project.group&.feature_available?(:epics) && issuable.project.group&.feature_available?(:epics) &&
current_user.can?(:"admin_#{issuable.to_ability_name}", issuable) current_user.can?(:"admin_#{issuable.to_ability_name}", issuable)
end end
params '<group&epic | Epic URL>' params '<&epic | group&epic | Epic URL>'
command :epic do |epic_param| command :epic do |epic_param|
@updates[:epic] = extract_epic(epic_param) @updates[:epic] = extract_epic(epic_param)
end end
......
---
title: Support short reference to epics from project entities
merge_request: 7475
author:
type: changed
...@@ -6,31 +6,50 @@ describe 'Referencing Epics', :js do ...@@ -6,31 +6,50 @@ describe 'Referencing Epics', :js do
let(:epic) { create(:epic, group: group) } let(:epic) { create(:epic, group: group) }
let(:project) { create(:project, :public) } let(:project) { create(:project, :public) }
let(:reference) { epic.to_reference(full: true) } let(:full_reference) { epic.to_reference(full: true) }
context 'reference on an issue' do context 'reference on an issue' do
let(:issue) { create(:issue, project: project, description: "Check #{reference}") }
before do before do
stub_licensed_features(epics: true) stub_licensed_features(epics: true)
sign_in(user) sign_in(user)
end end
context 'when referencing epics from the direct parent' do
let(:epic2) { create(:epic, group: group) }
let(:short_reference) { epic2.to_reference }
let(:text) { "Check #{full_reference} #{short_reference}" }
let(:child_project) { create(:project, :public, group: group) }
let(:issue) { create(:issue, project: child_project, description: text) }
it 'displays link to the reference' do
visit project_issue_path(child_project, issue)
page.within('.issuable-details .description') do
expect(page).to have_link(epic.to_reference, href: group_epic_path(group, epic))
expect(page).to have_link(short_reference, href: group_epic_path(group, epic2))
end
end
end
context 'when referencing an epic from another group' do
let(:text) { "Check #{full_reference}" }
let(:issue) { create(:issue, project: project, description: text) }
context 'when non group member displays the issue' do context 'when non group member displays the issue' do
context 'when referenced epic is in a public group' do context 'when referenced epic is in a public group' do
it 'displays link to the reference' do it 'displays link to the reference' do
visit project_issue_path(project, issue) visit project_issue_path(project, issue)
page.within('.issuable-details .description') do page.within('.issuable-details .description') do
expect(page).to have_link(reference, href: group_epic_path(group, epic)) expect(page).to have_link(full_reference, href: group_epic_path(group, epic))
end end
end end
end end
context 'when referenced epic is in a private group' do context 'when referenced epic is in a private group' do
before do before do
group.update_attribute(:visibility_level, Gitlab::VisibilityLevel::PRIVATE) group.update!(visibility_level: Gitlab::VisibilityLevel::PRIVATE)
end end
it 'does not display link to the reference' do it 'does not display link to the reference' do
...@@ -47,14 +66,15 @@ describe 'Referencing Epics', :js do ...@@ -47,14 +66,15 @@ describe 'Referencing Epics', :js do
context 'when referenced epic is in a private group' do context 'when referenced epic is in a private group' do
before do before do
group.add_developer(user) group.add_developer(user)
group.update_attribute(:visibility_level, Gitlab::VisibilityLevel::PRIVATE) group.update!(visibility_level: Gitlab::VisibilityLevel::PRIVATE)
end end
it 'displays link to the reference' do it 'displays link to the reference' do
visit project_issue_path(project, issue) visit project_issue_path(project, issue)
page.within('.issuable-details .description') do page.within('.issuable-details .description') do
expect(page).to have_link(reference, href: group_epic_path(group, epic)) expect(page).to have_link(full_reference, href: group_epic_path(group, epic))
end
end end
end end
end end
......
...@@ -470,6 +470,10 @@ describe Epic do ...@@ -470,6 +470,10 @@ describe Epic do
describe '#to_reference' do describe '#to_reference' do
let(:group) { create(:group, path: 'group-a') } let(:group) { create(:group, path: 'group-a') }
let(:subgroup) { create(:group) }
let(:group_project) { create(:project, group: group) }
let(:subgroup_project) { create(:project, group: subgroup) }
let(:other_project) { create(:project) }
let(:epic) { create(:epic, iid: 1, group: group) } let(:epic) { create(:epic, iid: 1, group: group) }
context 'when nil argument' do context 'when nil argument' do
...@@ -478,23 +482,42 @@ describe Epic do ...@@ -478,23 +482,42 @@ describe Epic do
end end
end end
context 'when group argument equals epic group' do context 'when from argument equals epic group' do
it 'returns epic id' do it 'returns epic id' do
expect(epic.to_reference(epic.group)).to eq('&1') expect(epic.to_reference(epic.group)).to eq('&1')
end end
end end
context 'when group argument differs from epic group' do context 'when from argument is a group different from epic group' do
it 'returns complete path to the epic' do it 'returns complete path to the epic' do
expect(epic.to_reference(create(:group))).to eq('group-a&1') expect(epic.to_reference(create(:group))).to eq('group-a&1')
end end
end end
context 'when from argument is a project under the epic group' do
it 'returns epic id' do
expect(epic.to_reference(group_project)).to eq('&1')
end
end
context 'when from argument is a project under the epic subgroup' do
it 'returns complete path to the epic' do
expect(epic.to_reference(subgroup_project)).to eq('group-a&1')
end
end
context 'when from argument is a project in another group' do
it 'returns complete path to the epic' do
expect(epic.to_reference(other_project)).to eq('group-a&1')
end
end
context 'when full is true' do context 'when full is true' do
it 'returns complete path to the epic' do it 'returns complete path to the epic' do
expect(epic.to_reference(full: true)).to eq('group-a&1') expect(epic.to_reference(full: true)).to eq('group-a&1')
expect(epic.to_reference(epic.group, full: true)).to eq('group-a&1') expect(epic.to_reference(epic.group, full: true)).to eq('group-a&1')
expect(epic.to_reference(group, full: true)).to eq('group-a&1') expect(epic.to_reference(group, full: true)).to eq('group-a&1')
expect(epic.to_reference(group_project, full: true)).to eq('group-a&1')
end end
end end
end end
......
...@@ -11,6 +11,12 @@ module Banzai ...@@ -11,6 +11,12 @@ module Banzai
def self.object_class def self.object_class
Epic Epic
end end
private
def group
context[:group] || context[:project]&.group
end
end end
end end
end end
...@@ -331,11 +331,12 @@ describe CacheMarkdownField do ...@@ -331,11 +331,12 @@ describe CacheMarkdownField do
end end
context 'with a project' do context 'with a project' do
let(:thing) { thing_subclass(:project).new(foo: markdown, foo_html: html, project: :project_value) } let(:project) { create(:project, group: create(:group)) }
let(:thing) { thing_subclass(:project).new(foo: markdown, foo_html: html, project: project) }
it 'sets the project in the context' do it 'sets the project in the context' do
is_expected.to have_key(:project) is_expected.to have_key(:project)
expect(context[:project]).to eq(:project_value) expect(context[:project]).to eq(project)
end end
it 'invalidates the cache when project changes' do it 'invalidates the cache when project changes' 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