katalyst-tables 3.1.0 → 3.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (48) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +21 -0
  3. data/README.md +27 -0
  4. data/app/assets/builds/katalyst/tables.esm.js +16 -0
  5. data/app/assets/builds/katalyst/tables.js +16 -0
  6. data/app/assets/builds/katalyst/tables.min.js +1 -1
  7. data/app/assets/builds/katalyst/tables.min.js.map +1 -1
  8. data/app/assets/stylesheets/katalyst/tables/_filter.scss +43 -0
  9. data/app/assets/stylesheets/katalyst/tables/_index.scss +1 -0
  10. data/app/assets/stylesheets/katalyst/tables/_select.scss +3 -0
  11. data/app/assets/stylesheets/katalyst/tables/_table.scss +3 -0
  12. data/app/assets/stylesheets/katalyst/tables/typed-columns/_enum.scss +9 -0
  13. data/app/assets/stylesheets/katalyst/tables/typed-columns/_index.scss +1 -0
  14. data/app/components/katalyst/table_component.rb +28 -0
  15. data/app/components/katalyst/tables/cells/enum_component.rb +27 -0
  16. data/app/components/katalyst/tables/filter/modal_component.html.erb +25 -0
  17. data/app/components/katalyst/tables/filter/modal_component.rb +112 -0
  18. data/app/components/katalyst/tables/filter_component.html.erb +18 -0
  19. data/app/components/katalyst/tables/filter_component.rb +91 -0
  20. data/app/helpers/katalyst/tables/frontend.rb +8 -0
  21. data/app/javascript/tables/application.js +5 -0
  22. data/app/javascript/tables/filter/modal_controller.js +13 -0
  23. data/app/models/concerns/katalyst/tables/collection/core.rb +44 -0
  24. data/app/models/concerns/katalyst/tables/collection/filtering.rb +17 -9
  25. data/app/models/concerns/katalyst/tables/collection/pagination.rb +1 -1
  26. data/app/models/concerns/katalyst/tables/collection/query/array_value_parser.rb +56 -0
  27. data/app/models/concerns/katalyst/tables/collection/query/parser.rb +73 -0
  28. data/app/models/concerns/katalyst/tables/collection/query/single_value_parser.rb +24 -0
  29. data/app/models/concerns/katalyst/tables/collection/query/value_parser.rb +34 -0
  30. data/app/models/concerns/katalyst/tables/collection/query.rb +34 -0
  31. data/app/models/concerns/katalyst/tables/collection/sorting.rb +1 -1
  32. data/app/models/katalyst/tables/collection/array.rb +0 -1
  33. data/app/models/katalyst/tables/collection/base.rb +0 -5
  34. data/app/models/katalyst/tables/collection/filter.rb +0 -1
  35. data/app/models/katalyst/tables/collection/type/boolean.rb +22 -0
  36. data/app/models/katalyst/tables/collection/type/date.rb +60 -0
  37. data/app/models/katalyst/tables/collection/type/enum.rb +21 -0
  38. data/app/models/katalyst/tables/collection/type/float.rb +57 -0
  39. data/app/models/katalyst/tables/collection/type/helpers/delegate.rb +50 -0
  40. data/app/models/katalyst/tables/collection/type/helpers/extensions.rb +28 -0
  41. data/app/models/katalyst/tables/collection/type/helpers/multiple.rb +30 -0
  42. data/app/models/katalyst/tables/collection/type/integer.rb +57 -0
  43. data/app/models/katalyst/tables/collection/type/query.rb +19 -0
  44. data/app/models/katalyst/tables/collection/type/search.rb +26 -0
  45. data/app/models/katalyst/tables/collection/type/string.rb +35 -0
  46. data/app/models/katalyst/tables/collection/type/value.rb +66 -0
  47. data/app/models/katalyst/tables/collection/type.rb +39 -0
  48. metadata +30 -3
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Katalyst
4
+ module Tables
5
+ module Collection
6
+ module Type
7
+ module Helpers
8
+ # Lifts a delegating type from value to arrays of values
9
+ module Delegate
10
+ delegate :type, to: :@delegate
11
+
12
+ def initialize(delegate:, **arguments)
13
+ super(**arguments)
14
+
15
+ @delegate = delegate.new(**arguments.except(:filter, :multiple, :scope))
16
+ end
17
+
18
+ using Extensions
19
+
20
+ def deserialize(value)
21
+ if multiple? && value.is_a?(::Array)
22
+ value.map { |v| @delegate.deserialize(v) }
23
+ else
24
+ @delegate.deserialize(value)
25
+ end
26
+ end
27
+
28
+ def serialize(value)
29
+ if multiple? && value.is_a?(::Array)
30
+ value.map { |v| @delegate.serialize(v) }
31
+ else
32
+ @delegate.serialize(value)
33
+ end
34
+ end
35
+
36
+ private
37
+
38
+ def cast_value(value)
39
+ if multiple? && value.is_a?(::Array)
40
+ value.map { |v| @delegate.cast(v) }
41
+ else
42
+ @delegate.cast(value)
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Katalyst
4
+ module Tables
5
+ module Collection
6
+ module Type
7
+ module Helpers
8
+ # Adds support default_value, multiple?, and filterable? to ActiveModel::Type::Value
9
+ module Extensions
10
+ refine(::ActiveModel::Type::Value) do
11
+ def default_value
12
+ nil
13
+ end
14
+
15
+ def multiple?
16
+ false
17
+ end
18
+
19
+ def filterable?
20
+ false
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Katalyst
4
+ module Tables
5
+ module Collection
6
+ module Type
7
+ module Helpers
8
+ # Adds support for multiple: true
9
+ module Multiple
10
+ def initialize(multiple: false, **)
11
+ super(**)
12
+
13
+ @multiple = multiple
14
+ end
15
+
16
+ def multiple?
17
+ @multiple
18
+ end
19
+
20
+ using Extensions
21
+
22
+ def default_value
23
+ multiple? ? [] : super
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,57 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Katalyst
4
+ module Tables
5
+ module Collection
6
+ module Type
7
+ class Integer < Value
8
+ include Helpers::Delegate
9
+ include Helpers::Multiple
10
+
11
+ def initialize(**)
12
+ super(**, delegate: ActiveModel::Type::Integer)
13
+ end
14
+
15
+ def serialize(value)
16
+ if value.is_a?(Range)
17
+ if value.begin.nil?
18
+ "<#{super(value.end)}"
19
+ elsif value.end.nil?
20
+ ">#{super(value.begin)}"
21
+ else
22
+ "#{super(value.begin)}..#{super(value.end)}"
23
+ end
24
+ else
25
+ super
26
+ end
27
+ end
28
+
29
+ private
30
+
31
+ INTEGER = /(-?\d+)/
32
+ SINGLE_VALUE = /\A#{INTEGER}\z/
33
+ LOWER_BOUND = /\A>#{INTEGER}\z/
34
+ UPPER_BOUND = /\A<#{INTEGER}\z/
35
+ BOUNDED = /\A#{INTEGER}\.\.#{INTEGER}\z/
36
+
37
+ def cast_value(value)
38
+ case value
39
+ when ::Range, ::Integer
40
+ value
41
+ when SINGLE_VALUE
42
+ super($1)
43
+ when LOWER_BOUND
44
+ ((super($1))..)
45
+ when UPPER_BOUND
46
+ (..(super($1)))
47
+ when BOUNDED
48
+ ((super($1))..(super($2)))
49
+ else
50
+ super
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Katalyst
4
+ module Tables
5
+ module Collection
6
+ module Type
7
+ class Query < Value
8
+ def type
9
+ :query
10
+ end
11
+
12
+ def filterable?
13
+ false
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Katalyst
4
+ module Tables
5
+ module Collection
6
+ module Type
7
+ class Search < Value
8
+ # @overwrite Value.initialize() to require scope
9
+ # rubocop:disable Lint/UselessMethodDefinition
10
+ def initialize(scope:, **)
11
+ super
12
+ end
13
+ # rubocop:enable Lint/UselessMethodDefinition
14
+
15
+ def type
16
+ :search
17
+ end
18
+
19
+ def filter_condition(model, _, value)
20
+ model.public_send(scope, value)
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Katalyst
4
+ module Tables
5
+ module Collection
6
+ module Type
7
+ class String < Value
8
+ include ActiveRecord::Sanitization::ClassMethods
9
+
10
+ attr_reader :exact
11
+ alias_method :exact?, :exact
12
+
13
+ delegate :type, :serialize, :deserialize, :cast, to: :@delegate
14
+
15
+ def initialize(exact: false, **)
16
+ super(**)
17
+
18
+ @exact = exact
19
+ @delegate = ActiveModel::Type::String.new
20
+ end
21
+
22
+ private
23
+
24
+ def filter_condition(model, column, value)
25
+ if exact? || scope
26
+ super
27
+ else
28
+ model.where(model.arel_table[column].matches("%#{sanitize_sql_like(value)}%"))
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,66 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Katalyst
4
+ module Tables
5
+ module Collection
6
+ module Type
7
+ class Value < ActiveModel::Type::Value
8
+ using Helpers::Extensions
9
+
10
+ attr_reader :scope
11
+
12
+ def initialize(scope: nil, filter: true)
13
+ super()
14
+
15
+ @scope = scope
16
+ @filterable = filter
17
+ end
18
+
19
+ def filterable?
20
+ @filterable
21
+ end
22
+
23
+ def filter?(attribute, value)
24
+ filterable? && (value.present? || attribute.came_from_user?)
25
+ end
26
+
27
+ def filter(scope, attribute)
28
+ value = filter_value(attribute)
29
+
30
+ return scope unless filter?(attribute, value)
31
+
32
+ scope, model, column = model_and_column_for(scope, attribute)
33
+ condition = filter_condition(model, column, value)
34
+
35
+ scope.merge(condition)
36
+ end
37
+
38
+ private
39
+
40
+ def filter_value(attribute)
41
+ attribute.value
42
+ end
43
+
44
+ def filter_condition(model, column, value)
45
+ if value.nil?
46
+ model.none
47
+ elsif scope
48
+ model.public_send(scope, value)
49
+ else
50
+ model.where(column => value)
51
+ end
52
+ end
53
+
54
+ def model_and_column_for(scope, attribute)
55
+ if attribute.name.include?(".")
56
+ table, column = attribute.name.split(".")
57
+ [scope.joins(table.to_sym), scope.model.reflections[table].klass, column]
58
+ else
59
+ [scope, scope.model, attribute.name]
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_model/type"
4
+
5
+ module Katalyst
6
+ module Tables
7
+ module Collection
8
+ # Based on ActiveModel::Type – provides a registry for Collection filtering
9
+ module Type
10
+ @registry = ActiveModel::Type::Registry.new
11
+
12
+ class << self
13
+ attr_accessor :registry # :nodoc:
14
+
15
+ def register(type_name, klass = nil, &)
16
+ registry.register(type_name, klass, &)
17
+ end
18
+
19
+ def lookup(...)
20
+ registry.lookup(...)
21
+ end
22
+
23
+ def default_value
24
+ @default_value ||= Value.new
25
+ end
26
+ end
27
+
28
+ register(:boolean, Type::Boolean)
29
+ register(:date, Type::Date)
30
+ register(:enum, Type::Enum)
31
+ register(:float, Type::Float)
32
+ register(:integer, Type::Integer)
33
+ register(:string, Type::String)
34
+ register(:query, Type::Query)
35
+ register(:search, Type::Search)
36
+ end
37
+ end
38
+ end
39
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: katalyst-tables
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.1.0
4
+ version: 3.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Katalyst Interactive
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-06-14 00:00:00.000000000 Z
11
+ date: 2024-06-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: katalyst-html-attributes
@@ -54,14 +54,17 @@ files:
54
54
  - app/assets/builds/katalyst/tables.min.js
