Fixes #3821 - Add clear selection action or has changed condition.

This commit is contained in:
Rolf Schmidt 2021-11-05 14:59:10 +01:00
parent 9318f2046e
commit cb36109bc6
10 changed files with 99 additions and 12 deletions

View file

@ -50,15 +50,15 @@ class App.UiElement.core_workflow_condition extends App.UiElement.ApplicationSel
operatorsType = operatorsType =
'active$': ['is'] 'active$': ['is']
'boolean$': ['is', 'is not', 'is set', 'not set'] 'boolean$': ['is', 'is not', 'is set', 'not set', 'has changed', 'changed to']
'integer$': ['is', 'is not', 'is set', 'not set'] 'integer$': ['is', 'is not', 'is set', 'not set', 'has changed', 'changed to']
'^select$': ['is', 'is not', 'is set', 'not set'] '^select$': ['is', 'is not', 'is set', 'not set', 'has changed', 'changed to']
'^tree_select$': ['is', 'is not', 'is set', 'not set'] '^tree_select$': ['is', 'is not', 'is set', 'not set', 'has changed', 'changed to']
'^(input|textarea|richtext)$': ['is', 'is not', 'is set', 'not set', 'regex match', 'regex mismatch'] '^(input|textarea|richtext)$': ['is', 'is not', 'is set', 'not set', 'has changed', 'changed to', 'regex match', 'regex mismatch']
operatorsName = operatorsName =
'_id$': ['is', 'is not', 'is set', 'not set'] '_id$': ['is', 'is not', 'is set', 'not set', 'has changed', 'changed to']
'_ids$': ['is', 'is not', 'is set', 'not set'] '_ids$': ['is', 'is not', 'is set', 'not set', 'has changed', 'changed to']
# merge config # merge config
elements = {} elements = {}
@ -175,7 +175,7 @@ class App.UiElement.core_workflow_condition extends App.UiElement.ApplicationSel
currentOperator = elementRow.find('.js-operator option:selected').attr('value') currentOperator = elementRow.find('.js-operator option:selected').attr('value')
name = @buildValueName(elementFull, elementRow, groupAndAttribute, elements, meta, attribute) name = @buildValueName(elementFull, elementRow, groupAndAttribute, elements, meta, attribute)
if _.contains(['is set', 'not set'], currentOperator) if _.contains(['is set', 'not set', 'has changed'], currentOperator)
elementRow.find('.js-value').addClass('hide').html('<input type="hidden" name="' + name + '" value="true" />') elementRow.find('.js-value').addClass('hide').html('<input type="hidden" name="' + name + '" value="true" />')
return return

View file

@ -128,7 +128,7 @@ class App.UiElement.core_workflow_perform extends App.UiElement.ApplicationSelec
super(elementFull, elementRow, groupAndAttribute, elements, meta, attribute) super(elementFull, elementRow, groupAndAttribute, elements, meta, attribute)
@buildValueConfigMultiple: (config, meta) -> @buildValueConfigMultiple: (config, meta) ->
if _.contains(['add_option', 'remove_option', 'set_fixed_to'], meta.operator) if _.contains(['add_option', 'remove_option', 'set_fixed_to', 'select'], meta.operator)
config.multiple = true config.multiple = true
config.nulloption = true config.nulloption = true
else else

View file

@ -305,6 +305,11 @@ class App.FormHandlerCoreWorkflow
screen: ui.screen screen: ui.screen
} }
# send last changed attribute only once for has changed condition
if ui.lastChangedAttribute
requestData.last_changed_attribute = ui.lastChangedAttribute
ui.lastChangedAttribute = '-'
if App.FormHandlerCoreWorkflow.useWebSockets() if App.FormHandlerCoreWorkflow.useWebSockets()
App.WebSocket.send(requestData) App.WebSocket.send(requestData)
else else

View file

