activeadmin 0.5.1 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of activeadmin might be problematic. Click here for more details.

Files changed (196) hide show
  1. data/.travis.yml +8 -5
  2. data/CHANGELOG.md +151 -0
  3. data/Gemfile +16 -16
  4. data/LICENSE +1 -1
  5. data/activeadmin.gemspec +1 -0
  6. data/app/assets/images/active_admin/index_list_icons/block_icon.svg +10 -0
  7. data/app/assets/images/active_admin/index_list_icons/blog_icon.svg +4 -0
  8. data/app/assets/images/active_admin/index_list_icons/grid_icon.svg +13 -0
  9. data/app/assets/images/active_admin/index_list_icons/table_icon.svg +3 -0
  10. data/app/assets/javascripts/active_admin/components/jquery.aa.checkbox-toggler.js.coffee +17 -44
  11. data/app/assets/javascripts/active_admin/components/jquery.aa.dropdown-menu.js.coffee +2 -4
  12. data/app/assets/javascripts/active_admin/components/jquery.aa.popover.js.coffee +0 -3
  13. data/app/assets/javascripts/active_admin/components/jquery.aa.table-checkbox-toggler.js.coffee +10 -12
  14. data/app/assets/javascripts/active_admin/pages/application.js.coffee +13 -10
  15. data/app/assets/javascripts/active_admin/pages/batch_actions.js.coffee +3 -3
  16. data/app/assets/stylesheets/active_admin/_base.css.scss +1 -0
  17. data/app/assets/stylesheets/active_admin/_header.css.scss +5 -2
  18. data/app/assets/stylesheets/active_admin/components/_dropdown_menu.scss +2 -2
  19. data/app/assets/stylesheets/active_admin/components/_index_list.scss +12 -0
  20. data/app/assets/stylesheets/active_admin/components/_popovers.css.scss +2 -2
  21. data/app/assets/stylesheets/active_admin/components/_table_tools.css.scss +2 -2
  22. data/app/assets/stylesheets/active_admin/mixins/_buttons.css.scss +4 -4
  23. data/app/assets/stylesheets/active_admin/mixins/_gradients.css.scss +5 -4
  24. data/app/assets/stylesheets/active_admin/mixins/_sections.css.scss +1 -1
  25. data/app/assets/stylesheets/active_admin/pages/_logged_out.scss +1 -1
  26. data/app/assets/stylesheets/active_admin/print.css.scss +2 -2
  27. data/app/assets/stylesheets/active_admin/structure/_title_bar.scss +1 -1
  28. data/app/views/active_admin/devise/unlocks/new.html.erb +14 -12
  29. data/docs/1-general-configuration.md +13 -0
  30. data/docs/10-custom-pages.md +40 -28
  31. data/docs/11-decorators.md +6 -4
  32. data/docs/12-arbre-components.md +1 -1
  33. data/docs/13-authorization-adapter.md +206 -0
  34. data/docs/2-resource-customization.md +129 -14
  35. data/docs/3-index-pages.md +65 -0
  36. data/docs/3-index-pages/create-an-index.md +29 -0
  37. data/docs/3-index-pages/index-as-table.md +35 -11
  38. data/docs/5-forms.md +2 -2
  39. data/features/authorization.feature +64 -0
  40. data/features/authorization_cancan.feature +52 -0
  41. data/features/belongs_to.feature +41 -5
  42. data/features/index/batch_actions.feature +27 -3
  43. data/features/index/formats.feature +27 -0
  44. data/features/index/index_as_table.feature +74 -2
  45. data/features/index/index_parameters.feature +69 -0
  46. data/features/index/index_scopes.feature +7 -11
  47. data/features/index/page_title.feature +18 -0
  48. data/features/index/switch_index_view.feature +73 -0
  49. data/features/menu.feature +27 -0
  50. data/features/registering_pages.feature +21 -0
  51. data/features/step_definitions/additional_web_steps.rb +4 -0
  52. data/features/step_definitions/batch_action_steps.rb +16 -6
  53. data/features/step_definitions/index_scope_steps.rb +3 -3
  54. data/features/step_definitions/index_views_steps.rb +3 -0
  55. data/features/step_definitions/menu_steps.rb +4 -0
  56. data/features/support/env.rb +4 -0
  57. data/features/support/paths.rb +3 -0
  58. data/lib/active_admin.rb +4 -0
  59. data/lib/active_admin/application.rb +43 -76
  60. data/lib/active_admin/authorization_adapter.rb +128 -0
  61. data/lib/active_admin/base_controller.rb +18 -1
  62. data/lib/active_admin/base_controller/authorization.rb +153 -0
  63. data/lib/active_admin/base_controller/menu.rb +8 -3
  64. data/lib/active_admin/batch_actions/resource_extension.rb +8 -7
  65. data/lib/active_admin/batch_actions/views/batch_action_form.rb +1 -1
  66. data/lib/active_admin/cancan_adapter.rb +40 -0
  67. data/lib/active_admin/dashboards.rb +4 -5
  68. data/lib/active_admin/dashboards/dashboard_controller.rb +1 -1
  69. data/lib/active_admin/devise.rb +22 -7
  70. data/lib/active_admin/dsl.rb +18 -5
  71. data/lib/active_admin/engine.rb +1 -1
  72. data/lib/active_admin/filters/dsl.rb +1 -1
  73. data/lib/active_admin/filters/forms.rb +9 -7
  74. data/lib/active_admin/filters/resource_extension.rb +20 -15
  75. data/lib/active_admin/form_builder.rb +44 -49
  76. data/lib/active_admin/helpers/optional_display.rb +4 -8
  77. data/lib/active_admin/inputs/filter_boolean_input.rb +1 -1
  78. data/lib/active_admin/inputs/filter_string_input.rb +5 -1
  79. data/lib/active_admin/locales/bg.yml +1 -1
  80. data/lib/active_admin/locales/ca.yml +1 -1
  81. data/lib/active_admin/locales/cs.yml +26 -25
  82. data/lib/active_admin/locales/da.yml +1 -1
  83. data/lib/active_admin/locales/de.yml +1 -1
  84. data/lib/active_admin/locales/en.yml +11 -1
  85. data/lib/active_admin/locales/es.yml +16 -16
  86. data/lib/active_admin/locales/fr.yml +1 -1
  87. data/lib/active_admin/locales/he.yml +1 -1
  88. data/lib/active_admin/locales/hr.yml +1 -1
  89. data/lib/active_admin/locales/hu.yml +1 -1
  90. data/lib/active_admin/locales/it.yml +1 -1
  91. data/lib/active_admin/locales/ja.yml +4 -1
  92. data/lib/active_admin/locales/ko.yml +1 -1
  93. data/lib/active_admin/locales/lt.yml +1 -1
  94. data/lib/active_admin/locales/lv.yml +12 -1
  95. data/lib/active_admin/locales/nl.yml +2 -2
  96. data/lib/active_admin/locales/no-NB.yml +22 -1
  97. data/lib/active_admin/locales/pl.yml +1 -1
  98. data/lib/active_admin/locales/pt-BR.yml +1 -1
  99. data/lib/active_admin/locales/pt-PT.yml +81 -0
  100. data/lib/active_admin/locales/ro.yml +1 -1
  101. data/lib/active_admin/locales/ru.yml +1 -1
  102. data/lib/active_admin/locales/sv-SE.yml +1 -1
  103. data/lib/active_admin/locales/tr.yml +1 -1
  104. data/lib/active_admin/locales/vi.yml +1 -1
  105. data/lib/active_admin/locales/zh-CN.yml +1 -1
  106. data/lib/active_admin/locales/zh-TW.yml +1 -1
  107. data/lib/active_admin/menu.rb +76 -38
  108. data/lib/active_admin/menu_collection.rb +96 -0
  109. data/lib/active_admin/menu_item.rb +61 -71
  110. data/lib/active_admin/namespace.rb +67 -5
  111. data/lib/active_admin/page.rb +6 -0
  112. data/lib/active_admin/page_controller.rb +13 -3
  113. data/lib/active_admin/resource.rb +11 -20
  114. data/lib/active_admin/resource/action_items.rb +3 -3
  115. data/lib/active_admin/resource/controllers.rb +0 -17
  116. data/lib/active_admin/resource/menu.rb +52 -24
  117. data/lib/active_admin/resource/naming.rb +6 -10
  118. data/lib/active_admin/resource/page_presenters.rb +57 -3
  119. data/lib/active_admin/resource/routes.rb +46 -0
  120. data/lib/active_admin/resource_controller.rb +2 -17
  121. data/lib/active_admin/resource_controller/data_access.rb +299 -0
  122. data/lib/active_admin/resource_controller/decorators.rb +2 -1
  123. data/lib/active_admin/resource_dsl.rb +12 -14
  124. data/lib/active_admin/router.rb +61 -56
  125. data/lib/active_admin/scope.rb +28 -18
  126. data/lib/active_admin/version.rb +1 -1
  127. data/lib/active_admin/view_factory.rb +0 -1
  128. data/lib/active_admin/view_helpers/breadcrumb_helper.rb +13 -19
  129. data/lib/active_admin/view_helpers/fields_for.rb +2 -0
  130. data/lib/active_admin/view_helpers/form_helper.rb +1 -1
  131. data/lib/active_admin/view_helpers/method_or_proc_helper.rb +66 -11
  132. data/lib/active_admin/views/components/attributes_table.rb +7 -4
  133. data/lib/active_admin/views/components/index_list.rb +68 -0
  134. data/lib/active_admin/views/components/paginated_collection.rb +13 -9
  135. data/lib/active_admin/views/components/scopes.rb +2 -8
  136. data/lib/active_admin/views/components/table_for.rb +1 -1
  137. data/lib/active_admin/views/footer.rb +1 -1
  138. data/lib/active_admin/views/header.rb +3 -2
  139. data/lib/active_admin/views/index_as_block.rb +4 -0
  140. data/lib/active_admin/views/index_as_blog.rb +4 -0
  141. data/lib/active_admin/views/index_as_grid.rb +4 -0
  142. data/lib/active_admin/views/index_as_table.rb +49 -7
  143. data/lib/active_admin/views/pages/index.rb +19 -4
  144. data/lib/active_admin/views/tabbed_navigation.rb +10 -54
  145. data/lib/generators/active_admin/install/install_generator.rb +5 -1
  146. data/lib/generators/active_admin/install/templates/active_admin.rb.erb +58 -0
  147. data/spec/integration/{default_namespace.rb → default_namespace_spec.rb} +0 -16
  148. data/spec/spec_helper.rb +3 -0
  149. data/spec/support/detect_rails_version.rb +10 -3
  150. data/spec/support/rails_template.rb +1 -1
  151. data/spec/support/templates/post_decorator.rb +6 -6
  152. data/spec/unit/application_spec.rb +5 -5
  153. data/spec/unit/authorization/authorization_adapter_spec.rb +61 -0
  154. data/spec/unit/authorization/controller_authorization_spec.rb +47 -0
  155. data/spec/unit/base_controller_spec.rb +0 -2
  156. data/spec/unit/batch_actions/resource_spec.rb +1 -1
  157. data/spec/unit/breadcrumbs_spec.rb +3 -3
  158. data/spec/unit/cancan_adapter_spec.rb +35 -0
  159. data/spec/unit/config_shared_examples.rb +9 -30
  160. data/spec/unit/devise_spec.rb +29 -0
  161. data/spec/unit/dsl_spec.rb +61 -0
  162. data/spec/unit/filters/filter_form_builder_spec.rb +58 -4
  163. data/spec/unit/filters/resource_spec.rb +17 -5
  164. data/spec/unit/form_builder_spec.rb +15 -0
  165. data/spec/unit/menu_collection_spec.rb +62 -0
  166. data/spec/unit/menu_item_spec.rb +51 -37
  167. data/spec/unit/menu_spec.rb +33 -29
  168. data/spec/unit/namespace/authorization_spec.rb +31 -0
  169. data/spec/unit/namespace/register_page_spec.rb +6 -28
  170. data/spec/unit/namespace/register_resource_spec.rb +11 -34
  171. data/spec/unit/namespace_spec.rb +63 -2
  172. data/spec/unit/page_controller_spec.rb +0 -3
  173. data/spec/unit/reloader_spec.rb +5 -5
  174. data/spec/unit/resource/menu_spec.rb +1 -13
  175. data/spec/unit/resource/naming_spec.rb +20 -2
  176. data/spec/unit/resource/page_presenters_spec.rb +14 -2
  177. data/spec/unit/resource_controller/{collection_spec.rb → data_access_spec.rb} +31 -13
  178. data/spec/unit/resource_controller_spec.rb +4 -5
  179. data/spec/unit/resource_spec.rb +33 -11
  180. data/spec/unit/routing_spec.rb +43 -0
  181. data/spec/unit/scope_spec.rb +13 -0
  182. data/spec/unit/view_factory_spec.rb +0 -1
  183. data/spec/unit/view_helpers/fields_for_spec.rb +4 -0
  184. data/spec/unit/view_helpers/form_helper_spec.rb +6 -2
  185. data/spec/unit/view_helpers/method_or_proc_helper_spec.rb +97 -0
  186. data/spec/unit/views/components/attributes_table_spec.rb +11 -0
  187. data/spec/unit/views/components/index_list_spec.rb +32 -0
  188. data/spec/unit/views/tabbed_navigation_spec.rb +42 -40
  189. data/tasks/test.rake +1 -1
  190. metadata +127 -40
  191. data/lib/active_admin/menu_builder.rb +0 -65
  192. data/lib/active_admin/resource_controller/callbacks.rb +0 -59
  193. data/lib/active_admin/resource_controller/collection.rb +0 -158
  194. data/lib/active_admin/views/utility_nav.rb +0 -41
  195. data/spec/unit/base_controller_shared_examples.rb +0 -25
  196. data/spec/unit/dsl_include_spec.rb +0 -20
