Skip to content

Commit

Permalink
Merge pull request #4775 from romanblanco/bz1635738-master
Browse files Browse the repository at this point in the history
Display custom buttons after comming from relationship table

(cherry picked from commit 98b7dd0)

Fixes https://bugzilla.redhat.com/show_bug.cgi?id=1635738
himdel authored and simaishi committed Oct 31, 2018
1 parent c40152c commit 19322da
Showing 11 changed files with 148 additions and 31 deletions.
1 change: 1 addition & 0 deletions app/controllers/application_controller.rb
Original file line number Diff line number Diff line change
@@ -38,6 +38,7 @@ class ApplicationController < ActionController::Base
include Mixins::CustomButtons
include Mixins::CheckedIdMixin
include ParamsHelper
include ApplicationHelper::Toolbar::Mixins::CustomButtonToolbarMixin

helper ToolbarHelper
helper JsHelper
40 changes: 10 additions & 30 deletions app/controllers/application_controller/buttons.rb
Original file line number Diff line number Diff line change
@@ -257,28 +257,6 @@ def open_url_after_dialog
private

BASE_MODEL_EXPLORER_CLASSES = [MiqGroup, MiqTemplate, Service, Switch, Tenant, User, Vm].freeze
APPLIES_TO_CLASS_BASE_MODELS = %w(AvailabilityZone CloudNetwork CloudObjectStoreContainer CloudSubnet CloudTenant
CloudVolume ContainerGroup ContainerImage ContainerNode ContainerProject
ContainerTemplate ContainerVolume EmsCluster ExtManagementSystem
GenericObject GenericObjectDefinition Host LoadBalancer
MiqGroup MiqTemp MiqTemplate NetworkRouter OrchestrationStack SecurityGroup Service
ServiceTemplate Storage Switch Tenant User Vm VmOrTemplate).freeze
def applies_to_class_model(applies_to_class)
# TODO: Give a better name for this concept, including ServiceTemplate using Service
# This should probably live in the model once this concept is defined.
unless APPLIES_TO_CLASS_BASE_MODELS.include?(applies_to_class)
raise ArgumentError, "Received: #{applies_to_class}, expected one of #{APPLIES_TO_CLASS_BASE_MODELS}"
end

case applies_to_class
when "ServiceTemplate"
Service
when "GenericObjectDefinition"
GenericObject
else
applies_to_class.constantize
end
end

def custom_button_done
url = SystemConsole.find_by(:vm => params[:id]).try(:url)
@@ -316,17 +294,19 @@ def sync_playbook_dialog(button)

def custom_buttons(ids = nil, display_options = {})
button = CustomButton.find(params[:button_id])
cls = applies_to_class_model(button.applies_to_class)
cls = custom_button_class_model(button.applies_to_class)
@explorer = true if BASE_MODEL_EXPLORER_CLASSES.include?(cls)
ids ||= params[:id]
if ids.to_s == 'LIST'
objs = Rbac.filtered(cls.where(:id => find_checked_items))
obj = objs.first
else
obj = Rbac.filtered_object(cls.find(ids.to_i))
objs = [obj]
ids ||= params[:id] unless relationship_table_screen? && @record.nil?
ids = find_checked_items if ids == 'LIST' || ids.nil?

if ids.blank?
render_flash(_("Error executing custom button: No item was selected."), :error)
return
end

objs = Rbac.filtered(cls.where(:id => ids))
obj = objs.first

