activeadmin 0.4.0 → 0.4.1

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 (57) hide show
  1. data/CHANGELOG.md +46 -0
  2. data/Gemfile +1 -0
  3. data/README.rdoc +1 -1
  4. data/activeadmin.gemspec +1 -1
  5. data/app/assets/stylesheets/active_admin/_base.css.scss +2 -1
  6. data/app/assets/stylesheets/active_admin/components/_columns.scss +3 -0
  7. data/app/assets/stylesheets/active_admin/mixins/_sections.css.scss +1 -1
  8. data/app/views/active_admin/devise/sessions/new.html.erb +1 -1
  9. data/docs/2-resource-customization.md +13 -0
  10. data/docs/3-index-pages.md +23 -0
  11. data/docs/3-index-pages/index-as-grid.md +2 -2
  12. data/docs/7-sidebars.md +7 -0
  13. data/docs/8-custom-actions.md +6 -0
  14. data/features/action_item.feature +73 -0
  15. data/features/index/filters.feature +55 -22
  16. data/features/index/index_parameters.feature +12 -0
  17. data/features/index/index_scope_to.feature +29 -0
  18. data/features/index/index_scopes.feature +13 -0
  19. data/features/index/pagination.feature +14 -5
  20. data/features/sidebar_sections.feature +45 -0
  21. data/features/step_definitions/action_item_steps.rb +4 -0
  22. data/features/step_definitions/factory_steps.rb +3 -2
  23. data/features/step_definitions/filter_steps.rb +17 -0
  24. data/features/step_definitions/format_steps.rb +4 -0
  25. data/features/step_definitions/index_scope_steps.rb +5 -0
  26. data/lib/active_admin/arbre/html/tag.rb +9 -1
  27. data/lib/active_admin/helpers/optional_display.rb +13 -3
  28. data/lib/active_admin/locales/da.yml +15 -0
  29. data/lib/active_admin/locales/es.yml +18 -2
  30. data/lib/active_admin/locales/he_il.yml +45 -0
  31. data/lib/active_admin/menu_item.rb +0 -21
  32. data/lib/active_admin/page.rb +9 -0
  33. data/lib/active_admin/page_controller.rb +4 -0
  34. data/lib/active_admin/page_dsl.rb +7 -0
  35. data/lib/active_admin/reloader.rb +0 -1
  36. data/lib/active_admin/resource.rb +6 -0
  37. data/lib/active_admin/resource/action_items.rb +2 -2
  38. data/lib/active_admin/resource/pagination.rb +19 -0
  39. data/lib/active_admin/resource/sidebars.rb +2 -2
  40. data/lib/active_admin/resource_controller/callbacks.rb +13 -1
  41. data/lib/active_admin/resource_controller/collection.rb +17 -10
  42. data/lib/active_admin/router.rb +3 -0
  43. data/lib/active_admin/version.rb +1 -1
  44. data/lib/active_admin/views/components/columns.rb +115 -12
  45. data/lib/active_admin/views/components/scopes.rb +4 -4
  46. data/lib/active_admin/views/index_as_table.rb +14 -2
  47. data/lib/active_admin/views/pages/base.rb +2 -2
  48. data/lib/active_admin/views/pages/index.rb +25 -13
  49. data/lib/active_admin/views/tabbed_navigation.rb +14 -2
  50. data/spec/unit/menu_item_spec.rb +0 -14
  51. data/spec/unit/namespace/register_resource_spec.rb +1 -1
  52. data/spec/unit/resource/pagination_spec.rb +38 -0
  53. data/spec/unit/resource_controller/collection_spec.rb +1 -1
  54. data/spec/unit/views/components/columns_spec.rb +61 -4
  55. data/spec/unit/views/tabbed_navigation_spec.rb +2 -2
  56. metadata +20 -11
  57. data/features/index/filter_with_check_boxes.feature +0 -25
@@ -6,10 +6,6 @@ module ActiveAdmin
6
6
  module Collection
7
7
  extend ActiveSupport::Concern
8
8
 
9
- included do
10
- before_filter :setup_pagination_for_csv
11
- end
12
-
13
9
  module BaseCollection
14
10
  protected
15
11
 
@@ -50,7 +46,8 @@ module ActiveAdmin
50
46
  column = $1