@@ -3,7 +3,7 @@ vi:
3
3
  dashboard: Dashboard
4
4
  dashboard_welcome:
5
5
  welcome: "Chào mừng bạn đến với Active Admin. Đây là trang Dashboard mặc định."
6
- call_to_action: "Để thêm phần phần cho trang Dashboar hãy chỉnh sửa 'app/admin/dashboards.rb'"
6
+ call_to_action: "Để thêm phần phần cho trang Dashboar hãy chỉnh sửa 'app/admin/dashboard.rb'"
7
7
  view: "Xem"
8
8
  edit: "Chỉnh sửa"
9
9
  delete: "Xóa"
@@ -3,7 +3,7 @@
3
3
  dashboard: "控制面板"
4
4
  dashboard_welcome:
5
5
  welcome: "欢迎使用Active Admin. 这是默认的控制面板页."
6
- call_to_action: "若要添加新的面板内容, 请修改 'app/admin/dashboards.rb'"
6
+ call_to_action: "若要添加新的面板内容, 请修改 'app/admin/dashboard.rb'"
7
7
  view: "查看"
8
8
  edit: "编辑"
9
9
  delete: "删除"
@@ -3,7 +3,7 @@
3
3
  dashboard: 儀表板
4
4
  dashboard_welcome:
5
5
  welcome: "歡迎來到 Active Admin 這是預設的儀表板頁面。"
