katalyst-tables 3.4.6 → 3.5.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.
- checksums.yaml +4 -4
- data/app/assets/builds/katalyst/tables.esm.js +15 -3
- data/app/assets/builds/katalyst/tables.js +15 -3
- data/app/assets/builds/katalyst/tables.min.js +1 -1
- data/app/assets/builds/katalyst/tables.min.js.map +1 -1
- data/app/assets/stylesheets/katalyst/tables/_query.scss +20 -20
- data/app/components/katalyst/tables/query/input_component.html.erb +7 -6
- data/app/components/katalyst/tables/query/input_component.rb +23 -7
- data/app/components/katalyst/tables/query/modal_component.html.erb +7 -17
- data/app/components/katalyst/tables/query/modal_component.rb +7 -62
- data/app/components/katalyst/tables/query/suggestion_component.html.erb +3 -0
- data/app/components/katalyst/tables/query/suggestion_component.rb +35 -0
- data/app/components/katalyst/tables/query_component.rb +0 -1
- data/app/javascript/tables/query_controller.js +10 -3
- data/app/javascript/tables/query_input_controller.js +5 -0
- data/app/models/concerns/katalyst/tables/collection/query/array_value_parser.rb +19 -1
- data/app/models/concerns/katalyst/tables/collection/query/parser.rb +12 -11
- data/app/models/concerns/katalyst/tables/collection/query/single_value_parser.rb +10 -0
- data/app/models/concerns/katalyst/tables/collection/query/untagged_literal.rb +36 -0
- data/app/models/concerns/katalyst/tables/collection/query/value_parser.rb +11 -2
- data/app/models/concerns/katalyst/tables/collection/query.rb +11 -26
- data/app/models/concerns/katalyst/tables/collection/suggestions.rb +120 -0
- data/app/models/katalyst/tables/suggestions/attribute.rb +13 -0
- data/app/models/katalyst/tables/suggestions/base.rb +31 -0
- data/app/models/katalyst/tables/suggestions/constant_value.rb +28 -0
- data/app/models/katalyst/tables/suggestions/custom_value.rb +26 -0
- data/app/models/katalyst/tables/suggestions/database_value.rb +36 -0
- data/app/models/katalyst/tables/suggestions/search_value.rb +13 -0
- data/config/locales/tables.en.yml +9 -1
- data/lib/katalyst/tables/collection/type/boolean.rb +10 -2
- data/lib/katalyst/tables/collection/type/date.rb +7 -5
- data/lib/katalyst/tables/collection/type/enum.rb +4 -4
- data/lib/katalyst/tables/collection/type/helpers/extensions.rb +1 -11
- data/lib/katalyst/tables/collection/type/value.rb +14 -12
- metadata +12 -3
- data/lib/katalyst/tables/collection/type/example.rb +0 -30
@@ -8,6 +8,7 @@ module Katalyst
|
|
8
8
|
include Katalyst::Tables::Frontend
|
9
9
|
|
10
10
|
renders_one :footer
|
11
|
+
renders_many :suggestions, SuggestionComponent
|
11
12
|
|
12
13
|
attr_reader :collection, :url
|
13
14
|
|
@@ -17,6 +18,12 @@ module Katalyst
|
|
17
18
|
@collection = collection
|
18
19
|
end
|
19
20
|
|
21
|
+
def before_render
|
22
|
+
collection.suggestions.each do |suggestion|
|
23
|
+
with_suggestion(suggestion:)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
20
27
|
private
|
21
28
|
|
22
29
|
def default_html_attributes
|
@@ -28,68 +35,6 @@ module Katalyst
|
|
28
35
|
},
|
29
36
|
}
|
30
37
|
end
|
31
|
-
|
32
|
-
using Collection::Type::Helpers::Extensions
|
33
|
-
|
34
|
-
def show_examples?
|
35
|
-
current_key && attributes[current_key]
|
36
|
-
end
|
37
|
-
|
38
|
-
def current_key
|
39
|
-
unless instance_variable_defined?(:@current_key)
|
40
|
-
attributes.each_key do |key|
|
41
|
-
@current_key = key if collection.query_active?(key)
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
@current_key ||= nil
|
46
|
-
end
|
47
|
-
|
48
|
-
def attributes
|
49
|
-
collection.class.attribute_types
|
50
|
-
.select { |_, a| a.filterable? && a.type != :search }
|
51
|
-
.to_h
|
52
|
-
end
|
53
|
-
|
54
|
-
def available_filters
|
55
|
-
keys = attributes.keys
|
56
|
-
|
57
|
-
if current_token.present?
|
58
|
-
keys = keys.select { |k| k.include?(current_token) }
|
59
|
-
end
|
60
|
-
|
61
|
-
keys.map do |key|
|
62
|
-
[key, collection.model.human_attribute_name(key)]
|
63
|
-
end
|
64
|
-
end
|
65
|
-
|
66
|
-
def examples_for(key)
|
67
|
-
collection.examples_for(key).filter_map do |example|
|
68
|
-
case example
|
69
|
-
when Collection::Type::Example
|
70
|
-
example if example.value.to_s.present?
|
71
|
-
else
|
72
|
-
raise ArgumentError, "Invalid example #{example.inspect} for #{collection.model_name}.#{key}"
|
73
|
-
end
|
74
|
-
end
|
75
|
-
end
|
76
|
-
|
77
|
-
def format_value(value)
|
78
|
-
if /\A[\w.-]*\z/.match?(value.to_s)
|
79
|
-
value.to_s
|
80
|
-
else
|
81
|
-
%("#{value}")
|
82
|
-
end
|
83
|
-
end
|
84
|
-
|
85
|
-
def current_token
|
86
|
-
return nil unless collection.position&.in?(0..collection.query.length)
|
87
|
-
|
88
|
-
prefix = collection.query[...collection.position].match(/\w*\z/)
|
89
|
-
suffix = collection.query[collection.position..].match(/\A\w*/)
|
90
|
-
|
91
|
-
"#{prefix}#{suffix}"
|
92
|
-
end
|
93
38
|
end
|
94
39
|
end
|
95
40
|
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Katalyst
|
4
|
+
module Tables
|
5
|
+
module Query
|
6
|
+
class SuggestionComponent < ViewComponent::Base
|
7
|
+
include Katalyst::HtmlAttributes
|
8
|
+
|
9
|
+
delegate :type, :value, to: :@suggestion
|
10
|
+
|
11
|
+
def initialize(suggestion:, **)
|
12
|
+
super(**)
|
13
|
+
|
14
|
+
@suggestion = suggestion
|
15
|
+
end
|
16
|
+
|
17
|
+
def default_html_attributes
|
18
|
+
{
|
19
|
+
class: ["suggestion", type.to_s],
|
20
|
+
}
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def format_value(value)
|
26
|
+
if /\A[\w.-]*\z/.match?(value.to_s)
|
27
|
+
value.to_s
|
28
|
+
else
|
29
|
+
%("#{value}")
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -37,11 +37,18 @@ export default class QueryController extends Controller {
|
|
37
37
|
document.addEventListener("selectionchange", this.selection);
|
38
38
|
}
|
39
39
|
|
40
|
+
/**
|
41
|
+
* If the user presses escape once, clear the input.
|
42
|
+
* If the user presses escape again, get them out of here.
|
43
|
+
*/
|
40
44
|
clear() {
|
41
45
|
if (this.query.value === "") {
|
42
|
-
// if the user presses escape once, browser clears the input
|
43
|
-
// if the user presses escape again, get them out of here
|
44
46
|
this.closeModal();
|
47
|
+
} else {
|
48
|
+
this.query.value = "";
|
49
|
+
this.query.dispatchEvent(new Event("input"));
|
50
|
+
this.query.dispatchEvent(new Event("change"));
|
51
|
+
this.update();
|
45
52
|
}
|
46
53
|
}
|
47
54
|
|
@@ -95,7 +102,7 @@ export default class QueryController extends Controller {
|
|
95
102
|
}
|
96
103
|
|
97
104
|
get query() {
|
98
|
-
return this.element.querySelector("
|
105
|
+
return this.element.querySelector("[role=searchbox]");
|
99
106
|
}
|
100
107
|
|
101
108
|
get position() {
|
@@ -18,6 +18,7 @@ module Katalyst
|
|
18
18
|
query.scan(/#{'\['}\s*/)
|
19
19
|
|
20
20
|
until query.eos?
|
21
|
+
@value_start = query.charpos
|
21
22
|
break unless take_quoted_value || take_unquoted_value
|
22
23
|
break unless take_delimiter
|
23
24
|
end
|
@@ -33,8 +34,25 @@ module Katalyst
|
|
33
34
|
query.scan(/\s*#{','}\s*/)
|
34
35
|
end
|
35
36
|
|
37
|
+
def value
|
38
|
+
@value.map(&:value)
|
39
|
+
end
|
40
|
+
|
36
41
|
def value=(value)
|
37
|
-
@value << value
|
42
|
+
@value << Value.new(value, @value_start, @query.charpos)
|
43
|
+
end
|
44
|
+
|
45
|
+
def value_at(position)
|
46
|
+
@value.detect { |v| v.range.cover?(position) }&.value
|
47
|
+
end
|
48
|
+
|
49
|
+
class Value
|
50
|
+
attr_accessor :range, :value
|
51
|
+
|
52
|
+
def initialize(value, start, fin)
|
53
|
+
@value = value
|
54
|
+
@range = (start..fin)
|
55
|
+
end
|
38
56
|
end
|
39
57
|
end
|
40
58
|
end
|
@@ -29,6 +29,11 @@ module Katalyst
|
|
29
29
|
self
|
30
30
|
end
|
31
31
|
|
32
|
+
def token_at_position(position:)
|
33
|
+
tagged.values.detect { |v| v.range.cover?(position) } ||
|
34
|
+
untagged.detect { |v| v.range.cover?(position) }
|
35
|
+
end
|
36
|
+
|
32
37
|
private
|
33
38
|
|
34
39
|
def skip_whitespace
|
@@ -43,31 +48,27 @@ module Katalyst
|
|
43
48
|
key, = query.values_at(1)
|
44
49
|
skip_whitespace
|
45
50
|
|
46
|
-
tagged[key] = value_parser(start).parse(query)
|
51
|
+
tagged[key] = value_parser(key, start).parse(query)
|
47
52
|
end
|
48
53
|
|
49
54
|
def take_untagged
|
55
|
+
start = query.charpos
|
56
|
+
|
50
57
|
return unless query.scan(/\S+/)
|
51
58
|
|
52
|
-
untagged << query.matched
|
59
|
+
untagged << UntaggedLiteral.new(value: query.matched, start:)
|
53
60
|
|
54
61
|
untagged
|
55
62
|
end
|
56
63
|
|
57
64
|
using Type::Helpers::Extensions
|
58
65
|
|
59
|
-
def value_parser(start)
|
66
|
+
def value_parser(key, start)
|
60
67
|
if query.check(/#{'\['}\s*/)
|
61
|
-
ArrayValueParser.new(start:)
|
68
|
+
ArrayValueParser.new(key:, start:)
|
62
69
|
else
|
63
|
-
SingleValueParser.new(start:)
|
70
|
+
SingleValueParser.new(key:, start:)
|
64
71
|
end
|
65
|
-
|
66
|
-
# if attribute.type.multiple? || attribute.value.is_a?(::Array)
|
67
|
-
# ArrayValueParser.new(attribute:, pos:)
|
68
|
-
# else
|
69
|
-
# SingleValueParser.new(attribute:, pos:)
|
70
|
-
# end
|
71
72
|
end
|
72
73
|
end
|
73
74
|
end
|
@@ -15,6 +15,8 @@ module Katalyst
|
|
15
15
|
def parse(query)
|
16
16
|
@query = query
|
17
17
|
|
18
|
+
@value_start = query.charpos
|
19
|
+
|
18
20
|
take_quoted_value || take_unquoted_value
|
19
21
|
|
20
22
|
@end = query.charpos
|
@@ -22,9 +24,17 @@ module Katalyst
|
|
22
24
|
self
|
23
25
|
end
|
24
26
|
|
27
|
+
def value
|
28
|
+
@value
|
29
|
+
end
|
30
|
+
|
25
31
|
def value=(value)
|
26
32
|
@value = value
|
27
33
|
end
|
34
|
+
|
35
|
+
def value_at(position)
|
36
|
+
@value if (@value_start..@end).cover?(position)
|
37
|
+
end
|
28
38
|
end
|
29
39
|
end
|
30
40
|
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Katalyst
|
4
|
+
module Tables
|
5
|
+
module Collection
|
6
|
+
module Query
|
7
|
+
class UntaggedLiteral
|
8
|
+
attr_accessor :query, :value
|
9
|
+
|
10
|
+
def initialize(value:, start:)
|
11
|
+
@value = value
|
12
|
+
@start = start
|
13
|
+
@end = start + value.length
|
14
|
+
end
|
15
|
+
|
16
|
+
def literal?
|
17
|
+
true
|
18
|
+
end
|
19
|
+
|
20
|
+
def tagged?
|
21
|
+
false
|
22
|
+
end
|
23
|
+
|
24
|
+
def range
|
25
|
+
@start..@end
|
26
|
+
end
|
27
|
+
|
28
|
+
def to_str
|
29
|
+
@value
|
30
|
+
end
|
31
|
+
alias to_s to_str
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -5,12 +5,21 @@ module Katalyst
|
|
5
5
|
module Collection
|
6
6
|
module Query
|
7
7
|
class ValueParser
|
8
|
-
attr_accessor :query, :
|
8
|
+
attr_accessor :query, :key
|
9
9
|
|
10
|
-
def initialize(start:)
|
10
|
+
def initialize(key:, start:)
|
11
|
+
@key = key
|
11
12
|
@start = start
|
12
13
|
end
|
13
14
|
|
15
|
+
def literal?
|
16
|
+
false
|
17
|
+
end
|
18
|
+
|
19
|
+
def tagged?
|
20
|
+
true
|
21
|
+
end
|
22
|
+
|
14
23
|
def range
|
15
24
|
@start..@end
|
16
25
|
end
|
@@ -7,6 +7,7 @@ module Katalyst
|
|
7
7
|
extend ActiveSupport::Concern
|
8
8
|
|
9
9
|
include Filtering
|
10
|
+
include Suggestions
|
10
11
|
|
11
12
|
class_methods do
|
12
13
|
def search_attribute
|
@@ -21,26 +22,13 @@ module Katalyst
|
|
21
22
|
included do
|
22
23
|
attribute :q, :query, default: ""
|
23
24
|
alias_attribute :query, :q
|
24
|
-
|
25
|
-
attribute :p, :integer, filter: false
|
26
|
-
alias_attribute :position, :p
|
27
25
|
end
|
28
26
|
|
29
|
-
|
30
|
-
|
31
|
-
def examples_for(key)
|
32
|
-
key = key.to_s
|
33
|
-
examples_method = "#{key.parameterize.underscore}_examples"
|
34
|
-
if respond_to?(examples_method)
|
35
|
-
public_send(examples_method)&.map { |e| e.is_a?(Example) ? e : Example.new(example) }
|
36
|
-
elsif @attributes.key?(key)
|
37
|
-
@attributes[key].type.examples_for(unscoped_items, @attributes[key])
|
38
|
-
end
|
27
|
+
def searchable?
|
28
|
+
self.class.search_attribute.present?
|
39
29
|
end
|
40
30
|
|
41
|
-
|
42
|
-
@attributes[attribute].query_range&.cover?(position)
|
43
|
-
end
|
31
|
+
using Type::Helpers::Extensions
|
44
32
|
|
45
33
|
private
|
46
34
|
|
@@ -48,19 +36,16 @@ module Katalyst
|
|
48
36
|
result = super
|
49
37
|
|
50
38
|
if query_changed?
|
51
|
-
|
39
|
+
@query_parser = Parser.new(self).parse(query)
|
40
|
+
|
41
|
+
@query_parser.tagged.each do |k, p|
|
42
|
+
next unless @attributes.key?(k)
|
52
43
|
|
53
|
-
|
54
|
-
if @attributes.key?(k)
|
55
|
-
_assign_attribute(k, p.value)
|
56
|
-
@attributes[k].query_range = p.range
|
57
|
-
else
|
58
|
-
errors.add(k, :unknown)
|
59
|
-
end
|
44
|
+
_assign_attribute(k, p.value)
|
60
45
|
end
|
61
46
|
|
62
|
-
if
|
63
|
-
_assign_attribute(search,
|
47
|
+
if @query_parser.untagged.any? && (search = self.class.search_attribute)
|
48
|
+
_assign_attribute(search, @query_parser.untagged.map(&:value).join(" "))
|
64
49
|
end
|
65
50
|
end
|
66
51
|
|
@@ -0,0 +1,120 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Katalyst
|
4
|
+
module Tables
|
5
|
+
module Collection
|
6
|
+
module Suggestions # :nodoc:
|
7
|
+
extend ActiveSupport::Concern
|
8
|
+
|
9
|
+
included do
|
10
|
+
attribute :p, :integer, filter: false
|
11
|
+
alias_attribute :position, :p
|
12
|
+
end
|
13
|
+
|
14
|
+
using Type::Helpers::Extensions
|
15
|
+
|
16
|
+
def suggestions(position: self.position)
|
17
|
+
query_token = token_at_position(position:)
|
18
|
+
|
19
|
+
attribute = attribute_for_token(query_token:)
|
20
|
+
method = suggestions_method(attribute) if attribute.present?
|
21
|
+
|
22
|
+
# build a suggestions list
|
23
|
+
suggestions = if method && respond_to?(method)
|
24
|
+
user_suggestions(attribute:, method:)
|
25
|
+
elsif attribute
|
26
|
+
value_suggestions(attribute:)
|
27
|
+
else
|
28
|
+
attribute_suggestions(query_token:)
|
29
|
+
end
|
30
|
+
|
31
|
+
add_context_suggestions(suggestions:, query_token:, attribute:) if query_token
|
32
|
+
|
33
|
+
suggestions
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
def attribute_for_token(query_token:)
|
39
|
+
return unless query_token&.tagged?
|
40
|
+
|
41
|
+
attribute = suggestable_attributes[query_token.key]
|
42
|
+
|
43
|
+
return unless attribute
|
44
|
+
|
45
|
+
# construct an attribute from the input token, so we can focus on what the user is currently typing instead
|
46
|
+
# of searching for the whole input for this attribute (e.g. if we're constructing an array filter)
|
47
|
+
ActiveModel::Attribute.from_user(attribute.name, query_token.value_at(position),
|
48
|
+
attribute.type, attribute)
|
49
|
+
end
|
50
|
+
|
51
|
+
# Augments suggestions to ensure the user always has some feedback on their input.
|
52
|
+
def add_context_suggestions(suggestions:, query_token:, attribute:)
|
53
|
+
if query_token.tagged?
|
54
|
+
if !attribute
|
55
|
+
# user has entered a `:` but we don't know the attribute
|
56
|
+
errors.add(:query, :unknown_key, input: query_token.key)
|
57
|
+
elsif suggestions.none?
|
58
|
+
# the user might know more than us about what values are valid
|
59
|
+
suggestions << Tables::Suggestions::SearchValue.new(query_token.value_at(position))
|
60
|
+
end
|
61
|
+
elsif searchable?
|
62
|
+
# user is typing an untagged search term, indicate they can continue
|
63
|
+
suggestions << Tables::Suggestions::SearchValue.new(query_token.value)
|
64
|
+
else
|
65
|
+
errors.add(:query, :no_untagged_search, input: query_token.value)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def attribute_suggestions(query_token:)
|
70
|
+
attributes = suggestable_attributes.values
|
71
|
+
|
72
|
+
if query_token&.literal?
|
73
|
+
attributes = attributes.select { |a| a.name.include?(query_token.value) }
|
74
|
+
end
|
75
|
+
|
76
|
+
attributes.map { |a| Tables::Suggestions::Attribute.new(a.name) }
|
77
|
+
end
|
78
|
+
|
79
|
+
def user_suggestions(attribute:, method:)
|
80
|
+
suggestions = public_send(method, attribute)
|
81
|
+
|
82
|
+
raise TypeError, "Suggestions must be an array" unless suggestions.is_a?(Enumerable)
|
83
|
+
|
84
|
+
suggestions.map do |suggestion|
|
85
|
+
case suggestion
|
86
|
+
when Tables::Suggestions::Base
|
87
|
+
suggestion
|
88
|
+
else
|
89
|
+
Tables::Suggestions::CustomValue.new(suggestion, name: attribute.name, type: attribute.type)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
def value_suggestions(attribute:)
|
95
|
+
attribute.type.suggestions(unscoped_items, attribute)
|
96
|
+
end
|
97
|
+
|
98
|
+
def suggestions_method(attribute)
|
99
|
+
:"#{attribute.name.parameterize.underscore}_suggestions" if attribute.present?
|
100
|
+
end
|
101
|
+
|
102
|
+
def suggestable_attributes
|
103
|
+
@attributes.keys.filter_map do |name|
|
104
|
+
attribute = @attributes[name]
|
105
|
+
|
106
|
+
# skip if the attribute can't generate useful suggestions
|
107
|
+
next unless attribute.type.filterable?
|
108
|
+
next if attribute.type.type == :search
|
109
|
+
|
110
|
+
[name, attribute]
|
111
|
+
end.to_h
|
112
|
+
end
|
113
|
+
|
114
|
+
def token_at_position(position: self.position)
|
115
|
+
@query_parser&.token_at_position(position:)
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Katalyst
|
4
|
+
module Tables
|
5
|
+
module Suggestions
|
6
|
+
class Base
|
7
|
+
attr_reader :value
|
8
|
+
|
9
|
+
def initialize(value)
|
10
|
+
@value = value
|
11
|
+
end
|
12
|
+
|
13
|
+
def type
|
14
|
+
raise NotImplementedError
|
15
|
+
end
|
16
|
+
|
17
|
+
def hash
|
18
|
+
[self.class, value].hash
|
19
|
+
end
|
20
|
+
|
21
|
+
def eql?(other)
|
22
|
+
other.class.eql?(self.class) && other.value.eql?(value)
|
23
|
+
end
|
24
|
+
|
25
|
+
def inspect
|
26
|
+
"#<#{self.class.name} value: #{value.inspect}>"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Katalyst
|
4
|
+
module Tables
|
5
|
+
module Suggestions
|
6
|
+
class ConstantValue < Base
|
7
|
+
delegate :to_param, to: :@attribute_type
|
8
|
+
|
9
|
+
def initialize(name:, type:, model:, column:, value:)
|
10
|
+
super(value)
|
11
|
+
|
12
|
+
@attribute_type = type
|
13
|
+
@model = model
|
14
|
+
@column = column
|
15
|
+
@name = name
|
16
|
+
end
|
17
|
+
|
18
|
+
def type
|
19
|
+
:constant_value
|
20
|
+
end
|
21
|
+
|
22
|
+
def value
|
23
|
+
to_param(@value)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Katalyst
|
4
|
+
module Tables
|
5
|
+
module Suggestions
|
6
|
+
class CustomValue < Base
|
7
|
+
delegate :to_param, to: :@attribute_type
|
8
|
+
|
9
|
+
def initialize(value, name:, type:)
|
10
|
+
super(value)
|
11
|
+
|
12
|
+
@name = name
|
13
|
+
@attribute_type = type
|
14
|
+
end
|
15
|
+
|
16
|
+
def type
|
17
|
+
:custom_value
|
18
|
+
end
|
19
|
+
|
20
|
+
def value
|
21
|
+
to_param(@value)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Katalyst
|
4
|
+
module Tables
|
5
|
+
module Suggestions
|
6
|
+
class DatabaseValue < Base
|
7
|
+
attr_reader :model, :column
|
8
|
+
|
9
|
+
delegate :to_param, to: :@attribute_type
|
10
|
+
|
11
|
+
def initialize(name:, type:, model:, column:, value:)
|
12
|
+
super(value)
|
13
|
+
|
14
|
+
@attribute_type = type
|
15
|
+
@model = model
|
16
|
+
@column = column
|
17
|
+
@name = name
|
18
|
+
end
|
19
|
+
|
20
|
+
def type
|
21
|
+
:database_value
|
22
|
+
end
|
23
|
+
|
24
|
+
using Tables::Collection::Type::Helpers::Extensions
|
25
|
+
|
26
|
+
def value
|
27
|
+
if @attribute_type.multiple? && @value.is_a?(Array) && @value.length == 1
|
28
|
+
to_param(@value.first)
|
29
|
+
else
|
30
|
+
to_param(@value)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|