diff options
-rw-r--r-- | app/controllers/boards/issues_controller.rb | 16 | ||||
-rw-r--r-- | app/models/issue.rb | 14 | ||||
-rw-r--r-- | app/serializers/README.md | 4 | ||||
-rw-r--r-- | app/serializers/issue_board_entity.rb | 51 | ||||
-rw-r--r-- | app/serializers/issue_serializer.rb | 6 | ||||
-rw-r--r-- | app/serializers/label_entity.rb | 4 | ||||
-rw-r--r-- | spec/controllers/boards/issues_controller_spec.rb | 6 | ||||
-rw-r--r-- | spec/fixtures/api/schemas/entities/issue_board.json | 38 | ||||
-rw-r--r-- | spec/fixtures/api/schemas/entities/issue_boards.json | 15 | ||||
-rw-r--r-- | spec/models/concerns/awardable_spec.rb | 4 | ||||
-rw-r--r-- | spec/serializers/issue_board_entity_spec.rb | 23 | ||||
-rw-r--r-- | spec/serializers/issue_serializer_spec.rb | 8 |
12 files changed, 155 insertions, 34 deletions
diff --git a/app/controllers/boards/issues_controller.rb b/app/controllers/boards/issues_controller.rb index 7f874687212..0dd7500623d 100644 --- a/app/controllers/boards/issues_controller.rb +++ b/app/controllers/boards/issues_controller.rb @@ -100,18 +100,12 @@ module Boards .merge(board_id: params[:board_id], list_id: params[:list_id], request: request) end + def serializer + IssueSerializer.new(current_user: current_user) + end + def serialize_as_json(resource) - resource.as_json( - only: [:id, :iid, :project_id, :title, :confidential, :due_date, :relative_position, :weight], - labels: true, - issue_endpoints: true, - include_full_project_path: board.group_board?, - include: { - project: { only: [:id, :path] }, - assignees: { only: [:id, :name, :username], methods: [:avatar_url] }, - milestone: { only: [:id, :title] } - } - ) + serializer.represent(resource, serializer: 'board', include_full_project_path: board.group_board?) end def whitelist_query_limiting diff --git a/app/models/issue.rb b/app/models/issue.rb index 0de5e434b02..abdb3448d4e 100644 --- a/app/models/issue.rb +++ b/app/models/issue.rb @@ -231,20 +231,6 @@ class Issue < ActiveRecord::Base def as_json(options = {}) super(options).tap do |json| - if options.key?(:issue_endpoints) && project - url_helper = Gitlab::Routing.url_helpers - - issue_reference = options[:include_full_project_path] ? to_reference(full: true) : to_reference - - json.merge!( - reference_path: issue_reference, - real_path: url_helper.project_issue_path(project, self), - issue_sidebar_endpoint: url_helper.project_issue_path(project, self, format: :json, serializer: 'sidebar'), - toggle_subscription_endpoint: url_helper.toggle_subscription_project_issue_path(project, self), - assignable_labels_endpoint: url_helper.project_labels_path(project, format: :json, include_ancestor_groups: true) - ) - end - if options.key?(:labels) json[:labels] = labels.as_json( project: project, diff --git a/app/serializers/README.md b/app/serializers/README.md index 0337f88db5f..bb94745b0b5 100644 --- a/app/serializers/README.md +++ b/app/serializers/README.md @@ -180,7 +180,7 @@ def index render json: MyResourceSerializer .new(current_user: @current_user) .represent_details(@project.resources) - nd + end end ``` @@ -196,7 +196,7 @@ def index .represent_details(@project.resources), count: @project.resources.count } - nd + end end ``` diff --git a/app/serializers/issue_board_entity.rb b/app/serializers/issue_board_entity.rb new file mode 100644 index 00000000000..6a9e9638e70 --- /dev/null +++ b/app/serializers/issue_board_entity.rb @@ -0,0 +1,51 @@ +# frozen_string_literal: true + +class IssueBoardEntity < Grape::Entity + include RequestAwareEntity + + expose :id + expose :iid + expose :title + + expose :confidential + expose :due_date + expose :project_id + expose :relative_position + expose :weight, if: -> (*) { respond_to?(:weight) } + + expose :project do |issue| + API::Entities::Project.represent issue.project, only: [:id, :path] + end + + expose :milestone, expose_nil: false do |issue| + API::Entities::Project.represent issue.milestone, only: [:id, :title] + end + + expose :assignees do |issue| + API::Entities::UserBasic.represent issue.assignees, only: [:id, :name, :username, :avatar_url] + end + + expose :labels do |issue| + LabelEntity.represent issue.labels, project: issue.project, only: [:id, :title, :description, :color, :priority, :text_color] + end + + expose :reference_path, if: -> (issue) { issue.project } do |issue, options| + options[:include_full_project_path] ? issue.to_reference(full: true) : issue.to_reference + end + + expose :real_path, if: -> (issue) { issue.project } do |issue| + project_issue_path(issue.project, issue) + end + + expose :issue_sidebar_endpoint, if: -> (issue) { issue.project } do |issue| + project_issue_path(issue.project, issue, format: :json, serializer: 'sidebar') + end + + expose :toggle_subscription_endpoint, if: -> (issue) { issue.project } do |issue| + toggle_subscription_project_issue_path(issue.project, issue) + end + + expose :assignable_labels_endpoint, if: -> (issue) { issue.project } do |issue| + project_labels_path(issue.project, format: :json, include_ancestor_groups: true) + end +end diff --git a/app/serializers/issue_serializer.rb b/app/serializers/issue_serializer.rb index 37cf5e28396..d66f0a5acb7 100644 --- a/app/serializers/issue_serializer.rb +++ b/app/serializers/issue_serializer.rb @@ -4,15 +4,17 @@ class IssueSerializer < BaseSerializer # This overrided method takes care of which entity should be used # to serialize the `issue` based on `basic` key in `opts` param. # Hence, `entity` doesn't need to be declared on the class scope. - def represent(merge_request, opts = {}) + def represent(issue, opts = {}) entity = case opts[:serializer] when 'sidebar' IssueSidebarEntity + when 'board' + IssueBoardEntity else IssueEntity end - super(merge_request, opts, entity) + super(issue, opts, entity) end end diff --git a/app/serializers/label_entity.rb b/app/serializers/label_entity.rb index 98743d62b50..5082245dda9 100644 --- a/app/serializers/label_entity.rb +++ b/app/serializers/label_entity.rb @@ -12,4 +12,8 @@ class LabelEntity < Grape::Entity expose :text_color expose :created_at expose :updated_at + + expose :priority, if: -> (*) { options.key?(:project) } do |label| + label.priority(options[:project]) + end end diff --git a/spec/controllers/boards/issues_controller_spec.rb b/spec/controllers/boards/issues_controller_spec.rb index 98946e4287b..6d0483f0032 100644 --- a/spec/controllers/boards/issues_controller_spec.rb +++ b/spec/controllers/boards/issues_controller_spec.rb @@ -50,7 +50,7 @@ describe Boards::IssuesController do parsed_response = JSON.parse(response.body) - expect(response).to match_response_schema('issues') + expect(response).to match_response_schema('entities/issue_boards') expect(parsed_response['issues'].length).to eq 2 expect(development.issues.map(&:relative_position)).not_to include(nil) end @@ -121,7 +121,7 @@ describe Boards::IssuesController do parsed_response = JSON.parse(response.body) - expect(response).to match_response_schema('issues') + expect(response).to match_response_schema('entities/issue_boards') expect(parsed_response['issues'].length).to eq 2 end end @@ -168,7 +168,7 @@ describe Boards::IssuesController do it 'returns the created issue' do create_issue user: user, board: board, list: list1, title: 'New issue' - expect(response).to match_response_schema('issue') + expect(response).to match_response_schema('entities/issue_board') end end diff --git a/spec/fixtures/api/schemas/entities/issue_board.json b/spec/fixtures/api/schemas/entities/issue_board.json new file mode 100644 index 00000000000..8d821ebb843 --- /dev/null +++ b/spec/fixtures/api/schemas/entities/issue_board.json @@ -0,0 +1,38 @@ +{ + "type": "object", + "properties" : { + "id": { "type": "integer" }, + "iid": { "type": "integer" }, + "title": { "type": "string" }, + "confidential": { "type": "boolean" }, + "due_date": { "type": "date" }, + "project_id": { "type": "integer" }, + "relative_position": { "type": ["integer", "null"] }, + "weight": { "type": "integer" }, + "project": { + "type": "object", + "properties": { + "id": { "type": "integer" }, + "path": { "type": "string" } + } + }, + "milestone": { + "type": "object", + "properties": { + "id": { "type": "integer" }, + "title": { "type": "string" } + } + }, + "assignees": { "type": ["array", "null"] }, + "labels": { + "type": "array", + "items": { "$ref": "label.json" } + }, + "reference_path": { "type": "string" }, + "real_path": { "type": "string" }, + "issue_sidebar_endpoint": { "type": "string" }, + "toggle_subscription_endpoint": { "type": "string" }, + "assignable_labels_endpoint": { "type": "string" } + }, + "additionalProperties": false +} diff --git a/spec/fixtures/api/schemas/entities/issue_boards.json b/spec/fixtures/api/schemas/entities/issue_boards.json new file mode 100644 index 00000000000..0ac1d9468c8 --- /dev/null +++ b/spec/fixtures/api/schemas/entities/issue_boards.json @@ -0,0 +1,15 @@ +{ + "type": "object", + "required" : [ + "issues", + "size" + ], + "properties" : { + "issues": { + "type": "array", + "items": { "$ref": "issue_board.json" } + }, + "size": { "type": "integer" } + }, + "additionalProperties": false +} diff --git a/spec/models/concerns/awardable_spec.rb b/spec/models/concerns/awardable_spec.rb index debc02fa51f..5713106418d 100644 --- a/spec/models/concerns/awardable_spec.rb +++ b/spec/models/concerns/awardable_spec.rb @@ -37,8 +37,8 @@ describe Awardable do create(:award_emoji, awardable: issue3, name: "star", user: award_emoji.user) create(:award_emoji, awardable: issue3, name: "star", user: award_emoji2.user) - expect(Issue.awarded(award_emoji.user)).to eq [issue, issue3] - expect(Issue.awarded(award_emoji2.user)).to eq [issue2, issue3] + expect(Issue.awarded(award_emoji.user)).to contain_exactly(issue, issue3) + expect(Issue.awarded(award_emoji2.user)).to contain_exactly(issue2, issue3) end end diff --git a/spec/serializers/issue_board_entity_spec.rb b/spec/serializers/issue_board_entity_spec.rb new file mode 100644 index 00000000000..06d9d3657e6 --- /dev/null +++ b/spec/serializers/issue_board_entity_spec.rb @@ -0,0 +1,23 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe IssueBoardEntity do + let(:project) { create(:project) } + let(:resource) { create(:issue, project: project) } + let(:user) { create(:user) } + + let(:request) { double('request', current_user: user) } + + subject { described_class.new(resource, request: request).as_json } + + it 'has basic attributes' do + expect(subject).to include(:id, :iid, :title, :confidential, :due_date, :project_id, :relative_position, + :project, :labels) + end + + it 'has path and endpoints' do + expect(subject).to include(:reference_path, :real_path, :issue_sidebar_endpoint, + :toggle_subscription_endpoint, :assignable_labels_endpoint) + end +end diff --git a/spec/serializers/issue_serializer_spec.rb b/spec/serializers/issue_serializer_spec.rb index 75578816e75..e8c46c0cdee 100644 --- a/spec/serializers/issue_serializer_spec.rb +++ b/spec/serializers/issue_serializer_spec.rb @@ -24,4 +24,12 @@ describe IssueSerializer do expect(json_entity).to match_schema('entities/issue_sidebar') end end + + context 'board issue serialization' do + let(:serializer) { 'board' } + + it 'matches board issue json schema' do + expect(json_entity).to match_schema('entities/issue_board') + end + end end |