6
- call_to_action: "要新增儀表板內容,請查看 'app/admin/dashboards.rb'"
6
+ call_to_action: "要新增儀表板內容,請查看 'app/admin/dashboard.rb'"
7
7
  view: "檢視"
8
8
  edit: "編輯"
9
9
  delete: "刪除"
@@ -5,8 +5,8 @@ module ActiveAdmin
5
5
  # To build a new menu:
6
6
  #
7
7
  # menu = Menu.new do |m|
8
- # m.add MenuItem.new(:label => "Dashboard", :url => "/")
9
- # m.add MenuItem.new(:label => "Admin", :url => "/admin")
8
+ # m.add label: 'Dashboard', url: '/'
9
+ # m.add label: 'Users', url: '/users'
10
10
  # end
11
11
  #
12
12
  # If you're interested in configuring a menu item, take a look at the
@@ -14,54 +14,92 @@ module ActiveAdmin
14
14
  #
15
15
  class Menu
16
16
 
17
- attr_accessor :children
18
-
19
17
  def initialize
20
- @children = Menu::ItemCollection.new
21
-
18
+ super # MenuNode
22
19
  yield(self) if block_given?
23
20
  end
24
21
 
25
- # Add a new MenuItem to the menu
26
- #
27
- # Example:
28
- # menu = Menu.new
29
- # dash = MenuItem.new :label => "Dashboard"
30
- # menu.add dash
31
- #
32
- # Accepts as many menu items as you wish to add:
33
- #
34
- # menu = Menu.new
35
- # dash = MenuItem.new :label => "Dashboard"
36
- # admin = MenuItem.new :label => "Admin"
37
- # menu.add dash, admin
38
- #
39
- # @param [MenuItem] menu_items Add as many menu items as you pass in
40
- def add(*menu_items)
41
- menu_items.each do |menu_item|
42
- menu_item.parent = nil
43
- @children << menu_item
22
+ module MenuNode
23
+ def initialize
24
+ @children = {}
44
25
  end
