app/controllers/report_controller/reports/editor.rb
module ReportController::Reports::Editor
extend ActiveSupport::Concern
included do
helper_method :cashed_reporting_available_fields, :cashed_reporting_available_fields
helper_method :chargeback_allocated_methods, :chargeback_allocated_methods
end
DEFAULT_PDF_PAGE_SIZE = "US-Letter".freeze
MAX_REPORT_COLUMNS = 100 # Default maximum number of columns in a report
CHAREGEBACK_ALLOCATED_METHODS = {
:max => N_('Maximum'),
:avg => N_('Average')
}.freeze
def self.chart_top_values
::Settings.reporting.chart_top_values
end
def chargeback_allocated_methods
CHAREGEBACK_ALLOCATED_METHODS.map { |k, v| [k, _(v)] }.to_h
end
def default_chargeback_allocated_method
chargeback_allocated_methods.keys.first
end
def miq_report_new
assert_privileges("miq_report_new")
@_params.delete(:id) # incase add button was pressed from report show screen.
miq_report_add_edit
end
def miq_report_copy
assert_privileges("miq_report_copy")
@report = nil # Clear any saved report object
if params[:tab] # Came in to change the tab
check_tabs
else
@sb[:miq_tab] = "edit_1"
@rpt = MiqReport.for_user(current_user).find(params[:id])
@rpt.id = nil # Treat as a new report
set_form_vars
end
build_edit_screen
replace_right_cell
end
def miq_report_edit
assert_privileges(params[:id] || (@edit && @edit[:rpt_id]) ? "miq_report_edit" : "miq_report_new")
case params[:button]
when "cancel"
if @edit[:rpt_id]
add_flash(_("Edit of Report \"%{name}\" was cancelled by the user") % {:name => @edit[:rpt_title]})
else
add_flash(_("Add of new Report was cancelled by the user"))
end
@edit = session[:edit] = nil # clean out the saved info
replace_right_cell
when "add", "save"
id = params[:id] ? params[:id] : "new"
return unless load_edit("report_edit__#{id}", "replace_cell__explorer")
get_form_vars
@changed = (@edit[:new] != @edit[:current])
@rpt = @edit[:rpt_id] ? find_record_with_rbac(MiqReport, params[:id]) : MiqReport.new
set_record_vars(@rpt)
unless valid_report?(@rpt)
build_edit_screen
replace_right_cell
return
end
if @edit[:new][:graph_type] && (@edit[:new][:sortby1].blank? || @edit[:new][:sortby1] == ReportHelper::NOTHING_STRING)
add_flash(_("Report can not be saved unless sort field has been configured for Charts"), :error)
@sb[:miq_tab] = "edit_4"
build_edit_screen
replace_right_cell
return
end
if @rpt.save
# update report name in menu if name is edited
menu_repname_update(@edit[:current][:name], @edit[:new][:name]) if @edit[:rpt_id] && @edit[:current][:name] != @edit[:new][:name]
AuditEvent.success(build_saved_audit(@rpt, @edit))
if @edit[:rpt_id]
add_flash(_("Report \"%{name}\" was saved") % {:name => @rpt.name})
else
add_flash(_("Report \"%{name}\" was added") % {:name => @rpt.name})
end
# only do this for new reports
unless @edit[:rpt_id]
self.x_node = "xx-#{@sb[:rpt_menu].length}_xx-#{@sb[:rpt_menu].length}-0"
setnode_for_customreport
end
@edit = session[:edit] = nil # clean out the saved info
if role_allows?(:feature => "miq_report_widget_editor")
# all widgets for this report
get_all_widgets("report", x_node.split('_').last)
end
replace_right_cell(:replace_trees => [:reports])
else
rpt.errors.each do |error|
add_flash("#{error.attribute.to_s.capitalize} #{error.message}", :error)
end
@in_a_form = true
session[:changed] = !!@changed
@changed = true
replace_right_cell
end
else
miq_report_add_edit
end
end
def miq_report_add_edit
add_flash(_("All changes have been reset"), :warning) if params[:button] == "reset"
@in_a_form = true
@report = nil # Clear any saved report object
if params[:tab] # Came in to change the tab
@rpt = @edit[:rpt_id] ? MiqReport.for_user(current_user).find(@edit[:rpt_id]) : MiqReport.new
check_tabs
else
@sb[:miq_tab] = "edit_1"
@rpt = params[:id] && params[:id] != "new" ? MiqReport.for_user(current_user).find(params[:id]) : MiqReport.new
if @rpt.rpt_type == "Default"
flash_to_session(_('Default reports can not be edited'), :error)
redirect_to(:action => "show", :id => @rpt.id)
return
end
set_form_vars
end
build_edit_screen
session[:changed] = @changed = (@edit[:new] != @edit[:current])
replace_right_cell
end
# Get string with unavailable fields while adding/editing report
def unavailable_fields_for_model(model)
case model
when 'ChargebackVm'
_('* Caution: CPU Cores Allocated Metric, CPU Cores Used Metric are not supported for Chargeback for Vms.')
when 'ChargebackContainerImage'
_('* Caution: CPU Allocated Metric, CPU Used Metric, Disk I/O Used Metric, Fixed Storage Metric, Storage Allocated Metric, Storage Used Metric are not supported for Chargeback for Images.')
when 'ChargebackContainerProject'
_('* Caution: CPU Allocated Metric, CPU Used Metric, CPU Cores Allocated Metric, Disk I/O Used Metric, Memory Allocated Metric, Fixed Storage Metric, Storage Allocated Metric, Storage Used Metric are not supported for Chargeback for Projects.')
end
end
# AJAX driven routine to check for changes in ANY field on the form
def form_field_changed
assert_privileges(session.fetch_path(:edit, :rpt_id) ? "miq_report_edit" : "miq_report_new")
return unless load_edit("report_edit__#{params[:id]}", "replace_cell__explorer")
get_form_vars
build_edit_screen
@unavailable_fields = unavailable_fields_for_model(@edit[:new][:model])
@changed = (@edit[:new] != @edit[:current])
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 => @refresh_partial) if @refresh_div
page.replace("chart_sample_div", :partial => "form_chart_sample") if @refresh_div == "chart_div"
page.replace_html("calc_#{@calc_div}_div", :text => @calc_val) if @calc_div
page << "miqSparkle(false);"
page << javascript_for_miq_button_visibility_changed(@changed)
if @formatting_changed # Reload the screen if the formatting pulldowns need to be reset
page.replace_html("formatting_div", :partial => "form_formatting")
end
end
end
def filter_change
assert_privileges(session.fetch_path(:edit, :rpt_id) ? "miq_report_edit" : "miq_report_new")
return unless load_edit("report_edit__#{params[:id]}", "replace_cell__explorer")
@expkey = $&.to_sym if params[:button].to_s =~ /^(record|display)_filter$/
render :update do |page|
page << javascript_prologue
page.replace("filter_div", :partial => "form_filter")
page << "miqSparkle(false);"
end
end
private
def build_edit_screen
build_tabs
get_time_profiles # Get time profiles list (global and user specific)
cb_entities_by_provider if Chargeback.db_is_chargeback?(@edit[:new][:model]) && [ChargebackContainerImage, ChargebackContainerProject, MeteringContainerImage, MeteringContainerProject].include?(@edit[:new][:model].safe_constantize)
refresh_chargeback_filter_tab if Chargeback.db_is_chargeback?(@edit[:new][:model])
case @sb[:miq_tab].split("_")[1]
when "1" # Select columns
@edit[:models] ||= reportable_models
# Add the blank choice if no table chosen yet
# @edit[:models].insert(0,["<Choose>", "<Choose>"]) if @edit[:new][:model] == nil && @edit[:models][0][0] != "<Choose>"
if @edit[:new][:model].nil?
if @edit[:models][0][0] != "<Choose>"
@edit[:models].insert(0, ["<Choose>", "<Choose>"])
end
elsif @edit[:models][0][0] == "<Choose>"
@edit[:models].delete_at(0)
end
when "8" # Consolidate
# Build group chooser arrays
@edit[:new][:pivot].options = @edit[:new][:fields].dup
@pivot = @edit[:new][:pivot]
when "3" # Filter
# Build record filter expression
if @edit[:miq_exp] || # Is this stored as an MiqExp object
%w[new copy create].include?(request.parameters["action"]) # or it's a new condition
new_record_filter = @edit[:new][:record_filter]
@edit[:record_filter][:expression] = copy_hash(new_record_filter) if new_record_filter.present?
@expkey = :record_filter
# Initialize the exp array
@edit[@expkey].history.reset(@edit[:record_filter][:expression]) if @edit[:record_filter].history.array.nil?
@edit[:record_filter][:exp_table] = exp_build_table(@edit[:record_filter][:expression])
@edit[:record_filter].prefill_val_types
@edit[:record_filter][:exp_model] = @edit[:new][:model] # Set the model for the expression editor
end
new_display_filter = @edit[:new][:display_filter]
@edit[:display_filter][:expression] = copy_hash(new_display_filter) if new_display_filter.present?
@expkey = :display_filter
# Initialize the exp array
@edit[@expkey].history.reset(@edit[:display_filter][:expression]) if @edit[:display_filter].history.array.nil?
@edit[:display_filter][:exp_table] = exp_build_table(@edit[:display_filter][:expression])
@edit[:display_filter][:exp_model] = "_display_filter_" # Set model for display filter
@expkey = :record_filter # Start with Record Filter showing
if @edit[:new][:perf_interval] && !@edit[:new][:time_profile]
set_time_profile_vars(selected_time_profile_for_pull_down, @edit[:new])
end
when "4" # Summarize
# Build sort chooser arrays(@edit[:new][:fields], :field)
@sortby1 = @edit[:new][:sortby1]
@sortby2 = @edit[:new][:sortby2]
@sort1 = @edit[:new][:field_order].dup
@sort2 = @sort1.dup.delete_if { |s| s[1] == @sortby1.split("__").first }
when "5" # Charts
options = chart_fields_options
if options.empty?
@edit[:new][:chart_column] = nil
else
@edit[:new][:chart_column] = options[0][1] unless options.detect { |_, v| v == @edit[:new][:chart_column] }
end
end
@in_a_form = true
@gtl_url = %w[new copy create].include?(request.parameters["action"]) ? '/new' : '/edit'
end
def reportable_models
MiqReport.reportable_models.collect do |m|
[Dictionary.gettext(m, :type => :model, :notfound => :titleize, :plural => true), m]
end
end
def ensure_perf_interval_defaults
case @edit[:new][:perf_interval]
when "hourly"
@edit[:new][:perf_end] ||= "0"
@edit[:new][:perf_start] ||= 1.day.to_s
when "daily"
@edit[:new][:perf_end] ||= "0"
@edit[:new][:perf_start] ||= 2.days.to_s
end
end
# Reset report column fields if model or interval was changed
def reset_report_col_fields
@edit[:new][:fields] = [] # Clear fields array
@edit[:new][:headers] = {} # Clear headers hash
@edit[:new][:pivot] = ReportController::PivotOptions.new
@edit[:new][:sortby1] = ReportHelper::NOTHING_STRING # Clear sort fields
@edit[:new][:sortby2] = ReportHelper::NOTHING_STRING
@edit[:new][:filter_operator] = nil
@edit[:new][:filter_string] = nil
@edit[:new][:categories] = []
@edit[:new][:graph_type] = nil # Clear graph field
@edit[:new][:chart_mode] = nil
@edit[:new][:chart_column] = nil
@edit[:new][:perf_trend_col] = nil
@edit[:new][:perf_trend_db] = nil
@edit[:new][:perf_trend_pct1] = nil
@edit[:new][:perf_trend_pct2] = nil
@edit[:new][:perf_trend_pct3] = nil
@edit[:new][:perf_limit_col] = nil
@edit[:new][:perf_limit_val] = nil
@edit[:new][:record_filter] = nil # Clear record filter
@edit[:new][:display_filter] = nil # Clear display filter
@edit[:miq_exp] = true
end
TAB_TITLES = {
'edit_1' => N_('Columns'),
'edit_3' => N_('Filter'),
'edit_7' => N_('Preview'),
'edit_8' => N_('Consolidation'),
'edit_2' => N_('Formatting'),
'edit_9' => N_('Styling'),
'edit_4' => N_('Summary'),
'edit_5' => N_('Charts'),
}.freeze
def build_tabs
tab_indexes = if @edit[:new][:model] == ApplicationController::TREND_MODEL
%w[edit_1 edit_3 edit_7]
elsif Chargeback.db_is_chargeback?(@edit[:new][:model].to_s)
%w[edit_1 edit_2 edit_3 edit_7]
else
%w[edit_1 edit_8 edit_2 edit_9 edit_3 edit_4 edit_5 edit_7]
end
@tabs = TAB_TITLES.slice(*tab_indexes).transform_values! { |value| _(value) }.to_a
tab = @sb[:miq_tab].split("_")[1] # Get the tab number of the active tab
@active_tab = "edit_#{tab}"
end
# Get variables from edit form
def get_form_vars
@assigned_filters = []
gfv_report_fields # Global report fields
gfv_move_cols_buttons # Move cols buttons
gfv_model # Model changes
gfv_trend # Trend fields
gfv_performance # Performance fields
gfv_chargeback # Chargeback fields
gfv_charts # Charting fields
gfv_pivots # Consolidation fields
gfv_sort # Summary fields
# Check for key prefixes (params starting with certain keys)
params.each do |key, value|
# See if any headers were sent in
@edit[:new][:headers][key.split("_")[1..-1].join("_")] = value if key.split("_").first == "hdr"
# See if any formats were sent in
if key.split("_").first == "fmt"
key2 = key.gsub("___", ".") # Put period sub table separator back into the key
@edit[:new][:col_formats][key2.split("_")[1..-1].join("_")] = value.blank? ? nil : value.to_sym
@formatting_changed = value.blank?
end
# See if any group calculation checkboxes were sent in
gfv_key_group_calculations(key, value) if key.split("_").first == "calc"
# See if any pivot calculation checkboxes were sent in
gfv_key_pivot_calculations(key, value) if key.split("_").first == "pivotcalc"
# Check for style fields
prefix = key.split("_").first
gfv_key_style(key, value) if prefix && prefix.starts_with?("style")
end
end
# Handle params starting with "calc"
def gfv_key_group_calculations(key, value)
field = @edit[:new][:field_order][key.split("_").last.to_i].last # Get the field name
@edit[:new][:col_options][field_to_col(field)] = {
:grouping => value.split(",").sort.map(&:to_sym).reject { |a| a == :null }
}
end
# Handle params starting with "pivotcalc"
def gfv_key_pivot_calculations(key, value)
field = @edit[:new][:fields][key.split("_").last.to_i].last # Get the field name
@edit[:pivot_cols][field] = []
value.split(',').sort.map(&:to_sym).each do |agg|
@edit[:pivot_cols][field] << agg
# Create new header from original header + aggregate function
@edit[:new][:headers][field + "__#{agg}"] = @edit[:new][:headers][field] + " (#{agg.to_s.titleize})"
end
build_field_order
end
# Handle params starting with "style"
def gfv_key_style(key, value)
parm, f_idx, s_idx = key.split("_") # Get the parm type, field index, and style index
f_idx = f_idx.to_i
s_idx = s_idx.to_i
f = @edit[:new][:field_order][f_idx] # Get the field element
field_sub_type = MiqExpression.get_col_info(f.last)[:format_sub_type]
field_data_type = MiqExpression.get_col_info(f.last)[:data_type]
field_name = MiqExpression.parse_field_or_tag(f.last).report_column
case parm
when "style" # New CSS class chosen
if value.blank?
@edit[:new][:col_options][field_name][:style].delete_at(s_idx)
@edit[:new][:col_options][field_name].delete(:style) if @edit[:new][:col_options][field_name][:style].empty?
@edit[:new][:col_options].delete(field_name) if @edit[:new][:col_options][field_name].empty?
else
@edit[:new][:col_options][field_name] ||= {}
@edit[:new][:col_options][field_name][:style] ||= []
@edit[:new][:col_options][field_name][:style][s_idx] ||= {}
@edit[:new][:col_options][field_name][:style][s_idx][:class] = value.to_sym
ovs = case field_data_type
when :boolean
%w[DEFAULT true]
when :integer, :float
["DEFAULT", "", MiqExpression::FORMAT_SUB_TYPES.fetch_path(field_sub_type, :units) ? MiqExpression::FORMAT_SUB_TYPES.fetch_path(field_sub_type, :units).first : nil]
else
["DEFAULT", ""]
end
op ||= ovs[0]
val ||= ovs[1]
suffix ||= ovs[2]
@edit[:new][:col_options][field_name][:style][s_idx][:operator] ||= op
@edit[:new][:col_options][field_name][:style][s_idx][:value] ||= val
@edit[:new][:col_options][field_name][:style][s_idx][:value_suffix] ||= suffix if suffix
end
@refresh_div = "styling_div"
@refresh_partial = "form_styling"
when "styleop" # New operator chosen
@edit[:new][:col_options][field_name][:style][s_idx][:operator] = value
if value == "DEFAULT"
@edit[:new][:col_options][field_name][:style][s_idx].delete(:value) # Remove value key
# Remove all style array elements after this one
((s_idx + 1)...@edit[:new][:col_options][field_name][:style].length).each_with_index do |_i, i_idx|
@edit[:new][:col_options][field_name][:style].delete_at(i_idx)
end
elsif value.include?("NIL") || value.include?("EMPTY")
@edit[:new][:col_options][field_name][:style][s_idx].delete(:value) # Remove value key
elsif %i[datetime date].include?(field_data_type)
@edit[:new][:col_options][field_name][:style][s_idx][:value] = ApplicationController::Filter::EXP_TODAY # Set default date value
elsif [:boolean].include?(field_data_type)
@edit[:new][:col_options][field_name][:style][s_idx][:value] = true # Set default boolean value
else
@edit[:new][:col_options][field_name][:style][s_idx][:value] = "" # Set default value
end
@refresh_div = "styling_div"
@refresh_partial = "form_styling"
when "styleval" # New value chosen
@edit[:new][:col_options][field_name][:style][s_idx][:value] = value
when "stylesuffix" # New suffix chosen
@edit[:new][:col_options][field_name][:style][s_idx][:value_suffix] = value.to_sym
@refresh_div = "styling_div"
@refresh_partial = "form_styling"
end
end
def gfv_report_fields
copy_params_if_present(@edit[:new], params, %i[pdf_page_size name title])
if params[:chosen_queue_timeout]
@edit[:new][:queue_timeout] = params[:chosen_queue_timeout].blank? ? nil : params[:chosen_queue_timeout].to_i
end
@edit[:new][:row_limit] = params[:row_limit].presence || ""
end
def gfv_move_cols_buttons
case params[:button]
when 'right' then move_cols_right
when 'left' then move_cols_left
when 'up' then move_cols_up
when 'down' then move_cols_down
when 'top' then move_cols_top
when 'bottom' then move_cols_bottom
end && build_field_order
end
def gfv_model
if params[:chosen_model] && # Check for db table changed
params[:chosen_model] != @edit[:new][:model]
@edit[:new][:model] = params[:chosen_model]
@edit[:new][:perf_interval] = nil # Clear performance interval setting
@edit[:new][:tz] = nil
if %i[performance trend].include?(model_report_type(@edit[:new][:model]))
@edit[:new][:perf_interval] ||= "daily" # Default to Daily
@edit[:new][:perf_avgs] ||= "time_interval"
@edit[:new][:tz] = session[:user_tz]
ensure_perf_interval_defaults
end
if Chargeback.db_is_chargeback?(@edit[:new][:model])
@edit[:new][:cb_model] = Chargeback.report_cb_model(@edit[:new][:model])
@edit[:new][:cb_interval] ||= "daily" # Default to Daily
@edit[:new][:cb_interval_size] ||= 1
@edit[:new][:cb_end_interval_offset] ||= 1
@edit[:new][:cb_groupby] ||= "date" # Default to Date grouping
@edit[:new][:tz] = session[:user_tz]
@edit[:new][:cb_include_metrics] = true if @edit[:new][:model] == 'ChargebackVm'
@edit[:new][:method_for_allocated_metrics] = default_chargeback_allocated_method
@edit[:new][:cumulative_rate_calculation] ||= false
end
reset_report_col_fields
build_edit_screen
@refresh_div = "form_div"
@refresh_partial = "form"
end
end
def gfv_trend
if params[:chosen_trend_col]
@edit[:new][:perf_interval] ||= "daily" # Default to Daily
@edit[:new][:perf_target_pct1] ||= 100 # Default to 100%
if params[:chosen_trend_col] == "<Choose>"
@edit[:new][:perf_trend_db] = nil
@edit[:new][:perf_trend_col] = nil
else
@edit[:new][:perf_trend_db], @edit[:new][:perf_trend_col] = params[:chosen_trend_col].split("-")
if MiqExpression.reporting_available_fields(@edit[:new][:model], @edit[:new][:perf_interval]).find { |af| af.last == params[:chosen_trend_col] }.first.include?("(%)")
@edit[:new][:perf_limit_val] = 100
@edit[:new][:perf_limit_col] = nil
@edit[:percent_col] = true
else
@edit[:percent_col] = false
@edit[:new][:perf_limit_val] = nil
end
ensure_perf_interval_defaults
@edit[:limit_cols] = VimPerformanceTrend.trend_limit_cols(@edit[:new][:perf_trend_db], @edit[:new][:perf_trend_col], @edit[:new][:perf_interval])
end
@refresh_div = "columns_div"
@refresh_partial = "form_columns"
# @edit[:limit_cols] = VimPerformanceTrend.trend_limit_cols(@edit[:new][:perf_trend_db], @edit[:new][:perf_trend_col], @edit[:new][:perf_interval])
elsif params[:chosen_limit_col]
if params[:chosen_limit_col] == "<None>"
@edit[:new][:perf_limit_col] = nil
else
@edit[:new][:perf_limit_col] = params[:chosen_limit_col]
@edit[:new][:perf_limit_val] = nil
end
@refresh_div = "columns_div"
@refresh_partial = "form_columns"
elsif params[:chosen_limit_val]
@edit[:new][:perf_limit_val] = params[:chosen_limit_val]
elsif params[:percent1]
@edit[:new][:perf_target_pct1] = params[:percent1].to_i
elsif params[:percent2]
@edit[:new][:perf_target_pct2] = params[:percent2] == "<None>" ? nil : params[:percent2].to_i
elsif params[:percent3]
@edit[:new][:perf_target_pct3] = params[:percent3] == "<None>" ? nil : params[:percent3].to_i
end
end
def gfv_performance
if params[:chosen_interval]
@edit[:new][:perf_interval] = params[:chosen_interval]
@edit[:new][:perf_start] = nil # Clear start/end offsets
@edit[:new][:perf_end] = nil
ensure_perf_interval_defaults
reset_report_col_fields
@refresh_div = "form_div"
@refresh_partial = "form"
elsif params[:perf_avgs]
@edit[:new][:perf_avgs] = params[:perf_avgs]
elsif params[:chosen_start]
@edit[:new][:perf_start] = params[:chosen_start]
elsif params[:chosen_end]
@edit[:new][:perf_end] = params[:chosen_end]
elsif params[:chosen_tz]
@edit[:new][:tz] = params[:chosen_tz]
elsif params.key?(:chosen_time_profile)
@edit[:new][:time_profile] = params[:chosen_time_profile].blank? ? nil : params[:chosen_time_profile].to_i
@refresh_div = "filter_div"
@refresh_partial = "form_filter"
end
end
def gfv_chargeback
# Chargeback options
if params.key?(:cb_show_typ)
@edit[:new][:cb_show_typ] = params[:cb_show_typ].presence
@refresh_div = "filter_div"
@refresh_partial = "form_filter"
elsif params.key?(:cb_tag_cat)
@refresh_div = "filter_div"
@refresh_partial = "form_filter"
if params[:cb_tag_cat].blank?
@edit[:new][:cb_tag_cat] = nil
@edit[:new][:cb_tag_value] = nil
else
@edit[:new][:cb_tag_cat] = params[:cb_tag_cat]
@edit[:cb_tags] = entries_hash(params[:cb_tag_cat])
end
elsif params.key?(:cb_include_metrics)
@edit[:new][:cb_include_metrics] = params[:cb_include_metrics] == 'true'
elsif params.key?(:method_for_allocated_metrics)
@edit[:new][:method_for_allocated_metrics] = params[:method_for_allocated_metrics].try(:to_sym) || default_chargeback_allocated_method
elsif params.key?(:cumulative_rate_calculation)
@edit[:new][:cumulative_rate_calculation] = params[:cumulative_rate_calculation] == 'true'
elsif params.key?(:cb_owner_id)
@edit[:new][:cb_owner_id] = params[:cb_owner_id].presence
elsif params.key?(:cb_tenant_id)
@edit[:new][:cb_tenant_id] = params[:cb_tenant_id].presence
elsif params.key?(:cb_tag_value)
@edit[:new][:cb_tag_value] = params[:cb_tag_value].presence
elsif params.key?(:cb_entity_id)
@edit[:new][:cb_entity_id] = params[:cb_entity_id].presence
elsif params.key?(:cb_provider_id)
@edit[:new][:cb_provider_id] = params[:cb_provider_id].presence
@edit[:new][:cb_entity_id] = "all"
build_edit_screen
@refresh_div = "form_div"
@refresh_partial = "form"
elsif params.key?(:cb_groupby)
@edit[:new][:cb_groupby] = params[:cb_groupby]
@refresh_div = "filter_div"
@refresh_partial = "form_filter"
elsif params.key?(:cb_groupby_tag)
@edit[:new][:cb_groupby_tag] = params[:cb_groupby_tag]
elsif params.key?(:cb_groupby_label)
@edit[:new][:cb_groupby_label] = params[:cb_groupby_label]
elsif params[:cb_interval]
@edit[:new][:cb_interval] = params[:cb_interval]
@edit[:new][:cb_interval_size] = 1
@edit[:new][:cb_end_interval_offset] = 1
@refresh_div = "filter_div"
@refresh_partial = "form_filter"
elsif params[:cb_interval_size]
@edit[:new][:cb_interval_size] = params[:cb_interval_size].to_i
elsif params[:cb_end_interval_offset]
@edit[:new][:cb_end_interval_offset] = params[:cb_end_interval_offset].to_i
end
end
def gfv_charts
if params[:chosen_graph] && params[:chosen_graph] != @edit[:new][:graph_type]
if params[:chosen_graph] == "<No chart>"
@edit[:new][:graph_type] = nil
# Reset other setting to initial settings if choosing <No chart>
@edit[:new][:graph_count] = @edit[:current][:graph_count]
@edit[:new][:graph_other] = @edit[:current][:graph_other]
@edit[:new][:chart_mode] = @edit[:current][:chart_mode]
@edit[:new][:chart_column] = @edit[:current][:chart_column]
else
@edit[:new][:graph_other] = true if @edit[:new][:graph_type].nil? # Reset other setting if choosing first chart
@edit[:new][:graph_type] = params[:chosen_graph] # Save graph type
@edit[:new][:graph_count] ||= ReportController::Reports::Editor.chart_top_values # Reset graph count, if not set
@edit[:new][:chart_mode] ||= 'counts'
@edit[:new][:chart_column] ||= ''
end
@refresh_div = "chart_div"
@refresh_partial = "form_chart"
end
if params[:chart_mode] && params[:chart_mode] != @edit[:new][:chart_mode]
@edit[:new][:chart_mode] = params[:chart_mode]
@refresh_div = "chart_div"
@refresh_partial = "form_chart"
end
if params[:chart_column] && params[:chart_column] != @edit[:new][:chart_column]
@edit[:new][:chart_column] = params[:chart_column]
@refresh_div = "chart_sample_div"
@refresh_partial = "form_chart_sample"
end
if params[:chosen_count] && params[:chosen_count] != @edit[:new][:graph_count]
@edit[:new][:graph_count] = params[:chosen_count].to_i
@refresh_div = "chart_sample_div"
@refresh_partial = "form_chart_sample"
end
if params[:chosen_other] # If a chart is showing, set the other setting based on check box present
chosen = (params[:chosen_other].to_s == "1")
if @edit[:new][:graph_other] != chosen
@edit[:new][:graph_other] = chosen
@refresh_div = "chart_sample_div"
@refresh_partial = "form_chart_sample"
end
end
end
def gfv_pivots
@edit[:new][:pivot] ||= ReportController::PivotOptions.new
@edit[:new][:pivot].update(params)
if params[:chosen_pivot1] || params[:chosen_pivot2] || params[:chosen_pivot3]
if @edit[:new][:pivot].by1 == ReportHelper::NOTHING_STRING
@edit[:pivot_cols] = {} # Clear pivot_cols if no pivot grouping fields selected
else
@edit[:pivot_cols].delete(@edit[:new][:pivot].by1) # Remove any pivot grouping fields from pivot cols
@edit[:pivot_cols].delete(@edit[:new][:pivot].by2)
@edit[:pivot_cols].delete(@edit[:new][:pivot].by3)
end
build_field_order
@refresh_div = "consolidate_div"
@refresh_partial = "form_consolidate"
end
end
def gfv_sort
@edit[:new][:order] = params[:sort_order] if params[:sort_order]
if params[:sort_group] # If grouping changed,
@edit[:new][:group] = params[:sort_group]
@refresh_div = "sort_div" # Resend the sort tab
@refresh_partial = "form_sort"
if @edit[:new][:chart_mode] == 'values' && !chart_mode_values_allowed?
@edit[:new][:chart_mode] = 'counts'
end
end
@edit[:new][:hide_details] = (params[:hide_details].to_s == "1") if params[:hide_details]
if params[:chosen_sort1] && params[:chosen_sort1] != @edit[:new][:sortby1].split("__").first
# Remove any col options for any existing sort + suffix
@edit[:new][:col_options].delete(@edit[:new][:sortby1].split("-").last) if @edit[:new][:sortby1].split("__")[1]
@edit[:new][:sortby1] = params[:chosen_sort1]
@edit[:new][:sortby2] = ReportHelper::NOTHING_STRING if params[:chosen_sort1] == ReportHelper::NOTHING_STRING || params[:chosen_sort1] == @edit[:new][:sortby2].split("__").first
@refresh_div = "sort_div"
@refresh_partial = "form_sort"
elsif params[:chosen_sort2] && params[:chosen_sort2] != @edit[:new][:sortby2].split("__").first
@edit[:new][:sortby2] = params[:chosen_sort2]
# Look at the 1st sort suffix (ie. month, day_of_week, etc)
elsif params[:sort1_suffix] && params[:sort1_suffix].to_s != @edit[:new][:sortby1].split("__")[1].to_s
# Remove any col options for any existing sort + suffix
@edit[:new][:col_options].delete(@edit[:new][:sortby1].split("-").last) if @edit[:new][:sortby1].split("__")[1]
@edit[:new][:sortby1] = @edit[:new][:sortby1].split("__").first +
(params[:sort1_suffix].blank? ? "" : "__#{params[:sort1_suffix]}")
# Look at the 2nd sort suffix (ie. month, day_of_week, etc)
elsif params[:sort2_suffix] && params[:sort2_suffix].to_s != @edit[:new][:sortby2].split("__")[1].to_s
# Remove any col options for any existing sort + suffix
@edit[:new][:col_options].delete(@edit[:new][:sortby2].split("-").last) if @edit[:new][:sortby2].split("__")[1]
@edit[:new][:sortby2] = @edit[:new][:sortby2].split("__").first + "__" + params[:sort2_suffix]
@edit[:new][:sortby2] = @edit[:new][:sortby2].split("__").first +
(params[:sort2_suffix].blank? ? "" : "__#{params[:sort2_suffix]}")
# Look at the break format
else
co_key1 = @edit[:new][:sortby1].split("-").last
if params[:break_format] &&
params[:break_format].to_s != @edit[:new].fetch_path(:col_options, co_key1)
if params[:break_format].blank? || # Remove format and col key (if empty)
params[:break_format].to_sym == MiqReport.get_col_info(@edit[:new][:sortby1])[:default_format]
if @edit[:new][:col_options][co_key1]
@edit[:new][:col_options][co_key1].delete(:break_format)
@edit[:new][:col_options].delete(co_key1) if @edit[:new][:col_options][co_key1].empty?
end
else # Add col and format to col_options
@edit[:new][:col_options][co_key1] ||= {}
@edit[:new][:col_options][co_key1][:break_format] = params[:break_format].to_sym
end
end
end
# Clear/set up the default break label
sort1 = @edit[:new][:sortby1].split("-").last if @edit[:new][:sortby1].present?
if @edit[:new][:group] == "No" # Clear any existing break label
if @edit[:new].fetch_path(:col_options, sort1, :break_label)
@edit[:new][:col_options][sort1].delete(:break_label)
@edit[:new][:col_options].delete(sort1) if @edit[:new][:col_options][sort1].empty?
end
else # Create a break label, if none there already
unless @edit[:new].fetch_path(:col_options, sort1, :break_label)
@edit[:new][:col_options][sort1] ||= {}
sort, suffix = @edit[:new][:sortby1].split("__")
@edit[:new][:col_options][sort1][:break_label] =
@edit[:new][:field_order].collect { |f| f.first if f.last == sort }.compact.join.strip +
(suffix ? " (%{suffixes})" % {:suffixes => MiqReport.date_time_break_suffixes.collect { |s| _(s.first) if s.last == suffix }.compact.join} : "") +
": "
end
end
# TODO: Not allowing user to change break label until editor is changed to not use form observe
# if params[:break_label]
# @edit[:new][:col_options][@edit[:new][:sortby1].split("-").last] ||= Hash.new
# @edit[:new][:col_options][@edit[:new][:sortby1].split("-").last][:break_label] == params[:break_label]
# end
end
def cashed_reporting_available_fields
@reporting_available_fields ||= {}
@reporting_available_fields[@edit[:new][:model]] ||= MiqExpression.reporting_available_fields(@edit[:new][:model], @edit[:new][:perf_interval])
end
def reporting_available_fields_clear_cash
@reporting_available_fields = nil
end
def move_cols_right
if params[:available_fields].blank? || params[:available_fields][0] == ""
add_flash(_("No fields were selected to move down"), :error)
elsif params[:available_fields].length + @edit[:new][:fields].length > MAX_REPORT_COLUMNS
add_flash(_("Fields not added: Adding the selected %{count} fields will exceed the maximum of %{max} fields") % {:count => params[:available_fields].length + @edit[:new][:fields].length, :max => MAX_REPORT_COLUMNS},
:error)
else
reporting_available_fields_clear_cash
cashed_reporting_available_fields.each do |af| # Go thru all available columns
# See if this column was selected to move or Only move if it's not there already
next if !params[:available_fields].include?(af[1]) || @edit[:new][:fields].include?(af)
@edit[:new][:fields].push(af) # Add it to the new fields list
if af[0].include?(":") && !af[1].include?(CustomAttributeMixin::CUSTOM_ATTRIBUTES_PREFIX) # Not a base column
table = af[0].split(" : ")[0].split(".")[-1] # Get the table name
table = table.singularize unless table == "OS" # Singularize, except "OS"
temp = af[0].split(" : ")[1]
temp_header = table == temp.split(" ")[0] ? af[0].split(" : ")[1] : table + " " + af[0].split(" : ")[1]
else
temp_header = af[0].strip # Base column, just use it without leading space
end
@edit[:new][:headers][af[1]] = temp_header # Add the column title to the headers hash
end
@refresh_div = "column_lists"
@refresh_partial = "column_lists"
end
end
def move_cols_left
if params[:selected_fields].blank? || params[:selected_fields][0] == ""
add_flash(_("No fields were selected to move up"), :error)
elsif display_filter_contains?(params[:selected_fields])
add_flash(_("No fields were moved up"), :error)
else
@edit[:new][:fields].each do |nf| # Go thru all new fields
next unless params[:selected_fields].include?(nf.last) # See if this col was selected to move
# Clear out headers and formatting
@edit[:new][:headers].delete(nf.last) # Delete the column name from the headers hash
@edit[:new][:headers].delete_if { |k, _v| k.starts_with?("#{nf.last}__") } # Delete pivot calc keys
@edit[:new][:col_formats].delete(nf.last) # Delete the column name from the col_formats hash
@edit[:new][:col_formats].delete_if { |k, _v| k.starts_with?("#{nf.last}__") } # Delete pivot calc keys
# Clear out pivot field options
@edit[:new][:pivot].drop_from_selection(nf.last)
@edit[:pivot_cols].delete(nf.last) # Delete the column name from the pivot_cols hash
# Clear out sort options
if @edit[:new][:sortby1] && nf.last == @edit[:new][:sortby1].split("__").first # If deleting the first sort field
if MiqReport.is_break_suffix?(@edit[:new][:sortby1].split("__")[1]) # If sort has a break suffix
@edit[:new][:col_options].delete(field_to_col(@edit[:new][:sortby1])) # Remove the <col>__<suffix> from col_options
end
unless @edit[:new][:group] == "No" # If we were grouping, remove all col_options :group keys
@edit[:new][:col_options].each do |co_key, co_val|
co_val.delete(:grouping) # Remove :group key
@edit[:new][:col_options].delete(co_key) if co_val.empty? # Remove the col, if empty
end
end
@edit[:new][:sortby1] = ReportHelper::NOTHING_STRING
@edit[:new][:sortby2] = ReportHelper::NOTHING_STRING
end
if @edit[:new][:sortby1] && nf.last == @edit[:new][:sortby2].split("__").first # If deleting the second sort field
@edit[:new][:sortby2] = ReportHelper::NOTHING_STRING
end
# Clear out selected chart data column
@edit[:new][:chart_column] = nil if @edit[:new][:chart_column] == nf.last
@edit[:new][:col_options].delete(field_to_col(nf.last)) # Remove this column from the col_options hash
end
@edit[:new][:fields].delete_if { |nf| params[:selected_fields].include?(nf.last) } # Remove selected fields
@refresh_div = "column_lists"
@refresh_partial = "column_lists"
end
end
# See if any of the fields passed in are present in the display filter expression
def display_filter_contains?(fields)
return false if @edit[:new][:display_filter].nil? # No display filter defined
exp = @edit[:new][:display_filter].inspect
@edit[:new][:fields].each do |f| # Go thru all of the selected fields
if fields.include?(f.last) && exp.include?(f.last) # Is this field being removed?
add_flash(_("%{name} is currently being used in the Display Filter") % {:name => f.first}, :error)
end
end
!@flash_array.nil?
end
def selected_consecutive?
first_idx = last_idx = 0
@edit[:new][:fields].each_with_index do |nf, idx|
first_idx = idx if nf[1] == params[:selected_fields].first
if nf[1] == params[:selected_fields].last
last_idx = idx
break
end
end
if last_idx - first_idx + 1 > params[:selected_fields].length
return [false, first_idx, last_idx]
else
return [true, first_idx, last_idx]
end
end
# Set record variables to new values
def set_record_vars(rpt)
# Set the simple string/number fields
rpt.template_type = "report"
rpt.name = @edit[:new][:name].to_s.strip
rpt.title = @edit[:new][:title].to_s.strip
rpt.db = @edit[:new][:model]
rpt.rpt_group = @edit[:new][:rpt_group]
rpt.rpt_type = @edit[:new][:rpt_type]
rpt.priority = @edit[:new][:priority]
rpt.categories = @edit[:new][:categories]
rpt.col_options = @edit[:new][:col_options]
rpt.order = @edit[:new][:sortby1].nil? ? nil : @edit[:new][:order]
# Set the graph fields
if @edit[:new][:sortby1] == ReportHelper::NOTHING_STRING || @edit[:new][:graph_type].nil?
rpt.dims = nil
rpt.graph = nil
else
rpt.dims = if @edit[:new][:graph_type] =~ /^(Pie|Donut)/ # Pie and Donut charts must be set to 1 dimension
1
else
@edit[:new][:sortby2] == ReportHelper::NOTHING_STRING ? 1 : 2 # Set dims to 1 or 2 based on presence of sortby2
end
if @edit[:new][:chart_mode] == 'values' && @edit[:new][:chart_column].blank?
options = chart_fields_options
@edit[:new][:chart_column] = options[0][1] unless options.empty?
end
rpt.graph = {
:type => @edit[:new][:graph_type],
:mode => @edit[:new][:chart_mode],
:column => @edit[:new][:chart_column],
:count => @edit[:new][:graph_count],
:other => @edit[:new][:graph_other],
}
end
# Set the conditions field (expression)
rpt.conditions = if !@edit[:new][:record_filter].nil? && @edit[:new][:record_filter]["???"].nil?
MiqExpression.new(@edit[:new][:record_filter])
end
# Set the display_filter field (expression)
rpt.display_filter = if !@edit[:new][:display_filter].nil? && @edit[:new][:display_filter]["???"].nil?
MiqExpression.new(@edit[:new][:display_filter])
end
# Set the performance options
rpt.db_options = {}
if model_report_type(rpt.db) == :performance
rpt.db_options[:interval] = @edit[:new][:perf_interval]
rpt.db_options[:calc_avgs_by] = @edit[:new][:perf_avgs]
rpt.db_options[:end_offset] = @edit[:new][:perf_end].to_i
rpt.db_options[:start_offset] = @edit[:new][:perf_end].to_i + @edit[:new][:perf_start].to_i
elsif model_report_type(rpt.db) == :trend
rpt.db_options[:rpt_type] = "trend"
rpt.db_options[:interval] = @edit[:new][:perf_interval]
rpt.db_options[:end_offset] = @edit[:new][:perf_end].to_i
rpt.db_options[:start_offset] = @edit[:new][:perf_end].to_i + @edit[:new][:perf_start].to_i
rpt.db_options[:trend_db] = @edit[:new][:perf_trend_db]
rpt.db_options[:trend_col] = @edit[:new][:perf_trend_col]
rpt.db_options[:limit_col] = @edit[:new][:perf_limit_col] if @edit[:new][:perf_limit_col]
rpt.db_options[:limit_val] = @edit[:new][:perf_limit_val] if @edit[:new][:perf_limit_val]
rpt.db_options[:target_pcts] = []
rpt.db_options[:target_pcts].push(@edit[:new][:perf_target_pct1])
rpt.db_options[:target_pcts].push(@edit[:new][:perf_target_pct2]) if @edit[:new][:perf_target_pct2]
rpt.db_options[:target_pcts].push(@edit[:new][:perf_target_pct3]) if @edit[:new][:perf_target_pct3]
elsif Chargeback.db_is_chargeback?(rpt.db)
rpt.db_options[:rpt_type] = @edit[:new][:model]
options = {} # CB options go in db_options[:options] key
options[:interval] = @edit[:new][:cb_interval]
options[:interval_size] = @edit[:new][:cb_interval_size]
options[:end_interval_offset] = @edit[:new][:cb_end_interval_offset]
if @edit[:new][:cb_show_typ] == "owner"
options[:owner] = @edit[:new][:cb_owner_id]
elsif @edit[:new][:cb_show_typ] == "tenant"
options[:tenant_id] = @edit[:new][:cb_tenant_id]
elsif @edit[:new][:cb_show_typ] == "tag"
if @edit[:new][:cb_tag_cat] && @edit[:new][:cb_tag_value]
options[:tag] = parse_tag_categories(@edit[:new][:cb_tag_cat], @edit[:new][:cb_tag_value])
end
elsif @edit[:new][:cb_show_typ] == "entity"
options[:provider_id] = @edit[:new][:cb_provider_id]
options[:entity_id] = @edit[:new][:cb_entity_id]
end
options[:method_for_allocated_metrics] = @edit[:new][:method_for_allocated_metrics]
options[:include_metrics] = @edit[:new][:cb_include_metrics]
options[:cumulative_rate_calculation] = @edit[:new][:cumulative_rate_calculation]
options[:groupby] = @edit[:new][:cb_groupby]
options[:groupby_tag] = @edit[:new][:cb_groupby] == 'tag' ? (@edit[:new][:cb_groupby_tag].kind_of?(String) ? @edit[:new][:cb_groupby_tag].split(',') : @edit[:new][:cb_groupby_tag]) : nil
options[:groupby_label] = @edit[:new][:cb_groupby] == 'label' ? @edit[:new][:cb_groupby_label] : nil
rpt.db_options[:options] = options
end
rpt.time_profile_id = @edit[:new][:time_profile]
if @edit[:new][:time_profile]
time_profile = TimeProfile.find(@edit[:new][:time_profile])
rpt.tz = time_profile.tz
end
# Set the line break group field
rpt.group = if @edit[:new][:sortby1] == ReportHelper::NOTHING_STRING # If no sort fields
nil # Clear line break group
else # Otherwise, check the setting
case @edit[:new][:group]
when "Yes"
"y"
when "Counts"
"c"
end
end
# Set defaults, if not present
rpt.rpt_group ||= "Custom"
rpt.rpt_type ||= "Custom"
rpt.cols = []
rpt.col_order = []
rpt.col_formats = []
rpt.headers = []
rpt.include = {}
rpt.sortby = @edit[:new][:sortby1] == ReportHelper::NOTHING_STRING ? nil : [] # Clear sortby if sortby1 not present, else set up array
# Add in the chargeback static fields
if Chargeback.db_is_chargeback?(rpt.db) # For chargeback, add in specific chargeback report options
tag_header = @edit[:cb_cats].try(:[], @edit[:new][:cb_groupby_tag])
groupby_label = @edit[:new][:cb_groupby_label]
chargeback_model = @edit[:new][:model].constantize
rpt = chargeback_model.set_chargeback_report_options(rpt, @edit[:new][:cb_groupby], tag_header, groupby_label, @edit[:new][:tz])
end
# Remove when we support user sorting of trend reports
if rpt.db == ApplicationController::TREND_MODEL
rpt.sortby = ["resource_name"]
rpt.order = "Ascending"
end
# Build column related report fields
@pg1 = @pg2 = @pg3 = nil # Init the pivot group cols
@edit[:new][:fields].each do |field_entry| # Go thru all of the fields
field = field_entry[1] # Get the encoded fully qualified field name
if @edit[:new][:pivot].by1 != ReportHelper::NOTHING_STRING && # If we are doing pivoting and
@edit[:pivot_cols].key?(field) # this is a pivot calc column
@edit[:pivot_cols][field].each do |calc_typ| # Add header/format/col_order for each calc type
rpt.headers.push(@edit[:new][:headers][field + "__#{calc_typ}"])
rpt.col_formats.push(@edit[:new][:col_formats][field + "__#{calc_typ}"])
add_field_to_col_order(rpt, field + "__#{calc_typ}")
end
else # Normal field, set header/format/col_order
rpt.headers.push(@edit[:new][:headers][field])
rpt.col_formats.push(@edit[:new][:col_formats][field])
add_field_to_col_order(rpt, field)
end
end
rpt.rpt_options ||= {}
rpt.rpt_options.delete(:pivot)
unless @pg1.nil? # Build the pivot group_cols array
rpt.rpt_options[:pivot] = {}
rpt.rpt_options[:pivot][:group_cols] = []
rpt.rpt_options[:pivot][:group_cols].push(@pg1)
rpt.rpt_options[:pivot][:group_cols].push(@pg2) unless @pg2.nil?
rpt.rpt_options[:pivot][:group_cols].push(@pg3) unless @pg3.nil?
end
if @edit[:new][:group] != "No" || @edit[:new][:row_limit].blank?
rpt.rpt_options.delete(:row_limit)
else
rpt.rpt_options[:row_limit] = @edit[:new][:row_limit].to_i
end
# Add pdf page size to rpt_options
rpt.rpt_options ||= {}
rpt.rpt_options[:pdf] ||= {}
rpt.rpt_options[:pdf][:page_size] = @edit[:new][:pdf_page_size] || DEFAULT_PDF_PAGE_SIZE
rpt.rpt_options[:queue_timeout] = @edit[:new][:queue_timeout]
# Add hide detail rows option, if grouping
if rpt.group.nil?
rpt.rpt_options.delete(:summary)
else
rpt.rpt_options[:summary] ||= {}
rpt.rpt_options[:summary][:hide_detail_rows] = @edit[:new][:hide_details]
end
user = current_user
rpt.user = user
rpt.miq_group = user.current_group
rpt.add_includes_for_virtual_custom_attributes
end
def add_field_to_col_order(rpt, field)
# Get the sort columns, removing the suffix if it exists
sortby1 = if MiqReport.is_break_suffix?(@edit[:new][:sortby1].split("__")[1])
@edit[:new][:sortby1].split("__").first
else
@edit[:new][:sortby1]
end
sortby2 = if MiqReport.is_break_suffix?(@edit[:new][:sortby2].split("__")[1])
@edit[:new][:sortby2].split("__").first
else
@edit[:new][:sortby2]
end
# Has a period, so it's an include
if field.include?(".") && !field.include?(CustomAttributeMixin::CUSTOM_ATTRIBUTES_PREFIX)
tables = field.split("-")[0].split(".")[1..-1] # Get the list of tables from before the hyphen
inc_hash = rpt.include # Start at the main hash
tables.each_with_index do |table, idx|
inc_hash[table] ||= {} # Create hash for the table, if it's not there already
if idx == tables.length - 1 # We're at the end of the field name, so add the column
inc_hash[table]["columns"] ||= [] # Create the columns array for this table
f = field.split("-")[1].split("__").first # Grab the field name after the hyphen, before the "__"
inc_hash[table]["columns"].push(f) unless inc_hash[table]["columns"].include?(f) # Add the field to the columns, if not there
table_field = tables.join('.') + "." + field.split("-")[1]
rpt.col_order.push(table_field) # Add the table.field to the col_order array
if field == sortby1 # Is this the first sort field?
rpt.sortby = [table_field] + rpt.sortby # Put the field first in the sortby array
elsif field == @edit[:new][:sortby2] # Is this the second sort field?
rpt.sortby.push(table_field) # Add the field to the sortby array
end
if field == @edit[:new][:pivot].by1 # Save the group fields
@pg1 = table_field
elsif field == @edit[:new][:pivot].by2
@pg2 = table_field
elsif field == @edit[:new][:pivot].by3
@pg3 = table_field
end
else # Set up for the next embedded include hash
inc_hash[table]["include"] ||= {} # Create include hash for next level
inc_hash = inc_hash[table]["include"] # Point to the new hash
end
end
else # No period, this is a main table column
if field.include?("__") # Check for pivot calculated field
f = field.split("-")[1].split("__").first # Grab the field name after the hyphen, before the "__"
rpt.cols.push(f) unless rpt.cols.include?(f) # Add the original field, if not already there
rpt.col_order.push(field.split("-")[1]) # Add the field to the col_order array
else
field_column = MiqExpression::Field.parse(field).column
rpt.cols.push(field_column)
rpt.col_order.push(field_column) # Add the field to the col_order array
end
if field == sortby1 # Is this the first sort field?
rpt.sortby = [@edit[:new][:sortby1].split("-")[1]] + rpt.sortby # Put the field first in the sortby array
elsif field == sortby2 # Is this the second sort field?
rpt.sortby.push(@edit[:new][:sortby2].split("-")[1]) # Add the field to the sortby array
end
if field == @edit[:new][:pivot].by1 # Save the group fields
@pg1 = field.split("-")[1]
elsif field == @edit[:new][:pivot].by2
@pg2 = field.split("-")[1]
elsif field == @edit[:new][:pivot].by3
@pg3 = field.split("-")[1]
end
end
end
def tag_category_from(tag_or_tags)
case tag_or_tags
when String
tag_or_tags
when Array
tag_or_tags.first
else
raise "Invalid tag category selected."
end.split("/")[-2]
end
def tag_values_from(tag_or_tags)
case tag_or_tags
when String
tag_or_tags.split("/")[-1]
when Array
tag_or_tags.map { |tag| tag.split("/")[-1] }
else
raise "Invalid tag value selected."
end
end
def parse_tag_categories(category, tag_values)
tag_values = tag_values.split(",") if tag_values.kind_of?(String)
tag_values.map { |tag_value| "/managed/#{category}/#{tag_value}" }
end
# Set form variables for edit
def set_form_vars
@edit = {}
@edit[:rpt_id] = @rpt.id # Save a record id to use it later to look a record
@edit[:rpt_title] = @rpt.title
@edit[:rpt_name] = @rpt.name
@edit[:new] = {}
@edit[:key] = "report_edit__#{@rpt.id || "new"}"
if params[:pressed] == "miq_report_copy"
@edit[:new][:rpt_group] = "Custom"
@edit[:new][:rpt_type] = "Custom"
else
@edit[:new][:rpt_group] = @rpt.rpt_group
@edit[:new][:rpt_type] = @rpt.rpt_type
end
# Get the simple string/number fields
@edit[:new][:name] = @rpt.name
@edit[:new][:title] = @rpt.title
@edit[:new][:model] = @rpt.db
@edit[:new][:priority] = @rpt.priority
@edit[:new][:order] = @rpt.order.presence || "Ascending"
# @edit[:new][:graph] = @rpt.graph
# Replaced above line to handle new graph settings Hash
if @rpt.graph.kind_of?(Hash)
@edit[:new][:graph_type] = @rpt.graph[:type]
@edit[:new][:graph_count] = @rpt.graph[:count]
@edit[:new][:chart_mode] = @rpt.graph[:mode]
@edit[:new][:chart_column] = @rpt.graph[:column]
@edit[:new][:graph_other] = @rpt.graph[:other] ? @rpt.graph[:other] : false
else
@edit[:new][:graph_type] = @rpt.graph
@edit[:new][:graph_count] = ReportController::Reports::Editor.chart_top_values
@edit[:new][:chart_mode] = 'counts'
@edit[:new][:chart_column] = ''
@edit[:new][:graph_other] = true
end
@edit[:new][:dims] = @rpt.dims
@edit[:new][:categories] = @rpt.categories
@edit[:new][:categories] ||= []
@edit[:new][:col_options] = @rpt.col_options.presence || {}
# Initialize options
@edit[:new][:perf_interval] = nil
@edit[:new][:perf_start] = nil
@edit[:new][:perf_end] = nil
@edit[:new][:tz] = nil
@edit[:new][:perf_trend_db] = nil
@edit[:new][:perf_trend_col] = nil
@edit[:new][:perf_limit_col] = nil
@edit[:new][:perf_limit_val] = nil
@edit[:new][:perf_target_pct1] = nil
@edit[:new][:perf_target_pct2] = nil
@edit[:new][:perf_target_pct3] = nil
@edit[:new][:cb_interval] = nil
@edit[:new][:cb_interval_size] = nil
@edit[:new][:cb_end_interval_offset] = nil
@edit[:cb_cats] = categories_hash
if %i[performance trend].include?(model_report_type(@rpt.db))
@edit[:new][:perf_interval] = @rpt.db_options[:interval]
@edit[:new][:perf_avgs] = @rpt.db_options[:calc_avgs_by]
@edit[:new][:perf_end] = @rpt.db_options[:end_offset].to_s
@edit[:new][:perf_start] = (@rpt.db_options[:start_offset] - @rpt.db_options[:end_offset]).to_s
@edit[:new][:tz] = @rpt.tz ? @rpt.tz : session[:user_tz] # Set the timezone, default to user's
if @rpt.time_profile
@edit[:new][:time_profile] = @rpt.time_profile_id
@edit[:new][:time_profile_tz] = @rpt.time_profile.tz
else
set_time_profile_vars(selected_time_profile_for_pull_down, @edit[:new])
end
@edit[:new][:perf_trend_db] = @rpt.db_options[:trend_db]
@edit[:new][:perf_trend_col] = @rpt.db_options[:trend_col]
@edit[:new][:perf_limit_col] = @rpt.db_options[:limit_col]
@edit[:new][:perf_limit_val] = @rpt.db_options[:limit_val]
@edit[:new][:perf_target_pct1], @edit[:new][:perf_target_pct2], @edit[:new][:perf_target_pct3] = @rpt.db_options[:target_pcts]
elsif Chargeback.db_is_chargeback?(@rpt.db)
@edit[:new][:tz] = @rpt.tz ? @rpt.tz : session[:user_tz] # Set the timezone, default to user's
options = @rpt.db_options[:options]
if options.key?(:owner) # Get the owner options
@edit[:new][:cb_show_typ] = "owner"
@edit[:new][:cb_owner_id] = options[:owner]
elsif options.key?(:tenant_id) # Get the tenant options
@edit[:new][:cb_show_typ] = "tenant"
@edit[:new][:cb_tenant_id] = options[:tenant_id]
elsif options.key?(:tag) # Get the tag options
@edit[:new][:cb_show_typ] = "tag"
@edit[:new][:cb_tag_cat] = tag_category_from(options[:tag])
@edit[:new][:cb_tag_value] = tag_values_from(options[:tag])
@edit[:cb_tags] = entries_hash(@edit[:new][:cb_tag_cat])
elsif options.key?(:entity_id)
@edit[:new][:cb_show_typ] = "entity"
@edit[:new][:cb_entity_id] = options[:entity_id]
@edit[:new][:cb_provider_id] = options[:provider_id]
end
# @edit[:new][:cb_include_metrics] = nil - it means YES (YES is default value for new and legacy reports)
@edit[:new][:cb_include_metrics] = options[:include_metrics].nil? || options[:include_metrics]
@edit[:new][:method_for_allocated_metrics] = options[:method_for_allocated_metrics].try(:to_sym) || default_chargeback_allocated_method
@edit[:new][:cumulative_rate_calculation] = options[:cumulative_rate_calculation].nil? || options[:cumulative_rate_calculation]
@edit[:new][:cb_groupby_tag] = options[:groupby_tag] if options.key?(:groupby_tag)
@edit[:new][:cb_groupby_label] = options[:groupby_label] if options.key?(:groupby_label)
@edit[:new][:cb_model] = Chargeback.report_cb_model(@rpt.db)
@edit[:new][:cb_interval] = options[:interval]
@edit[:new][:cb_interval_size] = options[:interval_size]
@edit[:new][:cb_end_interval_offset] = options[:end_interval_offset]
@edit[:new][:cb_groupby] = options[:groupby]
cb_entities_by_provider if [ChargebackContainerImage, ChargebackContainerProject, MeteringContainerImage, MeteringContainerProject].include?(@rpt.db.safe_constantize)
end
# Build trend limit cols array
if model_report_type(@rpt.db) == :trend
@edit[:limit_cols] = VimPerformanceTrend.trend_limit_cols(@edit[:new][:perf_trend_db], @edit[:new][:perf_trend_col], @edit[:new][:perf_interval])
end
if %i[performance trend].include?(model_report_type(@rpt.db))
ensure_perf_interval_defaults
end
expkey = :record_filter
@edit[expkey] ||= ApplicationController::Filter::Expression.new
@edit[expkey][:record_filter] = [] # Store exps in an array
@edit[expkey][:expression] = {"???" => "???"} # Set as new exp element
# Get the conditions MiqExpression
if @rpt.conditions.kind_of?(MiqExpression)
@edit[:new][:record_filter] = @rpt.conditions.exp
@edit[:miq_exp] = true
elsif @rpt.conditions.nil?
@edit[:new][:record_filter] = nil
@edit[:new][:record_filter] = @edit[expkey][:expression] # Copy to new exp
@edit[:miq_exp] = true
end
# Get the display_filter MiqExpression
@edit[:new][:display_filter] = @rpt.display_filter.nil? ? nil : @rpt.display_filter.exp
expkey = :display_filter
@edit[expkey] ||= ApplicationController::Filter::Expression.new
@edit[expkey][:expression] = [] # Store exps in an array
@edit[expkey][:expression] = {"???" => "???"} # Set as new exp element
# Build display filter expression
@edit[:new][:display_filter] = @edit[expkey][:expression] if @edit[:new][:display_filter].nil? # Copy to new exp
# Get the pdf page size, if present
@edit[:new][:pdf_page_size] = if @rpt.rpt_options.kind_of?(Hash) && @rpt.rpt_options[:pdf]
@rpt.rpt_options[:pdf][:page_size] || DEFAULT_PDF_PAGE_SIZE
else
DEFAULT_PDF_PAGE_SIZE
end
# Get the hide details setting, if present
@edit[:new][:hide_details] = if @rpt.rpt_options.kind_of?(Hash) && @rpt.rpt_options[:summary]
@rpt.rpt_options[:summary][:hide_detail_rows]
else
false
end
# Get the timeout if present
@edit[:new][:queue_timeout] = if @rpt.rpt_options.kind_of?(Hash) && @rpt.rpt_options[:queue_timeout]
@rpt.rpt_options[:queue_timeout]
end
case @rpt.group
when "y"
@edit[:new][:group] = "Yes"
when "c"
@edit[:new][:group] = "Counts"
else
@edit[:new][:group] = "No"
@edit[:new][:row_limit] = @rpt.rpt_options[:row_limit].to_s if @rpt.rpt_options
end
# build selected fields array from the report record
@edit[:new][:sortby1] = ReportHelper::NOTHING_STRING # Initialize sortby fields to nothing
@edit[:new][:sortby2] = ReportHelper::NOTHING_STRING
@edit[:new][:pivot] = ReportController::PivotOptions.new
if params[:pressed] == "miq_report_new"
@edit[:new][:fields] = []
@edit[:new][:categories] = []
@edit[:new][:headers] = {}
@edit[:new][:col_formats] = {}
@edit[:pivot_cols] = {}
else
build_selected_fields(@rpt) # Create the field related @edit arrays and hashes
end
# Rebuild the tag descriptions in the new fields array to match the ones in available fields
@edit[:new][:fields].each do |nf|
tag = nf.first.split(':')
if nf.first.include?("Managed :")
entry = MiqExpression.reporting_available_fields(@edit[:new][:model], @edit[:new][:perf_interval]).find { |a| a.last == nf.last }
nf[0] = entry ? entry.first : "#{tag.last.strip} (Category not found)"
end
end
@edit[:current] = %w[copy new].include?(params[:action]) ? {} : copy_hash(@edit[:new])
@edit[:new][:name] = "Copy of #{@rpt.name}" if params[:pressed] == "miq_report_copy"
# For trend reports, check for percent field chosen
if @rpt.db && @rpt.db == ApplicationController::TREND_MODEL &&
MiqExpression.reporting_available_fields(@edit[:new][:model], @edit[:new][:perf_interval]).find do |af|
af.last ==
@edit[:new][:perf_trend_db] + "-" + @edit[:new][:perf_trend_col]
end.first.include?("(%)")
@edit[:percent_col] = true
end
end
def cb_entities_by_provider
@edit[:cb_providers] = { :container_project => {}, :container_image => {} }
ManageIQ::Providers::ContainerManager.pluck(:name, :id).each do |provider_name, provider_id|
@edit[:cb_providers][:container_project][provider_name] = provider_id
@edit[:cb_providers][:container_image][provider_name] = provider_id
end
end
def categories_hash
# Omit categories for which entries dropdown would be empty.
cats = Classification.categories.select { |c| c.show && !c.entries.empty? }
cats.each_with_object({}) { |c, h| h[c.name] = c.description }
end
def entries_hash(category_name)
cat = Classification.lookup_by_name(category_name)
return {} unless cat
cat.entries.each_with_object({}) { |e, h| h[e.name] = e.description }
end
# Build the :fields array and :headers hash from the rpt record cols and includes hashes
def build_selected_fields(rpt)
fields = []
headers = {}
col_formats = {}
pivot_cols = {}
rpt.col_formats ||= Array.new(rpt.col_order.length) # Create array of nils if col_formats not present (backward compat)
rpt.col_order.each_with_index do |col, idx|
if col.starts_with?(CustomAttributeMixin::CUSTOM_ATTRIBUTES_PREFIX)
field_key = rpt.db + "-" + col
field_value = CustomAttributeMixin.to_human(col)
elsif !col.include?(".") # Main table field
field_key = rpt.db + "-" + col
field_value = friendly_model_name(rpt.db) +
Dictionary.gettext(rpt.db + "." + col.split("__").first, :type => :column, :notfound => :titleize)
else # Included table field
inc_string = find_includes(col.split("__").first, rpt.include) # Get the full include string
field_key = rpt.db + "." + inc_string.to_s + "-" + col.split(".").last
field_value = if inc_string.to_s.ends_with?(".managed") || inc_string.to_s == "managed"
# don't titleize tag name, need it to lookup later to get description by tag name
friendly_model_name(rpt.db + "." + inc_string.to_s) + col.split(".").last
else
friendly_model_name(rpt.db + "." + inc_string.to_s) +
Dictionary.gettext(col.split(".").last.split("__").first, :type => :column, :notfound => :titleize)
end
end
if field_key.include?("__") # Check for calculated pivot column
field_key1, calc_typ = field_key.split("__")
pivot_cols[field_key1] ||= []
pivot_cols[field_key1] << calc_typ.to_sym
pivot_cols[field_key1].sort! # Sort the array
fields.push([field_value, field_key1]) unless fields.include?([field_value, field_key1]) # Add original col to fields array
else
fields.push([field_value, field_key]) # Add to fields array
end
# Create the groupby keys if groupby array is present
if rpt.rpt_options &&
rpt.rpt_options[:pivot] &&
rpt.rpt_options[:pivot][:group_cols] &&
rpt.rpt_options[:pivot][:group_cols].kind_of?(Array)
unless rpt.rpt_options[:pivot][:group_cols].empty?
@edit[:new][:pivot].by1 = field_key if col == rpt.rpt_options[:pivot][:group_cols][0]
end
if rpt.rpt_options[:pivot][:group_cols].length > 1
@edit[:new][:pivot].by2 = field_key if col == rpt.rpt_options[:pivot][:group_cols][1]
end
if rpt.rpt_options[:pivot][:group_cols].length > 2
@edit[:new][:pivot].by3 = field_key if col == rpt.rpt_options[:pivot][:group_cols][2]
end
end
# Create the sortby keys if sortby array is present
if rpt.sortby.kind_of?(Array)
unless rpt.sortby.empty?
# If first sortby field as a break suffix, set up sortby1 with a suffix
if MiqReport.is_break_suffix?(rpt.sortby[0].split("__")[1])
sort1, suffix1 = rpt.sortby[0].split("__") # Get sort field and suffix, if present
@edit[:new][:sortby1] = field_key + (suffix1 ? "__#{suffix1}" : "") if col == sort1
elsif col == rpt.sortby[0] # Not a break suffix sort field, just copy the field name to sortby1
@edit[:new][:sortby1] = field_key
end
end
if rpt.sortby.length > 1
if MiqReport.is_break_suffix?(rpt.sortby[1].split("__")[1])
sort2, suffix2 = rpt.sortby[1].split("__") # Get sort field and suffix, if present
@edit[:new][:sortby2] = field_key + (suffix2 ? "__#{suffix2}" : "") if col == sort2
elsif col == rpt.sortby[1] # Not a break suffix sort field, just copy the field name to sortby1
@edit[:new][:sortby2] = field_key
end
end
end
headers[field_key] = rpt.headers[idx] # Add col to the headers hash
if field_key.include?("__") # if this a pivot calc field?
headers[field_key.split("__").first] = field_value # Save the original field key as well
end
col_formats[field_key] = rpt.col_formats[idx] # Add col to the headers hash
end
# Remove the non-cost and owner columns from the arrays for Chargeback
if Chargeback.db_is_chargeback?(rpt.db)
f_len = fields.length
for f_idx in 1..f_len # Go thru fields in reverse
f_key = fields[f_len - f_idx].last
next if f_key.ends_with?(*Chargeback::ALLOWED_FIELD_SUFFIXES) || f_key.include?('managed') || f_key.include?(CustomAttributeMixin::CUSTOM_ATTRIBUTES_PREFIX)
headers.delete(f_key)
col_formats.delete(f_key)
fields.delete_at(f_len - f_idx)
end
end
@edit[:new][:fields] = fields
@edit[:new][:headers] = headers
@edit[:new][:col_formats] = col_formats
@edit[:pivot_cols] = pivot_cols
build_field_order
end
# Create the field_order hash from the fields and pivot_cols structures
def build_field_order
@edit[:new][:field_order] = []
@edit[:new][:fields].each do |f|
if @edit[:new][:pivot] && @edit[:new][:pivot].by1 != ReportHelper::NOTHING_STRING && # If we are doing pivoting and
@edit[:pivot_cols].key?(f.last) # this is a pivot calc column
MiqReport::PIVOTS.each do |c|
calc_typ = c.first
@edit[:new][:field_order].push([f.first + " (#{calc_typ.to_s.titleize})", f.last + "__" + calc_typ.to_s]) if @edit[:pivot_cols][f.last].include?(calc_typ)
end
else
@edit[:new][:field_order].push(f)
end
end
end
# Build the full includes string by finding the column in the includes hash
def find_includes(col, includes)
tables = col.split(".")[0..-2]
field = col.split(".").last
table = tables.first
# Does this level include have the table name and does columns have the field name?
if includes[table] && includes[table]["columns"] && includes[table]["columns"].include?(field)
return table # Yes, return the table name
end
if includes[table] && includes[table]["include"]
new_col = [tables[1..-1], field].flatten.join('.')
# recursively search it for the table.col
inc_table = find_includes(new_col, includes[table]["include"])
return table + '.' + inc_table if inc_table
end
# Need to go to the next level
includes.each_pair do |key, inc| # Check each included table
next unless inc["include"] # Does the included table have an include?
inc_table = find_includes(col, inc["include"]) # Yes, recursively search it for the table.col
return nil if inc_table.nil? # If it comes back nil, we never found it
# Otherwise, return the table name + the included string
return key + "." + inc_table
end
nil
end
def setnode_for_customreport
@sb[:rpt_menu].each_with_index do |level1_nodes, i|
next unless level1_nodes[0] == reports_group_title
level1_nodes[1].each_with_index do |level2_nodes, k|
# Check for the existence of the Custom folder in the Reports tree and
# check if at least one report exists underneath it
next unless level2_nodes[0].downcase == "custom" && level2_nodes[1].count.positive?
level2_nodes[1].each do |report|
self.x_node = "xx-#{i}_xx-#{i}-#{k}_rep-#{@rpt.id}" if report == @rpt.name
end
end
end
end
def valid_report?(rpt)
active_tab = 'edit_1'
if @edit[:new][:model] == ApplicationController::TREND_MODEL
unless @edit[:new][:perf_trend_col]
add_flash(_('Trending for is required'), :error)
end
unless @edit[:new][:perf_limit_col] || @edit[:new][:perf_limit_val]
add_flash(_('Trend Target Limit must be configured'), :error)
end
if @edit[:new][:perf_limit_val] && !is_numeric?(@edit[:new][:perf_limit_val])
add_flash(_('Trend Target Limit must be numeric'), :error)
end
elsif @edit[:new][:fields].empty?
add_flash(_('At least one Field must be selected'), :error)
end
if Chargeback.db_is_chargeback?(@edit[:new][:model])
msg = case @edit[:new][:cb_show_typ]
when nil
_('Show Costs by must be selected')
when 'owner'
_('An Owner must be selected') unless @edit[:new][:cb_owner_id]
when 'tenant'
_('A Tenant Category must be selected') unless @edit[:new][:cb_tenant_id]
when 'tag'
if !@edit[:new][:cb_tag_cat]
_('A Tag Category must be selected')
elsif !@edit[:new][:cb_tag_value]
_('A Tag must be selected')
end
when 'entity'
unless @edit[:new][:cb_entity_id]
_("A specific %{chargeback} or all must be selected") % {:chargeback => ui_lookup(:model => @edit[:new][:cb_model])}
end
end
if @edit[:new][:cb_groupby] == "tag" && @edit[:new][:cb_groupby_tag].blank?
msg = _('A Group by Tag must be selected')
elsif @edit[:new][:cb_groupby] == "label" && @edit[:new][:cb_groupby_label].blank?
msg = _('A Group by Label must be selected')
elsif @edit[:new][:cb_groupby] == "label" && rpt.cols.any? { |x| x.include?(CustomAttributeMixin::CUSTOM_ATTRIBUTES_PREFIX) }
msg = _('Can not add label columns when grouping by label')
end
if msg
add_flash(msg, :error)
active_tab = 'edit_3'
end
end
active_tab = 'edit_5' unless valid_chart_data_column?
# Validate column styles
unless rpt.col_options.blank? || @edit[:new][:field_order].nil?
@edit[:new][:field_order].each do |f| # Go thru all of the cols in order
col = f.last.split('.').last.split('-').last
val = rpt.col_options[col]
next if !val || !val.key?(:style) # Skip if no options for this col or if no style options
val[:style].each_with_index do |s, s_idx| # Go through all of the configured ifs
next unless s[:value]
# See if the value is in error
e = MiqExpression.atom_error(rpt.col_to_expression_col(col.split('__').first), s[:operator], s[:value])
next unless e
msg = case s_idx + 1
when 1
add_flash(_("Styling for '%{item}', first value is in error: %{message}") %
{:item => f.first, :message => e.message}, :error)
when 2
add_flash(_("Styling for '%{item}', second value is in error: %{message}") %
{:item => f.first, :message => e.message}, :error)
when 3
add_flash(_("Styling for '%{item}', third value is in error: %{message}") %
{:item => f.first, :message => e.message}, :error)
end
active_tab = 'edit_9'
end
end
end
unless rpt.valid? # Check the model for errors
rpt.errors.each do |error|
add_flash("#{error.attribute.to_s.capitalize} #{error.message}", :error)
end
end
@sb[:miq_tab] = active_tab if flash_errors?
@flash_array.nil?
end
def valid_chart_data_column?
is_valid = !(@edit[:new][:graph_type] && @edit[:new][:chart_mode] == 'values' && @edit[:new][:chart_column].blank?)
add_flash(_('Data column must be selected when chart mode is set to "Values"'), :error) unless is_valid
is_valid
end
# Check for valid report configuration in @edit[:new]
# Check if chargeback field is valid
def valid_chargeback_fields
is_valid = false
# There are valid show typ fields
if %w[owner tenant tag entity].include?(@edit[:new][:cb_show_typ])
is_valid = case @edit[:new][:cb_show_typ]
when 'owner' then @edit[:new][:cb_owner_id]
when 'tenant' then @edit[:new][:cb_tenant_id]
when 'tag' then @edit[:new][:cb_tag_cat] && @edit[:new][:cb_tag_value]
when 'entity' then @edit[:new][:cb_entity_id] && @edit[:new][:cb_provider_id]
end
end
is_valid
end
# Check for tab switch error conditions
def check_tabs
@sb[:miq_tab] = params[:tab]
active_tab = 'edit_1'
case @sb[:miq_tab].split('_')[1]
when '8'
if @edit[:new][:fields].empty?
add_flash(_('Consolidation tab is not available until at least 1 field has been selected'), :error)
end
when '2'
if @edit[:new][:fields].empty?
add_flash(_('Formatting tab is not available until at least 1 field has been selected'), :error)
end
when '3'
if @edit[:new][:model] == ApplicationController::TREND_MODEL
unless @edit[:new][:perf_trend_col]
add_flash(_('Filter tab is not available until Trending for field has been selected'), :error)
end
unless @edit[:new][:perf_limit_col] || @edit[:new][:perf_limit_val]
add_flash(_('Filter tab is not available until Trending Target Limit has been configured'), :error)
end
if @edit[:new][:perf_limit_val] && !is_numeric?(@edit[:new][:perf_limit_val])
add_flash(_('Trend Target Limit must be numeric'), :error)
end
elsif @edit[:new][:fields].empty?
add_flash(_('Filter tab is not available until at least 1 field has been selected'), :error)
end
when '4'
if @edit[:new][:fields].empty?
add_flash(_('Summary tab is not available until at least 1 field has been selected'), :error)
end
when '5'
if @edit[:new][:fields].empty?
add_flash(_('Charts tab is not available until at least 1 field has been selected'), :error)
elsif @edit[:new][:sortby1].blank? || @edit[:new][:sortby1] == ReportHelper::NOTHING_STRING
add_flash(_('Charts tab is not available unless a sort field has been selected'), :error)
active_tab = 'edit_4'
end
when '7'
if @edit[:new][:model] == ApplicationController::TREND_MODEL
unless @edit[:new][:perf_trend_col]
add_flash(_('Preview tab is not available until Trending for field has been selected'), :error)
end
unless @edit[:new][:perf_limit_col] || @edit[:new][:perf_limit_val]
add_flash(_('Preview tab is not available until Trend Target Limit has been configured'), :error)
end
if @edit[:new][:perf_limit_val] && !is_numeric?(@edit[:new][:perf_limit_val])
add_flash(_('Trend Target Limit: Value must be numeric'), :error)
end
elsif @edit[:new][:fields].empty?
add_flash(_('Preview tab is not available until at least 1 field has been selected'), :error)
elsif Chargeback.db_is_chargeback?(@edit[:new][:model]) && !valid_chargeback_fields
add_flash(_('Preview tab is not available until Chargeback Filters has been configured'), :error)
active_tab = 'edit_3'
elsif !valid_chart_data_column?
active_tab = 'edit_5'
end
when '9'
if @edit[:new][:fields].empty?
add_flash(_('Styling tab is not available until at least 1 field has been selected'), :error)
end
end
@sb[:miq_tab] = active_tab if flash_errors?
end
end