Commit ce11d414 authored by Stan Hu's avatar Stan Hu

Merge branch '3861-use-serializers-for-project-group-boards' into 'master'

Use serializers for project / group boards

Closes #3861

See merge request gitlab-org/gitlab-ee!13052
parents a8fb6af4 2df13dc5
......@@ -35,6 +35,14 @@ module BoardsActions
boards.find(params[:id])
end
end
def serializer
BoardSerializer.new(current_user: current_user)
end
def serialize_as_json(resource)
serializer.represent(resource, serializer: 'board', include_full_project_path: board.group_board?)
end
end
BoardsActions.prepend(EE::BoardsActions)
......@@ -69,7 +69,7 @@ module BoardsResponses
end
def serialize_as_json(resource)
resource.as_json(only: [:id])
serializer.represent(resource).as_json
end
def respond_with(resource)
......@@ -80,6 +80,10 @@ module BoardsResponses
end
end
end
def serializer
BoardSerializer.new
end
end
BoardsResponses.prepend(EE::BoardsResponses)
# frozen_string_literal: true
class BoardSerializer < BaseSerializer
entity BoardSimpleEntity
end
# frozen_string_literal: true
class BoardSimpleEntity < Grape::Entity
expose :id
end
BoardSimpleEntity.prepend(EE::BoardSimpleEntity)
......@@ -12,15 +12,5 @@ module EE
def authorize_read_milestone
authorize_action_for!(board, :read_milestone)
end
override :serialize_as_json
def serialize_as_json(resource)
resource.as_json(
only: [:id, :name],
include: {
milestone: { only: [:id, :title] }
}
)
end
end
end
......@@ -43,17 +43,14 @@ module EE
parent.is_a?(Group) ? recent_group_boards_path(@group) : recent_project_boards_path(@project)
end
def current_board_json
def serializer
CurrentBoardSerializer.new
end
def current_board
board = @board || @boards.first
board.to_json(
only: [:id, :name, :milestone_id, :assignee_id, :weight, :label_ids],
include: {
milestone: { only: [:id, :title, :name] },
assignee: { only: [:id, :name, :username], methods: [:avatar_url] },
labels: { only: [:title, :color, :id] }
}
)
serializer.represent(board).as_json
end
override :boards_link_text
......
......@@ -46,19 +46,5 @@ module EE
super
end
end
def as_json(options = {})
milestone_attrs = options.fetch(:include, {})
.extract!(:milestone)
.dig(:milestone, :only)
super(options).tap do |json|
if milestone.present? && milestone_attrs.present?
json[:milestone] = milestone_attrs.each_with_object({}) do |attr, json|
json[attr] = milestone.public_send(attr) # rubocop:disable GitlabSecurity/PublicSend
end
end
end
end
end
end
# frozen_string_literal: true
class BoardAssigneeEntity < Grape::Entity
expose :id
expose :name
expose :username
expose :avatar_url
end
# frozen_string_literal: true
class BoardLabelEntity < Grape::Entity
expose :id
expose :color
expose :title
end
# frozen_string_literal: true
class BoardMilestoneEntity < Grape::Entity
expose :id
expose :title
expose :name
end
# frozen_string_literal: true
class CurrentBoardEntity < Grape::Entity
expose :id
expose :name
expose :milestone_id
expose :weight
expose :label_ids
expose :milestone, using: BoardMilestoneEntity
expose :assignee, using: BoardAssigneeEntity
expose :labels, using: BoardLabelEntity
end
# frozen_string_literal: true
class CurrentBoardSerializer < BaseSerializer
entity CurrentBoardEntity
end
# frozen_string_literal: true
module EE
module BoardSimpleEntity
extend ActiveSupport::Concern
prepended do
expose :name
expose :milestone, using: EE::MilestoneSimple, if: ->(board, _) { board&.milestone_id }
end
end
end
# frozen_string_literal: true
module EE
class MilestoneSimple < Grape::Entity
expose :id
expose :title
end
end
......@@ -2,7 +2,7 @@
- milestone_filter_opts = { format: :json }
- milestone_filter_opts = milestone_filter_opts.merge(only_group_milestones: true) if board.group_board?
#js-multiple-boards-switcher.inline.boards-switcher{ data: { current_board: current_board_json,
#js-multiple-boards-switcher.inline.boards-switcher{ data: { current_board: current_board.to_json,
milestone_path: milestones_filter_path(milestone_filter_opts),
board_base_url: board_base_url,
has_missing_boards: (!multiple_boards_available? && current_board_parent.boards.size > 1).to_s,
......
# frozen_string_literal: true
require 'spec_helper'
describe BoardsResponses do
let(:controller_class) do
Class.new do
include BoardsResponses
end
end
subject(:controller) { controller_class.new }
before do
stub_licensed_features(scoped_issue_board: true)
stub_licensed_features(multiple_project_issue_boards: true)
end
describe '#serialize_as_json' do
let!(:board) { create(:board, milestone: milestone) }
context 'with milestone' do
let(:milestone) { create(:milestone) }
before do
board.update_attribute(:milestone_id, milestone.id)
end
it 'serialises properly' do
expected = { id: board.id, name: board.name, milestone: { id: milestone.id, title: milestone.title } }.as_json
expect(subject.serialize_as_json(board)).to match(expected)
end
end
context 'without milestone' do
let(:milestone) { nil }
it 'serialises properly' do
expected = { id: board.id, name: board.name }.as_json
expect(subject.serialize_as_json(board)).to match(expected)
end
end
end
end
{
"type": "object",
"allOf": [
{
"required" : [
"title",
"color",
"id"
],
"properties": {
"id": { "type": "integer" },
"title": { "type": "string" },
"color": { "type": "string" }
}
}
]
}
{
"type": "array",
"items": { "$ref": "./board-label.json" }
}
{
"type": "object",
"allOf": [
{ "$ref": "board.json" },
{
"required" : [
"id",
"name"
],
"properties": {
"id": { "type": "integer" },
"name": { "type": "string" },
"milestone_id": { "type": ["integer", "null"] },
"weight": { "type": ["integer", "null"] },
"label_ids": { "type": "array" },
"assignee": {
"type": ["object", "null"],
"required": [
"id",
"name",
"username",
"avatar_url"
]
},
"labels": { "$ref": "board-labels.json" },
"milestone": {
"type": ["object", "null"],
"required": [
"id",
"title"
],
"properties": {
"id": { "type": "integer" },
"title": { "type": "string" }
}
}
}
}
]
}
......@@ -2,11 +2,12 @@
require 'spec_helper'
describe BoardsHelper do
let(:project) { create(:project) }
describe '#board_list_data' do
let(:results) { helper.board_list_data }
it 'contains an endpoint to get users list' do
project = create(:project)
board = create(:board, project: project)
assign(:board, board)
assign(:project, project)
......@@ -14,4 +15,26 @@ describe BoardsHelper do
expect(results).to include(list_assignees_path: "/-/boards/#{board.id}/users.json")
end
end
describe '#current_board' do
let(:board_json) { helper.current_board }
let(:user) { create(:user) }
let(:label1) { create(:label, name: "feijoa") }
let(:label2) { create(:label, name: "pineapple") }
let(:milestone) { create(:milestone) }
it 'serializes with child object attributes' do
board = create(:board, project: project, milestone: milestone, assignee: user, labels: [label1, label2])
assign(:board, board)
expect(board_json).to match_schema('current-board', dir: 'ee')
end
it 'can serialise with a basic set of attributes' do
board = create(:board, project: project)
assign(:board, board)
expect(board_json).to match_schema('current-board', dir: 'ee')
end
end
end
# frozen_string_literal: true
require 'spec_helper'
describe BoardSerializer do
let(:resource) { create(:board) }
let(:json_entity) do
described_class.new
.represent(resource, serializer: serializer)
.with_indifferent_access
end
context 'serialization' do
let(:serializer) { 'board' }
it 'matches current board json schema' do
expect(json_entity).to match_schema('board', dir: 'ee')
end
end
end
# frozen_string_literal: true
require 'spec_helper'
describe BoardsResponses do
let(:controller_class) do
Class.new do
include BoardsResponses
end
end
subject(:controller) { controller_class.new }
describe '#serialize_as_json' do
let!(:board) { create(:board) }
it 'serializes properly' do
expected = { "id" => board.id }
expect(subject.serialize_as_json(board)).to include(expected)
end
end
end
# frozen_string_literal: true
require 'spec_helper'
describe BoardSerializer do
let(:resource) { create(:board) }
let(:json_entity) do
described_class.new
.represent(resource, serializer: serializer)
.with_indifferent_access
end
context 'serialization' do
let(:serializer) { 'board' }
it 'matches issue_sidebar json schema' do
expect(json_entity).to match_schema('board')
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