plutonium 0.15.4 → 0.15.6

Sign up to get free protection for your applications and to get access to all the features.
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