Copy workflow to multiple types at once. wp/72383

This commit is contained in:
David F
2026-04-16 16:59:26 +02:00
parent 1d8f324dba
commit 8721ac9606
6 changed files with 48 additions and 50 deletions
@@ -36,7 +36,7 @@ class Workflows::Copies::FromTypesController < ApplicationController
before_action :require_admin
before_action :set_source_type
before_action :set_target_type
before_action :set_target_types
def create
if @source_type.nil?
@@ -45,18 +45,16 @@ class Workflows::Copies::FromTypesController < ApplicationController
scheme: :danger
)
@turbo_status = :unprocessable_entity
elsif @target_type.nil?
elsif @target_types.blank?
render_flash_message_via_turbo_stream(
message: I18n.t(:error_workflow_copy_target),
scheme: :danger
)
@turbo_status = :unprocessable_entity
else
Workflow.eligible_roles.each do |role|
Workflow.copy_one(@source_type, role, @target_type, role)
end
redirect_to edit_workflow_path(@target_type),
notice: t(".notice", type_name: @target_type.name)
Workflow.copy(@source_type, nil, @target_types, Workflow.eligible_roles)
redirect_to edit_workflow_path(@target_types.first),
notice: t(".notice", count: @target_types.size, type_name: @target_types.first.name)
return
end
@@ -69,7 +67,7 @@ class Workflows::Copies::FromTypesController < ApplicationController
@source_type = ::Type.find_by(id: params[:workflow_type_id])
end
def set_target_type
@target_type = ::Type.find_by(id: params[:target_type_id])
def set_target_types
@target_types = ::Type.where(id: params[:target_type_ids])
end
end
+15 -2
View File
@@ -71,8 +71,21 @@ class Workflows::Copies::Form < ApplicationForm
"show-when-value-selected-target": "effect"
}
) do |from_type|
target_label = helpers.t("workflows.copies.form.target_type_id.label")
from_type.select_list(name: :target_type_id, label: target_label, required: true) do |target_list|
from_type.autocompleter(
name: "target_type_ids",
required: true,
include_blank: false,
label: helpers.t("workflows.copies.form.target_type_ids.label"),
autocomplete_options: {
multiple: true,
decorated: true,
closeOnSelect: false,
appendTo: @append_to,
data: {
"test-selector": "target_types_autocomplete"
}
}
) do |target_list|
@other_types.each do |other_type|
target_list.option(label: other_type.name, value: other_type.id)
end
+5 -3
View File
@@ -1403,8 +1403,8 @@ en:
label: "Source role"
target_role_ids:
label: "Target roles"
target_type_id:
label: "Target type"
target_type_ids:
label: "Target types"
mode:
from_role:
label: "Copy to other roles"
@@ -1419,7 +1419,9 @@ en:
other: "Successfully copied workflow to %{count} roles."
from_types:
create:
notice: "Successfully copied workflow to '%{type_name}' type."
notice:
one: "Successfully copied workflow to '%{type_name}' type."
other: "Successfully copied workflow to %{count} types."
new:
title: "Copy workflow of \"%{source_type}\""
form:
@@ -40,26 +40,11 @@ RSpec.describe Workflows::Copies::FromTypesController do
end
end
let!(:other_types) do
build_stubbed_list(:type, 2).tap do |stubs|
where_double = instance_double(ActiveRecord::QueryMethods::WhereChain)
not_double = instance_double(ActiveRecord::Relation)
allow(Type).to receive(:where).and_return(where_double)
allow(where_double).to receive(:not).and_return(not_double)
allow(not_double).to receive(:order).and_return(stubs)
end
end
current_user { build_stubbed(:admin) }
describe "#create" do
let!(:target_type) do
other_types.last.tap do |stub|
allow(Type)
.to receive(:find_by).with(id: stub.id.to_s).and_return(stub)
end
end
let!(:target_types) { build_stubbed_list(:type, 2) }
let!(:target_type_ids) { target_types.map { |t| t.id.to_s } }
let!(:roles) do
build_stubbed_list(:project_role, 2).tap do |stubs|
@@ -71,28 +56,24 @@ RSpec.describe Workflows::Copies::FromTypesController do
end
before do
allow(Workflow).to receive(:copy_one)
allow(Type).to receive(:where).with(id: target_type_ids).and_return(target_types)
allow(Workflow).to receive(:copy)
post :create, params: {
workflow_type_id: source_type.id.to_s,
target_type_id: target_type.id.to_s
target_type_ids: target_type_ids
}, format: :turbo_stream
end
it "calls the Workflow.copy_one method on each role" do
it "calls the Workflow.copy method with all target types and eligible roles" do
expect(Workflow)
.to have_received(:copy_one).exactly(2).times
expect(Workflow)
.to have_received(:copy_one)
.with(source_type, roles.first, target_type, roles.first)
expect(Workflow)
.to have_received(:copy_one)
.with(source_type, roles.last, target_type, roles.last)
.to have_received(:copy)
.with(source_type, nil, target_types, roles)
end
it "redirects with a flash notice" do
expect(response).to redirect_to(edit_workflow_path(target_type))
expect(flash[:notice]).to eq("Successfully copied workflow to '#{target_type.name}' type.")
expect(response).to redirect_to(edit_workflow_path(target_types.first))
expect(flash[:notice]).to eq("Successfully copied workflow to 2 types.")
end
end
end
@@ -37,18 +37,21 @@ RSpec.describe "Workflow copy from type", :js do
current_user { admin }
let(:target_types_autocompleter) { FormFields::Primerized::AutocompleteField.new("target_types", selector: "[data-test-selector='target_types_autocomplete']") }
shared_examples "a copy-to-another-type dialog" do |with_source_role:|
it "permits to select a target type" do
it "permits to select target types" do
if with_source_role
choose "Copy to another type"
end
expect(page).to have_select("Target type", text: types.second.name)
select(types.last.name, from: "Target type")
target_types_autocompleter.select_option types.second.name, types.last.name
target_types_autocompleter.close_autocompleter
click_button "Copy"
expect(page).to have_css(".flash-success", text: "Successfully copied workflow to '#{types.last.name}' type.")
expect(page).to have_css(".flash-success", text: "Successfully copied workflow to 2 types.")
expect(page).to have_current_path(edit_workflow_path(types.second))
end
end
+4 -3
View File
@@ -45,9 +45,10 @@ RSpec.describe Workflows::Copies::Form, type: :forms do
expect(page).to have_field("Copy to other roles", checked: !another_type_at_first)
end
it "renders the Target type select list" do
expect(page).to have_select "Target type", required: true, visible: another_type_at_first do |select|
options_text = select.all("option", visible: another_type_at_first).map(&:text)
it "renders the Target types autocompleter" do
data_attributes = "[data-test-selector=\"target_types_autocomplete\"][data-multiple=\"true\"]"
expect(page).to have_css "opce-autocompleter#{data_attributes}", visible: another_type_at_first do |autocompleter|
options_text = JSON.parse(autocompleter["data-items"]).map { |item| item["name"] }
expect(options_text).to match_array(other_types.map(&:name))
end
end