avo 3.10.6 → 3.10.7
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +2 -2
- data/README.md +4 -9
- data/app/components/avo/fields/boolean_field/index_component.html.erb +1 -1
- data/app/components/avo/fields/boolean_field/show_component.html.erb +1 -1
- data/app/components/avo/fields/boolean_group_field/edit_component.rb +1 -1
- data/app/components/avo/fields/common/boolean_group_component.html.erb +3 -6
- data/app/components/avo/resource_component.rb +0 -2
- data/app/components/avo/turbo_frame_wrapper_component.html.erb +1 -1
- data/app/controllers/avo/base_controller.rb +9 -2
- data/lib/avo/asset_manager.rb +8 -3
- data/lib/avo/base_resource.rb +2 -601
- data/lib/avo/fields/boolean_group_field.rb +1 -1
- data/lib/avo/licensing/request.rb +3 -1
- data/lib/avo/resources/base.rb +607 -0
- data/lib/avo/resources/items/item_group.rb +2 -0
- data/lib/avo/resources/items/tab.rb +2 -0
- data/lib/avo/version.rb +1 -1
- data/lib/avo.rb +1 -0
- data/lib/generators/avo/eject_generator.rb +1 -1
- data/lib/generators/avo/templates/locales/avo.de.yml +120 -0
- data/lib/generators/avo/templates/locales/avo.it.yml +120 -0
- data/lib/generators/avo/templates/locales/avo.nl.yml +120 -0
- data/lib/generators/avo/templates/locales/avo.pl.yml +120 -0
- data/lib/generators/avo/templates/locales/avo.ru.yml +120 -0
- data/lib/generators/avo/templates/locales/avo.uk.yml +120 -0
- data/lib/generators/avo/templates/locales/avo.zh.yml +120 -0
- data/public/avo-assets/avo.base.css +3 -71
- data/public/avo-assets/avo.base.js +230 -227
- data/public/avo-assets/avo.base.js.map +4 -4
- data/public/avo-assets/logo-on-white.png +0 -0
- metadata +10 -2
data/lib/avo/base_resource.rb
CHANGED
@@ -1,604 +1,5 @@
|
|
1
1
|
module Avo
|
2
|
-
class BaseResource
|
3
|
-
|
4
|
-
|
5
|
-
include ActionView::Helpers::UrlHelper
|
6
|
-
include Avo::Concerns::HasItems
|
7
|
-
include Avo::Concerns::CanReplaceItems
|
8
|
-
include Avo::Concerns::HasControls
|
9
|
-
include Avo::Concerns::HasResourceStimulusControllers
|
10
|
-
include Avo::Concerns::ModelClassConstantized
|
11
|
-
include Avo::Concerns::HasDescription
|
12
|
-
include Avo::Concerns::HasCoverPhoto
|
13
|
-
include Avo::Concerns::HasProfilePhoto
|
14
|
-
include Avo::Concerns::HasHelpers
|
15
|
-
include Avo::Concerns::Hydration
|
16
|
-
include Avo::Concerns::Pagination
|
17
|
-
|
18
|
-
# Avo::Current methods
|
19
|
-
delegate :context, to: Avo::Current
|
20
|
-
def current_user
|
21
|
-
Avo::Current.user
|
22
|
-
end
|
23
|
-
delegate :params, to: Avo::Current
|
24
|
-
delegate :request, to: Avo::Current
|
25
|
-
delegate :view_context, to: Avo::Current
|
26
|
-
|
27
|
-
# view_context methods
|
28
|
-
delegate :simple_format, :content_tag, to: :view_context
|
29
|
-
delegate :main_app, to: :view_context
|
30
|
-
delegate :avo, to: :view_context
|
31
|
-
delegate :resource_path, to: :view_context
|
32
|
-
delegate :resources_path, to: :view_context
|
33
|
-
|
34
|
-
# I18n methods
|
35
|
-
delegate :t, to: ::I18n
|
36
|
-
|
37
|
-
# class methods
|
38
|
-
delegate :class_name, to: :class
|
39
|
-
delegate :route_key, to: :class
|
40
|
-
delegate :singular_route_key, to: :class
|
41
|
-
|
42
|
-
attr_accessor :view
|
43
|
-
attr_accessor :reflection
|
44
|
-
attr_accessor :user
|
45
|
-
attr_accessor :record
|
46
|
-
|
47
|
-
class_attribute :id, default: :id
|
48
|
-
class_attribute :title
|
49
|
-
class_attribute :search, default: {}
|
50
|
-
class_attribute :includes, default: []
|
51
|
-
class_attribute :attachments, default: []
|
52
|
-
class_attribute :single_includes, default: []
|
53
|
-
class_attribute :single_attachments, default: []
|
54
|
-
class_attribute :authorization_policy
|
55
|
-
class_attribute :translation_key
|
56
|
-
class_attribute :default_view_type, default: :table
|
57
|
-
class_attribute :devise_password_optional, default: false
|
58
|
-
class_attribute :scopes_loader
|
59
|
-
class_attribute :filters_loader
|
60
|
-
class_attribute :view_types
|
61
|
-
class_attribute :grid_view
|
62
|
-
class_attribute :visible_on_sidebar, default: true
|
63
|
-
class_attribute :index_query, default: -> {
|
64
|
-
query
|
65
|
-
}
|
66
|
-
class_attribute :find_record_method, default: -> {
|
67
|
-
query.find id
|
68
|
-
}
|
69
|
-
class_attribute :after_create_path, default: :show
|
70
|
-
class_attribute :after_update_path, default: :show
|
71
|
-
class_attribute :record_selector, default: true
|
72
|
-
class_attribute :keep_filters_panel_open, default: false
|
73
|
-
class_attribute :extra_params
|
74
|
-
class_attribute :link_to_child_resource, default: false
|
75
|
-
class_attribute :map_view
|
76
|
-
class_attribute :components, default: {}
|
77
|
-
|
78
|
-
# EXTRACT:
|
79
|
-
class_attribute :ordering
|
80
|
-
|
81
|
-
class << self
|
82
|
-
delegate :t, to: ::I18n
|
83
|
-
delegate :context, to: ::Avo::Current
|
84
|
-
|
85
|
-
def action(action_class, arguments: {})
|
86
|
-
deprecated_dsl_api __method__, "actions"
|
87
|
-
end
|
88
|
-
|
89
|
-
def filter(filter_class, arguments: {})
|
90
|
-
deprecated_dsl_api __method__, "filters"
|
91
|
-
end
|
92
|
-
|
93
|
-
def scope(scope_class)
|
94
|
-
deprecated_dsl_api __method__, "scopes"
|
95
|
-
end
|
96
|
-
|
97
|
-
# This resolves the scope when doing "where" queries (not find queries)
|
98
|
-
#
|
99
|
-
# It's used to apply the authorization feature.
|
100
|
-
def query_scope
|
101
|
-
authorization.apply_policy Avo::ExecutionContext.new(
|
102
|
-
target: index_query,
|
103
|
-
query: model_class
|
104
|
-
).handle
|
105
|
-
end
|
106
|
-
|
107
|
-
# This resolves the scope when finding records (not "where" queries)
|
108
|
-
#
|
109
|
-
# It's used to apply the authorization feature.
|
110
|
-
def find_scope
|
111
|
-
authorization.apply_policy model_class
|
112
|
-
end
|
113
|
-
|
114
|
-
def authorization
|
115
|
-
Avo::Services::AuthorizationService.new Avo::Current.user, model_class, policy_class: authorization_policy
|
116
|
-
end
|
117
|
-
|
118
|
-
def valid_association_name(record, association_name)
|
119
|
-
association_name if record._reflections.with_indifferent_access[association_name].present?
|
120
|
-
end
|
121
|
-
|
122
|
-
def valid_attachment_name(record, association_name)
|
123
|
-
association_name if record.class.reflect_on_attachment(association_name).present?
|
124
|
-
end
|
125
|
-
|
126
|
-
def get_available_models
|
127
|
-
ApplicationRecord.descendants
|
128
|
-
end
|
129
|
-
|
130
|
-
def get_model_by_name(model_name)
|
131
|
-
get_available_models.find do |m|
|
132
|
-
m.to_s == model_name.to_s
|
133
|
-
end
|
134
|
-
end
|
135
|
-
|
136
|
-
# Returns the model class being used for this resource.
|
137
|
-
#
|
138
|
-
# The Resource instance has a model_class method too so it can support the STI use cases
|
139
|
-
# where we figure out the model class from the record
|
140
|
-
def model_class(record_class: nil)
|
141
|
-
# get the model class off of the static property
|
142
|
-
return @model_class if @model_class.present?
|
143
|
-
|
144
|
-
# get the model class off of the record for STI models
|
145
|
-
return record_class if record_class.present?
|
146
|
-
|
147
|
-
# generate a model class
|
148
|
-
class_name.safe_constantize
|
149
|
-
end
|
150
|
-
|
151
|
-
# This is used as the model class ID
|
152
|
-
# We use this instead of the route_key to maintain compatibility with uncountable models
|
153
|
-
# With uncountable models route key appends an _index suffix (Fish->fish_index)
|
154
|
-
# Example: User->users, MediaItem->media_items, Fish->fish
|
155
|
-
def model_key
|
156
|
-
@model_key ||= model_class.model_name.plural
|
157
|
-
end
|
158
|
-
|
159
|
-
def class_name
|
160
|
-
@class_name ||= to_s.demodulize
|
161
|
-
end
|
162
|
-
|
163
|
-
def route_key
|
164
|
-
class_name.underscore.pluralize
|
165
|
-
end
|
166
|
-
|
167
|
-
def singular_route_key
|
168
|
-
route_key.singularize
|
169
|
-
end
|
170
|
-
|
171
|
-
def translation_key
|
172
|
-
@translation_key || "avo.resource_translations.#{class_name.underscore}"
|
173
|
-
end
|
174
|
-
|
175
|
-
def name
|
176
|
-
@name ||= name_from_translation_key(count: 1, default: class_name.underscore.humanize)
|
177
|
-
end
|
178
|
-
alias_method :singular_name, :name
|
179
|
-
|
180
|
-
def plural_name
|
181
|
-
name_from_translation_key(count: 2, default: name.pluralize)
|
182
|
-
end
|
183
|
-
|
184
|
-
# Get the name from the translation_key and fallback to default
|
185
|
-
# It can raise I18n::InvalidPluralizationData when using only resource_translation without pluralization keys like: one, two or other key
|
186
|
-
# Example:
|
187
|
-
# ---
|
188
|
-
# en:
|
189
|
-
# avo:
|
190
|
-
# resource_translations:
|
191
|
-
# product:
|
192
|
-
# save: "Save product"
|
193
|
-
def name_from_translation_key(count:, default:)
|
194
|
-
t(translation_key, count:, default:).humanize
|
195
|
-
rescue I18n::InvalidPluralizationData
|
196
|
-
default
|
197
|
-
end
|
198
|
-
|
199
|
-
def underscore_name
|
200
|
-
return @name if @name.present?
|
201
|
-
|
202
|
-
name.demodulize.underscore
|
203
|
-
end
|
204
|
-
|
205
|
-
def navigation_label
|
206
|
-
plural_name.humanize
|
207
|
-
end
|
208
|
-
|
209
|
-
def find_record(id, query: nil, params: nil)
|
210
|
-
query ||= find_scope # If no record is given we'll use the default
|
211
|
-
|
212
|
-
if single_includes.present?
|
213
|
-
query = query.includes(*single_includes)
|
214
|
-
end
|
215
|
-
|
216
|
-
if single_attachments.present?
|
217
|
-
single_attachments.each do |attachment|
|
218
|
-
query = query.send(:"with_attached_#{attachment}")
|
219
|
-
end
|
220
|
-
end
|
221
|
-
|
222
|
-
Avo::ExecutionContext.new(
|
223
|
-
target: find_record_method,
|
224
|
-
query: query,
|
225
|
-
id: id,
|
226
|
-
params: params
|
227
|
-
).handle
|
228
|
-
end
|
229
|
-
|
230
|
-
def search_query
|
231
|
-
search.dig(:query)
|
232
|
-
end
|
233
|
-
|
234
|
-
def search_results_count
|
235
|
-
search.dig(:results_count)
|
236
|
-
end
|
237
|
-
|
238
|
-
def fetch_search(key, record: nil)
|
239
|
-
# self.class.fetch_search
|
240
|
-
Avo::ExecutionContext.new(target: search[key], resource: self, record: record).handle
|
241
|
-
end
|
242
|
-
end
|
243
|
-
|
244
|
-
delegate :context, to: ::Avo::Current
|
245
|
-
delegate :name, to: :class
|
246
|
-
delegate :singular_name, to: :class
|
247
|
-
delegate :plural_name, to: :class
|
248
|
-
delegate :underscore_name, to: :class
|
249
|
-
delegate :to_param, to: :class
|
250
|
-
delegate :find_record, to: :class
|
251
|
-
delegate :model_key, to: :class
|
252
|
-
delegate :tab, to: :items_holder
|
253
|
-
|
254
|
-
def initialize(record: nil, view: nil, user: nil, params: nil)
|
255
|
-
@view = Avo::ViewInquirer.new(view) if view.present?
|
256
|
-
@user = user if user.present?
|
257
|
-
@params = params if params.present?
|
258
|
-
|
259
|
-
if record.present?
|
260
|
-
@record = record
|
261
|
-
|
262
|
-
hydrate_model_with_default_values if @view&.new?
|
263
|
-
end
|
264
|
-
|
265
|
-
unless self.class.model_class.present?
|
266
|
-
if model_class.present? && model_class.respond_to?(:base_class)
|
267
|
-
self.class.model_class = model_class.base_class
|
268
|
-
end
|
269
|
-
end
|
270
|
-
end
|
271
|
-
|
272
|
-
def detect_fields
|
273
|
-
self.items_holder = Avo::Resources::Items::Holder.new(parent: self)
|
274
|
-
|
275
|
-
# Used in testing to replace items
|
276
|
-
if temporary_items.present?
|
277
|
-
instance_eval(&temporary_items)
|
278
|
-
else
|
279
|
-
fetch_fields
|
280
|
-
end
|
281
|
-
|
282
|
-
self
|
283
|
-
end
|
284
|
-
|
285
|
-
VIEW_METHODS_MAPPING = {
|
286
|
-
index: [:index_fields, :display_fields],
|
287
|
-
show: [:show_fields, :display_fields],
|
288
|
-
edit: [:edit_fields, :form_fields],
|
289
|
-
update: [:edit_fields, :form_fields],
|
290
|
-
new: [:new_fields, :form_fields],
|
291
|
-
create: [:new_fields, :form_fields]
|
292
|
-
} unless defined? VIEW_METHODS_MAPPING
|
293
|
-
|
294
|
-
def fetch_fields
|
295
|
-
possible_methods_for_view = VIEW_METHODS_MAPPING[view.to_sym]
|
296
|
-
|
297
|
-
# Safe navigation operator is used because the view can be "destroy" or "preview"
|
298
|
-
possible_methods_for_view&.each do |method_for_view|
|
299
|
-
return send(method_for_view) if respond_to?(method_for_view)
|
300
|
-
end
|
301
|
-
|
302
|
-
fields
|
303
|
-
end
|
304
|
-
|
305
|
-
def fetch_cards
|
306
|
-
cards
|
307
|
-
end
|
308
|
-
|
309
|
-
def divider(label = nil)
|
310
|
-
entity_loader(:action).use({class: Divider, label: label}.compact)
|
311
|
-
end
|
312
|
-
|
313
|
-
# def fields / def cards
|
314
|
-
[:fields, :cards].each do |method_name|
|
315
|
-
define_method method_name do
|
316
|
-
# Empty method
|
317
|
-
end
|
318
|
-
end
|
319
|
-
|
320
|
-
[:action, :filter, :scope].each do |entity|
|
321
|
-
plural_entity = entity.to_s.pluralize
|
322
|
-
|
323
|
-
# def actions / def filters / def scopes
|
324
|
-
define_method plural_entity do
|
325
|
-
# blank entity method
|
326
|
-
end
|
327
|
-
|
328
|
-
# def action / def filter / def scope
|
329
|
-
define_method entity do |entity_class, arguments: {}, icon: nil|
|
330
|
-
entity_loader(entity).use({class: entity_class, arguments: arguments, icon: icon}.compact)
|
331
|
-
end
|
332
|
-
|
333
|
-
# def get_actions / def get_filters / def get_scopes
|
334
|
-
define_method "get_#{plural_entity}" do
|
335
|
-
return entity_loader(entity).bag if entity_loader(entity).present?
|
336
|
-
|
337
|
-
# ex: @actions_loader = Avo::Loaders::ActionsLoader.new
|
338
|
-
instance_variable_set(
|
339
|
-
"@#{plural_entity}_loader",
|
340
|
-
"Avo::Loaders::#{plural_entity.humanize}Loader".constantize.new
|
341
|
-
)
|
342
|
-
|
343
|
-
send plural_entity
|
344
|
-
|
345
|
-
entity_loader(entity).bag
|
346
|
-
end
|
347
|
-
|
348
|
-
# def get_action_arguments / def get_filter_arguments / def get_scope_arguments
|
349
|
-
define_method "get_#{entity}_arguments" do |entity_class|
|
350
|
-
klass = send("get_#{plural_entity}").find { |entity| entity[:class].to_s == entity_class.to_s }
|
351
|
-
|
352
|
-
raise "Couldn't find '#{entity_class}' in the 'def #{plural_entity}' method on your '#{self.class}' resource." if klass.nil?
|
353
|
-
|
354
|
-
klass[:arguments]
|
355
|
-
end
|
356
|
-
end
|
357
|
-
|
358
|
-
def hydrate(...)
|
359
|
-
super(...)
|
360
|
-
|
361
|
-
if @record.present?
|
362
|
-
hydrate_model_with_default_values if @view&.new?
|
363
|
-
end
|
364
|
-
|
365
|
-
self
|
366
|
-
end
|
367
|
-
|
368
|
-
def default_panel_name
|
369
|
-
return @params[:related_name].capitalize if @params.present? && @params[:related_name].present?
|
370
|
-
|
371
|
-
case @view.to_sym
|
372
|
-
when :show
|
373
|
-
record_title
|
374
|
-
when :edit
|
375
|
-
record_title
|
376
|
-
when :new
|
377
|
-
t("avo.create_new_item", item: name.humanize(capitalize: false)).upcase_first
|
378
|
-
end
|
379
|
-
end
|
380
|
-
|
381
|
-
# Returns the model class being used for this resource.
|
382
|
-
#
|
383
|
-
# We use the class method as a fallback but we pass it the record too so it can support the STI use cases
|
384
|
-
# where we figure out the model class from that record.
|
385
|
-
def model_class
|
386
|
-
record_class = @record&.class
|
387
|
-
|
388
|
-
self.class.model_class record_class: record_class
|
389
|
-
end
|
390
|
-
|
391
|
-
def record_title
|
392
|
-
return name if @record.nil?
|
393
|
-
|
394
|
-
# Get the title from the record if title is not set, try to get the name, title or label, or fallback to the id
|
395
|
-
return @record.try(:name) || @record.try(:title) || @record.try(:label) || @record.id if title.nil?
|
396
|
-
|
397
|
-
# If the title is a symbol, get the value from the record else execute the block/string
|
398
|
-
case title
|
399
|
-
when Symbol
|
400
|
-
@record.send title
|
401
|
-
when Proc
|
402
|
-
Avo::ExecutionContext.new(target: title, resource: self, record: @record).handle
|
403
|
-
end
|
404
|
-
end
|
405
|
-
|
406
|
-
def available_view_types
|
407
|
-
if self.class.view_types.present?
|
408
|
-
return Array(
|
409
|
-
Avo::ExecutionContext.new(
|
410
|
-
target: self.class.view_types,
|
411
|
-
resource: self,
|
412
|
-
record: record
|
413
|
-
).handle
|
414
|
-
)
|
415
|
-
end
|
416
|
-
|
417
|
-
view_types = [:table]
|
418
|
-
|
419
|
-
view_types << :grid if self.class.grid_view.present?
|
420
|
-
view_types << :map if map_view.present?
|
421
|
-
|
422
|
-
view_types
|
423
|
-
end
|
424
|
-
|
425
|
-
def attachment_fields
|
426
|
-
get_field_definitions.select do |field|
|
427
|
-
[Avo::Fields::FileField, Avo::Fields::FilesField].include? field.class
|
428
|
-
end
|
429
|
-
end
|
430
|
-
|
431
|
-
# Map the received params to their actual fields
|
432
|
-
def fields_by_database_id
|
433
|
-
get_field_definitions
|
434
|
-
.reject do |field|
|
435
|
-
field.computed
|
436
|
-
end
|
437
|
-
.map do |field|
|
438
|
-
[field.database_id.to_s, field]
|
439
|
-
end
|
440
|
-
.to_h
|
441
|
-
end
|
442
|
-
|
443
|
-
def fill_record(record, params, extra_params: [])
|
444
|
-
# Write the field values
|
445
|
-
params.each do |key, value|
|
446
|
-
field = fields_by_database_id[key]
|
447
|
-
|
448
|
-
next unless field.present?
|
449
|
-
|
450
|
-
record = field.fill_field record, key, value, params
|
451
|
-
end
|
452
|
-
|
453
|
-
# Write the user configured extra params to the record
|
454
|
-
if extra_params.present?
|
455
|
-
# Let Rails fill in the rest of the params
|
456
|
-
record.assign_attributes params.permit(extra_params)
|
457
|
-
end
|
458
|
-
|
459
|
-
record
|
460
|
-
end
|
461
|
-
|
462
|
-
def authorization(user: nil)
|
463
|
-
current_user = user || Avo::Current.user
|
464
|
-
Avo::Services::AuthorizationService.new(current_user, record || model_class, policy_class: authorization_policy)
|
465
|
-
end
|
466
|
-
|
467
|
-
def file_hash
|
468
|
-
content_to_be_hashed = ""
|
469
|
-
|
470
|
-
resource_path = Rails.root.join("app", "avo", "resources", "#{file_name}.rb").to_s
|
471
|
-
if File.file? resource_path
|
472
|
-
content_to_be_hashed += File.read(resource_path)
|
473
|
-
end
|
474
|
-
|
475
|
-
# policy file hash
|
476
|
-
policy_path = Rails.root.join("app", "policies", "#{file_name.gsub("_resource", "")}_policy.rb").to_s
|
477
|
-
if File.file? policy_path
|
478
|
-
content_to_be_hashed += File.read(policy_path)
|
479
|
-
end
|
480
|
-
|
481
|
-
Digest::MD5.hexdigest(content_to_be_hashed)
|
482
|
-
end
|
483
|
-
|
484
|
-
def file_name
|
485
|
-
@file_name ||= self.class.underscore_name.tr(" ", "_")
|
486
|
-
end
|
487
|
-
|
488
|
-
def cache_hash(parent_record)
|
489
|
-
result = [record, file_hash]
|
490
|
-
|
491
|
-
if parent_record.present?
|
492
|
-
result << parent_record
|
493
|
-
end
|
494
|
-
|
495
|
-
result
|
496
|
-
end
|
497
|
-
|
498
|
-
# We will not overwrite any attributes that come pre-filled in the record.
|
499
|
-
def hydrate_model_with_default_values
|
500
|
-
default_values = get_fields
|
501
|
-
.select do |field|
|
502
|
-
!field.computed && !field.is_a?(Avo::Fields::HeadingField)
|
503
|
-
end
|
504
|
-
.map do |field|
|
505
|
-
value = field.value
|
506
|
-
|
507
|
-
if field.type == "belongs_to"
|
508
|
-
|
509
|
-
reflection = @record._reflections.with_indifferent_access[@params[:via_relation]]
|
510
|
-
|
511
|
-
if field.polymorphic_as.present? && field.types.map(&:to_s).include?(@params[:via_relation_class])
|
512
|
-
# set the value to the actual record
|
513
|
-
via_resource = Avo.resource_manager.get_resource_by_model_class(@params[:via_relation_class])
|
514
|
-
value = via_resource.find_record(@params[:via_record_id])
|
515
|
-
elsif reflection.present? && reflection.foreign_key.present? && field.id.to_s == @params[:via_relation].to_s
|
516
|
-
resource = Avo.resource_manager.get_resource_by_model_class params[:via_relation_class]
|
517
|
-
record = resource.find_record @params[:via_record_id], params: params
|
518
|
-
id_param = reflection.options[:primary_key] || :id
|
519
|
-
|
520
|
-
value = record.send(id_param)
|
521
|
-
end
|
522
|
-
end
|
523
|
-
|
524
|
-
[field, value]
|
525
|
-
end
|
526
|
-
.to_h
|
527
|
-
.select do |_, value|
|
528
|
-
value.present?
|
529
|
-
end
|
530
|
-
|
531
|
-
default_values.each do |field, value|
|
532
|
-
field.assign_value record: @record, value: value
|
533
|
-
end
|
534
|
-
end
|
535
|
-
|
536
|
-
def model_name
|
537
|
-
model_class.model_name
|
538
|
-
end
|
539
|
-
|
540
|
-
def singular_model_key
|
541
|
-
model_class.model_name.singular
|
542
|
-
end
|
543
|
-
|
544
|
-
def record_path
|
545
|
-
resource_path(record: record, resource: self)
|
546
|
-
end
|
547
|
-
|
548
|
-
def records_path
|
549
|
-
resources_path(resource: self)
|
550
|
-
end
|
551
|
-
|
552
|
-
def avatar_field
|
553
|
-
get_field_definitions.find do |field|
|
554
|
-
field.as_avatar.present?
|
555
|
-
end
|
556
|
-
rescue
|
557
|
-
nil
|
558
|
-
end
|
559
|
-
|
560
|
-
def avatar
|
561
|
-
return avatar_field.to_image if avatar_field.respond_to? :to_image
|
562
|
-
|
563
|
-
return avatar_field.value.variant(resize_to_limit: [480, 480]) if avatar_field.type == "file"
|
564
|
-
|
565
|
-
avatar_field.value
|
566
|
-
rescue
|
567
|
-
nil
|
568
|
-
end
|
569
|
-
|
570
|
-
def avatar_type
|
571
|
-
avatar_field.as_avatar
|
572
|
-
rescue
|
573
|
-
nil
|
574
|
-
end
|
575
|
-
|
576
|
-
def form_scope
|
577
|
-
model_class.base_class.to_s.underscore.downcase
|
578
|
-
end
|
579
|
-
|
580
|
-
def has_record_id?
|
581
|
-
record.present? && record_id.present?
|
582
|
-
end
|
583
|
-
|
584
|
-
def id_attribute
|
585
|
-
:id
|
586
|
-
end
|
587
|
-
|
588
|
-
def record_id
|
589
|
-
record.send(id_attribute)
|
590
|
-
end
|
591
|
-
|
592
|
-
def description_attributes
|
593
|
-
{
|
594
|
-
view: view,
|
595
|
-
resource: self,
|
596
|
-
record: record
|
597
|
-
}
|
598
|
-
end
|
599
|
-
|
600
|
-
def entity_loader(entity)
|
601
|
-
instance_variable_get("@#{entity.to_s.pluralize}_loader")
|
602
|
-
end
|
2
|
+
class BaseResource < Avo::Resources::Base
|
3
|
+
# Users can override this class to add custom methods for all resources.
|
603
4
|
end
|
604
5
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
require "net/http"
|
2
|
+
|
1
3
|
module Avo
|
2
4
|
module Licensing
|
3
5
|
class Request
|
@@ -8,7 +10,7 @@ module Avo
|
|
8
10
|
http.use_ssl = (uri.scheme == "https")
|
9
11
|
http.read_timeout = timeout
|
10
12
|
http.open_timeout = timeout
|
11
|
-
request = Net::HTTP::Post.new(uri.request_uri, {
|
13
|
+
request = Net::HTTP::Post.new(uri.request_uri, {"Content-Type" => "application/json"})
|
12
14
|
request.body = body
|
13
15
|
http.request(request)
|
14
16
|
end
|