katalyst-tables 3.0.0.beta1 → 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 +12 -2
- data/README.md +56 -190
- 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/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 -75
- 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 +271 -53
- data/app/components/katalyst/tables/body_row_component.html.erb +5 -0
- data/app/components/katalyst/tables/body_row_component.rb +4 -31
- data/app/components/katalyst/tables/cell_component.rb +85 -0
- data/app/components/katalyst/tables/{body → cells}/boolean_component.rb +8 -2
- data/app/components/katalyst/tables/{body → cells}/currency_component.rb +7 -7
- data/app/components/katalyst/tables/{body → cells}/date_component.rb +12 -9
- data/app/components/katalyst/tables/{body → cells}/date_time_component.rb +13 -10
- data/app/components/katalyst/tables/{body → cells}/number_component.rb +5 -5
- data/app/components/katalyst/tables/cells/ordinal_component.rb +44 -0
- data/app/components/katalyst/tables/{body → cells}/rich_text_component.rb +8 -5
- 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/header_row_component.html.erb +5 -0
- data/app/components/katalyst/tables/header_row_component.rb +4 -25
- 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 +3 -3
- 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/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/config/locales/tables.en.yml +0 -6
- data/lib/katalyst/tables/config.rb +23 -0
- data/lib/katalyst/tables.rb +9 -0
- metadata +22 -29
- data/app/components/concerns/katalyst/tables/body/typed_columns.rb +0 -132
- data/app/components/concerns/katalyst/tables/configurable_component.rb +0 -52
- data/app/components/concerns/katalyst/tables/header/typed_columns.rb +0 -179
- data/app/components/katalyst/tables/body/attachment_component.rb +0 -58
- data/app/components/katalyst/tables/body/link_component.rb +0 -40
- data/app/components/katalyst/tables/body_cell_component.rb +0 -55
- data/app/components/katalyst/tables/header/attachment_component.rb +0 -15
- data/app/components/katalyst/tables/header/boolean_component.rb +0 -15
- data/app/components/katalyst/tables/header/currency_component.rb +0 -15
- data/app/components/katalyst/tables/header/date_component.rb +0 -15
- data/app/components/katalyst/tables/header/date_time_component.rb +0 -15
- data/app/components/katalyst/tables/header/link_component.rb +0 -15
- data/app/components/katalyst/tables/header/number_component.rb +0 -15
- data/app/components/katalyst/tables/header/rich_text_component.rb +0 -15
- data/app/components/katalyst/tables/header_cell_component.rb +0 -97
- 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 -120
@@ -1,40 +0,0 @@
|
|
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
|
@@ -1,55 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Katalyst
|
4
|
-
module Tables
|
5
|
-
class BodyCellComponent < ViewComponent::Base # :nodoc:
|
6
|
-
include Katalyst::HtmlAttributes
|
7
|
-
|
8
|
-
attr_reader :record
|
9
|
-
|
10
|
-
def initialize(table, record, attribute, heading: false, **html_attributes)
|
11
|
-
super(**html_attributes)
|
12
|
-
|
13
|
-
@table = table
|
14
|
-
@record = record
|
15
|
-
@attribute = attribute
|
16
|
-
@type = heading ? :th : :td
|
17
|
-
end
|
18
|
-
|
19
|
-
def before_render
|
20
|
-
# fallback if no content block is given
|
21
|
-
with_content(rendered_value) unless content?
|
22
|
-
end
|
23
|
-
|
24
|
-
def call
|
25
|
-
content # ensure content is set before rendering options
|
26
|
-
|
27
|
-
content_tag(@type, content, **html_attributes)
|
28
|
-
end
|
29
|
-
|
30
|
-
# @return the object for this row.
|
31
|
-
def object
|
32
|
-
@record
|
33
|
-
end
|
34
|
-
|
35
|
-
def value
|
36
|
-
@record.public_send(@attribute)
|
37
|
-
end
|
38
|
-
|
39
|
-
def rendered_value
|
40
|
-
value.to_s
|
41
|
-
end
|
42
|
-
|
43
|
-
def to_s
|
44
|
-
value.to_s
|
45
|
-
end
|
46
|
-
|
47
|
-
def inspect
|
48
|
-
"#<#{self.class.name} attribute: #{@attribute.inspect}, value: #{value.inspect}>"
|
49
|
-
end
|
50
|
-
|
51
|
-
# Backwards compatibility with tables 1.0
|
52
|
-
alias_method :options, :html_attributes=
|
53
|
-
end
|
54
|
-
end
|
55
|
-
end
|
@@ -1,15 +0,0 @@
|
|
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
|
@@ -1,15 +0,0 @@
|
|
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
|
@@ -1,15 +0,0 @@
|
|
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
|
@@ -1,15 +0,0 @@
|
|
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
|
@@ -1,15 +0,0 @@
|
|
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
|
@@ -1,15 +0,0 @@
|
|
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
|
@@ -1,15 +0,0 @@
|
|
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
|
@@ -1,15 +0,0 @@
|
|
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,97 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
using Katalyst::HtmlAttributes::HasHtmlAttributes
|
4
|
-
|
5
|
-
module Katalyst
|
6
|
-
module Tables
|
7
|
-
class HeaderCellComponent < ViewComponent::Base # :nodoc:
|
8
|
-
include Frontend::Helper
|
9
|
-
include Katalyst::HtmlAttributes
|
10
|
-
include Sortable
|
11
|
-
|
12
|
-
delegate :object_name, :collection, :sorting, to: :@table
|
13
|
-
|
14
|
-
def initialize(table, attribute, label: nil, link: {}, width: nil, **html_attributes)
|
15
|
-
super(**html_attributes)
|
16
|
-
|
17
|
-
@table = table
|
18
|
-
@attribute = attribute
|
19
|
-
@value = label
|
20
|
-
@width = width
|
21
|
-
@link_attributes = link
|
22
|
-
end
|
23
|
-
|
24
|
-
def call
|
25
|
-
tag.th(**html_attributes) do
|
26
|
-
if sortable?(@attribute)
|
27
|
-
link_to(value, sort_url(@attribute), **link_attributes)
|
28
|
-
else
|
29
|
-
value
|
30
|
-
end
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
def value
|
35
|
-
if !@value.nil?
|
36
|
-
@value
|
37
|
-
elsif object_name.present?
|
38
|
-
translation
|
39
|
-
else
|
40
|
-
default_value
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
|
-
def translation(key = "activerecord.attributes.#{object_name}.#{@attribute}")
|
45
|
-
translate(key, default: default_value)
|
46
|
-
end
|
47
|
-
|
48
|
-
def default_value
|
49
|
-
@attribute.to_s.humanize.capitalize
|
50
|
-
end
|
51
|
-
|
52
|
-
def inspect
|
53
|
-
"#<#{self.class.name} attribute: #{@attribute.inspect}, value: #{@value.inspect}>"
|
54
|
-
end
|
55
|
-
|
56
|
-
# Backwards compatibility with tables 1.0
|
57
|
-
alias_method :options, :html_attributes=
|
58
|
-
|
59
|
-
private
|
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
|
-
|
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
|
91
|
-
return {} unless sorting&.supports?(collection, @attribute)
|
92
|
-
|
93
|
-
{ data: { sort: sorting.status(@attribute) } }
|
94
|
-
end
|
95
|
-
end
|
96
|
-
end
|
97
|
-
end
|
@@ -1,31 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Katalyst
|
4
|
-
module Tables
|
5
|
-
module Frontend
|
6
|
-
# @deprecated Use {Katalyst::TableComponent} instead.
|
7
|
-
module Helper # :nodoc:
|
8
|
-
extend ActiveSupport::Concern
|
9
|
-
|
10
|
-
# Generates a url for applying/toggling sort for the given column.
|
11
|
-
#
|
12
|
-
# @param sort [String, nil] sort parameter to apply, or nil to remove sorting
|
13
|
-
# @return [String] URL for toggling column sorting
|
14
|
-
# @deprecated Use {Katalyst::TablesComponent} instead.
|
15
|
-
def sort_url_for(sort: nil, default: nil)
|
16
|
-
# Implementation inspired by pagy's `pagy_url_for` helper.
|
17
|
-
# Preserve any existing GET parameters
|
18
|
-
# CAUTION: these parameters are not sanitised
|
19
|
-
params = if sort && !sort.eql?(default)
|
20
|
-
request.GET.merge("sort" => sort).except("page")
|
21
|
-
else
|
22
|
-
request.GET.except("page", "sort")
|
23
|
-
end
|
24
|
-
query_string = params.empty? ? "" : "?#{Rack::Utils.build_nested_query(params)}"
|
25
|
-
|
26
|
-
"#{request.path}#{query_string}"
|
27
|
-
end
|
28
|
-
end
|
29
|
-
end
|
30
|
-
end
|
31
|
-
end
|
@@ -1,38 +0,0 @@
|
|
1
|
-
import { Controller } from "@hotwired/stimulus";
|
2
|
-
import { Turbo } from "@hotwired/turbo-rails";
|
3
|
-
|
4
|
-
export default class TurboCollectionController extends Controller {
|
5
|
-
static values = {
|
6
|
-
query: String,
|
7
|
-
sort: String,
|
8
|
-
};
|
9
|
-
|
10
|
-
queryValueChanged(query) {
|
11
|
-
Turbo.navigator.history.replace(this.#url(query));
|
12
|
-
}
|
13
|
-
|
14
|
-
sortValueChanged(sort) {
|
15
|
-
document.querySelectorAll(this.#sortSelector).forEach((input) => {
|
16
|
-
if (input) input.value = sort;
|
17
|
-
});
|
18
|
-
}
|
19
|
-
|
20
|
-
get #sortSelector() {
|
21
|
-
return "input[name='sort']";
|
22
|
-
}
|
23
|
-
|
24
|
-
#url(query) {
|
25
|
-
const frame = this.element.closest("turbo-frame");
|
26
|
-
let url;
|
27
|
-
|
28
|
-
if (frame) {
|
29
|
-
url = new URL(frame.baseURI);
|
30
|
-
} else {
|
31
|
-
url = new URL(window.location.href);
|
32
|
-
}
|
33
|
-
|
34
|
-
url.search = query;
|
35
|
-
|
36
|
-
return url;
|
37
|
-
}
|
38
|
-
}
|
@@ -1,120 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Katalyst
|
4
|
-
module Tables
|
5
|
-
module Collection
|
6
|
-
# A FormObject (model) representing the sort state of controller for a given
|
7
|
-
# collection/parameter.
|
8
|
-
class SortForm
|
9
|
-
DIRECTIONS = %w[asc desc].freeze
|
10
|
-
|
11
|
-
attr_accessor :column, :direction, :default
|
12
|
-
|
13
|
-
def self.normalize(param)
|
14
|
-
new(param:).to_param
|
15
|
-
end
|
16
|
-
|
17
|
-
def self.parse(param, **args)
|
18
|
-
new(param:, **args)
|
19
|
-
end
|
20
|
-
|
21
|
-
def initialize(param: nil, column: nil, direction: nil, default: nil)
|
22
|
-
if param.present?
|
23
|
-
column, direction = param.to_s.split
|
24
|
-
direction = "asc" unless DIRECTIONS.include?(direction)
|
25
|
-
end
|
26
|
-
|
27
|
-
self.column = column
|
28
|
-
self.direction = direction
|
29
|
-
self.default = SortForm.normalize(default) if default
|
30
|
-
end
|
31
|
-
|
32
|
-
def to_param
|
33
|
-
"#{column} #{direction}"
|
34
|
-
end
|
35
|
-
|
36
|
-
def default?
|
37
|
-
to_param == default.to_param
|
38
|
-
end
|
39
|
-
|
40
|
-
def hash
|
41
|
-
to_param.hash
|
42
|
-
end
|
43
|
-
|
44
|
-
def eql?(other)
|
45
|
-
to_param == other.to_param
|
46
|
-
end
|
47
|
-
|
48
|
-
alias to_s to_param
|
49
|
-
|
50
|
-
# Returns true if the given collection supports sorting on the given
|
51
|
-
# column. A column supports sorting if it is a database column or if
|
52
|
-
# the collection responds to `order_by_#{column}(direction)`.
|
53
|
-
#
|
54
|
-
# @param collection [ActiveRecord::Relation]
|
55
|
-
# @param column [String, Symbol]
|
56
|
-
# @return [true, false]
|
57
|
-
def supports?(collection, column)
|
58
|
-
scope_for(collection).respond_to?(:"order_by_#{column}") ||
|
59
|
-
model_for(collection).has_attribute?(column.to_s)
|
60
|
-
end
|
61
|
-
|
62
|
-
# Returns the current sort behaviour of the given column, for use as a
|
63
|
-
# column heading class in the table view.
|
64
|
-
#
|
65
|
-
# @param column [String, Symbol] the table column as defined in table_with
|
66
|
-
# @return [String] the current sort behaviour of the given column
|
67
|
-
def status(column)
|
68
|
-
direction if column.to_s == self.column
|
69
|
-
end
|
70
|
-
|
71
|
-
# Calculates the sort parameter to apply when the given column is toggled.
|
72
|
-
#
|
73
|
-
# @param column [String, Symbol]
|
74
|
-
# @return [String]
|
75
|
-
def toggle(column)
|
76
|
-
return "#{column} asc" unless column.to_s == self.column
|
77
|
-
|
78
|
-
case direction
|
79
|
-
when "asc"
|
80
|
-
"#{column} desc"
|
81
|
-
when "desc"
|
82
|
-
"#{column} asc"
|
83
|
-
end
|
84
|
-
end
|
85
|
-
|
86
|
-
# Apply the constructed sort ordering to the collection.
|
87
|
-
#
|
88
|
-
# @param collection [ActiveRecord::Relation]
|
89
|
-
# @return [Array(SortForm, ActiveRecord::Relation)]
|
90
|
-
def apply(collection)
|
91
|
-
return [self, collection] if column.nil?
|
92
|
-
|
93
|
-
if collection.respond_to?(:"order_by_#{column}")
|
94
|
-
collection = collection.reorder(nil).public_send(:"order_by_#{column}", direction.to_sym)
|
95
|
-
elsif collection.model.has_attribute?(column)
|
96
|
-
collection = collection.reorder(column => direction)
|
97
|
-
else
|
98
|
-
clear!
|
99
|
-
end
|
100
|
-
|
101
|
-
[self, collection]
|
102
|
-
end
|
103
|
-
|
104
|
-
private
|
105
|
-
|
106
|
-
def clear!
|
107
|
-
self.column = self.direction = nil
|
108
|
-
end
|
109
|
-
|
110
|
-
def scope_for(collection)
|
111
|
-
collection.is_a?(Core) ? collection.items : collection
|
112
|
-
end
|
113
|
-
|
114
|
-
def model_for(collection)
|
115
|
-
scope_for(collection).model
|
116
|
-
end
|
117
|
-
end
|
118
|
-
end
|
119
|
-
end
|
120
|
-
end
|