datagrid 0.9.3 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (39) hide show
  1. data/Readme.markdown +6 -4
  2. data/VERSION +1 -1
  3. data/app/assets/stylesheets/datagrid.css.sass +132 -0
  4. data/app/views/datagrid/_form.html.erb +5 -2
  5. data/app/views/datagrid/_order_for.html.erb +2 -2
  6. data/app/views/datagrid/_table.html.erb +1 -1
  7. data/datagrid.gemspec +10 -3
  8. data/lib/datagrid.rb +1 -0
  9. data/lib/datagrid/column_names_attribute.rb +38 -7
  10. data/lib/datagrid/columns.rb +38 -4
  11. data/lib/datagrid/columns/column.rb +29 -1
  12. data/lib/datagrid/drivers/abstract_driver.rb +8 -0
  13. data/lib/datagrid/drivers/active_record.rb +29 -1
  14. data/lib/datagrid/drivers/array.rb +14 -2
  15. data/lib/datagrid/drivers/mongo_mapper.rb +8 -0
  16. data/lib/datagrid/drivers/mongoid.rb +9 -1
  17. data/lib/datagrid/filters.rb +24 -6
  18. data/lib/datagrid/filters/base_filter.rb +42 -14
  19. data/lib/datagrid/filters/boolean_enum_filter.rb +1 -1
  20. data/lib/datagrid/filters/dynamic_filter.rb +57 -0
  21. data/lib/datagrid/filters/enum_filter.rb +4 -21
  22. data/lib/datagrid/filters/select_options.rb +26 -0
  23. data/lib/datagrid/form_builder.rb +41 -8
  24. data/lib/datagrid/helper.rb +2 -1
  25. data/lib/datagrid/i18n.rb +0 -0
  26. data/lib/datagrid/locale/en.yml +28 -0
  27. data/lib/datagrid/ordering.rb +33 -19
  28. data/lib/datagrid/utils.rb +8 -9
  29. data/spec/datagrid/column_names_attribute_spec.rb +44 -1
  30. data/spec/datagrid/columns_spec.rb +16 -0
  31. data/spec/datagrid/filters/dynamic_filter_spec.rb +37 -0
  32. data/spec/datagrid/filters/integer_filter_spec.rb +18 -0
  33. data/spec/datagrid/filters/string_filter_spec.rb +25 -0
  34. data/spec/datagrid/filters_spec.rb +15 -1
  35. data/spec/datagrid/form_builder_spec.rb +83 -0
  36. data/spec/datagrid/helper_spec.rb +1 -0
  37. data/spec/datagrid/ordering_spec.rb +41 -1
  38. data/spec/datagrid/utils_spec.rb +7 -2
  39. metadata +11 -4
@@ -93,12 +93,12 @@ In order to create a report, you need to define:
93
93
  ### Scope
94
94
 
95
95
  Default scope of objects to filter and display.
96
- In common case it is `ActiveRecord::Base` (or any other supported ORM) subclass with some generic scopes like in example above:
96
+ In common case it is `ActiveRecord::Base` (or any other supported ORM) subclass with some generic scopes like:
97
97
 
98
98
  ``` ruby
99
- scope do
100
- User.includes(:group)
101
- end
99
+ scope do
100
+ User.includes(:group)
101
+ end
102
102
  ```
103
103
 