45
- end
46
26
 
47
- def [](id)
48
- @children.find_by_id(id)
49
- end
27
+ def [](id)
28
+ @children[normalize_id(id)]
29
+ end
30
+ def []=(id, child)
31
+ @children[normalize_id(id)] = child
32
+ end
50
33
 
51
- # @return Sorted [Array] of [MenuItem]
52
- def items
53
- @children.sort
54
- end
34
+ # Recursively builds any given menu items. There are two syntaxes supported,
35
+ # as shown in the below examples. Both create an identical menu structure.
36
+ #
37
+ # Example 1:
38
+ # menu = Menu.new
39
+ # menu.add label: 'Dashboard' do |dash|
40
+ # dash.add label: 'My Child Dashboard'
41
+ # end
42
+ #
43
+ # Example 2:
44
+ # menu = Menu.new
45
+ # menu.add label: 'Dashboard'
46
+ # menu.add parent: 'Dashboard', label: 'My Child Dashboard'
47
+ #
48
+ def add(options)
49
+ item = if parent = options.delete(:parent)
50
+ (self[parent] || add(:label => parent)).add options
51
+ else
52
+ _add options.merge :parent => self
53
+ end
55
54
 
56
- class ItemCollection < Array
55
+ yield(item) if block_given?
57
56
 
