katalyst-tables 3.1.0 → 3.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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