From b0999e3764f0554d40d243f273f23fe53e164066 Mon Sep 17 00:00:00 2001 From: Eric Davis Date: Wed, 25 Nov 2009 05:36:50 +0000 Subject: Add support for unattached menus (generated dynamically) A MenuItem can define a :child_menus option with a Proc. When the menus are rendered, the Proc will be run and the resulting MenuItems will be added to the page as child menus #4250 git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/trunk@3091 e93f8b46-1217-0410-a6f0-8f06a7374b81 --- lib/redmine/menu_manager.rb | 73 +++++++++++++++++++++++++++++++++++++-------- 1 file changed, 61 insertions(+), 12 deletions(-) (limited to 'lib') diff --git a/lib/redmine/menu_manager.rb b/lib/redmine/menu_manager.rb index debcdd143..320d4a655 100644 --- a/lib/redmine/menu_manager.rb +++ b/lib/redmine/menu_manager.rb @@ -95,6 +95,9 @@ Tree::TreeNode.send(:include, TreeNodePatch) module Redmine module MenuManager + class MenuError < StandardError #:nodoc: + end + module MenuController def self.included(base) base.extend(ClassMethods) @@ -164,27 +167,71 @@ module Redmine end def render_menu_node(node, project=nil) + if node.hasChildren? || !node.child_menus.nil? + return render_menu_node_with_children(node, project) + else + caption, url, selected = extract_node_details(node, project) + return content_tag('li', + render_single_menu_node(node, caption, url, selected)) + end + end + + def render_menu_node_with_children(node, project=nil) caption, url, selected = extract_node_details(node, project) - if node.hasChildren? - html = [] + + html = returning [] do |html| html << '
  • ' - html << render_single_menu_node(node, caption, url, selected) # parent - html << ' ' + + html << content_tag(:ul, standard_children_list, :class => 'menu-children') unless standard_children_list.empty? + + # Unattached children + unattached_children_list = render_unattached_children_menu(node, project) + html << content_tag(:ul, unattached_children_list, :class => 'menu-children unattached') unless unattached_children_list.blank? + html << '
  • ' - return html.join("\n") - else - return content_tag('li', - render_single_menu_node(node, caption, url, selected)) + end + return html.join("\n") + end + + # Returns a list of unattached children menu items + def render_unattached_children_menu(node, project) + return nil unless node.child_menus + + returning "" do |child_html| + unattached_children = node.child_menus.call(project) + # Tree nodes support #each so we need to do object detection + if unattached_children.is_a? Array + unattached_children.each do |child| + child_html << content_tag(:li, render_unattached_menu_item(child, project)) + end + else + raise MenuError, ":child_menus must be an array of MenuItems" + end end end def render_single_menu_node(item, caption, url, selected) link_to(h(caption), url, item.html_options(:selected => selected)) end + + def render_unattached_menu_item(menu_item, project) + raise MenuError, ":child_menus must be an array of MenuItems" unless menu_item.is_a? MenuItem + + if User.current.allowed_to?(menu_item.url, project) + link_to(h(menu_item.caption), + menu_item.url, + menu_item.html_options) + end + end def menu_items_for(menu, project=nil) items = [] @@ -336,12 +383,13 @@ module Redmine class MenuItem < Tree::TreeNode include Redmine::I18n - attr_reader :name, :url, :param, :condition, :parent_menu + attr_reader :name, :url, :param, :condition, :parent_menu, :child_menus def initialize(name, url, options) raise ArgumentError, "Invalid option :if for menu item '#{name}'" if options[:if] && !options[:if].respond_to?(:call) raise ArgumentError, "Invalid option :html for menu item '#{name}'" if options[:html] && !options[:html].is_a?(Hash) raise ArgumentError, "Cannot set the :parent_menu to be the same as this item" if options[:parent_menu] == name.to_sym + raise ArgumentError, "Invalid option :child_menus for menu item '#{name}'" if options[:child_menus] && !options[:child_menus].respond_to?(:call) @name = name @url = url @condition = options[:if] @@ -351,6 +399,7 @@ module Redmine # Adds a unique class to each menu item based on its name @html_options[:class] = [@html_options[:class], @name.to_s.dasherize].compact.join(' ') @parent_menu = options[:parent_menu] + @child_menus = options[:child_menus] super @name.to_sym end -- cgit v1.2.3