app/controllers/report_controller/menus.rb
module ReportController::Menus
extend ActiveSupport::Concern
def get_tree_data
# build tree for selected role in left div of the right cell
group_id = x_node(:roles_tree).split('-').last
session[:role_choice] = MiqGroup.find(group_id).description if group_id.present?
session[:node_selected] = "" if params[:action] != "menu_field_changed"
@sb[:menu_default] = false
if @changed || @menu_lastaction == "discard_changes"
@rpt_menu = copy_array(@edit[:new])
elsif @menu_lastaction == "default"
else
populate_reports_menu(true)
tree = build_menu_roles_tree
@rpt_menu = tree.rpt_menu
end
@menu_lastaction = "menu_editor" if @menu_lastaction != "commit" && @menu_lastaction != "discard_changes" && params[:action] == "get_tree_data"
menu_editor
end
def menu_editor
assert_privileges("miq_report_menu_editor")
menu_set_form_vars if %w[explorer tree_select x_history].include?(params[:action])
@in_a_form = true
@menu_roles_tree = if @menu_lastaction != "menu_editor"
build_menu_roles_tree(@edit[:new])
else
# changing rpt_menu if changes have been commited to show updated tree with changes
build_menu_roles_tree
end
@sb[:role_list_flag] = true if params[:id]
if params[:node_id]
session[:node_selected] = params[:node_id]
elsif session[:node_selected].blank?
session[:node_selected] = "xx-b__Report Menus for #{session[:role_choice]}"
end
@sb[:node_clicked] = (params[:node_clicked] == "1")
@breadcrumbs = []
drop_breadcrumb(:name => "Edit Report menus for '#{session[:role_choice]}'")
if session[:node_selected].index(':').nil? || params[:button] == "reset"
edit_folder
replace_right_cell if params[:node_clicked]
else
edit_reports
end
end
def menu_folder_message_display
assert_privileges("miq_report_menu_editor")
text = if params[:typ] == "delete"
_("Can not delete folder, one or more reports in the selected folder are not owned by your group")
else
_("Double Click on 'New Folder' to edit")
end
render_flash(text, :warning)
end
# AJAX driven routine to check for changes in ANY field on the user form
def menu_field_changed
assert_privileges("miq_report_menu_editor")
return unless load_edit("menu_edit__#{session[:role_choice] ? session[:role_choice] : "new"}", "replace_cell__explorer")
menu_get_form_vars
@in_a_form = true
@edit[:tree_arr] = []
@edit[:tree_hash] = {}
@edit[:temp_new] = []
if params[:tree]
@menu_lastaction = "commit"
@sb[:tree_err] = false
rows = JSON.parse(params[:tree], :symbolize_names => true)
rows.each do |row|
if row[:text].nil?
@sb[:tree_err] = true
add_flash(_("Folder name is required"), :error)
elsif @edit[:tree_arr].include?(row[:text])
@sb[:tree_err] = true
add_flash(_("Folder name '%{value}' is already in use") % {:value => row[:text]}, :error)
else
@edit[:tree_arr].push(row[:text])
@edit[:tree_hash][row[:id].split('_')[1]] = row[:text]
end
end
@edit[:temp_new] = []
if @edit[:tree_arr].blank?
# if all subfolders were deleted
@edit[:temp_new].push(@edit[:temp_arr][0], [])
else
@edit[:tree_arr].each do |el|
old_folder = @edit[:tree_hash].key(el)
@edit[:temp_arr].each do |arr|
arr = Array.wrap(arr)
temp = []
if session[:node_selected].split('__')[1] == "Report Menus for #{session[:role_choice]}"
if arr[0] == old_folder
temp.push(el)
temp.push(arr[1])
elsif old_folder.nil?
temp.push(el) unless temp.include?(el)
temp.push([]) unless temp.include?([])
end
@edit[:temp_new].push(temp) if !temp.empty? && !@edit[:temp_new].include?(temp)
else
@edit[:temp_new][0] = @edit[:temp_arr][0]
arr.each do |a|
if a[0] == old_folder
temp.push(el)
temp.push(a[1])
elsif old_folder.nil?
temp.push(el) unless temp.include?(el)
temp.push([]) unless temp.include?([])
end
@edit[:temp_new][1] = [] if @edit[:temp_new][1].nil?
@edit[:temp_new][1].push(temp) if !temp.empty? && !@edit[:temp_new][1].include?(temp)
end
end
end
end
end
if !@edit[:idx].nil?
@edit[:new][@edit[:idx]] = copy_array(@edit[:temp_new])
else
@edit[:new] = copy_array(@edit[:temp_new])
end
end
if params[:pressed] == "commit" && (@edit[:selected_reports] || @edit[:available_reports])
@menu_lastaction = "commit"
val = session[:node_selected].split('__')[1]
old_val = val.split(':')
idx = @edit[:new].index(@edit[:temp_arr]) # index of temp_array that being worked on, in set_data
idx2 = @edit[:temp_arr].index(old_val[0]) # index of parent folder in temp_array
unless @edit[:user_typ]
# remove * at the starting of report names, before saving them for user
@edit[:selected_reports].each_with_index do |rep, i|
@edit[:selected_reports][i] = rep[1..rep.length - 1].strip! if rep.starts_with?('* ')
end
end
@edit[:temp_arr].each do |arr|
next unless arr.class == Array
arr.each do |a|
next if a[0] != old_val[1]
@edit[:temp] = a
idx4 = @edit[:temp_arr][idx2 + 1].index(@edit[:temp]) # index of temp in temp_array
if a[1].nil?
@edit[:temp].push(@edit[:selected_reports])
else
@edit[:reports] = a[1]
idx5 = @edit[:temp].index(@edit[:reports]) # index of reports array in temp
@edit[:temp][idx5] = @edit[:selected_reports]
end
@edit[:temp_arr][idx2 + 1][idx4] = @edit[:temp].dup
@edit[:new][idx] = @edit[:temp_arr].dup
end
end
end
@edit[:commited_new] = copy_array(@edit[:new])
id = session[:node_selected].split('__')
@selected = id[1].split(':')
@changed = (@edit[:new] != @edit[:current]) if @menu_lastaction == "commit"
get_tree_data if (!params[:selected_reports] && !params[:available_reports]) || @menu_lastaction == "commit"
# load if something in report selection changed or if something was commited
if !params[:tree]
replace_right_cell(:menu_edit_action => "menu_commit_reports")
else
replace_right_cell(:menu_edit_action => "menu_commit_folders")
end
end
def discard_changes
assert_privileges("miq_report_menu_editor")
@menu_lastaction = "discard_changes"
id = session[:node_selected].split('__')
@selected = id[1].split(':')
get_tree_data
@edit[:new] = copy_array(@edit[:commited_new]) if @edit[:commited_new]
@changed = (@edit[:new] != @edit[:current])
if params[:pressed] == "discard_reports"
replace_right_cell(:menu_edit_action => "menu_discard_reports")
else
replace_right_cell(:menu_edit_action => "menu_discard_folders")
end
end
def menu_update
assert_privileges("miq_report_menu_editor")
menu_get_form_vars
# @changed = (@edit[:new] != @edit[:current])
if params[:button] == "cancel"
add_flash(_("Edit of Report Menu for role \"%{role}\" was cancelled by the user") %
{:role => session[:role_choice]})
session[:node_selected] = ""
session[:role_choice] = nil
@new_menu_node = "roleroot"
@menu_roles_tree = nil
@edit = session[:edit] = nil
@changed = session[:changed] = false
self.x_node = "root"
replace_right_cell
elsif params[:button] == "reset"
@changed = session[:changed] = false
@edit[:new] = copy_array(@edit[:current])
@menu_lastaction = "reset"
add_flash(_("All changes have been reset"), :warning)
get_tree_data
replace_right_cell(:menu_edit_action => "menu_reset")
elsif params[:button] == "default"
@sb[:rpt_menu] = default_reports_menu
@menu_roles_tree = build_menu_roles_tree
@edit[:new] = copy_array(@sb[:rpt_menu])
@menu_lastaction = "default"
add_flash(_("Report Menu set to default"), :warning)
get_tree_data
# set menu_default flag to true
@sb[:menu_default] = true
replace_right_cell(:menu_edit_action => "menu_default")
elsif params[:button] == "save"
@menu_lastaction = "save"
role = session[:role_choice] unless session[:role_choice].nil?
rec = MiqGroup.find_by(:description => role)
rec[:settings] ||= {}
if @sb[:menu_default]
# delete report_menus from settings if menu set to default
rec[:settings].delete("report_menus")
else
rec[:settings]["report_menus"] ||= {}
rec[:settings]["report_menus"] = copy_array(@edit[:new])
end
if rec.save
session[:edit] = nil # clean out the saved info
add_flash(_("Report Menu for role \"%{role}\" was saved") % {:role => session[:role_choice]})
get_tree_data
session[:node_selected] = ""
session[:role_choice] = nil
@new_menu_node = "roleroot"
@menu_roles_tree = nil
@changed = session[:changed] = false
@edit = session[:edit] = nil
self.x_node = "root"
@in_a_form = false
replace_right_cell(:replace_trees => [:reports])
else
rec.errors.each do |error|
add_flash("#{error.attribute.to_s.capitalize} #{error.message}", :error)
end
@in_a_form = true
session[:changed] = @changed
@changed = true
end
end
end
private
def edit_reports
@edit[:selected_reports] = []
current_group_id = current_user.current_group.try(:id).to_i
id = session[:node_selected].split('__')
@selected = id[1].split(':')
all = MiqReport.all.sort_by { |r| [r.rpt_type, r.filename.to_s, r.name] }
@all_reports = []
all.each do |r|
next if r.template_type != "report" && r.template_type.present?
@all_reports.push(r.name)
end
@selected_reports = []
@assigned_reports = []
# calculating selected reports for selected folder
@edit[:new].each do |arr|
next if arr[0] != @selected[0]
arr.each do |a|
next unless a.class == Array
a.each do |r|
next if r[0] != @selected[1]
r.each do |rep|
next unless rep.class == Array
rep.each do |report_name|
report = MiqReport.find_by(:name => report_name.strip)
r_name = @edit[:user_typ] || report.miq_group_id.to_i == current_group_id ? report_name : "* #{report_name}"
@selected_reports.push(r_name)
end
end
end
end
end
# Calculating reports that are assigned to any of the folders
@edit[:new].each do |arr|
next unless arr.class == Array
arr.each do |a|
next unless a.class == Array
a.each do |r|
r.each do |rep|
next unless rep.class == Array
rep.each do |report_name|
@assigned_reports.push(report_name)
end
end
end
end
end
@available_reports = @all_reports.reject { |r| @assigned_reports.include?(r) }
@edit[:old_selected_reports] = @selected_reports.dup
@edit[:old_available_reports] = @available_reports.dup
@edit[:selected_reports] = @selected_reports.dup
@edit[:available_reports] = @available_reports.dup
# reload grid if folder node was clicked for report management
# if params[:action] == "menu_editor" && @menu_lastaction != "commit" && @menu_lastaction != "discard_changes"
if params[:pressed] != "commit" && params[:pressed] != "discard_reports" && params[:button] != "default" && params[:action] != "menu_field_changed"
replace_right_cell(:menu_edit_action => "menu_edit_reports")
end
end
# Convenience for TreeBuilderMenuRoles
#
def build_menu_roles_tree(rpt_menu = nil)
TreeBuilderMenuRoles.new(
:menu_roles_tree, # name
@sb, # sandbox
true, # build
:role_choice => session[:role_choice],
:rpt_menu => rpt_menu
)
end
def move_menu_cols_left
if params[:available_reports].blank? || params[:available_reports][0] == ""
add_flash(_("No fields were selected to move left"), :error)
else
@edit[:available_reports].each do |af| # Go thru all available columns
if params[:available_reports].include?(af) # See if this column was selected to move
@edit[:selected_reports].push(af) # Add it to the new fields list
end
end
@edit[:available_reports].delete_if { |af| params[:available_reports].include?(af) } # Remove selected fields
@refresh_div = "menu_div2"
@refresh_partial = "/report/menu_form2"
end
end
def move_menu_cols_right
if params[:selected_reports].blank? || params[:selected_reports][0] == ""
add_flash(_("No fields were selected to move right"), :error)
return
end
user = current_user
flg = 0
@edit[:selected_reports].each do |nf| # Go thru all new fields
next unless params[:selected_reports].include?(nf) # See if this col was selected to move
field = nf.split('* ')
r = MiqReport.find_by(:name => field.length == 1 ? field[0].strip : field[1].strip)
if !user.report_admin_user? && r.miq_group_id.to_i != user.current_group.id.to_i && flg.zero?
flg = 1
# only show this flash message once for all reports
add_flash(_("One or more selected reports are not owned by your group, they cannot be moved"), :warning)
end
if user.report_admin_user? || r.miq_group_id.to_i == user.current_group.id.to_i
@edit[:available_reports].push(nf) if @edit[:user_typ] || r.miq_group_id.to_i == user.current_group.id.to_i # Add to the available fields list
@edit[:selected_reports].delete(nf)
end
end
@edit[:available_reports].sort! # Sort the available fields array
@refresh_div = "menu_div2"
@refresh_partial = "/report/menu_form2"
end
def move_menu_cols_up
if params[:selected_reports].blank? || params[:selected_reports][0] == ""
add_flash(_("No fields were selected to move up"), :error)
return
end
consecutive, first_idx, last_idx = selected_menu_consecutive?
if !consecutive
add_flash(_("Select only one or consecutive fields to move up"), :error)
else
if first_idx.positive?
@edit[:selected_reports][first_idx..last_idx].reverse_each do |field|
pulled = @edit[:selected_reports].delete(field)
@edit[:selected_reports].insert(first_idx - 1, pulled)
end
end
@refresh_div = "menu_div2"
@refresh_partial = "/report/menu_form2"
end
@selected_reps = params[:selected_reports]
end
def move_menu_cols_down
if params[:selected_reports].blank? || params[:selected_reports][0] == ""
add_flash(_("No fields were selected to move down"), :error)
return
end
consecutive, first_idx, last_idx = selected_menu_consecutive?
if !consecutive
add_flash(_("Select only one or consecutive fields to move down"), :error)
else
if last_idx < @edit[:selected_reports].length - 1
insert_idx = last_idx + 1 # Insert before the element after the last one
insert_idx = -1 if last_idx == @edit[:selected_reports].length - 2 # Insert at end if 1 away from end
@edit[:selected_reports][first_idx..last_idx].each do |field|
pulled = @edit[:selected_reports].delete(field)
@edit[:selected_reports].insert(insert_idx, pulled)
end
end
@refresh_div = "menu_div2"
@refresh_partial = "/report/menu_form2"
end
@selected_reps = params[:selected_reports]
end
def move_menu_cols_top
if params[:selected_reports].blank? || params[:selected_reports][0] == ""
add_flash(_("No fields were selected to move up") % "", :error)
return
end
consecutive, first_idx, last_idx = selected_menu_consecutive?
if !consecutive
add_flash(_("Select only one or consecutive fields to move up"), :error)
else
if first_idx.positive?
@edit[:selected_reports][first_idx..last_idx].reverse_each do |field|
pulled = @edit[:selected_reports].delete(field)
@edit[:selected_reports].unshift(pulled)
end
end
@refresh_div = "menu_div2"
@refresh_partial = "/report/menu_form2"
end
@selected_reps = params[:selected_reports]
end
def move_menu_cols_bottom
if params[:selected_reports].blank? || params[:selected_reports][0] == ""
add_flash(_("No fields were selected to move down"), :error)
return
end
consecutive, first_idx, last_idx = selected_menu_consecutive?
if !consecutive
add_flash(_("Select only one or consecutive fields to move down"), :error)
else
if last_idx < @edit[:selected_reports].length - 1
@edit[:selected_reports][first_idx..last_idx].each do |field|
pulled = @edit[:selected_reports].delete(field)
@edit[:selected_reports].push(pulled)
end
end
@refresh_div = "menu_div2"
@refresh_partial = "/report/menu_form2"
end
@selected_reps = params[:selected_reports]
end
def selected_menu_consecutive?
first_idx = last_idx = 0
@edit[:selected_reports].each_with_index do |nf, idx|
first_idx = idx if nf == params[:selected_reports].first
if nf == params[:selected_reports].last
last_idx = idx
break
end
end
if last_idx - first_idx + 1 > params[:selected_reports].length
return [false, first_idx, last_idx]
else
return [true, first_idx, last_idx]
end
end
def menu_get_form_vars
copy_params_if_present(@edit[:form_vars], params, %i[selected_reports available_reports])
@edit[:temp_arr] = []
id = session[:node_selected].split('__')
selected = id[1].split(':')
@edit[:new].each do |a1, a2|
if a1 == selected[0]
@edit[:temp_arr].push(a1)
@edit[:temp_arr].push(a2)
elsif selected[0] == "Report Menus for #{session[:role_choice]}"
@edit[:temp_arr] = copy_array(@edit[:new])
end
@edit[:idx] = @edit[:new].index(@edit[:temp_arr])
end
case params[:button]
when 'right' then move_menu_cols_right
when 'left' then move_menu_cols_left
when 'up' then move_menu_cols_up
when 'down' then move_menu_cols_down
when 'top' then move_menu_cols_top
when 'bottom' then move_menu_cols_bottom
end
end
def menu_set_form_vars
# session[:changed] = @changed = false
@edit = {}
@edit[:new] = []
@edit[:key] = "menu_edit__#{session[:role_choice] ? session[:role_choice] : "new"}"
@edit[:temp_arr] = []
@edit[:form_vars] = {}
@edit[:current] = []
@edit[:new] = @rpt_menu unless @rpt_menu.nil?
user = current_user
@edit[:user_typ] = user.report_admin_user?
@edit[:user_group] = user.current_group.id
@edit[:group_reports] = []
menu_set_reports_for_group
@edit[:current] = copy_hash(@edit[:new]) unless @edit[:new].nil?
session[:edit] = @edit
end
def menu_set_reports_for_group
@edit[:new].each do |r|
r.each_slice(2) do |menu, section|
title = "#{menu}/"
next if section.nil? || section.class == String
section.each do |s|
next unless s.class == Array
s.each do |rec|
if rec.class == String
@sub_title = title + "#{rec}/"
else
rec.each do |report_name|
rpt = MiqReport.find_by(:name => report_name.strip)
@edit[:group_reports].push(@sub_title + report_name) if rpt&.miq_group && rpt.miq_group.id.to_i == @edit[:user_group].to_i
end
end
end
end
end
end
end
# Render the view data for the grid view
def menu_folders(view)
view.compact.map do |row|
row_id = nil
if @edit[:user_typ]
# if user is admin/super admin, no need to add special characters in id
row_id = "i_#{row}"
elsif @edit[:group_reports].empty?
# if group does not own any reports then add special characters in id, they cannot delete any folders.
row_id = "__|i_#{row}"
else
prefix = "|-|"
# FIXME: this is jast .last really, on purpose?
@edit[:group_reports].each do |rep|
# need to check if report is not owned by user add special character to the row id so it can be tracked in JS and folder cannnot be deleted in menu editor
nodes = rep.split('/')
val = session[:node_selected].split('__')[0]
row_id = if val == "b"
# if top node
if nodes[0] == row
"i_#{row}" # if report belongs to group
else
"#{prefix}i_#{row}" # if report is owned by other group
end
elsif nodes[1] == row # if second level folder node
"i_#{row}" # if report belongs to group
else
"#{prefix}i_#{row}" # if report is owned by other group
end
end
end
{:id => row_id, :text => row}
end
end
def edit_folder
if params[:button] == "reset" || params[:button] == "default" # resetting node in case reset button is pressed
session[:node_selected] = "xx-b__Report Menus for #{session[:role_choice]}"
end
@selected = session[:node_selected].split('__')
@folders = []
@edit[:folders] = []
# calculating selected reports for selected folder
if session[:node_selected] == "xx-b__Report Menus for #{session[:role_choice]}"
@edit[:new].each do |arr|
if arr[0] != reports_group_title
@folders.push(arr[0])
end
end
else
@edit[:new].each do |arr|
next if arr[0] != @selected[1]
arr.each do |a|
next unless a.class == Array
a.each do |s|
@folders.push(s[0])
end
end
end
end
@edit[:folders] = @folders.dup
@grid_folders = menu_folders(@edit[:folders])
end
def menu_get_all
roles, title = get_group_roles
@sb[:menu] = {}
roles.sort_by { |a| a.name.downcase }.each do |r|
@sb[:menu][r.id] = r.name
end
@right_cell_text = title
@right_cell_div = "role_list"
@menu_roles_tree = nil
end
def get_menu(_nodeid)
# build menu for selected role
get_tree_data
@right_cell_div = "role_list"
@right_cell_text = _("Editing EVM Group \"%{name}\"") % {:name => session[:role_choice]}
end
def get_group_roles
if super_admin_user?
roles = MiqGroup.non_tenant_groups
title = _("All EVM Groups")
else
title = _("My EVM Group")
roles = [current_user.current_group]
end
return roles, title
end
end