app/models/custom_button_set.rb
class CustomButtonSet < ApplicationRecord
acts_as_miq_set
before_save :update_button_order
after_save :update_children
def update_button_order
if set_data.try(:[], :button_order).nil?
self.set_data ||= {}
set_data[:button_order] ||= []
end
children = Set.new(Rbac.filtered(CustomButton.where(:id => set_data[:button_order])).pluck(:id))
# remove obsolete entries from button_order
set_data[:button_order].select! do |button_id|
children.include?(button_id)
end
end
def update_children
if set_data.try(:[], :button_order).nil?
remove_all_children
return
end
children = Rbac.filtered(CustomButton.where(:id => set_data[:button_order]))
replace_children(children)
end
def self.reorder_group_index(ids)
sets = CustomButtonSet.where(:id => ids).index_by(&:id)
raise ArgumentError, "not all requested ids found" unless sets.keys.sort == ids.sort
ids.each.with_index(1) do |id, i|
button_set = sets[id]
button_set.set_data[:group_index] = i
button_set.save!
end
end
def self.find_all_by_class_name(class_name, class_id = nil)
ordering = ->(o) { [o.set_data[:group_index].to_s, o.name] }
case class_name
when "ServiceTemplate"
# for services we need to show custom buttons for a specific Services parent ServiceTemplate and for all Services
applies_to_instance(class_name, class_id).sort_by(&ordering) +
applies_to_all_instances("Service").sort_by(&ordering)
when "GenericObjectDefinition"
# for generic objects we need to show custom buttons for a specific generic object's parent GenericObjectDefinition
# and for all Generic Objects
applies_to_instance(class_name, class_id).sort_by(&ordering) +
applies_to_all_instances("GenericObject").sort_by(&ordering)
else
applies_to_all_instances(class_name).sort_by(&ordering)
end
end
def self.applies_to_class(class_name)
where("set_data like ?", "%:applies_to_class: #{class_name}%")
end
def self.applies_to_instance(class_name, id)
applies_to_class(class_name).where("set_data like ?", "%:applies_to_id: #{id.to_i}%")
end
def self.applies_to_all_instances(class_name)
applies_to_class(class_name).where("set_data not like ?", "%:applies_to_id%")
end
# Params:
# custom_button_sets: <Array>CustomButtonSet
# object: for this object are evaluated visibility_expression of CustomButtons
# one CustomButtonSet contains any CustomButtons,
# CustomButtonSet has stored this ids of CustomButtons in array CustomButton#set_data[:button_order]
# Returns:
# <Array>CustomButtonSet
#
# example:
# let's have:
# custom_buttons_set =
# <Array> [<CustomButtonSet> id: 10000000000075,
# set_data:
# {:button_order=> [1, 2]}, list ids of custom buttons in custom button set (group of buttons in UI)
# ... ]
# object = Vm.first
#
# then CustomButtonSet.filter_with_visibility_expression(custom_button_sets, object) returns:
# - same custom_button_sets array when all visibility expressions are not populated(CustomButton#visibility_expression = nil)
# - same custom_button_sets array but with filtered list custom buttons ids in each custom button set from
# custom_button_sets when any visibility expression is evaluated to true
# - ids of custom buttons with visibility expression which are evaluated to false are removed from CustomButtonSet#set_data[:button_order]
# - filtered custom_button_sets array when all visibilty expression custom buttons have been evaluated to false
def self.filter_with_visibility_expression(custom_button_sets, object)
custom_button_sets.each_with_object([]) do |custom_button_set, ret|
custom_button_from_set = CustomButton.where(:id => custom_button_set.custom_buttons.pluck(:id)).select(:id, :visibility_expression).with_array_order(custom_button_set.set_data[:button_order])
filtered_ids = custom_button_from_set.select { |x| x.evaluate_visibility_expression_for(object) }.pluck(:id)
if filtered_ids.present?
custom_button_set.set_data[:button_order] = filtered_ids
ret << custom_button_set
end
ret
end
end
def deep_copy(options)
raise ArgumentError, "options[:owner] is required" if options[:owner].blank?
options.each_with_object(dup) { |(k, v), button_set| button_set.send(:"#{k}=", v) }.tap do |cbs|
cbs.guid = SecureRandom.uuid
cbs.name = "#{name}-#{cbs.guid}"
cbs.set_data[:button_order] = []
cbs.set_data[:applies_to_id] = options[:owner].id
cbs.save!
custom_buttons.each do |cb|
cb_copy = cb.copy(:applies_to => options[:owner])
cbs.add_member(cb_copy)
options[:owner][:options][:button_order] ||= []
options[:owner][:options][:button_order] << "cb-#{cb_copy.id}"
cbs.set_data[:button_order] << cb_copy.id
options[:owner].save!
cbs.save!
end
end
end
def self.display_name(number = 1)
n_('Button Group', 'Button Groups', number)
end
end