plutonium 0.15.3 → 0.15.5

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.
Files changed (39) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/plutonium.css +1 -1
  3. data/app/views/components/sidebar_menu/sidebar_menu_component.rb +1 -1
  4. data/app/views/components/table_search_input/table_search_input_component.html.erb +3 -3
  5. data/app/views/resource/_resource_table.html.erb +0 -321
  6. data/lib/plutonium/core/controllers/authorizable.rb +5 -0
  7. data/lib/plutonium/core/controllers/entity_scoping.rb +4 -4
  8. data/lib/plutonium/definition/base.rb +8 -0
  9. data/lib/plutonium/definition/defineable_props.rb +1 -1
  10. data/lib/plutonium/definition/presentable.rb +71 -0
  11. data/lib/plutonium/interaction/README.md +1 -1
  12. data/lib/plutonium/interaction/base.rb +6 -6
  13. data/lib/plutonium/lib/deep_freezer.rb +31 -0
  14. data/lib/plutonium/query/adhoc_block.rb +19 -0
  15. data/lib/plutonium/query/base.rb +29 -0
  16. data/lib/plutonium/query/filter.rb +12 -0
  17. data/lib/plutonium/query/filters/text.rb +77 -0
  18. data/lib/plutonium/query/model_scope.rb +19 -0
  19. data/lib/plutonium/resource/controller.rb +14 -7
  20. data/lib/plutonium/resource/controllers/authorizable.rb +1 -1
  21. data/lib/plutonium/resource/controllers/crud_actions/index_action.rb +26 -0
  22. data/lib/plutonium/resource/controllers/crud_actions.rb +2 -5
  23. data/lib/plutonium/resource/controllers/defineable.rb +0 -2
  24. data/lib/plutonium/resource/controllers/queryable.rb +36 -20
  25. data/lib/plutonium/resource/policy.rb +1 -1
  26. data/lib/plutonium/resource/query_object.rb +61 -147
  27. data/lib/plutonium/{refinements/parameter_refinements.rb → support/parameters.rb} +5 -7
  28. data/lib/plutonium/ui/component/methods.rb +1 -1
  29. data/lib/plutonium/ui/display/resource.rb +19 -15
  30. data/lib/plutonium/ui/form/query.rb +171 -0
  31. data/lib/plutonium/ui/form/resource.rb +21 -17
  32. data/lib/plutonium/ui/table/components/scopes_bar.rb +1 -1
  33. data/lib/plutonium/ui/table/components/search_bar.rb +6 -139
  34. data/lib/plutonium/ui/table/resource.rb +10 -9
  35. data/lib/plutonium/version.rb +1 -1
  36. data/package-lock.json +2 -2
  37. data/package.json +1 -1
  38. metadata +12 -4
  39. data/lib/plutonium/interaction/concerns/presentable.rb +0 -73
