Commit 78347c0e authored by Jarka Košanová's avatar Jarka Košanová

Support short reference to group entities from project entities

- add a direct project parent (group) to Banzai context
- if an epic is referenced from a direct descendant
  -> change epic to_reference to use short reference
parent b70a646f
# GitLab quick actions
Quick actions are textual shortcuts for common actions on issues, epics, merge requests,
Quick actions are textual shortcuts for common actions on issues, epics, merge requests,
and commits that are usually done by clicking buttons or dropdowns in GitLab's UI.
You can enter these commands while creating a new issue or merge request, or
in comments of issues, epics, merge requests, and commits. Each command should be
in comments of issues, epics, merge requests, and commits. Each command should be
on a separate line in order to be properly detected and executed. Once executed,
the commands are removed from the text body and not visible to anyone else.
......@@ -42,7 +42,7 @@ discussions, and descriptions:
| `/remove_due_date` | Remove due date | ✓ | |
| `/weight 0,1,2, ...` | Set 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]** | ✓ | |
| `/confidential` | Make confidential | ✓ | |
| `/duplicate #issue` | Mark this issue as a duplicate of another issue | ✓ |
......@@ -68,7 +68,7 @@ The following quick actions are applicable for epics threads and description:
|:---------------------------|:----------------------------------------|
| `/tableflip <Comment>` | Append the comment with `(╯°□°)╯︵ ┻━┻` |
| `/shrug <Comment>` | Append the comment with `¯\_(ツ)_/¯` |
| `/todo` | Add a todo |
| `/todo` | Add a todo |
| `/done` | Mark todo as done |
| `/subscribe` | Subscribe |
| `/unsubscribe` | Unsubscribe |
......@@ -78,4 +78,4 @@ The following quick actions are applicable for epics threads and description:
| `/award :emoji:` | Toggle emoji award |
| `/label ~label1 ~label2` | Add label(s) |
| `/unlabel ~label1 ~label2` | Remove all or specific label(s) |
| `/relabel ~label1 ~label2` | Replace label |
\ No newline at end of file
| `/relabel ~label1 ~label2` | Replace label |
......@@ -194,7 +194,7 @@ module EE
def to_reference(from = nil, full: false)
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}"
end
......
......@@ -55,7 +55,7 @@ module EE
issuable.project.group&.feature_available?(:epics) &&
current_user.can?(:"admin_#{issuable.to_ability_name}", issuable)
end
params '<group&epic | Epic URL>'
params '<&epic | group&epic | Epic URL>'
command :epic do |epic_param|
@updates[:epic] = extract_epic(epic_param)
end
......
---
title: Support short reference to epics from project entities
merge_request: 7475
author:
type: changed
......@@ -6,55 +6,75 @@ describe 'Referencing Epics', :js do
let(:epic) { create(:epic, group: group) }
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
let(:issue) { create(:issue, project: project, description: "Check #{reference}") }
before do
stub_licensed_features(epics: true)
sign_in(user)
end
context 'when non group member displays the issue' do
context 'when referenced epic is in a public group' do
it 'displays link to the reference' do
visit project_issue_path(project, issue)
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) }
page.within('.issuable-details .description') do
expect(page).to have_link(reference, href: group_epic_path(group, epic))
end
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 referenced epic is in a private group' do
before do
group.update_attribute(:visibility_level, Gitlab::VisibilityLevel::PRIVATE)
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 referenced epic is in a public group' do
it 'displays link to the reference' do
visit project_issue_path(project, issue)
page.within('.issuable-details .description') do
expect(page).to have_link(full_reference, href: group_epic_path(group, epic))
end
end
end
it 'does not display link to the reference' do
visit project_issue_path(project, issue)
context 'when referenced epic is in a private group' do
before do
group.update!(visibility_level: Gitlab::VisibilityLevel::PRIVATE)
end
it 'does not display link to the reference' do
visit project_issue_path(project, issue)
page.within('.issuable-details .description') do
expect(page).not_to have_link
page.within('.issuable-details .description') do
expect(page).not_to have_link
end
end
end
end
end
context 'when a group member displays the issue' do
context 'when referenced epic is in a private group' do
before do
group.add_developer(user)
group.update_attribute(:visibility_level, Gitlab::VisibilityLevel::PRIVATE)
end
context 'when a group member displays the issue' do
context 'when referenced epic is in a private group' do
before do
group.add_developer(user)
group.update!(visibility_level: Gitlab::VisibilityLevel::PRIVATE)
end
it 'displays link to the reference' do
visit project_issue_path(project, issue)
it 'displays link to the reference' do
visit project_issue_path(project, issue)
page.within('.issuable-details .description') do
expect(page).to have_link(reference, href: group_epic_path(group, epic))
page.within('.issuable-details .description') do
expect(page).to have_link(full_reference, href: group_epic_path(group, epic))
end
end
end
end
......
......@@ -470,6 +470,10 @@ describe Epic do
describe '#to_reference' do
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) }
context 'when nil argument' do
......@@ -478,23 +482,42 @@ describe Epic do
end
end
context 'when group argument equals epic group' do
context 'when from argument equals epic group' do
it 'returns epic id' do
expect(epic.to_reference(epic.group)).to eq('&1')
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
expect(epic.to_reference(create(:group))).to eq('group-a&1')
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
it 'returns complete path to the epic' do
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(group, full: true)).to eq('group-a&1')
expect(epic.to_reference(group_project, full: true)).to eq('group-a&1')
end
end
end
......
......@@ -11,6 +11,12 @@ module Banzai
def self.object_class
Epic
end
private
def group
context[:group] || context[:project]&.group
end
end
end
end
......@@ -331,11 +331,12 @@ describe CacheMarkdownField do
end
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
is_expected.to have_key(:project)
expect(context[:project]).to eq(:project_value)
expect(context[:project]).to eq(project)
end
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