58
- def find_by_id(id)
59
- id = MenuItem.generate_item_id(id)
60
- find{ |i| i.id == id }
57
+ item
61
58
  end
62
59
 
60
+ # Whether any children match the given item.
61
+ def include?(item)
62
+ @children.values.include? item
63
+ end
64
+
65
+ # Used in the UI to visually distinguish which menu item is selected.
66
+ def current?(item)
67
+ self == item || include?(item)
68
+ end
69
+
70
+ # Returns sorted array of menu items that should be displayed in this context.
71
+ # Sorts by priority first, then alphabetically by label if needed.
72
+ def items(context = nil)
73
+ @children.values.select{ |i| i.display?(context) }.sort do |a,b|
74
+ result = a.priority <=> b.priority
75
+ result = a.label(context) <=> b.label(context) if result == 0
76
+ result
77
+ end
78
+ end
79
+
80
+ attr_reader :children
81
+ private
82
+ attr_writer :children
83
+
84
+ # The method that actually adds new menu items. Called by the public method.
85
+ # If this ID is already taken, transfer the children of the existing item to the new item.
86
+ def _add(options)
87
+ item = ActiveAdmin::MenuItem.new(options)
88
+ item.send :children=, self[item.id].children if self[item.id]
89
+ self[item.id] = item
90
+ end
91
+
92
+ def normalize_id(id)
93
+ case id
94
+ when String, Symbol
95
+ id.to_s.downcase.gsub ' ', '_'
96
+ else
97
+ raise TypeError, "#{id.class} isn't supported as a Menu ID"
98
+ end
99
+ end
63
100
  end
64
101
 
65
- end
102
+ include MenuNode
66
103
 
104
+ end
67
105
  end
