app/presenters/explorer_presenter.rb
class ExplorerPresenter
include ApplicationHelper
include JsHelper
include ActionView::Helpers::JavaScriptHelper
include ToolbarHelper
include ActionView::Helpers::TagHelper
include ActionView::Context
# Returns hash for ManageIQ.explorer that contains data needed to replace the
# contents of an explorer view as directed by the (server side) controller.
# This presenter supports these options:
#
# add_nodes -- JSON string of nodes to add to the active tree
# delete_node -- key of node to be deleted from the active tree
# clear_search_toggle -- show or hide 'clear search' button
# build_calendar -- call miqBuildCalendar, true/false or Hash (:date_from, :date_to, :skip_days)
#
# init_dashboard -- call miqInitDashboardCols
# miq_widget_dd_url -- url to be used in url in miqDropComplete method
# (ManageIQ.widget.dashboardUrl)
#
# init_accords -- initialize accordion autoresize
# ajax_action -- Hash of options for AJAX action to fire
# clear_gtl_list_grid -- Clear ManageIQ.grids.gtl_list_grid
# right_cell_text -- Page title (content of the title area)
#
# :record_id sets ManageIQ.record.recordId -- record being displayed or edited
# :parent_id sets ManageIQ.record.parentId -- it's parent
# :parent_class sets ManageIQ.record.parentClass -- and it's (parent's) class
#
# osf_node -- node to open, select and focus
# open_accord -- accordion to open
# exp -- data for the expression editor
# active_tree -- x_active_tree view state from controller
# lock_sidebar -- enable or disable the sidebar
#
# Following options are hashes:
# update_partials -- partials to update contents
# replace_partials -- partials to replace (also wrapping tag)
# element_updates -- update DOM element content or title FIXME: content can be
# replaced with update_partials
# set_visible_elements -- elements to cal 'set_visible' on
# reload_toolbars -- toolbars to reload and their content
#
def self.right_cell(args = {})
new(args.update(:mode => 'right_cell'))
end
def self.flash(args = {})
new(args.update(:mode => 'flash'))
end
def self.rx(args = {})
new(args.update(:mode => 'rx'))
end
def self.main_div(args = {})
new(args.update(:mode => 'main_div'))
end
def self.buttons(show)
new(:mode => 'buttons', :show_miq_buttons => show)
end
def initialize(options = {})
@options = {
:set_visible_elements => {},
:update_partials => {},
:element_updates => {},
:replace_partials => {},
:reload_toolbars => {},
:reload_trees => {},
:exp => {},
:osf_node => '',
:show_miq_buttons => false,
:load_chart => nil,
:open_window => nil,
:remove_paging => nil,
:rx => nil,
}.update(options)
end
def remove_paging
@options[:remove_paging] = true
self
end
def reset_one_trans
@options[:reset_one_trans] = true
self
end
def focus(element_id)
@options[:focus] = element_id
self
end
def activate_tree_node(options)
@options[:activate_node] = options
self
end
def spinner_off
@options[:spinner_off] = true
self
end
def scroll_top
@options[:scroll_top] = true
self
end
def load_chart(chart_data)
@options[:load_chart] = chart_data
self
end
def show_miq_buttons(show = true)
@options[:show_miq_buttons] = show
self
end
def set_visibility(value, *elements)
elements.each { |el| @options[:set_visible_elements][el] = value }
self
end
def hide(*elements)
set_visibility(false, *elements)
end
def show(*elements)
set_visibility(true, *elements)
end
def reload_toolbars(toolbars)
toolbars.each_pair do |div_name, toolbar_data|
@options[:reload_toolbars][div_name] = toolbar_data
end
self
end
def reload_tree(name, data)
@options[:reload_trees][name] = data
end
def replace(div_name, content)
@options[:replace_partials][div_name] = content
self
end
def update(div_name, content)
@options[:update_partials][div_name] = content
self
end
def rx(data)
@options[:rx] = data
self
end
def self.open_window(url)
new(:mode => 'window', :open_url => url)
end
def []=(key, value)
@options[key] = value
end
def [](key)
@options[key]
end
def for_render
case @options[:mode]
when 'main_div' then for_render_main_div
when 'flash' then for_render_flash
when 'buttons' then for_render_buttons
when 'window' then for_render_window
when 'rx' then for_render_rx
else for_render_default
end
end
private
def for_render_flash
data = {:explorer => 'flash'}
data[:replacePartials] = @options[:replace_partials]
data[:spinnerOff] = true if @options[:spinner_off]
data[:scrollTop] = true if @options[:scroll_top] || @flash_array.present?
data[:focus] = @options[:focus] if @options[:focus]
data[:activateNode] = @options[:activate_node] if @options[:activate_node]
data
end
def for_render_window
data = {:explorer => 'window'}
data[:openUrl] = @options[:open_url]
data[:spinnerOff] = true if @options[:spinner_off]
data
end
def for_render_rx
data = {:explorer => 'rx'}
data[:rx] = @options[:rx]
data
end
def for_render_main_div
data = check_spinner(:explorer => 'replace_main_div')
data[:rightCellText] = escape_if_unsafe(@options[:right_cell_text]) if @options[:right_cell_text]
data[:updatePartials] = @options[:update_partials]
data[:setVisibility] = @options[:set_visible_elements]
data
end
def check_spinner(data)
data[:spinnerOff] = true if @options[:spinner_off]
data
end
def for_render_buttons
data = {:explorer => 'buttons'}
data[:showMiqButtons] = @options[:show_miq_buttons]
data
end
def escape_if_unsafe(string)
ActiveSupport::SafeBuffer === string ? string : ERB::Util.html_escape(string)
end
def for_render_default
data = {:explorer => 'replace_right_cell', :scrollTop => true}
if @options[:exp].present?
data.store_path(:expEditor, :first, :type, @options[:exp][:val1_type]) if @options[:exp][:val1_type]
data.store_path(:expEditor, :first, :title, @options[:exp][:val1_title]) if @options[:exp][:val1_title]
data.store_path(:expEditor, :second, :type, @options[:exp][:val2_type]) if @options[:exp][:val2_type]
data.store_path(:expEditor, :second, :title, @options[:exp][:val2_title]) if @options[:exp][:val2_title]
end
data[:showMiqButtons] = @options[:show_miq_buttons]
data[:clearTreeCookies] = @options[:clear_tree_cookies]
data[:treeExpandAll] = @options[:tree_expand_all]
# Open an accordion inside an other AJAX call
data[:accordionSwap] = @options[:open_accord] unless @options[:open_accord].to_s.empty?
if @options[:add_nodes]
data[:addNodes] = {
:activeTree => @options[:active_tree],
:key => @options[:add_nodes][:key],
:osf => @options[:osf_node],
:nodes => @options[:add_nodes][:nodes],
:remove => !!@options[:remove_nodes],
}
end
if @options[:delete_node]
data[:deleteNode] = {
:node => @options[:delete_node],
:activeTree => @options[:active_tree],
}
end
data[:dashboardUrl] = @options[:miq_widget_dd_url] if @options[:miq_widget_dd_url]
data[:updatePartials] = @options[:update_partials] # Replace content of given DOM element (element stays).
data[:updateElements] = @options[:element_updates] # Update element in the DOM with given options
data[:replacePartials] = @options[:replace_partials] # Replace given DOM element (and it's children) (element goes away).
data[:reloadTrees] = @options[:reload_trees] # Replace the data attribute of the given TreeViewComponent
data[:buildCalendar] = format_calendar_dates(@options[:build_calendar])
data[:initDashboard] = !!@options[:init_dashboard]
data[:ajaxUrl] = ajax_action_url(@options[:ajax_action]) if @options[:ajax_action]
data[:clearGtlListGrid] = !!@options[:clear_gtl_list_grid]
data[:setVisibility] = @options[:set_visible_elements]
data[:rightCellText] = escape_if_unsafe(@options[:right_cell_text]) if @options[:right_cell_text]
data[:providerPaused] = @options[:provider_paused] if @options.key?(:provider_paused)
data[:reloadToolbars] = @options[:reload_toolbars].collect do |_div_name, toolbar|
toolbar
end
# ids are nil or string
data[:record] = {
:parentId => @options[:parent_id]&.to_s,
:parentClass => @options[:parent_class],
:recordId => @options[:record_id]&.to_s,
}
if @options[:osf_node].present?
data[:activateNode] = {
:activeTree => @options[:active_tree],
:osf => @options[:osf_node]
}
end
data[:lockSidebar] = !!@options[:lock_sidebar]
data[:chartData] = @options[:load_chart]
data[:removePaging] = !!@options[:remove_paging]
data[:resetOneTrans] = !!@options[:reset_one_trans]
data[:focus] = @options[:focus]
data[:clearSearch] = @options[:clear_search_toggle] if @options.key?(:clear_search_toggle)
data[:hideModal] if @options[:hide_modal]
data[:initAccords] if @options[:init_accords]
data
end
def format_calendar_dates(options)
return {} unless @options[:build_calendar].kind_of?(Hash)
%i[date_from date_to].each_with_object({}) do |key, h|
h[key] = options[key].iso8601 if options[key].present?
end
end
def ajax_action_url(options)
['', options[:controller], options[:action], options[:record_id]].join('/')
end
end