avo 2.9.1.pre7 → 2.10.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of avo might be problematic. Click here for more details.

Files changed (74) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile.lock +5 -7
  3. data/README.md +4 -0
  4. data/app/assets/stylesheets/css/buttons.css +4 -1
  5. data/app/components/avo/base_component.rb +2 -0
  6. data/app/components/avo/button_component.rb +3 -1
  7. data/app/components/avo/fields/edit_component.rb +5 -0
  8. data/app/components/avo/fields/show_component.rb +1 -1
  9. data/app/components/avo/index/ordering/button_component.rb +3 -5
  10. data/app/components/avo/index/resource_table_component.html.erb +1 -1
  11. data/app/components/avo/index/table_row_component.html.erb +1 -1
  12. data/app/components/avo/item_switcher_component.html.erb +19 -0
  13. data/app/components/avo/item_switcher_component.rb +45 -0
  14. data/app/components/avo/panel_component.html.erb +23 -24
  15. data/app/components/avo/panel_component.rb +8 -5
  16. data/app/components/avo/tab_group_component.html.erb +53 -0
  17. data/app/components/avo/tab_group_component.rb +51 -0
  18. data/app/components/avo/tab_switcher_component.html.erb +21 -0
  19. data/app/components/avo/tab_switcher_component.rb +86 -0
  20. data/app/components/avo/views/resource_edit_component.html.erb +34 -56
  21. data/app/components/avo/views/resource_edit_component.rb +10 -0
  22. data/app/components/avo/views/resource_index_component.html.erb +1 -1
  23. data/app/components/avo/views/resource_index_component.rb +1 -1
  24. data/app/components/avo/views/resource_show_component.html.erb +58 -89
  25. data/app/components/avo/views/resource_show_component.rb +2 -2
  26. data/app/controllers/avo/actions_controller.rb +1 -1
  27. data/app/controllers/avo/application_controller.rb +6 -10
  28. data/app/helpers/avo/application_helper.rb +0 -6
  29. data/app/helpers/avo/url_helpers.rb +1 -1
  30. data/app/javascript/js/controllers/loading_button_controller.js +25 -21
  31. data/app/javascript/js/controllers/tabs_controller.js +9 -3
  32. data/app/javascript/js/controllers.js +2 -0
  33. data/app/views/avo/base/index.html.erb +1 -1
  34. data/app/views/avo/base/show.html.erb +1 -1
  35. data/app/views/avo/cards/show.html.erb +1 -1
  36. data/app/views/avo/debug/index.html.erb +1 -1
  37. data/app/views/avo/home/_actions.html.erb +1 -1
  38. data/app/views/avo/home/_dashboards.html.erb +19 -0
  39. data/app/views/avo/home/_filters.html.erb +1 -1
  40. data/app/views/avo/home/_resources.html.erb +1 -1
  41. data/app/views/avo/home/failed_to_load.html.erb +1 -1
  42. data/app/views/avo/home/index.html.erb +14 -2
  43. data/app/views/avo/partials/_tabs_toggle.html.erb +20 -0
  44. data/app/views/avo/private/design.html.erb +1 -1
  45. data/lib/avo/base_action.rb +2 -19
  46. data/lib/avo/base_resource.rb +0 -94
  47. data/lib/avo/base_resource_tool.rb +3 -1
  48. data/lib/avo/concerns/has_fields.rb +247 -50
  49. data/lib/avo/concerns/has_html_attributes.rb +1 -1
  50. data/lib/avo/concerns/is_resource_item.rb +36 -0
  51. data/lib/avo/dsl/field_parser.rb +83 -0
  52. data/lib/avo/fields/base_field.rb +19 -2
  53. data/lib/avo/fields/field_extensions/visible_in_different_views.rb +18 -1
  54. data/lib/avo/fields/has_base_field.rb +18 -1
  55. data/lib/avo/grid_collector.rb +6 -3
  56. data/lib/avo/items_holder.rb +68 -0
  57. data/lib/avo/licensing/h_q.rb +10 -0
  58. data/lib/avo/main_panel.rb +3 -0
  59. data/lib/avo/menu/builder.rb +6 -6
  60. data/lib/avo/panel.rb +25 -0
  61. data/lib/avo/panel_builder.rb +23 -0
  62. data/lib/avo/tab.rb +78 -0
  63. data/lib/avo/tab_builder.rb +25 -0
  64. data/lib/avo/tab_group.rb +40 -0
  65. data/lib/avo/tab_group_builder.rb +43 -0
  66. data/lib/avo/version.rb +1 -1
  67. data/lib/generators/avo/templates/resource/controller.tt +2 -0
  68. data/lib/generators/avo/templates/resource_tools/partial.tt +1 -1
  69. data/lib/generators/avo/templates/tool/view.tt +1 -1
  70. data/public/avo-assets/avo.css +27 -3
  71. data/public/avo-assets/avo.js +73 -73
  72. data/public/avo-assets/avo.js.map +3 -3
  73. metadata +22 -5
  74. data/lib/avo/concerns/has_tools.rb +0 -47