51
47
  order = $2
52
48
  table = active_admin_config.resource_table_name
53
- table_column = (column =~ /\./) ? column : "#{table}.#{column}"
49
+ table_column = (column =~ /\./) ? column :
50
+ "#{table}.#{active_admin_config.resource_quoted_column_name(column)}"
54
51
 
55
52
  chain.order("#{table_column} #{order}")
56
53
  else
@@ -118,13 +115,23 @@ module ActiveAdmin
118
115
  paginate(super)
119
116
  end
120
117
 
121
- # Allow more records for csv files
122
- def setup_pagination_for_csv
123
- @per_page = 10_000 if request.format == 'text/csv'
118
+ def paginate(chain)
119
+ chain.send(Kaminari.config.page_method_name, params[:page]).per(per_page)
124
120
  end
125
121
 
126
- def paginate(chain)
127
- chain.send(Kaminari.config.page_method_name, params[:page]).per(@per_page || active_admin_namespace.default_per_page)
122
+ def per_page
123
+ return max_csv_records if request.format == 'text/csv'
124
+ return max_per_page if active_admin_config.paginate == false
125
+
126
+ @per_page || active_admin_config.per_page
127
+ end
128
+
129
+ def max_csv_records
130
+ 10_000
131
+ end
132
+
133
+ def max_per_page
134
+ 10_000
128
135
  end
129
136
  end
130
137
 
@@ -53,6 +53,9 @@ module ActiveAdmin
53
53
  end
54
54
  when Page
55
55
  match "/#{config.underscored_resource_name}" => "#{config.underscored_resource_name}#index"
56
+ config.page_actions.each do |action|
57
+ match "/#{config.underscored_resource_name}/#{action.name}" => "#{config.underscored_resource_name}##{action.name}", :via => action.http_verb
58
+ end
56
59
  else
57
60
  raise "Unsupported config class: #{config.class}"
58
61
  end
@@ -1,3 +1,3 @@
1
1
  module ActiveAdmin
2
- VERSION = '0.4.0'
2
+ VERSION = '0.4.1'
3
3
  end
@@ -1,9 +1,70 @@
1
1
  module ActiveAdmin
2
2
  module Views
3
3
 
4
+ # = Columns Component
5
+ #
6
+ # The Columns component allows you draw content into scalable columns. All
7
+ # you need to do is define the number of columns and the component will
8
+ # take care of the rest.
9
+ #
10
+ # == Simple Columns
11
+ #
12
+ # To display columns, use the #columns method. Within the block, call the
13
+ # #column method to create a new column.
14
+ #
15
+ # To createa a two column layout:
16
+ #
17
+ # colums do
18
+ # column do
19
+ # span "Column # 1
20
+ # end
21
+ # column do
22
+ # span "Column # 2
23
+ # end
24
+ # end
25
+ #
26
+ #
27
+ # == Multiple Span Columns
28
+ #
29
+ # To make a column span multiple, pass the :span option to the column method:
30
+ #
31
+ # colums do
32
+ # column :span => 2 do
33
+ # span "Column # 1
34
+ # end
35
+ # column do
36
+ # span "Column # 2
37
+ # end
38
+ # end
39
+ #
40
+ # By default, each column spans 1 column. So the above layout would have 2 columns,
41
+ # the first being 2 time bigger than the second.
42
+ #
43
+ #
44
+ # == Max and Mix Column Sizes
45
+ #
46
+ # Active Admin is a fluid width layout, which means that columns are all defined
47
+ # using percentages. Sometimes this can cause issues if you don't want a column
48
+ # to shrink or expand past a certain point.
49
+ #
50
+ # To overcome this, columns include a :max_width and :min_width option.
51
+ #
52
+ # colums do
53
+ # column :max_width => "200px", :min_width => "100px" do
54
+ # span "Column # 1
55
+ # end
56
+ # column do
57
+ # span "Column # 2
58
+ # end
59
+ # end
60
+ #
61
+ # Now the first column will not grow bigger than 200px and will not shrink smaller
62
+ # than 100px.
4
63
  class Columns < ActiveAdmin::Component
5
64
  builder_method :columns
6
65
 
66
+
67
+ # For documentation, please take a look at Column#build
7
68
  def column(*args, &block)