@@ -0,0 +1,96 @@
1
+ module ActiveAdmin
2
+
3
+ DEFAULT_MENU = :default
4
+
5
+ # A MenuCollection stores multiple menus for any given namespace. Namespaces delegate
6
+ # the addition of menu items to this class.
7
+ class MenuCollection
8
+
9
+ NoMenuError = Class.new(KeyError)
10
+
11
+ def initialize
12
+ @menus = {}
13
+ @build_callbacks = []
14
+ @built = false
15
+ end
16
+
17
+ # Add a new menu item to a menu in the collection
18
+ def add(menu_name, menu_item_options = {})
19
+ menu = find_or_create(menu_name)
20
+
21
+ menu.add menu_item_options
22
+ end
23
+
24
+ def clear!
25
+ @menus = {}
26
+ @built = false
27
+ end
28
+
29
+ def exists?(menu_name)
30
+ @menus.keys.include? menu_name
31
+ end
32
+
33
+ def fetch(menu_name)
34
+ build_menus!
35
+
36
+ @menus[menu_name] or
37
+ raise NoMenuError, "No menu by the name of #{menu_name.inspect} in availble menus: #{@menus.keys.join(", ")}"
38
+ end
39
+
40
+ # Add callbacks that will be run when the menu is going to be built. This
41
+ # helps use with reloading and allows configurations to add items to menus.
42
+ #
43
+ # @param [Proc] block A block which will be ran when the menu is built. The
44
+ # will have the menu collection yielded.
45
+ def on_build(&block)
46
+ @build_callbacks << block
47
+ end
48
+
49
+ # Add callbacks that will be run before the menu is built
50
+ def before_build(&block)
51
+ @build_callbacks.unshift(block)
52
+ end
53
+
54
+ def menu(menu_name)
55
+ menu = find_or_create(menu_name)
56
+
57
+ yield(menu) if block_given?
58
+
59
+ menu
60
+ end
61
+
62
+ private
63
+
64
+ def built?
65
+ @built
66
+ end
67
+
68
+ def build_menus!
69
+ return if built?
70
+
71
+ build_default_menu
72
+ run_on_build_callbacks
73
+
74
+ @built = true
75
+ end
76
+
77
+ def run_on_build_callbacks
78
+ @build_callbacks.each do |callback|
79
+ callback.call(self)
80
+ end
81
+ end
82
+
83
+ def build_default_menu
84
+ find_or_create DEFAULT_MENU
85
+ end
86
+
87
+ def find_or_create(menu_name)
88
+ menu_name ||= DEFAULT_MENU
89
+ @menus[menu_name] ||= ActiveAdmin::Menu.new
90
+ end
91
+
92
+
93
+
94
+ end
95
+
96
+ end
@@ -1,106 +1,96 @@
1
- module ActiveAdmin
1
+ require 'active_admin/view_helpers/method_or_proc_helper'
2
2
 
3
+ module ActiveAdmin
3
4
  class MenuItem
5
+ include Menu::MenuNode
6
+ include MethodOrProcHelper
4
7
 
5
- attr_accessor :id, :label, :url, :priority, :parent, :display_if_block, :children
8
+ attr_reader :html_options, :parent, :priority
6
9
 
7
- # Build a new menu item
10
+ # Builds a new menu item
8
11
  #
9
12
  # @param [Hash] options The options for the menu
10
13
  #
11
- # @option options [String, Proc] :label
12
- # The label to display for this menu item. It can either be a String or a
13
- # Proc. If the option is Proc, it is called each time the label is requested.
14
+ # @option options [String, Symbol, Proc] :label
15
+ # The label to display for this menu item.
16
+ # Default: Titleized Resource Name
14
17
  #
15
18
  # @option options [String] :id
16
- # A custom id to reference this menu item with. If empty an id is automatically
17
- # generated for you.
19
+ # A custom id to reference this menu item with.
20
+ # Default: underscored_resource_name
18
21
  #
19
- # @option options [String, Symbol] :url
20
- # A string or symbol representing the url for this item. If it's a symbol, the
21
- # view will automatically call the method for you.
22
+ # @option options [String, Symbol, Proc] :url
23
+ # The URL this item will link to.
22
24
  #
23
25
  # @option options [Integer] :priority
24
- # MenuItems are sorted by priority then by label. The lower the priority, the
25
- # earlier in the menu the item will be displayed.
26
+ # The lower the priority, the earlier in the menu the item will be displayed.
26
27
  # Default: 10
27
28
  #
