Skip to content

Commit

Permalink
Merge pull request #16950 from opf/fix/version-copy-board
Browse files Browse the repository at this point in the history
Fix copying a version column board
  • Loading branch information
cbliard authored Oct 15, 2024
2 parents dcc5d00 + 15dbd79 commit 4ca5eca
Show file tree
Hide file tree
Showing 7 changed files with 142 additions and 27 deletions.
8 changes: 4 additions & 4 deletions app/services/grids/copy/widgets_dependent_service.rb
Original file line number Diff line number Diff line change
Expand Up @@ -108,11 +108,11 @@ def map_query_id(query_id, params)
end

def map_query_filters(filters, _params)
::Queries::Copy::FiltersMapper
.new(state, filters)
.map_filters!
result = ::Queries::Copy::FiltersMapper
.new(state)
.map_filters(filters)

ServiceResult.success result: filters
ServiceResult.success(result:)
end

def duplicate_query(query_id, params)
Expand Down
32 changes: 16 additions & 16 deletions app/services/queries/copy/filters_mapper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -28,26 +28,28 @@

module Queries::Copy
class FiltersMapper
attr_reader :state, :filters, :mappers
attr_reader :state, :mappers

def initialize(state, filters)
def initialize(state)
@state = state
@filters = filters
@mappers = build_filter_mappers
end

##
# Returns the mapped filter array for either
# hash-based APIv3 filters or filter clasess
def map_filters!
# Returns the mapped filter array for
# an array of hash-based APIv3 filters
def map_filters(filters)
filters.map do |input|
if input.is_a?(Hash)
filter = input.dup.with_indifferent_access
filter.tap(&method(:map_api_filter_hash))
else
map_filter_class(input)
input
end
filter = input.dup.with_indifferent_access
map_api_filter_hash(filter)
end
end

##
# Maps the given query instance
def map_query!(query)
query.filters.each do |filter|
filter.values = mapped_values(filter.name, filter.values)
end
end

Expand All @@ -63,10 +65,8 @@ def map_api_filter_hash(filter)
ar_name = ::API::Utilities::QueryFiltersNameConverter.to_ar_name(name, refer_to_ids: true)

subhash["values"] = mapped_values(ar_name, subhash["values"])
end

def map_filter_class(filter)
filter.values = mapped_values(filter.name, filter.values)
filter
end

def mapped_values(ar_name, values)
Expand Down
4 changes: 2 additions & 2 deletions app/services/queries/copy_service.rb
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,8 @@ def set_attributes(_params)
new_query.sort_criteria = source.sort_criteria if source.sort_criteria

::Queries::Copy::FiltersMapper
.new(state, new_query.filters)
.map_filters!
.new(state)
.map_query!(new_query)

ServiceResult.new(success: new_query.valid?, result: new_query)
end
Expand Down
19 changes: 17 additions & 2 deletions modules/boards/app/services/boards/copy_service.rb
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,23 @@ class CopyService < ::Grids::CopyService
protected

def set_attributes_params(params)
super
.merge(project: state.project || model.project)
super.deep_symbolize_keys.tap do |hash|
hash[:project] = state.project || model.project

hash[:options] = mapped_options(hash[:options]) if hash.key?(:options)
end
end

def mapped_options(options)
options[:filters] = mapped_filters(options[:filters]) if options.key?(:filters)

options
end

def mapped_filters(filters)
::Queries::Copy::FiltersMapper
.new(state)
.map_filters(filters)
end
end
end
34 changes: 34 additions & 0 deletions modules/boards/spec/factories/board_factory.rb
Original file line number Diff line number Diff line change
Expand Up @@ -100,4 +100,38 @@
board.save!
end
end

factory :version_board, class: "Boards::Grid" do
project
name { "My version board" }
row_count { 1 }
column_count { 4 }

transient do
version_columns { [create(:version, project:)] }
end

callback(:after_create) do |board, evaluator|
evaluator.version_columns.each do |version|
query = build(:public_query, name: version.name, project: board.project).tap do |q|
q.sort_criteria = [[:manual_sorting, "asc"]]
q.save!
end

filters = [{ "version_id" => { "operator" => "=", "values" => [version.id.to_s] } }]

board.widgets << create(:grid_widget,
identifier: "work_package_query",
start_row: 1,
end_row: 2,
start_column: 1,
end_column: 1,
options: { "queryId" => query.id,
"filters" => filters })
end

board.options = { "type" => "action", "attribute" => "version" }
board.save!
end
end
end
62 changes: 62 additions & 0 deletions modules/boards/spec/services/copy_service_integration_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,68 @@
end
end

describe "for a version board" do
let(:current_user) do
create(:user, member_with_roles: { source => role })
end
let!(:version) { create(:version, project: source) }
let!(:board_view) do
create(:version_board, project: source, version_columns: [version])
end
let(:only_args) { %w[work_packages boards versions] }

before do
login_as current_user
end

it "succeeds to copy the version column" do
expect(subject).to be_success
expect(board_copies.count).to eq 1

expect(board_view.widgets.count).to eq(1)
expect(board_copy.widgets.count).to eq(1)

widget_source = board_view.widgets.first.options
widget_copy = board_copy.widgets.first.options

filter_source = widget_source["filters"].first["version_id"]
filter_copy = widget_copy["filters"].first["version_id"]

expect(widget_source["queryId"]).not_to eq(widget_copy["queryId"])
expect(filter_source["values"]).to eq [version.id.to_s]

copied_version = project_copy.versions.first
expect(filter_copy["values"]).to eq [copied_version.id.to_s]
end
end

describe "for a board filtered by version" do
let(:current_user) do
create(:user, member_with_roles: { source => role })
end
let!(:version) { create(:version, project: source) }
let!(:board_view) do
create(:board_grid, project: source)
end
let(:only_args) { %w[work_packages boards versions] }

before do
board_view.update! options: {
filters: [{ version: { operator: "=", values: [version.id.to_s] } }]
}
login_as current_user
end

it "maps the filters in the board options" do
expect(subject).to be_success
expect(board_copies.count).to eq 1

version_filter = board_copy.options[:filters].first[:version]
copied_version = project_copy.versions.first
expect(version_filter[:values]).to eq [copied_version.id.to_s]
end
end

describe "for ordered work packages" do
let!(:board_view) { create(:board_grid_with_query, project: source, name: "My Board") }
let!(:wp_1) { create(:work_package, project: source, subject: "Second") }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,8 @@

RSpec.describe Queries::Copy::FiltersMapper do
let(:state) { Shared::ServiceState.new }
let(:instance) { described_class.new(state, filters) }
let(:instance) { described_class.new(state) }

subject { instance.map_filters! }

describe "with a query filters array" do
let(:query) do
Expand All @@ -43,7 +42,8 @@

query
end
let(:filters) { query.filters }

subject { instance.map_query!(query) }

context "when mapping state exists" do
before do
Expand Down Expand Up @@ -77,6 +77,8 @@
]
end

subject { instance.map_filters(filters) }

context "when mapping state exists" do
before do
state.work_package_id_lookup = { 1 => 11 }
Expand Down Expand Up @@ -107,6 +109,8 @@
]
end

subject { instance.map_filters(filters) }

context "when mapping state exists" do
before do
state.work_package_id_lookup = { 1 => 11 }
Expand Down

0 comments on commit 4ca5eca

Please sign in to comment.