8
69
  insert_tag Column, *args, &block
9
70
  end
@@ -14,34 +75,76 @@ module ActiveAdmin
14
75
  calculate_columns!
15
76
  end
16
77
 
17
- def to_s
18
- super.to_s + "<div style=\"clear:both;\"></div>".html_safe
19
- end
20
-
21
78
  protected
22
79
 
80
+ # Override the closing tag to include a clear
81
+ def closing_tag
82
+ "<div style=\"clear:both;\"></div>" + super
83
+ end
84
+
23
85
  def margin_size
24
86
  2
25
87
  end
26
88
 
89
+ # Calculate our columns sizes and margins
27
90
  def calculate_columns!
28
- # Calculate our columns sizes and margins
29
- count = children.size
30
- margins_width = margin_size * (count - 1)
31
- column_width = (100.00 - margins_width) / count
91
+ span_count = columns_span_count
92
+ columns_count = children.size
32
93
 
33
- # Convert to an integer if its not a float
34
- column_width = column_width.to_i == column_width ? column_width.to_i : column_width
94
+ all_margins_width = margin_size * (span_count - 1)
95
+ column_width = (100.00 - all_margins_width) / span_count
35
96
 
36
97
  children.each_with_index do |col, i|
37
- col.set_attribute :style, "width: #{column_width}%;"
38
- col.attr(:style) << " margin-right: #{margin_size}%;" unless i == (count - 1)
98
+ is_last_column = i == (columns_count - 1)
99
+ col.set_column_styles(column_width, margin_size, is_last_column)
39
100
  end
40
101
  end
41
102
 
103
+ def columns_span_count
104
+ count = 0
105
+ children.each {|column| count += column.span_size }
106
+
107
+ count
108
+ end
109
+
42
110
  end
43
111
 
44
112
  class Column < ActiveAdmin::Component
113
+
114
+ attr_accessor :span_size, :max_width, :min_width
115
+
116
+ # @param [Hash] options An options hash for the column
117
+ #
118
+ # @options options [Integer] :span The columns this column should span
119
+ def build(options = {})
120
+ options = options.dup
121
+ @span_size = options.delete(:span) || 1
122
+ @max_width = options.delete(:max_width)
123
+ @min_width = options.delete(:min_width)
124
+
125
+ super(options)
126
+ end
127
+
128
+ def set_column_styles(column_width, margin_width, is_last_column = false)
129
+ column_with_span_width = (span_size * column_width) + ((span_size - 1) * margin_width)
130
+
131
+ styles = []
132
+
133
+ styles << "width: #{column_with_span_width}%;"
134
+
135
+ if max_width
136
+ styles << "max-width: #{max_width};"
137
+ end
138
+
139
+ if min_width
140
+ styles << "min-width: #{min_width};"
141
+ end
142
+
143
+ styles << "margin-right: #{margin_width}%;" unless is_last_column
144
+
145
+ set_attribute :style, styles.join(" ")
146
+ end
147
+
45
148
  end
46
149
  end
47
150
  end
@@ -16,17 +16,17 @@ module ActiveAdmin
16
16
  'ul'
17
17
  end
18
18
 
19
- def build(scopes)
19
+ def build(scopes, options = {})
20
20
  unless current_filter_search_empty?
21
21
  scopes.each do |scope|
22
- build_scope(scope) if call_method_or_proc_on(self, scope.display_if_block)
22
+ build_scope(scope, options) if call_method_or_proc_on(self, scope.display_if_block)
23
23
  end
24
24
  end
25
25
  end
26
26
 
27
27
  protected
28
28
 
29
- def build_scope(scope)
29
+ def build_scope(scope, options)
30
30
  li :class => classes_for_scope(scope) do
31
31
  begin
32
32
  scope_name = I18n.t!("active_admin.scopes.#{scope.id}")
@@ -38,7 +38,7 @@ module ActiveAdmin
38
38
  text_node scope_name
39
39
  span :class => 'count' do
40
40
  "(" + get_scope_count(scope).to_s + ")"
41
- end
41
+ end if options[:scope_count]
42
42
  end
43
43
  end
44
44
  end
@@ -97,11 +97,13 @@ module ActiveAdmin
97
97
  :id => active_admin_config.plural_underscored_resource_name,
