ecoportal-api-v2 1.1.6 → 1.1.8
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.
- checksums.yaml +4 -4
- data/.rubocop.yml +54 -15
- data/CHANGELOG.md +17 -2
- data/lib/ecoportal/api/common/concerns/benchmarkable.rb +160 -0
- data/lib/ecoportal/api/common/concerns.rb +10 -0
- data/lib/ecoportal/api/common/content/array_model.rb +82 -79
- data/lib/ecoportal/api/common/content/class_helpers.rb +25 -26
- data/lib/ecoportal/api/common/content/collection_model.rb +108 -84
- data/lib/ecoportal/api/common/content/double_model.rb +125 -87
- data/lib/ecoportal/api/common.v2.rb +1 -0
- data/lib/ecoportal/api/v2/page/component.rb +60 -64
- data/lib/ecoportal/api/v2/page/components.rb +9 -9
- data/lib/ecoportal/api/v2/page/force.rb +5 -6
- data/lib/ecoportal/api/v2/page.rb +13 -14
- data/lib/ecoportal/api/v2_version.rb +1 -1
- metadata +4 -2
@@ -6,12 +6,8 @@ module Ecoportal
|
|
6
6
|
# which differs of `attr_*` ruby native class methods because `pass*`
|
7
7
|
# completelly **links** the methods **to a subjacent `Hash` model**
|
8
8
|
class DoubleModel < Common::BaseModel
|
9
|
-
NOT_USED = Common::Content::ClassHelpers::NOT_USED
|
10
|
-
extend Common::Content::ClassHelpers
|
11
|
-
include Common::Content::ModelHelpers
|
12
|
-
|
13
9
|
class UnlinkedModel < StandardError
|
14
|
-
def initialize
|
10
|
+
def initialize(msg = "Something went wrong when linking the document.", from: nil, key: nil)
|
15
11
|
msg += " From: #{from}." if from
|
16
12
|
msg += " key: #{key}." if key
|
17
13
|
super(msg)
|
@@ -21,6 +17,10 @@ module Ecoportal
|
|
21
17
|
class NoKeyMethod < StandardError
|
22
18
|
end
|
23
19
|
|
20
|
+
NOT_USED = Common::Content::ClassHelpers::NOT_USED
|
21
|
+
extend Common::Content::ClassHelpers
|
22
|
+
include Common::Content::ModelHelpers
|
23
|
+
|
24
24
|
class << self
|
25
25
|
attr_reader :key
|
26
26
|
|
@@ -38,6 +38,16 @@ module Ecoportal
|
|
38
38
|
uid(length)
|
39
39
|
end
|
40
40
|
|
41
|
+
def read_only?
|
42
|
+
@read_only = false if @read_only.nil?
|
43
|
+
@read_only
|
44
|
+
end
|
45
|
+
|
46
|
+
# Be able to define if a class should be read-only
|
47
|
+
def read_only!
|
48
|
+
@read_only = true
|
49
|
+
end
|
50
|
+
|
41
51
|
# Same as `attr_reader` but links to a subjacent `Hash` model property
|
42
52
|
# @note it does **not** create an _instance variable_
|
43
53
|
# @param methods [Array<Symbol>] the method that exposes the value
|
@@ -108,7 +118,7 @@ module Ecoportal
|
|
108
118
|
# as well as its `key` in the underlying `Hash` model.
|
109
119
|
# @param default [Value] the default value that
|
110
120
|
# this `key` will be written in the model when it doesn't exixt
|
111
|
-
def passforced(method, default
|
121
|
+
def passforced(method, default:, read_only: false)
|
112
122
|
model_forced_keys[method.to_s.freeze] = default
|
113
123
|
passthrough(method, read_only: read_only)
|
114
124
|
end
|
@@ -116,8 +126,9 @@ module Ecoportal
|
|
116
126
|
# Ensures `doc` has the `model_forced_keys`. If it doesn't, it adds those missing
|
117
127
|
# with the defined `default` values
|
118
128
|
def enforce!(doc)
|
119
|
-
return unless doc
|
120
|
-
return if
|
129
|
+
return unless doc.is_a?(Hash)
|
130
|
+
return if model_forced_keys.empty?
|
131
|
+
|
121
132
|
model_forced_keys.each do |key, default|
|
122
133
|
doc[key] = default unless doc.key?(key)
|
123
134
|
end
|
@@ -129,8 +140,8 @@ module Ecoportal
|
|
129
140
|
# as well as its `key` in the underlying `Hash` model.
|
130
141
|
# @param read_only [Boolean] should it only define the reader?
|
131
142
|
def passthrough(*methods, read_only: false)
|
132
|
-
pass_reader
|
133
|
-
pass_writer
|
143
|
+
pass_reader(*methods)
|
144
|
+
pass_writer(*methods) unless read_only
|
134
145
|
self
|
135
146
|
end
|
136
147
|
|
@@ -141,9 +152,7 @@ module Ecoportal
|
|
141
152
|
# @param read_only [Boolean] should it only define the reader?
|
142
153
|
def passdate(*methods, read_only: false)
|
143
154
|
pass_reader(*methods) {|value| to_time(value)}
|
144
|
-
unless read_only
|
145
|
-
pass_writer(*methods) {|value| to_time(value)&.iso8601}
|
146
|
-
end
|
155
|
+
pass_writer(*methods) {|value| to_time(value)&.iso8601} unless read_only
|
147
156
|
self
|
148
157
|
end
|
149
158
|
|
@@ -153,9 +162,7 @@ module Ecoportal
|
|
153
162
|
# @param read_only [Boolean] should it only define the reader?
|
154
163
|
def passboolean(*methods, read_only: false)
|
155
164
|
pass_reader(*methods) {|value| value}
|
156
|
-
unless read_only
|
157
|
-
pass_writer(*methods) {|value| !!value}
|
158
|
-
end
|
165
|
+
pass_writer(*methods) {|value| !!value} unless read_only
|
159
166
|
self
|
160
167
|
end
|
161
168
|
|
@@ -176,7 +183,7 @@ module Ecoportal
|
|
176
183
|
|
177
184
|
define_method method do
|
178
185
|
return instance_variable_get(var) if instance_variable_defined?(var)
|
179
|
-
new_obj = dim_class.new(parent: self, key: method, read_only:
|
186
|
+
new_obj = dim_class.new(parent: self, key: method, read_only: read_only?)
|
180
187
|
variable_set(var, new_obj)
|
181
188
|
end
|
182
189
|
end
|
@@ -187,7 +194,7 @@ module Ecoportal
|
|
187
194
|
# @param key [Symbol] the `key` that embeds it to the underlying `Hash` model
|
188
195
|
# @nullable [Boolean] to specify if this object can be `nil`
|
189
196
|
# @param klass [Class, String] the class of the embedded object
|
190
|
-
def embeds_one(method, key: method, nullable: false
|
197
|
+
def embeds_one(method, klass:, key: method, nullable: false)
|
191
198
|
embed(method, key: key, nullable: nullable, multiple: false, klass: klass)
|
192
199
|
end
|
193
200
|
|
@@ -202,73 +209,83 @@ module Ecoportal
|
|
202
209
|
# @param read_only [Boolean] whether or not should try to **work around** items `klass` missing a `key`
|
203
210
|
# - If set to `true` this is meant only for read purposes (won't be able to successufully insert)
|
204
211
|
def embeds_many(method, key: method, klass: nil, enum_class: nil,
|
205
|
-
order_matters: false, order_key: nil, read_only:
|
212
|
+
order_matters: false, order_key: nil, read_only: read_only?)
|
206
213
|
if enum_class
|
207
214
|
eclass = enum_class
|
208
215
|
elsif klass
|
209
216
|
eclass = new_class("#{method}::#{klass}", inherits: Common::Content::CollectionModel) do |dim_class|
|
210
|
-
|
217
|
+
# NOTE: new_class may resolve the namespace of the class to an already existing class
|
218
|
+
dim_class.klass ||= klass
|
211
219
|
dim_class.order_matters = order_matters
|
212
220
|
dim_class.order_key = order_key
|
221
|
+
dim_class.read_only! if read_only
|
213
222
|
end
|
214
223
|
else
|
215
224
|
raise "You should either specify the 'klass' of the elements or the 'enum_class'"
|
216
225
|
end
|
217
|
-
|
226
|
+
|
227
|
+
embed(
|
228
|
+
method, key: key,
|
229
|
+
multiple: true, klass: eclass,
|
230
|
+
read_only: read_only
|
231
|
+
) do |instance_with_called_method|
|
218
232
|
# keep reference to the original class to resolve the `klass` dependency
|
219
233
|
# See stackoverflow: https://stackoverflow.com/a/73709529/4352306
|
220
234
|
referrer_class = instance_with_called_method.class
|
221
|
-
eclass.klass
|
235
|
+
eclass.klass = {referrer_class => klass} if klass
|
236
|
+
# This helps `resolve_class` to correctly resolve a symbol
|
237
|
+
# by using referrer_class as a base module to resolve it
|
222
238
|
end
|
223
239
|
end
|
224
240
|
|
225
241
|
private
|
226
242
|
|
227
|
-
def embed(
|
243
|
+
def embed(
|
244
|
+
method, klass:, key: method,
|
245
|
+
nullable: false, multiple: false, read_only: read_only?,
|
246
|
+
&embed_block
|
247
|
+
)
|
228
248
|
method = method.to_s.freeze
|
229
249
|
var = instance_variable_name(method).freeze
|
230
|
-
|
250
|
+
obj_k = key.to_s.freeze
|
231
251
|
|
232
252
|
# retrieving method (getter)
|
233
253
|
define_method(method) do
|
234
|
-
|
254
|
+
# set item klass as referrer to klass (to allow resolve symbol)
|
255
|
+
embed_block&.call(self)
|
235
256
|
return instance_variable_get(var) if instance_variable_defined?(var)
|
236
|
-
unless nullable
|
237
|
-
doc[k] ||= multiple ? [] : {}
|
238
|
-
end
|
239
|
-
return variable_set(var, nil) unless doc[k]
|
240
257
|
|
241
|
-
|
258
|
+
doc[obj_k] ||= (multiple ? [] : {}) unless nullable
|
259
|
+
return variable_set(var, nil) unless doc[obj_k]
|
242
260
|
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
embedded_class.new(doc[k], parent: self, key: k, read_only: self._read_only || read_only).tap do |obj|
|
255
|
-
variable_set(var, obj)
|
261
|
+
embedded_class = self.class.resolve_class(klass)
|
262
|
+
setup_items_key(embedded_class, doc[obj_k]) if multiple && read_only
|
263
|
+
|
264
|
+
embedded_class.new(
|
265
|
+
doc[obj_k],
|
266
|
+
parent: self,
|
267
|
+
key: obj_k,
|
268
|
+
read_only: read_only? || read_only
|
269
|
+
).tap do |collection|
|
270
|
+
variable_set(var, collection)
|
256
271
|
end
|
257
272
|
end
|
258
273
|
end
|
259
274
|
|
260
275
|
# The list of keys that will be forced in the model
|
261
276
|
def model_forced_keys
|
262
|
-
@
|
277
|
+
@model_forced_keys ||= {}
|
263
278
|
end
|
264
279
|
end
|
265
280
|
|
266
|
-
inheritable_class_vars :
|
281
|
+
inheritable_class_vars :model_forced_keys, :key, :read_only
|
267
282
|
|
268
|
-
# `_key` refers to the
|
283
|
+
# `_key` refers to the `_parent`'s property that links to this model
|
284
|
+
# @note while `key` refers to the value of theproperty of this model
|
285
|
+
# that is key (identifies an item in a set of elements)
|
269
286
|
attr_reader :_parent, :_key, :_read_only
|
270
287
|
|
271
|
-
def initialize(doc = {}, parent: self, key: nil, read_only:
|
288
|
+
def initialize(doc = {}, parent: self, key: nil, read_only: self.class.read_only?) # rubocop:disable Lint/MissingSuper
|
272
289
|
@_dim_vars = []
|
273
290
|
@_parent = parent || self
|
274
291
|
@_key = key || self
|
@@ -281,10 +298,16 @@ module Ecoportal
|
|
281
298
|
@original_doc = JSON.parse(@doc.to_json)
|
282
299
|
end
|
283
300
|
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
301
|
+
return unless key_method? && doc && doc.is_a?(Hash)
|
302
|
+
|
303
|
+
self.key = doc[key_method]
|
304
|
+
#puts "\n$(#{self.key}<=>#{self.class})"
|
305
|
+
end
|
306
|
+
|
307
|
+
# @note `read_only` allows for some optimizations, such as storing values
|
308
|
+
# in instance variables, for optimization purposes
|
309
|
+
def read_only?
|
310
|
+
@_read_only
|
288
311
|
end
|
289
312
|
|
290
313
|
def root
|
@@ -294,15 +317,20 @@ module Ecoportal
|
|
294
317
|
|
295
318
|
# @return [String] the `value` of the `key` method (i.e. `id` value)
|
296
319
|
def key
|
297
|
-
raise NoKeyMethod
|
298
|
-
|
320
|
+
raise NoKeyMethod, "No key_method defined for #{self.class}" unless key_method?
|
321
|
+
|
322
|
+
method(key_method).call
|
299
323
|
end
|
300
324
|
|
301
325
|
# @param [String] the `value` of the `key` method (i.e. `id` value)
|
302
326
|
def key=(value)
|
303
|
-
raise NoKeyMethod
|
304
|
-
|
305
|
-
|
327
|
+
raise NoKeyMethod, "No key_method defined for #{self.class}" unless key_method?
|
328
|
+
|
329
|
+
method("#{key_method}=").call(value)
|
330
|
+
end
|
331
|
+
|
332
|
+
def resolved_doc_key
|
333
|
+
[_doc_key(_key)]
|
306
334
|
end
|
307
335
|
|
308
336
|
# Offers a method for child classes to transform the key,
|
@@ -320,25 +348,22 @@ module Ecoportal
|
|
320
348
|
# @return [nil, Hash] the underlying `Hash` model as is (carrying current changes)
|
321
349
|
def doc
|
322
350
|
return @doc if doc_var?
|
351
|
+
|
323
352
|
raise UnlinkedModel.new(from: "#{self.class}#doc", key: _key) unless linked?
|
324
|
-
if is_root?
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
_parent.doc.dig(*[_doc_key(_key)].flatten)
|
330
|
-
end
|
353
|
+
return @doc if is_root?
|
354
|
+
|
355
|
+
# transform parent's `_key` to this object into a
|
356
|
+
# path key that can rerieve from the parents's doc
|
357
|
+
_parent.doc.dig(*resolved_doc_key.flatten)
|
331
358
|
end
|
332
359
|
|
333
360
|
# The `original_doc` holds the model as is now on server-side.
|
334
361
|
# @return [nil, Hash] the underlying `Hash` model as after last `consolidate!` changes
|
335
362
|
def original_doc
|
336
363
|
raise UnlinkedModel.new(from: "#{self.class}#original_doc", key: _key) unless linked?
|
337
|
-
if is_root?
|
338
|
-
|
339
|
-
|
340
|
-
_parent.original_doc.dig(*[_doc_key(_key)].flatten)
|
341
|
-
end
|
364
|
+
return @original_doc if is_root?
|
365
|
+
|
366
|
+
_parent.original_doc.dig(*resolved_doc_key.flatten)
|
342
367
|
end
|
343
368
|
|
344
369
|
def as_json
|
@@ -359,7 +384,7 @@ module Ecoportal
|
|
359
384
|
# @return [Boolean] stating if there are changes
|
360
385
|
def dirty?
|
361
386
|
au = as_update
|
362
|
-
!((au == {}) ||
|
387
|
+
!((au == {}) || au.nil?)
|
363
388
|
end
|
364
389
|
|
365
390
|
# It makes `original_doc` to be like `doc`
|
@@ -379,7 +404,7 @@ module Ecoportal
|
|
379
404
|
if key
|
380
405
|
keys = [key].flatten.compact
|
381
406
|
odoc = original_doc.dig(*keys)
|
382
|
-
odoc
|
407
|
+
odoc &&= JSON.parse(odoc.to_json)
|
383
408
|
dig_set(doc, keys, odoc)
|
384
409
|
else
|
385
410
|
replace_doc(JSON.parse(original_doc.to_json))
|
@@ -393,13 +418,11 @@ module Ecoportal
|
|
393
418
|
|
394
419
|
def replace_doc(new_doc)
|
395
420
|
raise UnlinkedModel.new(from: "#{self.class}#replace_doc", key: _key) unless linked?
|
396
|
-
if is_root?
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
#variables_remove!
|
402
|
-
end
|
421
|
+
return (@doc = new_doc) if is_root?
|
422
|
+
|
423
|
+
dig_set(_parent.doc, resolved_doc_key.flatten, new_doc)
|
424
|
+
_parent.variable_remove!(_key) unless new_doc
|
425
|
+
#variables_remove!
|
403
426
|
end
|
404
427
|
|
405
428
|
protected
|
@@ -408,6 +431,9 @@ module Ecoportal
|
|
408
431
|
!!defined?(@doc)
|
409
432
|
end
|
410
433
|
|
434
|
+
# Both requisites
|
435
|
+
# @note that for optimization purposes, `@doc` var may be used when
|
436
|
+
# the object is `read_only?`
|
411
437
|
def is_root?
|
412
438
|
_parent == self && doc_var?
|
413
439
|
end
|
@@ -418,11 +444,9 @@ module Ecoportal
|
|
418
444
|
|
419
445
|
def replace_original_doc(new_doc)
|
420
446
|
raise UnlinkedModel.new(from: "#{self.class}#replace_original_doc", key: _key) unless linked?
|
421
|
-
if is_root?
|
422
|
-
|
423
|
-
|
424
|
-
dig_set(_parent.original_doc, [_doc_key(_key)].flatten, new_doc)
|
425
|
-
end
|
447
|
+
return (@original_doc = new_doc) if is_root?
|
448
|
+
|
449
|
+
dig_set(_parent.original_doc, resolved_doc_key.flatten, new_doc)
|
426
450
|
end
|
427
451
|
|
428
452
|
# Helper to track down persistent variables
|
@@ -435,16 +459,16 @@ module Ecoportal
|
|
435
459
|
# Helper to remove tracked down instance variables
|
436
460
|
def variable_remove!(key)
|
437
461
|
var = instance_variable_name(key)
|
438
|
-
unless
|
439
|
-
|
440
|
-
|
441
|
-
|
462
|
+
return unless @_dim_vars.include?(var)
|
463
|
+
|
464
|
+
@_dim_vars.delete(var)
|
465
|
+
remove_instance_variable(var)
|
442
466
|
end
|
443
467
|
|
444
468
|
# Removes all the persistent variables
|
445
469
|
def variables_remove!
|
446
470
|
#puts "going to remove vars: #{@_dim_vars} on #{self.class} (parent: #{identify_parent(self._parent)})"
|
447
|
-
@_dim_vars.dup.map {|
|
471
|
+
@_dim_vars.dup.map {|var| variable_remove!(var)}
|
448
472
|
end
|
449
473
|
|
450
474
|
private
|
@@ -482,6 +506,20 @@ module Ecoportal
|
|
482
506
|
self.class.key
|
483
507
|
end
|
484
508
|
|
509
|
+
# It allows to work-around missing item_key
|
510
|
+
def setup_items_key(embedded_class, obj_doc)
|
511
|
+
# only if is going to be a collection
|
512
|
+
return unless obj_doc.is_a?(Array) && embedded_class < Common::Content::CollectionModel
|
513
|
+
return unless (item_class = embedded_class.klass)
|
514
|
+
# if already has key don't need to work around
|
515
|
+
return if item_class&.key
|
516
|
+
|
517
|
+
# apply work around
|
518
|
+
item_class.passkey :id
|
519
|
+
obj_doc.each_with_index do |item_doc, idx|
|
520
|
+
item_doc["id"] = idx.to_s unless item_doc.key?("id")
|
521
|
+
end
|
522
|
+
end
|
485
523
|
end
|
486
524
|
end
|
487
525
|
end
|
@@ -30,65 +30,64 @@ module Ecoportal
|
|
30
30
|
class << self
|
31
31
|
def new_doc(type: nil)
|
32
32
|
{
|
33
|
-
"id"
|
33
|
+
"id" => new_uuid
|
34
34
|
}.tap do |base_doc|
|
35
35
|
if type
|
36
36
|
base_doc.merge!({"type" => type})
|
37
|
-
if klass = get_class(base_doc)
|
37
|
+
if (klass = get_class(base_doc))
|
38
38
|
base_doc.merge!(klass.new_doc || {})
|
39
39
|
end
|
40
40
|
end
|
41
41
|
end
|
42
42
|
end
|
43
43
|
|
44
|
-
def get_class(doc)
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
end
|
44
|
+
def get_class(doc) # rubocop:disable Metrics/AbcSize
|
45
|
+
return nil unless doc.is_a?(Hash)
|
46
|
+
case doc["type"]
|
47
|
+
when "tag_field"
|
48
|
+
tag_field_class
|
49
|
+
when "geo"
|
50
|
+
geo_field_class
|
51
|
+
when "select"
|
52
|
+
selection_field_class
|
53
|
+
when "date"
|
54
|
+
date_field_class
|
55
|
+
when "number"
|
56
|
+
number_field_class
|
57
|
+
when "gauge"
|
58
|
+
gauge_field_class
|
59
|
+
when "plain_text"
|
60
|
+
plain_text_field_class
|
61
|
+
when "rich_text"
|
62
|
+
rich_text_field_class
|
63
|
+
when "people"
|
64
|
+
people_field_class
|
65
|
+
when "contractor_entities"
|
66
|
+
contractor_entities_field_class
|
67
|
+
when "checklist"
|
68
|
+
checklist_field_class
|
69
|
+
when "page_action", "checklist_task"
|
70
|
+
action_field_class
|
71
|
+
when "actions_list"
|
72
|
+
actions_field_class
|
73
|
+
when "file"
|
74
|
+
files_field_class
|
75
|
+
when "image_gallery"
|
76
|
+
images_field_class
|
77
|
+
when "signature"
|
78
|
+
signature_field_class
|
79
|
+
when "cross_reference"
|
80
|
+
reference_field_class
|
81
|
+
when "law"
|
82
|
+
law_field_class
|
83
|
+
when "mailbox"
|
84
|
+
mailbox_field_class
|
85
|
+
when "chart"
|
86
|
+
chart_field_class
|
87
|
+
when "frequency_rate_chart"
|
88
|
+
chart_fr_field_class
|
89
|
+
else
|
90
|
+
self
|
92
91
|
end
|
93
92
|
end
|
94
93
|
end
|
@@ -103,7 +102,7 @@ module Ecoportal
|
|
103
102
|
passarray :refs
|
104
103
|
|
105
104
|
def ooze
|
106
|
-
|
105
|
+
_parent.ooze
|
107
106
|
end
|
108
107
|
|
109
108
|
def ref_backend
|
@@ -111,9 +110,9 @@ module Ecoportal
|
|
111
110
|
end
|
112
111
|
|
113
112
|
def ref(any_length: false)
|
114
|
-
|
115
|
-
|
116
|
-
|
113
|
+
digest = self.class.hash_label(label, any_length: any_length)
|
114
|
+
return unless digest
|
115
|
+
[type, digest].join(".")
|
117
116
|
end
|
118
117
|
|
119
118
|
# Looks up the section that this component belongs to.
|
@@ -159,7 +158,7 @@ module Ecoportal
|
|
159
158
|
|
160
159
|
# @return [Boolean] `true` if the component is bound to any force, `false` otherwise
|
161
160
|
def bindings?
|
162
|
-
forces.count
|
161
|
+
forces.count&.positive?
|
163
162
|
end
|
164
163
|
|
165
164
|
# If the field has bindings they are replaced by this new field
|
@@ -168,10 +167,10 @@ module Ecoportal
|
|
168
167
|
if fld.section
|
169
168
|
fld.move(section: self.section, before: self)
|
170
169
|
else
|
171
|
-
|
170
|
+
section.add(fld, before: self)
|
172
171
|
end
|
173
172
|
replace_bindings(fld)
|
174
|
-
|
173
|
+
delete!
|
175
174
|
end
|
176
175
|
|
177
176
|
def replace_bindings(fld)
|
@@ -180,12 +179,12 @@ module Ecoportal
|
|
180
179
|
|
181
180
|
def delete!
|
182
181
|
bindings.each {|b| b.delete!}
|
183
|
-
|
184
|
-
|
182
|
+
unattach!
|
183
|
+
_parent.delete!(self)
|
185
184
|
end
|
186
185
|
|
187
186
|
def move(section:, before: nil, after: nil, side: nil)
|
188
|
-
|
187
|
+
unattach!
|
189
188
|
section.add_component(self, before: before, after: after, side: side)
|
190
189
|
end
|
191
190
|
|
@@ -212,9 +211,7 @@ module Ecoportal
|
|
212
211
|
when :hide_reports
|
213
212
|
self.hidden_on_reports = true
|
214
213
|
when Hash
|
215
|
-
if cnf.key?(:global)
|
216
|
-
self.global_binding = cnf[:global]
|
217
|
-
end
|
214
|
+
self.global_binding = cnf[:global] if cnf.key?(:global)
|
218
215
|
else
|
219
216
|
unused.push(cnf)
|
220
217
|
end
|
@@ -222,7 +219,6 @@ module Ecoportal
|
|
222
219
|
raise "Unsupported configuration options '#{unused}' for #{self.class}" unless unused.empty?
|
223
220
|
end
|
224
221
|
end
|
225
|
-
|
226
222
|
end
|
227
223
|
end
|
228
224
|
end
|
@@ -5,28 +5,28 @@ module Ecoportal
|
|
5
5
|
class Components < Common::Content::CollectionModel
|
6
6
|
class_resolver :component_class, "Ecoportal::API::V2::Page::Component"
|
7
7
|
|
8
|
-
|
8
|
+
klass do |doc|
|
9
9
|
component_class.get_class(doc).tap do |klass|
|
10
10
|
klass.key = :id
|
11
11
|
end
|
12
12
|
end
|
13
13
|
|
14
|
-
order_matters = true
|
14
|
+
#self.order_matters = true
|
15
15
|
|
16
16
|
def ooze
|
17
|
-
|
17
|
+
_parent.ooze
|
18
18
|
end
|
19
19
|
|
20
20
|
# @return [Ecoportal::API::V2::Page::Component] the field with `id`
|
21
21
|
def get_by_id(id)
|
22
|
-
|
22
|
+
find do |comp|
|
23
23
|
comp.id == id
|
24
24
|
end
|
25
25
|
end
|
26
26
|
|
27
27
|
# @return [Array<Ecoportal::API::V2::Page::Component>] the fields of that `type`
|
28
28
|
def get_by_type(type)
|
29
|
-
|
29
|
+
select do |comp|
|
30
30
|
comp.type.downcase == type.to_s.strip.downcase
|
31
31
|
end
|
32
32
|
end
|
@@ -53,19 +53,19 @@ module Ecoportal
|
|
53
53
|
def add(doc: nil, label: doc && doc["label"], type: doc && doc["type"])
|
54
54
|
fld_doc = doc ? JSON.parse(doc.to_json) : component_class.new_doc(type: type)
|
55
55
|
upsert!(fld_doc) do |fld|
|
56
|
-
fld.label
|
57
|
-
yield(fld)
|
56
|
+
fld.label = label unless doc
|
57
|
+
yield(fld) if block_given?
|
58
58
|
end
|
59
59
|
end
|
60
60
|
|
61
61
|
# @return [Array<Ecoportal::API::V2::Page::Component>] **orphaned** fields (with no section).
|
62
62
|
def unattached
|
63
|
-
|
63
|
+
reject(&:attached?)
|
64
64
|
end
|
65
65
|
|
66
66
|
# @return [Array<Ecoportal::API::V2::Page::Component>] fields belonging to more than one section.
|
67
67
|
def multi_section
|
68
|
-
select
|
68
|
+
select(&:multi_section?)
|
69
69
|
end
|
70
70
|
end
|
71
71
|
end
|