Merge pull request #9658 from opf/feature/32867/custom-field-me-action-11.4

[32867] Generalize me associated action for custom fields
pull/9663/head
ulferts 3 years ago committed by GitHub
commit 7acadc029d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 51
      app/models/custom_actions/actions/assigned_to.rb
  2. 4
      app/models/custom_actions/actions/custom_field.rb
  3. 84
      app/models/custom_actions/actions/strategies/me_associated.rb
  4. 46
      app/models/custom_actions/actions/strategies/user_custom_field.rb
  5. 86
      spec/features/work_packages/custom_actions/custom_actions_me_value_spec.rb
  6. 0
      spec/features/work_packages/custom_actions/custom_actions_spec.rb
  7. 58
      spec/models/custom_actions/actions/custom_field_spec.rb

@ -29,28 +29,12 @@
#++
class CustomActions::Actions::AssignedTo < CustomActions::Actions::Base
include CustomActions::Actions::Strategies::Associated
include CustomActions::Actions::Strategies::MeAssociated
def self.key
:assigned_to
end
def associated
[[current_user_value_key, I18n.t('custom_actions.actions.assigned_to.executing_user_value')]] + available_principles
end
def values=(values)
values = Array(values).map do |v|
if v == current_user_value_key
v
else
to_integer_or_nil(v)
end
end
@values = values.uniq
end
def available_principles
principal_class
.not_locked
@ -63,39 +47,6 @@ class CustomActions::Actions::AssignedTo < CustomActions::Actions::Base
work_package.assigned_to_id = transformed_value(values.first)
end
##
# Returns the me value if the user is logged
def transformed_value(val)
return val unless has_me_value?
if User.current.logged?
User.current.id
end
end
def current_user_value_key
'current_user'.freeze
end
def has_me_value?
values.first == current_user_value_key
end
def validate(errors)
super
validate_me_value(errors)
end
private
def validate_me_value(errors)
if has_me_value? && !User.current.logged?
errors.add :actions,
:not_logged_in,
name: human_name
end
end
def principal_class
Principal
end

@ -90,7 +90,9 @@ class CustomActions::Actions::CustomField < CustomActions::Actions::Base
CustomActions::Actions::Strategies::Date
when 'bool'
CustomActions::Actions::Strategies::Boolean
when 'list', 'version', 'user'
when 'user'
CustomActions::Actions::Strategies::UserCustomField
when 'list', 'version'
CustomActions::Actions::Strategies::AssociatedCustomField
end
end

@ -0,0 +1,84 @@
#-- encoding: UTF-8
#-- copyright
# OpenProject is an open source project management software.
# Copyright (C) 2012-2021 the OpenProject GmbH
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License version 3.
#
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
# Copyright (C) 2006-2013 Jean-Philippe Lang
# Copyright (C) 2010-2013 the ChiliProject Team
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# See docs/COPYRIGHT.rdoc for more details.
#++
module CustomActions::Actions::Strategies::MeAssociated
include ::CustomActions::Actions::Strategies::Associated
def associated
me_value = [current_user_value_key, I18n.t('custom_actions.actions.assigned_to.executing_user_value')]
[me_value] + available_principles
end
def values=(values)
values = Array(values).map do |v|
if v == current_user_value_key
v
else
to_integer_or_nil(v)
end
end
@values = values.uniq
end
##
# Returns the me value if the user is logged
def transformed_value(val)
return val unless has_me_value?
if User.current.logged?
User.current.id
end
end
def current_user_value_key
'current_user'.freeze
end
def has_me_value?
values.first == current_user_value_key
end
def validate(errors)
super
validate_me_value(errors)
end
private
def validate_me_value(errors)
if has_me_value? && !User.current.logged?
errors.add :actions,
:not_logged_in,
name: human_name
end
end
end

@ -0,0 +1,46 @@
#-- encoding: UTF-8
#-- copyright
# OpenProject is an open source project management software.
# Copyright (C) 2012-2021 the OpenProject GmbH
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License version 3.
#
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
# Copyright (C) 2006-2013 Jean-Philippe Lang
# Copyright (C) 2010-2013 the ChiliProject Team
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# See docs/COPYRIGHT.rdoc for more details.
#++
module CustomActions::Actions::Strategies::UserCustomField
include CustomActions::Actions::Strategies::CustomField
include ::CustomActions::Actions::Strategies::MeAssociated
def apply(work_package)
if work_package.respond_to?(:"#{custom_field.accessor_name}=")
work_package.send(:"#{custom_field.accessor_name}=", transformed_value(values.first))
end
end
def available_principles
custom_field
.possible_values_options
.map { |label, value| [value.empty? ? nil : value.to_i, label] }
end
end

