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.
Files changed (64) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +16 -1
  3. data/README.md +57 -213
  4. data/app/assets/builds/katalyst/tables.esm.js +17 -47
  5. data/app/assets/builds/katalyst/tables.js +17 -47
  6. data/app/assets/builds/katalyst/tables.min.js +1 -1
  7. data/app/assets/builds/katalyst/tables.min.js.map +1 -1
  8. data/app/assets/stylesheets/katalyst/tables/_index.scss +1 -0
  9. data/app/assets/stylesheets/katalyst/tables/_ordinal.scss +38 -0
  10. data/app/assets/stylesheets/katalyst/tables/_table.scss +123 -0
  11. data/app/assets/stylesheets/katalyst/tables/typed-columns/_boolean.scss +4 -0
  12. data/app/assets/stylesheets/katalyst/tables/typed-columns/_currency.scss +5 -0
  13. data/app/assets/stylesheets/katalyst/tables/typed-columns/_date.scss +4 -0
  14. data/app/assets/stylesheets/katalyst/tables/typed-columns/_datetime.scss +4 -0
  15. data/app/assets/stylesheets/katalyst/tables/typed-columns/_index.scss +5 -0
  16. data/app/assets/stylesheets/katalyst/tables/typed-columns/_number.scss +5 -0
  17. data/app/components/concerns/katalyst/tables/has_table_content.rb +17 -8
  18. data/app/components/concerns/katalyst/tables/identifiable.rb +51 -0
  19. data/app/components/concerns/katalyst/tables/orderable.rb +35 -105
  20. data/app/components/concerns/katalyst/tables/selectable.rb +18 -74
  21. data/app/components/concerns/katalyst/tables/sortable.rb +51 -17
  22. data/app/components/katalyst/table_component.html.erb +4 -4
  23. data/app/components/katalyst/table_component.rb +277 -47
  24. data/app/components/katalyst/tables/body_row_component.html.erb +5 -0
  25. data/app/components/katalyst/tables/body_row_component.rb +4 -24
  26. data/app/components/katalyst/tables/cell_component.rb +85 -0
  27. data/app/components/katalyst/tables/cells/boolean_component.rb +20 -0
  28. data/app/components/katalyst/tables/cells/currency_component.rb +29 -0
  29. data/app/components/katalyst/tables/cells/date_component.rb +67 -0
  30. data/app/components/katalyst/tables/cells/date_time_component.rb +60 -0
  31. data/app/components/katalyst/tables/cells/number_component.rb +22 -0
  32. data/app/components/katalyst/tables/cells/ordinal_component.rb +44 -0
  33. data/app/components/katalyst/tables/cells/rich_text_component.rb +21 -0
  34. data/app/components/katalyst/tables/cells/select_component.rb +39 -0
  35. data/app/components/katalyst/tables/data.rb +30 -0
  36. data/app/components/katalyst/tables/empty_caption_component.rb +1 -1
  37. data/app/components/katalyst/tables/header_row_component.html.erb +5 -0
  38. data/app/components/katalyst/tables/header_row_component.rb +4 -24
  39. data/app/components/katalyst/tables/label.rb +37 -0
  40. data/app/components/katalyst/tables/orderable/form_component.rb +38 -0
  41. data/app/components/katalyst/tables/selectable/form_component.html.erb +6 -4
  42. data/app/components/katalyst/tables/selectable/form_component.rb +8 -11
  43. data/app/controllers/concerns/katalyst/tables/backend.rb +2 -28
  44. data/app/helpers/katalyst/tables/frontend.rb +48 -2
  45. data/app/javascript/tables/application.js +0 -5
  46. data/app/javascript/tables/orderable/form_controller.js +8 -6
  47. data/app/javascript/tables/orderable/item_controller.js +9 -0
  48. data/app/models/concerns/katalyst/tables/collection/core.rb +6 -1
  49. data/app/models/concerns/katalyst/tables/collection/pagination.rb +8 -1
  50. data/app/models/concerns/katalyst/tables/collection/sorting.rb +85 -17
  51. data/app/models/katalyst/tables/collection/array.rb +38 -0
  52. data/app/models/katalyst/tables/collection/base.rb +4 -0
  53. data/lib/katalyst/tables/config.rb +23 -0
  54. data/lib/katalyst/tables.rb +9 -0
  55. metadata +32 -15
  56. data/app/components/concerns/katalyst/tables/configurable_component.rb +0 -52
  57. data/app/components/concerns/katalyst/tables/turbo_replaceable.rb +0 -79
  58. data/app/components/katalyst/tables/body_cell_component.rb +0 -47
  59. data/app/components/katalyst/tables/header_cell_component.rb +0 -65
  60. data/app/components/katalyst/turbo/pagy_nav_component.rb +0 -23
  61. data/app/components/katalyst/turbo/table_component.rb +0 -45
  62. data/app/helpers/katalyst/tables/frontend/helper.rb +0 -31
  63. data/app/javascript/tables/turbo/collection_controller.js +0 -38
  64. 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