Skip to content

Commit

Permalink
Merge pull request #3347 from martinpovolny/menu_plug
Browse files Browse the repository at this point in the history
Menu pluggability improvements
(cherry picked from commit 19b59d9)
  • Loading branch information
himdel authored and simaishi committed May 31, 2018
1 parent 0c1876e commit 99b027b
Show file tree
Hide file tree
Showing 5 changed files with 93 additions and 16 deletions.
4 changes: 2 additions & 2 deletions app/presenters/menu/item.rb
@@ -1,5 +1,5 @@
module Menu
Item = Struct.new(:id, :name, :feature, :rbac_feature, :href, :type, :defaults) do
Item = Struct.new(:id, :name, :feature, :rbac_feature, :href, :type, :parent_id) do
extend ActiveModel::Naming

def self.base_class
Expand All @@ -10,7 +10,7 @@ def self.base_model
model_name
end

def initialize(an_id, a_name, features, rbac_feature, href, type = :default, defaults = nil)
def initialize(an_id, a_name, features, rbac_feature, href, type = :default, parent_id = nil)
super
@parent = nil
@name = a_name.kind_of?(Proc) ? a_name : -> { a_name }
Expand Down
21 changes: 15 additions & 6 deletions app/presenters/menu/manager.rb
Expand Up @@ -74,23 +74,32 @@ def initialize
def merge_sections(sections)
sections.each do |section|
position = nil

parent = if section.parent_id && @id_to_section.key?(section.parent_id)
@id_to_section[section.parent_id].items
else
@menu
end

if section.before
position = @menu.index { |existing_section| existing_section.id == section.before }
position = parent.index { |existing_section| existing_section.id == section.before }
end

if position
@menu.insert(position, section)
parent.insert(position, section)
else
@menu << section
parent << section
end
end
end

def merge_items(items)
items.each do |item|
raise InvalidMenuDefinition, 'Invalid parent' unless @id_to_section.key?(item.parent)
@id_to_section[item.parent].items << item
item.parent = @id_to_section[item.parent]
parent = @id_to_section[item.parent_id]
raise InvalidMenuDefinition, 'Invalid parent' if parent.nil?

parent.items << item
item.parent = parent
end
end

Expand Down
2 changes: 1 addition & 1 deletion app/presenters/menu/section.rb
@@ -1,5 +1,5 @@
module Menu
Section = Struct.new(:id, :name, :icon, :items, :placement, :before, :type, :href) do
Section = Struct.new(:id, :name, :icon, :items, :placement, :before, :type, :href, :parent_id) do
extend ActiveModel::Naming

def self.base_class
Expand Down
16 changes: 9 additions & 7 deletions app/presenters/menu/yaml_loader.rb
Expand Up @@ -33,13 +33,15 @@ def create_custom_menu_item(properties)
raise Menu::Manager::InvalidMenuDefinition,
"incomplete definition -- missing #{property}" if properties[property].blank?
end
item = Item.new(properties['id'],
properties['name'],
properties['feature'],
rbac,
properties['href'],
item_type)
item.parent = properties['parent'].to_sym
item = Item.new(
properties['id'],
properties['name'],
properties['feature'],
rbac,
properties['href'],
item_type,
properties['parent'].to_sym
)
item
end

Expand Down
66 changes: 66 additions & 0 deletions spec/presenters/menu/custom_loader_spec.rb
@@ -0,0 +1,66 @@
describe Menu::CustomLoader do
before :each do
Singleton.__init__(Menu::Manager)
Singleton.__init__(Menu::CustomLoader)
end

context '.register' do
it 'loads custom menu items' do
# create custom section with 2 custom items
described_class.register(
Menu::Section.new(:spike, N_('Plugin'), 'fa fa-map-pin', [
Menu::Item.new('plug1', N_('Test'), 'miq_report', {:feature => 'miq_report', :any => true}, '/plug'),
Menu::Item.new('plug2', N_('Demo'), 'miq_report', {:feature => 'miq_report', :any => true}, '/demo')
])
)

expect(Menu::Manager.item('plug1')).to be
expect(Menu::Manager.item('plug2')).to be
end

it 'loads a custom menu item under an existing section' do
# create custom item placed in an existing section 'vi' (Cloud Intel)
described_class.register(
Menu::Item.new('plug3', N_('Plug Item'), 'miq_report', {:feature => 'miq_report', :any => true}, '/demo', :default, :vi)
)

item = Menu::Manager.item('plug3')
expect(item).to be
expect(item.parent.id).to eq(:vi)
end

it 'loads a custom menu section and places it before an existing section' do
# create custom section and place it before existing section 'compute' (Compute)
described_class.register(
Menu::Section.new(:spike3, N_('Plugin 2'), 'fa fa-map-pin', [
Menu::Item.new('plug4', N_('Demo'), 'miq_report', {:feature => 'miq_report', :any => true}, '/demo')
], :default, :compute)
)

item = Menu::Manager.item('plug4')
expect(item).to be

menu = Menu::Manager.instance.instance_eval { @menu }
compute_index = menu.find_index { |s| s.id == :compute }

expect(menu[compute_index - 1].id).to eq(:spike3)
end

it 'loads a custom menu section and places it at a given position in inside an existing section' do
# create custom section and place it inside an existing section 'compute' (Compute), before existing subsection 'clo' (Cloud)
described_class.register(
Menu::Section.new(:spike3, N_('Nested section after'), 'fa fa-map-pin', [
Menu::Item.new('plug5', N_('Test item'), 'miq_report', {:feature => 'miq_report', :any => true}, '/demo')
], :default, :clo, :default, nil, :compute)
)

item = Menu::Manager.item('plug5')
expect(item).to be

compute_section = Menu::Manager.section(:compute)
spike_index = compute_section.items.find_index { |i| i.id == :spike3 }
clo_index = compute_section.items.find_index { |i| i.id == :clo }
expect(spike_index).to eq(clo_index - 1)
end
end
end

0 comments on commit 99b027b

Please sign in to comment.