55
55
  - app/assets/builds/katalyst/tables.min.js.map
56
56
  - app/assets/config/katalyst-tables.js
57
+ - app/assets/stylesheets/katalyst/tables/_filter.scss
57
58
  - app/assets/stylesheets/katalyst/tables/_index.scss
58
59
  - app/assets/stylesheets/katalyst/tables/_ordinal.scss
60
+ - app/assets/stylesheets/katalyst/tables/_select.scss
59
61
  - app/assets/stylesheets/katalyst/tables/_summary.scss
60
62
  - app/assets/stylesheets/katalyst/tables/_table.scss
61
63
  - app/assets/stylesheets/katalyst/tables/typed-columns/_boolean.scss
62
64
  - app/assets/stylesheets/katalyst/tables/typed-columns/_currency.scss
63
65
  - app/assets/stylesheets/katalyst/tables/typed-columns/_date.scss
64
66
  - app/assets/stylesheets/katalyst/tables/typed-columns/_datetime.scss
67
+ - app/assets/stylesheets/katalyst/tables/typed-columns/_enum.scss
65
68
  - app/assets/stylesheets/katalyst/tables/typed-columns/_index.scss
66
69
  - app/assets/stylesheets/katalyst/tables/typed-columns/_number.scss
67
70
  - app/components/concerns/katalyst/tables/has_table_content.rb