@ -0,0 +1,86 @@
#-- copyright
# OpenProject is an open source project management software.
# Copyright (C) 2012-2021 the OpenProject GmbH
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License version 3.
#
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
# Copyright (C) 2006-2013 Jean-Philippe Lang
# Copyright (C) 2010-2013 the ChiliProject Team
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# See docs/COPYRIGHT.rdoc for more details.
#++
require 'spec_helper'
describe 'Custom actions me value', type: :feature, js: true do
shared_let(:admin) { FactoryBot.create :admin }
let(:permissions) { %i(view_work_packages edit_work_packages) }
let(:role) { FactoryBot.create(:role, permissions: permissions) }
let(:user) do
FactoryBot.create(:user,
member_in_project: project,
member_through_role: role)
end
let(:type) { FactoryBot.create(:type_task) }
let(:project) { FactoryBot.create(:project, types: [type], name: 'This project') }
let!(:custom_field) { FactoryBot.create :user_wp_custom_field, types: [type], projects: [project] }
let!(:work_package) do
FactoryBot.create(:work_package,
type: type,
project: project)
end
let(:wp_page) { Pages::FullWorkPackage.new(work_package) }
let(:default_priority) do
FactoryBot.create(:default_priority, name: 'Normal')
end
let(:index_ca_page) { Pages::Admin::CustomActions::Index.new }
before do
with_enterprise_token(:custom_actions)
login_as(admin)
end
it 'can assign user custom field to self' do
# create custom action 'Unassign'
index_ca_page.visit!
new_ca_page = index_ca_page.new
retry_block do
new_ca_page.visit!
new_ca_page.set_name('Set CF to me')
new_ca_page.add_action(custom_field.name, I18n.t('custom_actions.actions.assigned_to.executing_user_value'))
end
new_ca_page.create
assign = CustomAction.last
expect(assign.actions.length).to eq(1)
expect(assign.conditions.length).to eq(0)
expect(assign.actions.first.values).to eq(['current_user'])
login_as user
wp_page.visit!
wp_page.expect_custom_action('Set CF to me')
wp_page.click_custom_action('Set CF to me')
wp_page.expect_attributes "customField#{custom_field.id}": user.name
end
end

@ -243,6 +243,60 @@ describe CustomActions::Actions::CustomField, type: :model do
expect(instance.type)
.to eql(:associated_property)
end
describe 'current_user special value' do
let(:work_package) { FactoryBot.build_stubbed(:work_package) }
let(:user) { FactoryBot.build_stubbed(:user) }
before do
allow(work_package).to receive(:available_custom_fields).and_return([custom_field])
instance.values = ['current_user']
end
it 'can set the value' do
expect(instance).to have_me_value
end
it 'includes the value in available_values' do
expect(instance.associated)
.to include([instance.current_user_value_key, I18n.t('custom_actions.actions.assigned_to.executing_user_value')])
end
context 'when logged in' do
before do
login_as user
end
it 'sets the current user' do
instance.apply work_package
expect(work_package.custom_value_for(custom_field).value).to eq(user.id.to_s)
end
it 'validates the me value when executing' do
errors = ActiveModel::Errors.new(CustomAction.new)
instance.validate errors
expect(errors.symbols_for(:actions)).to be_empty
end
end
context 'when not logged in' do
before do
login_as User.anonymous
end
it 'returns nil for the current user id' do
instance.apply work_package
expect(work_package.custom_value_for(custom_field).value).to be_nil
end
it 'validates the me value when executing' do
errors = ActiveModel::Errors.new(CustomAction.new)
instance.validate errors
expect(errors.symbols_for(:actions)).to include :not_logged_in
end
end
end
end
context 'for an int custom field' do
@ -372,8 +426,8 @@ describe CustomActions::Actions::CustomField, type: :model do
.and_return(users)
end
let(:expected) do
users
.map { |u| { value: u.id, label: u.name } }
values = [{ label: "(Assign to executing user)", value: "current_user" }]
values + users.map { |u| { value: u.id, label: u.name } }
end
context 'for a non required field' do

Loading…
Cancel
Save