##// END OF EJS Templates
Fixes menu translation....
Jean-Philippe Lang -
r2434:9819a6bfd1bf
parent child
Show More
@@ -1,216 +1,219
1 # redMine - project management software
1 # redMine - project management software
2 # Copyright (C) 2006-2007 Jean-Philippe Lang
2 # Copyright (C) 2006-2007 Jean-Philippe Lang
3 #
3 #
4 # This program is free software; you can redistribute it and/or
4 # This program is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU General Public License
5 # modify it under the terms of the GNU General Public License
6 # as published by the Free Software Foundation; either version 2
6 # as published by the Free Software Foundation; either version 2
7 # of the License, or (at your option) any later version.
7 # of the License, or (at your option) any later version.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU General Public License
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software
15 # along with this program; if not, write to the Free Software
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17
17
18 module Redmine
18 module Redmine
19 module MenuManager
19 module MenuManager
20 module MenuController
20 module MenuController
21 def self.included(base)
21 def self.included(base)
22 base.extend(ClassMethods)
22 base.extend(ClassMethods)
23 end
23 end
24
24
25 module ClassMethods
25 module ClassMethods
26 @@menu_items = Hash.new {|hash, key| hash[key] = {:default => key, :actions => {}}}
26 @@menu_items = Hash.new {|hash, key| hash[key] = {:default => key, :actions => {}}}
27 mattr_accessor :menu_items
27 mattr_accessor :menu_items
28
28
29 # Set the menu item name for a controller or specific actions
29 # Set the menu item name for a controller or specific actions
30 # Examples:
30 # Examples:
31 # * menu_item :tickets # => sets the menu name to :tickets for the whole controller
31 # * menu_item :tickets # => sets the menu name to :tickets for the whole controller
32 # * menu_item :tickets, :only => :list # => sets the menu name to :tickets for the 'list' action only
32 # * menu_item :tickets, :only => :list # => sets the menu name to :tickets for the 'list' action only
33 # * menu_item :tickets, :only => [:list, :show] # => sets the menu name to :tickets for 2 actions only
33 # * menu_item :tickets, :only => [:list, :show] # => sets the menu name to :tickets for 2 actions only
34 #
34 #
35 # The default menu item name for a controller is controller_name by default
35 # The default menu item name for a controller is controller_name by default
36 # Eg. the default menu item name for ProjectsController is :projects
36 # Eg. the default menu item name for ProjectsController is :projects
37 def menu_item(id, options = {})
37 def menu_item(id, options = {})
38 if actions = options[:only]
38 if actions = options[:only]
39 actions = [] << actions unless actions.is_a?(Array)
39 actions = [] << actions unless actions.is_a?(Array)
40 actions.each {|a| menu_items[controller_name.to_sym][:actions][a.to_sym] = id}
40 actions.each {|a| menu_items[controller_name.to_sym][:actions][a.to_sym] = id}
41 else
41 else
42 menu_items[controller_name.to_sym][:default] = id
42 menu_items[controller_name.to_sym][:default] = id
43 end
43 end
44 end
44 end
45 end
45 end
46
46
47 def menu_items
47 def menu_items
48 self.class.menu_items
48 self.class.menu_items
49 end
49 end
50
50
51 # Returns the menu item name according to the current action
51 # Returns the menu item name according to the current action
52 def current_menu_item
52 def current_menu_item
53 @current_menu_item ||= menu_items[controller_name.to_sym][:actions][action_name.to_sym] ||
53 @current_menu_item ||= menu_items[controller_name.to_sym][:actions][action_name.to_sym] ||
54 menu_items[controller_name.to_sym][:default]
54 menu_items[controller_name.to_sym][:default]
55 end
55 end
56
56
57 # Redirects user to the menu item of the given project
57 # Redirects user to the menu item of the given project
58 # Returns false if user is not authorized
58 # Returns false if user is not authorized
59 def redirect_to_project_menu_item(project, name)
59 def redirect_to_project_menu_item(project, name)
60 item = Redmine::MenuManager.items(:project_menu).detect {|i| i.name.to_s == name.to_s}
60 item = Redmine::MenuManager.items(:project_menu).detect {|i| i.name.to_s == name.to_s}
61 if item && User.current.allowed_to?(item.url, project) && (item.condition.nil? || item.condition.call(project))
61 if item && User.current.allowed_to?(item.url, project) && (item.condition.nil? || item.condition.call(project))
62 redirect_to({item.param => project}.merge(item.url))
62 redirect_to({item.param => project}.merge(item.url))
63 return true
63 return true
64 end
64 end
65 false
65 false
66 end
66 end
67 end
67 end
68
68
69 module MenuHelper
69 module MenuHelper
70 # Returns the current menu item name
70 # Returns the current menu item name
71 def current_menu_item
71 def current_menu_item
72 @controller.current_menu_item
72 @controller.current_menu_item
73 end
73 end
74
74
75 # Renders the application main menu
75 # Renders the application main menu
76 def render_main_menu(project)
76 def render_main_menu(project)
77 render_menu((project && !project.new_record?) ? :project_menu : :application_menu, project)
77 render_menu((project && !project.new_record?) ? :project_menu : :application_menu, project)
78 end
78 end
79
79
80 def render_menu(menu, project=nil)
80 def render_menu(menu, project=nil)
81 links = []
81 links = []
82 menu_items_for(menu, project) do |item, caption, url, selected|
82 menu_items_for(menu, project) do |item, caption, url, selected|
83 links << content_tag('li',
83 links << content_tag('li',
84 link_to(h(caption), url, item.html_options(:selected => selected)))
84 link_to(h(caption), url, item.html_options(:selected => selected)))
85 end
85 end
86 links.empty? ? nil : content_tag('ul', links.join("\n"))
86 links.empty? ? nil : content_tag('ul', links.join("\n"))
87 end
87 end
88
88
89 def menu_items_for(menu, project=nil)
89 def menu_items_for(menu, project=nil)
90 items = []
90 items = []
91 Redmine::MenuManager.allowed_items(menu, User.current, project).each do |item|
91 Redmine::MenuManager.allowed_items(menu, User.current, project).each do |item|
92 unless item.condition && !item.condition.call(project)
92 unless item.condition && !item.condition.call(project)
93 url = case item.url
93 url = case item.url
94 when Hash
94 when Hash
95 project.nil? ? item.url : {item.param => project}.merge(item.url)
95 project.nil? ? item.url : {item.param => project}.merge(item.url)
96 when Symbol
96 when Symbol
97 send(item.url)
97 send(item.url)
98 else
98 else
99 item.url
99 item.url
100 end
100 end
101 caption = item.caption(project)
101 caption = item.caption(project)
102 caption = l_or_humanize(caption, :prefix => 'label_') if caption.is_a?(Symbol)
103 if block_given?
102 if block_given?
104 yield item, caption, url, (current_menu_item == item.name)
103 yield item, caption, url, (current_menu_item == item.name)
105 else
104 else
106 items << [item, caption, url, (current_menu_item == item.name)]
105 items << [item, caption, url, (current_menu_item == item.name)]
107 end
106 end
108 end
107 end
109 end
108 end
110 return block_given? ? nil : items
109 return block_given? ? nil : items
111 end
110 end
112 end
111 end
113
112
114 class << self
113 class << self
115 def map(menu_name)
114 def map(menu_name)
116 @items ||= {}
115 @items ||= {}
117 mapper = Mapper.new(menu_name.to_sym, @items)
116 mapper = Mapper.new(menu_name.to_sym, @items)
118 if block_given?
117 if block_given?
119 yield mapper
118 yield mapper
120 else
119 else
121 mapper
120 mapper
122 end
121 end
123 end
122 end
124
123
125 def items(menu_name)
124 def items(menu_name)
126 @items[menu_name.to_sym] || []
125 @items[menu_name.to_sym] || []
127 end
126 end
128
127
129 def allowed_items(menu_name, user, project)
128 def allowed_items(menu_name, user, project)
130 project ? items(menu_name).select {|item| user && user.allowed_to?(item.url, project)} : items(menu_name)
129 project ? items(menu_name).select {|item| user && user.allowed_to?(item.url, project)} : items(menu_name)
131 end
130 end
132 end
131 end
133
132
134 class Mapper
133 class Mapper
135 def initialize(menu, items)
134 def initialize(menu, items)
136 items[menu] ||= []
135 items[menu] ||= []
137 @menu = menu
136 @menu = menu
138 @menu_items = items[menu]
137 @menu_items = items[menu]
139 end
138 end
140
139
141 @@last_items_count = Hash.new {|h,k| h[k] = 0}
140 @@last_items_count = Hash.new {|h,k| h[k] = 0}
142
141
143 # Adds an item at the end of the menu. Available options:
142 # Adds an item at the end of the menu. Available options:
144 # * param: the parameter name that is used for the project id (default is :id)
143 # * param: the parameter name that is used for the project id (default is :id)
145 # * if: a Proc that is called before rendering the item, the item is displayed only if it returns true
144 # * if: a Proc that is called before rendering the item, the item is displayed only if it returns true
146 # * caption that can be:
145 # * caption that can be:
147 # * a localized string Symbol
146 # * a localized string Symbol
148 # * a String
147 # * a String
149 # * a Proc that can take the project as argument
148 # * a Proc that can take the project as argument
150 # * before, after: specify where the menu item should be inserted (eg. :after => :activity)
149 # * before, after: specify where the menu item should be inserted (eg. :after => :activity)
151 # * last: menu item will stay at the end (eg. :last => true)
150 # * last: menu item will stay at the end (eg. :last => true)
152 # * html_options: a hash of html options that are passed to link_to
151 # * html_options: a hash of html options that are passed to link_to
153 def push(name, url, options={})
152 def push(name, url, options={})
154 options = options.dup
153 options = options.dup
155
154
156 # menu item position
155 # menu item position
157 if before = options.delete(:before)
156 if before = options.delete(:before)
158 position = @menu_items.collect(&:name).index(before)
157 position = @menu_items.collect(&:name).index(before)
159 elsif after = options.delete(:after)
158 elsif after = options.delete(:after)
160 position = @menu_items.collect(&:name).index(after)
159 position = @menu_items.collect(&:name).index(after)
161 position += 1 unless position.nil?
160 position += 1 unless position.nil?
162 elsif options.delete(:last)
161 elsif options.delete(:last)
163 position = @menu_items.size
162 position = @menu_items.size
164 @@last_items_count[@menu] += 1
163 @@last_items_count[@menu] += 1
165 end
164 end
166 # default position
165 # default position
167 position ||= @menu_items.size - @@last_items_count[@menu]
166 position ||= @menu_items.size - @@last_items_count[@menu]
168
167
169 @menu_items.insert(position, MenuItem.new(name, url, options))
168 @menu_items.insert(position, MenuItem.new(name, url, options))
170 end
169 end
171
170
172 # Removes a menu item
171 # Removes a menu item
173 def delete(name)
172 def delete(name)
174 @menu_items.delete_if {|i| i.name == name}
173 @menu_items.delete_if {|i| i.name == name}
175 end
174 end
176 end
175 end
177
176
178 class MenuItem
177 class MenuItem
179 include Redmine::I18n
178 include Redmine::I18n
180 attr_reader :name, :url, :param, :condition
179 attr_reader :name, :url, :param, :condition
181
180
182 def initialize(name, url, options)
181 def initialize(name, url, options)
183 raise "Invalid option :if for menu item '#{name}'" if options[:if] && !options[:if].respond_to?(:call)
182 raise "Invalid option :if for menu item '#{name}'" if options[:if] && !options[:if].respond_to?(:call)
184 raise "Invalid option :html for menu item '#{name}'" if options[:html] && !options[:html].is_a?(Hash)
183 raise "Invalid option :html for menu item '#{name}'" if options[:html] && !options[:html].is_a?(Hash)
185 @name = name
184 @name = name
186 @url = url
185 @url = url
187 @condition = options[:if]
186 @condition = options[:if]
188 @param = options[:param] || :id
187 @param = options[:param] || :id
189 @caption = options[:caption] || @name
188 @caption = options[:caption]
190 @html_options = options[:html] || {}
189 @html_options = options[:html] || {}
191 # Adds a unique class to each menu item based on its name
190 # Adds a unique class to each menu item based on its name
192 @html_options[:class] = [@html_options[:class], @name.to_s.dasherize].compact.join(' ')
191 @html_options[:class] = [@html_options[:class], @name.to_s.dasherize].compact.join(' ')
193 end
192 end
194
193
195 def caption(project=nil)
194 def caption(project=nil)
196 if @caption.is_a?(Proc)
195 if @caption.is_a?(Proc)
197 c = @caption.call(project).to_s
196 c = @caption.call(project).to_s
198 c = @name.to_s.humanize if c.blank?
197 c = @name.to_s.humanize if c.blank?
199 c
198 c
200 else
199 else
201 @caption
200 if @caption.nil?
201 l_or_humanize(name, :prefix => 'label_')
202 else
203 @caption.is_a?(Symbol) ? l(@caption) : @caption
204 end
202 end
205 end
203 end
206 end
204
207
205 def html_options(options={})
208 def html_options(options={})
206 if options[:selected]
209 if options[:selected]
207 o = @html_options.dup
210 o = @html_options.dup
208 o[:class] += ' selected'
211 o[:class] += ' selected'
209 o
212 o
210 else
213 else
211 @html_options
214 @html_options
212 end
215 end
213 end
216 end
214 end
217 end
215 end
218 end
216 end
219 end
General Comments 0
You need to be logged in to leave comments. Login now