@@ -81,6 +84,7 @@ files:
81
84
  - app/components/katalyst/tables/cells/currency_component.rb
82
85
  - app/components/katalyst/tables/cells/date_component.rb
83
86
  - app/components/katalyst/tables/cells/date_time_component.rb
87
+ - app/components/katalyst/tables/cells/enum_component.rb
84
88
  - app/components/katalyst/tables/cells/number_component.rb
85
89
  - app/components/katalyst/tables/cells/ordinal_component.rb
86
90
  - app/components/katalyst/tables/cells/rich_text_component.rb
@@ -88,6 +92,10 @@ files:
88
92
  - app/components/katalyst/tables/data.rb
89
93
  - app/components/katalyst/tables/empty_caption_component.html.erb
90
94
  - app/components/katalyst/tables/empty_caption_component.rb
95
+ - app/components/katalyst/tables/filter/modal_component.html.erb
96
+ - app/components/katalyst/tables/filter/modal_component.rb
97
+ - app/components/katalyst/tables/filter_component.html.erb
98
+ - app/components/katalyst/tables/filter_component.rb
91
99
  - app/components/katalyst/tables/header_row_component.html.erb
92
100
  - app/components/katalyst/tables/header_row_component.rb
93
101
  - app/components/katalyst/tables/label.rb
