katalyst-tables 3.0.0.beta1 → 3.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (82) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +16 -2
  3. data/README.md +65 -187
  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/_summary.scss +14 -0
  10. data/app/assets/stylesheets/katalyst/tables/typed-columns/_boolean.scss +1 -1
  11. data/app/assets/stylesheets/katalyst/tables/typed-columns/_currency.scss +3 -0
  12. data/app/assets/stylesheets/katalyst/tables/typed-columns/_date.scss +1 -1
  13. data/app/assets/stylesheets/katalyst/tables/typed-columns/_datetime.scss +1 -1
  14. data/app/assets/stylesheets/katalyst/tables/typed-columns/_number.scss +3 -0
  15. data/app/components/concerns/katalyst/tables/has_table_content.rb +19 -10
  16. data/app/components/concerns/katalyst/tables/identifiable.rb +51 -0
  17. data/app/components/concerns/katalyst/tables/orderable.rb +35 -105
  18. data/app/components/concerns/katalyst/tables/row_renderer.rb +1 -1
  19. data/app/components/concerns/katalyst/tables/selectable.rb +18 -75
  20. data/app/components/concerns/katalyst/tables/sortable.rb +51 -17
  21. data/app/components/katalyst/summary_table_component.html.erb +15 -0
  22. data/app/components/katalyst/summary_table_component.rb +44 -0
  23. data/app/components/katalyst/table_component.html.erb +4 -4
  24. data/app/components/katalyst/table_component.rb +271 -53
  25. data/app/components/katalyst/tables/body_row_component.html.erb +5 -0
  26. data/app/components/katalyst/tables/body_row_component.rb +4 -31
  27. data/app/components/katalyst/tables/cell_component.rb +85 -0
  28. data/app/components/katalyst/tables/{body → cells}/boolean_component.rb +8 -2
  29. data/app/components/katalyst/tables/{body → cells}/currency_component.rb +7 -7
  30. data/app/components/katalyst/tables/{body → cells}/date_component.rb +12 -9
  31. data/app/components/katalyst/tables/{body → cells}/date_time_component.rb +13 -10
  32. data/app/components/katalyst/tables/{body → cells}/number_component.rb +5 -5
  33. data/app/components/katalyst/tables/cells/ordinal_component.rb +44 -0
  34. data/app/components/katalyst/tables/{body → cells}/rich_text_component.rb +8 -5
  35. data/app/components/katalyst/tables/cells/select_component.rb +39 -0
  36. data/app/components/katalyst/tables/data.rb +30 -0
  37. data/app/components/katalyst/tables/header_row_component.html.erb +5 -0
  38. data/app/components/katalyst/tables/header_row_component.rb +4 -25
  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 +3 -3
  42. data/app/components/katalyst/tables/selectable/form_component.rb +8 -11
  43. data/app/components/katalyst/tables/summary/body_component.html.erb +3 -0
  44. data/app/components/katalyst/tables/summary/body_component.rb +10 -0
  45. data/app/components/katalyst/tables/summary/header_component.html.erb +3 -0
  46. data/app/components/katalyst/tables/summary/header_component.rb +10 -0
  47. data/app/components/katalyst/tables/summary/row_component.html.erb +4 -0
  48. data/app/components/katalyst/tables/summary/row_component.rb +12 -0
  49. data/app/controllers/concerns/katalyst/tables/backend.rb +17 -28
  50. data/app/helpers/katalyst/tables/frontend.rb +67 -2
  51. data/app/javascript/tables/application.js +0 -5
  52. data/app/javascript/tables/orderable/form_controller.js +8 -6
  53. data/app/javascript/tables/orderable/item_controller.js +9 -0
  54. data/app/models/concerns/katalyst/tables/collection/core.rb +6 -1
  55. data/app/models/concerns/katalyst/tables/collection/pagination.rb +2 -2
  56. data/app/models/concerns/katalyst/tables/collection/sorting.rb +86 -18
  57. data/app/models/katalyst/tables/collection/array.rb +38 -0
  58. data/app/models/katalyst/tables/collection/base.rb +4 -0
  59. data/app/models/katalyst/tables/collection/filter.rb +2 -2
  60. data/config/importmap.rb +1 -0
  61. data/config/locales/tables.en.yml +0 -6
  62. data/lib/katalyst/tables/config.rb +23 -0
  63. data/lib/katalyst/tables.rb +9 -0
  64. metadata +32 -30
  65. data/app/components/concerns/katalyst/tables/body/typed_columns.rb +0 -132
  66. data/app/components/concerns/katalyst/tables/configurable_component.rb +0 -52
  67. data/app/components/concerns/katalyst/tables/header/typed_columns.rb +0 -179
  68. data/app/components/katalyst/tables/body/attachment_component.rb +0 -58
  69. data/app/components/katalyst/tables/body/link_component.rb +0 -40
  70. data/app/components/katalyst/tables/body_cell_component.rb +0 -55
  71. data/app/components/katalyst/tables/header/attachment_component.rb +0 -15
  72. data/app/components/katalyst/tables/header/boolean_component.rb +0 -15
  73. data/app/components/katalyst/tables/header/currency_component.rb +0 -15
  74. data/app/components/katalyst/tables/header/date_component.rb +0 -15
  75. data/app/components/katalyst/tables/header/date_time_component.rb +0 -15
  76. data/app/components/katalyst/tables/header/link_component.rb +0 -15
  77. data/app/components/katalyst/tables/header/number_component.rb +0 -15
  78. data/app/components/katalyst/tables/header/rich_text_component.rb +0 -15
  79. data/app/components/katalyst/tables/header_cell_component.rb +0 -97
  80. data/app/helpers/katalyst/tables/frontend/helper.rb +0 -31
  81. data/app/javascript/tables/turbo/collection_controller.js +0 -38
  82. data/app/models/katalyst/tables/collection/sort_form.rb +0 -120