if objs.empty?
render_flash(_("Error executing custom button: No item was selected."), :error)
return
2 changes: 2 additions & 0 deletions app/controllers/mixins/custom_buttons.rb
Original file line number Diff line number Diff line change
@@ -24,6 +24,8 @@ def custom_toolbar_simple
Mixins::CustomButtons::Result.new(:single)
elsif @lastaction == "show_list"
Mixins::CustomButtons::Result.new(:list)
elsif relationship_table_screen?
Mixins::CustomButtons::Result.new(:list)
elsif @display == 'generic_objects'
@lastaction == 'generic_object' ? Mixins::CustomButtons::Result.new(:single) : Mixins::CustomButtons::Result.new(:list)
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
module ApplicationHelper::Toolbar::Mixins::CustomButtonToolbarMixin
# FIXME: replace with CustomButton.button_classes
# (ServiceTemplate, VmOrTemplate, GenericObjectDefinition are exceptions)
APPLIES_TO_CLASS_BASE_MODELS = %w(AvailabilityZone CloudNetwork CloudObjectStoreContainer CloudSubnet CloudTenant
CloudVolume ContainerGroup ContainerImage ContainerNode ContainerProject
ContainerTemplate ContainerVolume EmsCluster ExtManagementSystem
GenericObject GenericObjectDefinition Host LoadBalancer
MiqGroup MiqTemplate NetworkRouter OrchestrationStack
SecurityGroup Service ServiceTemplate Storage Switch Tenant
User Vm VmOrTemplate).freeze

def custom_button_appliable_class?(model)
# FIXME: merge with model replacement in 'custom_button_class_model'
model = "MiqTemplate" if model == "Image"
model = "Vm" if model == "Instance"
model = "ContainerVolume" if model == "PersistentVolume"
model = "ExtManagementSystem" if model == "StorageManager"
APPLIES_TO_CLASS_BASE_MODELS.include?(model)
end

def custom_button_class_model(applies_to_class)
# TODO: Give a better name for this concept, including ServiceTemplate using Service
# 'custom_button_appliable_class' -> 'display_to_model'
# This should probably live in the model once this concept is defined.
unless custom_button_appliable_class?(applies_to_class)
raise ArgumentError, "Received: #{applies_to_class}, expected one of #{APPLIES_TO_CLASS_BASE_MODELS}"
end

case applies_to_class
when "ServiceTemplate"
Service
when "PersistentVolume"
ContainerVolume
when "GenericObjectDefinition"
GenericObject
when "Instance"
Vm
when "Image"
MiqTemplate
when "StorageManager"
ExtManagementSystem
else
applies_to_class.constantize
end
end

# Indicates, whether the user has came from providers relationship screen
# or not
#
# Used to
# - indicate if the custom buttons should be rendered
# - decide where to look for id of checked records
def relationship_table_screen?
return false if @display.nil?
display_class = @display.camelize.singularize
return false unless custom_button_appliable_class?(display_class)

show_action = @lastaction == "show"
display_model = custom_button_class_model(display_class)
# method is accessed twice from a different location - from toolbar builder
# and custom button mixin - and so controller class changes
ctrl = self.class == ApplicationHelper::ToolbarBuilder ? controller : self
controller_model = ctrl.class.model

display_model != controller_model && show_action
end
end
9 changes: 8 additions & 1 deletion app/helpers/application_helper/toolbar_builder.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
class ApplicationHelper::ToolbarBuilder
include MiqAeClassHelper
include RestfulControllerMixin
include ApplicationHelper::Toolbar::Mixins::CustomButtonToolbarMixin

def call(toolbar_name)
build_toolbar(toolbar_name)
@@ -233,7 +234,11 @@ def create_custom_button(input, model, record)
}
button[:text] = button_name if input[:text_display]
button[:onwhen] = '1+' if cb_enabled_for_nested
button[:send_checked] = true if record_id == 'LIST'
if record_id == 'LIST' ||
(@display.present? &&
custom_button_appliable_class?(@display.camelize.singularize))
button[:send_checked] = true
end
button
end

@@ -283,6 +288,8 @@ def custom_toolbar_class(toolbar_result)
if @display == 'generic_objects'
model = GenericObjectDefinition
record = GenericObject.find_by(:id => @sb[:rec_id])
elsif relationship_table_screen?
model = custom_button_class_model(@display.camelize.singularize)
else
model = @record ? @record.class : model_for_custom_toolbar
end
5 changes: 5 additions & 0 deletions spec/controllers/ems_cloud_controller_spec.rb
Original file line number Diff line number Diff line change
@@ -726,4 +726,9 @@ def verify_password_and_confirm(password, verify)
expect(response.body).not_to have_selector("button[title*='Select a filter to set it as my default']", :text => "Set Default")
end
end

