express_admin 1.6.3 → 1.6.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (34) hide show
  1. checksums.yaml +4 -4
  2. data/app/components/express_admin/command_button.rb +39 -36
  3. data/app/components/express_admin/command_button_list.rb +25 -21
  4. data/app/components/express_admin/definition_list.rb +54 -50
  5. data/app/components/express_admin/definition_table.rb +16 -12
  6. data/app/components/express_admin/icon.rb +13 -8
  7. data/app/components/express_admin/icon_link.rb +42 -37
  8. data/app/components/express_admin/layout_component.rb +4 -0
  9. data/app/components/express_admin/layout_components/h_box.rb +5 -1
  10. data/app/components/express_admin/layout_components/pane.rb +24 -19
  11. data/app/components/express_admin/layout_components/sidebar_region.rb +5 -1
  12. data/app/components/express_admin/layout_components/v_box.rb +5 -1
  13. data/app/components/express_admin/main_region.rb +5 -1
  14. data/app/components/express_admin/page_header.rb +15 -11
  15. data/app/components/express_admin/smart_form.rb +106 -102
  16. data/app/components/express_admin/smart_table.rb +177 -165
  17. data/app/helpers/express_admin/admin_helper.rb +8 -0
  18. data/lib/express_admin/version.rb +1 -1
  19. data/test/dummy/db/test.sqlite3 +0 -0
  20. data/vendor/gems/express_templates/Gemfile.lock +7 -1
  21. data/vendor/gems/express_templates/express_templates-0.11.2.gem +0 -0
  22. data/vendor/gems/express_templates/express_templates.gemspec +2 -0
  23. data/vendor/gems/express_templates/lib/express_templates/components/all.rb +17 -15
  24. data/vendor/gems/express_templates/lib/express_templates/components/forms.rb +1 -0
  25. data/vendor/gems/express_templates/lib/express_templates/components/forms/country_select.rb +23 -0
  26. data/vendor/gems/express_templates/lib/express_templates/components/tree_for.rb +72 -70
  27. data/vendor/gems/express_templates/lib/express_templates/template/handler.rb +3 -2
  28. data/vendor/gems/express_templates/lib/express_templates/version.rb +1 -1
  29. data/vendor/gems/express_templates/test/components/forms/country_select_test.rb +34 -0
  30. data/vendor/gems/express_templates/test/dummy/log/test.log +654 -0
  31. data/vendor/gems/express_templates/test/test_helper.rb +1 -1
  32. metadata +5 -4
  33. data/vendor/gems/express_templates/express_templates-0.11.0.gem +0 -0
  34. data/vendor/gems/express_templates/express_templates-0.11.1.gem +0 -0
@@ -1,4 +1,8 @@
1
1
  module ExpressAdmin
2
- class SidebarRegion < LayoutComponent
2
+ module Components
3
+ module Layout
4
+ class SidebarRegion < LayoutComponent
5
+ end
6
+ end
3
7
  end
4
8
  end
@@ -1,4 +1,8 @@
1
1
  module ExpressAdmin
2
- class VBox < LayoutComponent
2
+ module Components
3
+ module Layout
4
+ class VBox < LayoutComponent
5
+ end
6
+ end
3
7
  end
4
8
  end
@@ -1,4 +1,8 @@
1
1
  module ExpressAdmin
2
- class MainRegion < ExpressTemplates::Components::Container
2
+ module Components
3
+ module Layout
4
+ class MainRegion < ExpressTemplates::Components::Container
5
+ end
6
+ end
3
7
  end
4
8
  end
@@ -1,17 +1,21 @@
1
1
  module ExpressAdmin
2
- class PageHeader < ExpressTemplates::Components::Base
2
+ module Components
3
+ module Presenters
4
+ class PageHeader < ExpressTemplates::Components::Base
3
5
 