28
- # @option options [Proc] :if
29
- # A block for the view to call to decide if this menu item should be displayed.
30
- # The block should return true of false
29
+ # @option options [Symbol, Proc] :if
30
+ # This decides whether the menu item will be displayed. Evaluated on each request.
31
+ #
32
+ # @option options [Hash] :html_options
33
+ # A hash of options to pass to `link_to` when rendering the item
34
+ #
35
+ # @option [ActiveAdmin::MenuItem] :parent
36
+ # This menu item's parent. It will be displayed nested below its parent.
37
+ #
38
+ # NOTE: for :label, :url, and :if
39
+ # These options are evaluated in the view context at render time. Symbols are called
40
+ # as methods on `self`, and Procs are exec'd within `self`.
41
+ # Here are some examples of what you can do:
42
+ #
43
+ # menu if: :admin?
44
+ # menu url: :new_book_path
45
+ # menu url: :awesome_helper_you_defined
46
+ # menu label: ->{ User.some_method }
47
+ # menu label: ->{ I18n.t 'menus.user' }
31
48
  #
32
- # @option options [Proc] :parent
33
- # The parent label to display for this menu item. Menu item will be nested
34
- # under that label. It can either be a String or a Proc. If the option is Proc,
35
- # it is called each time the label is requested.
36
49
  def initialize(options = {})
37
- @label = options[:label]
38
- @id = MenuItem.generate_item_id(options[:id] || label)
39
- @url = options[:url]
40
- @priority = options[:priority] || 10
41
- @children = Menu::ItemCollection.new
42
- @parent = options[:parent]
43
-
44
- @display_if_block = options[:if]
50
+ super() # MenuNode
51
+ @label = options[:label]
52
+ @dirty_id = options[:id] || options[:label]
53
+ @url = options[:url] || '#'
54
+ @priority = options[:priority] || 10
55
+ @html_options = options[:html_options] || {}
56
+ @should_display = options[:if] || proc{true}
57
+ @parent = options[:parent]
45
58
 
46
59
  yield(self) if block_given? # Builder style syntax
47
60
  end
48
61
 
49
- def self.generate_item_id(id)
50
- id.to_s.downcase.gsub(" ", "_")
62
+ def id
63
+ @id ||= normalize_id @dirty_id
51
64
  end
52
65
 
53
- def label
54
- case @label
55
- when Proc
56
- @label.call
57
- else
58
- @label.to_s
59
- end
66
+ def label(context = nil)
67
+ render_in_context context, @label
60
68
  end
61
69
 
62
- def add(*menu_items)
63
- menu_items.each do |menu_item|
64
- menu_item.parent = self
65
- @children << menu_item
66
- end
70
+ def url(context = nil)
71
+ render_in_context context, @url
67
72
  end
68
73
 
69
- def children
70
- @children.sort
74
+ # Don't display if the :if option passed says so
75
+ # Don't display if the link isn't real, we have children, and none of the children are being displayed.
76
+ def display?(context = nil)
77
+ return false unless render_in_context(context, @should_display)
78
+ return false if !real_url?(context) && @children.any? && !items(context).any?
79
+ true
71
80
  end
72
81
 
73
- def parent?
74
- !parent.nil?
75
- end
76
-
77
- def dom_id
78
- id.gsub( " ", '_' ).gsub( /[^a-z0-9_]/, '' )
79
- end
80
-
81
- # Returns an array of the ancestory of this menu item
82
- # The first item is the immediate parent fo the item
82
+ # Returns an array of the ancestory of this menu item.
83
+ # The first item is the immediate parent of the item.
83
84
  def ancestors
84
- return [] unless parent?
85
- [parent, parent.ancestors].flatten
85
+ parent ? [parent, parent.ancestors].flatten : []
86
86
  end
87
87
 
88
- # Returns the child item with the name passed in
89
- # @blog_menu["Create New"] => <#MenuItem @name="Create New" >
90
- def [](id)
91
- @children.find_by_id(id)
92
- end
93
-
94
- def <=>(other)
95
- result = priority <=> other.priority
96
- result = label <=> other.label if result == 0
97
- result
98
- end
88
+ private
99
89
 
100
- # Returns the display if block. If the block was not explicitly defined
101
- # a default block always returning true will be returned.
102
- def display_if_block
103
- @display_if_block || lambda { |_| true }
90
+ # URL is not nil, empty, or '#'
91
+ def real_url?(context = nil)
92
+ url = url context
93
+ url.present? && url != '#'
104
94
  end
