katalyst-tables 2.6.0 → 3.0.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/CHANGELOG.md +16 -1
- data/README.md +57 -213
- data/app/assets/builds/katalyst/tables.esm.js +17 -47
- data/app/assets/builds/katalyst/tables.js +17 -47
- 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/_index.scss +1 -0
- data/app/assets/stylesheets/katalyst/tables/_ordinal.scss +38 -0
- data/app/assets/stylesheets/katalyst/tables/_table.scss +123 -0
- data/app/assets/stylesheets/katalyst/tables/typed-columns/_boolean.scss +4 -0
- data/app/assets/stylesheets/katalyst/tables/typed-columns/_currency.scss +5 -0
- data/app/assets/stylesheets/katalyst/tables/typed-columns/_date.scss +4 -0
- data/app/assets/stylesheets/katalyst/tables/typed-columns/_datetime.scss +4 -0
- data/app/assets/stylesheets/katalyst/tables/typed-columns/_index.scss +5 -0
- data/app/assets/stylesheets/katalyst/tables/typed-columns/_number.scss +5 -0
- data/app/components/concerns/katalyst/tables/has_table_content.rb +17 -8
- data/app/components/concerns/katalyst/tables/identifiable.rb +51 -0
- data/app/components/concerns/katalyst/tables/orderable.rb +35 -105
- data/app/components/concerns/katalyst/tables/selectable.rb +18 -74
- data/app/components/concerns/katalyst/tables/sortable.rb +51 -17
- data/app/components/katalyst/table_component.html.erb +4 -4
- data/app/components/katalyst/table_component.rb +277 -47
- data/app/components/katalyst/tables/body_row_component.html.erb +5 -0
- data/app/components/katalyst/tables/body_row_component.rb +4 -24
- data/app/components/katalyst/tables/cell_component.rb +85 -0
- data/app/components/katalyst/tables/cells/boolean_component.rb +20 -0
- data/app/components/katalyst/tables/cells/currency_component.rb +29 -0
- data/app/components/katalyst/tables/cells/date_component.rb +67 -0
- data/app/components/katalyst/tables/cells/date_time_component.rb +60 -0
- data/app/components/katalyst/tables/cells/number_component.rb +22 -0
- data/app/components/katalyst/tables/cells/ordinal_component.rb +44 -0
- data/app/components/katalyst/tables/cells/rich_text_component.rb +21 -0
- data/app/components/katalyst/tables/cells/select_component.rb +39 -0
- data/app/components/katalyst/tables/data.rb +30 -0
- data/app/components/katalyst/tables/empty_caption_component.rb +1 -1
- data/app/components/katalyst/tables/header_row_component.html.erb +5 -0
- data/app/components/katalyst/tables/header_row_component.rb +4 -24
- data/app/components/katalyst/tables/label.rb +37 -0
- data/app/components/katalyst/tables/orderable/form_component.rb +38 -0
- data/app/components/katalyst/tables/selectable/form_component.html.erb +6 -4
- data/app/components/katalyst/tables/selectable/form_component.rb +8 -11
- data/app/controllers/concerns/katalyst/tables/backend.rb +2 -28
- data/app/helpers/katalyst/tables/frontend.rb +48 -2
- data/app/javascript/tables/application.js +0 -5
- data/app/javascript/tables/orderable/form_controller.js +8 -6
- data/app/javascript/tables/orderable/item_controller.js +9 -0
- data/app/models/concerns/katalyst/tables/collection/core.rb +6 -1
- data/app/models/concerns/katalyst/tables/collection/pagination.rb +8 -1
- data/app/models/concerns/katalyst/tables/collection/sorting.rb +85 -17
- data/app/models/katalyst/tables/collection/array.rb +38 -0
- data/app/models/katalyst/tables/collection/base.rb +4 -0
- data/lib/katalyst/tables/config.rb +23 -0
- data/lib/katalyst/tables.rb +9 -0
- metadata +32 -15
- data/app/components/concerns/katalyst/tables/configurable_component.rb +0 -52
- data/app/components/concerns/katalyst/tables/turbo_replaceable.rb +0 -79
- data/app/components/katalyst/tables/body_cell_component.rb +0 -47
- data/app/components/katalyst/tables/header_cell_component.rb +0 -65
- data/app/components/katalyst/turbo/pagy_nav_component.rb +0 -23
- data/app/components/katalyst/turbo/table_component.rb +0 -45
- data/app/helpers/katalyst/tables/frontend/helper.rb +0 -31
- data/app/javascript/tables/turbo/collection_controller.js +0 -38
- data/app/models/katalyst/tables/collection/sort_form.rb +0 -102
@@ -0,0 +1,85 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Katalyst
|
4
|
+
module Tables
|
5
|
+
class CellComponent < ViewComponent::Base # :nodoc:
|
6
|
+
include Katalyst::HtmlAttributes
|
7
|
+
|
8
|
+
attr_reader :collection, :row, :column, :record
|
9
|
+
|
10
|
+
def initialize(collection:, row:, column:, record:, label:, heading:, **)
|
11
|
+
super(**)
|
12
|
+
|
13
|
+
@collection = collection
|
14
|
+
@row = row
|
15
|
+
@column = column
|
16
|
+
@record = record
|
17
|
+
@heading = heading
|
18
|
+
|
19
|
+
if @row.header?
|
20
|
+
@label = Label.new(collection:, column:, label:)
|
21
|
+
else
|
22
|
+
@data = Data.new(record:, column:)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
# @return true if the cell is a heading cell (th).
|
27
|
+
def heading?
|
28
|
+
@row.header? || @heading
|
29
|
+
end
|
30
|
+
|
31
|
+
# Adds a component to wrap the content of the cell, similar to a layout in Rails views.
|
32
|
+
def with_content_wrapper(component)
|
33
|
+
@content_wrapper = component
|
34
|
+
|
35
|
+
self
|
36
|
+
end
|
37
|
+
|
38
|
+
def call
|
39
|
+
content = if content?
|
40
|
+
self.content
|
41
|
+
elsif @row.header?
|
42
|
+
label
|
43
|
+
else
|
44
|
+
rendered_value
|
45
|
+
end
|
46
|
+
|
47
|
+
content = @content_wrapper.with_content(content).render_in(view_context) if @content_wrapper
|
48
|
+
|
49
|
+
concat(content_tag(cell_tag, content, **html_attributes))
|
50
|
+
end
|
51
|
+
|
52
|
+
# Return the rendered and sanitized label for the column.
|
53
|
+
def label
|
54
|
+
@label&.to_s
|
55
|
+
end
|
56
|
+
|
57
|
+
# Return the raw value of the cell (i.e. the value of the data read from the record)
|
58
|
+
def value
|
59
|
+
@data&.value
|
60
|
+
end
|
61
|
+
|
62
|
+
# Return the serialized and sanitised data value for rendering in the cell.
|
63
|
+
def rendered_value
|
64
|
+
@data&.to_s
|
65
|
+
end
|
66
|
+
|
67
|
+
# Serialize data for use in blocks, i.e.
|
68
|
+
# row.text(:name) { |cell| tag.span(cell) }
|
69
|
+
def to_s
|
70
|
+
# Note, this can't be `content` because the block is evaluated in order to produce content.
|
71
|
+
rendered_value
|
72
|
+
end
|
73
|
+
|
74
|
+
def inspect
|
75
|
+
"#<#{self.class.name} method: #{@method.inspect}>"
|
76
|
+
end
|
77
|
+
|
78
|
+
private
|
79
|
+
|
80
|
+
def cell_tag
|
81
|
+
heading? ? :th : :td
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Katalyst
|
4
|
+
module Tables
|
5
|
+
module Cells
|
6
|
+
# Shows Yes/No for boolean values
|
7
|
+
class BooleanComponent < CellComponent
|
8
|
+
def rendered_value
|
9
|
+
value ? "Yes" : "No"
|
10
|
+
end
|
11
|
+
|
12
|
+
private
|
13
|
+
|
14
|
+
def default_html_attributes
|
15
|
+
{ class: "type-boolean" }
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Katalyst
|
4
|
+
module Tables
|
5
|
+
module Cells
|
6
|
+
# Formats the value as a money value
|
7
|
+
#
|
8
|
+
# The value is expected to be in cents.
|
9
|
+
# Adds a class to the cell to allow for custom styling
|
10
|
+
class CurrencyComponent < CellComponent
|
11
|
+
def initialize(options:, **)
|
12
|
+
super(**)
|
13
|
+
|
14
|
+
@options = options
|
15
|
+
end
|
16
|
+
|
17
|
+
def rendered_value
|
18
|
+
value.present? ? number_to_currency(value / 100.0, @options) : ""
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def default_html_attributes
|
24
|
+
{ class: "type-currency" }
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Katalyst
|
4
|
+
module Tables
|
5
|
+
module Cells
|
6
|
+
# Formats the value as a date
|
7
|
+
# @param format [String] date format
|
8
|
+
# @param relative [Boolean] if true, the date may be(if within 5 days) shown as a relative date
|
9
|
+
class DateComponent < CellComponent
|
10
|
+
def initialize(format:, relative:, **)
|
11
|
+
super(**)
|
12
|
+
|
13
|
+
@format = format
|
14
|
+
@relative = relative
|
15
|
+
end
|
16
|
+
|
17
|
+
def value
|
18
|
+
super&.to_date
|
19
|
+
end
|
20
|
+
|
21
|
+
def rendered_value
|
22
|
+
@relative ? relative_time : absolute_time
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def default_html_attributes
|
28
|
+
{
|
29
|
+
class: "type-date",
|
30
|
+
title: (absolute_time if row.body? && @relative && value.present? && days_ago_in_words(value).present?),
|
31
|
+
}
|
32
|
+
end
|
33
|
+
|
34
|
+
def absolute_time
|
35
|
+
value.present? ? I18n.l(value, format: @format) : ""
|
36
|
+
end
|
37
|
+
|
38
|
+
def relative_time
|
39
|
+
if value.blank?
|
40
|
+
""
|
41
|
+
else
|
42
|
+
days_ago_in_words(value)&.capitalize || absolute_time
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def days_ago_in_words(value)
|
47
|
+
from_time = value.to_time
|
48
|
+
to_time = Date.current.to_time
|
49
|
+
distance_in_days = ((to_time - from_time) / (24.0 * 60.0 * 60.0)).round
|
50
|
+
|
51
|
+
case distance_in_days
|
52
|
+
when 0
|
53
|
+
"today"
|
54
|
+
when 1
|
55
|
+
"yesterday"
|
56
|
+
when -1
|
57
|
+
"tomorrow"
|
58
|
+
when 2..5
|
59
|
+
"#{distance_in_days} days ago"
|
60
|
+
when -5..-2
|
61
|
+
"#{distance_in_days.abs} days from now"
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Katalyst
|
4
|
+
module Tables
|
5
|
+
module Cells
|
6
|
+
# Formats the value as a datetime
|
7
|
+
# @param format [String] datetime format
|
8
|
+
# @param relative [Boolean] if true, the datetime may be(if today) shown as a relative date/time
|
9
|
+
class DateTimeComponent < CellComponent
|
10
|
+
include ActionView::Helpers::DateHelper
|
11
|
+
|
12
|
+
def initialize(format:, relative:, **)
|
13
|
+
super(**)
|
14
|
+
|
15
|
+
@format = format
|
16
|
+
@relative = relative
|
17
|
+
end
|
18
|
+
|
19
|
+
def value
|
20
|
+
super&.to_datetime
|
21
|
+
end
|
22
|
+
|
23
|
+
def rendered_value
|
24
|
+
@relative ? relative_time : absolute_time
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def default_html_attributes
|
30
|
+
{
|
31
|
+
class: "type-datetime",
|
32
|
+
title: (absolute_time if row.body? && @relative && today?),
|
33
|
+
}
|
34
|
+
end
|
35
|
+
|
36
|
+
def absolute_time
|
37
|
+
value.present? ? I18n.l(value, format: @format) : ""
|
38
|
+
end
|
39
|
+
|
40
|
+
def today?
|
41
|
+
value&.to_date == Date.current
|
42
|
+
end
|
43
|
+
|
44
|
+
def relative_time
|
45
|
+
return "" if value.blank?
|
46
|
+
|
47
|
+
if today?
|
48
|
+
if value > DateTime.current
|
49
|
+
"#{distance_of_time_in_words(value, DateTime.current)} from now".capitalize
|
50
|
+
else
|
51
|
+
"#{distance_of_time_in_words(value, DateTime.current)} ago".capitalize
|
52
|
+
end
|
53
|
+
else
|
54
|
+
absolute_time
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Katalyst
|
4
|
+
module Tables
|
5
|
+
module Cells
|
6
|
+
# Formats the value as a number
|
7
|
+
#
|
8
|
+
# Adds a class to the cell to allow for custom styling
|
9
|
+
class NumberComponent < CellComponent
|
10
|
+
def rendered_value
|
11
|
+
value.present? ? number_to_human(value) : ""
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
def default_html_attributes
|
17
|
+
{ class: "type-number" }
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Katalyst
|
4
|
+
module Tables
|
5
|
+
module Cells
|
6
|
+
class OrdinalComponent < CellComponent
|
7
|
+
def initialize(primary_key:, **)
|
8
|
+
super(**)
|
9
|
+
|
10
|
+
@primary_key = primary_key
|
11
|
+
end
|
12
|
+
|
13
|
+
def rendered_value
|
14
|
+
t("katalyst.tables.orderable.value")
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def default_html_attributes
|
20
|
+
if @row.header?
|
21
|
+
{ class: "ordinal" }
|
22
|
+
else
|
23
|
+
{
|
24
|
+
class: "ordinal",
|
25
|
+
data: {
|
26
|
+
controller: Orderable::ITEM_CONTROLLER,
|
27
|
+
"#{Orderable::ITEM_CONTROLLER}-params-value": params.to_json,
|
28
|
+
},
|
29
|
+
}
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def params
|
34
|
+
{
|
35
|
+
id_name: @primary_key,
|
36
|
+
id_value: record.public_send(@primary_key),
|
37
|
+
index_name: column,
|
38
|
+
index_value: record.public_send(column),
|
39
|
+
}
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Katalyst
|
4
|
+
module Tables
|
5
|
+
module Cells
|
6
|
+
# Displays the plain text for rich text content
|
7
|
+
#
|
8
|
+
# Adds a title attribute to allow for hover over display of the full content
|
9
|
+
class RichTextComponent < CellComponent
|
10
|
+
private
|
11
|
+
|
12
|
+
def default_html_attributes
|
13
|
+
{
|
14
|
+
class: "type-rich-text",
|
15
|
+
title: (value.to_plain_text unless row.header?),
|
16
|
+
}
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Katalyst
|
4
|
+
module Tables
|
5
|
+
module Cells
|
6
|
+
class SelectComponent < CellComponent
|
7
|
+
def initialize(params:, form_id:, **)
|
8
|
+
super(**)
|
9
|
+
|
10
|
+
@params = params
|
11
|
+
@form_id = form_id
|
12
|
+
end
|
13
|
+
|
14
|
+
def rendered_value
|
15
|
+
tag.input(type: :checkbox)
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def default_html_attributes
|
21
|
+
if @row.header?
|
22
|
+
{ class: "selection" }
|
23
|
+
else
|
24
|
+
{
|
25
|
+
class: "selection",
|
26
|
+
data: {
|
27
|
+
controller: Selectable::ITEM_CONTROLLER,
|
28
|
+
"#{Selectable::ITEM_CONTROLLER}-params-value" => @params.to_json,
|
29
|
+
"#{Selectable::ITEM_CONTROLLER}-#{Selectable::FORM_CONTROLLER}-outlet" => "##{@form_id}",
|
30
|
+
action: "change->#{Selectable::ITEM_CONTROLLER}#change",
|
31
|
+
turbo_permanent: "",
|
32
|
+
},
|
33
|
+
}
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Katalyst
|
4
|
+
module Tables
|
5
|
+
class Data
|
6
|
+
def initialize(record:, column:)
|
7
|
+
@record = record
|
8
|
+
@column = column
|
9
|
+
end
|
10
|
+
|
11
|
+
def value
|
12
|
+
return @value if defined?(@value)
|
13
|
+
|
14
|
+
@value = @record&.public_send(@column)
|
15
|
+
end
|
16
|
+
|
17
|
+
def call
|
18
|
+
ActionView::OutputBuffer.new.tap do |output|
|
19
|
+
output << value.to_s
|
20
|
+
end.to_s
|
21
|
+
end
|
22
|
+
|
23
|
+
alias to_s call
|
24
|
+
|
25
|
+
def inspect
|
26
|
+
"#<#{self.class.name} column: #{@column.inspect}, value: #{value.inspect}>"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -5,27 +5,10 @@ module Katalyst
|
|
5
5
|
class HeaderRowComponent < ViewComponent::Base # :nodoc:
|
6
6
|
include Katalyst::HtmlAttributes
|
7
7
|
|
8
|
-
renders_many :
|
8
|
+
renders_many :cells, ->(cell) { cell }
|
9
9
|
|
10
|
-
def
|
11
|
-
|
12
|
-
|
13
|
-
@table = table
|
14
|
-
@link_attributes = link
|
15
|
-
end
|
16
|
-
|
17
|
-
def call
|
18
|
-
content # generate content before rendering
|
19
|
-
|
20
|
-
tag.tr(**html_attributes) do
|
21
|
-
columns.each do |column|
|
22
|
-
concat(column.to_s)
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
def cell(attribute, **, &)
|
28
|
-
with_column(@table.header_cell_component.new(@table, attribute, link: @link_attributes, **), &)
|
10
|
+
def before_render
|
11
|
+
content # ensure content is rendered so html_attributes can be set
|
29
12
|
end
|
30
13
|
|
31
14
|
def header?
|
@@ -37,11 +20,8 @@ module Katalyst
|
|
37
20
|
end
|
38
21
|
|
39
22
|
def inspect
|
40
|
-
"#<#{self.class.name}
|
23
|
+
"#<#{self.class.name}>"
|
41
24
|
end
|
42
|
-
|
43
|
-
# Backwards compatibility with tables 1.0
|
44
|
-
alias_method :options, :html_attributes=
|
45
25
|
end
|
46
26
|
end
|
47
27
|
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Katalyst
|
4
|
+
module Tables
|
5
|
+
class Label
|
6
|
+
def initialize(collection:, column:, label: nil)
|
7
|
+
@collection = collection
|
8
|
+
@column = column
|
9
|
+
@label = label
|
10
|
+
end
|
11
|
+
|
12
|
+
def value
|
13
|
+
return @value if defined?(@value)
|
14
|
+
|
15
|
+
@value = if !@label.nil?
|
16
|
+
@label
|
17
|
+
elsif @collection.model.present?
|
18
|
+
@collection.model.human_attribute_name(@column)
|
19
|
+
else
|
20
|
+
@column.to_s.humanize.capitalize
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def call
|
25
|
+
ActionView::OutputBuffer.new.tap do |output|
|
26
|
+
output << value.to_s
|
27
|
+
end.to_s
|
28
|
+
end
|
29
|
+
|
30
|
+
alias to_s call
|
31
|
+
|
32
|
+
def inspect
|
33
|
+
"#<#{self.class.name} column: #{@column.inspect} value: #{value.inspect}>"
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Katalyst
|
4
|
+
module Tables
|
5
|
+
module Orderable
|
6
|
+
class FormComponent < ViewComponent::Base # :nodoc:
|
7
|
+
include Katalyst::Tables::Identifiable::Defaults
|
8
|
+
|
9
|
+
attr_reader :id, :url
|
10
|
+
|
11
|
+
# @param collection [Katalyst::Tables::Collection::Core] the collection to render
|
12
|
+
# @param url [String] the url to submit the form to (e.g. <resources>_order_path)
|
13
|
+
# @param id [String] the id of the form element (defaults to <resources>_order_form)
|
14
|
+
# @param scope [String] the base scope to use for form inputs (defaults to order[<resources>])
|
15
|
+
def initialize(collection:, url:, id: nil, scope: nil)
|
16
|
+
super
|
17
|
+
|
18
|
+
@id = id || Orderable.default_form_id(collection)
|
19
|
+
@url = url
|
20
|
+
@scope = scope || Orderable.default_scope(collection)
|
21
|
+
end
|
22
|
+
|
23
|
+
def call
|
24
|
+
form_with(id:, url:, method: :patch, data: {
|
25
|
+
controller: FORM_CONTROLLER,
|
26
|
+
"#{FORM_CONTROLLER}-scope-value": @scope,
|
27
|
+
}) do |form|
|
28
|
+
form.button(hidden: "")
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def inspect
|
33
|
+
"#<#{self.class.name} id: #{id.inspect}, url: #{url.inspect}>"
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -1,12 +1,14 @@
|
|
1
1
|
<%= form_with(method: :patch,
|
2
2
|
id:,
|
3
3
|
class: "tables--selection--form",
|
4
|
-
data: { controller:
|
5
|
-
|
4
|
+
data: { controller: form_controller,
|
5
|
+
turbo_action: "replace",
|
6
|
+
turbo_permanent: "" },
|
7
|
+
html: { action: false, hidden: "" }) do |form| %>
|
6
8
|
<p class="tables--selection--summary">
|
7
9
|
<span data-<%= form_target("count") %>>0</span>
|
8
|
-
<span data-<%= form_target("singular") %> hidden><%= @
|
9
|
-
<span data-<%= form_target("plural") %>><%= @
|
10
|
+
<span data-<%= form_target("singular") %> hidden><%= @collection.model_name.singular %></span>
|
11
|
+
<span data-<%= form_target("plural") %>><%= @collection.model_name.plural %></span>
|
10
12
|
selected
|
11
13
|
</p>
|
12
14
|
<%= content %>
|
@@ -4,24 +4,21 @@ module Katalyst
|
|
4
4
|
module Tables
|
5
5
|
module Selectable
|
6
6
|
class FormComponent < ViewComponent::Base # :nodoc:
|
7
|
+
include Katalyst::Tables::Identifiable::Defaults
|
8
|
+
|
7
9
|
attr_reader :id, :primary_key
|
8
10
|
|
9
|
-
|
11
|
+
# @param collection [Katalyst::Tables::Collection::Core] the collection to render
|
12
|
+
# @param id [String] the id of the form element (defaults to <resources>_selection_form)
|
13
|
+
# @param primary_key [String] the primary key of the record in the collection (defaults to :id)
|
14
|
+
def initialize(collection:,
|
10
15
|
id: nil,
|
11
16
|
primary_key: :id)
|
12
17
|
super
|
13
18
|
|
14
|
-
@
|
15
|
-
@id = id
|
19
|
+
@collection = collection
|
20
|
+
@id = id || Selectable.default_form_id(collection)
|
16
21
|
@primary_key = primary_key
|
17
|
-
|
18
|
-
if @id.nil?
|
19
|
-
table_id = table.try(:id)
|
20
|
-
|
21
|
-
raise ArgumentError, "Table selection requires an id" if table_id.nil?
|
22
|
-
|
23
|
-
@id = "#{table_id}_selection"
|
24
|
-
end
|
25
22
|
end
|
26
23
|
|
27
24
|
def inspect
|
@@ -2,35 +2,10 @@
|
|
2
2
|
|
3
3
|
module Katalyst
|
4
4
|
module Tables
|
5
|
-
#
|
6
|
-
# in a table view using Katalyst::Tables::Frontend.
|
7
|
-
#
|
8
|
-
# Provides `table_sort` for sorting based on column interactions (sort param).
|
5
|
+
# Configuration for controllers to specify which TableComponent should be used in associated views.
|
9
6
|
module Backend
|
10
7
|
extend ActiveSupport::Concern
|
11
8
|
|
12
|
-
# @deprecated backwards compatibility
|
13
|
-
class SortForm < Katalyst::Tables::Collection::SortForm
|
14
|
-
end
|
15
|
-
|
16
|
-
# Sort the given collection by params[:sort], which is set when a user
|
17
|
-
# interacts with a column header in a frontend table view.
|
18
|
-
#
|
19
|
-
# @return [[SortForm, ActiveRecord::Relation]]
|
20
|
-
def table_sort(collection)
|
21
|
-
column, direction = params[:sort]&.split
|
22
|
-
direction = "asc" unless SortForm::DIRECTIONS.include?(direction)
|
23
|
-
|
24
|
-
SortForm.new(column:,
|
25
|
-
direction:)
|
26
|
-
.apply(collection)
|
27
|
-
end
|
28
|
-
|
29
|
-
def self_referred?
|
30
|
-
request.referer.present? && URI.parse(request.referer).path == request.path
|
31
|
-
end
|
32
|
-
alias self_refered? self_referred?
|
33
|
-
|
34
9
|
included do
|
35
10
|
class_attribute :_default_table_component, instance_accessor: false
|
36
11
|
end
|
@@ -39,8 +14,7 @@ module Katalyst
|
|
39
14
|
# Set the table component to be used as the default for all tables
|
40
15
|
# in the views rendered by this controller and its subclasses.
|
41
16
|
#
|
42
|
-
#
|
43
|
-
# * <tt>component</tt> - Default table component, an instance of +Katalyst::TableComponent+
|
17
|
+
# @param component [Class] the table component class to use
|
44
18
|
def default_table_component(component)
|
45
19
|
self._default_table_component = component
|
46
20
|
end
|