@@ -1,5 +1,5 @@
1
1
  <div class="flex flex-col">
2
- <%= render Avo::PanelComponent.new title: 'Welcome to Avo', description: 'This page is visible only in development. It will be hidden in other environments.' do |c| %>
2
+ <%= render Avo::PanelComponent.new(title: 'Welcome to Avo', description: 'This page is visible only in development. It will be hidden in other environments.') do |c| %>
3
3
  <% c.body do %>
4
4
  <div class="flex flex-col justify-between py-6 min-h-24">
5
5
  <div class="px-6 space-y-4">
@@ -23,10 +23,20 @@
23
23
  <li><span class="mr-2">👍</span> Grid view</li>
24
24
  <li><span class="mr-2">👍</span> Authorization</li>
25
25
  <li><span class="mr-2">👍</span> Localization</li>
26
+ <li><span class="mr-2">👍</span> Resource tools</li>
26
27
  <li><span class="mr-2">👍</span> Custom tools</li>
27
28
  <li><span class="mr-2">👍</span> Custom fields</li>
29
+ <li><span class="mr-2">👍</span> Menu editor</li>
28
30
  <li><span class="mr-2">👍</span> Search</li>
29
- <li><span class="mr-2">🕐</span> Dashboards</li>
31
+ <li><span class="mr-2">👍</span> Dashboards</li>
32
+ <li><span class="mr-2">👍</span> Responsive design</li>
33
+ <li><span class="mr-2">👍</span> Menu editor</li>
34
+ <li><span class="mr-2">👍</span> Stimulus JS integration</li>
35
+ <li><span class="mr-2">👍</span> Tabs and panels</li>
36
+ <li><span class="mr-2">🕐</span> Resource cards</li>
37
+ <li><span class="mr-2">🕐</span> Track resource changes</li>
38
+ <li><span class="mr-2">🕐</span> Smart resource generation</li>
39
+ <li><span class="mr-2">🕐</span> Records preview</li>
30
40
  <li><span class="mr-2">🕐</span> Themes</li>
31
41
  </ul>
32
42
  </p>
@@ -37,6 +47,8 @@
37
47
  <div class="space">
38
48
  <%= render partial: 'resources' %>
39
49
  <hr class="my-6">
50
+ <%= render partial: 'dashboards' %>
51
+ <hr class="my-6">
40
52
  <%= render partial: 'filters' %>
41
53
  <hr class="my-6">
42
54
  <%= render partial: 'actions' %>