%w(availability_zones cloud_tenants security_groups instances images
orchestration_stacks storage_managers).each do |custom_button_class|
include_examples "relationship table screen with custom buttons", custom_button_class
end
end
4 changes: 4 additions & 0 deletions spec/controllers/ems_container_controller_spec.rb
Original file line number Diff line number Diff line change
@@ -375,4 +375,8 @@ def test_setting_few_fields
end

include_examples '#download_summary_pdf', :ems_kubernetes
%w(container_projects container_nodes container_images container_volumes
container_templates).each do |custom_button_class|
include_examples "relationship table screen with custom buttons", custom_button_class
end
end
32 changes: 32 additions & 0 deletions spec/controllers/ems_infra_controller_spec.rb
Original file line number Diff line number Diff line change
@@ -281,6 +281,38 @@

subject { get :show, :params => {:id => @ems.id}.merge(url_params) }

context "display=hosts" do
it 'renders custom buttons for hosts accessed from relationship screen' do
custom_button = FactoryGirl.create(
:custom_button, :name => "My Button", :applies_to_class => "Host",
:visibility => {:roles => ["_ALL_"]},
:options => {:display => true, :open_url => false, :display_for => "both"}
)
custom_button_set = FactoryGirl.create(
:custom_button_set, :set_data => {
:applies_to_class => "Host", :button_order => [custom_button.id]
}
)
custom_button_set.add_member(custom_button)
controller.instance_variable_set(:@record, @ems)
allow(controller).to receive(:controller).and_return(controller)

# format js to avoid redirection (application_controller/explorer.rb#generic_x_show)
get :show, :params => {:id => @ems.id, :display => 'hosts', :format => :js}

toolbar = controller.send(:toolbar_from_hash)
toolbar_custom_button = toolbar.select do |button_group|
button_group&.map do |button|
button if button[:id].starts_with?("custom_")
end&.compact.present?
end.flatten.first

expect(toolbar_custom_button).not_to be_nil
expect(toolbar_custom_button[:items].count).to eql(1)
expect(response.status).to eq(200)
end
end

context "display=timeline" do
let(:url_params) { {:display => 'timeline'} }
it { is_expected.to have_http_status 200 }
4 changes: 4 additions & 0 deletions spec/controllers/ems_network_controller_spec.rb
Original file line number Diff line number Diff line change
@@ -2,4 +2,8 @@
include_examples :shared_examples_for_ems_network_controller, %w(openstack azure google amazon)

it_behaves_like "controller with custom buttons"
%w(cloud_tenants cloud_networks cloud_subnets network_routers security_groups
load_balancers).each do |custom_button_class|
include_examples "relationship table screen with custom buttons", custom_button_class
end
end
4 changes: 4 additions & 0 deletions spec/controllers/vm_infra_controller_spec.rb
Original file line number Diff line number Diff line change
@@ -666,4 +666,8 @@
controller.report_data
expect(assigns(:edit)[:new]).to_not include(:expression)
end

%w(ems_clusters hosts storages vms miq_templates).each do |custom_button_class|
include_examples "relationship table screen with custom buttons", custom_button_class
end
end
11 changes: 11 additions & 0 deletions spec/shared/controllers/shared_example_for_custom_buttons.rb
Original file line number Diff line number Diff line change
@@ -88,3 +88,14 @@
expect(controller.custom_toolbar).to be_a_kind_of Mixins::CustomButtons::Result
end
end

shared_examples 'relationship table screen with custom buttons' do |display|
context "displayed entity is #{display}" do
it "has custom toolbar when navigating through relationship table" do
controller.instance_variable_set(:@display, display)
controller.instance_variable_set(:@lastaction, 'show')
controller.instance_variable_set(:@record, true) # @record is the provider
expect(controller.custom_toolbar).to be_a_kind_of Mixins::CustomButtons::Result
end
end
end

0 comments on commit 19322da

Please sign in to comment.