Skip to content

Commit

Permalink
#1677, add the "Any tag" for batch update form
Browse files Browse the repository at this point in the history
  • Loading branch information
Ivanov-Anton committed Feb 11, 2025
1 parent 7afbe4c commit 1e39eef
Show file tree
Hide file tree
Showing 7 changed files with 159 additions and 21 deletions.
2 changes: 1 addition & 1 deletion app/assets/javascripts/build_tags.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ $(document).on('mass_update_modal_dialog:after_open', function (event, form) {
'name': 'routing_tag_ids[]',
'class': 'chosen',
'id': 'batch_update_routing_tag_ids',
'value': '', // reset default value
'value': null, // reset default value
'multiple': true
});
var tagsCheckbox = $('#mass_update_dialog_routing_tag_ids');
Expand Down
56 changes: 46 additions & 10 deletions app/forms/batch_update_form/base.rb
Original file line number Diff line number Diff line change
Expand Up @@ -120,17 +120,53 @@ def form_data_boolean(_options)
# :display_name [Symbol] default :name.
# :primary_key [Symbol] default :id.
# :scope [Proc,Symbol,nil] optional.
# :input_html [Hash] Input options
# @return [Array<Array(2)>]
def form_data_foreign_key(options)
klass = options.fetch(:class_name).constantize
display_name = options.fetch(:display_name, :name)
primary_key = options.fetch(:primary_key, :id)
custom_scope = options[:scope]

scope = klass.all
scope = scope.public_send(custom_scope) if custom_scope.is_a?(Symbol)
scope = custom_scope.call(scope) if custom_scope.is_a?(Proc)
scope.pluck(display_name, primary_key)
def form_data_foreign_key(options = {})
opts = extract_foreign_key_options(options)
klass = opts[:class_name].constantize

relation = klass.all
relation = apply_foreign_key_sorting(relation, opts)
result = apply_select_attributes(relation, opts)
add_foreign_key_additional_options(result, opts)
end

def extract_foreign_key_options(options)
options.assert_valid_keys(:class_name, :display_name, :primary_key, :scope, :input_html, :type)
options[:input_html].assert_valid_keys(:additional_options) if options[:input_html].present?

{
class_name: options.fetch(:class_name),
display_name: options.fetch(:display_name, :name),
primary_key: options.fetch(:primary_key, :id),
scope: options[:scope],
additional_options: options.dig(:input_html, :additional_options) || []
}
end

def apply_foreign_key_sorting(relation, options)
if options[:scope].is_a?(Symbol)
relation = relation.public_send(options[:scope])
elsif options[:scope].respond_to?(:call)
relation = options[:scope].call(relation)
else
relation
end
end

def apply_select_attributes(relation, options)
relation.pluck(options[:display_name], options[:primary_key])
end

# Adds additional items for array collection.
#
# @param result [Array] The array of options to be modified.
# @param _options [Hash] The original options hash (unused).
#
# @return [Array] The modified array of options.
def add_foreign_key_additional_options(result, _options)
result
end

def form_data_integer_collection(options)
Expand Down
7 changes: 6 additions & 1 deletion app/forms/batch_update_form/destination.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# frozen_string_literal: true

class BatchUpdateForm::Destination < BatchUpdateForm::Base
include BatchUpdateForm::RoutingTagOptions

model_class 'Routing::Destination'
attribute :enabled, type: :boolean
attribute :prefix
Expand All @@ -25,7 +27,10 @@ class BatchUpdateForm::Destination < BatchUpdateForm::Base
attribute :asr_limit
attribute :acd_limit
attribute :short_calls_limit
attribute :routing_tag_ids, type: :foreign_key, class_name: 'Routing::RoutingTag'
attribute :routing_tag_ids, type: :foreign_key,
class_name: 'Routing::RoutingTag',
input_html: { additional_options: [{ label: Routing::RoutingTag::ANY_TAG, value: nil }] },
scope: ->(scope) { scope.order(:name) }

# presence validations
validates :dst_number_min_length, presence: true, if: :dst_number_min_length_changed?
Expand Down
7 changes: 6 additions & 1 deletion app/forms/batch_update_form/dialpeer.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# frozen_string_literal: true

class BatchUpdateForm::Dialpeer < BatchUpdateForm::Base
include BatchUpdateForm::RoutingTagOptions

model_class 'Dialpeer'
attribute :enabled, type: :boolean
attribute :prefix
Expand Down Expand Up @@ -34,7 +36,10 @@ class BatchUpdateForm::Dialpeer < BatchUpdateForm::Base
attribute :src_rewrite_result
attribute :dst_rewrite_rule
attribute :dst_rewrite_result
attribute :routing_tag_ids, type: :foreign_key, class_name: 'Routing::RoutingTag'
attribute :routing_tag_ids, type: :foreign_key,
class_name: 'Routing::RoutingTag',
input_html: { additional_options: [{ label: Routing::RoutingTag::ANY_TAG, value: nil }] },
scope: ->(scope) { scope.order(:name) }