@@ -0,0 +1,20 @@
1
+ <div class="flex">
2
+ <div class="button-group">
3
+ <% tabs.each do |tab| %>
4
+ <% is_active_view = tab.name.to_s == active_tab_name.to_s %>
5
+ <%= a_link resource_path(resource: @resource, model: @resource.model, keep_query_params: true, active_tab_name: tab.name, tab_turbo_frame: group.turbo_frame_id),
6
+ color: is_active_view ? :gray : :primary,
7
+ rounded: false,
8
+ size: :sm,
9
+ class: is_active_view ? ' bg-gray-100 border-gray-300' : ' z-20',
10
+ title: tab.description || tab.name,
11
+ data: {
12
+ tippy: 'tooltip',
13
+ 'turbo-frame': group.turbo_frame_id,
14
+ control: "view-type-toggle-#{tab}"
15
+ } do %>
16
+ <%= tab.name %>
17
+ <% end %>
18
+ <% end %>
19
+ </div>
20
+ </div>
@@ -1,5 +1,5 @@
1
1
  <div class="flex flex-col">
2
- <%= render Avo::PanelComponent.new title: 'Welcome to Avo', description: 'This page is visible only in development. It will be hidden in other environments.' do |c| %>
2
+ <%= render Avo::PanelComponent.new(title: 'Welcome to Avo', description: 'This page is visible only in development. It will be hidden in other environments.') do |c| %>
3
3
  <% c.tools do %>
4
4
  <%= a_link('/admin', icon: 'arrow-left', style: :primary, is_link: true) do %>
5
5
  Primary
@@ -13,7 +13,6 @@ module Avo
13
13
  class_attribute :view
14
14
  class_attribute :user
15
15
  class_attribute :resource
16
- class_attribute :invalid_fields
17
16
  class_attribute :standalone, default: false
18
17
  class_attribute :visible
19
18
  class_attribute :may_download_file, default: false
@@ -22,7 +21,8 @@ module Avo
22
21
  attr_accessor :model
23
22
  attr_accessor :resource
24
23
  attr_accessor :user
25
- attr_accessor :fields_loader
24
+
25
+ delegate :view, to: :class
26
26
 
27
27
  class << self
28
28
  def form_data_attributes
@@ -68,23 +68,6 @@ module Avo
68
68
  self.class.context
69
69
  end
70
70
 
71
- def get_field_definitions
72
- return [] if self.class.fields.blank?
73
-
74
- self.class.fields.map do |field|
75
- field.hydrate(action: self)
76
- end
77
- end
78
-
79
- def get_fields
80
- get_field_definitions.map do |field|
81
- field.hydrate(action: self, model: @model)
82
- end
83
- .select do |field|
84
- field.visible?
85
- end
86
- end
87
-
88
71
  def get_attributes_for_action
89
72
  get_fields.map do |field|
90
73
  [field.id, field.value]
@@ -4,7 +4,6 @@ module Avo
4
4
  extend HasContext
5
5
 
6
6
  include ActionView::Helpers::UrlHelper
7
- include Avo::Concerns::HasTools
8
7
  include Avo::Concerns::HasModel
9
8
  include Avo::Concerns::HasFields
10
9
  include Avo::Concerns::HasStimulusControllers
@@ -44,7 +43,6 @@ module Avo
44
43
  class_attribute :hide_from_global_search, default: false
45
44
  class_attribute :after_create_path, default: :show
46
45
  class_attribute :after_update_path, default: :show
47
- class_attribute :invalid_fields
48
46
  class_attribute :record_selector, default: true
49
47
  class_attribute :keep_filters_panel_open, default: false
50
48
 
@@ -123,80 +121,6 @@ module Avo
123
121
  self
124
122
  end
125
123
 