@ -8,7 +8,7 @@ class CoreWorkflow::Condition
def initialize(result_object:, workflow:) def initialize(result_object:, workflow:)
@user = result_object.user @user = result_object.user
@payload = result_object.payload @payload = result_object.payload
@workflow = workflow @workflow = workflow
@attribute_object = result_object.attributes @attribute_object = result_object.attributes
@result_object = result_object @result_object = result_object
@check = nil @check = nil

View file

@ -10,6 +10,10 @@ class CoreWorkflow::Condition::Backend
attr_reader :value attr_reader :value
def field
@key.sub(%r{.*\.}, '')
end
def object?(object) def object?(object)
@condition_object.attributes.instance_of?(object) @condition_object.attributes.instance_of?(object)
end end

View file

@ -0,0 +1,9 @@
# Copyright (C) 2012-2021 Zammad Foundation, http://zammad-foundation.org/
class CoreWorkflow::Condition::ChangedTo < CoreWorkflow::Condition::Backend
def match
return if !CoreWorkflow::Condition::HasChanged.new(condition_object: @condition_object, key: @key, condition: @condition, value: @value).match
CoreWorkflow::Condition::Is.new(condition_object: @condition_object, key: @key, condition: @condition, value: @value).match
end
end

View file

@ -0,0 +1,9 @@
# Copyright (C) 2012-2021 Zammad Foundation, http://zammad-foundation.org/
class CoreWorkflow::Condition::HasChanged < CoreWorkflow::Condition::Backend
def match
return if @condition_object.payload['last_changed_attribute'] != field
true
end
end

View file

@ -11,7 +11,7 @@ class CoreWorkflow::Result::FillIn < CoreWorkflow::Result::Backend
end end
def skip? def skip?
return true if fill_in_value.blank? return true if fill_in_value.nil?
return true if params_set? return true if params_set?
return true if fill_in_set? return true if fill_in_set?

View file

@ -11,7 +11,7 @@ class CoreWorkflow::Result::Select < CoreWorkflow::Result::Backend
end end
def skip? def skip?
return true if select_value.blank? return true if select_value.nil?
return true if params_set? return true if params_set?
return true if select_set? return true if select_set?

View file

@ -1790,4 +1790,64 @@ RSpec.describe CoreWorkflow, type: :model do
expect(result[:matched_workflows]).to include(workflow1.id, workflow2.id) expect(result[:matched_workflows]).to include(workflow1.id, workflow2.id)
end end
end end
describe 'Add clear selection action or has changed condition #3821' do
let!(:workflow_has_changed) do
create(:core_workflow,
object: 'Ticket',
condition_selected: {
'ticket.priority_id': {
operator: 'has_changed',
},
})
end
let!(:workflow_changed_to) do
create(:core_workflow,
object: 'Ticket',
condition_selected: {
'ticket.priority_id': {
operator: 'changed_to',
value: [ Ticket::Priority.find_by(name: '3 high').id.to_s ]
},
})
end
context 'when priority changed' do
let(:payload) do
base_payload.merge('last_changed_attribute' => 'priority_id', 'params' => { 'priority_id' => Ticket::Priority.find_by(name: '3 high').id.to_s })
end
it 'does match on condition has changed' do
expect(result[:matched_workflows]).to include(workflow_has_changed.id)
end
it 'does match on condition changed to' do
expect(result[:matched_workflows]).to include(workflow_changed_to.id)
end
end
context 'when nothing changed' do
it 'does not match on condition has changed' do
expect(result[:matched_workflows]).not_to include(workflow_has_changed.id)
end
it 'does not match on condition changed to' do
expect(result[:matched_workflows]).not_to include(workflow_changed_to.id)
end
end
context 'when state changed' do
let(:payload) do
base_payload.merge('last_changed_attribute' => 'state_id')
end
it 'does not match on condition has changed' do
expect(result[:matched_workflows]).not_to include(workflow_has_changed.id)
end
it 'does not match on condition changed to' do
expect(result[:matched_workflows]).not_to include(workflow_changed_to.id)
end
end
end
end end