From 4a2ba1c7a3752bb72095d302116e2fea969015dc Mon Sep 17 00:00:00 2001 From: Harpreet Kataria Date: Tue, 29 Dec 2020 19:44:05 -0500 Subject: [PATCH] Action explorer de-explorized version - This commit includes de-explorized Actions list/details screen with Add/Edit/Delete buttons working. - Updated MiqAction controller spec tests https://github.com/ManageIQ/manageiq-ui-classic/issues/6819 --- app/controllers/miq_action_controller.rb | 353 ++++-------- .../button/miq_action_edit.rb | 3 +- .../application_helper/page_layouts.rb | 1 + .../toolbar/miq_action_center.rb | 6 +- .../toolbar/miq_actions_center.rb | 28 + .../application_helper/toolbar_chooser.rb | 4 +- app/presenters/menu/default_menu.rb | 2 +- .../miq_action/_action_details.html.haml | 532 +++++++++--------- app/views/miq_action/edit.html.haml | 1 + app/views/miq_action/explorer.html.haml | 9 - app/views/miq_action/new.html.haml | 1 + app/views/miq_action/show.html.haml | 1 + ...ion_list.html.haml => show_list.html.haml} | 0 config/routes.rb | 15 +- .../controllers/miq_action_controller_spec.rb | 114 ++-- 15 files changed, 477 insertions(+), 593 deletions(-) create mode 100644 app/views/miq_action/edit.html.haml delete mode 100644 app/views/miq_action/explorer.html.haml create mode 100644 app/views/miq_action/new.html.haml create mode 100644 app/views/miq_action/show.html.haml rename app/views/miq_action/{_action_list.html.haml => show_list.html.haml} (100%) diff --git a/app/controllers/miq_action_controller.rb b/app/controllers/miq_action_controller.rb index ed211bcebf98..2524c0bf68e1 100644 --- a/app/controllers/miq_action_controller.rb +++ b/app/controllers/miq_action_controller.rb @@ -4,7 +4,10 @@ class MiqActionController < ApplicationController after_action :cleanup_action after_action :set_session_data + include Mixins::GenericFormMixin + include Mixins::GenericListMixin include Mixins::GenericSessionMixin + include Mixins::GenericShowMixin include Mixins::BreadcrumbsMixin include Mixins::PolicyMixin @@ -12,143 +15,46 @@ def title @title = _("Actions") end - def index - flash_to_session - redirect_to(:action => 'explorer') + def new + miq_action_reset_or_set end - # handle buttons pressed on the button bar - def button - @edit = session[:edit] # Restore @edit for adv search box - @refresh_div = "main_div" # Default div for button.rjs to refresh - - unless @refresh_partial # if no button handler ran, show not implemented msg - add_flash(_("Button not yet implemented"), :error) - @refresh_partial = "layouts/flash_msg" - @refresh_div = "flash_msg_div" + def edit + @_params[:pressed] ||= 'miq_action_edit' + case params[:button] + when "cancel" + miq_action_cancel + when "save", "add" + miq_action_save_add + when "reset", nil # displaying edit from for actions: new, edit or copy + @_params[:id] ||= find_checked_items[0] + @redirect_id = params[:id] if params[:id] + @refresh_partial = "edit" + miq_action_reset_or_set end end - ACTION_X_BUTTON_ALLOWED_ACTIONS = { - 'miq_action_edit' => :miq_action_edit, - 'miq_action_new' => :miq_action_edit, - }.freeze - - def x_button - generic_x_button(ACTION_X_BUTTON_ALLOWED_ACTIONS) - end - - def explorer - @breadcrumbs = [] - @explorer = true - - self.x_active_tree ||= 'action_tree' - self.x_active_accord ||= 'action' - - build_accordions_and_trees - get_node_info(x_node) - - render :layout => "application" - end - - # Item clicked on in the explorer right cell - def x_show - @explorer = true - tree_select - end - - def accordion_select - self.x_active_accord = params[:id].sub(/_accord$/, '') - self.x_active_tree = "#{self.x_active_accord}_tree" - get_node_info(x_node) - replace_right_cell(:nodetype => @nodetype) - end - - def tree_select - # set these when a link on one of the summary screen was pressed - self.x_active_accord = params[:accord] if params[:accord] - self.x_active_tree = "#{params[:accord]}_tree" if params[:accord] - self.x_active_tree = params[:tree] if params[:tree] - self.x_node = params[:id] - - @sb[:action] = nil - get_node_info(x_node) - replace_right_cell(:nodetype => @nodetype) - end - - def search - get_node_info(x_node) - replace_right_cell(:nodetype => x_node) - end - def miq_action_edit assert_privileges(params[:pressed]) if params[:pressed] - case params[:button] - when "cancel" - @sb[:action] = @edit = nil - @action = MiqAction.find(session[:edit][:action_id]) if session[:edit] && session[:edit][:action_id] - if @action.present? - add_flash(_("Edit of Action \"%{name}\" was cancelled by the user") % {:name => @action.description}) - else - add_flash(_("Add of new Action was cancelled by the user")) - end - @sb[:action] = nil - get_node_info(x_node) - replace_right_cell(:nodetype => @nodetype, :remove_form_buttons => true) - return - when "reset", nil # Reset or first time in - action_build_edit_screen - @sb[:action] = "miq_action_edit" - if params[:button] == "reset" - add_flash(_("All changes have been reset"), :warning) - end - replace_right_cell(:nodetype => "a") - return - end - # Load @edit/vars for other buttons id = params[:id] || "new" - return unless load_edit("action_edit__#{id}", "replace_cell__explorer") + return unless load_edit("miq_action_edit__#{id}") @action = @edit[:action_id] ? MiqAction.find(@edit[:action_id]) : MiqAction.new case params[:button] - when "save", "add" - action = @action.id.blank? ? MiqAction.new : MiqAction.find(@action.id) # Get new or existing record - - # set email "from" to default value if it's not present - if @edit[:new][:action_type] == "email" && @edit[:new][:options][:from].nil? - @edit[:new][:options][:from] = "cfadmin@cfserver.com" - end - - action_set_record_vars(action) - if action_valid_record?(action) && !@flash_array && action.save - AuditEvent.success(build_saved_audit(action, @edit)) - if params[:button] == "save" - add_flash(_("Action \"%{name}\" was saved") % {:name => @edit[:new][:description]}) - else - add_flash(_("Action \"%{name}\" was added") % {:name => @edit[:new][:description]}) - end - action_get_info(MiqAction.find(action.id)) - @sb[:action] = @edit = nil - @nodetype = "a" - @new_action_node = "a-#{action.id}" - replace_right_cell(:nodetype => "a", :replace_trees => params[:button] == "save" ? %i[policy_profile policy action] : %i[action], :remove_form_buttons => true) - @sb[:action] = nil - else - action.errors.each do |field, msg| - add_flash("#{field.to_s.capitalize} #{msg}", :error) - end - javascript_flash - end when "move_right", "move_left", "move_allleft" action_handle_selection_buttons(:alerts) - session[:changed] = (@edit[:new] != @edit[:current]) - replace_right_cell(:nodetype => "a") + @changed = (@edit[:new] != @edit[:current]) + render :update do |page| + page << javascript_prologue + page.replace("flash_msg_div", :partial => "layouts/flash_msg") + page.replace_html("action_details_div", :partial => "action_details") unless @flash_errors + end end end def action_field_changed - return unless load_edit("action_edit__#{params[:id]}", "replace_cell__explorer") + return unless load_edit("miq_action_edit__#{params[:id]}") @action = @edit[:action_id] ? MiqAction.find(@edit[:action_id]) : MiqAction.new @@ -232,12 +138,82 @@ def update_playbook_variables(params) @edit[:new][:options][:use_localhost] = @edit[:new][:inventory_type] == 'localhost' end - def action_get_all - peca_get_all('action', -> { get_view(MiqAction) }) + def show + super + # Get information for an action + @alert_guids = [] + if @record.options && @record.options[:alert_guids] + @alert_guids = MiqAlert.where(:guid => @record.options[:alert_guids]) + end + + @action_policies = @record.miq_policies.sort_by { |p| p.description.downcase } + + if %w[inherit_parent_tags remove_tags].include?(@record.action_type) + @cats = Classification.lookup_by_names(@record.options[:cats]).pluck(:description).sort_by(&:downcase).join(" | ") + end end private + def miq_action_reset_or_set + assert_privileges('miq_action_edit') if params[:button] == "reset" + @in_a_form = true + @action = params[:id] ? MiqAction.find(params[:id]) : MiqAction.new # Get existing or new record + + if @action.try(:id) && @action.action_type == "default" + add_flash(_("Default Action \"%{name}\" cannot be edited.") % {:name => @action.description}, :error) + flash_to_session + redirect_to(:action => 'show_list') + end + + action_build_edit_screen + javascript_redirect(:action => 'edit', + :id => params[:id], + :flash_msg => _("All changes have been reset"), + :flash_warning => true) if params[:button] == "reset" + end + + def miq_action_cancel + @action = MiqAction.find_by(:id => params[:id]) + if @action.present? + flash_msg = _("Edit of Action \"%{name}\" was cancelled by the user") % {:name => @action.description} + else + flash_msg = _("Add of new Action was cancelled by the user") + end + @edit = session[:edit] = nil # clean out the saved info + session[:changed] = false + javascript_redirect(:action => @lastaction, :id => params[:id], :flash_msg => flash_msg) + end + + def miq_action_save_add + assert_privileges("miq_action_#{params[:id] ? "edit" : "new"}") + return unless load_edit("miq_action_edit__#{params[:id] ? "#{params[:id]}" : "new"}") + + action = @edit[:action_id].blank? ? MiqAction.new : MiqAction.find_by(:id => @edit[:action_id]) # Get new or existing record + # set email "from" to default value if it's not present + if @edit[:new][:action_type] == "email" && @edit[:new][:options][:from].nil? + @edit[:new][:options][:from] = "cfadmin@cfserver.com" + end + + action_set_record_vars(action) + if action_valid_record?(action) && !@flash_array && action.save + AuditEvent.success(build_saved_audit(action, @edit)) + if params[:button] == "save" + flash_msg = _("Action \"%{name}\" was saved") % {:name => @edit[:new][:description]} + else + flash_msg = _("Action \"%{name}\" was added") % {:name => @edit[:new][:description]} + end + @edit = session[:edit] = nil # clean out the saved info + session[:changed] = @changed = false + javascript_redirect(:controller => 'miq_action', :action => @lastaction, :id => params[:id], :flash_msg => flash_msg) + else + action.errors.each do |field, msg| + add_flash("#{field.to_s.capitalize} #{msg}", :error) + end + javascript_flash + end + end + def action_build_snmp_variables @edit[:new][:options][:snmp_version] = "v1" if @edit[:new][:action_type] == "snmp_trap" && @edit[:new][:options][:snmp_version].blank? @edit[:snmp_var_types] = MiqSnmp.available_types @@ -296,8 +272,7 @@ def action_build_edit_screen @edit[:new] = {} @edit[:current] = {} - @action = params[:id] ? MiqAction.find(params[:id]) : MiqAction.new # Get existing or new record - @edit[:key] = "action_edit__#{@action.id || "new"}" + @edit[:key] = "miq_action_edit__#{@action.id || "new"}" @edit[:rec_id] = @action.id || nil @edit[:action_id] = @action.id @@ -447,124 +422,6 @@ def validate_playbook_options(options) end end - # Get information for an action - def action_get_info(action) - @record = @action = action - @right_cell_text = _("Action \"%{name}\"") % {:name => action.description} - @right_cell_div = "action_details" - @alert_guids = [] - if action.options && action.options[:alert_guids] - @alert_guids = MiqAlert.where(:guid => action.options[:alert_guids]) - end - - if x_active_tree == :action_tree - @action_policies = @action.miq_policies.sort_by { |p| p.description.downcase } - end - - if %w[inherit_parent_tags remove_tags].include?(@action.action_type) - @cats = Classification.lookup_by_names(@action.options[:cats]).pluck(:description).sort_by(&:downcase).join(" | ") - end - end - - # Get all info for the node about to be displayed - def get_node_info(treenodeid, show_list = true) - @show_list = show_list - _modelname, nodeid, @nodetype = TreeBuilder.extract_node_model_and_id(valid_active_node(treenodeid)) - node_ids = {} - treenodeid.split("_").each do |p| - # Create a hash of all record ids represented by the selected tree node - node_ids[p.split("-").first] = p.split("-").last - end - @sb[:node_ids] ||= {} - @sb[:node_ids][x_active_tree] = node_ids - x_node == "root" ? action_get_all : action_get_info(MiqAction.find(nodeid)) - @show_adv_search = @nodetype == "root" - {:view => @view, :pages => @pages} - end - - # replace_trees can be an array of tree symbols to be replaced - def replace_right_cell(options = {}) - nodetype, replace_trees, presenter = options.values_at(:nodetype, :replace_trees, :presenter) - replace_trees = @replace_trees if @replace_trees # get_node_info might set this - replace_trees = Array(replace_trees) - @explorer = true - - trees = build_replaced_trees(replace_trees, %i[action]) - - c_tb = build_toolbar(center_toolbar_filename) - - # Build a presenter to render the JS - presenter ||= ExplorerPresenter.new( - :active_tree => x_active_tree, - :open_accord => params[:accord] - ) - - # Simply replace the tree partials to reload the trees - replace_trees.each do |name| - case name - when :action - self.x_node = @new_action_node if @new_action_node - else - raise _("unknown tree in replace_trees: %{name}") % {name => name} - end - end - reload_trees_by_presenter(presenter, trees) - - presenter[:osf_node] = x_node - - @changed = session[:changed] if @edit # to get save/reset buttons to highlight when fields are moved left/right - - # Replace right side with based on selected tree node type - case nodetype - when 'root' - partial_name, model = ['action_list', _('Actions')] - presenter.update(:main_div, r[:partial => partial_name]) - right_cell_text = _("All %{models}") % {:models => model} - right_cell_text += _(" (Names with \"%{search_text}\")") % {:search_text => @search_text} if @search_text.present? - when 'a', 'ta', 'fa' - presenter.update(:main_div, r[:partial => 'action_details', :locals => {:read_only => true}]) - right_cell_text = if @action.id.blank? - _("Adding a new Action") - else - msg = @edit ? _("Editing Action \"%{name}\"") : _("Action \"%{name}\"") - msg % {:name => @action.description} - end - end - presenter[:right_cell_text] = @right_cell_text = right_cell_text - - presenter.reload_toolbars(:center => c_tb) - - if ((@edit && @edit[:new]) || @assign) && params[:action] != "x_search_by_name" - locals = { - :action_url => @sb[:action], - :record_id => @edit ? @edit[:rec_id] : @assign[:rec_id], - } - presenter.hide(:toolbar) - # If was hidden for summary screen and there were no records on show_list - presenter.show(:paging_div, :form_buttons_div) - presenter.update(:form_buttons_div, r[:partial => "layouts/x_edit_buttons", :locals => locals]) - else - # Added so buttons can be turned off even tho div is not being displayed it still pops up - # Abandon changes box when trying to change a node on tree after saving a record - presenter.hide(:buttons_on).show(:toolbar).hide(:paging_div) - end - - presenter.hide(:form_buttons_div) if options[:remove_form_buttons] - - replace_search_box(presenter, :nameonly => true) - - # Hide/show searchbox depending on if a list is showing - presenter.set_visibility(@show_adv_search, :adv_searchbox_div) - - presenter[:record_id] = @record.try(:id) - - presenter[:lock_sidebar] = (@edit || @assign) && params[:action] != "x_search_by_name" - - presenter.update(:breadcrumbs, r[:partial => 'layouts/breadcrumbs']) - - render :json => presenter.for_render - end - def get_session_data @title = _("Actions") @layout = "miq_action" @@ -579,26 +436,16 @@ def set_session_data session[:miq_action_current_page] = @current_page end - def features - [ - { - :name => :action, - :title => _("Actions"), - :role => "action", - :role_any => true - }, - ].map { |hsh| ApplicationController::Feature.new_with_hash(hsh) } - end - def breadcrumbs_options { :breadcrumbs => [ {:title => _("Control")}, - {:title => _('Explorer')}, + {:title => _('Actions'), :url => controller_url}, ].compact, :record_title => :description, } end + toolbar :miq_action,:miq_actions menu_section :con end diff --git a/app/helpers/application_helper/button/miq_action_edit.rb b/app/helpers/application_helper/button/miq_action_edit.rb index 9dfff99d36f1..585633fb6a22 100644 --- a/app/helpers/application_helper/button/miq_action_edit.rb +++ b/app/helpers/application_helper/button/miq_action_edit.rb @@ -1,8 +1,7 @@ -class ApplicationHelper::Button::MiqActionEdit < ApplicationHelper::Button::MiqActionModify +class ApplicationHelper::Button::MiqActionEdit < ApplicationHelper::Button::Basic needs :@record def disabled? - super @error_message = _("Default actions can not be changed.") if @record.action_type == "default" @error_message.present? end diff --git a/app/helpers/application_helper/page_layouts.rb b/app/helpers/application_helper/page_layouts.rb index a98a962a06da..421075db08d9 100644 --- a/app/helpers/application_helper/page_layouts.rb +++ b/app/helpers/application_helper/page_layouts.rb @@ -23,6 +23,7 @@ def layout_uses_listnav? cloud_topology diagnostics exception + miq_action miq_ae_automate_button miq_ae_customization miq_ae_export diff --git a/app/helpers/application_helper/toolbar/miq_action_center.rb b/app/helpers/application_helper/toolbar/miq_action_center.rb index 2861c17f9153..f1621104bf02 100644 --- a/app/helpers/application_helper/toolbar/miq_action_center.rb +++ b/app/helpers/application_helper/toolbar/miq_action_center.rb @@ -11,8 +11,9 @@ class ApplicationHelper::Toolbar::MiqActionCenter < ApplicationHelper::Toolbar:: 'pficon pficon-edit fa-lg', t = N_('Edit this Action'), t, - :klass => ApplicationHelper::Button::MiqActionEdit, - :url_parms => "?type=basic"), + :klass => ApplicationHelper::Button::MiqActionEdit, + :url => "/edit", + :send_checked => true,), button( :miq_action_delete, 'pficon pficon-delete fa-lg', @@ -21,6 +22,7 @@ class ApplicationHelper::Toolbar::MiqActionCenter < ApplicationHelper::Toolbar:: :klass => ApplicationHelper::Button::MiqActionDelete, :data => {'function' => 'sendDataWithRx', 'function-data' => {:api_url => 'actions', + :redirect_url => '/miq_action/show_list', :component_name => 'RemoveGenericItemModal', :controller => 'provider_dialogs', :display_field => 'description', diff --git a/app/helpers/application_helper/toolbar/miq_actions_center.rb b/app/helpers/application_helper/toolbar/miq_actions_center.rb index 936aca2ef9dc..fcaede8e0bca 100644 --- a/app/helpers/application_helper/toolbar/miq_actions_center.rb +++ b/app/helpers/application_helper/toolbar/miq_actions_center.rb @@ -11,7 +11,35 @@ class ApplicationHelper::Toolbar::MiqActionsCenter < ApplicationHelper::Toolbar: 'pficon pficon-add-circle-o fa-lg', t = N_('Add a new Action'), t, + :url => "/new", :klass => ApplicationHelper::Button::ButtonNewDiscover), + button( + :miq_action_edit, + 'pficon pficon-edit fa-lg', + t = N_('Edit the selected Action'), + t, + :url => "/edit", + :url_parms => "main_div", + :send_checked => true, + :enabled => false, + :onwhen => "1"), + button( + :miq_action_delete, + 'pficon pficon-delete fa-lg', + N_('Delete selected Actions'), + N_('Delete Actions'), + :enabled => false, + :onwhen => "1+", + :data => {'function' => 'sendDataWithRx', + 'function-data' => {:api_url => 'actions', + :redirect_url => '/miq_action/show_list', + :component_name => 'RemoveGenericItemModal', + :controller => 'provider_dialogs', + :display_field => 'description', + :modal_text => N_("Are you sure you want to delete selected Actions?"), + :modal_title => N_("Delete Actions")}} + ), + ] ), ]) diff --git a/app/helpers/application_helper/toolbar_chooser.rb b/app/helpers/application_helper/toolbar_chooser.rb index f4350bc047c2..3749805d0728 100644 --- a/app/helpers/application_helper/toolbar_chooser.rb +++ b/app/helpers/application_helper/toolbar_chooser.rb @@ -102,7 +102,7 @@ def center_toolbar_filename_explorer center_toolbar_filename_chargeback_report elsif @layout == "miq_ae_tools" super_admin_user? ? "miq_ae_tools_simulate_center_tb" : nil - elsif %w[miq_action miq_alert miq_alert_set miq_event].include?(@layout) + elsif %w[miq_alert miq_alert_set miq_event miq_policy].include?(@layout) center_toolbar_filename_miq_policy elsif @layout == "ops" center_toolbar_filename_ops @@ -229,13 +229,11 @@ def center_toolbar_filename_miq_policy case @nodetype when "root" case x_active_tree - when :action_tree then "miq_actions_center_tb" when :alert_tree then "miq_alerts_center_tb" end when "p" then "miq_policy_center_tb" when "co" then "condition_center_tb" when "ev" then "miq_event_center_tb" - when "a" then "miq_action_center_tb" when "al" then "miq_alert_center_tb" when "ap" then "miq_alert_set_center_tb" end diff --git a/app/presenters/menu/default_menu.rb b/app/presenters/menu/default_menu.rb index cf2d634159d0..b1561d41abd6 100644 --- a/app/presenters/menu/default_menu.rb +++ b/app/presenters/menu/default_menu.rb @@ -230,7 +230,7 @@ def control_menu_section Menu::Item.new('miq_policy', N_('Policies'), 'miq_policy', {:feature => 'miq_policy_show_list'}, '/miq_policy/show_list'), Menu::Item.new('miq_event', N_('Events'), 'miq_event', {:feature => 'miq_event_definition_show_list'}, '/miq_event_definition/show_list'), Menu::Item.new('condition', N_('Conditions'), 'condition', {:feature => 'condition_show_list'}, '/condition/show_list'), - Menu::Item.new('miq_action', N_('Actions'), 'miq_action', {:feature => 'miq_action', :any => true}, '/miq_action/explorer'), + Menu::Item.new('miq_action', N_('Actions'), 'miq_action', {:feature => 'miq_action_show_list'}, '/miq_action/show_list'), Menu::Item.new('miq_alert_set', N_('Alert Profiles'), 'miq_alert_set', {:feature => 'miq_alert_set', :any => true}, '/miq_alert_set/explorer'), Menu::Item.new('miq_alert', N_('Alerts'), 'miq_alert', {:feature => 'miq_alert', :any => true}, '/miq_alert/explorer'), Menu::Item.new('miq_policy_rsop', N_('Simulation'), 'policy_simulation', {:feature => 'policy_simulation'}, '/miq_policy_rsop'), diff --git a/app/views/miq_action/_action_details.html.haml b/app/views/miq_action/_action_details.html.haml index a34455478f2e..4603526456e1 100644 --- a/app/views/miq_action/_action_details.html.haml +++ b/app/views/miq_action/_action_details.html.haml @@ -1,264 +1,282 @@ #action_details_div - - if @action - #action_info_div - = render :partial => "layouts/flash_msg" - %h3 - = _('Basic Information') - .form-horizontal - - if @edit - -# Don't show description unless in edit mode - - url = url_for_only_path(:action => 'action_field_changed', :id => (@action.id || 'new')) + #action_info_div + = render :partial => "layouts/flash_msg" + %h3 + = _('Basic Information') + .form-horizontal + -# Don't show description unless in edit mode + - url = url_for_only_path(:action => 'action_field_changed', :id => (@edit[:rec_id] || 'new')) if @edit + .form-group + %label.col-md-2.control-label + = _('Description') + .col-md-8 + - if @edit + = text_field_tag("description", + @edit[:new][:description], + :maxlength => ViewHelper::MAX_DESC_LEN, + :class => "form-control", + "data-miq_focus" => true, + "data-miq_observe" => {:interval => '.5', :url => url}.to_json) + - else + %p.form-control-static + = h(@record.description) + .form-group + %label.col-md-2.control-label + = _('Action Type') + .col-md-8 + - if @edit + = select_tag('miq_action_type', + options_for_select([["<#{_('Choose')}>", nil]] + MiqAction::TYPES.map { |k, v| [_(v), k] }.sort, @edit[:new][:action_type]), + :class => "selectpicker form-control") + :javascript + miqInitSelectPicker(); + miqSelectPickerEvent('miq_action_type', '#{url}', {beforeSend: true, complete: true}) + - else + %p.form-control-static + = h(@record.action_type == "default" ? _('Default') : _(MiqAction::TYPES[@record.action_type])) + %hr + - if @edit + = render :partial => "action_options" + - else + - case @record.action_type + - when "create_snapshot" + %h3 + = _('Snapshot Settings') + .form-horizontal .form-group - %label.col-md-2.control-label - = _('Description') + %label.control-label.col-md-2= _('Name') .col-md-8 - - if @edit - = text_field_tag("description", - @edit[:new][:description], - :maxlength => ViewHelper::MAX_DESC_LEN, - :class => "form-control", - "data-miq_observe" => {:interval => '.5', :url => url}.to_json) - = javascript_tag(javascript_focus('description')) - - else - %p.form-control-static - = h(@action.description) - .form-group - %label.col-md-2.control-label - = _('Action Type') - .col-md-8 - - if @edit - = select_tag('miq_action_type', - options_for_select([["<#{_('Choose')}>", nil]] + MiqAction::TYPES.map { |k, v| [_(v), k] }.sort, @edit[:new][:action_type]), - :class => "selectpicker form-control") - :javascript - miqInitSelectPicker(); - miqSelectPickerEvent('miq_action_type', '#{url}', {beforeSend: true, complete: true}) - - else - %p.form-control-static - = h(@action.action_type == "default" ? _('Default') : _(MiqAction::TYPES[@action.action_type])) - %hr - - if @edit - = render :partial => "action_options" - - else - - case @action.action_type - - when "create_snapshot" - %h3 - = _('Snapshot Settings') - .form-horizontal - .form-group - %label.control-label.col-md-2= _('Name') - .col-md-8 - %p.form-control-static= h(@action.options[:name]) - - %hr - - when "delete_snapshots_by_age" - %h3= _('Snapshot Age Settings') - .form-horizontal - .form-group - %label.control-label.col-md-2= _('Delete if older than') - .col-md-8 - %p.form-control-static= h(MiqPolicyHelper::SNAPSHOT_AGES[@action.options[:age]]) + %p.form-control-static= h(@record.options[:name]) - %hr - - when "custom_automation" - %h3 - = _('Custom Automation') - .form-horizontal - .form-group - .col-md-8 - %h4 - = _('Object Details') - .form-horizontal - .form-group - %label.control-label.col-md-2 - = _('Starting Message') - .col-md-8 - = h(@action.options[:ae_message]) - .form-group - %label.control-label.col-md-2 - = _('Request') - .col-md-8 - = h(@action.options[:ae_request]) - %h4 - = _('Attribute/Value Pairs') - .form-horizontal - - if !@action.options[:ae_hash].blank? - - @action.options[:ae_hash].each do |k, v| - .form-group - %label.control-label.col-md-2 - = h(k) - .col-md-8 - = h(v) - - else - = _('No Attribute/Value Pairs found') - %hr - - when "email" - %h3 - = _('E-mail Settings') - .form-horizontal - .form-group - %label.control-label.col-md-2 - = _('From E-mail Address') - .col-md-8 - = h(@action.options[:from]) - .form-group - %label.control-label.col-md-2 - = _('To E-mail Address') - .col-md-8 - = h(@action.options[:to]) - %hr - - when "set_custom_attribute" - %h3 - = _('Set Custom Attribute Settings') - .form-horizontal - .form-group - %label.control-label.col-md-2 - = _('Attribute Name') - .col-md-8 - = h(@action.options[:attribute]) - .form-group - %label.control-label.col-md-2 - = _("Value to Set") - .col-md-8 - = h(@action.options[:value]) - %hr - - when "reconfigure_cpus" - %h3 - = _("Reconfigure CPU") - .form-horizontal - .form-group - %label.control-label.col-md-2 - = _("Number of CPU's") - .col-md-8 - = h(@action.options[:value]) - %hr - - when "reconfigure_memory" - %h3 - = _("Reconfigure Memory") - .form-horizontal - .form-group - %label.control-label.col-md-2 - = _("Memory Size") - .col-md-8 - = "#{h(@action.options[:value])} MB" - %hr - - when "tag" - %h3 - = _("Applied Tag") - .form-horizontal - .form-group - %label.control-label.col-md-2 - = _("Tag") - .col-md-8 - = h(Classification.tag2human(@action.options[:tags].first)) - %hr - - when "snmp_trap" - %h3 - = _("SNMP Trap") - .form-horizontal - .form-group - %label.control-label.col-md-2 - = _("Host") - .col-md-8 - = h(@action.options[:host]) - .form-group - %label.control-label.col-md-2 - = _("Version") - .col-md-8 - = h(@action.options[:snmp_version]) - - trap_text = @action.options[:snmp_version] == "v1" || @action.options[:snmp_version].nil? ? _("Trap Number") : _("Trap Object ID") - .form-group - %label.control-label.col-md-2 - = trap_text - .col-md-8 - = h(@action.options[:trap_id]) - %hr - %h3 - = _("Variables") - - if @action.options.fetch(:variables, []).empty? - = render :partial => 'layouts/info_msg', :locals => {:message => _('No variables configured.')} - - else - %table.table.table-striped.table-bordered.table-hover - %thead - %tr - %th= _('Object ID') - %th= _('Type') - %th= _('Value') - %tbody - - @action.options[:variables].each do |var| - - unless var[:oid].blank? - %tr - %td - = h(var[:oid]) - %td - = h(var[:var_type]) - %td - = h(var[:value]) - %hr - - when "assign_scan_profile" - %h3 - = _("Analysis Profile") - .form-horizontal - .form-group - %label.control-label.col-md-2 - = _("Assigned Analysis Profile") - .col-md-8 - = h(@action.options[:scan_item_set_name]) - %hr - - when "evaluate_alerts" - %h3 - = _("Alerts to Evaluate") - - if @alert_guids.empty? - = render :partial => 'layouts/info_msg', :locals => {:message => _("No Alerts have been selected.")} - - else - %table.table.table-striped.table-bordered.table-hover - %tbody - - @alert_guids.sort_by(&:description).each do |alert| - - id = "al-#{alert.id}" - %tr{:title => _('View This Alert'), - :onclick => remote_function(:url => "/miq_policy/x_show/#{id}?accord=alert")} - %td.table-view-pf-select - %i.pficon.pficon-warning-triangle-o - = alert.description - %hr - - when "inherit_parent_tags" - %h3 - = _("Inherit Tags") - .form-horizontal - .form-group - %label.control-label.col-md-2 - = _("Parent Type") - .col-md-8 - = h(ui_lookup(:table => @action.options[:parent_type])) - .form-group - %label.control-label.col-md-2 - = _("Categories") - .col-md-8 - = h(@cats) - %hr - - when "remove_tags" - %h3 - = _("Remove Tags") - .form-horizontal - .form-group - %label.control-label.col-md-2 - = _("Categories") - .col-md-8 - = h(@cats) - %hr + %hr + - when "delete_snapshots_by_age" + %h3= _('Snapshot Age Settings') + .form-horizontal + .form-group + %label.control-label.col-md-2= _('Delete if older than') + .col-md-8 + %p.form-control-static= h(MiqPolicyHelper::SNAPSHOT_AGES[@record.options[:age]]) - - if x_active_tree == :action_tree - %h3= _("Assigned to Policies") - - if @action_policies.empty? - = render :partial => 'layouts/info_msg', :locals => {:message => _("This Action is not assigned to any Policies.")} - - else - %table.table.table-striped.table-bordered.table-hover - %tbody - - @action_policies.each do |p| - - id = "xx-#{p.mode.downcase}_xx-#{p.mode.downcase}-#{p.towhat.camelize(:lower)}_p-#{p.id}" + %hr + - when "custom_automation" + %h3 + = _('Custom Automation') + .form-horizontal + .form-group + .col-md-8 + %h4 + = _('Object Details') + .form-horizontal + .form-group + %label.control-label.col-md-2 + = _('Starting Message') + .col-md-8 + = h(@record.options[:ae_message]) + .form-group + %label.control-label.col-md-2 + = _('Request') + .col-md-8 + = h(@record.options[:ae_request]) + %h4 + = _('Attribute/Value Pairs') + .form-horizontal + - if !@record.options[:ae_hash].blank? + - @record.options[:ae_hash].each do |k, v| + .form-group + %label.control-label.col-md-2 + = h(k) + .col-md-8 + = h(v) + - else + = _('No Attribute/Value Pairs found') + %hr + - when "email" + %h3 + = _('E-mail Settings') + .form-horizontal + .form-group + %label.control-label.col-md-2 + = _('From E-mail Address') + .col-md-8 + = h(@record.options[:from]) + .form-group + %label.control-label.col-md-2 + = _('To E-mail Address') + .col-md-8 + = h(@record.options[:to]) + %hr + - when "set_custom_attribute" + %h3 + = _('Set Custom Attribute Settings') + .form-horizontal + .form-group + %label.control-label.col-md-2 + = _('Attribute Name') + .col-md-8 + = h(@record.options[:attribute]) + .form-group + %label.control-label.col-md-2 + = _("Value to Set") + .col-md-8 + = h(@record.options[:value]) + %hr + - when "reconfigure_cpus" + %h3 + = _("Reconfigure CPU") + .form-horizontal + .form-group + %label.control-label.col-md-2 + = _("Number of CPU's") + .col-md-8 + = h(@record.options[:value]) + %hr + - when "reconfigure_memory" + %h3 + = _("Reconfigure Memory") + .form-horizontal + .form-group + %label.control-label.col-md-2 + = _("Memory Size") + .col-md-8 + = "#{h(@record.options[:value])} MB" + %hr + - when "tag" + %h3 + = _("Applied Tag") + .form-horizontal + .form-group + %label.control-label.col-md-2 + = _("Tag") + .col-md-8 + = h(Classification.tag2human(@record.options[:tags].first)) + %hr + - when "snmp_trap" + %h3 + = _("SNMP Trap") + .form-horizontal + .form-group + %label.control-label.col-md-2 + = _("Host") + .col-md-8 + = h(@record.options[:host]) + .form-group + %label.control-label.col-md-2 + = _("Version") + .col-md-8 + = h(@record.options[:snmp_version]) + - trap_text = @record.options[:snmp_version] == "v1" || @record.options[:snmp_version].nil? ? _("Trap Number") : _("Trap Object ID") + .form-group + %label.control-label.col-md-2 + = trap_text + .col-md-8 + = h(@record.options[:trap_id]) + %hr + %h3 + = _("Variables") + - if @record.options.fetch(:variables, []).empty? + = render :partial => 'layouts/info_msg', :locals => {:message => _('No variables configured.')} + - else + %table.table.table-striped.table-bordered.table-hover + %thead + %tr + %th= _('Object ID') + %th= _('Type') + %th= _('Value') + %tbody + - @record.options[:variables].each do |var| + - unless var[:oid].blank? %tr - %td.table-view-pf-select - %i{:class => p.decorate.fonticon} %td - = p.description - %hr + = h(var[:oid]) + %td + = h(var[:var_type]) + %td + = h(var[:value]) + %hr + - when "assign_scan_profile" + %h3 + = _("Analysis Profile") + .form-horizontal + .form-group + %label.control-label.col-md-2 + = _("Assigned Analysis Profile") + .col-md-8 + = h(@record.options[:scan_item_set_name]) + %hr + - when "evaluate_alerts" + %h3 + = _("Alerts to Evaluate") + - if @alert_guids.empty? + = render :partial => 'layouts/info_msg', :locals => {:message => _("No Alerts have been selected.")} + - else + %table.table.table-striped.table-bordered.table-hover + %tbody + - @alert_guids.sort_by(&:description).each do |alert| + - id = "al-#{alert.id}" + %tr{:title => _('View This Alert'), + :onclick => remote_function(:url => "/miq_policy/x_show/#{id}?accord=alert")} + %td.table-view-pf-select + %i.pficon.pficon-warning-triangle-o + = alert.description + %hr + - when "inherit_parent_tags" + %h3 + = _("Inherit Tags") + .form-horizontal + .form-group + %label.control-label.col-md-2 + = _("Parent Type") + .col-md-8 + = h(ui_lookup(:table => @record.options[:parent_type])) + .form-group + %label.control-label.col-md-2 + = _("Categories") + .col-md-8 + = h(@cats) + %hr + - when "remove_tags" + %h3 + = _("Remove Tags") + .form-horizontal + .form-group + %label.control-label.col-md-2 + = _("Categories") + .col-md-8 + = h(@cats) + %hr + + %h3= _("Assigned to Policies") + - if @action_policies + %table.table.table-striped.table-bordered.table-hover + %tbody + - @action_policies.each do |p| + %tr + %td.table-view-pf-select + %i{:class => p.decorate.fonticon} + %td + = p.description + - else + = render :partial => 'layouts/info_msg', :locals => {:message => _("This Action is not assigned to any Policies.")} + + %hr + %br/ + - if @edit + - unless @edit[:rec_id] + %table{:width => "100%"} + %tr + %td{:align => 'right'} + = button_tag(t = _("Add"), + :class => 'btn btn-primary', + :alt => t, + :title => t, + :onclick => "miqAjaxButton('#{url_for_only_path(:action => 'edit', + :button => "add")}');") + = button_tag(t = _("Cancel"), + :class => 'btn btn-default', + :alt => t, + :title => t, + :onclick => "miqAjaxButton('#{url_for_only_path(:action => 'edit', + :button => "cancel")}');") + - else + = render :partial => '/layouts/edit_form_buttons', + :locals => {:action_url => "edit", :record_id => @edit[:rec_id], :ajax_buttons => true} diff --git a/app/views/miq_action/edit.html.haml b/app/views/miq_action/edit.html.haml new file mode 100644 index 000000000000..4791282b43b1 --- /dev/null +++ b/app/views/miq_action/edit.html.haml @@ -0,0 +1 @@ += render :partial => 'action_details' diff --git a/app/views/miq_action/explorer.html.haml b/app/views/miq_action/explorer.html.haml deleted file mode 100644 index ae706a7c9041..000000000000 --- a/app/views/miq_action/explorer.html.haml +++ /dev/null @@ -1,9 +0,0 @@ -- content_for :search do - = render(:partial => "layouts/x_adv_searchbox", :locals => {:nameonly => true}) - -#main_div - - case @nodetype - - when "root" - = render :partial => "action_list" - - when "a", "ta", "fa" - = render :partial => "action_details", :locals => {:read_only => true} diff --git a/app/views/miq_action/new.html.haml b/app/views/miq_action/new.html.haml new file mode 100644 index 000000000000..4791282b43b1 --- /dev/null +++ b/app/views/miq_action/new.html.haml @@ -0,0 +1 @@ += render :partial => 'action_details' diff --git a/app/views/miq_action/show.html.haml b/app/views/miq_action/show.html.haml new file mode 100644 index 000000000000..4791282b43b1 --- /dev/null +++ b/app/views/miq_action/show.html.haml @@ -0,0 +1 @@ += render :partial => 'action_details' diff --git a/app/views/miq_action/_action_list.html.haml b/app/views/miq_action/show_list.html.haml similarity index 100% rename from app/views/miq_action/_action_list.html.haml rename to app/views/miq_action/show_list.html.haml diff --git a/config/routes.rb b/config/routes.rb index 23e63a91bcb0..b9977e35099f 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -2135,17 +2135,18 @@ :miq_action => { :get => %w( - explorer + edit + new + show + show_list ), :post => %w( miq_action_edit action_field_changed - button - reload - tree_autoload - tree_select - ) + - x_post + edit + show + show_list + ) }, :miq_alert => { diff --git a/spec/controllers/miq_action_controller_spec.rb b/spec/controllers/miq_action_controller_spec.rb index 8591e4804d33..aefd6f4141d4 100644 --- a/spec/controllers/miq_action_controller_spec.rb +++ b/spec/controllers/miq_action_controller_spec.rb @@ -1,112 +1,109 @@ describe MiqActionController do - before do - login_as user_with_feature(%w[miq_action_edit miq_action_new]) + before { stub_user(:features => :all) } + + describe "#show_list" do + render_views + + it "renders index" do + get :index + expect(response.status).to eq(302) + expect(response).to redirect_to(:action => 'show_list') + end end context "#action_edit" do before do @action = FactoryBot.create(:miq_action, :name => "Test_Action") - controller.instance_variable_set(:@sb, {}) - allow(controller).to receive(:replace_right_cell) - allow(controller).to receive(:action_build_cat_tree) - allow(controller).to receive(:get_node_info) - allow(controller).to receive(:action_get_info) + controller.instance_variable_set(:@lastaction, "show") end it "first time in" do - controller.miq_action_edit + controller.edit expect(controller.send(:flash_errors?)).not_to be_truthy end it "Test reset button" do - controller.params = {:id => @action.id, :button => "reset"} - controller.miq_action_edit - expect(assigns(:flash_array).first[:message]).to include("reset") - expect(controller.send(:flash_errors?)).not_to be_truthy + controller.params = {:button => "reset", :id => @action.id} + expect(controller).to receive(:javascript_redirect).with(:action => 'edit', + :id => @action.id, + :flash_msg => _("All changes have been reset"), + :flash_warning => true) + controller.send(:edit) end it "Test cancel button" do - controller.instance_variable_set(:@sb, :trees => {:action_tree => {:active_node => "a-#{@action.id}"}}, :active_tree => :action_tree) - controller.params = {:id => @action.id, :button => "cancel"} - controller.miq_action_edit - expect(assigns(:flash_array).first[:message]).to include("cancelled") - expect(controller.send(:flash_errors?)).not_to be_truthy + controller.params = {:button => "cancel", :id => @action.id} + expect(controller).to receive(:javascript_redirect).with(:action => 'show', + :flash_msg => _("Edit of Action \"%{name}\" was cancelled by the user") % {:name => @action.description}, + :id => @action.id) + controller.send(:edit) end it "Test saving an action without selecting a Tag" do - controller.params = {:id => @action.id} - controller.miq_action_edit - expect(controller.send(:flash_errors?)).not_to be_truthy - edit = controller.instance_variable_get(:@edit) + edit = {:key => "miq_action_edit__#{@action.id}", :new => {:description => @action.description, :options => {}, :attrs => {}} } edit[:new][:action_type] = "tag" + controller.instance_variable_set(:@edit, edit) session[:edit] = assigns(:edit) controller.params = {:id => @action.id, :button => "save"} - expect(controller).to receive(:render) - controller.miq_action_edit + expect(controller).to receive(:javascript_flash) + controller.edit expect(assigns(:flash_array).first[:message]).to include("At least one Tag") - expect(assigns(:flash_array).first[:message]).not_to include("saved") - expect(controller.send(:flash_errors?)).to be_truthy end it "Test saving an action after selecting a Tag" do - controller.params = {:id => @action.id} - controller.miq_action_edit - expect(controller.send(:flash_errors?)).not_to be_truthy - edit = controller.instance_variable_get(:@edit) + edit = {:key => "miq_action_edit__#{@action.id}", :new => {:description => "test", :options => {}, :attrs => {}} } edit[:new][:action_type] = "tag" - edit[:new][:options] = {} edit[:new][:options][:tags] = "Some Tag" + controller.instance_variable_set(:@edit, edit) session[:edit] = assigns(:edit) controller.params = {:id => @action.id, :button => "save"} - controller.miq_action_edit - expect(assigns(:flash_array).first[:message]).not_to include("At least one Tag") - expect(assigns(:flash_array).first[:message]).to include("saved") - expect(controller.send(:flash_errors?)).not_to be_truthy + expect(controller).to receive(:javascript_redirect).with(:action => 'show', + :controller=> "miq_action", + :flash_msg => "Action \"test\" was saved", + :id => @action.id) + controller.edit end it "can edit an Ansible playbook action" do - controller.params = {:id => @action.id} - controller.miq_action_edit - edit = controller.instance_variable_get(:@edit) + edit = {:key => "miq_action_edit__#{@action.id}", :new => {:description => "test", :options => {}, :attrs => {}} } edit[:new][:action_type] = "run_ansible_playbook" edit[:new][:inventory_type] = 'manual' edit[:new][:options][:hosts] = 'host1, host2' edit[:new][:options][:service_template_id] = '01' + controller.instance_variable_set(:@edit, edit) session[:edit] = assigns(:edit) controller.params = {:id => @action.id, :button => "save"} - controller.miq_action_edit - expect(assigns(:flash_array).first[:message]).not_to include("At least one Playbook") - expect(assigns(:flash_array).first[:message]).to include("saved") - expect(controller.send(:flash_errors?)).not_to be_truthy + expect(controller).to receive(:javascript_redirect).with(:action => 'show', + :controller=> "miq_action", + :flash_msg => "Action \"test\" was saved", + :id => @action.id) + controller.edit end it "displays an error if no Ansible playbook is selected" do - allow(controller).to receive(:javascript_flash) - controller.params = {:id => @action.id} - controller.miq_action_edit - edit = controller.instance_variable_get(:@edit) + edit = {:key => "miq_action_edit__#{@action.id}", :new => {:description => "test", :options => {}, :attrs => {}} } edit[:new][:action_type] = "run_ansible_playbook" edit[:new][:inventory_type] = 'event_target' edit[:new][:options][:use_event_target] = true edit[:new][:options][:use_event_localhost] = false + controller.instance_variable_set(:@edit, edit) session[:edit] = assigns(:edit) controller.params = {:id => @action.id, :button => "save"} - controller.miq_action_edit + expect(controller).to receive(:javascript_flash) + controller.edit expect(assigns(:flash_array).first[:message]).to include("An Ansible Playbook must be selected") - expect(controller.send(:flash_errors?)).to be_truthy end it "displays an error if no hosts are slected for an Ansible playbook with 'manual' inventory" do - allow(controller).to receive(:javascript_flash) - controller.params = {:id => @action.id} - controller.miq_action_edit - edit = controller.instance_variable_get(:@edit) + edit = {:key => "miq_action_edit__#{@action.id}", :new => {:description => "test", :options => {}, :attrs => {}} } edit[:new][:action_type] = "run_ansible_playbook" edit[:new][:inventory_type] = 'manual' edit[:new][:options][:service_template_id] = '01' + controller.instance_variable_set(:@edit, edit) session[:edit] = assigns(:edit) controller.params = {:id => @action.id, :button => "save"} - controller.miq_action_edit + expect(controller).to receive(:javascript_flash) + controller.edit expect(assigns(:flash_array).first[:message]).to include("At least one host must be specified for manual mode") expect(controller.send(:flash_errors?)).to be_truthy end @@ -119,7 +116,7 @@ attrs = [["a1", "v1"], ["a2", "v2"], ["a3", "v3"], ["a4", "v4"], ["a5", "v5"]] edit = { :rec_id => @action.id, - :key => "action_edit__#{@action.id}", + :key => "miq_action_edit__#{@action.id}", :new => {:description => "foo", :options => options, :attrs => attrs} } edit[:current] = copy_hash(edit[:new]) @@ -154,13 +151,10 @@ end end - describe "#action_get_info" do + describe "#show" do let(:cat1) { FactoryBot.create(:classification, :description => res.first) } let(:cat2) { FactoryBot.create(:classification, :description => res.second) } - before do - controller.instance_variable_set(:@sb, :active_tree => :action_tree) - end let(:res) { %w(test1 test2) } let(:action) do @@ -169,8 +163,10 @@ :options => {:cats => [cat1.name, cat2.name]}) end - it "joins classification tags" do - controller.send(:action_get_info, action) + it "render show" do + get(:show, :params => {:id => action.id}) + + expect(response.status).to eq(200) expect(controller.instance_variable_get(:@cats)).to eq(res.join(' | ')) end end