126
- def get_field_definitions
127
- return [] if self.class.fields.blank?
128
-
129
- fields = self.class.fields.map do |field|
130
- field.hydrate(resource: self, panel_name: default_panel_name, user: user)
131
- end
132
-
133
- if Avo::App.license.lacks_with_trial(:custom_fields)
134
- fields = fields.reject do |field|
135
- field.custom?
136
- end
137
- end
138
-
139
- if Avo::App.license.lacks_with_trial(:advanced_fields)
140
- fields = fields.reject do |field|
141
- field.type == "tags"
142
- end
143
- end
144
-
145
- fields
146
- end
147
-
148
- def get_fields(panel: nil, reflection: nil)
149
- fields = get_field_definitions
150
- .select do |field|
151
- field.send("show_on_#{@view}")
152
- end
153
- .select do |field|
154
- field.visible?
155
- end
156
- .select do |field|
157
- is_valid = true
158
-
159
- # Strip out the reflection field in index queries with a parent association.
160
- if reflection.present?
161
- # regular non-polymorphic association
162
- # we're matching the reflection inverse_of foriegn key with the field's foreign_key
163
- if field.is_a?(Avo::Fields::BelongsToField)
164
- if field.respond_to?(:foreign_key) &&
165
- reflection.inverse_of.present? &&
166
- reflection.inverse_of.foreign_key == field.foreign_key
167
- is_valid = false
168
- end
169
-
170
- # polymorphic association
171
- if field.respond_to?(:foreign_key) &&
172
- field.is_polymorphic? &&
173
- reflection.respond_to?(:polymorphic?) &&
174
- reflection.inverse_of.foreign_key == field.reflection.foreign_key
175
- is_valid = false
176
- end
177
- end
178
- end
179
-
180
- is_valid
181
- end
182
-
183
- if panel.present?
184
- fields = fields.select do |field|
185
- field.panel_name == panel
186
- end
187
- end
188
-
189
- hydrate_fields(model: @model, view: @view)
190
-
191
- fields
192
- end
193
-
194
- def get_field(id)
195
- get_field_definitions.find do |f|
196
- f.id == id.to_sym
197
- end
198
- end
199
-
200
124
  def get_grid_fields
201
125
  return if self.class.grid_loader.blank?
202
126
 
@@ -215,14 +139,6 @@ module Avo
215
139
  self.class.actions_loader.bag
216
140
  end
217
141
 
218
- def hydrate_fields(model: nil, view: nil)
219
- fields.map do |field|
220
- field.hydrate(model: @model, view: @view, resource: self)
221
- end
222
-
223
- self
224
- end
225
-
226
142
  def default_panel_name
227
143
  return @params[:related_name].capitalize if @params.present? && @params[:related_name].present?
228
144
 
@@ -236,16 +152,6 @@ module Avo
236
152
  end
237
153
  end
238
154
 
239
- def panels
240
- [
241
- {
242
- name: default_panel_name,
243
- type: :fields,
244
- in_panel: true
245
- }
246
- ]
247
- end
248
-
249
155
  def class_name_without_resource
250
156
  self.class.name.demodulize.chomp("Resource")
251
157
  end
@@ -1,9 +1,11 @@
1
1
  module Avo
2
2
  class BaseResourceTool
3
+ include Avo::Concerns::IsResourceItem
3
4
  include Avo::Fields::FieldExtensions::VisibleInDifferentViews
4
5
 
5
6
  class_attribute :name
6
7
  class_attribute :partial
8
+ class_attribute :item_type, default: :tool
7
9
 
8
10
  attr_accessor :params
9
11
  attr_accessor :resource
@@ -20,7 +22,7 @@ module Avo
20
22
  end
21
23
 
22
24
  def hydrate(view: nil)
23
- @view = view
25
+ @view = view if view.present?
24
26
 
25
27
  self
26
28
  end
@@ -4,88 +4,285 @@ module Avo
4
4
  extend ActiveSupport::Concern
5
5
 
6
6
  included do
7
- class_attribute :fields
8
- class_attribute :fields_index, default: 0
7
+ class_attribute :items_holder
8
+ class_attribute :items_index, default: 0
9
+ class_attribute :tabs_holder
10
+ class_attribute :tabs_tabs_holder
11
+ class_attribute :raw_tabs
12
+ class_attribute :tools_holder
9
13
  end
10
14
 
11
15
  class_methods do
12
- def field(field_name, as:, **args, &block)
13
- self.invalid_fields ||= []
16
+ delegate :tool, to: :items_holder
14
17
 
