plutonium 0.15.4 → 0.15.6

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 (73) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/plutonium.css +1 -1
  3. data/app/assets/plutonium.ico +0 -0
  4. data/app/assets/plutonium.png +0 -0
  5. data/app/views/components/table_search_input/table_search_input_component.html.erb +3 -3
  6. data/app/views/resource/_resource_table.html.erb +0 -321
  7. data/docs/.vitepress/config.ts +61 -0
  8. data/docs/.vitepress/theme/custom.css +61 -0
  9. data/docs/.vitepress/theme/index.ts +4 -0
  10. data/docs/api-examples.md +49 -0
  11. data/docs/guide/getting-started/authorization.md +296 -0
  12. data/docs/guide/getting-started/core-concepts.md +432 -0
  13. data/docs/guide/getting-started/index.md +18 -0
  14. data/docs/guide/getting-started/installation.md +269 -0
  15. data/docs/guide/getting-started/resources.md +254 -0
  16. data/docs/guide/what-is-plutonium.md +211 -0
  17. data/docs/index.md +43 -0
  18. data/docs/markdown-examples.md +85 -0
  19. data/docs/public/android-chrome-192x192.png +0 -0
  20. data/docs/public/android-chrome-512x512.png +0 -0
  21. data/docs/public/apple-touch-icon.png +0 -0
  22. data/docs/public/favicon-16x16.png +0 -0
  23. data/docs/public/favicon-32x32.png +0 -0
  24. data/docs/public/favicon.ico +0 -0
  25. data/docs/public/plutonium.png +0 -0
  26. data/docs/public/site.webmanifest +1 -0
  27. data/docs/public/templates/plutonium.rb +21 -0
  28. data/lib/generators/pu/core/assets/assets_generator.rb +2 -3
  29. data/lib/generators/pu/core/assets/templates/tailwind.config.js +2 -2
  30. data/lib/generators/pu/core/install/install_generator.rb +9 -1
  31. data/lib/generators/pu/core/install/templates/config/initializers/plutonium.rb +0 -1
  32. data/lib/plutonium/core/controllers/authorizable.rb +1 -1
  33. data/lib/plutonium/definition/base.rb +8 -0
  34. data/lib/plutonium/definition/defineable_props.rb +1 -1
  35. data/lib/plutonium/definition/presentable.rb +71 -0
  36. data/lib/plutonium/interaction/README.md +1 -1
  37. data/lib/plutonium/interaction/base.rb +6 -6
  38. data/lib/plutonium/lib/deep_freezer.rb +31 -0
  39. data/lib/plutonium/query/adhoc_block.rb +19 -0
  40. data/lib/plutonium/query/base.rb +29 -0
  41. data/lib/plutonium/query/filter.rb +12 -0
  42. data/lib/plutonium/query/filters/text.rb +77 -0
  43. data/lib/plutonium/query/model_scope.rb +19 -0
  44. data/lib/plutonium/railtie.rb +0 -10
  45. data/lib/plutonium/resource/controller.rb +0 -3
  46. data/lib/plutonium/resource/controllers/crud_actions/index_action.rb +26 -0
  47. data/lib/plutonium/resource/controllers/crud_actions.rb +3 -6
  48. data/lib/plutonium/resource/controllers/defineable.rb +0 -2
  49. data/lib/plutonium/resource/controllers/queryable.rb +36 -20
  50. data/lib/plutonium/resource/policy.rb +5 -6
  51. data/lib/plutonium/resource/query_object.rb +61 -147
  52. data/lib/plutonium/resource/register.rb +3 -0
  53. data/lib/plutonium/{refinements/parameter_refinements.rb → support/parameters.rb} +5 -7
  54. data/lib/plutonium/ui/action_button.rb +34 -19
  55. data/lib/plutonium/ui/component/methods.rb +1 -1
  56. data/lib/plutonium/ui/display/resource.rb +19 -15
  57. data/lib/plutonium/ui/form/query.rb +171 -0
  58. data/lib/plutonium/ui/form/resource.rb +22 -17
  59. data/lib/plutonium/ui/table/components/scopes_bar.rb +1 -1
  60. data/lib/plutonium/ui/table/components/search_bar.rb +6 -139
  61. data/lib/plutonium/ui/table/resource.rb +10 -9
  62. data/lib/plutonium/version.rb +1 -1
  63. data/package-lock.json +5769 -1853
  64. data/package.json +11 -5
  65. data/src/js/core.js +0 -1
  66. data/tailwind.options.js +89 -11
  67. metadata +37 -13
  68. data/app/assets/plutonium-original.png +0 -0
  69. data/app/assets/plutonium-white.png +0 -0
  70. data/lib/plutonium/interaction/concerns/presentable.rb +0 -73
  71. data/public/plutonium-assets/fonts/bootstrap-icons.woff +0 -0
  72. data/public/plutonium-assets/fonts/bootstrap-icons.woff2 +0 -0
  73. /data/{templates → docs/public/templates}/base.rb +0 -0