@@ -0,0 +1,171 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Plutonium
4
+ module UI
5
+ module Form
6
+ class Query < Base
7
+ attr_reader :query_object
8
+
9
+ def initialize(*, query_object:, page_size:, attributes: {}, **options, &)
10
+ options[:as] = :q
11
+ options[:method] = :get
12
+ attributes.deep_merge!(
13
+ id: :search_form,
14
+ class!: "space-y-2 mb-4",
15
+ controller: "form",
16
+ data: {controller: "form", turbo_frame: nil}
17
+ )
18
+ super(*, attributes:, **options, &)
19
+
20
+ @query_object = query_object
21
+ @page_size = page_size
22
+ end
23
+
24
+ def form_template
25
+ render_fields
26
+ end
27
+
28
+ private
29
+
30
+ def render_fields
31
+ render_search_fields
32
+ render_filter_fields
33
+ div hidden: true do # workaround the fact that input array does not accept other attributes for now
34
+ input(name: "limit", value: @page_size, type: :hidden, hidden: true) if @page_size
35
+ render_sort_fields
36
+ render_scope_fields
37
+ end
38
+ end
39
+
40
+ def render_sort_fields
41
+ # q[sort_fields][]=name&q[sort_fields][]=created_at
42
+ field :sort_fields do |name|
43
+ render name.input_array_tag do |array|
44
+ render array.input_tag(type: :hidden, hidden: true)
45
+ end
46
+ end
47
+ # q[sort_directions][created_at]=ASC&q[sort_directions][name]=ASC&
48
+ nest_one :sort_directions do |nested|
49
+ query_object.sort_definitions.each do |filter_name, definition|
50
+ nested.field(filter_name) do |f|
51
+ render f.input_tag(type: :hidden, hidden: true)
52
+ end
53
+ end
54
+ end
55
+ end
56
+
57
+ def render_scope_fields
58
+ # q[scope]=&
59
+ return if query_object.scope_definitions.blank?
60
+
61
+ render field(:scope).input_tag(type: :hidden, hidden: true)
62
+ end
63
+
64
+ def render_search_fields
65
+ # q[search]=&
66
+ return unless query_object.search_filter
67
+
68
+ search_query = query_object.search_query
69
+ div(class: "relative") do
70
+ div(class: "absolute inset-y-0 left-0 flex items-center pl-3 pointer-events-none") do
71
+ svg(
72
+ class: "w-5 h-5 text-gray-500 dark:text-gray-400",
73
+ aria_hidden: "true",
74
+ fill: "currentColor",
75
+ viewbox: "0 0 20 20",
76
+ xmlns: "http://www.w3.org/2000/svg"
77
+ ) do |s|
78
+ s.path(
79
+ fill_rule: "evenodd",
80
+ d:
81
+ "M8 4a4 4 0 100 8 4 4 0 000-8zM2 8a6 6 0 1110.89 3.476l4.817 4.817a1 1 0 01-1.414 1.414l-4.816-4.816A6 6 0 012 8z",
82
+ clip_rule: "evenodd"
83
+ )
84
+ end
85
+ end
86
+ render field(:search, value: search_query)
87
+ .placeholder("Search...")
88
+ .input_tag(
89
+ value: search_query,
90
+ class: "block w-full p-2 pl-10 text-sm text-gray-900 border border-gray-300 rounded-lg bg-gray-50 focus:ring-primary-500 focus:border-primary-500 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-primary-500 dark:focus:border-primary-500",
91
+ data: {
92
+ action: "form#submit",
93
+ turbo_permanent: true
94
+ }
95
+ )
96
+ end
97
+ end
98
+
99
+ def render_filter_fields
100
+ div(class: "flex flex-wrap items-center gap-4") do
101
+ span(class: "text-sm font-medium text-gray-900 dark:text-white") { "Filters:" }
102
+ div(class: "flex flex-wrap items-center gap-4 mr-auto") do
103
+ div class: "flex flex-wrap items-center gap-4" do
104
+ query_object.filter_definitions.each do |filter_name, definition|
105
+ nest_one filter_name do |nested|
106
+ definition.defined_inputs.each do |input_name, _|
107
+ render_defined_field nested, definition, input_name
108
+ end
109
+ end
110
+ end
111
+ end
112
+ end
113
+ div(class: "flex flex-wrap items-center gap-2") do
114
+ actions_wrapper do
115
+ render field(:submit).submit_button_tag(
116
+ name: nil,
117
+ class!: "inline-flex items-center text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:ring-blue-300 font-medium rounded-lg text-sm px-4 py-2 dark:bg-blue-600 dark:hover:bg-blue-700 focus:outline-none dark:focus:ring-blue-800"
118
+ ) do
119
+ render Phlex::TablerIcons::Filter.new(class: "w-4 h-4 mr-2")
120
+ plain "Apply Filters"
121
+ end
122
+
123
+ render field(:reset).submit_button_tag(
124
+ name: nil,
125
+ type: :reset,
126
+ class!: "inline-flex items-center text-gray-900 bg-white border border-gray-300 focus:outline-none hover:bg-gray-100 focus:ring-4 focus:ring-gray-200 font-medium rounded-lg text-sm px-4 py-2 dark:bg-gray-800 dark:text-white dark:border-gray-600 dark:hover:bg-gray-700 dark:hover:border-gray-600 dark:focus:ring-gray-700"
127
+ ) do
128
+ render Phlex::TablerIcons::X.new(class: "w-4 h-4 mr-2")
129
+ plain "Clear Filters"
130
+ end
131
+ end
132
+ end
133
+ end
134
+ end
135
+
136
+ def form_action
137
+ # query forms post to the same page
138
+ nil
139
+ end
140
+
141
+ def render_defined_field(nested, resource_definition, name)
142
+ # field :name, as: :string
143
+ # input :name, as: :string
144
+ # input :description, class: "col-span-full"
145
+ # input :age, tag: {class: "max-h-fit"}
146
+ # input :dob do |f|
147
+ # f.date_tag
148
+ # end
149
+
150
+ field_options = resource_definition.defined_fields[name] ? resource_definition.defined_fields[name][:options] : {}
151
+
152
+ input_definition = resource_definition.defined_inputs[name] || {}
153
+ input_options = input_definition[:options] || {}
154
+
155
+ tag = field_options[:as] || input_options[:as]
156
+ tag_attributes = input_options[:tag] || {}
157
+ tag_block = input_definition[:block] || ->(f) {
158
+ tag ||= f.inferred_field_component
159
+ f.send(:"#{tag}_tag", **tag_attributes, class: tokens(tag_attributes[:class], "flex-1"))
160
+ }
161
+
162
+ field_options = field_options.except(:as)
163
+ nested.field(name, **field_options) do |f|
164
+ f.placeholder(f.label) unless f.placeholder
165
+ render tag_block.call(f)
166
+ end
167
+ end
168
+ end
169
+ end
170
+ end
171
+ end
@@ -34,32 +34,36 @@ module Plutonium
34
34
  end