105
95
 
106
96
  end
@@ -1,6 +1,5 @@
1
1
  require 'active_admin/helpers/settings'
2
2
  require 'active_admin/resource_collection'
3
- require 'active_admin/menu_builder'
4
3
 
5
4
  module ActiveAdmin
6
5
 
@@ -33,7 +32,7 @@ module ActiveAdmin
33
32
 
34
33
  RegisterEvent = 'active_admin.namespace.register'.freeze
35
34
 
36
- attr_reader :application, :resources, :name, :menu
35
+ attr_reader :application, :resources, :name, :menus
37
36
 
38
37
  def initialize(application, name)
39
38
  @application = application
@@ -41,6 +40,7 @@ module ActiveAdmin
41
40
  @resources = ResourceCollection.new
42
41
  register_module unless root?
43
42
  generate_dashboard_controller
43
+ build_menu_collection
44
44
  end
45
45
 
46
46
  # Register a resource into this namespace. The preffered method to access this is to
@@ -114,16 +114,78 @@ module ActiveAdmin
114
114
  application.send(name)
115
115
  end
116
116
 
117
- def menu
118
- @menu ||= MenuBuilder.build_for_namespace(self)
117
+ def fetch_menu(name)
118
+ @menus.fetch(name)
119
119
  end
120
120
 
121
121
  def reset_menu!
122
- @menu = nil
122
+ @menus.clear!
123
+ end
124
+
125
+ # Add a callback to be ran when we build the menu
126
+ #
127
+ # @param [Symbol] name The name of the menu. Default: :default
128
+ # @param [Proc] block The block to be ran when the menu is built
129
+ #
130
+ # @returns [void]
131
+ def build_menu(name = DEFAULT_MENU, &block)
132
+ @menus.before_build do |menus|
133
+ menus.menu name do |menu|
134
+ block.call(menu)
135
+ end
136
+ end
137
+ end
138
+
139
+ # Add the default logout button to the menu, using the ActiveAdmin configuration settings
140
+ #
141
+ # @param [ActiveAdmin::MenuItem] menu The menu to add the logout link to
142
+ # @param [Fixnum] priority Override the default priority of 100 to position the logout button where you want
143
+ # @param [Hash] html_options An options hash to pass along to link_to
144
+ #
145
+ # @returns [void]
146
+ def add_logout_button_to_menu(menu, priority=100, html_options={})
147
+ if logout_link_path
148
+ logout_method = logout_link_method || :get
149
+ menu.add :id => 'logout',
150
+ :priority => priority,
151
+ :label => proc{ I18n.t('active_admin.logout') },
152
+ :html_options => html_options.reverse_merge(:method => logout_method),
153
+ :url => proc{ render_or_call_method_or_proc_on self, active_admin_namespace.logout_link_path },
154
+ :if => proc{ current_active_admin_user? }
155
+ end
123
156
  end
124
157
 
125
158
  protected
126
159
 
160
+ def build_menu_collection
161
+ @menus = MenuCollection.new
162
+
163
+ @menus.on_build do |menus|
164
+ # Support for deprecated dashboards...
165
+ Dashboards.add_to_menu(self, menus.menu(DEFAULT_MENU))
166
+
167
+ # Build the default utility navigation
168
+ build_default_utility_nav
169
+
170
+ resources.each do |resource|
171
+ resource.add_to_menu(@menus)
172
+ end
173
+ end
174
+ end
175
+
176
+ # Builds the default utility navigation in top right header with current user & logout button
177
+ def build_default_utility_nav
178
+ return if @menus.exists? :utility_navigation
179
+ @menus.menu :utility_navigation do |menu|
180
+ menu.add :label => proc{ display_name current_active_admin_user },
181
+ :url => '#',
182
+ :id => 'current_user',
183
+ :if => proc{ current_active_admin_user? }
184
+
185
+ add_logout_button_to_menu menu
186
+ end
187
+ end
188
+
127
189
  # Either returns an existing Resource instance or builds a new
128
190
  # one for the resource and options
129
191
  def find_or_build_resource(resource_class, options)