98
98
  :sortable => true,
99
99
  :class => "index_table",
100
- :i18n => active_admin_config.resource_class
100
+ :i18n => active_admin_config.resource_class,
101
+ :paginator => page_presenter[:paginator] != false
101
102
  }
102
103
 
103
104
  table_for collection, table_options do |t|
104
- instance_exec(t, &page_presenter.block)
105
+ table_config_block = page_presenter.block || default_table
106
+ instance_exec(t, &table_config_block)
105
107
  end
106
108
  end
107
109
 
@@ -109,6 +111,16 @@ module ActiveAdmin
109
111
  insert_tag IndexTableFor, *args, &block
110
112
  end
111
113
 
114
+ def default_table
115
+ proc do
116
+ id_column
117
+ resource_class.content_columns.each do |col|
118
+ column col.name.to_sym
119
+ end
120
+ default_actions
121
+ end
122
+ end
123
+
112
124
  #
113
125
  # Extend the default ActiveAdmin::Views::TableFor with some
114
126
  # methods for quickly displaying items on the index page
@@ -87,7 +87,7 @@ module ActiveAdmin
87
87
 
88
88
  def build_action_items
89
89
  if active_admin_config && active_admin_config.action_items?
90
- items = active_admin_config.action_items_for(params[:action])
90
+ items = active_admin_config.action_items_for(params[:action], self)
91
91
  insert_tag view_factory.action_items, items
92
92
  end
93
93
  end
@@ -135,7 +135,7 @@ module ActiveAdmin
135
135
  # Returns the sidebar sections to render for the current action
136
136
  def sidebar_sections_for_action
137
137
  if active_admin_config && active_admin_config.sidebar_sections?
138
- active_admin_config.sidebar_sections_for(params[:action])
138
+ active_admin_config.sidebar_sections_for(params[:action], self)
139
139
  else
140
140
  []
141
141
  end
@@ -17,7 +17,7 @@ module ActiveAdmin
17
17
  def main_content
18
18
  build_scopes
19
19
 
20
- if collection.any?
20
+ if items_in_collection?
21
21
  render_index
22
22
  else
23
23
  if params[:q]
@@ -29,8 +29,18 @@ module ActiveAdmin
29
29
  end
30
30
 
31
31
  protected
32
-
33
-
32
+
33
+ def items_in_collection?
34
+ # Remove the order clause before limiting to 1. This ensures that
35
+ # any referenced columns in the order will not try to be accessed.
36
+ #
37
+ # When we call #exists?, the query's select statement is changed to "1".
38
+ #
39
+ # If we don't reorder, there may be some columns referenced in the order
40
+ # clause that requires the original select.
41
+ collection.reorder("").limit(1).exists?
42
+ end
43
+
34
44
  # TODO: Refactor to new HTML DSL
35
45
  def build_download_format_links(formats = [:csv, :xml, :json])
36
46
  links = formats.collect do |format|
@@ -41,8 +51,12 @@ module ActiveAdmin
41
51
 
42
52
  def build_scopes
43
53
  if active_admin_config.scopes.any?
54
+ scope_options = {
55
+ :scope_count => config[:scope_count].nil? ? true : config[:scope_count]
56
+ }
57
+
44
58
  div :class => "table_tools" do
45
- scopes_renderer active_admin_config.scopes
59
+ scopes_renderer active_admin_config.scopes, scope_options
46
60
  end
47
61
  end
48
62
  end
@@ -50,13 +64,7 @@ module ActiveAdmin
50
64
  # Creates a default configuration for the resource class. This is a table
51
65
  # with each column displayed as well as all the default actions
52
66
  def default_index_config
53
- @default_index_config ||= ::ActiveAdmin::PagePresenter.new(:as => :table) do |display|
54
- id_column
55
- resource_class.content_columns.each do |col|
56
- column col.name.to_sym
57
- end
58
- default_actions
59
- end
67
+ @default_index_config ||= ::ActiveAdmin::PagePresenter.new(:as => :table)
60
68
  end
61
69
 
62
70
  # Returns the actual class for renderering the main content on the index
@@ -87,9 +95,13 @@ module ActiveAdmin
87
95
 
88
96
  def render_index
