Commit 45762399 authored by Jan Provaznik's avatar Jan Provaznik

Expose `blocked` attribute for board issues

Exposes an additional boolean `blocked` attribute for each issue,
but only if the issue is blocked by an issue visible to a user.
parent 7465e2d1
...@@ -27,17 +27,7 @@ module Boards ...@@ -27,17 +27,7 @@ module Boards
issues = list_service.execute issues = list_service.execute
issues = issues.page(params[:page]).per(params[:per] || 20).without_count issues = issues.page(params[:page]).per(params[:per] || 20).without_count
Issue.move_nulls_to_end(issues) if Gitlab::Database.read_write? Issue.move_nulls_to_end(issues) if Gitlab::Database.read_write?
issues = issues.preload(:milestone, issues = issues.preload(associations_to_preload)
:assignees,
project: [
:route,
{
namespace: [:route]
}
],
labels: [:priorities],
notes: [:award_emoji, :author]
)
render_issues(issues, list_service.metadata) render_issues(issues, list_service.metadata)
end end
...@@ -74,6 +64,21 @@ module Boards ...@@ -74,6 +64,21 @@ module Boards
private private
def associations_to_preload
[
:milestone,
:assignees,
project: [
:route,
{
namespace: [:route]
}
],
labels: [:priorities],
notes: [:award_emoji, :author]
]
end
def can_move_issues? def can_move_issues?
head(:forbidden) unless can?(current_user, :admin_issue, board) head(:forbidden) unless can?(current_user, :admin_issue, board)
end end
...@@ -139,3 +144,5 @@ module Boards ...@@ -139,3 +144,5 @@ module Boards
end end
end end
end end
Boards::IssuesController.prepend_if_ee('EE::Boards::IssuesController')
# frozen_string_literal: true
module EE
module Boards
module IssuesController
extend ::Gitlab::Utils::Override
override :associations_to_preload
def associations_to_preload
super << { target_issue_links: { source: { project: :project_feature } } }
end
end
end
end
...@@ -42,6 +42,8 @@ module EE ...@@ -42,6 +42,8 @@ module EE
has_many :vulnerability_links, class_name: 'Vulnerabilities::IssueLink', inverse_of: :issue has_many :vulnerability_links, class_name: 'Vulnerabilities::IssueLink', inverse_of: :issue
has_many :related_vulnerabilities, through: :vulnerability_links, source: :vulnerability has_many :related_vulnerabilities, through: :vulnerability_links, source: :vulnerability
has_many :target_issue_links, class_name: 'IssueLink', foreign_key: :target_id
validates :weight, allow_nil: true, numericality: { greater_than_or_equal_to: 0 } validates :weight, allow_nil: true, numericality: { greater_than_or_equal_to: 0 }
after_create :update_generic_alert_title, if: :generic_alert_with_default_title? after_create :update_generic_alert_title, if: :generic_alert_with_default_title?
......
...@@ -2,9 +2,13 @@ ...@@ -2,9 +2,13 @@
module EE module EE
module IssueBoardEntity module IssueBoardEntity
extend ActiveSupport::Concern extend ActiveSupport::Concern
include RequestAwareEntity
prepended do prepended do
expose :weight, if: ->(issue, _) { issue.supports_weight? } expose :weight, if: ->(issue, _) { issue.supports_weight? }
expose :blocked do |issue|
issue.target_issue_links.any? { |link| link.link_type == IssueLink::TYPE_BLOCKS && can?(request.current_user, :read_issue, link.source) }
end
end end
end end
end end
# frozen_string_literal: true
require 'spec_helper'
describe IssueBoardEntity do
let_it_be(:project) { create(:project) }
let_it_be(:issue) { create(:issue, project: project) }
let_it_be(:user) { create(:user) }
let(:request) { double('request', current_user: user) }
subject { described_class.new(issue.reload, request: request).as_json }
describe '#weight' do
it 'has `weight` attribute' do
expect(subject).to include(:weight)
end
context 'when project does not support issue weights' do
before do
stub_licensed_features(issue_weights: false)
end
it 'does not have `weight` attribute' do
expect(subject).not_to include(:weight)
end
end
end
describe '#blocked' do
it 'is not blocked by default' do
expect(subject[:blocked]).to be_falsey
end
context 'when the issue is referenced by other issue' do
let_it_be(:project2) { create(:project) }
let_it_be(:related_issue) { create(:issue, project: project2) }
context 'when the issue is blocking' do
let_it_be(:issue_link) { create(:issue_link, source: related_issue, target: issue, link_type: IssueLink::TYPE_BLOCKS) }
context 'when the referencing issue is not visible to the user' do
it 'is not blocked' do
expect(subject[:blocked]).to be_falsey
end
end
context 'when the referencing issue is visible to the user' do
before do
project2.add_developer(user)
end
it 'is blocked' do
expect(subject[:blocked]).to be_truthy
end
end
end
context 'when the issue is not blocking' do
let_it_be(:issue_link) { create(:issue_link, source: related_issue, target: issue, link_type: IssueLink::TYPE_RELATES_TO) }
before do
project2.add_developer(user)
end
it 'is not blocked' do
expect(subject[:blocked]).to be_falsey
end
end
end
end
end
...@@ -36,7 +36,8 @@ ...@@ -36,7 +36,8 @@
"real_path": { "type": "string" }, "real_path": { "type": "string" },
"issue_sidebar_endpoint": { "type": "string" }, "issue_sidebar_endpoint": { "type": "string" },
"toggle_subscription_endpoint": { "type": "string" }, "toggle_subscription_endpoint": { "type": "string" },
"assignable_labels_endpoint": { "type": "string" } "assignable_labels_endpoint": { "type": "string" },
"blocked": { "type": "boolean" }
}, },
"additionalProperties": false "additionalProperties": false
} }
...@@ -38,6 +38,7 @@ issues: ...@@ -38,6 +38,7 @@ issues:
- vulnerability_links - vulnerability_links
- related_vulnerabilities - related_vulnerabilities
- user_mentions - user_mentions
- target_issue_links
events: events:
- author - author
- project - project
......
...@@ -3,11 +3,11 @@ ...@@ -3,11 +3,11 @@
require 'spec_helper' require 'spec_helper'
describe IssueBoardEntity do describe IssueBoardEntity do
let(:project) { create(:project) } let_it_be(:project) { create(:project) }
let(:resource) { create(:issue, project: project) } let_it_be(:resource) { create(:issue, project: project) }
let(:user) { create(:user) } let_it_be(:user) { create(:user) }
let(:milestone) { create(:milestone, project: project) } let_it_be(:milestone) { create(:milestone, project: project) }
let(:label) { create(:label, project: project, title: 'Test Label') } let_it_be(:label) { create(:label, project: project, title: 'Test Label') }
let(:request) { double('request', current_user: user) } let(:request) { double('request', current_user: user) }
subject { described_class.new(resource, request: request).as_json } subject { described_class.new(resource, request: request).as_json }
......
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