katalyst-tables 2.6.0.beta → 3.0.0.beta1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +6 -1
- data/README.md +1 -23
- 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/body/typed_columns.rb +132 -0
- data/app/components/concerns/katalyst/tables/has_table_content.rb +1 -1
- data/app/components/concerns/katalyst/tables/header/typed_columns.rb +179 -0
- data/app/components/concerns/katalyst/tables/orderable.rb +1 -1
- data/app/components/concerns/katalyst/tables/selectable.rb +2 -1
- data/app/components/katalyst/table_component.rb +13 -1
- data/app/components/katalyst/tables/body/attachment_component.rb +58 -0
- data/app/components/katalyst/tables/body/boolean_component.rb +14 -0
- data/app/components/katalyst/tables/body/currency_component.rb +29 -0
- data/app/components/katalyst/tables/body/date_component.rb +64 -0
- data/app/components/katalyst/tables/body/date_time_component.rb +57 -0
- data/app/components/katalyst/tables/body/link_component.rb +40 -0
- data/app/components/katalyst/tables/body/number_component.rb +22 -0
- data/app/components/katalyst/tables/body/rich_text_component.rb +18 -0
- data/app/components/katalyst/tables/body_cell_component.rb +9 -1
- data/app/components/katalyst/tables/body_row_component.rb +9 -2
- data/app/components/katalyst/tables/empty_caption_component.rb +1 -1
- data/app/components/katalyst/tables/header/attachment_component.rb +15 -0
- data/app/components/katalyst/tables/header/boolean_component.rb +15 -0
- data/app/components/katalyst/tables/header/currency_component.rb +15 -0
- data/app/components/katalyst/tables/header/date_component.rb +15 -0
- data/app/components/katalyst/tables/header/date_time_component.rb +15 -0
- data/app/components/katalyst/tables/header/link_component.rb +15 -0
- data/app/components/katalyst/tables/header/number_component.rb +15 -0
- data/app/components/katalyst/tables/header/rich_text_component.rb +15 -0
- data/app/components/katalyst/tables/header_cell_component.rb +35 -3
- data/app/components/katalyst/tables/header_row_component.rb +3 -2
- data/app/components/katalyst/tables/selectable/form_component.html.erb +4 -2
- data/app/controllers/concerns/katalyst/tables/backend.rb +2 -2
- data/app/helpers/katalyst/tables/frontend.rb +2 -2
- data/app/models/concerns/katalyst/tables/collection/pagination.rb +8 -1
- data/app/models/concerns/katalyst/tables/collection/sorting.rb +3 -3
- data/app/models/katalyst/tables/collection/sort_form.rb +26 -8
- data/config/locales/tables.en.yml +6 -0
- metadata +33 -9
- data/app/components/concerns/katalyst/tables/turbo_replaceable.rb +0 -79
- data/app/components/katalyst/turbo/pagy_nav_component.rb +0 -23
- data/app/components/katalyst/turbo/table_component.rb +0 -45
@@ -0,0 +1,58 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
using Katalyst::HtmlAttributes::HasHtmlAttributes
|
4
|
+
|
5
|
+
module Katalyst
|
6
|
+
module Tables
|
7
|
+
module Body
|
8
|
+
# Shows an attachment
|
9
|
+
#
|
10
|
+
# The value is expected to be an ActiveStorage attachment
|
11
|
+
#
|
12
|
+
# If it is representable, shows as a image tag using a default variant named :thumb.
|
13
|
+
#
|
14
|
+
# Otherwise shows as a link to download.
|
15
|
+
class AttachmentComponent < BodyCellComponent
|
16
|
+
def initialize(table, record, attribute, variant: :thumb, **options)
|
17
|
+
super(table, record, attribute, **options)
|
18
|
+
|
19
|
+
@variant = variant
|
20
|
+
end
|
21
|
+
|
22
|
+
def rendered_value
|
23
|
+
representation
|
24
|
+
end
|
25
|
+
|
26
|
+
def representation
|
27
|
+
if value.try(:variable?) && named_variant.present?
|
28
|
+
image_tag(value.variant(@variant))
|
29
|
+
elsif value.try(:attached?)
|
30
|
+
filename.to_s
|
31
|
+
else
|
32
|
+
""
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def filename
|
37
|
+
value.blob.filename
|
38
|
+
end
|
39
|
+
|
40
|
+
# Utility for accessing the path Rails provides for retrieving the
|
41
|
+
# attachment for use in cells. Example:
|
42
|
+
# <% row.attachment :file do |cell| %>
|
43
|
+
# <%= link_to "Download", cell.internal_path %>
|
44
|
+
# <% end %>
|
45
|
+
def internal_path
|
46
|
+
rails_blob_path(value, disposition: :attachment)
|
47
|
+
end
|
48
|
+
|
49
|
+
private
|
50
|
+
|
51
|
+
# Find the reflective variant by name (i.e. :thumb by default)
|
52
|
+
def named_variant
|
53
|
+
object.attachment_reflections[@attribute.to_s].named_variants[@variant.to_sym]
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
using Katalyst::HtmlAttributes::HasHtmlAttributes
|
4
|
+
|
5
|
+
module Katalyst
|
6
|
+
module Tables
|
7
|
+
module Body
|
8
|
+
# Formats the value as a money value
|
9
|
+
#
|
10
|
+
# The value is expected to be in cents.
|
11
|
+
# Adds a class to the cell to allow for custom styling
|
12
|
+
class CurrencyComponent < BodyCellComponent
|
13
|
+
def initialize(table, record, attribute, options: {}, **html_attributes)
|
14
|
+
super(table, record, attribute, **html_attributes)
|
15
|
+
|
16
|
+
@options = options
|
17
|
+
end
|
18
|
+
|
19
|
+
def rendered_value
|
20
|
+
value.present? ? number_to_currency(value / 100.0, @options) : ""
|
21
|
+
end
|
22
|
+
|
23
|
+
def default_html_attributes
|
24
|
+
super.merge_html(class: "type-currency")
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Katalyst
|
4
|
+
module Tables
|
5
|
+
module Body
|
6
|
+
# Formats the value as a date
|
7
|
+
# @param format [String] date format, defaults to :table
|
8
|
+
# @param relative [Boolean] if true, the date may be(if within 5 days) shown as a relative date
|
9
|
+
class DateComponent < BodyCellComponent
|
10
|
+
def initialize(table, record, attribute, format: :table, relative: true, **options)
|
11
|
+
super(table, record, attribute, **options)
|
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 absolute_time
|
28
|
+
value.present? ? I18n.l(value, format: @format) : ""
|
29
|
+
end
|
30
|
+
|
31
|
+
def relative_time
|
32
|
+
if value.blank?
|
33
|
+
""
|
34
|
+
else
|
35
|
+
days_ago_in_words(value)&.capitalize || absolute_time
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def default_html_attributes
|
40
|
+
@relative && value.present? && days_ago_in_words(value).present? ? { title: absolute_time } : {}
|
41
|
+
end
|
42
|
+
|
43
|
+
def days_ago_in_words(value)
|
44
|
+
from_time = value.to_time
|
45
|
+
to_time = Date.current.to_time
|
46
|
+
distance_in_days = ((to_time - from_time) / (24.0 * 60.0 * 60.0)).round
|
47
|
+
|
48
|
+
case distance_in_days
|
49
|
+
when 0
|
50
|
+
"today"
|
51
|
+
when 1
|
52
|
+
"yesterday"
|
53
|
+
when -1
|
54
|
+
"tomorrow"
|
55
|
+
when 2..5
|
56
|
+
"#{distance_in_days} days ago"
|
57
|
+
when -5..-2
|
58
|
+
"#{distance_in_days.abs} days from now"
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Katalyst
|
4
|
+
module Tables
|
5
|
+
module Body
|
6
|
+
# Formats the value as a datetime
|
7
|
+
# @param format [String] datetime format, defaults to :admin
|
8
|
+
# @param relative [Boolean] if true, the datetime may be(if today) shown as a relative date/time
|
9
|
+
class DateTimeComponent < BodyCellComponent
|
10
|
+
include ActionView::Helpers::DateHelper
|
11
|
+
|
12
|
+
def initialize(table, record, attribute, format: :table, relative: true, **options)
|
13
|
+
super(table, record, attribute, **options)
|
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 absolute_time
|
30
|
+
value.present? ? I18n.l(value, format: @format) : ""
|
31
|
+
end
|
32
|
+
|
33
|
+
def today?
|
34
|
+
value&.to_date == Date.current
|
35
|
+
end
|
36
|
+
|
37
|
+
def relative_time
|
38
|
+
return "" if value.blank?
|
39
|
+
|
40
|
+
if today?
|
41
|
+
if value > DateTime.current
|
42
|
+
"#{distance_of_time_in_words(value, DateTime.current)} from now".capitalize
|
43
|
+
else
|
44
|
+
"#{distance_of_time_in_words(value, DateTime.current)} ago".capitalize
|
45
|
+
end
|
46
|
+
else
|
47
|
+
absolute_time
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def default_html_attributes
|
52
|
+
@relative && today? ? { title: absolute_time } : {}
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
using Katalyst::HtmlAttributes::HasHtmlAttributes
|
4
|
+
|
5
|
+
module Katalyst
|
6
|
+
module Tables
|
7
|
+
module Body
|
8
|
+
# Displays a link to the record
|
9
|
+
# The link text is the value of the attribute
|
10
|
+
# @see Koi::Tables::BodyRowComponent#link
|
11
|
+
class LinkComponent < BodyCellComponent
|
12
|
+
def initialize(table, record, attribute, url:, link: {}, **options)
|
13
|
+
super(table, record, attribute, **options)
|
14
|
+
|
15
|
+
@url = url
|
16
|
+
@link_options = link
|
17
|
+
end
|
18
|
+
|
19
|
+
def call
|
20
|
+
content # ensure content is set before rendering options
|
21
|
+
|
22
|
+
link = content.present? && url.present? ? link_to(content, url, @link_options) : content.to_s
|
23
|
+
content_tag(@type, link, **html_attributes)
|
24
|
+
end
|
25
|
+
|
26
|
+
def url
|
27
|
+
case @url
|
28
|
+
when Symbol
|
29
|
+
# helpers are not available until the component is rendered
|
30
|
+
@url = helpers.public_send(@url, record)
|
31
|
+
when Proc
|
32
|
+
@url = @url.call(record)
|
33
|
+
else
|
34
|
+
@url
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
using Katalyst::HtmlAttributes::HasHtmlAttributes
|
4
|
+
|
5
|
+
module Katalyst
|
6
|
+
module Tables
|
7
|
+
module Body
|
8
|
+
# Formats the value as a number
|
9
|
+
#
|
10
|
+
# Adds a class to the cell to allow for custom styling
|
11
|
+
class NumberComponent < BodyCellComponent
|
12
|
+
def rendered_value
|
13
|
+
value.present? ? number_to_human(value) : ""
|
14
|
+
end
|
15
|
+
|
16
|
+
def default_html_attributes
|
17
|
+
super.merge_html(class: "type-number")
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
using Katalyst::HtmlAttributes::HasHtmlAttributes
|
4
|
+
|
5
|
+
module Katalyst
|
6
|
+
module Tables
|
7
|
+
module Body
|
8
|
+
# Displays the plain text for rich text content
|
9
|
+
#
|
10
|
+
# Adds a title attribute to allow for hover over display of the full content
|
11
|
+
class RichTextComponent < BodyCellComponent
|
12
|
+
def default_html_attributes
|
13
|
+
{ title: value.to_plain_text }
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -18,7 +18,7 @@ module Katalyst
|
|
18
18
|
|
19
19
|
def before_render
|
20
20
|
# fallback if no content block is given
|
21
|
-
with_content(
|
21
|
+
with_content(rendered_value) unless content?
|
22
22
|
end
|
23
23
|
|
24
24
|
def call
|
@@ -36,6 +36,14 @@ module Katalyst
|
|
36
36
|
@record.public_send(@attribute)
|
37
37
|
end
|
38
38
|
|
39
|
+
def rendered_value
|
40
|
+
value.to_s
|
41
|
+
end
|
42
|
+
|
43
|
+
def to_s
|
44
|
+
value.to_s
|
45
|
+
end
|
46
|
+
|
39
47
|
def inspect
|
40
48
|
"#<#{self.class.name} attribute: #{@attribute.inspect}, value: #{value.inspect}>"
|
41
49
|
end
|
@@ -4,6 +4,7 @@ module Katalyst
|
|
4
4
|
module Tables
|
5
5
|
class BodyRowComponent < ViewComponent::Base # :nodoc:
|
6
6
|
include Katalyst::HtmlAttributes
|
7
|
+
include Body::TypedColumns
|
7
8
|
|
8
9
|
renders_many :columns, ->(component) { component }
|
9
10
|
|
@@ -24,8 +25,8 @@ module Katalyst
|
|
24
25
|
end
|
25
26
|
end
|
26
27
|
|
27
|
-
def cell(attribute,
|
28
|
-
with_column(@table.body_cell_component.new(@table, @record, attribute, **
|
28
|
+
def cell(attribute, **, &)
|
29
|
+
with_column(@table.body_cell_component.new(@table, @record, attribute, **), &)
|
29
30
|
end
|
30
31
|
|
31
32
|
def header?
|
@@ -36,6 +37,12 @@ module Katalyst
|
|
36
37
|
true
|
37
38
|
end
|
38
39
|
|
40
|
+
def default_html_attributes
|
41
|
+
return {} unless @table.generate_ids?
|
42
|
+
|
43
|
+
{ id: dom_id(@record) }
|
44
|
+
end
|
45
|
+
|
39
46
|
def inspect
|
40
47
|
"#<#{self.class.name} record: #{record.inspect}>"
|
41
48
|
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
using Katalyst::HtmlAttributes::HasHtmlAttributes
|
4
|
+
|
5
|
+
module Katalyst
|
6
|
+
module Tables
|
7
|
+
module Header
|
8
|
+
class AttachmentComponent < HeaderCellComponent
|
9
|
+
def default_html_attributes
|
10
|
+
super.merge_html(class: "type-attachment")
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
using Katalyst::HtmlAttributes::HasHtmlAttributes
|
4
|
+
|
5
|
+
module Katalyst
|
6
|
+
module Tables
|
7
|
+
module Header
|
8
|
+
class BooleanComponent < HeaderCellComponent
|
9
|
+
def default_html_attributes
|
10
|
+
super.merge_html(class: "type-boolean")
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
using Katalyst::HtmlAttributes::HasHtmlAttributes
|
4
|
+
|
5
|
+
module Katalyst
|
6
|
+
module Tables
|
7
|
+
module Header
|
8
|
+
class CurrencyComponent < HeaderCellComponent
|
9
|
+
def default_html_attributes
|
10
|
+
super.merge_html(class: "type-currency")
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
using Katalyst::HtmlAttributes::HasHtmlAttributes
|
4
|
+
|
5
|
+
module Katalyst
|
6
|
+
module Tables
|
7
|
+
module Header
|
8
|
+
class DateComponent < HeaderCellComponent
|
9
|
+
def default_html_attributes
|
10
|
+
super.merge_html(class: "type-date")
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
using Katalyst::HtmlAttributes::HasHtmlAttributes
|
4
|
+
|
5
|
+
module Katalyst
|
6
|
+
module Tables
|
7
|
+
module Header
|
8
|
+
class DateTimeComponent < HeaderCellComponent
|
9
|
+
def default_html_attributes
|
10
|
+
super.merge_html(class: "type-datetime")
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
using Katalyst::HtmlAttributes::HasHtmlAttributes
|
4
|
+
|
5
|
+
module Katalyst
|
6
|
+
module Tables
|
7
|
+
module Header
|
8
|
+
class LinkComponent < HeaderCellComponent
|
9
|
+
def default_html_attributes
|
10
|
+
super.merge_html(class: "type-link")
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
using Katalyst::HtmlAttributes::HasHtmlAttributes
|
4
|
+
|
5
|
+
module Katalyst
|
6
|
+
module Tables
|
7
|
+
module Header
|
8
|
+
class NumberComponent < HeaderCellComponent
|
9
|
+
def default_html_attributes
|
10
|
+
super.merge_html(class: "type-number")
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
using Katalyst::HtmlAttributes::HasHtmlAttributes
|
4
|
+
|
5
|
+
module Katalyst
|
6
|
+
module Tables
|
7
|
+
module Header
|
8
|
+
class RichTextComponent < HeaderCellComponent
|
9
|
+
def default_html_attributes
|
10
|
+
super.merge_html(class: "type-rich-text")
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
using Katalyst::HtmlAttributes::HasHtmlAttributes
|
4
|
+
|
3
5
|
module Katalyst
|
4
6
|
module Tables
|
5
7
|
class HeaderCellComponent < ViewComponent::Base # :nodoc:
|
@@ -9,19 +11,20 @@ module Katalyst
|
|
9
11
|
|
10
12
|
delegate :object_name, :collection, :sorting, to: :@table
|
11
13
|
|
12
|
-
def initialize(table, attribute, label: nil, link: {}, **html_attributes)
|
14
|
+
def initialize(table, attribute, label: nil, link: {}, width: nil, **html_attributes)
|
13
15
|
super(**html_attributes)
|
14
16
|
|
15
17
|
@table = table
|
16
18
|
@attribute = attribute
|
17
19
|
@value = label
|
20
|
+
@width = width
|
18
21
|
@link_attributes = link
|
19
22
|
end
|
20
23
|
|
21
24
|
def call
|
22
25
|
tag.th(**html_attributes) do
|
23
26
|
if sortable?(@attribute)
|
24
|
-
link_to(value, sort_url(@attribute),
|
27
|
+
link_to(value, sort_url(@attribute), **link_attributes)
|
25
28
|
else
|
26
29
|
value
|
27
30
|
end
|
@@ -47,7 +50,7 @@ module Katalyst
|
|
47
50
|
end
|
48
51
|
|
49
52
|
def inspect
|
50
|
-
"#<#{self.class.name} attribute: #{@attribute.inspect}, value: #{value.inspect}>"
|
53
|
+
"#<#{self.class.name} attribute: #{@attribute.inspect}, value: #{@value.inspect}>"
|
51
54
|
end
|
52
55
|
|
53
56
|
# Backwards compatibility with tables 1.0
|
@@ -55,7 +58,36 @@ module Katalyst
|
|
55
58
|
|
56
59
|
private
|
57
60
|
|
61
|
+
def width_class
|
62
|
+
case @width
|
63
|
+
when :xs
|
64
|
+
"width-xs"
|
65
|
+
when :s
|
66
|
+
"width-s"
|
67
|
+
when :m
|
68
|
+
"width-m"
|
69
|
+
when :l
|
70
|
+
"width-l"
|
71
|
+
else
|
72
|
+
""
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def link_attributes
|
77
|
+
{ data: { turbo_action: "replace" } }.merge_html(@link_attributes)
|
78
|
+
end
|
79
|
+
|
58
80
|
def default_html_attributes
|
81
|
+
sort_data.merge(width_data)
|
82
|
+
end
|
83
|
+
|
84
|
+
def width_data
|
85
|
+
return {} unless @width
|
86
|
+
|
87
|
+
{ class: width_class }
|
88
|
+
end
|
89
|
+
|
90
|
+
def sort_data
|
59
91
|
return {} unless sorting&.supports?(collection, @attribute)
|
60
92
|
|
61
93
|
{ data: { sort: sorting.status(@attribute) } }
|
@@ -4,6 +4,7 @@ module Katalyst
|
|
4
4
|
module Tables
|
5
5
|
class HeaderRowComponent < ViewComponent::Base # :nodoc:
|
6
6
|
include Katalyst::HtmlAttributes
|
7
|
+
include Header::TypedColumns
|
7
8
|
|
8
9
|
renders_many :columns, ->(component) { component }
|
9
10
|
|
@@ -24,8 +25,8 @@ module Katalyst
|
|
24
25
|
end
|
25
26
|
end
|
26
27
|
|
27
|
-
def cell(attribute,
|
28
|
-
with_column(@table.header_cell_component.new(@table, attribute, link: @link_attributes, **
|
28
|
+
def cell(attribute, **, &)
|
29
|
+
with_column(@table.header_cell_component.new(@table, attribute, link: @link_attributes, **), &)
|
29
30
|
end
|
30
31
|
|
31
32
|
def header?
|
@@ -1,7 +1,9 @@
|
|
1
1
|
<%= form_with(method: :patch,
|
2
|
-
id
|
2
|
+
id:,
|
3
3
|
class: "tables--selection--form",
|
4
|
-
data: { controller:
|
4
|
+
data: { controller: form_controller,
|
5
|
+
turbo_action: "replace",
|
6
|
+
turbo_permanent: "" },
|
5
7
|
html: { hidden: "" }) do |form| %>
|
6
8
|
<p class="tables--selection--summary">
|
7
9
|
<span data-<%= form_target("count") %>>0</span>
|
@@ -21,8 +21,8 @@ module Katalyst
|
|
21
21
|
column, direction = params[:sort]&.split
|
22
22
|
direction = "asc" unless SortForm::DIRECTIONS.include?(direction)
|
23
23
|
|
24
|
-
SortForm.new(column
|
25
|
-
direction:
|
24
|
+
SortForm.new(column:,
|
25
|
+
direction:)
|
26
26
|
.apply(collection)
|
27
27
|
end
|
28
28
|
|
@@ -4,9 +4,9 @@ module Katalyst
|
|
4
4
|
module Tables
|
5
5
|
# View Helper for generating HTML tables. Include in your ApplicationHelper, or similar.
|
6
6
|
module Frontend
|
7
|
-
def table_with(collection:, component: nil,
|
7
|
+
def table_with(collection:, component: nil, **, &)
|
8
8
|
component ||= default_table_component_class
|
9
|
-
render(component.new(collection
|
9
|
+
render(component.new(collection:, **), &)
|
10
10
|
end
|
11
11
|
|
12
12
|
private
|
@@ -35,7 +35,14 @@ module Katalyst
|
|
35
35
|
end
|
36
36
|
|
37
37
|
def paginate_options
|
38
|
-
@paginate.is_a?(Hash) ? @paginate : {}
|
38
|
+
opts = @paginate.is_a?(Hash) ? @paginate : {}
|
39
|
+
opts = opts.dup
|
40
|
+
opts[:anchor_string] ||= anchor_string
|
41
|
+
opts
|
42
|
+
end
|
43
|
+
|
44
|
+
def anchor_string
|
45
|
+
"data-turbo-action=\"replace\""
|
39
46
|
end
|
40
47
|
|
41
48
|
class Paginate # :nodoc:
|
@@ -22,16 +22,16 @@ module Katalyst
|
|
22
22
|
end
|
23
23
|
|
24
24
|
def initialize(sorting: config.sorting, **options)
|
25
|
-
@sorting = SortForm.parse(sorting) if sorting
|
25
|
+
@sorting = SortForm.parse(sorting, default: sorting) if sorting
|
26
26
|
|
27
|
-
super(sort: sorting, **options) # set default sort based on config
|
27
|
+
super(sort: @sorting.to_param, **options) # set default sort based on config
|
28
28
|
end
|
29
29
|
|
30
30
|
def sort=(value)
|
31
31
|
return unless @sorting
|
32
32
|
|
33
33
|
# update internal proxy
|
34
|
-
@sorting = SortForm.parse(value, default:
|
34
|
+
@sorting = SortForm.parse(value, default: @sorting.default)
|
35
35
|
|
36
36
|
# update attribute based on normalized value
|
37
37
|
super(@sorting.to_param)
|