app/controllers/application_controller/buttons.rb
module ApplicationController::Buttons
extend ActiveSupport::Concern
included do
include Mixins::PlaybookOptions
include CustomButtonHelper
end
def ab_group_edit
assert_privileges("ab_group_edit")
group_new_edit("edit")
end
def ab_group_new
assert_privileges("ab_group_new")
group_new_edit("new")
end
def ab_group_reorder
assert_privileges("ab_group_reorder")
case params[:button]
when "cancel"
add_flash(_("Button Group Reorder cancelled"))
@edit = session[:edit] = nil # clean out the saved info
ab_get_node_info(x_node) if x_active_tree == :ab_tree
replace_right_cell(:nodetype => x_node)
when "save"
return unless load_edit("group_reorder", "replace_cell__explorer")
# save group_index of each custombuttonset in set_data
if x_active_tree == :sandt_tree
button_order = []
st = ServiceTemplate.find(@sb[:applies_to_id])
end
@edit[:new][:fields].each_with_index do |field, i|
field_nodes = field.last.split('-')
button_order.push(field.last) if x_active_tree == :sandt_tree
next if field_nodes.first != "cbg"
cs = CustomButtonSet.find(field_nodes.last)
cs.set_data[:group_index] = i + 1
cs.save!
end
if x_active_tree == :sandt_tree
st.options[:button_order] = button_order
st.save
end
add_flash(_("Button Group Reorder saved"))
@edit = session[:edit] = nil # clean out the saved info
ab_get_node_info(x_node) if x_active_tree == :ab_tree
replace_right_cell(:nodetype => x_node, :replace_trees => x_active_tree == :ab_tree ? [:ab] : [:sandt])
else
if params[:button] == "reset"
@changed = session[:changed] = false
add_flash(_("All changes have been reset"), :warning)
end
group_reorder_set_form_vars
@in_a_form = true
@lastaction = "automate_button"
@layout = "miq_ae_automate_button"
replace_right_cell(:nodetype => "group_reorder", :action => "group_reorder")
end
end
def group_reorder_field_changed
assert_privileges("ab_group_reorder")
if params['selected_fields']
return unless load_edit("group_reorder", "replace_cell__explorer")
move_cols_up if params[:button] == "up"
move_cols_down if params[:button] == "down"
@changed = (@edit[:new] != @edit[:current])
@refresh_partial = "group_order_form"
render :update do |page|
page << javascript_prologue
page.replace("flash_msg_div", :partial => "layouts/flash_msg") unless @refresh_div && @refresh_div != "column_lists"
page << "miqScrollTop();" if @flash_array.present?
page.replace(@refresh_div, :partial => "shared/buttons/#{@refresh_partial}") if @refresh_div
page << "miqSparkle(false);"
page << javascript_for_miq_button_visibility_changed(@changed)
end
else
add_flash(_("No Button Group was selected!"), :error)
javascript_flash
end
end
def group_create
assert_privileges("ab_group_new")
group_create_update("create")
end
def group_update
assert_privileges("ab_group_edit")
group_create_update("update")
end
# Provider, Service, User, Group, Tenant, Cloud Tenant, Generic Object
# we need a "Provider" so adding an "ExtManagementSystem" to the list.
MODEL_WITH_OPEN_URL = %w[ExtManagementSystem Service User MiqGroup Tenant CloudTenant GenericObject Vm].freeze
def automate_button_field_changed
assert_privileges(feature_by_action)
unless params[:target_class]
@edit = session[:edit]
@custom_button = @edit[:custom_button]
if params[:readonly]
@edit[:new][:readonly] = (params[:readonly] != "1")
end
copy_params_if_set(@edit[:new], params, %i[instance_name other_name object_message object_request])
ApplicationController::AE_MAX_RESOLUTION_FIELDS.times do |i|
f = ("attribute_" + (i + 1).to_s)
v = ("value_" + (i + 1).to_s)
@edit[:new][:attrs][i][0] = params[f] if params[f.to_sym]
@edit[:new][:attrs][i][1] = params[v] if params[v.to_sym]
end
@edit[:new][:display] = params[:display] == "1" if params[:display]
@edit[:new][:open_url] = params[:open_url] == "1" if params[:open_url]
copy_params_if_set(@edit[:new], params, %i[name target_attr_name display_for submit_how description button_icon button_color disabled_text button_type inventory_type])
@edit[:new][:disabled_open_url] = !(MODEL_WITH_OPEN_URL.include?(@resolve[:target_class]) && @edit[:new][:display_for] == 'single')
@edit[:new][:open_url] = false if @edit[:new][:disabled_open_url]
@edit[:new][:dialog_id] = nil if params[:display_for].present? && params[:display_for] != 'single'
@edit[:new][:dialog_id] = params[:dialog_id] == "" ? nil : params[:dialog_id] if params.key?("dialog_id")
visibility_box_edit
if params[:button_type] == 'default'
clear_playbook_variables
end
if params[:button_type] == 'ansible_playbook'
initialize_playbook_variables
@edit[:new][:dialog_id] = nil
@edit[:new][:object_request] = CustomButton::PLAYBOOK_METHOD
end
end
render :update do |page|
page << javascript_prologue
if %i[display_for instance_name other_name target_class button_type].any? { |k| params.key?(k) }
@sb[:active_tab] = params[:instance_name] ? "ab_advanced_tab" : "ab_options_tab"
page.replace("ab_form", :partial => "shared/buttons/ab_form")
end
if params[:visibility_typ]
page.replace("form_role_visibility", :partial => "layouts/role_visibility", :locals => {:rec_id => (@custom_button.id || "new").to_s, :action => "automate_button_field_changed"})
end
unless params[:target_class]
@changed = session[:changed] = (@edit[:new] != @edit[:current])
page << javascript_for_miq_button_visibility(@changed)
end
page << "miqSparkle(false);"
end
end
def ab_button_new
assert_privileges("ab_button_new")
button_new_edit("new")
end
def ab_button_edit
assert_privileges("ab_button_edit")
button_new_edit("edit")
end
def button_update
assert_privileges("ab_button_edit")
button_create_update("update")
end
def button_create
assert_privileges("ab_button_new")
button_create_update("create")
end
def group_form_valid
required = %i[name description button_icon]
required.none? do |field|
@edit[:new][field].blank?
end
end
def open_url_after_dialog
external_url = ExternalUrl.find_by(
:resource_id => params[:targetId],
:resource_type => params[:realTargetType],
:user => User.current_user
)
# FIXME: remove this fallback once the ':remote_console_url=' is removed from automate
external_url ||= SystemConsole.find_by(:vm_id => params[:targetId])
url = external_url.try(:url)
render :json => {:open_url => url}
end
private
def feature_by_action
features_in_action = %w[ab_button_new ab_button_edit]
@sb[:action] if features_in_action.include?(@sb[:action])
end
BASE_MODEL_EXPLORER_CLASSES = [MiqGroup, MiqTemplate, Tenant, User, Vm].freeze
def custom_button_done
external_url = ExternalUrl.find_by(
:resource_id => params[:id],
:resource_type => params[:base_cls],
:user => User.current_user
)
# FIXME: remove this fallback once the ':remote_console_url=' is removed from automate
external_url ||= SystemConsole.find_by(:vm_id => params[:id])
url = external_url.try(:url)
if url.present?
javascript_open_window(url)
else
render_flash(_('No url was returned from automate.'), :error)
end
end
def custom_buttons_invoke(button, objs)
if objs.length > 1 &&
(button.options&.key?(:submit_how) && button.options[:submit_how].to_s == 'all')
button.invoke(objs, 'UI')
else
objs.each { |obj| button.invoke(obj, 'UI') }
end
end
def sync_playbook_dialog(button)
service_template = ServiceTemplate.find_by(:name => button.uri_attributes[:service_template_name])
dialog_id = nil
service_template&.resource_actions&.each do |ra|
d = Dialog.where(:id => ra.dialog_id).first
dialog_id = d.id if d
end
if dialog_id && button.resource_action.dialog_id != dialog_id
button.resource_action.dialog_id = dialog_id
button.save
end
end
def custom_buttons(ids = nil, display_options = {})
button = CustomButton.find(params[:button_id])
cls = custom_button_class_model(button.applies_to_class)
@explorer = true if BASE_MODEL_EXPLORER_CLASSES.include?(cls)
ids ||= params[:id] unless relationship_table_screen? && @record.nil?
ids = find_checked_items if ids == 'LIST' || ids.nil?
if ids.blank?
render_flash(_("Error launching custom button: No item was selected."), :error)
return
end
objs = Rbac.filtered(cls.where(:id => ids))
obj = objs.first
if objs.empty?
render_flash(_("Error launching custom button: No item was selected."), :error)
return
end
@right_cell_text = _("%{record} - \"%{button_text}\"") % {:record => obj.name, :button_text => button.name}
if button.resource_action.dialog_id
sync_playbook_dialog(button) if button.options.try(:[], :button_type) == 'ansible_playbook'
options = {
:header => @right_cell_text,
:target_id => obj.id,
:target_ids => objs.collect(&:id),
:target_kls => obj.class.name,
}
options[:dialog_locals] = DialogLocalService.new.determine_dialog_locals_for_custom_button(obj, button.name, button.resource_action, display_options)
options[:dialog_locals][:open_url] = button.options.present? && button.options.fetch_path(:open_url)
options.merge!(display_options) unless display_options.empty?
dialog_initialize(button.resource_action, options)
elsif button.options.present? && button.options.fetch_path(:open_url)
# not supported for objs: cannot do wait for task for multiple tasks
task_id = button.invoke_async(obj, 'UI')
initiate_wait_for_task(
:task_id => task_id,
:action => :custom_button_done,
:extra_params => { :base_cls => cls.base_class.to_s }
)
else
begin
custom_buttons_invoke(button, objs)
rescue StandardError => bang
add_flash(_("Error launching: \"%{task_description}\" %{error_message}") %
{:task_description => params[:desc], :error_message => bang.message}, :error)
else
add_flash(_("\"%{task_description}\" was launched") % {:task_description => params[:desc]})
end
javascript_flash
end
end
def load_available_dialogs
@edit[:new][:available_dialogs] = {}
Dialog.all.each do |d|
@edit[:new][:available_dialogs][d.id] = d.label
end
end
def group_button_cancel(typ)
if typ == "update"
add_flash(_("Edit of Button Group \"%{name}\" was cancelled by the user") % {:name => @edit[:current][:name]})
else
add_flash(_("Add of new Button Group was cancelled by the user"))
end
@edit = session[:edit] = nil # clean out the saved info
ab_get_node_info(x_node) if x_active_tree == :ab_tree
replace_right_cell(:nodetype => x_node)
end
def group_button_add_save(typ)
assert_privileges(params[:button] == "add" ? "ab_group_new" : "ab_group_edit")
if typ == "update"
update_page_content("saved")
else
all_sets = CustomButtonSet.find_all_by_class_name(params[:applies_to_class])
all_sets.each_with_index do |group, i|
group.set_data[:group_index] = i + 1
group.save!
end
if x_active_tree == :sandt_tree
aset = CustomButtonSet.find_by(:id => params[:id])
# push new button at the end of button_order array
if aset
st = ServiceTemplate.find(@sb[:applies_to_id])
st.custom_button_sets.push(aset)
st.options[:button_order] ||= []
st.options[:button_order].push("cbg-#{aset.id}")
st.save
end
end
update_page_content("added")
end
end
def update_page_content(action)
add_flash("Button Group #{params[:name]} was #{action}")
@edit = session[:edit] = nil # clean out the saved info
ab_get_node_info(x_node) if x_active_tree == :ab_tree
replace_right_cell(:nodetype => x_node, :replace_trees => x_active_tree == :ab_tree ? [:ab] : [:sandt])
end
def group_create_update(typ)
@edit = session[:edit]
@record = @custom_button_set = @edit[:custom_button_set_id] ? CustomButtonSet.find(@edit[:custom_button_set_id]) : CustomButtonSet.new
@changed = (@edit[:new] != @edit[:current])
case params[:button]
when 'cancel' then group_button_cancel(typ)
when 'add', 'save' then group_button_add_save(typ)
end
end
def button_create_update(typ)
@edit = session[:edit]
@record = @custom_button = @edit[:custom_button]
@changed = (@edit[:new] != @edit[:current])
case params[:button]
when 'cancel' then ab_button_cancel(typ)
when 'add' then ab_button_add
when 'save' then ab_button_save
when 'reset' then ab_button_reset
when 'enablement_expression', 'visibility_expression' then ab_expression
end
end
def ab_expression
@changed = session[:changed] = (@edit[:new] != @edit[:current])
@expkey = params[:button].to_sym
@edit[:visibility_expression_table] = exp_build_table_or_nil(@edit[:new][:visibility_expression])
@edit[:enablement_expression_table] = exp_build_table_or_nil(@edit[:new][:enablement_expression])
@in_a_form = true
@sb[:active_tab] = "ab_advanced_tab"
replace_right_cell(:action => 'button_edit')
end
def ab_button_cancel(typ)
if typ == "update"
add_flash(_("Edit of Custom Button \"%{name}\" was cancelled by the user") % {:name => @edit[:current][:name]})
else
add_flash(_("Add of new Custom Button was cancelled by the user"))
end
@edit = session[:edit] = nil
ab_get_node_info(x_node) if x_active_tree == :ab_tree
replace_right_cell(:nodetype => x_node)
end
def ab_button_add
assert_privileges("ab_button_new")
@sb[:active_tab] = "ab_options_tab"
@resolve = session[:resolve]
name = @edit[:new][:instance_name].presence || @edit[:new][:other_name]
unless button_valid?
@breadcrumbs = []
drop_breadcrumb(:name => _("Edit of Button"), :url => "/miq_ae_customization/button_edit")
@lastaction = "automate_button"
@layout = "miq_ae_automate_button"
if @switch_tab
render :update do |page|
page << javascript_prologue
page.replace("flash_msg_div", :partial => "layouts/flash_msg")
page << "miqScrollTop();" if @flash_array.present?
page << "document.querySelector(\"#ab_advanced_tab_tab > a\").click();"
end
else
javascript_flash
end
return
end
attrs = {}
@edit[:new][:attrs].each do |a|
attrs[a[0].to_sym] = a[1] if a[0].present?
end
@edit[:uri] = MiqAeEngine.create_automation_object(name, attrs, :fqclass => @edit[:new][:starting_object], :message => @edit[:new][:object_message])
@edit[:new][:description] = @edit[:new][:description].strip == "" ? nil : @edit[:new][:description] unless @edit[:new][:description].nil?
button_set_record_vars(@custom_button)
nodes = x_node.split('_')
if nodes[0].split('-')[1] != "ub" && nodes.length >= 2
# if group is not unassigned group, add uri as a last member of the group
if x_active_tree == :ab_tree || nodes.length > 2
# find custombutton set in ab_tree or when adding button under a group
group_id = nodes[2].split('-').last
@aset = CustomButtonSet.find(group_id)
end
end
if @custom_button.save
add_flash(_("Custom Button \"%{name}\" was added") % {:name => @edit[:new][:description]})
@edit = session[:edit] = nil
au = CustomButton.find(@custom_button.id)
if @aset && nodes[0].split('-')[1] != "ub" && nodes.length >= 2
# if group is not unassigned group, add uri as a last member of the group
@aset.set_data[:button_order] ||= []
@aset.set_data[:button_order].push(au.id)
@aset.save!
end
if x_active_tree == :sandt_tree
# push new button at the end of button_order array
st = ServiceTemplate.find(@sb[:applies_to_id])
st.custom_buttons.push(au) if nodes.length >= 2 && nodes[1].split('-').first != "cbg"
st.options[:button_order] ||= []
st.options[:button_order].push("cb-#{au.id}")
st.save
end
ab_get_node_info(x_node) if x_active_tree == :ab_tree
replace_right_cell(:nodetype => x_node, :replace_trees => x_active_tree == :ab_tree ? [:ab] : [:sandt])
else
@custom_button.errors.each do |error|
add_flash(_("Error during 'add': %{error_message}") %
{:error_message => @custom_button.errors.full_message(error.attribute, error.message)}, :error)
end
@lastaction = "automate_button"
@layout = "miq_ae_automate_button"
javascript_flash
end
end
def ab_button_save
assert_privileges("ab_button_edit")
@resolve = session[:resolve]
attrs = {}
@sb[:active_tab] = "ab_options_tab"
@edit[:new][:attrs].each do |a|
attrs[a[0].to_sym] = a[1] if a[0].present?
end
@edit[:uri] = MiqAeEngine.create_automation_object(ab_button_name, attrs, :fqclass => @edit[:new][:starting_object], :message => @edit[:new][:object_message])
@edit[:new][:description] = @edit[:new][:description].strip == "" ? nil : @edit[:new][:description] unless @edit[:new][:description].nil?
unless button_valid?
@breadcrumbs = []
drop_breadcrumb(:name => _("Edit of Button"), :url => "/miq_ae_customization/button_edit")
@lastaction = "automate_button"
@layout = "miq_ae_automate_button"
if @switch_tab
render :update do |page|
page << javascript_prologue
page.replace("flash_msg_div", :partial => "layouts/flash_msg")
page << "miqScrollTop();" if @flash_array.present?
page << "document.querySelector(\"#ab_advanced_tab_tab > a\").click();"
end
else
javascript_flash
end
return
end
button_set_record_vars(@custom_button)
if @custom_button.save
add_flash(_("Custom Button \"%{name}\" was saved") % {:name => @edit[:new][:description]})
@edit = session[:edit] = nil
ab_get_node_info(x_node) if x_active_tree == :ab_tree
build_filter_exp_table
replace_right_cell(:nodetype => x_node, :replace_trees => x_active_tree == :ab_tree ? [:ab] : [:sandt])
else
@custom_button.errors.each do |error|
add_flash(_("Error during 'edit': %{field_name} %{error_message}") %
{:field_name => error.attribute.to_s.capitalize, :error_message => error.message}, :error)
end
@breadcrumbs = []
drop_breadcrumb(:name => "Edit of Button", :url => "/miq_ae_customization/button_edit")
@lastaction = "automate_button"
@layout = "miq_ae_automate_button"
javascript_flash
end
end
def ab_button_reset
button_set_form_vars
@changed = session[:changed] = false
@sb[:active_tab] = "ab_options_tab"
add_flash(_("All changes have been reset"), :warning)
@in_a_form = true
@breadcrumbs = []
drop_breadcrumb(:name => _("Edit of Button"), :url => "/miq_ae_customization/button_edit")
@lastaction = "automate_button"
@layout = "miq_ae_automate_button"
replace_right_cell(:action => "button_edit")
end
# Set form variables for button add/edit
def group_reorder_set_form_vars
@edit = {}
@edit[:new] = {}
@edit[:current] = {}
@edit[:key] = "group_reorder"
@edit[:new][:fields] = []
@sb[:buttons_node] = true
if x_active_tree == :ab_tree
groups = CustomButtonSet.find_all_by_class_name(x_node.split('_').last)
groups.each do |g|
@edit[:new][:fields].push([g.name.split('|').first, "#{g.kind_of?(CustomButton) ? 'cb' : 'cbg'}-#{g.id}"])
end
else
st = ServiceTemplate.find(@sb[:applies_to_id])
groups = st.custom_button_sets + st.custom_buttons
if st.options && st.options[:button_order]
st.options[:button_order].each do |item_id|
groups.each do |g|
rec_id = "#{g.kind_of?(CustomButton) ? 'cb' : 'cbg'}-#{g.id}"
@edit[:new][:fields].push([g.name.split('|').first, rec_id]) if item_id == rec_id
end
end
end
end
@edit[:current] = copy_hash(@edit[:new])
@sb[:button_groups] = nil
@sb[:buttons] = nil
session[:edit] = @edit
end
def group_new_edit(typ)
@record = @custom_button_set = typ == "new" ? CustomButtonSet.new : CustomButtonSet.find(params[:id])
if typ == "edit" && x_node.split('_').last == "ub"
add_flash(_("'Unassigned Button Group' can not be edited"), :error)
get_node_info
replace_right_cell(:nodetype => x_node)
return
end
group_set_form_vars
@right_cell_text = if typ == "new"
_("Adding a new Button Group")
else
_("Editing Button Group \"%{name}\"") % {:name => @custom_button_set.name.split('|').first}
end
@in_a_form = true
@lastaction = "automate_button"
@layout = "miq_ae_automate_button"
@sb[:button_groups] = nil
@sb[:buttons] = nil
# Symbol selection based on active controller
if controller_path == 'miq_ae_customization'
replace_right_cell(:nodetype => 'group_edit')
else
replace_right_cell(:action => 'group_edit')
end
end
def button_new_edit(typ)
@record = @custom_button = typ == "new" ? CustomButton.new : CustomButton.find(params[:id])
@sb[:active_tab] = "ab_options_tab"
button_set_form_vars
@in_a_form = true
@changed = session[:changed] = false
@breadcrumbs = []
@right_cell_text = if typ == "new"
_("Adding a new Button")
else
_("Editing Button \"%{name}\"") % {:name => @custom_button.name}
end
@lastaction = "automate_button"
@layout = "miq_ae_automate_button"
@sb[:buttons] = nil
@sb[:button_groups] = nil
# Symbol selection based on active controller
if controller_path == 'miq_ae_customization'
replace_right_cell(:nodetype => 'button_edit')
else
replace_right_cell(:action => 'button_edit')
end
end
# Set form variables for button add/edit
def group_set_form_vars
@sb[:buttons_node] = true
if session[:resolve]
@resolve = session[:resolve]
else
build_resolve_screen
end
@edit = {}
@edit[:new] = {}
@edit[:current] = {}
@edit[:key] = "bg_edit__#{@custom_button_set.id || "new"}"
@edit[:custom_button_set_id] = @custom_button_set.id
@edit[:rec_id] = @custom_button_set.try(:id)
@edit[:new][:name] = @custom_button_set[:name].split("|").first if @custom_button_set[:name].present?
@edit[:new][:applies_to_class] = @custom_button_set[:set_data] && @custom_button_set[:set_data][:applies_to_class] ? @custom_button_set[:set_data][:applies_to_class] : @sb[:applies_to_class]
@edit[:new][:description] = @custom_button_set.description
@edit[:new][:button_icon] = @custom_button_set[:set_data] && @custom_button_set[:set_data][:button_icon] ? @custom_button_set[:set_data][:button_icon] : ""
@edit[:new][:button_color] = @custom_button_set[:set_data] && @custom_button_set[:set_data][:button_color] ? @custom_button_set[:set_data][:button_color] : ""
@edit[:new][:display] = @custom_button_set[:set_data] && @custom_button_set[:set_data].key?(:display) ? @custom_button_set[:set_data][:display] : true
@edit[:new][:fields] = []
button_order = @custom_button_set[:set_data].try(:[], :button_order)
if button_order # show assigned buttons in order they were saved
button_order.each do |bidx|
@custom_button_set.members.each do |mem|
@edit[:new][:fields].push([mem.name, mem.id]) if bidx == mem.id && !@edit[:new][:fields].include?([mem.name, mem.id])
end
end
else
@custom_button_set.members.each do |mem|
@edit[:new][:fields].push([mem.name, mem.id])
end
end
@edit[:new][:available_fields] =
CustomButton.buttons_for(@sb[:applies_to_class])
.select { |u| u.custom_button_sets.blank? }
.sort_by(&:name)
.collect { |u| [u.name, u.id] }
@edit[:current] = copy_hash(@edit[:new])
session[:edit] = @edit
end
def move_cols_top
if params[:selected_fields].blank? || params[:selected_fields][0] == ""
add_flash(_("No fields were selected to move top"), :error)
return
end
consecutive, first_idx, last_idx = selected_consecutive?
if !consecutive
add_flash(_("Select only one or consecutive fields to move to the top"), :error)
else
if first_idx.positive?
@edit[:new][:fields][first_idx..last_idx].reverse_each do |field|
pulled = @edit[:new][:fields].delete(field)
@edit[:new][:fields].unshift(pulled)
end
end
@refresh_div = "column_lists"
@refresh_partial = "column_lists"
end
@selected = params[:selected_fields]
end
def move_cols_bottom
if params[:selected_fields].blank? || params[:selected_fields][0] == ""
add_flash(_("No fields were selected to move bottom"), :error)
return
end
consecutive, first_idx, last_idx = selected_consecutive?
if !consecutive
add_flash(_("Select only one or consecutive fields to move to the bottom"), :error)
else
if last_idx < @edit[:new][:fields].length - 1
@edit[:new][:fields][first_idx..last_idx].each do |field|
pulled = @edit[:new][:fields].delete(field)
@edit[:new][:fields].push(pulled)
end
end
@refresh_div = "column_lists"
@refresh_partial = "column_lists"
end
@selected = params[:selected_fields]
end
def ab_button_name(button_hash = @edit[:new])
button_hash[:instance_name].presence || button_hash[:instance_name]
end
def button_valid?(button_hash = @edit[:new])
add_flash(_("Button Name is required"), :error) if button_hash[:name].blank? || button_hash[:name].strip.blank?
if button_hash[:button_icon].blank?
add_flash(_("Button Icon must be selected"), :error)
end
add_flash(_("Button Description is required"), :error) if button_hash[:description].blank?
if button_hash[:visibility_typ] == "role" && button_hash[:roles].blank?
add_flash(_("At least one Role must be selected"), :error)
end
if button_hash[:open_url] == true && button_hash[:display_for] != 'single'
add_flash(_('URL can be opened only by buttons for a single entity'), :error)
end
if (button_hash[:dialog_id].present? && !button_hash[:dialog_id].to_i.zero?) && button_hash[:display_for] != 'single'
add_flash(_('Dialog can be opened only by buttons for a single entity'), :error)
end
validate_playbook_button(button_hash) if button_hash[:button_type] == "ansible_playbook"
if ab_button_name(button_hash).blank?
add_flash(_("Starting Process is required"), :error)
@switch_tab = true if @flash_array.length == 1
end
if button_hash[:object_request].blank?
add_flash(_("Request is required"), :error)
@switch_tab = true if @flash_array.length == 1
end
!flash_errors?
end
def validate_playbook_button(button_hash)
if button_hash[:service_template_id].blank? || button_hash[:service_template_id].zero?
add_flash(_("An Ansible Playbook must be selected"), :error)
end
if button_hash[:inventory_type] == 'manual' && button_hash[:hosts].blank?
add_flash(_("At least one host must be specified for manual mode"), :error)
end
end
# Set user record variables to new values
def button_set_record_vars(button)
button.name = @edit[:new][:name]
button.description = @edit[:new][:description]
button.applies_to_class = x_active_tree == :ab_tree ? @resolve[:target_class] : "ServiceTemplate"
button.applies_to_id = x_active_tree == :ab_tree ? nil : @sb[:applies_to_id]
button.userid = session[:userid]
button.uri = @edit[:uri]
button[:options] = {}
button.disabled_text = @edit[:new][:disabled_text]
button.uri_path, button.uri_attributes, button.uri_message = CustomButton.parse_uri(@edit[:uri])
button.uri_attributes["request"] = @edit[:new][:object_request]
button.options[:button_icon] = @edit[:new][:button_icon] if @edit[:new][:button_icon].present?
button.options[:button_color] = @edit[:new][:button_color] if @edit[:new][:button_color].present?
%i[button_type display open_url display_for submit_how].each do |key|
button[:options][key] = @edit[:new][key]
end
button.visibility ||= {}
if @edit[:new][:visibility_typ] == "role"
roles = []
@edit[:new][:roles].each do |r|
role = MiqUserRole.find_by(:id => r)
roles.push(role.name) if role
end
button.visibility[:roles] = roles
else
button.visibility[:roles] = ["_ALL_"]
end
button_set_resource_action(button)
if @edit[:new][:display_for] == "single"
button_set_expressions_record(button)
else
button.visibility_expression = button.enablement_expression = nil
end
button_set_playbook_record(button)
end
def button_set_expressions_record(button)
exp_remove_tokens(@edit[:new][:visibility_expression])
exp_remove_tokens(@edit[:new][:enablement_expression])
button.visibility_expression = @edit[:new][:visibility_expression]["???"] ? nil : MiqExpression.new(@edit[:new][:visibility_expression])
button.enablement_expression = @edit[:new][:enablement_expression]["???"] ? nil : MiqExpression.new(@edit[:new][:enablement_expression])
end
def field_expression_model
@custom_button.applies_to_class ||= (x_active_tree == :ab_tree ? @resolve[:target_class] : "ServiceTemplate")
end
def button_set_expression_vars(field_expression, field_expression_table)
@edit[:new][field_expression] = @custom_button[field_expression].kind_of?(MiqExpression) ? @custom_button[field_expression].exp : nil
# Populate exp editor fields for the expression column
@edit[field_expression] ||= ApplicationController::Filter::Expression.new
@edit[field_expression][:expression] = [] # Store exps in an array
if @edit[:new][field_expression].blank?
@edit[field_expression][:expression] = {"???" => "???"} # Set as new exp element
@edit[:new][field_expression] = copy_hash(@edit[field_expression][:expression]) # Copy to new exp
else
@edit[field_expression][:expression] = copy_hash(@edit[:new][field_expression])
end
@edit[field_expression_table] = exp_build_table_or_nil(@edit[field_expression][:expression])
@expkey = field_expression # Set expression key to expression
@edit[field_expression].history.reset(@edit[field_expression][:expression])
@edit[field_expression][:exp_table] = exp_build_table(@edit[field_expression][:expression])
@edit[field_expression][:exp_model] = field_expression_model # Set model for the exp editor
end
def button_set_resource_action(button)
d = @edit[:new][:dialog_id].nil? ? nil : Dialog.find(@edit[:new][:dialog_id])
# if resource_Action is there update it else create new one
ra = button.resource_action
if ra
ra.dialog = d
ra.save
else
attrs = {:dialog => d}
button.resource_action.build(attrs)
end
end
def button_set_playbook_record(button)
if @edit[:new][:button_type] == 'ansible_playbook'
target = case @edit[:new][:inventory_type]
when "event_target"
'vmdb_object'
when "manual"
@edit[:new][:hosts]
when 'localhost'
'localhost'
end
attrs = {:service_template_name => ServiceTemplate.find(@edit[:new][:service_template_id]).name, :hosts => target}
button.uri_attributes.merge!(attrs)
end
end
def button_set_playbook_form_vars
@edit[:ansible_playbooks] = ServiceTemplateAnsiblePlaybook.order(:name).pluck(:name, :id) || []
service_template = ServiceTemplate.find_by(:name => @custom_button.uri_attributes[:service_template_name])
@edit[:new][:service_template_id] = service_template.try(:id)
service_template&.resource_actions&.each do |ra|
d = Dialog.where(:id => ra.dialog_id).first
@edit[:new][:dialog_id] = d.id if d
end
@edit[:new][:inventory_type] = if @custom_button.uri_attributes[:hosts].blank?
'localhost'
else
case @custom_button.uri_attributes[:hosts]
when 'vmdb_object'
"event_target"
when 'localhost'
"localhost"
else
@edit[:new][:hosts] = @custom_button.uri_attributes[:hosts]
"manual"
end
end
end
# Set form variables for button add/edit
def button_set_form_vars
@sb[:buttons_node] = true
@edit = {}
if session[:resolve] && session[:resolve][:instance_name]
@resolve = session[:resolve]
else
build_resolve_screen
end
@resolve[:target_class] = if x_active_tree == :sandt_tree
"ServiceTemplate"
elsif x_node.starts_with?("-ub-")
x_node.sub(/-ub-([^_]+)(_.*)?/, '\1')
else
x_node.sub(/xx-ab_([^_]+)_.*/, '\1')
end
@record = @edit[:custom_button] = @custom_button
@edit[:instance_names] = Array(@resolve[:instance_names])
@edit[:new] = {}
@edit[:current] = {}
@edit[:new][:attrs] ||= []
@edit[:rec_id] = @custom_button.try(:id)
if @custom_button.uri_attributes
instance_name = @custom_button.uri_object_name
if @edit[:instance_names].include?(instance_name)
@edit[:new][:instance_name] = instance_name
else
@edit[:new][:other_name] = instance_name
end
@edit[:new][:object_request] = @custom_button.uri_attributes["request"]
button_type = @custom_button.options.try(:[], :button_type) ? @custom_button.options[:button_type] : 'default'
default_attributes = %w[request]
default_attributes = %w[request service_template_name hosts] if button_type == 'ansible_playbook'
@custom_button.uri_attributes.each do |attr|
if attr[0] != "object_name" && !default_attributes.include?(attr[0].to_s)
@edit[:new][:attrs].push(attr) unless @edit[:new][:attrs].include?(attr)
end
end
end
(ApplicationController::AE_MAX_RESOLUTION_FIELDS - @edit[:new][:attrs].length).times { @edit[:new][:attrs].push([]) }
@edit[:new][:starting_object] ||= "SYSTEM/PROCESS"
@edit[:new][:instance_name] ||= "Request"
@edit[:new].update(
:target_class => @resolve[:target_class],
:name => @custom_button.name,
:description => @custom_button.description,
:button_icon => @custom_button.options.try(:[], :button_icon),
:button_color => @custom_button.options.try(:[], :button_color),
:disabled_text => @custom_button.disabled_text,
:display => @custom_button.options.try(:[], :display).nil? ? true : @custom_button.options[:display],
:open_url => @custom_button.options.try(:[], :open_url) ? @custom_button.options[:open_url] : false,
:display_for => @custom_button.options.try(:[], :display_for) ? @custom_button.options[:display_for] : 'single',
:submit_how => @custom_button.options.try(:[], :submit_how) ? @custom_button.options[:submit_how] : 'one',
:button_type => button_type,
:object_message => @custom_button.uri_message || "create"
)
button_set_expression_vars(:enablement_expression, :enablement_expression_table)
button_set_expression_vars(:visibility_expression, :visibility_expression_table)
@edit[:new][:disabled_open_url] = !(MODEL_WITH_OPEN_URL.include?(@resolve[:target_class]) && @edit[:new][:display_for] == 'single')
@edit[:current] = copy_hash(@edit[:new])
@edit[:visibility_types] = [["<#{_('To All')}>", "all"], ["<#{_('By Role')}>", "role"]]
# Visibility Box
if @custom_button.visibility && @custom_button.visibility[:roles]
@edit[:new][:visibility_typ] = @custom_button.visibility[:roles][0] == "_ALL_" ? "all" : "role"
if @custom_button.visibility[:roles][0] == "_ALL_"
@edit[:new][:roles] = ["_ALL_"]
else
@edit[:new][:roles] ||= []
@custom_button.visibility[:roles].each do |r|
role = MiqUserRole.find_by(:name => r)
@edit[:new][:roles].push(role.id) if role
end
end
@edit[:new][:roles].sort! if @edit[:new][:roles].present?
end
@edit[:sorted_user_roles] = []
MiqUserRole.all.sort_by { |ur| ur.name.downcase }.each do |r|
@edit[:sorted_user_roles].push(r.name => r.id)
end
@edit[:new][:dialog_id] = @custom_button.resource_action.dialog_id
load_available_dialogs
button_set_playbook_form_vars
@edit[:current] = copy_hash(@edit[:new])
session[:edit] = @edit
@changed = session[:changed] = (@edit[:new] != @edit[:current])
end
def buttons_get_node_info(node)
nodetype = node.split("_")
# initializing variables to hold data for selected node
@custom_button = nil
@sb[:button_groups] = nil
@sb[:buttons] = nil
@sb[:buttons_node] = true
@sb[:applies_to_class] = "ServiceTemplate"
@sb[:applies_to_id] = nodetype[1].split('-').last
if nodetype.length == 3 && nodetype[2].split('-').first == "cbg" # buttons group selected
@sb[:applies_to_class] = "ServiceTemplate"
@record = CustomButtonSet.find(nodetype[2].split('-').last)
# saving id of catalogitem to use it in view to build id for right cell
@sb[:rec_id] = @record.id
@right_cell_text = _("Button Group \"%{name}\"") % {:name => @record.name.split("|").first}
@sb[:buttons] = []
button_order = @record[:set_data] && @record[:set_data][:button_order] ? @record[:set_data][:button_order] : nil
button_order&.each do |bidx| # show assigned buttons in order they were saved
@record.members.each do |b|
next if bidx != b.id
button = {
:name => b.name,
:id => b.id,
:description => b.description,
:button_icon => b.options[:button_icon],
:button_color => b.options[:button_color],
}
@sb[:buttons].push(button) unless @sb[:buttons].include?(button)
end
end
elsif nodetype.length >= 3 && (nodetype[2].split('-').first == "cb" || nodetype[3].split('-').first == "cb") # button selected
id = nodetype[2].split('-').first == "cb" ? nodetype[2].split('-').last : nodetype[3].split('-').last
@record = @custom_button = CustomButton.find(id)
build_resolve_screen
@resolve[:new][:attrs] = []
if @custom_button.uri_attributes
@custom_button.uri_attributes.each do |attr|
if attr[0] != "object_name" && attr[0] != "request"
@resolve[:new][:attrs].push(attr) unless @resolve[:new][:attrs].include?(attr)
end
end
@resolve[:new][:object_request] = @custom_button.uri_attributes["request"]
end
@sb[:user_roles] = []
if @custom_button.visibility && @custom_button.visibility[:roles] && @custom_button.visibility[:roles][0] != "_ALL_"
MiqUserRole.all.sort_by(&:name).each do |r|
@sb[:user_roles].push(r.name) if @custom_button.visibility[:roles].include?(r.name)
end
end
@resolve[:new][:target_class] = "ServiceTemplate"
dialog_id = @custom_button.resource_action.dialog_id
@sb[:dialog_label] = dialog_id ? Dialog.find(dialog_id).label : _("No Dialog")
@right_cell_text = _("Button \"%{name}\"") % {:name => @custom_button.name}
end
@right_cell_div = "ab_list"
end
def build_resolve_screen
@resolve ||= {}
@resolve[:new] ||= {}
@resolve[:new][:starting_object] ||= "SYSTEM/PROCESS"
@resolve[:new][:readonly] = false unless @resolve[:new][:readonly]
@resolve[:throw_ready] = false
# Following commented out since all resolutions start at SYSTEM/PROCESS
# @resolve[:starting_objects] = MiqAeClass.find_all_by_namespace("SYSTEM").collect{|c| c.fqname}
matching_instances = MiqAeClass.find_distinct_instances_across_domains(current_user, @resolve[:new][:starting_object])
if matching_instances.any?
@resolve[:instance_names] = matching_instances.collect(&:name)
instance_name = @custom_button&.uri_object_name
@resolve[:new][:instance_name] = instance_name || @resolve[:new][:instance_name] || "Request"
@resolve[:new][:object_message] = @custom_button.try(:uri_message) || @resolve[:new][:object_message] || "create"
@resolve[:target_class] = nil
@resolve[:target_classes] = CustomButton.button_classes.each_with_object({}) do |klass, hash|
hash[klass] = target_class_name(klass)
end
@resolve[:new][:attrs] ||= []
if @resolve[:new][:attrs].empty?
ApplicationController::AE_MAX_RESOLUTION_FIELDS.times { @resolve[:new][:attrs].push([]) }
else
# add empty array if @resolve[:new][:attrs] length is less than ApplicationController::AE_MAX_RESOLUTION_FIELDS
ApplicationController::AE_MAX_RESOLUTION_FIELDS.times { @resolve[:new][:attrs].push([]) if @resolve[:new][:attrs].length < ApplicationController::AE_MAX_RESOLUTION_FIELDS }
end
@resolve[:throw_ready] = ready_to_throw
else
add_flash(_("Simulation unavailable: Required Class \"System/Process\" is missing"), :warning)
end
end
def move_cols_up
if params[:selected_fields].blank? || params[:selected_fields][0] == ""
add_flash(_("No fields were selected to move up"), :error)
return
end
consecutive, first_idx, last_idx = selected_consecutive?
if !consecutive
add_flash(_("Select only one or consecutive fields to move up"), :error)
else
if first_idx.positive?
@edit[:new][:fields][first_idx..last_idx].reverse_each do |field|
pulled = @edit[:new][:fields].delete(field)
@edit[:new][:fields].insert(first_idx - 1, pulled)
end
end
@refresh_div = "column_lists"
@refresh_partial = "column_lists"
end
@selected = params[:selected_fields]
end
def move_cols_down
if params[:selected_fields].blank? || params[:selected_fields][0] == ""
add_flash(_("No fields were selected to move down"), :error)
return
end
consecutive, first_idx, last_idx = selected_consecutive?
if !consecutive
add_flash(_("Select only one or consecutive fields to move down"), :error)
else
if last_idx < @edit[:new][:fields].length - 1
insert_idx = last_idx + 1 # Insert before the element after the last one
insert_idx = -1 if last_idx == @edit[:new][:fields].length - 2 # Insert at end if 1 away from end
@edit[:new][:fields][first_idx..last_idx].each do |field|
pulled = @edit[:new][:fields].delete(field)
@edit[:new][:fields].insert(insert_idx, pulled)
end
end
@refresh_div = "column_lists"
@refresh_partial = "column_lists"
end
@selected = params[:selected_fields]
end
def selected_consecutive?
first_idx = last_idx = 0
@edit[:new][:fields].each_with_index do |nf, idx|
first_idx = idx if nf[1].to_s == params[:selected_fields].first
if nf[1].to_s == params[:selected_fields].last
last_idx = idx
break
end
end
is_consecutive = last_idx - first_idx + 1 <= params[:selected_fields].length
[is_consecutive, first_idx, last_idx]
end
# Get information for a condition
def build_filter_exp_table
@visibility_expression_table = @custom_button.visibility_expression.kind_of?(MiqExpression) ? exp_build_table(@custom_button.visibility_expression.exp) : nil
@enablement_expression_table = @custom_button.enablement_expression.kind_of?(MiqExpression) ? exp_build_table(@custom_button.enablement_expression.exp) : nil
end
end