15
- field_instance = parse_field(field_name, as: as, order_index: fields_index, **args, &block)
18
+ # DSL methods
19
+ def field(name, **args, &block)
20
+ ensure_items_holder_initialized
16
21
 
17
- if field_instance.present?
18
- add_to_fields field_instance
22
+ self.items_holder.field name, **args, &block
23
+ end
24
+
25
+ def panel(name = nil, **args, &block)
26
+ ensure_items_holder_initialized
27
+
28
+ self.items_holder.panel name, **args, &block
29
+ end
30
+
31
+ def tabs(&block)
32
+ ensure_items_holder_initialized
33
+
34
+ self.items_holder.tabs Avo::TabGroupBuilder.parse_block(&block)
35
+ end
36
+
37
+ def heading(body, **args)
38
+ self.items_holder.add_item Avo::Fields::HeadingField.new(body, order_index: items_index, **args)
39
+ end
40
+ # END DSL methods
41
+
42
+ def items
43
+ if self.items_holder.present?
44
+ self.items_holder.items
19
45
  else
20
- self.invalid_fields << ({
21
- name: field_name,
22
- as: as,
23
- resource: name,
24
- message: "There's an invalid field configuration for this resource. <br/> <code class='px-1 py-px rounded bg-red-600'>field :#{field_name}, as: #{as}</code>"
25
- })
46
+ []
26
47
  end
27
48
  end
28
49
 
29
- def parse_field(field_name, as:, **args, &block)
30
- # The field is passed as a symbol eg: :text, :color_picker, :trix
31
- if as.is_a? Symbol
32
- parse_symbol field_name, as: as, **args, &block
33
- elsif as.is_a? Class
34
- parse_class field_name, as: as, **args, &block
50
+ def tools
51
+ self.tools_holder
52
+ end
53
+
54
+ # Dives deep into panels and tabs to fetch all the fields for a resource.
55
+ def fields(only_root: false)
56
+ fields = []
57
+
58
+ self.items.each do |item|
59
+ next if item.nil?
60
+
61
+ unless only_root
62
+ # Dive into panels to fetch their fields
63
+ if item.is_panel?
64
+ fields << extract_fields_from_items(item)
65
+ end
66
+
67
+ # Dive into tabs to fetch their fields
68
+ if item.is_tab_group?
69
+ item.items.map do |tab|
70
+ fields << extract_fields_from_items(tab)
71
+ end
72
+ end
73
+ end
74
+
75
+
76
+ if item.is_field?
77
+ fields << item
78
+ end
35
79
  end
80
+
81
+ fields.flatten
36
82
  end
37
83
 
38
- def heading(body, **args)
39
- add_to_fields Avo::Fields::HeadingField.new(body, order_index: fields_index, **args)
84
+ def tab_groups
85
+ self.items.select do |item|
86
+ item.instance_of? Avo::TabGroup
87
+ end
40
88
  end
41
89
 
42
90
  private
43
91
 
92
+ def extract_fields_from_items(thing)
93
+ fields = []
94
+
95
+ thing.items.each do |item|
96
+ if item.is_field?
97
+ fields << item
98
+ elsif item.is_panel?
99
+ fields << extract_fields_from_items(item)
100
+ end
101
+ end
102
+
103
+ fields
104
+ end
105
+
106
+ def ensure_items_holder_initialized
107
+ self.items_holder ||= Avo::ItemsHolder.new
108
+ end
109
+
44
110
  def add_to_fields(instance)
45
- self.fields ||= []
46
- self.fields << instance
47
- self.fields_index += 1
111
+ self.items ||= []
112
+ self.items << instance
113
+ increment_order_index
48
114
  end
49
115
 