35
35
 
36
36
  def render_resource_field(name)
37
- # input :name, as: :string
38
- # input :description, class: "col-span-full"
39
- # input :age, field: {class: "max-h-fit"}
40
- # input :dob do |f|
41
- # f.date_tag
42
- # end
43
-
44
37
  when_permitted(name) do
38
+ # field :name, as: :string
39
+ # input :name, as: :string
40
+ # input :description, class: "col-span-full"
41
+ # input :age, tag: {class: "max-h-fit"}
42
+ # input :dob do |f|
43
+ # f.date_tag
44
+ # end
45
+
46
+ field_options = resource_definition.defined_fields[name] ? resource_definition.defined_fields[name][:options] : {}
47
+
45
48
  input_definition = resource_definition.defined_inputs[name] || {}
46
49
  input_options = input_definition[:options] || {}
47
- input_field_as = input_options.delete(:as)
48
50
 
49
- input_field_options = input_options.delete(:field) || {}
50
- input_block = input_definition[:block] || ->(f) {
51
- input_field_as ||= f.inferred_field_component
52
- f.send(:"#{input_field_as}_tag", **input_field_options)
51
+ tag = field_options[:as] || input_options[:as]
52
+ tag_attributes = input_options[:tag] || {}
53
+ tag_block = input_definition[:block] || ->(f) {
54
+ tag ||= f.inferred_field_component
55
+ f.send(:"#{tag}_tag", **tag_attributes)
53
56
  }
54
57
 
55
- field_options = resource_definition.defined_fields[name] ? resource_definition.defined_fields[name][:options] : {}
56
- if !input_options[:class] || !input_options[:class].include?("col-span")
58
+ field_options = field_options.except(:as)
59
+ wrapper_options = input_options.except(:tag, :as)
60
+ if !wrapper_options[:class] || wrapper_options[:class].include?("col-span")
57
61
  # temp hack to allow col span overrides
58
62
  # TODO: remove once we complete theming, which will support merges
59
- input_options[:class] = tokens("col-span-full", input_options[:class])
63
+ wrapper_options[:class] = tokens("col-span-full", wrapper_options[:class])
60
64
  end
61
- render field(name, **field_options).wrapped(**input_options) do |f|
62
- render input_block.call(f)
65
+ render field(name, **field_options).wrapped(**wrapper_options) do |f|
66
+ render tag_block.call(f)
63
67
  end
64
68
  end
65
69
  end
@@ -124,7 +124,7 @@ module Plutonium
124
124
 
125
125
  private
126
126
 
127
- def current_scope = resource_query_params[:scope]
127
+ def current_scope = raw_resource_query_params[:scope]
128
128
 
129
129
  def render?
130
130
  current_query_object.scope_definitions.present?
@@ -6,150 +6,17 @@ module Plutonium
6
6
  module Components
7
7
  class SearchBar < Plutonium::UI::Component::Base
8
8
  def view_template
9
- original_attributes = Phlex::HTML::EVENT_ATTRIBUTES
10
- temp_attributes = Phlex::HTML::EVENT_ATTRIBUTES.dup
11
- temp_attributes.delete("oninput")
12
- temp_attributes.delete("onclick")
13
- Phlex::HTML.const_set(:EVENT_ATTRIBUTES, temp_attributes)
14
-
15
- div(
16
- class:
17
- # "p-4 bg-white border border-gray-200 rounded-lg dark:bg-gray-800 dark:border-gray-700 space-y-2 mb-4"
18
- "space-y-2 mb-4"
19
- ) do
20
- search_query = current_query_object.search_query
21
- query_params = resource_query_params
22
- render Phlexi::Form(:q, attributes: {class!: nil, data: {controller: "form", turbo_frame: nil}}) {
23
- div(class: "relative") do
24
- div(class: "absolute inset-y-0 left-0 flex items-center pl-3 pointer-events-none") do
25
- svg(
26
- class: "w-5 h-5 text-gray-500 dark:text-gray-400",
27
- aria_hidden: "true",
28
- fill: "currentColor",
29
- viewbox: "0 0 20 20",
30
- xmlns: "http://www.w3.org/2000/svg"
31
- ) do |s|
32
- s.path(
33
- fill_rule: "evenodd",
34
- d:
35
- "M8 4a4 4 0 100 8 4 4 0 000-8zM2 8a6 6 0 1110.89 3.476l4.817 4.817a1 1 0 01-1.414 1.414l-4.816-4.816A6 6 0 012 8z",
36
- clip_rule: "evenodd"
37
- )
38
- end
39
- end
40
- render field(:search, value: search_query)
41
- .placeholder("Search...")
42
- .input_tag(
43
- id: "search",
44
- value: search_query,
45
- class: "block w-full p-2 pl-10 text-sm text-gray-900 border border-gray-300 rounded-lg bg-gray-50 focus:ring-primary-500 focus:border-primary-500 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-primary-500 dark:focus:border-primary-500",
46
- data: {
47
- action: "form#submit",
48
- turbo_permanent: true
49
- }
50
- )
51
-
52
- render field(:scope, value: query_params[:scope]).input_tag(type: :hidden)
53
- render field(:sort_fields, value: query_params[:sort_fields]).input_array_tag do |f|
54
- render f.input_tag(type: :hidden)
55
- end
56
- nest_one(:sort_directions) do |directions|
57
- query_params[:sort_directions]&.each do |name, value|
58
- render directions.field(name, value:).input_tag(hidden: true)
59
- end
60
- end
61
- end
62
- }
63
-
64
- # div(class: "flex flex-wrap items-center gap-4") do
65
- # span(class: "text-sm font-medium text-gray-900 dark:text-white") do
66
- # "Filters:"
67
- # end
68
- # select(
69
- # id: "category-filter",
70
- # class:
71
- # "bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-primary-500 focus:border-primary-500 p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-primary-500 dark:focus:border-primary-500"
72
- # ) do
73
- # option(selected: "selected", value: "") { "All Categories" }
74
- # option(value: "technology") { "Technology" }
75
- # option(value: "science") { "Science" }
76
- # option(value: "health") { "Health" }
77
- # end
78
- # div(class: "flex items-center space-x-2") do
79
- # input(
80
- # type: "date",
81
- # id: "start-date",
82
- # class:
83
- # "bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-primary-500 focus:border-primary-500 p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-primary-500 dark:focus:border-primary-500"
84
- # )
85
- # span(class: "text-gray-500 dark:text-gray-400") { "to" }
86
- # input(
87
- # type: "date",
88
- # id: "end-date",
89
- # class:
90
- # "bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-primary-500 focus:border-primary-500 p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-primary-500 dark:focus:border-primary-500"
91
- # )
92
- # end
93
- # select(
94
- # id: "author-filter",
95
- # class:
96
- # "bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-primary-500 focus:border-primary-500 p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-primary-500 dark:focus:border-primary-500"
97
- # ) do
98
- # option(selected: "selected", value: "") { "All Authors" }
99
- # option(value: "john-doe") { "John Doe" }
100
- # option(value: "jane-smith") { "Jane Smith" }
101
- # end
102
- # button(
103
- # onclick: "applyFilters()",
104
- # class:
105
- # "inline-flex items-center text-white bg-primary-700 hover:bg-primary-800 focus:ring-4 focus:ring-primary-300 font-medium rounded-lg text-sm px-4 py-2 dark:bg-primary-600 dark:hover:bg-primary-700 focus:outline-none dark:focus:ring-primary-800"
106
- # ) do
107
- # svg(
108
- # class: "w-4 h-4 mr-2",
109
- # fill: "currentColor",
110
- # viewbox: "0 0 20 20",
111
- # xmlns: "http://www.w3.org/2000/svg"
112
- # ) do |s|
113
- # s.path(
114
- # fill_rule: "evenodd",
115
- # d:
116
- # "M3 3a1 1 0 011-1h12a1 1 0 011 1v3a1 1 0 01-.293.707L12 11.414V15a1 1 0 01-.293.707l-2 2A1 1 0 018 17v-5.586L3.293 6.707A1 1 0 013 6V3z",
117
- # clip_rule: "evenodd"
118
- # )
119
- # end
120
- # plain " Apply Filters "
121
- # end
122
- # button(
123
- # onclick: "clearFilters()",
124
- # class:
125
- # "inline-flex items-center text-gray-900 bg-white border border-gray-300 focus:outline-none hover:bg-gray-100 focus:ring-4 focus:ring-gray-200 font-medium rounded-lg text-sm px-4 py-2 dark:bg-gray-800 dark:text-white dark:border-gray-600 dark:hover:bg-gray-700 dark:hover:border-gray-600 dark:focus:ring-gray-700"
126
- # ) do
127
- # svg(
128
- # class: "w-4 h-4 mr-2",
129
- # fill: "currentColor",
130
- # viewbox: "0 0 20 20",
131
- # xmlns: "http://www.w3.org/2000/svg"
132
- # ) do |s|
133
- # s.path(
134
- # fill_rule: "evenodd",
135
- # d:
136
- # "M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z",
137
- # clip_rule: "evenodd"
138
- # )
139
- # end
140
- # plain " Clear Filters "
141
- # end
142
- # end
143
- end
144
- ensure
145
- # TODO: remove this once Phlex adds support for SafeValues
146
- Phlex::HTML.const_set(:EVENT_ATTRIBUTES, original_attributes)
9
+ render current_definition.query_form.new(
10
+ raw_resource_query_params,
11
+ query_object: current_query_object,
12
+ page_size: request.parameters[:limit]
13
+ )
147
14
  end
148
15
 
149
16
  private
150
17
 
151
18
  def render?
152
- current_query_object.search_filter.present? && current_policy.allowed_to?(:search?)
19
+ current_query_object.filter_definitions.present? && current_policy.allowed_to?(:search?)
153
20
  end
154
21
  end
155
22
  end
@@ -53,19 +53,20 @@ module Plutonium
53
53
 
54
54
  column_definition = resource_definition.defined_columns[name] || {}
55
55
  column_display_options = column_definition[:options] || {}
56
- display_field_as = column_display_options.delete(:as)
57
- align_field_to = column_display_options.delete(:align)
58
56
 
59
- display_block = column_definition[:block] || ->(wrapped_object, key) {
57
+ display_tag = column_display_options[:as]
58
+ display_tag_options = column_display_options.except(:as, :align)
59
+ display_tag_block = column_definition[:block] || ->(wrapped_object, key) {
60
60
  f = wrapped_object.field(key)
61
- display_field_as ||= f.inferred_field_component
62
- f.send(:"#{display_field_as}_tag", **column_display_options)
61
+ display_tag ||= f.inferred_field_component
62
+ f.send(:"#{display_tag}_tag", **display_tag_options)
63
63
  }
64
64
 
65
- field_options = resource_definition.defined_fields[name] ? resource_definition.defined_fields[name][:options] : {}
66
- field_options[:as] = display_field_as
67
- field_options[:align] = align_field_to if align_field_to
68
- table.column name, **field_options, sort_params: current_query_object.sort_params_for(name), &display_block
65
+ # align_field_to = column_display_options.slice(:align)
66
+ field_options = resource_definition.defined_fields[name] ? resource_definition.defined_fields[name][:options].dup : {}
67
+ field_options = field_options.merge(**column_display_options.slice(:align))
68
+ # field_options[:align] = align_field_to if align_field_to
69
+ table.column name, **field_options, sort_params: current_query_object.sort_params_for(name), &display_tag_block
69
70
  end
70
71
 
71
72
  table.actions do |wrapped_object|
@@ -1,5 +1,5 @@
1
1
  module Plutonium
2
- VERSION = "0.15.3"
2
+ VERSION = "0.15.5"
3
3
  NEXT_MAJOR_VERSION = VERSION.split(".").tap { |v|
4
4
  v[1] = v[1].to_i + 1
5
5
  v[2] = 0
data/package-lock.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@radioactive-labs/plutonium",
3
- "version": "0.1.3",
3
+ "version": "0.1.5",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "@radioactive-labs/plutonium",
9
- "version": "0.1.3",
9
+ "version": "0.1.5",
10
10
  "license": "MIT",
11
11
  "dependencies": {
12
12
  "@hotwired/stimulus": "^3.2.2",
data/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@radioactive-labs/plutonium",
3
- "version": "0.1.3",
3
+ "version": "0.1.5",
4
4
  "description": "Core assets for the Plutonium gem",
5
5
  "type": "module",
6
6
  "main": "src/js/core.js",
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: plutonium
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.15.3
4
+ version: 0.15.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Stefan Froelich
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-10-06 00:00:00.000000000 Z
11
+ date: 2024-10-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: zeitwerk
@@ -1256,6 +1256,7 @@ files:
1256
1256
  - lib/plutonium/definition/base.rb
1257
1257
  - lib/plutonium/definition/config_attr.rb
1258
1258
  - lib/plutonium/definition/defineable_props.rb
1259
+ - lib/plutonium/definition/presentable.rb
1259
1260
  - lib/plutonium/definition/search.rb
1260
1261
  - lib/plutonium/definition/sorting.rb
1261
1262
  - lib/plutonium/engine.rb
@@ -1275,7 +1276,6 @@ files:
1275
1276
  - lib/plutonium/icons.rb
1276
1277
  - lib/plutonium/interaction/README.md
1277
1278
  - lib/plutonium/interaction/base.rb
1278
- - lib/plutonium/interaction/concerns/presentable.rb
1279
1279
  - lib/plutonium/interaction/concerns/workflow_dsl.rb
1280
1280
  - lib/plutonium/interaction/outcome.rb
1281
1281
  - lib/plutonium/interaction/response/base.rb
@@ -1286,6 +1286,7 @@ files:
1286
1286
  - lib/plutonium/interaction/response/render.rb
1287
1287
  - lib/plutonium/lib/after_commit.rb
1288
1288
  - lib/plutonium/lib/bit_flags.rb
1289
+ - lib/plutonium/lib/deep_freezer.rb
1289
1290
  - lib/plutonium/lib/overlayed_hash.rb
1290
1291
  - lib/plutonium/lib/smart_cache.rb
1291
1292
  - lib/plutonium/models/has_cents.rb
@@ -1295,13 +1296,18 @@ files:
1295
1296
  - lib/plutonium/portal/engine.rb
1296
1297
  - lib/plutonium/preserved__/field.rb.bk
1297
1298
  - lib/plutonium/preserved__/input.rb.bk
1299
+ - lib/plutonium/query/adhoc_block.rb
1300
+ - lib/plutonium/query/base.rb
1301
+ - lib/plutonium/query/filter.rb
1302
+ - lib/plutonium/query/filters/text.rb
1303
+ - lib/plutonium/query/model_scope.rb
1298
1304
  - lib/plutonium/railtie.rb
1299
- - lib/plutonium/refinements/parameter_refinements.rb
1300
1305
  - lib/plutonium/reloader.rb
1301
1306
  - lib/plutonium/resource/context.rb
1302
1307
  - lib/plutonium/resource/controller.rb
1303
1308
  - lib/plutonium/resource/controllers/authorizable.rb
1304
1309
  - lib/plutonium/resource/controllers/crud_actions.rb
1310
+ - lib/plutonium/resource/controllers/crud_actions/index_action.rb
1305
1311
  - lib/plutonium/resource/controllers/defineable.rb
1306
1312
  - lib/plutonium/resource/controllers/interactive_actions.rb
1307
1313
  - lib/plutonium/resource/controllers/presentable.rb
@@ -1319,6 +1325,7 @@ files:
1319
1325
  - lib/plutonium/routing/route_set_extensions.rb
1320
1326
  - lib/plutonium/simple_form/attachment_component.rb
1321
1327
  - lib/plutonium/simple_form/input_group_component.rb
1328
+ - lib/plutonium/support/parameters.rb
1322
1329
  - lib/plutonium/ui.rb
1323
1330
  - lib/plutonium/ui/action_button.rb
1324
1331
  - lib/plutonium/ui/breadcrumbs.rb
@@ -1334,6 +1341,7 @@ files:
1334
1341
  - lib/plutonium/ui/empty_card.rb
1335
1342
  - lib/plutonium/ui/form/base.rb
1336
1343
  - lib/plutonium/ui/form/interaction.rb
1344
+ - lib/plutonium/ui/form/query.rb
1337
1345
  - lib/plutonium/ui/form/resource.rb
1338
1346
  - lib/plutonium/ui/form/theme.rb
1339
1347
  - lib/plutonium/ui/page/base.rb
@@ -1,73 +0,0 @@
1
- module Plutonium
2
- module Interaction
3
- module Concerns
4
- # Provides presentation-related functionality for interactions.
5
- #
6
- # This module allows interactions to define metadata such as labels, icons,
7
- # and descriptions, which can be used for UI generation or documentation.
8
- #
9
- # @example
10
- # class MyInteraction < Plutonium::Interaction::Base
11
- # include Plutonium::Interaction::Concerns::Presentable
12
- #
13
- # presents label: "My Interaction",
14
- # icon: "star",
15
- # description: "Does something awesome"
16
- #
17
- # # ... rest of the interaction
18
- # end
19
- module Presentable
20
- extend ActiveSupport::Concern
21
-
22
- included do
23
- class_attribute :presentation_metadata, default: {}
24
- end
25
-
26
- class_methods do
27
- # Defines presentation metadata for the interaction.
28
- #
29
- # @param options [Hash] The presentation options.
30
- # @option options [String] :label The label for the interaction.
31
- # @option options [String] :icon The icon for the interaction.
32
- # @option options [String] :description The description of the interaction.
33
- def presents(**options)
34
- self.presentation_metadata = options
35
- end
36
-
37
- # Returns the label for the interaction.
38
- #
39
- # @return [String] The label defined in the presentation metadata or a default generated from the class name.
40
- def label
41
- presentation_metadata[:label] || name.demodulize.titleize
42
- end
43
-
44
- # Returns the icon for the interaction.
45
- #
46
- # @return [String, nil] The icon defined in the presentation metadata.
47
- def icon
48
- presentation_metadata[:icon]
49
- end
50
-
51
- # Returns the description for the interaction.
52
- #
53
- # @return [String, nil] The description defined in the presentation metadata.
54
- def description
55
- presentation_metadata[:description]
56
- end
57
- end
58
-
59
- def label
60
- self.class.label
61
- end
62
-
63
- def icon
64
- self.class.icon
65
- end
66
-
67
- def description
68
- self.class.description
69
- end
70
- end
71
- end
72
- end
73
- end