4
- contains -> {
5
- if content_for?(:page_header)
6
- h1 {
7
- content_for(:page_header)
6
+ contains -> {
7
+ if content_for?(:page_header)
8
+ h1 {
9
+ content_for(:page_header)
10
+ }
11
+ end
12
+ if content_for?(:page_header_lead)
13
+ para(class: 'lead') {
14
+ content_for(:page_header_lead)
15
+ }
16
+ end
8
17
  }
9
18
  end
10
- if content_for?(:page_header_lead)
11
- para(class: 'lead') {
12
- content_for(:page_header_lead)
13
- }
14
- end
15
- }
19
+ end
16
20
  end
17
21
  end
@@ -1,121 +1,125 @@
1
1
  require 'rails/generators/generated_attribute'
2
2
 
3
3
  module ExpressAdmin
4
- class SmartForm < ExpressTemplates::Components::Forms::ExpressForm
5
- TIMESTAMPS = %w(updated_at created_at)
6
-
7
- has_option :virtual, 'Override the list of virtual attributes of the resource to be displayed', type: :array,
8
- values: -> (*) { resource_class.respond_to?(:virtual_attributes) ? resource_class.virtual_attributes : [] }
9
- has_option :exclude, 'Attributes not to be included in the form', type: :array
10
- has_option :only, 'Respects the order the attributes are listed in', type: :array
11
- has_option :show_timestamps, 'Set to true to show timestamps as labels'
12
-
13
- contains {
14
- # TODO: taken from express_form. should be inherited?
15
- div(style: 'display:none') {
16
- add_child helpers.utf8_enforcer_tag
17
- add_child helpers.send(:method_tag, resource.persisted? ? :put : :post)
18
- helpers.send(:token_tag)
19
- }
20
-
21
- filter_by_name(editable_attributes).each do |attrib|
22
- form_field_for(attrib)
23
- end
24
- filter_by_name(has_many_through_associations).each do |assoc|
25
- select_collection(assoc.name, nil, nil, class: 'select2')
26
- end
27
- if show_timestamps?
28
- filter_by_name(timestamp_attributes).each do |timestamp|
29
- div {
30
- label {
31
- "#{timestamp.name.titleize}: #{resource.try(timestamp.name.to_sym)}"
32
- }
4
+ module Components
5
+ module Forms
6
+ class SmartForm < ExpressTemplates::Components::Forms::ExpressForm
7
+ TIMESTAMPS = %w(updated_at created_at)
8
+
9
+ has_option :virtual, 'Override the list of virtual attributes of the resource to be displayed', type: :array,
10
+ values: -> (*) { resource_class.respond_to?(:virtual_attributes) ? resource_class.virtual_attributes : [] }
11
+ has_option :exclude, 'Attributes not to be included in the form', type: :array
12
+ has_option :only, 'Respects the order the attributes are listed in', type: :array
13
+ has_option :show_timestamps, 'Set to true to show timestamps as labels'
14
+
15
+ contains {
16
+ # TODO: taken from express_form. should be inherited?
17
+ div(style: 'display:none') {
18
+ add_child helpers.utf8_enforcer_tag
19
+ add_child helpers.send(:method_tag, resource.persisted? ? :put : :post)
20
+ helpers.send(:token_tag)
33
21
  }
34
- end
35
- end
36
- submit(class: 'button')
37
- }
38
-
39
-
40
- def form_field_for(attrib)
41
- field_type_substitutions = {'text_area' => 'textarea',
42
- 'datetime_select' => 'datetime',
43
- 'check_box' => 'checkbox'}
44
- field_type = attrib.field_type.to_s.sub(/_field$/,'')
45
- field_type = "password" if attrib.name.match(/password/)
46
- if relation = attrib.name.match(/(\w+)_id$/).try(:[], 1)
47
- # TODO: should allow select2 override
48
- select(attrib.name.to_sym, options: config["#{relation}_collection".to_sym], select2: true)
49
- else
50
- if field_type == 'text_area'
51
- if attrib.name == 'definition'
52
- # TODO allow other fields aside from layout.definition
53
- base_styles = "position: relative; height: 300px;"
54
- target = [attributes[:class].to_a.last, attrib.name].join("_")
55
- textarea attrib.name.to_sym, rows: 10, class: "hide", hidden: true
56
- content_tag(:div, '', id: "ace_#{attrib.name}", class: "ace-input", style: base_styles, data: { target: target })
22
+
23
+ filter_by_name(editable_attributes).each do |attrib|
24
+ form_field_for(attrib)
25
+ end
26
+ filter_by_name(has_many_through_associations).each do |assoc|
27
+ select_collection(assoc.name, nil, nil, class: 'select2')
28
+ end
29
+ if show_timestamps?
30
+ filter_by_name(timestamp_attributes).each do |timestamp|
31
+ div {
32
+ label {
33
+ "#{timestamp.name.titleize}: #{resource.try(timestamp.name.to_sym)}"
34
+ }
35
+ }
36
+ end
37
+ end
38
+ submit(class: 'button')
39
+ }
40
+
41
+
42
+ def form_field_for(attrib)
43
+ field_type_substitutions = {'text_area' => 'textarea',
44
+ 'datetime_select' => 'datetime',
45
+ 'check_box' => 'checkbox'}
46
+ field_type = attrib.field_type.to_s.sub(/_field$/,'')
47
+ field_type = "password" if attrib.name.match(/password/)
48
+ if relation = attrib.name.match(/(\w+)_id$/).try(:[], 1)
49
+ # TODO: should allow select2 override
50
+ select(attrib.name.to_sym, options: config["#{relation}_collection".to_sym], select2: true)
57
51
  else
58
- textarea attrib.name.to_sym, rows: 10
52
+ if field_type == 'text_area'
53
+ if attrib.name == 'definition'
54
+ # TODO allow other fields aside from layout.definition
55
+ base_styles = "position: relative; height: 300px;"
56
+ target = [attributes[:class].to_a.last, attrib.name].join("_")
57
+ textarea attrib.name.to_sym, rows: 10, class: "hide", hidden: true
58
+ content_tag(:div, '', id: "ace_#{attrib.name}", class: "ace-input", style: base_styles, data: { target: target })
59
+ else
60
+ textarea attrib.name.to_sym, rows: 10
61
+ end
62
+ else
63
+ self.send((field_type_substitutions[field_type] || field_type), attrib.name.to_sym)
64
+ end
59
65
  end
60
- else
61
- self.send((field_type_substitutions[field_type] || field_type), attrib.name.to_sym)
62
66
  end
63
- end
64
- end
65
67
 
66
- protected
68
+ protected
67
69
 
68
- def resource_attributes
69
- super.map do |attrib|
70
- field_definition = [attrib.name, attrib.type] # index not important here for now
71
- Rails::Generators::GeneratedAttribute.parse(field_definition.join(":"))
72
- end
73
- end
70
+ def resource_attributes
71
+ super.map do |attrib|
72
+ field_definition = [attrib.name, attrib.type] # index not important here for now
73
+ Rails::Generators::GeneratedAttribute.parse(field_definition.join(":"))
74
+ end
75
+ end
74
76
 
75
- def editable_attributes
76
- non_timestamp_attributes + virtual_attributes
77
- end
77
+ def editable_attributes
78
+ non_timestamp_attributes + virtual_attributes
79
+ end
78
80
 
79
- def virtual_attributes
80
- (config[:virtual]||[]).map do |attrib_name|
81
- Rails::Generators::GeneratedAttribute.parse("#{attrib_name}:string")
82
- end
83
- end
81
+ def virtual_attributes
82
+ (config[:virtual]||[]).map do |attrib_name|
83
+ Rails::Generators::GeneratedAttribute.parse("#{attrib_name}:string")
84
+ end
85
+ end
84
86
 
85
- def excluded_attributes
86
- excl = [:id]
87
- excl += config[:exclude] if config[:exclude]
88
- excl
89
- end
87
+ def excluded_attributes
88
+ excl = [:id]
89
+ excl += config[:exclude] if config[:exclude]
90
+ excl
91
+ end
90
92
 
91
- def timestamp_attributes
92
- resource_attributes.select {|attrib| TIMESTAMPS.include?(attrib.name) }
93
- end
93
+ def timestamp_attributes
94
+ resource_attributes.select {|attrib| TIMESTAMPS.include?(attrib.name) }
95
+ end
94
96
 
95
- def show_timestamps?
96
- !!config[:show_timestamps]
97
- end
97
+ def show_timestamps?
98
+ !!config[:show_timestamps]
99
+ end
98
100
 
99
- def non_timestamp_attributes
100
- resource_attributes.reject {|attrib| TIMESTAMPS.include?(attrib.name) }
101
- end
101
+ def non_timestamp_attributes
102
+ resource_attributes.reject {|attrib| TIMESTAMPS.include?(attrib.name) }
103
+ end
102
104
 
103
- def has_many_through_associations
104
- resource_class.reflect_on_all_associations(:has_many).select do |assoc|
105
- assoc.options.keys.include?(:through)
106
- end
107
- end
105
+ def has_many_through_associations
106
+ resource_class.reflect_on_all_associations(:has_many).select do |assoc|
107
+ assoc.options.keys.include?(:through)
108
+ end
109
+ end
108
110
 
109
- def filter_by_name(attribs)
110
- if config[:only]
111
- # if using :only, we respect the order
112
- config[:only].map do |only|
113
- attribs.detect {|attrib| only.to_s.eql?(attrib.name)} || nil
114
- end.compact
115
- else
116
- attribs
117
- end.reject {|attrib| (excluded_attributes).map(&:to_s).include? attrib.name }
118
- end
111
+ def filter_by_name(attribs)
112
+ if config[:only]
113
+ # if using :only, we respect the order
114
+ config[:only].map do |only|
115
+ attribs.detect {|attrib| only.to_s.eql?(attrib.name)} || nil
116
+ end.compact
117
+ else
118
+ attribs
119
+ end.reject {|attrib| (excluded_attributes).map(&:to_s).include? attrib.name }
120
+ end
119
121
 
122
+ end
123
+ end
120
124
  end
121
- end
125
+ end
@@ -1,192 +1,204 @@
1
1
  module ExpressAdmin
2
- class SmartTable < ExpressTemplates::Components::Configurable
3
- include ExpressTemplates::Components::Capabilities::Resourceful
4
-
5
- tag :table
6
-
7
- MAX_COLS_TO_SHOW_IDX = 5
8
-
9
- attr :columns
10
-
11
- has_option :scrollable, 'Set to true if the table should be scrollable', type: :boolean, default: false
12
- has_option :show_actions, 'Set to true if table has actions for each row'
13
- has_option :row_class, 'Add a class to each table row'
14
-
15
- column_defs = {}
16
- column_defs[:array] = {description: "List of fields to include in the table as columns",
17
- options: -> { resource.columns.map(&:name)} }
18
- column_defs[:hash] = {description: "Hash of column names (titles) and how to calculate the cell values."}
19
-
20
- has_option :columns, 'Specify the columns. May provide as a hash with values used to provide cell values as a proc.',
21
- type: [:array, :hash],
22
- values: -> (*) {
23
- options = resource_class.columns.map(&:name)
24
- resource_class.columns.map(&:name).each do |name|
25
- options << if name.match(/(\w+)_at$/)
26
- "#{name}_in_words"
27
- else
28
- "#{name}_link"
29
- end
30
- end
31
- options = options + resource_class.instance_methods.grep(/_count$/).map(&:to_s)
32
- }
33
-
34
- contains -> {
35
- thead {
36
- tr {
37
- display_columns.each do |column|
38
- th(class: column.name) {
39
- column.title
2
+ module Components
3
+ module Presenters
4
+ class SmartTable < ExpressTemplates::Components::Configurable
5
+ include ExpressTemplates::Components::Capabilities::Resourceful
6
+
7
+ tag :table
8
+
9
+ MAX_COLS_TO_SHOW_IDX = 5
10
+
11
+ attr :columns
12
+
13
+ has_option :scrollable, 'Set to true if the table should be scrollable', type: :boolean, default: false
14
+ has_option :show_actions, 'Set to true if table has actions for each row'
15
+ has_option :row_class, 'Add a class to each table row'
16
+
17
+ column_defs = {}
18
+ column_defs[:array] = {description: "List of fields to include in the table as columns",
19
+ options: -> { resource.columns.map(&:name)} }
20
+ column_defs[:hash] = {description: "Hash of column names (titles) and how to calculate the cell values."}
21
+
22
+ has_option :columns, 'Specify the columns. May provide as a hash with values used to provide cell values as a proc.',
23
+ type: [:array, :hash],
24
+ values: -> (*) {
25
+ options = resource_class.columns.map(&:name)
26
+ resource_class.columns.map(&:name).each do |name|
27
+ options << if name.match(/(\w+)_at$/)
28
+ "#{name}_in_words"
29
+ else
30
+ "#{name}_link"
31
+ end
32
+ end
33
+ options = options + resource_class.instance_methods.grep(/_count$/).map(&:to_s)
34
+ }
35
+
36
+ contains -> {
37
+ thead {
38
+ tr {
39
+ display_columns.each do |column|
40
+ th(class: column.name) {
41
+ column.title
42
+ }
43
+ end
44
+ actions_header if should_show_actions?
45
+ hidden_columns_header_indicator if columns_hidden?
40
46
  }
41
- end
42
- actions_header if should_show_actions?
43
- hidden_columns_header_indicator if columns_hidden?
44
- }
45
- }
46
- tbody {
47
- stored_member_assigns = assigns[collection_member_name.to_sym]
48
- collection.each do |item|
49
- assigns[collection_member_name.to_sym] = item
50
- tr(id: row_id(item), class: row_class(item)) {
51
- display_columns.each do |column|
52
- td(class: column.name) {
53
- cell_value(item, column.accessor)
47
+ }
48
+ tbody {
49
+ stored_member_assigns = assigns[collection_member_name.to_sym]
50
+ collection.each do |item|
51
+ assigns[collection_member_name.to_sym] = item
52
+ tr(id: row_id(item), class: row_class(item)) {
53
+ display_columns.each do |column|
54
+ td(class: column.name) {
55
+ cell_value(item, column.accessor)
56
+ }
57
+ end
58
+ actions_column(item) if should_show_actions?
59
+ hidden_column_cell if columns_hidden?
54
60
  }
55
- end
56
- actions_column(item) if should_show_actions?
57
- hidden_column_cell if columns_hidden?
61
+ assigns[collection_member_name.to_sym] = stored_member_assigns
62
+ end ; nil
58
63
  }
59
- assigns[collection_member_name.to_sym] = stored_member_assigns
60
- end ; nil
61
- }
62
-
63
- scroll_table if !!config[:scrollable]
64
- }
65
-
66
- before_build -> {
67
- _initialize_columns
68
- add_class 'table striped'
69
- }
70
-
71
- def scroll_table
72
- script {
73
- %Q($('\##{config[:id]}').scrollTableBody())
74
- }
75
- end
76
64
 
77
- def actions_header
78
- th(class: 'actions') { 'Actions' }
79
- end
65
+ scroll_table if !!config[:scrollable]
66
+ }
80
67
 
81
- def should_show_actions?
82
- !!config[:show_actions]
83
- end
68
+ before_build -> {
69
+ _initialize_columns
70
+ add_class 'table striped'
71
+ }
84
72
 
85
- def should_show_delete?(item)
86
- if item.respond_to?(:can_delete?) && item.can_delete?
87
- true
88
- elsif !item.respond_to?(:can_delete?)
89
- true
90
- else
91
- false
92
- end
93
- end
73
+ def scroll_table
74
+ script {
75
+ %Q($('\##{config[:id]}').scrollTableBody())
76
+ }
77
+ end
94
78
 
95
- def actions_column(item)
96
- td {
97
- if should_show_delete?(item)
98
- link_to 'Delete', resource_path(item), method: :delete, data: {confirm: 'Are you sure?'}, class: 'button small secondary'
79
+ def actions_header
80
+ th(class: 'actions') { 'Actions' }
99
81
  end
100
- }
101
- end
102
82
 
103
- def row_class(item)
104
- if config[:row_class].try(:respond_to?, :call)
105
- config[:row_class].call(item)
106
- else
107
- item.eql?(resource) ? 'current' : ''
108
- end
109
- end
83
+ def should_show_actions?
84
+ !!config[:show_actions]
85
+ end
110
86
 
111
- def row_id(item)
112
- "#{collection_member_name}:#{item.to_param}"
113
- end
87
+ def should_show_delete?(item)
88
+ if item.respond_to?(:can_delete?) && item.can_delete?
89
+ true
90
+ elsif !item.respond_to?(:can_delete?)
91
+ true
92
+ else
93
+ false
94
+ end
95
+ end
114
96
 
115
- def cell_value(item, accessor)
116
- value = if accessor.respond_to?(:call)
117
- begin
118
- accessor.call(item).try(:html_safe)
119
- rescue
120
- 'Error: '+$!.to_s
121
- end
122
- elsif attrib = accessor.to_s.match(/(\w+)_link$/).try(:[], 1)
123
- # TODO: only works with non-namespaced routes
124
- helpers.link_to item.send(attrib), resource_path(item)
125
- elsif attrib = accessor.to_s.match(/(\w+)_in_words/).try(:[], 1)
126
- item.send(attrib) ? (helpers.time_ago_in_words(item.send(attrib))+' ago') : 'never'
127
- else
128
- if relation_name = accessor.to_s.match(/(.*)_id$/).try(:[], 1)
129
- reflection = resource_class.reflect_on_association(relation_name.to_sym)
130
- end
97
+ def actions_column(item)
98
+ td {
99
+ if should_show_delete?(item)
100
+ link_to 'Delete', resource_path(item), method: :delete, data: {confirm: 'Are you sure?'}, class: 'button small secondary'
101
+ end
102
+ }
103
+ end
131
104
 
132
- if reflection
133
- relation = item.send(relation_name)
134
- relation.try(:name) || relation.to_s
135
- else
136
- item.send(accessor)
137
- end
138
- end
139
- current_arbre_element.add_child value
140
- end
105
+ def row_class(item)
106
+ if config[:row_class].try(:respond_to?, :call)
107
+ config[:row_class].call(item)
108
+ else
109
+ item.eql?(resource) ? 'current' : ''
110
+ end
111
+ end
141
112
 
142
- def display_columns
143
- specified_columns? ? @columns : @columns.slice(1..MAX_COLS_TO_SHOW_IDX)
144
- end
113
+ def row_id(item)
114
+ "#{collection_member_name}:#{item.to_param}"
115
+ end
145
116
 
146
- def columns_hidden?
147
- !specified_columns? && columns.size > MAX_COLS_TO_SHOW_IDX+1
148
- end
117
+ def cell_value(item, accessor)
118
+ value = if accessor.respond_to?(:call)
119
+ begin
120
+ accessor.call(item).try(:html_safe)
121
+ rescue
122
+ 'Error: '+$!.to_s
123
+ end
124
+ elsif attrib = accessor.to_s.match(/(\w+)_link$/).try(:[], 1)
125
+ # TODO: only works with non-namespaced routes
126
+ helpers.link_to item.send(attrib), resource_path(item)
127
+ elsif attrib = accessor.to_s.match(/(\w+)_in_words/).try(:[], 1)
128
+ if item.send(attrib)
129
+ if item.send(attrib) < DateTime.now
130
+ "#{helpers.time_ago_in_words(item.send(attrib))} ago"
131
+ else
132
+ helpers.time_ago_in_words(item.send(attrib))
133
+ end
134
+ else
135
+ 'never'
136
+ end
137
+ else
138
+ if relation_name = accessor.to_s.match(/(.*)_id$/).try(:[], 1)
139
+ reflection = resource_class.reflect_on_association(relation_name.to_sym)
140
+ end
141
+
142
+ if reflection
143
+ relation = item.send(relation_name)
144
+ relation.try(:name) || relation.to_s
145
+ else
146
+ item.send(accessor)
147
+ end
148
+ end
149
+ current_arbre_element.add_child value
150
+ end
149
151
 
150
- class Column
151
- attr :name, :title, :accessor
152
- def initialize(accessor, title = nil)
153
- @name = accessor.kind_of?(Symbol) ? accessor.to_s.underscore : title.titleize.gsub(/\s+/,'').underscore
154
- @accessor = accessor
155
- @title = title || @name.titleize
156
- end
157
- end
152
+ def display_columns
153
+ specified_columns? ? @columns : @columns.slice(1..MAX_COLS_TO_SHOW_IDX)
154
+ end
158
155
 
159
- def specified_columns?
160
- !!specified_columns
161
- end
156
+ def columns_hidden?
157
+ !specified_columns? && columns.size > MAX_COLS_TO_SHOW_IDX+1
158
+ end
162
159
 
163
- def specified_columns
164
- config[:columns]
165
- end
160
+ class Column
161
+ attr :name, :title, :accessor
162
+ def initialize(accessor, title = nil)
163
+ @name = accessor.kind_of?(Symbol) ? accessor.to_s.underscore : title.titleize.gsub(/\s+/,'').underscore
164
+ @accessor = accessor
165
+ @title = title || @name.titleize
166
+ end
167
+ end
166
168
 
167
- def hidden_columns_header_indicator
168
- th(class: 'more-columns-indicator') {
169
- "..."
170
- }
171
- end
169
+ def specified_columns?
170
+ !!specified_columns
171
+ end
172
172
 
173
- def hidden_column_cell
174
- td(class: 'more-columns-indicator')
175
- end
173
+ def specified_columns
174
+ config[:columns]
175
+ end
176
176
 
177
- private
178
- def _initialize_columns
179
- @columns =
180
- if specified_columns.kind_of?(Array)
181
- specified_columns.map { |name| Column.new(name) }
177
+ def hidden_columns_header_indicator
178
+ th(class: 'more-columns-indicator') {
179
+ "..."
180
+ }
181
+ end
182
182
 
183
- elsif specified_columns.kind_of?(Hash)
184
- specified_columns.map { |title, accessor| Column.new(accessor, title) }
183
+ def hidden_column_cell
184
+ td(class: 'more-columns-indicator')
185
+ end
185
186
 
186
- else
187
- resource_attributes.map { |column| Column.new(column.name.to_sym) }
187
+ private
188
+ def _initialize_columns
189
+ @columns =
190
+ if specified_columns.kind_of?(Array)
191
+ specified_columns.map { |name| Column.new(name) }
192
+
193
+ elsif specified_columns.kind_of?(Hash)
194
+ specified_columns.map { |title, accessor| Column.new(accessor, title) }
195
+
196
+ else
197
+ resource_attributes.map { |column| Column.new(column.name.to_sym) }
198
+ end
188
199
  end
189
- end
190
200
 
201
+ end
202
+ end
191
203
  end
192
204
  end