50
- def instantiate_field(field_name, klass:, **args, &block)
51
- if block
52
- klass.new(field_name, **args || {}, &block)
53
- else
54
- klass.new(field_name, **args || {})
55
- end
116
+ def increment_order_index
117
+ self.items_index += 1
118
+ end
119
+ end
120
+
121
+ delegate :invalid_fields, to: :items_holder
122
+ delegate :items, to: :items_holder
123
+
124
+ def hydrate_fields(model: nil, view: nil)
125
+ fields.map do |field|
126
+ field.hydrate(model: @model, view: @view, resource: self)
127
+ end
128
+
129
+ self
130
+ end
131
+
132
+ def get_tabs
133
+ tabs_holder
134
+ end
135
+
136
+ def fields(**args)
137
+ self.class.fields(**args)
138
+ end
139
+
140
+ def tab_groups
141
+ self.class.tab_groups
142
+ end
143
+
144
+ def get_field_definitions(only_root: false)
145
+ fields = self.fields(only_root: only_root)
146
+
147
+ return [] if fields.blank?
148
+
149
+ items = fields.map do |field|
150
+ field.hydrate(resource: self, user: user, view: view)
56
151
  end
57
152
 
58
- def field_class_from_symbol(symbol)
59
- matched_field = Avo::App.fields.find do |field|
60
- field[:name].to_s == symbol.to_s
153
+ if Avo::App.license.lacks_with_trial(:custom_fields)
154
+ items = items.reject do |field|
155
+ field.custom?
61
156
  end
157
+ end
62
158
 
63
- return matched_field[:class] if matched_field.present? && matched_field[:class].present?
159
+ if Avo::App.license.lacks_with_trial(:advanced_fields)
160
+ items = items.reject do |field|
161
+ field.type == "tags"
162
+ end
64
163
  end
65
164
 
66
- def parse_symbol(field_name, as:, **args, &block)
67
- field_class = field_class_from_symbol(as)
165
+ items
166
+ end
68
167
 
69
- if field_class.present?
70
- # The field has been registered before.
71
- instantiate_field(field_name, klass: field_class, **args, &block)
72
- else
73
- # The symbol can be transformed to a class and found.
74
- class_name = as.to_s.camelize
75
- field_class = "#{class_name}Field"
168
+ def get_fields(panel: nil, reflection: nil, only_root: false)
169
+ fields = get_field_definitions(only_root: only_root)
170
+ .select do |field|
171
+ field.visible_on?(view)
172
+ end
173
+ .select do |field|
174
+ field.visible?
175
+ end
176
+ .select do |field|
177
+ is_valid = true
178
+
179
+ # Strip out the reflection field in index queries with a parent association.
180
+ if reflection.present?
181
+ # regular non-polymorphic association
182
+ # we're matching the reflection inverse_of foriegn key with the field's foreign_key
183
+ if field.is_a?(Avo::Fields::BelongsToField)
184
+ if field.respond_to?(:foreign_key) &&
185
+ reflection.inverse_of.present? &&
186
+ reflection.inverse_of.foreign_key == field.foreign_key
187
+ is_valid = false
188
+ end
76
189
 
77
- # Discover & load custom field classes
78
- if Object.const_defined? field_class
79
- instantiate_field(field_name, klass: field_class.safe_constantize, **args, &block)
190
+ # polymorphic association
191
+ if field.respond_to?(:foreign_key) &&
192
+ field.is_polymorphic? &&
193
+ reflection.respond_to?(:polymorphic?) &&
194
+ reflection.inverse_of.foreign_key == field.reflection.foreign_key
195
+ is_valid = false
196
+ end
197
+ end
80
198
  end
199
+
200
+ is_valid
201
+ end
202
+
203
+ if panel.present?
204
+ fields = fields.select do |field|
205
+ field.panel_name == panel
81
206
  end
82
207
  end
83
208
 
84
- def parse_class(field_name, as:, **args, &block)
85
- # The field has been passed as a class.
86
- if Object.const_defined? as.to_s
87
- instantiate_field(field_name, klass: as, **args, &block)
209
+ hydrate_fields(model: @model, view: @view)
210
+
211
+ fields
212
+ end
213
+
214
+ def get_field(id)
215
+ get_field_definitions.find do |f|
216
+ f.id == id.to_sym
217
+ end
218
+ end
219
+
220
+ def tools
221
+ check_license
222
+
223
+ return [] if App.license.lacks_with_trial :resource_tools
224
+ return [] if self.class.tools.blank?
225
+
226
+ self.items
227
+ .select do |item|
228
+ next if item.nil?
229
+
230
+ item.is_tool?
88
231
  end
