katalyst-tables 2.6.0 → 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 +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
@@ -1,65 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Katalyst
|
4
|
-
module Tables
|
5
|
-
class HeaderCellComponent < ViewComponent::Base # :nodoc:
|
6
|
-
include Frontend::Helper
|
7
|
-
include Katalyst::HtmlAttributes
|
8
|
-
include Sortable
|
9
|
-
|
10
|
-
delegate :object_name, :collection, :sorting, to: :@table
|
11
|
-
|
12
|
-
def initialize(table, attribute, label: nil, link: {}, **html_attributes)
|
13
|
-
super(**html_attributes)
|
14
|
-
|
15
|
-
@table = table
|
16
|
-
@attribute = attribute
|
17
|
-
@value = label
|
18
|
-
@link_attributes = link
|
19
|
-
end
|
20
|
-
|
21
|
-
def call
|
22
|
-
tag.th(**html_attributes) do
|
23
|
-
if sortable?(@attribute)
|
24
|
-
link_to(value, sort_url(@attribute), **@link_attributes)
|
25
|
-
else
|
26
|
-
value
|
27
|
-
end
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
def value
|
32
|
-
if !@value.nil?
|
33
|
-
@value
|
34
|
-
elsif object_name.present?
|
35
|
-
translation
|
36
|
-
else
|
37
|
-
default_value
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
def translation(key = "activerecord.attributes.#{object_name}.#{@attribute}")
|
42
|
-
translate(key, default: default_value)
|
43
|
-
end
|
44
|
-
|
45
|
-
def default_value
|
46
|
-
@attribute.to_s.humanize.capitalize
|
47
|
-
end
|
48
|
-
|
49
|
-
def inspect
|
50
|
-
"#<#{self.class.name} attribute: #{@attribute.inspect}, value: #{value.inspect}>"
|
51
|
-
end
|
52
|
-
|
53
|
-
# Backwards compatibility with tables 1.0
|
54
|
-
alias_method :options, :html_attributes=
|
55
|
-
|
56
|
-
private
|
57
|
-
|
58
|
-
def default_html_attributes
|
59
|
-
return {} unless sorting&.supports?(collection, @attribute)
|
60
|
-
|
61
|
-
{ data: { sort: sorting.status(@attribute) } }
|
62
|
-
end
|
63
|
-
end
|
64
|
-
end
|
65
|
-
end
|
@@ -1,23 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Katalyst
|
4
|
-
module Turbo
|
5
|
-
class PagyNavComponent < Tables::PagyNavComponent # :nodoc:
|
6
|
-
include Tables::TurboReplaceable
|
7
|
-
|
8
|
-
def initialize(id:, **options)
|
9
|
-
super(id:, **options)
|
10
|
-
end
|
11
|
-
|
12
|
-
def id
|
13
|
-
pagy_options[:id]
|
14
|
-
end
|
15
|
-
|
16
|
-
private
|
17
|
-
|
18
|
-
def pagy_options
|
19
|
-
super.merge(anchor_string: "data-turbo-stream")
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|
@@ -1,45 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Katalyst
|
4
|
-
module Turbo
|
5
|
-
# Renders a table that uses turbo stream replacement when sorting or
|
6
|
-
# paginating.
|
7
|
-
class TableComponent < ::Katalyst::TableComponent
|
8
|
-
include Tables::TurboReplaceable
|
9
|
-
|
10
|
-
attr_reader :id
|
11
|
-
|
12
|
-
def initialize(collection:, id:, header: true, **options)
|
13
|
-
header = if header.is_a?(Hash)
|
14
|
-
default_header_options.merge(header)
|
15
|
-
elsif header
|
16
|
-
default_header_options
|
17
|
-
end
|
18
|
-
|
19
|
-
@id = id
|
20
|
-
|
21
|
-
super(collection:, header:, id:, **options)
|
22
|
-
end
|
23
|
-
|
24
|
-
private
|
25
|
-
|
26
|
-
def default_html_attributes
|
27
|
-
{
|
28
|
-
data: {
|
29
|
-
controller: "tables--turbo--collection",
|
30
|
-
tables__turbo__collection_query_value: current_query,
|
31
|
-
tables__turbo__collection_sort_value: collection.sort,
|
32
|
-
},
|
33
|
-
}
|
34
|
-
end
|
35
|
-
|
36
|
-
def current_query
|
37
|
-
Rack::Utils.build_nested_query(collection.to_params)
|
38
|
-
end
|
39
|
-
|
40
|
-
def default_header_options
|
41
|
-
{ link: { data: { turbo_stream: "" } } }
|
42
|
-
end
|
43
|
-
end
|
44
|
-
end
|
45
|
-
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,102 +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.parse(param, default: nil)
|
14
|
-
column, direction = param.to_s.split
|
15
|
-
direction = "asc" unless DIRECTIONS.include?(direction)
|
16
|
-
|
17
|
-
default = SortForm.parse(default).to_param if default.present?
|
18
|
-
|
19
|
-
SortForm.new(column:, direction:, default:)
|
20
|
-
end
|
21
|
-
|
22
|
-
def initialize(column: nil, direction: nil, default: nil)
|
23
|
-
self.column = column
|
24
|
-
self.direction = direction
|
25
|
-
self.default = default
|
26
|
-
end
|
27
|
-
|
28
|
-
def to_param
|
29
|
-
"#{column} #{direction}"
|
30
|
-
end
|
31
|
-
|
32
|
-
# Returns true if the given collection supports sorting on the given
|
33
|
-
# column. A column supports sorting if it is a database column or if
|
34
|
-
# the collection responds to `order_by_#{column}(direction)`.
|
35
|
-
#
|
36
|
-
# @param collection [ActiveRecord::Relation]
|
37
|
-
# @param column [String, Symbol]
|
38
|
-
# @return [true, false]
|
39
|
-
def supports?(collection, column)
|
40
|
-
scope_for(collection).respond_to?(:"order_by_#{column}") ||
|
41
|
-
model_for(collection).has_attribute?(column.to_s)
|
42
|
-
end
|
43
|
-
|
44
|
-
# Returns the current sort behaviour of the given column, for use as a
|
45
|
-
# column heading class in the table view.
|
46
|
-
#
|
47
|
-
# @param column [String, Symbol] the table column as defined in table_with
|
48
|
-
# @return [String] the current sort behaviour of the given column
|
49
|
-
def status(column)
|
50
|
-
direction if column.to_s == self.column
|
51
|
-
end
|
52
|
-
|
53
|
-
# Calculates the sort parameter to apply when the given column is toggled.
|
54
|
-
#
|
55
|
-
# @param column [String, Symbol]
|
56
|
-
# @return [String]
|
57
|
-
def toggle(column)
|
58
|
-
return "#{column} asc" unless column.to_s == self.column
|
59
|
-
|
60
|
-
case direction
|
61
|
-
when "asc"
|
62
|
-
"#{column} desc"
|
63
|
-
when "desc"
|
64
|
-
"#{column} asc"
|
65
|
-
end
|
66
|
-
end
|
67
|
-
|
68
|
-
# Apply the constructed sort ordering to the collection.
|
69
|
-
#
|
70
|
-
# @param collection [ActiveRecord::Relation]
|
71
|
-
# @return [Array(SortForm, ActiveRecord::Relation)]
|
72
|
-
def apply(collection)
|
73
|
-
return [self, collection] if column.nil?
|
74
|
-
|
75
|
-
if collection.respond_to?(:"order_by_#{column}")
|
76
|
-
collection = collection.reorder(nil).public_send(:"order_by_#{column}", direction.to_sym)
|
77
|
-
elsif collection.model.has_attribute?(column)
|
78
|
-
collection = collection.reorder(column => direction)
|
79
|
-
else
|
80
|
-
clear!
|
81
|
-
end
|
82
|
-
|
83
|
-
[self, collection]
|
84
|
-
end
|
85
|
-
|
86
|
-
private
|
87
|
-
|
88
|
-
def clear!
|
89
|
-
self.column = self.direction = nil
|
90
|
-
end
|
91
|
-
|
92
|
-
def scope_for(collection)
|
93
|
-
collection.is_a?(Core) ? collection.items : collection
|
94
|
-
end
|
95
|
-
|
96
|
-
def model_for(collection)
|
97
|
-
scope_for(collection).model
|
98
|
-
end
|
99
|
-
end
|
100
|
-
end
|
101
|
-
end
|
102
|
-
end
|