@@ -80,7 +80,7 @@ module Plutonium
80
80
  if @variant == :table
81
81
  "h-4 w-4 mr-1"
82
82
  else
83
- "h-3.5 w-3.5 mr-2 -ml-1"
83
+ "h-3.5 w-3.5 -ml-1"
84
84
  end
85
85
  end
86
86
 
@@ -91,35 +91,50 @@ module Plutonium
91
91
  def color_classes
92
92
  case @action.color || @action.category.to_sym
93
93
  when :primary
94
- table_variant_class(
95
- "bg-primary-100 text-primary-700 hover:bg-primary-200 focus:ring-primary-300 dark:bg-primary-700 dark:text-primary-100 dark:hover:bg-primary-600 dark:focus:ring-primary-600",
96
- "bg-primary-700 text-white hover:bg-primary-800 focus:ring-primary-300 dark:bg-primary-600 dark:hover:bg-primary-700 dark:focus:ring-primary-800"
94
+ variant_class(
95
+ "bg-primary-700 text-white hover:bg-primary-800 focus:ring-primary-300 dark:bg-primary-600 dark:hover:bg-primary-700 dark:focus:ring-primary-800",
96
+ table: "bg-primary-100 text-primary-700 hover:bg-primary-200 focus:ring-primary-300 dark:bg-primary-700 dark:text-primary-100 dark:hover:bg-primary-600 dark:focus:ring-primary-600"
97
+ )
98
+ when :success
99
+ variant_class(
100
+ "bg-success-700 text-white hover:bg-success-800 focus:ring-success-300 dark:bg-success-600 dark:hover:bg-success-700 dark:focus:ring-success-800",
101
+ table: "bg-success-100 text-success-700 hover:bg-success-200 focus:ring-success-300 dark:bg-success-700 dark:text-success-100 dark:hover:bg-success-600 dark:focus:ring-success-600"
102
+ )
103
+ when :info
104
+ variant_class(
105
+ "bg-info-700 text-white hover:bg-info-800 focus:ring-info-300 dark:bg-info-600 dark:hover:bg-info-700 dark:focus:ring-info-800",
106
+ table: "bg-info-100 text-info-700 hover:bg-info-200 focus:ring-info-300 dark:bg-info-700 dark:text-info-100 dark:hover:bg-info-600 dark:focus:ring-info-600"
97
107
  )
98
108
  when :warning
99
- table_variant_class(
100
- "bg-yellow-100 text-yellow-700 hover:bg-yellow-200 focus:ring-yellow-300 dark:bg-yellow-700 dark:text-yellow-100 dark:hover:bg-yellow-600 dark:focus:ring-yellow-600",
101
- "bg-yellow-400 text-white hover:bg-yellow-500 focus:ring-yellow-300 dark:bg-yellow-600 dark:hover:bg-yellow-700 dark:focus:ring-yellow-800"
109
+ variant_class(
110
+ "bg-warning-700 text-white hover:bg-warning-800 focus:ring-warning-300 dark:bg-warning-600 dark:hover:bg-warning-700 dark:focus:ring-warning-800",
111
+ table: "bg-warning-100 text-warning-700 hover:bg-warning-200 focus:ring-warning-300 dark:bg-warning-700 dark:text-warning-100 dark:hover:bg-warning-600 dark:focus:ring-warning-600"
102
112
  )
103
113
  when :danger
104
- table_variant_class(
105
- "bg-red-100 text-red-700 hover:bg-red-200 focus:ring-red-300 dark:bg-red-700 dark:text-red-100 dark:hover:bg-red-600 dark:focus:ring-red-600",
106
- "bg-red-700 text-white hover:bg-red-800 focus:ring-red-300 dark:bg-red-600 dark:hover:bg-red-700 dark:focus:ring-red-900"
114
+ variant_class(
115
+ "bg-danger-700 text-white hover:bg-danger-800 focus:ring-danger-300 dark:bg-danger-600 dark:hover:bg-danger-700 dark:focus:ring-danger-800",
116
+ table: "bg-danger-100 text-danger-700 hover:bg-danger-200 focus:ring-danger-300 dark:bg-danger-700 dark:text-danger-100 dark:hover:bg-danger-600 dark:focus:ring-danger-600"
107
117
  )
108
- when :success
109
- table_variant_class(
110
- "bg-green-100 text-green-700 hover:bg-green-200 focus:ring-green-300 dark:bg-green-700 dark:text-green-100 dark:hover:bg-green-600 dark:focus:ring-green-600",
111
- "bg-green-700 text-white hover:bg-green-800 focus:ring-green-300 dark:bg-green-600 dark:hover:bg-green-700 dark:focus:ring-green-800"
118
+ when :accent
119
+ variant_class(
120
+ "bg-accent-700 text-white hover:bg-accent-800 focus:ring-accent-300 dark:bg-accent-600 dark:hover:bg-accent-700 dark:focus:ring-accent-800",
121
+ table: "bg-accent-100 text-accent-700 hover:bg-accent-200 focus:ring-accent-300 dark:bg-accent-700 dark:text-accent-100 dark:hover:bg-accent-600 dark:focus:ring-accent-600"
112
122
  )
113
123
  else
114
- table_variant_class(
115
- "bg-gray-100 text-gray-700 hover:bg-gray-200 focus:ring-gray-300 dark:bg-gray-700 dark:text-gray-100 dark:hover:bg-gray-600 dark:focus:ring-gray-600",
116
- "border border-gray-200 bg-white text-gray-900 hover:bg-gray-100 hover:text-primary-700 focus:z-10 focus:ring-gray-100 dark:border-gray-600 dark:bg-gray-800 dark:text-gray-200 dark:hover:bg-gray-700 dark:hover:text-white dark:focus:ring-gray-700"
124
+ variant_class(
125
+ "bg-secondary-700 text-white hover:bg-secondary-800 focus:ring-secondary-300 dark:bg-secondary-600 dark:hover:bg-secondary-700 dark:focus:ring-secondary-800",
126
+ table: "bg-secondary-100 text-secondary-700 hover:bg-secondary-200 focus:ring-secondary-300 dark:bg-secondary-700 dark:text-secondary-100 dark:hover:bg-secondary-600 dark:focus:ring-secondary-600"
117
127
  )
118
128
  end
119
129
  end
120
130
 
121
- def table_variant_class(table_class, default_class)
122
- (@variant == :table) ? table_class : default_class
131
+ def variant_class(default, table:)
132
+ case @variant
133
+ when :table
134
+ table
135
+ else
136
+ default
137
+ end
123
138
  end
124
139
  end
125
140
  end
@@ -41,7 +41,7 @@ module Plutonium
41
41
  :resource_url_for,
42
42
  :current_definition,
43
43
  :current_query_object,
44
- :resource_query_params,
44
+ :raw_resource_query_params,
45
45
  :current_policy,
46
46
  :current_turbo_frame,
47
47
  :current_interactive_action,
@@ -37,27 +37,31 @@ module Plutonium
37
37
  end
38
38
 
39
39
  def render_resource_field(name)
40
- # display :name, as: :string
41
- # display :description, class: "col-span-full"
42
- # display :age, field: {class: "max-h-fit"}
43
- # display :dob do |f|
44
- # f.date_tag
45
- # end
46
-
47
40
  when_permitted(name) do
41
+ # field :name, as: :string
42
+ # display :name, as: :string
43
+ # display :description, class: "col-span-full"
44
+ # display :age, tag: {class: "max-h-fit"}
45
+ # display :dob do |f|
46
+ # f.date_tag
47
+ # end
48
+
49
+ field_options = resource_definition.defined_fields[name] ? resource_definition.defined_fields[name][:options] : {}
50
+
48
51
  display_definition = resource_definition.defined_displays[name] || {}
49
52
  display_options = display_definition[:options] || {}
50
- display_field_as = display_options.delete(:as)
51
53
 
52
- display_field_options = display_options.delete(:field) || {}
53
- display_block = display_definition[:block] || ->(f) {
54
- display_field_as ||= f.inferred_field_component
55
- f.send(:"#{display_field_as}_tag", **display_field_options)
54
+ tag = field_options[:as] || display_options[:as]
55
+ tag_attributes = display_options[:tag] || {}
56
+ tag_block = display_definition[:block] || ->(f) {
57
+ tag ||= f.inferred_field_component
58
+ f.send(:"#{tag}_tag", **tag_attributes)
56
59
  }
57
60
 
58
- field_options = resource_definition.defined_fields[name] ? resource_definition.defined_fields[name][:options] : {}
59
- render field(name, **field_options).wrapped(**display_options) do |f|
60
- render display_block.call(f)
61
+ field_options = field_options.except(:as)
62
+ wrapper_options = display_options.except(:tag, :as)
63
+ render field(name, **field_options).wrapped(**wrapper_options) do |f|
64
+ render tag_block.call(f)
61
65
  end
62
66
  end
63
67
  end
@@ -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,37 @@ 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
+
66
+ render field(name, **field_options).wrapped(**wrapper_options) do |f|
67
+ render tag_block.call(f)
63
68
  end
64
69
  end
65
70
  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.search_filter.present? || 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.4"
2
+ VERSION = "0.15.6"
3
3
  NEXT_MAJOR_VERSION = VERSION.split(".").tap { |v|
4
4
  v[1] = v[1].to_i + 1
5
5
  v[2] = 0