katalyst-tables 3.0.0.beta1 → 3.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|