@@ -104,6 +112,7 @@ files:
104
112
  - app/controllers/concerns/katalyst/tables/backend.rb
105
113
  - app/helpers/katalyst/tables/frontend.rb
106
114
  - app/javascript/tables/application.js
115
+ - app/javascript/tables/filter/modal_controller.js
107
116
  - app/javascript/tables/orderable/form_controller.js
108
117
  - app/javascript/tables/orderable/item_controller.js
109
118
  - app/javascript/tables/orderable/list_controller.js
@@ -113,11 +122,29 @@ files:
113
122
  - app/models/concerns/katalyst/tables/collection/filtering.rb
114
123
  - app/models/concerns/katalyst/tables/collection/has_params.rb
115
124
  - app/models/concerns/katalyst/tables/collection/pagination.rb
125
+ - app/models/concerns/katalyst/tables/collection/query.rb
126
+ - app/models/concerns/katalyst/tables/collection/query/array_value_parser.rb
127
+ - app/models/concerns/katalyst/tables/collection/query/parser.rb
128
+ - app/models/concerns/katalyst/tables/collection/query/single_value_parser.rb
129
+ - app/models/concerns/katalyst/tables/collection/query/value_parser.rb
116
130
  - app/models/concerns/katalyst/tables/collection/reducers.rb
117
131
  - app/models/concerns/katalyst/tables/collection/sorting.rb
118
132
  - app/models/katalyst/tables/collection/array.rb
119
133
  - app/models/katalyst/tables/collection/base.rb
120
134
  - app/models/katalyst/tables/collection/filter.rb
135
+ - app/models/katalyst/tables/collection/type.rb
136
+ - app/models/katalyst/tables/collection/type/boolean.rb
137
+ - app/models/katalyst/tables/collection/type/date.rb
138
+ - app/models/katalyst/tables/collection/type/enum.rb
139
+ - app/models/katalyst/tables/collection/type/float.rb
140
+ - app/models/katalyst/tables/collection/type/helpers/delegate.rb
141
+ - app/models/katalyst/tables/collection/type/helpers/extensions.rb
142
+ - app/models/katalyst/tables/collection/type/helpers/multiple.rb
143
+ - app/models/katalyst/tables/collection/type/integer.rb
144
+ - app/models/katalyst/tables/collection/type/query.rb
145
+ - app/models/katalyst/tables/collection/type/search.rb
146
+ - app/models/katalyst/tables/collection/type/string.rb
147
+ - app/models/katalyst/tables/collection/type/value.rb
121
148
  - config/importmap.rb
122
149
  - config/locales/tables.en.yml
123
150
  - lib/katalyst/tables.rb
@@ -147,7 +174,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
147
174
  - !ruby/object:Gem::Version
148
175
  version: '0'
149
176
  requirements: []
150
- rubygems_version: 3.5.9
177
+ rubygems_version: 3.5.11
151
178
  signing_key:
152
179
  specification_version: 4
153
180
  summary: HTML table generator for Rails views