@@ -1,13 +1,15 @@
1
1
  import { Controller } from "@hotwired/stimulus";
2
2
 
3
3
  export default class OrderableFormController extends Controller {
4
+ static values = { scope: String };
5
+
4
6
  add(item) {
5
- const { id_name, id_value, index_name } = item.paramsValue;
6
- this.element.insertAdjacentHTML(
7
- "beforeend",
8
- `<input type="hidden" name="${id_name}" value="${id_value}" data-generated>
9
- <input type="hidden" name="${index_name}" value="${item.index}" data-generated>`,
10
- );
7
+ item.params(this.scopeValue).forEach(({ name, value }) => {
8
+ this.element.insertAdjacentHTML(
9
+ "beforeend",
10
+ `<input type="hidden" name="${name}" value="${value}" data-generated>`,
11
+ );
12
+ });
11
13
  }
12
14
 
13
15
  submit() {
@@ -48,6 +48,15 @@ export default class OrderableRowController extends Controller {
48
48
  this.index = index;
49
49
  }
50
50
 
51
+ /** Retrieve params for use in the form */
52
+ params(scope) {
53
+ const { id_name, id_value, index_name } = this.paramsValue;
54
+ return [
55
+ { name: `${scope}[${id_value}][${id_name}]`, value: this.id },
56
+ { name: `${scope}[${id_value}][${index_name}]`, value: this.index },
57
+ ];
58
+ }
59
+
51
60
  /**
52
61
  * Restore any visual changes made during drag and remove the drag state.
53
62
  */
@@ -18,7 +18,7 @@ module Katalyst
18
18
  def permitted_params
19
19
  _default_attributes.to_h.each_with_object([]) do |(k, v), h|
20
20
  h << case v
21
- when Array
21
+ when ::Array
22
22
  { k => [] }
23
23
  else
24
24
  k
@@ -39,6 +39,11 @@ module Katalyst
39
39
  clear_changes_information
40
40
  end
41
41
 
42
+ # Collections that do not include Sorting are never sortable.
43
+ def sortable?
44
+ false
45
+ end
46
+
42
47
  def apply(items)
43
48
  @items = items
44
49
  reducers.build do |_|
@@ -24,8 +24,8 @@ module Katalyst
24
24
  config_accessor :paginate
25
25
  end
26
26
 
27
- def initialize(paginate: config.paginate, **options)
28
- super(**options)
27
+ def initialize(paginate: config.paginate, **)
28
+ super(**)
29
29
 
30
30
  @paginate = paginate.freeze
31
31
  end
@@ -14,27 +14,88 @@ module Katalyst
14
14
  module Sorting
15
15
  extend ActiveSupport::Concern
16
16
 
17
- included do
18
- config_accessor :sorting
19
- attr_accessor :sorting
17
+ DIRECTIONS = %w[asc desc].freeze
18
+
19
+ module SortParams
20
+ refine Hash do
21
+ def to_param
22
+ "#{self[:column]} #{self[:direction]}"
23
+ end
24
+ end
25
+
26
+ refine String do
27
+ def to_param
28
+ to_h.to_param
29
+ end
20
30
 
31
+ def to_h
32
+ column, direction = split(/[ +]/, 2)
33
+
34
+ direction = "asc" unless DIRECTIONS.include?(direction)
35
+ { column:, direction: }
36
+ end
37
+ end
38
+ end
39
+
40
+ using SortParams
41
+
42
+ included do
21
43
  attribute :sort, :string
44
+
45
+ attr_reader :default_sort
22
46
  end
23
47
 
24
- def initialize(sorting: config.sorting, **options)
25
- @sorting = SortForm.parse(sorting, default: sorting) if sorting
48
+ def initialize(sorting: config.sorting, **)
49
+ @default_sort = sorting.to_param if sorting.present?
50
+
51
+ super(sort: @default_sort, **) # set default sort based on config
52
+ end
26
53
 
27
- super(sort: @sorting.to_param, **options) # set default sort based on config
54
+ def default_sort?
55
+ sort == @default_sort
28
56
  end
29
57
 
58
+ # Returns true if the collection supports sorting on the given column.
59
+ # A column supports sorting if it is a database column or if
60
+ # the collection responds to `order_by_#{column}(direction)`.
61
+ #
62
+ # @param column [String, Symbol]
63
+ # @return [true, false]
64
+ def sortable?(column = nil)
65
+ if column.nil?
66
+ @default_sort.present?
67
+ else
68
+ items.respond_to?(:"order_by_#{column}") || items.model.has_attribute?(column.to_s)
69
+ end
70
+ end
71
+
72
+ # Set the current sort behaviour of the collection.
73
+ #
74
+ # @param value [String, Hash] "column direction", or { column:, direction: }
30
75
  def sort=(value)
31
- return unless @sorting
76
+ super(value.to_param) if @default_sort
77
+ end
78
+
79
+ # Returns the current sort behaviour of the given column, for use as a
80
+ # column heading class in the table view.
81
+ #
82
+ # @param column [String, Symbol] the table column as defined in table_with
83
+ # @return [String] the current sort behaviour of the given column
84
+ def sort_status(column)
85
+ current, direction = sort.to_h.values_at(:column, :direction)
86
+ direction if column.to_s == current
87
+ end
32
88
 
33
- # update internal proxy
34
- @sorting = SortForm.parse(value, default: @sorting.default)
89
+ # Calculates the sort parameter to apply when the given column is toggled.
90
+ #
91
+ # @param column [String, Symbol]
92
+ # @return [String]
93
+ def toggle_sort(column)
94
+ current, direction = sort.to_h.values_at(:column, :direction)
35
95
 
36
- # update attribute based on normalized value
37
- super(@sorting.to_param)
96
+ return "#{column} asc" unless column.to_s == current
97
+
98
+ direction == "asc" ? "#{column} desc" : "#{column} asc"
38
99
  end
39
100
 
40
101
  class Sort # :nodoc:
@@ -44,15 +105,22 @@ module Katalyst
44
105
  @app = app
45
106
  end
46
107
 
108
+ using SortParams
109
+
47
110
  def call(collection)
48
- @collection = @app.call(collection)
49
- @collection.sorting, @collection.items = @collection.sorting.apply(@collection.items) if @collection.sorting
50
- @collection
51
- end
111
+ collection = @app.call(collection)
112
+
113
+ column, direction = collection.sort.to_h.values_at(:column, :direction)
114
+
115
+ return collection if column.nil?
116
+
117
+ if collection.items.respond_to?(:"order_by_#{column}")
118
+ collection.items = collection.items.reorder(nil).public_send(:"order_by_#{column}", direction.to_sym)
119
+ elsif collection.items.model.has_attribute?(column)
120
+ collection.items = collection.items.reorder(column => direction)
121
+ end
52
122
 
53
- # pagy shim
54
- def params
55
- @collection.attributes
123
+ collection
56
124
  end
57
125
  end
58
126
  end
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Katalyst
4
+ module Tables
5
+ module Collection
6
+ # Entry point for creating a collection from an array for use with table components.
7
+ class Array
8
+ include Core
9
+ include Filtering
10
+
11
+ def self.with_params(params)
12
+ new.with_params(params)
13
+ end
14
+
15
+ def model
16
+ items.first&.class || ActiveRecord::Base
17
+ end
18
+
19
+ def model_name
20
+ @model_name ||= items.first&.model_name || ActiveModel::Name.new(Object, nil, "record")
21
+ end
22
+
23
+ def with_params(params)
24
+ # test support
25
+ params = ActionController::Parameters.new(params) unless params.is_a?(ActionController::Parameters)
26
+
27
+ self.attributes = params.permit(self.class.permitted_params)
28
+
29
+ self
30
+ end
31
+
32
+ def inspect
33
+ "#<#{self.class.name} @attributes=#{attributes.inspect} @model_name=\"#{model_name}\" @count=#{items&.count}>"
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -34,6 +34,10 @@ module Katalyst
34
34
  new.with_params(params)
35
35
  end
36
36
 
37
+ def model
38
+ items.model
39
+ end
40
+
37
41
  def model_name
38
42
  @model_name ||= items.model_name.dup.tap do |name|
39
43
  name.param_key = ""
@@ -40,8 +40,8 @@ module Katalyst
40
40
 
41
41
  attr_reader :param_key
42
42
 
43
- def initialize(param_key: :filters, **options)
44
- super(**options)
43
+ def initialize(param_key: :filters, **)
44
+ super(**)
45
45
 
46
46
  @param_key = param_key.to_sym
47
47
  end
data/config/importmap.rb CHANGED
@@ -1,2 +1,3 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  pin "@katalyst/tables", to: "katalyst/tables.js"
@@ -1,10 +1,4 @@
1
1
  en:
2
- time:
3
- formats:
4
- table: "%e %B %Y, %l:%M%P"
5
- date:
6
- formats:
7
- table: "%e %B %Y"
8
2
  katalyst:
9
3
  tables:
10
4
  orderable:
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/configurable"
4
+
5
+ module Katalyst
6
+ module Tables
7
+ class Config
8
+ include ActiveSupport::Configurable
9
+
10
+ config_accessor(:component_extensions) do
11
+ %w[
12
+ Katalyst::Tables::Identifiable
13
+ Katalyst::Tables::Orderable
14
+ Katalyst::Tables::Selectable
15
+ Katalyst::Tables::Sortable
16
+ ]
17
+ end
18
+
19
+ config_accessor(:date_format) { :default }
20
+ config_accessor(:datetime_format) { :default }
21
+ end
22
+ end
23
+ end
@@ -3,10 +3,19 @@
3
3
  require "view_component"
4
4
  require "katalyst/html_attributes"
5
5
 
6
+ require_relative "tables/config"
6
7
  require_relative "tables/engine"
7
8
 
8
9
  module Katalyst
9
10
  module Tables
10
11
  class Error < StandardError; end
12
+
13
+ def self.config
14
+ @config ||= Config.new
15
+ end
16
+
17
+ def self.configure
18
+ yield config
19
+ end
11
20
  end
12
21
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: katalyst-tables
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.0.0.beta1
4
+ version: 3.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Katalyst Interactive
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-05-03 00:00:00.000000000 Z
11
+ date: 2024-06-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: katalyst-html-attributes
@@ -56,6 +56,7 @@ files:
56
56
  - app/assets/config/katalyst-tables.js
57
57
  - app/assets/stylesheets/katalyst/tables/_index.scss
58
58
  - app/assets/stylesheets/katalyst/tables/_ordinal.scss
59
+ - app/assets/stylesheets/katalyst/tables/_summary.scss
59
60
  - app/assets/stylesheets/katalyst/tables/_table.scss
60
61
  - app/assets/stylesheets/katalyst/tables/typed-columns/_boolean.scss
61
62
  - app/assets/stylesheets/katalyst/tables/typed-columns/_currency.scss
@@ -63,63 +64,64 @@ files:
63
64
  - app/assets/stylesheets/katalyst/tables/typed-columns/_datetime.scss
64
65
  - app/assets/stylesheets/katalyst/tables/typed-columns/_index.scss
65
66
  - app/assets/stylesheets/katalyst/tables/typed-columns/_number.scss
66
- - app/components/concerns/katalyst/tables/body/typed_columns.rb
67
- - app/components/concerns/katalyst/tables/configurable_component.rb
68
67
  - app/components/concerns/katalyst/tables/has_table_content.rb
69
- - app/components/concerns/katalyst/tables/header/typed_columns.rb
68
+ - app/components/concerns/katalyst/tables/identifiable.rb
70
69
  - app/components/concerns/katalyst/tables/orderable.rb
71
70
  - app/components/concerns/katalyst/tables/row_renderer.rb
72
71
  - app/components/concerns/katalyst/tables/selectable.rb
73
72
  - app/components/concerns/katalyst/tables/sortable.rb
73
+ - app/components/katalyst/summary_table_component.html.erb
74
+ - app/components/katalyst/summary_table_component.rb
74
75
  - app/components/katalyst/table_component.html.erb
75
76
  - app/components/katalyst/table_component.rb
76
- - app/components/katalyst/tables/body/attachment_component.rb
77
- - app/components/katalyst/tables/body/boolean_component.rb
78
- - app/components/katalyst/tables/body/currency_component.rb
79
- - app/components/katalyst/tables/body/date_component.rb
80
- - app/components/katalyst/tables/body/date_time_component.rb
81
- - app/components/katalyst/tables/body/link_component.rb
82
- - app/components/katalyst/tables/body/number_component.rb
83
- - app/components/katalyst/tables/body/rich_text_component.rb
84
- - app/components/katalyst/tables/body_cell_component.rb
77
+ - app/components/katalyst/tables/body_row_component.html.erb
85
78
  - app/components/katalyst/tables/body_row_component.rb
79
+ - app/components/katalyst/tables/cell_component.rb
80
+ - app/components/katalyst/tables/cells/boolean_component.rb
81
+ - app/components/katalyst/tables/cells/currency_component.rb
82
+ - app/components/katalyst/tables/cells/date_component.rb
83
+ - app/components/katalyst/tables/cells/date_time_component.rb
84
+ - app/components/katalyst/tables/cells/number_component.rb
85
+ - app/components/katalyst/tables/cells/ordinal_component.rb
86
+ - app/components/katalyst/tables/cells/rich_text_component.rb
87
+ - app/components/katalyst/tables/cells/select_component.rb
88
+ - app/components/katalyst/tables/data.rb
86
89
  - app/components/katalyst/tables/empty_caption_component.html.erb
87
90
  - app/components/katalyst/tables/empty_caption_component.rb
88
- - app/components/katalyst/tables/header/attachment_component.rb
89
- - app/components/katalyst/tables/header/boolean_component.rb
90
- - app/components/katalyst/tables/header/currency_component.rb
91
- - app/components/katalyst/tables/header/date_component.rb
92
- - app/components/katalyst/tables/header/date_time_component.rb
93
- - app/components/katalyst/tables/header/link_component.rb
94
- - app/components/katalyst/tables/header/number_component.rb
95
- - app/components/katalyst/tables/header/rich_text_component.rb
96
- - app/components/katalyst/tables/header_cell_component.rb
91
+ - app/components/katalyst/tables/header_row_component.html.erb
97
92
  - app/components/katalyst/tables/header_row_component.rb
93
+ - app/components/katalyst/tables/label.rb
94
+ - app/components/katalyst/tables/orderable/form_component.rb
98
95
  - app/components/katalyst/tables/pagy_nav_component.rb
99
96
  - app/components/katalyst/tables/selectable/form_component.html.erb
100
97
  - app/components/katalyst/tables/selectable/form_component.rb
98
+ - app/components/katalyst/tables/summary/body_component.html.erb
99
+ - app/components/katalyst/tables/summary/body_component.rb
100
+ - app/components/katalyst/tables/summary/header_component.html.erb
101
+ - app/components/katalyst/tables/summary/header_component.rb
102
+ - app/components/katalyst/tables/summary/row_component.html.erb
103
+ - app/components/katalyst/tables/summary/row_component.rb
101
104
  - app/controllers/concerns/katalyst/tables/backend.rb
102
105
  - app/helpers/katalyst/tables/frontend.rb
103
- - app/helpers/katalyst/tables/frontend/helper.rb
104
106
  - app/javascript/tables/application.js
105
107
  - app/javascript/tables/orderable/form_controller.js
106
108
  - app/javascript/tables/orderable/item_controller.js
107
109
  - app/javascript/tables/orderable/list_controller.js
108
110
  - app/javascript/tables/selection/form_controller.js
109
111
  - app/javascript/tables/selection/item_controller.js
110
- - app/javascript/tables/turbo/collection_controller.js
111
112
  - app/models/concerns/katalyst/tables/collection/core.rb
112
113
  - app/models/concerns/katalyst/tables/collection/filtering.rb
113
114
  - app/models/concerns/katalyst/tables/collection/has_params.rb
114
115
  - app/models/concerns/katalyst/tables/collection/pagination.rb
115
116
  - app/models/concerns/katalyst/tables/collection/reducers.rb
116
117
  - app/models/concerns/katalyst/tables/collection/sorting.rb
118
+ - app/models/katalyst/tables/collection/array.rb
117
119
  - app/models/katalyst/tables/collection/base.rb
118
120
  - app/models/katalyst/tables/collection/filter.rb
119
- - app/models/katalyst/tables/collection/sort_form.rb
120
121
  - config/importmap.rb
121
122
  - config/locales/tables.en.yml
122
123
  - lib/katalyst/tables.rb
124
+ - lib/katalyst/tables/config.rb
123
125
  - lib/katalyst/tables/engine.rb
124
126
  homepage: https://github.com/katalyst/tables
125
127
  licenses:
@@ -130,7 +132,7 @@ metadata:
130
132
  homepage_uri: https://github.com/katalyst/tables
131
133
  source_code_uri: https://github.com/katalyst/tables
132
134
  changelog_uri: https://github.com/katalyst/tables/blobs/main/CHANGELOG.md
133
- post_install_message:
135
+ post_install_message:
134
136
  rdoc_options: []
135
137
  require_paths:
136
138
  - lib
@@ -138,7 +140,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
138
140
  requirements:
139
141
  - - ">="
140
142
  - !ruby/object:Gem::Version
141
- version: 3.2.0
143
+ version: 3.3.0
142
144
  required_rubygems_version: !ruby/object:Gem::Requirement
143
145
  requirements:
144
146
  - - ">="
@@ -146,7 +148,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
146
148
  version: '0'
147
149
  requirements: []
148
150
  rubygems_version: 3.5.9
149
- signing_key:
151
+ signing_key:
150
152
  specification_version: 4
151
153
  summary: HTML table generator for Rails views
152
154
  test_files: []
@@ -1,132 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Katalyst
4
- module Tables
5
- module Body
6
- module TypedColumns
7
- extend ActiveSupport::Concern
8
-
9
- # Generates a column from boolean values rendered as "Yes" or "No".
10
- #
11
- # @param method [Symbol] the method to call on the record
12
- # @param attributes [Hash] HTML attributes to be added to the cell
13
- # @param block [Proc] optional block to alter the cell content
14
- # @return [void]
15
- #
16
- # @example Render a boolean column indicating whether the record is active
17
- # <% row.boolean :active %> # => <td>Yes</td>
18
- def boolean(method, **attributes, &)
19
- with_column(Body::BooleanComponent.new(@table, @record, method, **attributes), &)
20
- end
21
-
22
- # Generates a column from date values rendered using I18n.l.
23
- # The default format is :admin, but it can be overridden.
24
- #
25
- # @param method [Symbol] the method to call on the record
26
- # @param format [Symbol] the I18n date format to use when rendering
27
- # @param attributes [Hash] HTML attributes to be added to the cell tag
28
- # @param block [Proc] optional block to alter the cell content
29
- # @return [void]
30
- #
31
- # @example Render a date column describing when the record was created
32
- # <% row.date :created_at %> # => <td>29 Feb 2024</td>
33
- def date(method, format: :table, **attributes, &)
34
- with_column(Body::DateComponent.new(@table, @record, method, format:, **attributes), &)
35
- end
36
-
37
- # Generates a column from datetime values rendered using I18n.l.
38
- # The default format is :admin, but it can be overridden.
39
- #
40
- # @param method [Symbol] the method to call on the record
41
- # @param format [Symbol] the I18n datetime format to use when rendering
42
- # @param attributes [Hash] HTML attributes to be added to the cell tag
43
- # @param block [Proc] optional block to alter the cell content
44
- # @return [void]
45
- #
46
- # @example Render a datetime column describing when the record was created
47
- # <% row.datetime :created_at %> # => <td>29 Feb 2024, 5:00pm</td>
48
- def datetime(method, format: :table, **attributes, &)
49
- with_column(Body::DateTimeComponent.new(@table, @record, method, format:, **attributes), &)
50
- end
51
-
52
- # Generates a column from numeric values formatted appropriately.
53
- #
54
- # @param method [Symbol] the method to call on the record
55
- # @param attributes [Hash] HTML attributes to be added to the cell tag
56
- # @param block [Proc] optional block to alter the cell content
57
- # @return [void]
58
- #
59
- # @example Render the number of comments on a post
60
- # <% row.number :comment_count %> # => <td>0</td>
61
- def number(method, **attributes, &)
62
- with_column(Body::NumberComponent.new(@table, @record, method, **attributes), &)
63
- end
64
-
65
- # Generates a column from numeric values rendered using `number_to_currency`.
66
- #
67
- # @param method [Symbol] the method to call on the record
68
- # @param options [Hash] options to be passed to `number_to_currency`
69
- # @param attributes [Hash] HTML attributes to be added to the cell tag
70
- # @param block [Proc] optional block to alter the cell content
71
- # @return [void]
72
- #
73
- # @example Render a currency column for the price of a product
74
- # <% row.currency :price %> # => <td>$3.50</td>
75
- def currency(method, options: {}, **attributes, &)
76
- with_column(Body::CurrencyComponent.new(@table, @record, method, options:, **attributes), &)
77
- end
78
-
79
- # Generates a column containing HTML markup.
80
- #
81
- # @param method [Symbol] the method to call on the record
82
- # @param attributes [Hash] HTML attributes to be added to the cell tag
83
- # @param block [Proc] optional block to alter the cell content
84
- # @return [void]
85
- #
86
- # @note This method assumes that the method returns HTML-safe content.
87
- # If the content is not HTML-safe, it will be escaped.
88
- #
89
- # @example Render a description column containing HTML markup
90
- # <% row.rich_text :description %> # => <td><em>Emphasis</em></td>
91
- def rich_text(method, **attributes, &)
92
- with_column(Body::RichTextComponent.new(@table, @record, method, **attributes), &)
93
- end
94
-
95
- # Generates a column that links to the record's show page (by default).
96
- #
97
- # @param method [Symbol] the method to call on the record
98
- # @param link [Hash] options to be passed to the link_to helper
99
- # @option opts [Hash, Array, String, Symbol] :url ([:admin, object]) options for url_for,
100
- # or a symbol to be passed to the route helper
101
- # @param attributes [Hash] HTML attributes to be added to the cell tag
102
- # @param block [Proc] optional block to alter the cell content
103
- # @return [void]
104
- #
105
- # @example Render a column containing the record's title, linked to its show page
106
- # <% row.link :title %> # => <td><a href="/admin/post/15">About us</a></td>
107
- # @example Render a column containing the record's title, linked to its edit page
108
- # <% row.link :title, url: :edit_admin_post_path do |cell| %>
109
- # Edit <%= cell %>
110
- # <% end %>
111
- # # => <td><a href="/admin/post/15/edit">Edit About us</a></td>
112
- def link(method, url: @record, link: {}, **attributes, &)
113
- with_column(Body::LinkComponent.new(@table, @record, method, url:, link:, **attributes), &)
114
- end
115
-
116
- # Generates a column that renders an ActiveStorage attachment as a downloadable link.
117
- #
118
- # @param method [Symbol] the method to call on the record
119
- # @param variant [Symbol] the variant to use when rendering the image (default :thumb)
120
- # @param attributes [Hash] HTML attributes to be added to the cell tag
121
- # @param block [Proc] optional block to alter the cell content
122
- # @return [void]
123
- #
124
- # @example Render a column containing a download link to the record's background image
125
- # <% row.attachment :background %> # => <td><a href="...">background.png</a></td>
126
- def attachment(method, variant: :thumb, **attributes, &)
127
- with_column(Body::AttachmentComponent.new(@table, @record, method, variant:, **attributes), &)
128
- end
129
- end
130
- end
131
- end
132
- end
@@ -1,52 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Katalyst
4
- module Tables
5
- module ConfigurableComponent # :nodoc:
6
- extend ActiveSupport::Concern
7
-
8
- include ActiveSupport::Configurable
9
-
10
- included do
11
- # Workaround: ViewComponent::Base.config is incompatible with ActiveSupport::Configurable
12
- @_config = Class.new(ActiveSupport::Configurable::Configuration).new
13
- end
14
-
15
- class_methods do
16
- # Define a configurable sub-component.
17
- # Sub-components are cached on the table instance. We want to allow run
18
- # time mixins for tables so that we can extend tables with cross-cutting
19
- # concerns that affect multiple sub-components by including the concern
20
- # into the top-level table class. We achieve this by subclassing the
21
- # component as soon as it is created so that when a mixin is added to
22
- # the table class, it can immediately retrieve and modify the
23
- # sub-component class as well without needing to worry about affecting
24
- # other tables.
25
- def config_component(name, component_name: "#{name}_component", default: nil) # rubocop:disable Metrics/MethodLength
26
- config_accessor(name)
27
- config.public_send(:"#{name}=", default)
28
- define_method(component_name) do
29
- return instance_variable_get(:"@#{component_name}") if instance_variable_defined?(:"@#{component_name}")
30
-
31
- klass = config.public_send(name)
32
- component = klass ? self.class.const_get(klass) : nil
33
-
34
- # subclass to allow table-specific extensions
35
- if component
36
- component = Class.new(component)
37
- component.extend(HiddenSubcomponent)
38
- end
39
-
40
- instance_variable_set(:"@#{component_name}", component) if component
41
- end
42
- end
43
- end
44
-
45
- # View Component uses `name` to resolve the template path, so we need to
46
- # hide the subclass from the template resolver.
47
- module HiddenSubcomponent
48
- delegate :name, to: :superclass
49
- end
50
- end
51
- end
52
- end