##// END OF EJS Templates
Pluggable admin menu (patch #2031 by Yuki Sonoda with slight changes)....
Jean-Philippe Lang -
r2020:d7718470785c
parent child
Show More
@@ -1,41 +1,47
1 <h2><%=l(:label_administration)%></h2>
1 <h2><%=l(:label_administration)%></h2>
2
2
3 <%= render :partial => 'no_data' if @no_configuration_data %>
3 <%= render :partial => 'no_data' if @no_configuration_data %>
4
4
5 <p class="icon22 icon22-projects">
5 <p class="icon22 icon22-projects">
6 <%= link_to l(:label_project_plural), :controller => 'admin', :action => 'projects' %> |
6 <%= link_to l(:label_project_plural), :controller => 'admin', :action => 'projects' %> |
7 <%= link_to l(:label_new), :controller => 'projects', :action => 'add' %>
7 <%= link_to l(:label_new), :controller => 'projects', :action => 'add' %>
8 </p>
8 </p>
9
9
10 <p class="icon22 icon22-users">
10 <p class="icon22 icon22-users">
11 <%= link_to l(:label_user_plural), :controller => 'users' %> |
11 <%= link_to l(:label_user_plural), :controller => 'users' %> |
12 <%= link_to l(:label_new), :controller => 'users', :action => 'add' %>
12 <%= link_to l(:label_new), :controller => 'users', :action => 'add' %>
13 </p>
13 </p>
14
14
15 <p class="icon22 icon22-role">
15 <p class="icon22 icon22-role">
16 <%= link_to l(:label_role_and_permissions), :controller => 'roles' %>
16 <%= link_to l(:label_role_and_permissions), :controller => 'roles' %>
17 </p>
17 </p>
18
18
19 <p class="icon22 icon22-tracker">
19 <p class="icon22 icon22-tracker">
20 <%= link_to l(:label_tracker_plural), :controller => 'trackers' %> |
20 <%= link_to l(:label_tracker_plural), :controller => 'trackers' %> |
21 <%= link_to l(:label_issue_status_plural), :controller => 'issue_statuses' %> |
21 <%= link_to l(:label_issue_status_plural), :controller => 'issue_statuses' %> |
22 <%= link_to l(:label_workflow), :controller => 'workflows', :action => 'edit' %>
22 <%= link_to l(:label_workflow), :controller => 'workflows', :action => 'edit' %>
23 </p>
23 </p>
24
24
25 <p class="icon22 icon22-workflow">
25 <p class="icon22 icon22-workflow">
26 <%= link_to l(:label_custom_field_plural), :controller => 'custom_fields' %>
26 <%= link_to l(:label_custom_field_plural), :controller => 'custom_fields' %>
27 </p>
27 </p>
28
28
29 <p class="icon22 icon22-options">
29 <p class="icon22 icon22-options">
30 <%= link_to l(:label_enumerations), :controller => 'enumerations' %>
30 <%= link_to l(:label_enumerations), :controller => 'enumerations' %>
31 </p>
31 </p>
32
32
33 <p class="icon22 icon22-settings">
33 <p class="icon22 icon22-settings">
34 <%= link_to l(:label_settings), :controller => 'settings' %>
34 <%= link_to l(:label_settings), :controller => 'settings' %>
35 </p>
35 </p>
36
36
37 <% menu_items_for(:admin_menu) do |item, caption, url, selected| -%>
38 <%= content_tag 'p',
39 link_to(h(caption), item.url, item.html_options),
40 :class => ["icon22", "icon22-#{item.name}"].join(' ') %>
41 <% end -%>
42
37 <p class="icon22 icon22-info">
43 <p class="icon22 icon22-info">
38 <%= link_to l(:label_information_plural), :controller => 'admin', :action => 'info' %>
44 <%= link_to l(:label_information_plural), :controller => 'admin', :action => 'info' %>
39 </p>
45 </p>
40
46
41 <% html_title(l(:label_administration)) -%>
47 <% html_title(l(:label_administration)) -%>
@@ -1,159 +1,163
1 require 'redmine/access_control'
1 require 'redmine/access_control'
2 require 'redmine/menu_manager'
2 require 'redmine/menu_manager'
3 require 'redmine/activity'
3 require 'redmine/activity'
4 require 'redmine/mime_type'
4 require 'redmine/mime_type'
5 require 'redmine/core_ext'
5 require 'redmine/core_ext'
6 require 'redmine/themes'
6 require 'redmine/themes'
7 require 'redmine/hook'
7 require 'redmine/hook'
8 require 'redmine/plugin'
8 require 'redmine/plugin'
9 require 'redmine/wiki_formatting'
9 require 'redmine/wiki_formatting'
10
10
11 begin
11 begin
12 require_library_or_gem 'RMagick' unless Object.const_defined?(:Magick)
12 require_library_or_gem 'RMagick' unless Object.const_defined?(:Magick)
13 rescue LoadError
13 rescue LoadError
14 # RMagick is not available
14 # RMagick is not available
15 end
15 end
16
16
17 REDMINE_SUPPORTED_SCM = %w( Subversion Darcs Mercurial Cvs Bazaar Git Filesystem )
17 REDMINE_SUPPORTED_SCM = %w( Subversion Darcs Mercurial Cvs Bazaar Git Filesystem )
18
18
19 # Permissions
19 # Permissions
20 Redmine::AccessControl.map do |map|
20 Redmine::AccessControl.map do |map|
21 map.permission :view_project, {:projects => [:show, :activity]}, :public => true
21 map.permission :view_project, {:projects => [:show, :activity]}, :public => true
22 map.permission :search_project, {:search => :index}, :public => true
22 map.permission :search_project, {:search => :index}, :public => true
23 map.permission :edit_project, {:projects => [:settings, :edit]}, :require => :member
23 map.permission :edit_project, {:projects => [:settings, :edit]}, :require => :member
24 map.permission :select_project_modules, {:projects => :modules}, :require => :member
24 map.permission :select_project_modules, {:projects => :modules}, :require => :member
25 map.permission :manage_members, {:projects => :settings, :members => [:new, :edit, :destroy]}, :require => :member
25 map.permission :manage_members, {:projects => :settings, :members => [:new, :edit, :destroy]}, :require => :member
26 map.permission :manage_versions, {:projects => [:settings, :add_version], :versions => [:edit, :destroy]}, :require => :member
26 map.permission :manage_versions, {:projects => [:settings, :add_version], :versions => [:edit, :destroy]}, :require => :member
27
27
28 map.project_module :issue_tracking do |map|
28 map.project_module :issue_tracking do |map|
29 # Issue categories
29 # Issue categories
30 map.permission :manage_categories, {:projects => [:settings, :add_issue_category], :issue_categories => [:edit, :destroy]}, :require => :member
30 map.permission :manage_categories, {:projects => [:settings, :add_issue_category], :issue_categories => [:edit, :destroy]}, :require => :member
31 # Issues
31 # Issues
32 map.permission :view_issues, {:projects => [:changelog, :roadmap],
32 map.permission :view_issues, {:projects => [:changelog, :roadmap],
33 :issues => [:index, :changes, :show, :context_menu],
33 :issues => [:index, :changes, :show, :context_menu],
34 :versions => [:show, :status_by],
34 :versions => [:show, :status_by],
35 :queries => :index,
35 :queries => :index,
36 :reports => :issue_report}, :public => true
36 :reports => :issue_report}, :public => true
37 map.permission :add_issues, {:issues => :new}
37 map.permission :add_issues, {:issues => :new}
38 map.permission :edit_issues, {:issues => [:edit, :reply, :bulk_edit, :destroy_attachment]}
38 map.permission :edit_issues, {:issues => [:edit, :reply, :bulk_edit, :destroy_attachment]}
39 map.permission :manage_issue_relations, {:issue_relations => [:new, :destroy]}
39 map.permission :manage_issue_relations, {:issue_relations => [:new, :destroy]}
40 map.permission :add_issue_notes, {:issues => [:edit, :reply]}
40 map.permission :add_issue_notes, {:issues => [:edit, :reply]}
41 map.permission :edit_issue_notes, {:journals => :edit}, :require => :loggedin
41 map.permission :edit_issue_notes, {:journals => :edit}, :require => :loggedin
42 map.permission :edit_own_issue_notes, {:journals => :edit}, :require => :loggedin
42 map.permission :edit_own_issue_notes, {:journals => :edit}, :require => :loggedin
43 map.permission :move_issues, {:issues => :move}, :require => :loggedin
43 map.permission :move_issues, {:issues => :move}, :require => :loggedin
44 map.permission :delete_issues, {:issues => :destroy}, :require => :member
44 map.permission :delete_issues, {:issues => :destroy}, :require => :member
45 # Queries
45 # Queries
46 map.permission :manage_public_queries, {:queries => [:new, :edit, :destroy]}, :require => :member
46 map.permission :manage_public_queries, {:queries => [:new, :edit, :destroy]}, :require => :member
47 map.permission :save_queries, {:queries => [:new, :edit, :destroy]}, :require => :loggedin
47 map.permission :save_queries, {:queries => [:new, :edit, :destroy]}, :require => :loggedin
48 # Gantt & calendar
48 # Gantt & calendar
49 map.permission :view_gantt, :issues => :gantt
49 map.permission :view_gantt, :issues => :gantt
50 map.permission :view_calendar, :issues => :calendar
50 map.permission :view_calendar, :issues => :calendar
51 # Watchers
51 # Watchers
52 map.permission :view_issue_watchers, {}
52 map.permission :view_issue_watchers, {}
53 map.permission :add_issue_watchers, {:watchers => :new}
53 map.permission :add_issue_watchers, {:watchers => :new}
54 end
54 end
55
55
56 map.project_module :time_tracking do |map|
56 map.project_module :time_tracking do |map|
57 map.permission :log_time, {:timelog => :edit}, :require => :loggedin
57 map.permission :log_time, {:timelog => :edit}, :require => :loggedin
58 map.permission :view_time_entries, :timelog => [:details, :report]
58 map.permission :view_time_entries, :timelog => [:details, :report]
59 map.permission :edit_time_entries, {:timelog => [:edit, :destroy]}, :require => :member
59 map.permission :edit_time_entries, {:timelog => [:edit, :destroy]}, :require => :member
60 map.permission :edit_own_time_entries, {:timelog => [:edit, :destroy]}, :require => :loggedin
60 map.permission :edit_own_time_entries, {:timelog => [:edit, :destroy]}, :require => :loggedin
61 end
61 end
62
62
63 map.project_module :news do |map|
63 map.project_module :news do |map|
64 map.permission :manage_news, {:news => [:new, :edit, :destroy, :destroy_comment]}, :require => :member
64 map.permission :manage_news, {:news => [:new, :edit, :destroy, :destroy_comment]}, :require => :member
65 map.permission :view_news, {:news => [:index, :show]}, :public => true
65 map.permission :view_news, {:news => [:index, :show]}, :public => true
66 map.permission :comment_news, {:news => :add_comment}
66 map.permission :comment_news, {:news => :add_comment}
67 end
67 end
68
68
69 map.project_module :documents do |map|
69 map.project_module :documents do |map|
70 map.permission :manage_documents, {:documents => [:new, :edit, :destroy, :add_attachment, :destroy_attachment]}, :require => :loggedin
70 map.permission :manage_documents, {:documents => [:new, :edit, :destroy, :add_attachment, :destroy_attachment]}, :require => :loggedin
71 map.permission :view_documents, :documents => [:index, :show, :download]
71 map.permission :view_documents, :documents => [:index, :show, :download]
72 end
72 end
73
73
74 map.project_module :files do |map|
74 map.project_module :files do |map|
75 map.permission :manage_files, {:projects => :add_file, :versions => :destroy_file}, :require => :loggedin
75 map.permission :manage_files, {:projects => :add_file, :versions => :destroy_file}, :require => :loggedin
76 map.permission :view_files, :projects => :list_files, :versions => :download
76 map.permission :view_files, :projects => :list_files, :versions => :download
77 end
77 end
78
78
79 map.project_module :wiki do |map|
79 map.project_module :wiki do |map|
80 map.permission :manage_wiki, {:wikis => [:edit, :destroy]}, :require => :member
80 map.permission :manage_wiki, {:wikis => [:edit, :destroy]}, :require => :member
81 map.permission :rename_wiki_pages, {:wiki => :rename}, :require => :member
81 map.permission :rename_wiki_pages, {:wiki => :rename}, :require => :member
82 map.permission :delete_wiki_pages, {:wiki => :destroy}, :require => :member
82 map.permission :delete_wiki_pages, {:wiki => :destroy}, :require => :member
83 map.permission :view_wiki_pages, :wiki => [:index, :special]
83 map.permission :view_wiki_pages, :wiki => [:index, :special]
84 map.permission :view_wiki_edits, :wiki => [:history, :diff, :annotate]
84 map.permission :view_wiki_edits, :wiki => [:history, :diff, :annotate]
85 map.permission :edit_wiki_pages, :wiki => [:edit, :preview, :add_attachment]
85 map.permission :edit_wiki_pages, :wiki => [:edit, :preview, :add_attachment]
86 map.permission :delete_wiki_pages_attachments, :wiki => :destroy_attachment
86 map.permission :delete_wiki_pages_attachments, :wiki => :destroy_attachment
87 map.permission :protect_wiki_pages, {:wiki => :protect}, :require => :member
87 map.permission :protect_wiki_pages, {:wiki => :protect}, :require => :member
88 end
88 end
89
89
90 map.project_module :repository do |map|
90 map.project_module :repository do |map|
91 map.permission :manage_repository, {:repositories => [:edit, :committers, :destroy]}, :require => :member
91 map.permission :manage_repository, {:repositories => [:edit, :committers, :destroy]}, :require => :member
92 map.permission :browse_repository, :repositories => [:show, :browse, :entry, :annotate, :changes, :diff, :stats, :graph]
92 map.permission :browse_repository, :repositories => [:show, :browse, :entry, :annotate, :changes, :diff, :stats, :graph]
93 map.permission :view_changesets, :repositories => [:show, :revisions, :revision]
93 map.permission :view_changesets, :repositories => [:show, :revisions, :revision]
94 map.permission :commit_access, {}
94 map.permission :commit_access, {}
95 end
95 end
96
96
97 map.project_module :boards do |map|
97 map.project_module :boards do |map|
98 map.permission :manage_boards, {:boards => [:new, :edit, :destroy]}, :require => :member
98 map.permission :manage_boards, {:boards => [:new, :edit, :destroy]}, :require => :member
99 map.permission :view_messages, {:boards => [:index, :show], :messages => [:show]}, :public => true
99 map.permission :view_messages, {:boards => [:index, :show], :messages => [:show]}, :public => true
100 map.permission :add_messages, {:messages => [:new, :reply, :quote]}
100 map.permission :add_messages, {:messages => [:new, :reply, :quote]}
101 map.permission :edit_messages, {:messages => :edit}, :require => :member
101 map.permission :edit_messages, {:messages => :edit}, :require => :member
102 map.permission :edit_own_messages, {:messages => :edit}, :require => :loggedin
102 map.permission :edit_own_messages, {:messages => :edit}, :require => :loggedin
103 map.permission :delete_messages, {:messages => :destroy}, :require => :member
103 map.permission :delete_messages, {:messages => :destroy}, :require => :member
104 map.permission :delete_own_messages, {:messages => :destroy}, :require => :loggedin
104 map.permission :delete_own_messages, {:messages => :destroy}, :require => :loggedin
105 end
105 end
106 end
106 end
107
107
108 Redmine::MenuManager.map :top_menu do |menu|
108 Redmine::MenuManager.map :top_menu do |menu|
109 menu.push :home, :home_path, :html => { :class => 'home' }
109 menu.push :home, :home_path, :html => { :class => 'home' }
110 menu.push :my_page, { :controller => 'my', :action => 'page' }, :html => { :class => 'mypage' }, :if => Proc.new { User.current.logged? }
110 menu.push :my_page, { :controller => 'my', :action => 'page' }, :html => { :class => 'mypage' }, :if => Proc.new { User.current.logged? }
111 menu.push :projects, { :controller => 'projects', :action => 'index' }, :caption => :label_project_plural, :html => { :class => 'projects' }
111 menu.push :projects, { :controller => 'projects', :action => 'index' }, :caption => :label_project_plural, :html => { :class => 'projects' }
112 menu.push :administration, { :controller => 'admin', :action => 'index' }, :html => { :class => 'admin' }, :if => Proc.new { User.current.admin? }, :last => true
112 menu.push :administration, { :controller => 'admin', :action => 'index' }, :html => { :class => 'admin' }, :if => Proc.new { User.current.admin? }, :last => true
113 menu.push :help, Redmine::Info.help_url, :html => { :class => 'help' }, :last => true
113 menu.push :help, Redmine::Info.help_url, :html => { :class => 'help' }, :last => true
114 end
114 end
115
115
116 Redmine::MenuManager.map :account_menu do |menu|
116 Redmine::MenuManager.map :account_menu do |menu|
117 menu.push :login, :signin_path, :html => { :class => 'login' }, :if => Proc.new { !User.current.logged? }
117 menu.push :login, :signin_path, :html => { :class => 'login' }, :if => Proc.new { !User.current.logged? }
118 menu.push :register, { :controller => 'account', :action => 'register' }, :html => { :class => 'register' }, :if => Proc.new { !User.current.logged? && Setting.self_registration? }
118 menu.push :register, { :controller => 'account', :action => 'register' }, :html => { :class => 'register' }, :if => Proc.new { !User.current.logged? && Setting.self_registration? }
119 menu.push :my_account, { :controller => 'my', :action => 'account' }, :html => { :class => 'myaccount' }, :if => Proc.new { User.current.logged? }
119 menu.push :my_account, { :controller => 'my', :action => 'account' }, :html => { :class => 'myaccount' }, :if => Proc.new { User.current.logged? }
120 menu.push :logout, :signout_path, :html => { :class => 'logout' }, :if => Proc.new { User.current.logged? }
120 menu.push :logout, :signout_path, :html => { :class => 'logout' }, :if => Proc.new { User.current.logged? }
121 end
121 end
122
122
123 Redmine::MenuManager.map :application_menu do |menu|
123 Redmine::MenuManager.map :application_menu do |menu|
124 # Empty
124 # Empty
125 end
125 end
126
126
127 Redmine::MenuManager.map :admin_menu do |menu|
128 # Empty
129 end
130
127 Redmine::MenuManager.map :project_menu do |menu|
131 Redmine::MenuManager.map :project_menu do |menu|
128 menu.push :overview, { :controller => 'projects', :action => 'show' }
132 menu.push :overview, { :controller => 'projects', :action => 'show' }
129 menu.push :activity, { :controller => 'projects', :action => 'activity' }
133 menu.push :activity, { :controller => 'projects', :action => 'activity' }
130 menu.push :roadmap, { :controller => 'projects', :action => 'roadmap' },
134 menu.push :roadmap, { :controller => 'projects', :action => 'roadmap' },
131 :if => Proc.new { |p| p.versions.any? }
135 :if => Proc.new { |p| p.versions.any? }
132 menu.push :issues, { :controller => 'issues', :action => 'index' }, :param => :project_id, :caption => :label_issue_plural
136 menu.push :issues, { :controller => 'issues', :action => 'index' }, :param => :project_id, :caption => :label_issue_plural
133 menu.push :new_issue, { :controller => 'issues', :action => 'new' }, :param => :project_id, :caption => :label_issue_new,
137 menu.push :new_issue, { :controller => 'issues', :action => 'new' }, :param => :project_id, :caption => :label_issue_new,
134 :html => { :accesskey => Redmine::AccessKeys.key_for(:new_issue) }
138 :html => { :accesskey => Redmine::AccessKeys.key_for(:new_issue) }
135 menu.push :news, { :controller => 'news', :action => 'index' }, :param => :project_id, :caption => :label_news_plural
139 menu.push :news, { :controller => 'news', :action => 'index' }, :param => :project_id, :caption => :label_news_plural
136 menu.push :documents, { :controller => 'documents', :action => 'index' }, :param => :project_id, :caption => :label_document_plural
140 menu.push :documents, { :controller => 'documents', :action => 'index' }, :param => :project_id, :caption => :label_document_plural
137 menu.push :wiki, { :controller => 'wiki', :action => 'index', :page => nil },
141 menu.push :wiki, { :controller => 'wiki', :action => 'index', :page => nil },
138 :if => Proc.new { |p| p.wiki && !p.wiki.new_record? }
142 :if => Proc.new { |p| p.wiki && !p.wiki.new_record? }
139 menu.push :boards, { :controller => 'boards', :action => 'index', :id => nil }, :param => :project_id,
143 menu.push :boards, { :controller => 'boards', :action => 'index', :id => nil }, :param => :project_id,
140 :if => Proc.new { |p| p.boards.any? }, :caption => :label_board_plural
144 :if => Proc.new { |p| p.boards.any? }, :caption => :label_board_plural
141 menu.push :files, { :controller => 'projects', :action => 'list_files' }, :caption => :label_attachment_plural
145 menu.push :files, { :controller => 'projects', :action => 'list_files' }, :caption => :label_attachment_plural
142 menu.push :repository, { :controller => 'repositories', :action => 'show' },
146 menu.push :repository, { :controller => 'repositories', :action => 'show' },
143 :if => Proc.new { |p| p.repository && !p.repository.new_record? }
147 :if => Proc.new { |p| p.repository && !p.repository.new_record? }
144 menu.push :settings, { :controller => 'projects', :action => 'settings' }, :last => true
148 menu.push :settings, { :controller => 'projects', :action => 'settings' }, :last => true
145 end
149 end
146
150
147 Redmine::Activity.map do |activity|
151 Redmine::Activity.map do |activity|
148 activity.register :issues, :class_name => %w(Issue Journal)
152 activity.register :issues, :class_name => %w(Issue Journal)
149 activity.register :changesets
153 activity.register :changesets
150 activity.register :news
154 activity.register :news
151 activity.register :documents, :class_name => %w(Document Attachment)
155 activity.register :documents, :class_name => %w(Document Attachment)
152 activity.register :files, :class_name => 'Attachment'
156 activity.register :files, :class_name => 'Attachment'
153 activity.register :wiki_edits, :class_name => 'WikiContent::Version', :default => false
157 activity.register :wiki_edits, :class_name => 'WikiContent::Version', :default => false
154 activity.register :messages, :default => false
158 activity.register :messages, :default => false
155 end
159 end
156
160
157 Redmine::WikiFormatting.map do |format|
161 Redmine::WikiFormatting.map do |format|
158 format.register :textile, Redmine::WikiFormatting::Textile::Formatter, Redmine::WikiFormatting::Textile::Helper
162 format.register :textile, Redmine::WikiFormatting::Textile::Formatter, Redmine::WikiFormatting::Textile::Helper
159 end
163 end
@@ -1,184 +1,196
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 require 'gloc'
18 require 'gloc'
19
19
20 module Redmine
20 module Redmine
21 module MenuManager
21 module MenuManager
22 module MenuController
22 module MenuController
23 def self.included(base)
23 def self.included(base)
24 base.extend(ClassMethods)
24 base.extend(ClassMethods)
25 end
25 end
26
26
27 module ClassMethods
27 module ClassMethods
28 @@menu_items = Hash.new {|hash, key| hash[key] = {:default => key, :actions => {}}}
28 @@menu_items = Hash.new {|hash, key| hash[key] = {:default => key, :actions => {}}}
29 mattr_accessor :menu_items
29 mattr_accessor :menu_items
30
30
31 # Set the menu item name for a controller or specific actions
31 # Set the menu item name for a controller or specific actions
32 # Examples:
32 # Examples:
33 # * menu_item :tickets # => sets the menu name to :tickets for the whole controller
33 # * menu_item :tickets # => sets the menu name to :tickets for the whole controller
34 # * menu_item :tickets, :only => :list # => sets the menu name to :tickets for the 'list' action only
34 # * menu_item :tickets, :only => :list # => sets the menu name to :tickets for the 'list' action only
35 # * menu_item :tickets, :only => [:list, :show] # => sets the menu name to :tickets for 2 actions only
35 # * menu_item :tickets, :only => [:list, :show] # => sets the menu name to :tickets for 2 actions only
36 #
36 #
37 # The default menu item name for a controller is controller_name by default
37 # The default menu item name for a controller is controller_name by default
38 # Eg. the default menu item name for ProjectsController is :projects
38 # Eg. the default menu item name for ProjectsController is :projects
39 def menu_item(id, options = {})
39 def menu_item(id, options = {})
40 if actions = options[:only]
40 if actions = options[:only]
41 actions = [] << actions unless actions.is_a?(Array)
41 actions = [] << actions unless actions.is_a?(Array)
42 actions.each {|a| menu_items[controller_name.to_sym][:actions][a.to_sym] = id}
42 actions.each {|a| menu_items[controller_name.to_sym][:actions][a.to_sym] = id}
43 else
43 else
44 menu_items[controller_name.to_sym][:default] = id
44 menu_items[controller_name.to_sym][:default] = id
45 end
45 end
46 end
46 end
47 end
47 end
48
48
49 def menu_items
49 def menu_items
50 self.class.menu_items
50 self.class.menu_items
51 end
51 end
52
52
53 # Returns the menu item name according to the current action
53 # Returns the menu item name according to the current action
54 def current_menu_item
54 def current_menu_item
55 menu_items[controller_name.to_sym][:actions][action_name.to_sym] ||
55 menu_items[controller_name.to_sym][:actions][action_name.to_sym] ||
56 menu_items[controller_name.to_sym][:default]
56 menu_items[controller_name.to_sym][:default]
57 end
57 end
58 end
58 end
59
59
60 module MenuHelper
60 module MenuHelper
61 # Returns the current menu item name
61 # Returns the current menu item name
62 def current_menu_item
62 def current_menu_item
63 @controller.current_menu_item
63 @controller.current_menu_item
64 end
64 end
65
65
66 # Renders the application main menu
66 # Renders the application main menu
67 def render_main_menu(project)
67 def render_main_menu(project)
68 render_menu((project && !project.new_record?) ? :project_menu : :application_menu, project)
68 render_menu((project && !project.new_record?) ? :project_menu : :application_menu, project)
69 end
69 end
70
70
71 def render_menu(menu, project=nil)
71 def render_menu(menu, project=nil)
72 links = []
72 links = []
73 menu_items_for(menu, project) do |item, caption, url, selected|
74 links << content_tag('li',
75 link_to(h(caption), url, (selected ? item.html_options.merge(:class => 'selected') : item.html_options)))
76 end
77 links.empty? ? nil : content_tag('ul', links.join("\n"))
78 end
79
80 def menu_items_for(menu, project=nil)
81 items = []
73 Redmine::MenuManager.allowed_items(menu, User.current, project).each do |item|
82 Redmine::MenuManager.allowed_items(menu, User.current, project).each do |item|
74 unless item.condition && !item.condition.call(project)
83 unless item.condition && !item.condition.call(project)
75 url = case item.url
84 url = case item.url
76 when Hash
85 when Hash
77 project.nil? ? item.url : {item.param => project}.merge(item.url)
86 project.nil? ? item.url : {item.param => project}.merge(item.url)
78 when Symbol
87 when Symbol
79 send(item.url)
88 send(item.url)
80 else
89 else
81 item.url
90 item.url
82 end
91 end
83 caption = item.caption(project)
92 caption = item.caption(project)
84 caption = l(caption) if caption.is_a?(Symbol)
93 caption = l(caption) if caption.is_a?(Symbol)
85 links << content_tag('li',
94 if block_given?
86 link_to(h(caption), url, (current_menu_item == item.name ? item.html_options.merge(:class => 'selected') : item.html_options)))
95 yield item, caption, url, (current_menu_item == item.name)
96 else
97 items << [item, caption, url, (current_menu_item == item.name)]
98 end
87 end
99 end
88 end
100 end
89 links.empty? ? nil : content_tag('ul', links.join("\n"))
101 return block_given? ? nil : items
90 end
102 end
91 end
103 end
92
104
93 class << self
105 class << self
94 def map(menu_name)
106 def map(menu_name)
95 @items ||= {}
107 @items ||= {}
96 mapper = Mapper.new(menu_name.to_sym, @items)
108 mapper = Mapper.new(menu_name.to_sym, @items)
97 if block_given?
109 if block_given?
98 yield mapper
110 yield mapper
99 else
111 else
100 mapper
112 mapper
101 end
113 end
102 end
114 end
103
115
104 def items(menu_name)
116 def items(menu_name)
105 @items[menu_name.to_sym] || []
117 @items[menu_name.to_sym] || []
106 end
118 end
107
119
108 def allowed_items(menu_name, user, project)
120 def allowed_items(menu_name, user, project)
109 project ? items(menu_name).select {|item| user && user.allowed_to?(item.url, project)} : items(menu_name)
121 project ? items(menu_name).select {|item| user && user.allowed_to?(item.url, project)} : items(menu_name)
110 end
122 end
111 end
123 end
112
124
113 class Mapper
125 class Mapper
114 def initialize(menu, items)
126 def initialize(menu, items)
115 items[menu] ||= []
127 items[menu] ||= []
116 @menu = menu
128 @menu = menu
117 @menu_items = items[menu]
129 @menu_items = items[menu]
118 end
130 end
119
131
120 @@last_items_count = Hash.new {|h,k| h[k] = 0}
132 @@last_items_count = Hash.new {|h,k| h[k] = 0}
121
133
122 # Adds an item at the end of the menu. Available options:
134 # Adds an item at the end of the menu. Available options:
123 # * param: the parameter name that is used for the project id (default is :id)
135 # * param: the parameter name that is used for the project id (default is :id)
124 # * if: a Proc that is called before rendering the item, the item is displayed only if it returns true
136 # * if: a Proc that is called before rendering the item, the item is displayed only if it returns true
125 # * caption that can be:
137 # * caption that can be:
126 # * a localized string Symbol
138 # * a localized string Symbol
127 # * a String
139 # * a String
128 # * a Proc that can take the project as argument
140 # * a Proc that can take the project as argument
129 # * before, after: specify where the menu item should be inserted (eg. :after => :activity)
141 # * before, after: specify where the menu item should be inserted (eg. :after => :activity)
130 # * last: menu item will stay at the end (eg. :last => true)
142 # * last: menu item will stay at the end (eg. :last => true)
131 # * html_options: a hash of html options that are passed to link_to
143 # * html_options: a hash of html options that are passed to link_to
132 def push(name, url, options={})
144 def push(name, url, options={})
133 options = options.dup
145 options = options.dup
134
146
135 # menu item position
147 # menu item position
136 if before = options.delete(:before)
148 if before = options.delete(:before)
137 position = @menu_items.collect(&:name).index(before)
149 position = @menu_items.collect(&:name).index(before)
138 elsif after = options.delete(:after)
150 elsif after = options.delete(:after)
139 position = @menu_items.collect(&:name).index(after)
151 position = @menu_items.collect(&:name).index(after)
140 position += 1 unless position.nil?
152 position += 1 unless position.nil?
141 elsif options.delete(:last)
153 elsif options.delete(:last)
142 position = @menu_items.size
154 position = @menu_items.size
143 @@last_items_count[@menu] += 1
155 @@last_items_count[@menu] += 1
144 end
156 end
145 # default position
157 # default position
146 position ||= @menu_items.size - @@last_items_count[@menu]
158 position ||= @menu_items.size - @@last_items_count[@menu]
147
159
148 @menu_items.insert(position, MenuItem.new(name, url, options))
160 @menu_items.insert(position, MenuItem.new(name, url, options))
149 end
161 end
150
162
151 # Removes a menu item
163 # Removes a menu item
152 def delete(name)
164 def delete(name)
153 @menu_items.delete_if {|i| i.name == name}
165 @menu_items.delete_if {|i| i.name == name}
154 end
166 end
155 end
167 end
156
168
157 class MenuItem
169 class MenuItem
158 include GLoc
170 include GLoc
159 attr_reader :name, :url, :param, :condition, :html_options
171 attr_reader :name, :url, :param, :condition, :html_options
160
172
161 def initialize(name, url, options)
173 def initialize(name, url, options)
162 raise "Invalid option :if for menu item '#{name}'" if options[:if] && !options[:if].respond_to?(:call)
174 raise "Invalid option :if for menu item '#{name}'" if options[:if] && !options[:if].respond_to?(:call)
163 raise "Invalid option :html for menu item '#{name}'" if options[:html] && !options[:html].is_a?(Hash)
175 raise "Invalid option :html for menu item '#{name}'" if options[:html] && !options[:html].is_a?(Hash)
164 @name = name
176 @name = name
165 @url = url
177 @url = url
166 @condition = options[:if]
178 @condition = options[:if]
167 @param = options[:param] || :id
179 @param = options[:param] || :id
168 @caption = options[:caption]
180 @caption = options[:caption]
169 @html_options = options[:html] || {}
181 @html_options = options[:html] || {}
170 end
182 end
171
183
172 def caption(project=nil)
184 def caption(project=nil)
173 if @caption.is_a?(Proc)
185 if @caption.is_a?(Proc)
174 c = @caption.call(project).to_s
186 c = @caption.call(project).to_s
175 c = @name.to_s.humanize if c.blank?
187 c = @name.to_s.humanize if c.blank?
176 c
188 c
177 else
189 else
178 # check if localized string exists on first render (after GLoc strings are loaded)
190 # check if localized string exists on first render (after GLoc strings are loaded)
179 @caption_key ||= (@caption || (l_has_string?("label_#{@name}".to_sym) ? "label_#{@name}".to_sym : @name.to_s.humanize))
191 @caption_key ||= (@caption || (l_has_string?("label_#{@name}".to_sym) ? "label_#{@name}".to_sym : @name.to_s.humanize))
180 end
192 end
181 end
193 end
182 end
194 end
183 end
195 end
184 end
196 end
General Comments 0
You need to be logged in to leave comments. Login now