232
+ .map do |tool|
233
+ tool.hydrate view: view
234
+ tool
235
+ end
236
+ .select do |item|
237
+ item.visible_on?(view)
238
+ end
239
+ end
240
+
241
+ # Separates the fields that are in a panel and those that are just hanging out.
242
+ # Take the ones that aren't placed into a panel and add them to the "default" panel.
243
+ # This is to keep compatibility with the versions before 2.10 when you didn't have the ability to add fields to panels.
244
+ def get_items
245
+ panelless_items = []
246
+ panelfull_items = []
247
+
248
+ items.each do |item|
249
+ # fields and tabs can be hidden on some views
250
+ if item.respond_to? :visible_on?
251
+ next unless item.visible_on?(view)
252
+ end
253
+ if item.respond_to? :visible?
254
+ next unless item.visible?
255
+ end
256
+
257
+ if item.is_field?
258
+ if item.has_own_panel?
259
+ panelfull_items << item
260
+ else
261
+ panelless_items << item
262
+ end
263
+ else
264
+ panelfull_items << item
265
+ end
266
+ end
267
+
268
+ # Add all the panelles fields to a new panel
269
+ main_panel_holder = Avo::ItemsHolder.new
270
+ main_panel_holder.items = panelless_items
271
+
272
+ # Add that panel to the main panel
273
+ main_panel = Avo::MainPanel.new
274
+ main_panel.items_holder = main_panel_holder
275
+
276
+ # Return all the items but this time with all the panelless ones inside the main panel
277
+ [main_panel, *panelfull_items]
278
+ end
279
+
280
+ private
281
+
282
+ def check_license
283
+ if !Rails.env.production? && App.license.present? && App.license.lacks(:resource_tools)
284
+ # Add error message to let the developer know the resource tool will not be available in a production environment.
285
+ Avo::App.error_messages.push "Warning: Your license is invalid or doesn't support resource tools. The resource tools will not be visible in a production environment."
89
286
  end
90
287
  end
91
288
  end
@@ -50,7 +50,7 @@ module Avo
50
50
  end
51
51
 
52
52
  def add_default_data_attributes(attributes, name, element, view)
53
- if !attributes.nil? && name == :data && element == :input && view.in?([:edit, :new]) && resource.present?
53
+ if !attributes.nil? && name == :data && element == :input && view.in?([:edit, :new]) && resource.present? && resource.respond_to?(:get_stimulus_controllers)
54
54
  extra_attributes = resource.get_stimulus_controllers
55
55
  .split(" ")
56
56
  .map do |controller|
@@ -0,0 +1,36 @@
1
+ # This concern helps us figure out what kind of items (field, tool, tab_group, or panel) have been passed to the resource or action.
2
+ module Avo
3
+ module Concerns
4
+ module IsResourceItem
5
+ extend ActiveSupport::Concern
6
+
7
+ included do
8
+ class_attribute :item_type, default: nil
9
+ end
10
+
11
+ def is_field?
12
+ self.class.item_type == :field
13
+ end
14
+
15
+ def is_panel?
16
+ self.class.item_type == :panel || self.class.item_type == :main_panel
17
+ end
18
+
19
+ def is_main_panel?
20
+ self.class.item_type == :main_panel
21
+ end
22
+
23
+ def is_tool?
24
+ self.class.item_type == :tool
25
+ end
26
+
27
+ def is_tab?
28
+ self.class.item_type == :tab
29
+ end
30
+
31
+ def is_tab_group?
32
+ self.class.item_type == :tab_group
33
+ end
34
+ end
35
+ end
36
+ end