104
104
  [More about scope](https://github.com/bogdan/datagrid/wiki/Scope)
@@ -116,11 +116,13 @@ Datagrid supports different type of filters including:
116
116
 
117
117
  * text
118
118
  * integer
119
+ * float
119
120
  * date
120
121
  * boolean
121
122
  * eboolean - the select of "yes", "no" and any
122
123
  * enum
123
124
  * string
125
+ * dynamic
124
126
 
125
127
  [More about filters](https://github.com/bogdan/datagrid/wiki/Filters)
126
128
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.9.3
1
+ 1.0.0
@@ -0,0 +1,132 @@
1
+ $dg-form-label: 150px
2
+
3
+ = clearfix
4
+ *zoom: 1
5
+
6
+ &:before,
7
+ &:after
8
+ display: table
9
+ content: ''
10
+
11
+ &:after
12
+ clear: both
13
+
14
+ =inline-block
15
+ display: inline-block
16
+ zoom: 1
17
+ *display: inline
18
+
19
+ table.datagrid
20
+ background-color: transparent
21
+ border-collapse: collapse
22
+ max-width: 100%
23
+
24
+ th
25
+ background-color: #eee
26
+ text-align: left
27
+
28
+ td,
29
+ th
30
+ border: 1px solid #d6d6d6
31
+ padding: 5px 10px
32
+
33
+ .order
34
+ a.asc, a.desc
35
+ text-decoration: none
36
+ font-weight: normal
37
+
38
+ &.ordered
39
+ background-color: #fff7d5
40
+
41
+ &.asc
42
+ a.asc
43
+ font-weight: bold
44
+ color: #d00
45
+
46
+ &.desc
47
+ a.desc
48
+ font-weight: bold
49
+ color: #d00
50
+ .noresults
51
+ text-align: center
52
+
53
+ .datagrid-form
54
+ background-color: #f0f0f0
55
+ border-radius: 5px
56
+ padding: 20px
57
+
58
+ .datagrid-filter
59
+ margin: 10px
60
+ +clearfix
61
+
62
+ label
63
+ width: $dg-form-label
64
+ float: left
65
+ a
66
+ float: left
67
+
68
+ &.dp-choose-date
69
+ margin-left: -22px
70
+ margin-top: 7px
71
+
72
+ input[class*='filter']
73
+ border: 2px solid #ccc
74
+ border-radius: 4px
75
+ float: left
76
+ padding: 5px 12px
77
+ width: 207px
78
+
79
+ &.from, &.to
80
+ width: 83px
81
+
82
+ select
83
+ float: left
84
+ width: 235px
85
+
86
+ &[multiple]
87
+ border: 2px solid #ccc
88
+ border-radius: 5px
89
+ height: 100px
90
+ &.dynamic_filter
91
+ &.field
92
+ width: 178px
93
+ &.operation
94
+ margin-left: 7px
95
+ width: 50px
96
+ input.dynamic_filter.value
97
+ margin: 10px 0 0 $dg-form-label
98
+ clear: both
99
+
100
+ .separator
101
+ float: left
102
+ margin: 6px 4px 0
103
+
104
+
105
+ .datagrid-actions
106
+ padding-left: $dg-form-label +10
107
+
108
+ input[type='submit']
109
+ background-color: #555
110
+ border: none
111
+ border-radius: 5px
112
+ color: white
113
+ cursor: pointer
114
+ font-size: 14px
115
+ font-weight: bold
116
+ line-height: normal
117
+ padding: 7px 15px
118
+ vertical-align: middle
119
+ +inline-block
120
+
121
+ &:hover,
122
+ &:focus
123
+ background-color: #333
124
+
125
+ &:active
126
+ background-color: #000
127
+
128
+ > a
129
+ font-size: 14px
130
+ padding: 7px 15px
131
+ vertical-align: middle
132
+ +inline-block
@@ -1,9 +1,12 @@
1
1
  <%= form_for grid, options do |f| -%>
2
2
  <% grid.filters.each do |filter| %>
3
- <div class="filter">
3
+ <div class="datagrid-filter filter">
4
4
  <%= f.datagrid_label filter %>
5
5
  <%= f.datagrid_filter filter %>
6
6
  </div>
7
7
  <% end %>
8
- <%= f.submit I18n.t("datgrid.form.submit", :default => "Search").html_safe %>
8
+ <div class="datagrid-actions">
9
+ <%= f.submit I18n.t("datagrid.form.search").html_safe, :class => "datagrid-submit" %>
10
+ <%= link_to I18n.t('datagrid.form.reset').html_safe, url_for(grid.to_param => {}), :class => "datagrid-reset" %>
11
+ </div>
9
12
  <% end -%>
@@ -1,10 +1,10 @@
1
1
  <div class="order">
2
2
  <%= link_to(
3
- I18n.t("datagrid.table.order.asc", :default => "&uarr;".html_safe).html_safe,
3
+ I18n.t("datagrid.table.order.asc").html_safe,
4
4
  url_for(grid.param_name => grid.as_query.merge(:order => column.name, :descending => false)),
5
5
  :class => "asc") %>
6
6
  <%= link_to(
7
- I18n.t("datagrid.table.order.desc", :default => "&darr;".html_safe).html_safe,
7
+ I18n.t("datagrid.table.order.desc").html_safe,
8
8
  url_for(grid.param_name => grid.as_query.merge(:order => column.name, :descending => true )),
9
9
  :class => "desc") %>
10
10
  </div>
@@ -10,7 +10,7 @@ Local variables:
10
10
  </thead>
11
11
  <tbody>
12
12
  <% if assets.empty? %>
13
- <tr><td class="noresults" colspan="100%"><%= I18n.t 'datagrid.no_results', :default => '&mdash;&mdash;'.html_safe %></td></tr>
13
+ <tr><td class="noresults" colspan="100%"><%= I18n.t('datagrid.no_results').html_safe %></td></tr>
14
14
  <% else %>
15
15
  <%= datagrid_rows(grid, assets, options) %>
16
16
  <% end %>
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = "datagrid"
8
- s.version = "0.9.3"
8
+ s.version = "1.0.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Bogdan Gusiev"]
12
- s.date = "2013-08-26"
12
+ s.date = "2013-09-19"
13
13
  s.description = "This allows you to easily build datagrid aka data tables with sortable columns and filters"
14
14
  s.email = "agresso@gmail.com"
15
15
  s.extra_rdoc_files = [
@@ -23,6 +23,7 @@ Gem::Specification.new do |s|
23
23
  "Rakefile",
24
24
  "Readme.markdown",
25
25
  "VERSION",
26
+ "app/assets/stylesheets/datagrid.css.sass",
26
27
  "app/views/datagrid/_form.html.erb",
27
28
  "app/views/datagrid/_head.html.erb",
28
29
  "app/views/datagrid/_order_for.html.erb",
@@ -50,13 +51,17 @@ Gem::Specification.new do |s|
50
51
  "lib/datagrid/filters/composite_filters.rb",
51
52
  "lib/datagrid/filters/date_filter.rb",
52
53
  "lib/datagrid/filters/default_filter.rb",
54
+ "lib/datagrid/filters/dynamic_filter.rb",
53
55
  "lib/datagrid/filters/enum_filter.rb",
54
56
  "lib/datagrid/filters/float_filter.rb",
55
57
  "lib/datagrid/filters/integer_filter.rb",
56
58
  "lib/datagrid/filters/ranged_filter.rb",
59
+ "lib/datagrid/filters/select_options.rb",
57
60
  "lib/datagrid/filters/string_filter.rb",
58
61
  "lib/datagrid/form_builder.rb",
59
62
  "lib/datagrid/helper.rb",
63
+ "lib/datagrid/i18n.rb",
64
+ "lib/datagrid/locale/en.yml",
60
65
  "lib/datagrid/ordering.rb",
61
66
  "lib/datagrid/renderer.rb",
62
67
  "lib/datagrid/rspec.rb",
@@ -74,9 +79,11 @@ Gem::Specification.new do |s|
74
79
  "spec/datagrid/filters/boolean_enum_filter_spec.rb",
75
80
  "spec/datagrid/filters/composite_filters_spec.rb",
76
81
  "spec/datagrid/filters/date_filter_spec.rb",
82
+ "spec/datagrid/filters/dynamic_filter_spec.rb",
77
83
  "spec/datagrid/filters/enum_filter_spec.rb",
78
84
  "spec/datagrid/filters/float_filter_spec.rb",
79
85
  "spec/datagrid/filters/integer_filter_spec.rb",
86
+ "spec/datagrid/filters/string_filter_spec.rb",
80
87
  "spec/datagrid/filters_spec.rb",
81
88
  "spec/datagrid/form_builder_spec.rb",
82
89
  "spec/datagrid/helper_spec.rb",
@@ -99,7 +106,7 @@ Gem::Specification.new do |s|
99
106
  s.homepage = "http://github.com/bogdan/datagrid"
100
107
  s.licenses = ["MIT"]
101
108
  s.require_paths = ["lib"]
102
- s.rubygems_version = "1.8.24"
109
+ s.rubygems_version = "1.8.25"
103
110
  s.summary = "Ruby gem to create datagrids"
104
111
 
105
112
  if s.respond_to? :specification_version then
@@ -46,5 +46,6 @@ module Datagrid
46
46
  end
47
47
 
48
48
  require "datagrid/scaffold"
49
+ I18n.load_path << File.expand_path('../datagrid/locale/en.yml', __FILE__)
49
50
 
50
51
 
@@ -9,7 +9,7 @@ module Datagrid
9
9
  datagrid_attribute :column_names do |names|
10
10
  names = Array(names).reject(&:blank?)
11
11
  if names.reject(&:blank?).blank?
12
- columns.map(&:name)
12
+ []
13
13
  else
14
14
  names
15
15
  end
@@ -18,10 +18,12 @@ module Datagrid
18
18
 
19
19
  module ClassMethods
20
20
  # Adds a filter that acts like a column selection
21
- def column_names_filter
22
- filter(:column_names, :enum, :select => proc { |grid| grid.class.columns.map {|c| [c.header, c.name] }}, :multiple => true ) do |value|
23
- scoped
24
- end
21
+ def column_names_filter(options = {})
22
+ filter(:column_names, :enum, {
23
+ :select => :optional_columns_select,
24
+ :multiple => true,
25
+ :dummy => true
26
+ }.merge(options || {}))
25
27
  end
26
28
  end
27
29
 
@@ -32,17 +34,46 @@ module Datagrid
32
34
  super(*column_names)
33
35
  end
34
36
 
37
+ # Returns a list of columns with <tt>:mandatory => true</tt> option
38
+ # If no mandatory columns specified than all of them considered mandatory
39
+ def mandatory_columns
40
+ self.class.columns.select(&:mandatory?)
41
+ end
42
+
43
+ # Returns a list of columns without <tt>:mandatory => true</tt> option
44
+ def optional_columns
45
+ self.class.columns - mandatory_columns
46
+ end
47
+
35
48
  protected
36
49
 
37
- def selected_column_names(*args)
50
+ def optional_columns_select #:nodoc:
51
+ optional_columns.map {|c| [c.header, c.name] }
52
+ end
53
+
54
+ def selected_column_names(*args)
38
55
  if args.any?
39
56
  args.compact!
40
57
  args.map!(&:to_sym)
41
58
  args
42
59
  else
43
- column_names ? column_names.clone : []
60
+ if column_names && column_names.any?
61
+ column_names + mandatory_columns.map(&:name)
62
+ else
63
+ columns_enabled_by_default.map(&:name)
64
+ end
44
65
  end
45
66
  end
67
+
68
+ def columns_visibility_enabled?
69
+ self.class.columns.any? do |column|
70
+ column.options.key?(:mandatory)
71
+ end
72
+ end
73
+
74
+ def columns_enabled_by_default
75
+ columns_visibility_enabled? ? mandatory_columns : []
76
+ end
46
77
  end
47
78
  end
48
79
 
@@ -12,12 +12,39 @@ module Datagrid
12
12
 
13
13
  include Datagrid::Core
14
14
 
15
+ class_attribute :default_column_options
16
+ self.default_column_options = {}
17
+
15
18
  end
16
19
  base.send :include, InstanceMethods
17
20
  end # self.included
18
21
 
19
22
  module ClassMethods
20
23
 
24
+
25
+ ##
26
+ # :method: default_column_options=
27
+ #
28
+ # :call-seq: default_column_options=(options)
29
+ #
30
+ # Specifies default options for `column` method.
31
+ # They still can be overwritten at column level.
32
+ #
33
+ # # Disable default order
34
+ # self.default_column_options = { :order => false }
35
+ # # Makes entire report HTML
36
+ # self.default_column_options = { :html => true }
37
+ #
38
+
39
+ ##
40
+ # :method: default_column_options
41
+ #
42
+ # :call-seq: default_column_options
43
+ #
44
+ # Returns specified default column options hash
45
+ # See <tt>default_column_options=</tt> for more information
46
+ #
47
+
21
48
  # Returns a list of columns defined.
22
49
  # All column definistion are returned by default
23
50
  # You can limit the output with only columns you need like:
@@ -32,7 +59,7 @@ module Datagrid
32
59
  args.compact!
33
60
  args.map!(&:to_sym)
34
61
  columns_array.select do |column|
35
- (!options[:data] || column.data?) && (!options[:html] || column.html?)&& (args.empty? || args.include?(column.name))
62
+ (!options[:data] || column.data?) && (!options[:html] || column.html?) && (column.mandatory? || args.empty? || args.include?(column.name))
36
63
  end
37
64
  end
38
65
 
@@ -47,8 +74,15 @@ module Datagrid
47
74
  # Available options:
48
75
  #
49
76
  # * <tt>:html</tt> - determines if current column should be present in html table and how is it formatted
50
- # * <tt>:order</tt> - determines if this column could be sortable and how
51
- # * <tt>:order_desc</tt> - determines a descending order for given column (only in case when <tt>:order</tt> can not be easily inverted
77
+ # * <tt>:order</tt> - determines if this column could be sortable and how.
78
+ # The value of order is explicitly passed to ORM ordering method.
79
+ # Ex: <tt>"created_at, id"</tt> for ActiveRecord, <tt>[:created_at, :id]</tt> for Mongoid
80
+ # * <tt>:order_desc</tt> - determines a descending order for given column
81
+ # (only in case when <tt>:order</tt> can not be easily reversed by ORM)
82
+ # * <tt>:order_by_value</tt> - used in case it is easier to perform ordering at ruby level not on database level.
83
+ # Warning: using ruby to order large datasets is very unrecommended.
84
+ # If set to true - datagrid will use column value to order by this column
85
+ # If block is given - datagrid will use value returned from block
52
86
  # * <tt>:url</tt> - a proc with one argument, pass this option to easily convert the value into an URL
53
87
  # * <tt>:before</tt> - determines the position of this column, by adding it before the column passed here
54
88
  # * <tt>:after</tt> - determines the position of this column, by adding it after the column passed here
@@ -60,7 +94,7 @@ module Datagrid
60
94
  model.send(name)
61
95
  end
62
96
  position = Datagrid::Utils.extract_position_from_options(columns_array, options)
63
- column = Datagrid::Columns::Column.new(self, name, options, &block)
97
+ column = Datagrid::Columns::Column.new(self, name, default_column_options.merge(options), &block)
64
98
  columns_array.insert(position, column)
65
99
  end
66
100
 
@@ -58,13 +58,29 @@ class Datagrid::Columns::Column
58
58
  end
59
59
 
60
60
  def order
61
- if options.has_key?(:order)
61
+ if options.has_key?(:order) && options[:order] != true
62
62
  self.options[:order]
63
63
  else
64
64
  grid_class.driver.default_order(grid_class.scope, name)
65
65
  end
66
66
  end
67
67
 
68
+ def supports_order?
69
+ order || order_by_value?
70
+ end
71
+
72
+ def order_by_value(model, grid)
73
+ if options[:order_by_value] == true
74
+ data_value(model, grid)
75
+ else
76
+ Datagrid::Utils.apply_args(model, grid, &options[:order_by_value])
77
+ end
78
+ end
79
+
80
+ def order_by_value?
81
+ !! options[:order_by_value]
82
+ end
83
+
68
84
  def order_desc
69
85
  return nil unless order
70
86
  self.options[:order_desc]
@@ -77,6 +93,18 @@ class Datagrid::Columns::Column
77
93
  def data?
78
94
  self.data_block != nil
79
95
  end
96
+
97
+ def mandatory?
98
+ !! options[:mandatory]
99
+ end
100
+
101
+ def inspect
102
+ "#<Datagird::Columns::Column #{grid_class}##{name} #{options.inspect}>"
103
+ end
104
+
105
+ def to_s
106
+ header
107
+ end
80
108
 
81
109
  def html_value(context, asset, grid)
82
110
  if html? && html_block