89
97
  renderer_class = find_index_renderer_class(config[:as])
98
+ paginator = config[:paginator].nil? ? true : config[:paginator]
99
+ download_links = config[:download_links].nil? ? true : config[:download_links]
90
100
 
91
- paginated_collection(collection, :entry_name => active_admin_config.resource_name,
92
- :entries_name => active_admin_config.plural_resource_name) do
101
+ paginated_collection(collection, :entry_name => active_admin_config.resource_name,
102
+ :entries_name => active_admin_config.plural_resource_name,
103
+ :download_links => download_links,
104
+ :paginator => paginator) do
93
105
  div :class => 'index_content' do
94
106
  insert_tag(renderer_class, config, collection)
95
107
  end
@@ -42,17 +42,29 @@ module ActiveAdmin
42
42
  def build_menu_item(item)
43
43
  li :id => item.dom_id do |li_element|
44
44
  li_element.add_class "current" if current?(item)
45
+ link_path = url_for_menu_item(item)
45
46
 
46
47
  if item.children.any?
47
48
  li_element.add_class "has_nested"
48
- text_node link_to(item.name, item.url || "#")
49
+ text_node link_to(item.name, link_path)
49
50
  render_nested_menu(item)
50
51
  else
51
- link_to item.name, item.url
52
+ link_to item.name, link_path
52
53
  end
53
54
  end
54
55
  end
55
56
 
57
+ def url_for_menu_item(menu_item)
58
+ case menu_item.url
59
+ when Symbol
60
+ send(menu_item.url)
61
+ when nil
62
+ "#"
63
+ else
64
+ menu_item.url
65
+ end
66
+ end
67
+
56
68
  def render_nested_menu(item)
57
69
  ul do
58
70
  displayable_items(item.children).each do |child|
@@ -35,20 +35,6 @@ module ActiveAdmin
35
35
  item.display_if_block.call(self).should == true
36
36
  end
37
37
 
38
- describe "url generation and caching" do
39
- it "should generate a url if it is a symbol" do
40
- item = MenuItem.new("Posts", :admin_posts_path)
41
- MenuItem.should_receive(:generate_url).with(:admin_posts_path).
42
- and_return("/admin/posts")
43
-
44
- item.url.should == "/admin/posts"
45
- end
46
-
47
- it "should generate a url if it is a string" do
48
- MenuItem.new("Posts", "/admin/posts").url.should == "/admin/posts"
49
- end
50
- end
51
-
52
38
  context "with no children" do
53
39
  it "should be empty" do
54
40
  item = MenuItem.new("Blog", "/admin/blog")
@@ -22,7 +22,7 @@ describe ActiveAdmin::Namespace, "registering a resource" do
22
22
  it "should create a menu item" do
23
23
  namespace.load_menu!
24
24
  namespace.menu["Categories"].should be_an_instance_of(ActiveAdmin::MenuItem)
25
- namespace.menu["Categories"].url.should == "/admin/categories"
25
+ namespace.menu["Categories"].url.should == :admin_categories_path
26
26
  end
27
27
  end # context "with no configuration"
28
28
 
@@ -0,0 +1,38 @@
1
+ require 'spec_helper'
2
+
3
+ module ActiveAdmin
4
+ describe Resource, "Pagination" do
5
+
6
+ before { load_defaults! }
7
+
8
+ let(:application){ ActiveAdmin::Application.new }
9
+ let(:namespace){ Namespace.new(application, :admin) }
10
+
11
+ def config(options = {})
12
+ @config ||= Resource.new(namespace, Category, options)
13
+ end
14
+
15
+ describe "#paginate" do
16
+ it "should default to true" do
17
+ config.paginate.should == true
18
+ end
19
+
20
+ it "should be settable to false" do
21
+ config.paginate = false
22
+ config.paginate.should == false
23
+ end
24
+ end
25
+
26
+ describe "#per_page" do
27
+ it "should default to namespace.default_per_page" do
28
+ namespace.should_receive(:default_per_page).and_return(5)
29
+ config.per_page.should == 5
30
+ end
31
+
32
+ it "should be settable" do
33
+ config.per_page = 5
34
+ config.per_page.should == 5
35
+ end
36
+ end
37
+ end
38
+ end