# presence
validates :dst_number_min_length, presence: true, if: :dst_number_min_length_changed?
Expand Down
20 changes: 20 additions & 0 deletions app/forms/batch_update_form/routing_tag_options.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# frozen_string_literal: true

module BatchUpdateForm::RoutingTagOptions
extend ActiveSupport::Concern

class_methods do
def add_foreign_key_additional_options(result, options)
additional_options = options[:additional_options]
# Expect additional_options to be an array of hashes, for example:
# [{ label: 'Any tag', value: nil }]
additional_options.each do |opt|
# Prepend each additional option to the result array.
# Each item is represented as [label, value].
result.prepend([opt[:label], opt[:value]])
end

result
end
end
end
62 changes: 55 additions & 7 deletions spec/features/routing/destinations/batch_update_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,6 @@
let!(:profit_control_mode_id) { Routing::RateProfitControlMode::MODE_PER_CALL }
let!(:routing_tags) { create_list(:routing_tag, 5) }

before do
visit destinations_path
click_button 'Update batch'
expect(page).to have_selector('.ui-dialog')
end

subject do
fill_batch_form
click_button 'OK'
Expand Down Expand Up @@ -46,7 +40,7 @@
asr_limit: '0.9',
acd_limit: '1',
short_calls_limit: '4',
routing_tag_ids: routing_tags.map { |tag| tag.id.to_s }
routing_tag_ids: routing_tags.sort_by(&:name).map { |tag| tag.id.to_s }
}
end

Expand Down Expand Up @@ -178,6 +172,12 @@
end

context 'should check validates' do
before do
visit destinations_path
click_button 'Update batch'
expect(page).to have_selector('.ui-dialog')
end

context 'when change :dp_margin_percent' do
let(:assign_params) { { dp_margin_percent: '0' } }

Expand Down Expand Up @@ -207,4 +207,52 @@
end
end
end

context 'when user wants to change routing_tag_ids to "NOT TAGGED"' do
subject { click_button :OK }

let(:_destinations) { nil }
let(:assign_params) { {} }

before do
visit destinations_path
click_button 'Update batch'
page.scroll_to find_button('OK')
check :Routing_tag_ids
# toggle checkbox and then leave it empty to chnage value to empty array
end

it 'should create Job to update routing_tag_ids field of desctination to default value: []' do
expect do
subject
expect(page).to have_selector '.flash', text: success_message
end.to enqueue_job(AsyncBatchUpdateJob).with('Routing::Destination', be_present, { routing_tag_ids: '' }, be_present)

# ensure that destination model converts "" to [] because the system consider [] as Routing::RoutingTag::NOT_TAGGED
expect(Routing::Destination.new(routing_tag_ids: '')).to have_attributes(routing_tag_ids: [])
end
end

context 'when user wants to change routing_tag_ids to "ANY TAG"' do
let(:_destinations) { nil }
let(:assign_params) { {} }

before do
visit destinations_path
click_button 'Update batch'
page.scroll_to find_button('OK')
check :Routing_tag_ids
end

it 'should create a Job to update routing_tag_ids to any tag: [nil]' do
fill_in_chosen 'routing_tag_ids[]', with: Routing::RoutingTag::ANY_TAG, multiple: true
expect do
subject
expect(page).to have_selector '.flash', text: success_message
end.to enqueue_job(AsyncBatchUpdateJob).with('Routing::Destination', be_present, { routing_tag_ids: [''] }, be_present)

# ensure that destination model converts [""] to [nil] because the system consider [nil] as Routing::RoutingTag::ANY_TAG
expect(Routing::Destination.new(routing_tag_ids: [''])).to have_attributes(routing_tag_ids: [nil])
end
end
end
26 changes: 25 additions & 1 deletion spec/features/routing/dialpeers/batch_update_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@
src_rewrite_result: '12',
dst_rewrite_rule: '12',
dst_rewrite_result: '12',
routing_tag_ids: routing_tags.map { |tag| tag.id.to_s }
routing_tag_ids: routing_tags.sort_by(&:name).map { |tag| tag.id.to_s }
}
end
let(:fill_batch_form) do
Expand Down Expand Up @@ -266,4 +266,28 @@
end
end
end

context 'when user wants to change routing_tag_ids to "ANY TAG"' do
subject { click_button :OK }

let(:_dialpeers) { nil }
let(:routing_group) { nil }
let!(:routeset_discriminator) { nil }
let(:assign_params) { {} }

before do
check :Routing_tag_ids
fill_in_chosen 'routing_tag_ids[]', with: Routing::RoutingTag::ANY_TAG, multiple: true
end

it 'should create a Job to update routing_tag_ids to any tag: [nil]' do
expect do
subject
expect(page).to have_selector '.flash', text: success_message
end.to enqueue_job(AsyncBatchUpdateJob).with('Dialpeer', be_present, { routing_tag_ids: [''] }, be_present)

# ensure that dialpeer model converts "" to [] because the system considers [""] as Routing::RoutingTag::ANY_TAG
expect(Dialpeer.new(routing_tag_ids: [''])).to have_attributes(routing_tag_ids: [nil])
end
end
end

0 comments on commit 1e39eef

Please sign in to comment.