ecoportal-api-v2 0.8.12 → 0.8.16

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 692fe87a2a9dd089ee091bae7133915ac5c9ae4b0643be6086b57206569a1044
4
- data.tar.gz: 4d9866b6e5727b176caaff881cb44a3cd13ca08418884e69283f8c64c0e80272
3
+ metadata.gz: 4655b94325aaad222aabf7ec6376aa4e0be39f03db94338ceab8fcd77dca229b
4
+ data.tar.gz: af7d89a41346d634dce2acea3c689e0f823b9ec85f68d662807939c2222e843d
5
5
  SHA512:
6
- metadata.gz: b812fc350ccdfd173d8ca7b02b05bd0676eda8dac97e2a981cd6c87e1e62c7170744a352ef962144ffb24b3bf9eb43011156c78c09f22a00db154431fd2be5ca
7
- data.tar.gz: 00c551099e991a339125e5a985f98aa918b8f9844e03b7b6ba79c6cc2fc5d9ffa4303eaee51c2acc6205932472cdf5324692a73d875e647ba0bcd685f676c60c
6
+ metadata.gz: a749ce7f98f2765c133d662c4257ba7f3bac24fb2b35a369f8e060dc97ff5ccd13a5c91be65fb004f3de31c98b3559eb4f91fdf6fb15e71d178004e66c407ac8
7
+ data.tar.gz: 454fc8004933d15357f0e4dc0e5d7e923b42876bb049cad72ea58a8b32a0b3246a3316c8fad05df22d16fa4c87296a9e8bdbda0932a73f7cad8e16ae4b386a41
data/CHANGELOG.md CHANGED
@@ -1,12 +1,75 @@
1
1
  # Change Log
2
2
  All notable changes to this project will be documented in this file.
3
3
 
4
- ## [0.8.12] - 2021-08-xx
4
+ ## [0.8.16] - 2021-09-xx
5
5
 
6
6
  ### Added
7
- - `Ecoportal::API::V2::Pages::PageStage#current_stage`
8
-
9
7
  ### Changed
8
+ ### Fixed
9
+
10
+
11
+ ## [0.8.15] - 2021-09-29
12
+
13
+ ### Fixed
14
+ - Typo in `Section#component?`
15
+
16
+ ## [0.8.14] - 2021-09-28
17
+
18
+ ### Added
19
+ - `Ecoportal::API::Common::Content::CollectionModel`
20
+ - `#_doc_pos` for clarity
21
+ - `#include?` to check if an element is present in the collection
22
+ - `Ecoportal::API::V2::Page::Stage#section?` check if section belongs to stage
23
+ - `Ecoportal::API::V2::Page::Sections`
24
+ - `#get_by_id`
25
+ - `#unattached` sections that are not attached to any stage
26
+ - `Ecoportal::API::V2::Page::Section`
27
+ - `#add_component` **added** parameter `before`: to cover case where you want to add it at the beginning
28
+ - `#component?` **widened** parameter type
29
+ - `#stages` stages where this section is attached
30
+ - `attached?` whether or not the section is attached
31
+ - `Ecoportal::API::V2::Page::Component`
32
+ - `#attached?` whether or not the field is attached to some section
33
+ - `#multi_section?` if the field is attached to more than one section :/
34
+ - **added** support for `forces`
35
+ - `Ecoportal::API::V2::Page::Force`
36
+ - `Ecoportal::API::V2::Page::Forces`
37
+ - `Ecoportal::API::V2::Page::Force::Binding`
38
+ - `Ecoportal::API::V2::Page::Force::Bindings`
39
+ - **added** shortcut to `#ooze` throughout all the model
40
+ - **validations** in some methods
41
+ - `Ecoportal::API::V2::Page::Stage#add_section`: section should be in `ooze.sections`
42
+ - `Ecoportal::API::V2::Page::Section#add_component`: component should be in `ooze.components`
43
+ - `Ecoportal::API::V2::Page::Force::Bindings#add`:
44
+ - section to be in `ooze.sections`
45
+ - component to be in `ooze.components`
46
+ - `Ecoportal::API::V2::Pages::PageStage#as_update` on page instances, it checks that
47
+ - Fields do not belong to more than one section
48
+ - Fields belong at least to one section
49
+ - Sections belong to at least one stage
50
+
51
+ ### Fixed
52
+ - `Ecoportal::API::Common::Content::ArrayModel#insert_one` was not inserting when not found. Should insert at least at the end.
53
+
54
+ ## [0.8.13] - 2021-09-03
55
+
56
+ ### Fixed
57
+ - `Ecoportal::API::V2::Page::Sections`
58
+ - `weight` fixing should only happen on entire page, **not** on stage sections that could change the order of section shared with other stages
59
+ - `#scope_weight` was not excluding the section when using `weight` of the last one
60
+ - Several classes with `embeds_many` were performing the `ordering` of those elements in the wrong way
61
+ - `Ecoportall::API::Common::Content::DoubleModel`
62
+ - `#replace_original_doc` had a couple of typos
63
+ - `#replace_doc` should only remove the variable referring to the current object and only if `new_doc` is `nil`
64
+ - `Ecoportal::API::Common::Content::CollectionModel` on insertion and deletion it was removing instance variable objects.
65
+ - There was no need for this approach, as the only necessary thing is to just keep those variable instances up to date in the correct unique access point to do so.
66
+ - Aside note: the reason why this was initially designed this way is because there were some difficulties to identify the existing elements in the subjacent model. Once `#passkey` as added, this difficulty could be overcome.
67
+ - `Ecoportal::API::Common::Content::ArrayModel` on initialize, default `doc` should be an `Array`
68
+
69
+ ## [0.8.12] - 2021-08-30
70
+
71
+ ### Added
72
+ - `Ecoportal::API::V2::Pages::PageStage#current_stage`
10
73
 
11
74
  ### Fixed
12
75
  - `Ecoportal::API::Common::Content::DocHelpers#get_body` typo and wrong parameters on call.
@@ -33,7 +33,7 @@ module Ecoportal
33
33
 
34
34
  end
35
35
 
36
- def initialize(doc = {}, parent: self, key: nil)
36
+ def initialize(doc = [], parent: self, key: nil)
37
37
  super(doc, parent: parent, key: key)
38
38
  end
39
39
 
@@ -224,25 +224,18 @@ module Ecoportal
224
224
  i = index(value)
225
225
  return i if (i && uniq?)
226
226
  pos = case
227
- when used_param?(pos)
228
- pos || length
229
- when used_param?(before)
230
- before ? index(before) : length
231
- when used_param?(after)
232
- if after
233
- if i = index(after) then i + 1 end
234
- else
235
- length
236
- end
237
- else
238
- length
227
+ when used_param?(pos) && pos
228
+ pos
229
+ when used_param?(before) && before
230
+ index(before)
231
+ when used_param?(after) && after
232
+ if i = index(after) then i + 1 end
239
233
  end
240
234
 
235
+ pos ||= length
241
236
  pos.tap do |i|
242
- unless !i
243
- _items.insert(pos, value)
244
- on_change
245
- end
237
+ _items.insert(pos, value)
238
+ on_change
246
239
  end
247
240
  end
248
241
 
@@ -109,7 +109,14 @@ module Ecoportal
109
109
  self.class.klass
110
110
  end
111
111
 
112
+ def _doc_pos(value)
113
+ _doc_key(value)
114
+ end
115
+
112
116
  # Transforms `value` into the actual `key` to access the object in the doc `Array`
117
+ # @note
118
+ # - The name of the method is after the paren't class method
119
+ # - This method would have been better called `_doc_pos` :)
113
120
  def _doc_key(value)
114
121
  #print "*(#{value.class})"
115
122
  return super(value) unless value.is_a?(Hash) || value.is_a?(Content::DoubleModel)
@@ -149,6 +156,13 @@ module Ecoportal
149
156
  items_by_key[get_key(value)]
150
157
  end
151
158
 
159
+ # Checks if an element exists in the collection
160
+ # @param value [String, Hash, Ecoportal::API::Common::Content::DoubleModel]
161
+ # @return [Boolean] whether or not it is included
162
+ def include?(value)
163
+ items_by_key.key?(get_key(value))
164
+ end
165
+
152
166
  # @return [Array<Object>] the `items_class` element object
153
167
  def values_at(*keys)
154
168
  keys.map {|key| self[key]}
@@ -167,7 +181,10 @@ module Ecoportal
167
181
  if item = self[value]
168
182
  item.replace_doc(item_doc)
169
183
  else
170
- pos_idx = _doc_upsert(item_doc, pos: pos, before: before, after: after)
184
+ _doc_upsert(item_doc, pos: pos, before: before, after: after).tap do |pos_idx|
185
+ _items.insert(pos_idx, new_item(item_doc))
186
+ @indexed = false
187
+ end
171
188
  end
172
189
  (item || self[item_doc]).tap do |item|
173
190
  yield(item) if block_given?
@@ -185,6 +202,8 @@ module Ecoportal
185
202
  end
186
203
  if item = self[value]
187
204
  _doc_delete(item.doc)
205
+ @indexed = false
206
+ _items.delete(item)
188
207
  end
189
208
  end
190
209
 
@@ -195,7 +214,8 @@ module Ecoportal
195
214
  def items_key; self.class.items_key; end
196
215
 
197
216
  def on_change
198
- variables_remove!
217
+ @indexed = false
218
+ #variables_remove!
199
219
  end
200
220
 
201
221
  # Gets the `key` of the object `value`
@@ -253,9 +273,7 @@ module Ecoportal
253
273
  # @return [Object] the element deleted from `doc`
254
274
  def _doc_delete(value)
255
275
  if current_pos = _doc_key(value)
256
- _doc_items.delete_at(current_pos).tap do |deleted|
257
- on_change
258
- end
276
+ _doc_items.delete_at(current_pos)
259
277
  end
260
278
  end
261
279
 
@@ -275,7 +293,6 @@ module Ecoportal
275
293
  pos = (pos && pos < _doc_items.length)? pos : _doc_items.length
276
294
  pos.tap do |i|
277
295
  _doc_items.insert(pos, value)
278
- on_change
279
296
  end
280
297
 
281
298
  end
@@ -240,7 +240,7 @@ module Ecoportal
240
240
  end
241
241
 
242
242
  inheritable_class_vars :forced_model_keys
243
-
243
+
244
244
  attr_reader :_parent, :_key
245
245
 
246
246
  def initialize(doc = {}, parent: self, key: nil)
@@ -367,8 +367,8 @@ module Ecoportal
367
367
  @doc = new_doc
368
368
  else
369
369
  dig_set(_parent.doc, [_doc_key(_key)].flatten, new_doc)
370
- _parent.variable_remove!(_key)
371
- variables_remove!
370
+ _parent.variable_remove!(_key) unless new_doc
371
+ #variables_remove!
372
372
  end
373
373
  end
374
374
 
@@ -385,9 +385,9 @@ module Ecoportal
385
385
  def replace_original_doc(new_doc)
386
386
  raise UnlinkedModel.new(from: "#{self.class}#replace_original_doc", key: _key) unless linked?
387
387
  if is_root?
388
- @orginal_doc = new_doc
388
+ @original_doc = new_doc
389
389
  else
390
- dig_set(_parent.orginal_doc, [_doc_key(_key)].flatten, new_doc)
390
+ dig_set(_parent.original_doc, [_doc_key(_key)].flatten, new_doc)
391
391
  end
392
392
  end
393
393
 
@@ -409,11 +409,21 @@ module Ecoportal
409
409
 
410
410
  # Removes all the persistent variables
411
411
  def variables_remove!
412
+ #puts "going to remove vars: #{@_dim_vars} on #{self.class} (parent: #{identify_parent(self._parent)})"
412
413
  @_dim_vars.dup.map {|k| variable_remove!(k)}
413
414
  end
414
415
 
415
416
  private
416
417
 
418
+ def identify_parent(object)
419
+ case object
420
+ when Ecoportal::API::V2::Page::Stage
421
+ "stage #{object.name}"
422
+ when Ecoportal::API::V2::Page::Section
423
+ "section #{object.heading}"
424
+ end
425
+ end
426
+
417
427
  def instance_variable_name(key)
418
428
  self.class.instance_variable_name(key)
419
429
  end
@@ -60,7 +60,7 @@ module Ecoportal
60
60
  a == b
61
61
  end
62
62
 
63
- # Compares `a` as charring changes of `b`
63
+ # Compares `a` as carrying changes of `b`
64
64
  # @return [Hash] patch data object with only changes
65
65
  def patch_data(a, b = nil, delete: false)
66
66
  {}.tap do |data_hash|
@@ -8,7 +8,7 @@ module Ecoportal
8
8
  def new_doc
9
9
  {
10
10
  "id" => new_uuid,
11
- "weight" => 9999
11
+ "weight" => 99
12
12
  }
13
13
  end
14
14
  end
@@ -25,9 +25,9 @@ module Ecoportal
25
25
  end
26
26
 
27
27
  def ordered_tasks
28
- actions.each_with_index.sort_by do |task, index|
29
- (task.weight >= 9999) ? [index, index] : [task.weight, index]
30
- end.map(&:first)
28
+ actions.sort_by.with_index do |task, index|
29
+ [task.weight, index]
30
+ end
31
31
  end
32
32
 
33
33
  # Quick config helper
@@ -19,9 +19,9 @@ module Ecoportal
19
19
  end
20
20
 
21
21
  def ordered_items
22
- items.each_with_index.sort_by do |item, index|
23
- (item.weight >= 9999) ? [index, index] : [item.weight, index]
24
- end.map(&:first)
22
+ items.sort_by.with_index do |item, index|
23
+ [item.weight, index]
24
+ end
25
25
  end
26
26
 
27
27
  private
@@ -8,7 +8,7 @@ module Ecoportal
8
8
  def new_doc
9
9
  {
10
10
  "id" => new_uuid,
11
- "position" => 9999
11
+ "position" => 99
12
12
  }
13
13
  end
14
14
  end
@@ -19,9 +19,9 @@ module Ecoportal
19
19
  end
20
20
 
21
21
  def ordered_files
22
- items.each_with_index.sort_by do |file, index|
23
- (file.position >= 9999) ? [index, index] : [file.position, index]
24
- end.map(&:first)
22
+ items.sort_by.with_index do |file, index|
23
+ [file.position, index]
24
+ end
25
25
  end
26
26
 
27
27
  private
@@ -21,9 +21,9 @@ module Ecoportal
21
21
  end
22
22
 
23
23
  def ordered_stops
24
- stops.each_with_index.sort_by do |stop, index|
25
- (stop.threshold >= 9999) ? [index, index] : [stop.threshold, index]
26
- end.map(&:first)
24
+ stops.sort_by.with_index do |stop, index|
25
+ [stop.threshold, index]
26
+ end
27
27
  end
28
28
 
29
29
  end
@@ -58,9 +58,9 @@ module Ecoportal
58
58
  end
59
59
 
60
60
  def ordered_options
61
- options.each_with_index.sort_by do |option, index|
62
- (option.weight >= 9999) ? [index, index] : [option.weight, index]
63
- end.map(&:first)
61
+ options.sort_by.with_index do |option, index|
62
+ [option.weight, index]
63
+ end
64
64
  end
65
65
 
66
66
  # Quick config helper
@@ -93,6 +93,10 @@ module Ecoportal
93
93
  passboolean :hide_view, :hidden_on_reports, :hidden_on_mobile
94
94
  passarray :refs
95
95
 
96
+ def ooze
97
+ self._parent.ooze
98
+ end
99
+
96
100
  def ref_backend
97
101
  refs.first
98
102
  end
@@ -103,10 +107,23 @@ module Ecoportal
103
107
  end
104
108
  end
105
109
 
110
+ # Looks up the section that this component belongs to.
111
+ # @return [Ecoportal::API::V2::Page::Section, nil] the section where this field is attached to.
106
112
  def section
107
113
  root.sections.find {|sec| sec.component?(id)}
108
114
  end
109
115
 
116
+ # @return [Boolean] whether or not this field is attached to any section.
117
+ def attached?
118
+ !!section
119
+ end
120
+
121
+ # @return [Boolean] whether or not the component has been attached to more than one section.
122
+ def multi_section?
123
+ secs = ooze.sections.select {|sec| sec.component?(id)}
124
+ secs.length > 1
125
+ end
126
+
110
127
  def indexable_label
111
128
  self.class.indexable_label(label)
112
129
  end
@@ -13,18 +13,27 @@ module Ecoportal
13
13
 
14
14
  order_matters = true
15
15
 
16
+ def ooze
17
+ self._parent.ooze
18
+ end
19
+
20
+ # @return [Ecoportal::API::V2::Page::Component] the field with `id`
16
21
  def get_by_id(id)
17
22
  self.find do |comp|
18
23
  comp.id == id
19
24
  end
20
25
  end
21
26
 
27
+ # @return [Array<Ecoportal::API::V2::Page::Component>] the fields of that `type`
22
28
  def get_by_type(type)
23
29
  self.select do |comp|
24
30
  comp.type.downcase == type.to_s.strip.downcase
25
31
  end
26
32
  end
27
33
 
34
+ # @param name [String, Regexp] the `name` to search the field based on their `label`
35
+ # @param type [String] the `type` of the fields to be included
36
+ # @return [Array<Ecoportal::API::V2::Page::Component>] the fields that match `name`.
28
37
  def get_by_name(name, type: nil)
29
38
  pool = type ? get_by_type(type) : self
30
39
  pool.select do |comp|
@@ -32,6 +41,12 @@ module Ecoportal
32
41
  end
33
42
  end
34
43
 
44
+ # It creates a **new** component
45
+ # @param label [String, nil]
46
+ # @param type [String] the type of the field
47
+ # @yield [field] do some stuff with field
48
+ # @yieldparam [Ecoportal::API::V2::Page::Component] the created field
49
+ # @return [Ecoportal::API::V2::Page::Component] the created field.
35
50
  def add(label:, type:)
36
51
  fld_doc = component_class.new_doc(type: type)
37
52
  upsert!(fld_doc) do |fld|
@@ -40,6 +55,15 @@ module Ecoportal
40
55
  end
41
56
  end
42
57
 
58
+ # @return [Array<Ecoportal::API::V2::Page::Component>] **orphaned** fields (with no section).
59
+ def unattached
60
+ select {|comp| !comp.attached?}
61
+ end
62
+
63
+ # @return [Array<Ecoportal::API::V2::Page::Component>] fields belonging to more than one section.
64
+ def multi_section
65
+ select {|comp| comp.multi_section?}
66
+ end
43
67
  end
44
68
  end
45
69
  end
@@ -0,0 +1,54 @@
1
+ module Ecoportal
2
+ module API
3
+ class V2
4
+ class Page
5
+ class Force
6
+ class Binding < Common::Content::DoubleModel
7
+ class << self
8
+ def new_doc
9
+ {
10
+ "id" => new_uuid
11
+ }
12
+ end
13
+ end
14
+ COMPONENT_TYPE = "membrane_binding"
15
+ SECTION_TYPE = "flow_node_binding"
16
+
17
+ passkey :id
18
+ passforced :patch_ver, default: 1
19
+ passthrough :name, :reference_id, :type
20
+
21
+ def ooze
22
+ self._parent.ooze
23
+ end
24
+
25
+ # @return [Boolean] whether or not this the binding refers to a Component
26
+ def component?
27
+ type == COMPONENT_TYPE
28
+ end
29
+
30
+ # @return [Boolean] whether or not this the binding refers to a Section
31
+ def section?
32
+ type == SECTION_TYPE
33
+ end
34
+
35
+ # @return [Ecoportal::API::V2::Page::Component] field referenced by this binding.
36
+ def component
37
+ raise "This is not a component binding, but a section binding" unless component?
38
+ ooze.components.get_by_id(reference_id)
39
+ end
40
+
41
+ # @return [Ecoportal::API::V2::Page::Section] section referenced by this binding.
42
+ def section
43
+ raise "This is not a section binding, but a component binding" unless section?
44
+ ooze.sections.get_by_id(reference_id)
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
52
+
53
+ require 'ecoportal/api/v2/page/force/binding'
54
+ require 'ecoportal/api/v2/page/force/bindings'
@@ -0,0 +1,126 @@
1
+ module Ecoportal
2
+ module API
3
+ class V2
4
+ class Page
5
+ class Force
6
+ class Bindings < Common::Content::CollectionModel
7
+ class_resolver :binding_class, "Ecoportal::API::V2::Page::Force::Binding"
8
+
9
+ self.klass = :binding_class
10
+ order_matters = true
11
+
12
+ def ooze
13
+ self._parent.ooze
14
+ end
15
+
16
+ # @param id [String] the `id` of the binding to find.
17
+ # @return [Ecoportal::API::V2::Page::Force::Binding] binding with `id`
18
+ def get_by_id(id)
19
+ self.find do |bind|
20
+ bind.id == id
21
+ end
22
+ end
23
+
24
+ # @param type [String] target `type` of binding
25
+ # 1. Ecoportal::API::V2::Page::Force::Binding::COMPONENT_TYPE
26
+ # 2. Ecoportal::API::V2::Page::Force::Binding::SECTION_TYPE
27
+ # @return [Array<Ecoportal::API::V2::Page::Force::Binding>] the bindings of type `type`
28
+ def get_by_type(type = Ecoportal::API::V2::Page::Force::Binding::COMPONENT_TYPE)
29
+ self.select do |bind|
30
+ bind.type.downcase == type.to_s.strip.downcase
31
+ end
32
+ end
33
+
34
+ # @param type [String] target `type` of binding
35
+ # 1. Ecoportal::API::V2::Page::Force::Binding::COMPONENT_TYPE
36
+ # 2. Ecoportal::API::V2::Page::Force::Binding::SECTION_TYPE
37
+ # @return [Array<Ecoportal::API::V2::Page::Force::Binding>] the bindings matching `name`
38
+ def get_by_name(name, type: nil)
39
+ pool = type ? get_by_type(type) : self
40
+ pool.select do |bind|
41
+ same_string?(bind.name, name)
42
+ end
43
+ end
44
+
45
+ # Creates a new `binding`
46
+ # @note
47
+ # - As there's no position property, it will upsert to the array of bindings
48
+ # @raise [ArgumentError] when `reference` is neither of Component or Section
49
+ # @raise [Exception] when
50
+ # 1. `reference` is a field missing in ooze.components
51
+ # 2. `reference` is a section missing in ooze.sections
52
+ # @param reference [Ecoportal::API::V2::Page::Component, Ecoportal::API::V2::Page::Section]
53
+ # The field or the section to bind.
54
+ # @yield [binding] do some stuff with binding
55
+ # @yieldparam binding [Ecoportal::API::V2::Page::Force::Binding] the created binding
56
+ # @return [Ecoportal::API::V2::Page::Force::Binding] the created binding.
57
+ def add(reference, name:, pos: NOT_USED, before: NOT_USED, after: NOT_USED)
58
+ binding_doc = binding_class.new_doc
59
+
60
+ type = case reference
61
+ when Ecoportal::API::V2::Page::Component
62
+ unless ooze.components.include?(reference)
63
+ msg = "The field '#{reference.label}' (#{reference.id}) is not present in ooze.components.\n"
64
+ msg += "Review your script (i.e. @var where you store previous ooze runs)."
65
+ raise msg
66
+ end
67
+ Ecoportal::API::V2::Page::Force::Binding::COMPONENT_TYPE
68
+ when Ecoportal::API::V2::Page::Section
69
+ unless ooze.sections.include?(reference)
70
+ msg = "The section '#{reference.heading}' (#{reference.id}) is not present in ooze.sections.\n"
71
+ msg += "Review your script (i.e. @var where you store previous ooze runs)."
72
+ raise msg
73
+ end
74
+ Ecoportal::API::V2::Page::Force::Binding::SECTION_TYPE
75
+ else
76
+ msg = "You can only create bindings with Component and Section. Given: #{reference.class}"
77
+ raise ArgumentError.new(msg)
78
+ end
79
+
80
+ position = scope_position(pos: pos, before: before, after: after)
81
+ upsert!(binding_doc, pos: position) do |bind|
82
+ bind.name = name
83
+ bind.reference_id = reference.id
84
+ bind.type = type
85
+ yield(bind) if block_given?
86
+ end
87
+ end
88
+
89
+ private
90
+
91
+ def scope_position(pos: NOT_USED, before: NOT_USED, after: NOT_USED)
92
+ case
93
+ when used_param?(pos)
94
+ if pos = to_binding(pos)
95
+ _doc_pos(pos) - 1
96
+ end
97
+ when used_param?(before)
98
+ if before = to_binding(before)
99
+ _doc_pos(before) - 1
100
+ end
101
+ when used_param?(after)
102
+ if after = to_binding(after)
103
+ _doc_pos(after) - 1
104
+ end
105
+ end.yield_self do |position|
106
+ position ||= self.count
107
+ end
108
+ end
109
+
110
+ def to_binding(value)
111
+ case value
112
+ when Ecoportal::API::V2::Page::Force::Binding
113
+ value
114
+ when Numeric
115
+ self[value]
116
+ else
117
+ get_by_name(value).first
118
+ end
119
+ end
120
+
121
+ end
122
+ end
123
+ end
124
+ end
125
+ end
126
+ end
@@ -0,0 +1,34 @@
1
+ module Ecoportal
2
+ module API
3
+ class V2
4
+ class Page
5
+ class Force < Common::Content::DoubleModel
6
+ INITIAL_WEIGHT = 9999
7
+
8
+ class << self
9
+ def new_doc
10
+ {
11
+ "id" => new_uuid,
12
+ "weight" => INITIAL_WEIGHT
13
+ }
14
+ end
15
+ end
16
+
17
+ class_resolver :bindings_class, "Ecoportal::API::V2::Page::Force::Bindings"
18
+
19
+ passkey :id
20
+ passforced :patch_ver, default: 1
21
+ passthrough :name, :weight, :script
22
+ embeds_many :bindings, enum_class: :bindings_class
23
+
24
+ def ooze
25
+ self._parent.ooze
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
32
+
33
+ require 'ecoportal/api/v2/page/force/binding'
34
+ require 'ecoportal/api/v2/page/force/bindings'
@@ -0,0 +1,103 @@
1
+ module Ecoportal
2
+ module API
3
+ class V2
4
+ class Page
5
+ class Forces < Common::Content::CollectionModel
6
+ class_resolver :force_class, "Ecoportal::API::V2::Page::Force"
7
+
8
+ self.klass = :force_class
9
+ order_matters = true
10
+
11
+ def ooze
12
+ self._parent.ooze
13
+ end
14
+
15
+ # @return [Ecoportal::API::V2::Page::Force]
16
+ def get_by_id(id)
17
+ self.find do |force|
18
+ force.id == id
19
+ end
20
+ end
21
+
22
+ # @return [Array<Ecoportal::API::V2::Page::Force>]
23
+ def get_by_name(name)
24
+ self.select do |force|
25
+ same_string?(force.name, name)
26
+ end
27
+ end
28
+
29
+ # Creates a new `force`
30
+ # @note
31
+ # - It won't fix weights unless all the forces of the ooze are present
32
+ # - This means that it doesn't fix forces weights on stages,
33
+ # as shared forces could change order in other stages
34
+ # @yield [force] to do some stuff with the `force`
35
+ # @yieldparam force [Ecoportal::API::V2::Page::Force] the created force
36
+ # @return [Ecoportal::API::V2::Page::Force]
37
+ def add(name, pos: NOT_USED, before: NOT_USED, after: NOT_USED)
38
+ force_doc = force_class.new_doc
39
+ upsert!(force_doc) do |force| #, pos: pos, before: before, after: after) do |section|
40
+ force.name = name
41
+ if weight = scope_weight(force, pos: pos, before: before, after: after)
42
+ force.weight = weight
43
+ end
44
+ fix_weights!
45
+ yield(force) if block_given?
46
+ end
47
+ end
48
+
49
+ # Gets the forces ordered by `weight` (as they appear in the page)
50
+ # @return [Array<Ecoportal::API::V2::Page::Force>] forces ordered by `weight`
51
+ def ordered
52
+ self.sort_by.with_index do |force, index|
53
+ [force.weight, index]
54
+ end
55
+ end
56
+
57
+ private
58
+
59
+ def fix_weights!
60
+ unless self._parent.is_a?(Ecoportal::API::V2::Pages::PageStage)
61
+ ordered.each_with_index do |force, index|
62
+ force.weight = index
63
+ end
64
+ end
65
+ end
66
+
67
+ def scope_weight(force, pos: NOT_USED, before: NOT_USED, after: NOT_USED)
68
+ case
69
+ when used_param?(pos)
70
+ if pos = to_force(pos)
71
+ pos.weight - 1
72
+ end
73
+ when used_param?(before)
74
+ if before = to_force(before)
75
+ before.weight - 1
76
+ end
77
+ when used_param?(after)
78
+ if after = to_force(after)
79
+ after.weight
80
+ end
81
+ end.yield_self do |weight|
82
+ weight = ordered.reject do |frc|
83
+ frc.id == force.id
84
+ end.last&.weight
85
+ weight ||= force_class.const_get(:INITIAL_WEIGHT)
86
+ end
87
+ end
88
+
89
+ def to_force(value)
90
+ case value
91
+ when Ecoportal::API::V2::Page::Force
92
+ value
93
+ when Numeric
94
+ ordered[value]
95
+ else
96
+ get_by_name(value).first
97
+ end
98
+ end
99
+ end
100
+ end
101
+ end
102
+ end
103
+ end
@@ -57,9 +57,7 @@ module Ecoportal
57
57
  end.yield_self do |unused|
58
58
  raise "Unknown configuaration options #{unused}" unless unused.empty?
59
59
  end
60
-
61
60
  end
62
-
63
61
  end
64
62
  end
65
63
  end
@@ -3,12 +3,14 @@ module Ecoportal
3
3
  class V2
4
4
  class Page
5
5
  class Section < Common::Content::DoubleModel
6
+ INITIAL_WEIGHT = 9999
7
+
6
8
  class << self
7
9
  def new_doc(split: false)
8
10
  {
9
11
  "id" => new_uuid,
10
12
  "type" => split ? "split" : "content",
11
- "weight" => 800
13
+ "weight" => INITIAL_WEIGHT
12
14
  }.tap do |out|
13
15
  component_ids = if split
14
16
  {
@@ -32,19 +34,48 @@ module Ecoportal
32
34
  passarray :component_ids, :left_component_ids, :right_component_ids
33
35
  passboolean :minimized
34
36
 
37
+ def ooze
38
+ self._parent.ooze
39
+ end
40
+
41
+ # @return [Array<Ecoportal::API::V2::Page::Stage>] the stage(s) this section belongs to.
42
+ def stages
43
+ ooze.stages.select {|stg| stg.section?(self)}
44
+ end
45
+
46
+ # @return [Boolean] whether or not the section appears in an ooze instance
47
+ def attached?
48
+ !ooze.stages? || stages.any?
49
+ end
50
+
51
+ # @return [Boolean] whether or not this section is a split section
35
52
  def split?
36
53
  doc && doc["type"] == "split"
37
54
  end
38
55
 
56
+ # @return [Array<String>] all the `ids` of the components/fields in this section
39
57
  def all_component_ids
40
58
  return component_ids.to_a unless split?
41
59
  left_component_ids.to_a | right_component_ids.to_a
42
60
  end
43
61
 
44
- def component?(id)
45
- all_component_ids.include?(id)
62
+ # @raise [ArgumentError] if `com_or_id` is not of any of the allowed types
63
+ # @param com_or_id [Ecoportal::API::V2::Page::Component, String] Component or `id` thereof
64
+ # @return [Boolean] whether or not a component/field belongs to this section.
65
+ def component?(com_or_id)
66
+ case com_or_id
67
+ when Ecoportal::API::V2::Page::Component
68
+ component?(com_or_id.id)
69
+ when String
70
+ all_component_ids.include?(id)
71
+ else
72
+ msg = "Missuse: com_or_id should be a Component or a String. Given: #{com_or_id.class}"
73
+ raise ArgumentError.new(msg)
74
+ end
46
75
  end
47
76
 
77
+ # It looks up the components that belong to this section.
78
+ # @return [Array<Ecoportal::API::V2::Page::Component>]
48
79
  def components(side: nil)
49
80
  case side
50
81
  when :right
@@ -58,11 +89,17 @@ module Ecoportal
58
89
  end
59
90
  end
60
91
 
92
+ # It looks up the components that belong to the `left` side of this section.
93
+ # @raise [Exception] if this is not a `split` section
94
+ # @return [Array<Ecoportal::API::V2::Page::Component>]
61
95
  def components_left
62
96
  raise "You are trying to retrieve side components in a Split Section" unless split?
63
97
  components_by_id(*left_component_ids)
64
98
  end
65
99
 
100
+ # It looks up the components that belong to the `right` side of this section.
101
+ # @raise [Exception] if this is not a `split` section
102
+ # @return [Array<Ecoportal::API::V2::Page::Component>]
66
103
  def components_right
67
104
  raise "You are trying to retrieve side components in a Split Section" unless split?
68
105
  components_by_id(*right_component_ids)
@@ -75,32 +112,41 @@ module Ecoportal
75
112
  # - If `after` is specified, it searches field
76
113
  # - On the specific `side`, if specified (and split section)
77
114
  # - And adds the `field` after it, when found, or at the end if `after` is not found
115
+ # @raise [ArgumentError] if `field` is not a Component
116
+ # @raise [Exception] if the field does not belong to ooze.components
117
+ # @raise [Exception] if the field belongs to another section
78
118
  # @param field [Ecoportal::API::V2::Page::Component] the field to be added.
79
- def add_component(field, after: nil, side: nil)
80
- raise "field should be a Ecoportal::API::V2::Page::Component. Given: #{field.class}" unless field.is_a?(Ecoportal::API::V2::Page::Component)
119
+ def add_component(field, before: nil, after: nil, side: nil)
120
+ unless field.is_a?(Ecoportal::API::V2::Page::Component)
121
+ msg = "Expected Ecoportal::API::V2::Page::Component. Given: #{field.class}"
122
+ raise ArgumentError.new(msg)
123
+ end
124
+ unless ooze.components.include?(field)
125
+ msg = "The field '#{field.label}' (#{field.id}) is not present in ooze.components.\n"
126
+ msg += "Review your script (i.e. @var where you store previous ooze runs)."
127
+ raise msg
128
+ end
129
+ # IMPORTANT NOTE: The code below creates objects, because field.section does a search on section.component_ids
81
130
  if field.section == self
82
- raise "Field with id '#{field.id}' already belongs to this section"
131
+ puts "Field with id '#{field.id}' already belongs to this section"
83
132
  elsif sec = field.section
84
133
  # Field belongs to another section
85
134
  raise "Field with id '#{field.id}' belongs to section '#{sec.heading || "Unnamed"}' (id: '#{sec.id}')"
86
135
  end
87
136
 
137
+ if before
138
+ before_fld = to_component(before, side: side)
139
+ elsif after
140
+ after_fld = to_component(afterm, side: side)
141
+ end
142
+
88
143
  if split?
89
144
  ids_ary = side == :right ? right_component_ids : left_component_ids
90
- fields = components(side: side || :left)
91
145
  else
92
146
  ids_ary = component_ids
93
- fields = components
94
- end
95
- if after
96
- after_fld = fields.find do |fld|
97
- found = nil
98
- found ||= !!after if after.is_a?(Ecoportal::API::V2::Page::Component)
99
- found ||= fld.id == after
100
- found ||= same_string?(fld.label, after)
101
- end
102
147
  end
103
- ids_ary.insert_one(field.id, after: after_fld&.id)
148
+
149
+ ids_ary.insert_one(field.id, before: before_fld&.id, after: after_fld&.id)
104
150
  self
105
151
  end
106
152
 
@@ -113,6 +159,20 @@ module Ecoportal
113
159
  end
114
160
  end
115
161
 
162
+ def to_component(value, side: nil)
163
+ if split?
164
+ fields = components(side: side || :left)
165
+ else
166
+ fields = components
167
+ end
168
+
169
+ fields.find do |fld|
170
+ found = nil
171
+ found ||= !!value if value.is_a?(Ecoportal::API::V2::Page::Component)
172
+ found ||= fld.id == value
173
+ found ||= same_string?(fld.label, value)
174
+ end
175
+ end
116
176
  end
117
177
  end
118
178
  end
@@ -7,12 +7,20 @@ module Ecoportal
7
7
 
8
8
  self.klass = :section_class
9
9
 
10
+ def ooze
11
+ self._parent.ooze
12
+ end
13
+
10
14
  # Creates a new `section`
15
+ # @note
16
+ # - It won't fix weights unless all the sections of the ooze are present
17
+ # - This means that it doesn't fix section weights on stages,
18
+ # as shared sections could change order in other stages
11
19
  def add(name: nil, split: false, pos: NOT_USED, before: NOT_USED, after: NOT_USED)
12
20
  sec_doc = section_class.new_doc(split: split)
13
21
  upsert!(sec_doc) do |section| #, pos: pos, before: before, after: after) do |section|
14
22
  section.heading = name
15
- if weight = scope_weight(pos: pos, before: before, after: after)
23
+ if weight = scope_weight(section, pos: pos, before: before, after: after)
16
24
  section.weight = weight
17
25
  end
18
26
  fix_weights!
@@ -20,12 +28,21 @@ module Ecoportal
20
28
  end
21
29
  end
22
30
 
31
+ # @return [Ecoportal::API::V2::Page::Section]
32
+ def get_by_id(id)
33
+ self.find do |sec|
34
+ sec.id == id
35
+ end
36
+ end
37
+
38
+ # @return [Array<Ecoportal::API::V2::Page::Section>]
23
39
  def get_by_type(type)
24
40
  ordered.select do |sec|
25
41
  sec.type == type
26
42
  end
27
43
  end
28
44
 
45
+ # @return [Array<Ecoportal::API::V2::Page::Section>]
29
46
  def get_by_heading(heading)
30
47
  ordered.select do |sec|
31
48
  value = heading == :unnamed ? nil : heading
@@ -34,6 +51,7 @@ module Ecoportal
34
51
  end
35
52
 
36
53
  # Gets all the sections between `sec1` and `sec2`
54
+ # @return [Array<Ecoportal::API::V2::Page::Section>]
37
55
  def between(sec1, sec2, included: false)
38
56
  sorted_secs = ordered
39
57
  pos1 = (sec1 = to_section(sec1)) && sorted_secs.index(sec1)
@@ -49,15 +67,21 @@ module Ecoportal
49
67
  end
50
68
 
51
69
  # Gets the sections ordered by `weight` (as they appear in the page)
70
+ # @return [Array<Ecoportal::API::V2::Page::Section>] section sorted by `weight`
52
71
  def ordered
53
72
  self.sort_by.with_index do |section, index|
54
- (section.weight >= 9999) ? [index, index] : [section.weight, index]
73
+ [section.weight, index]
55
74
  end
56
75
  end
57
76
 
77
+ # @return [Array<Ecoportal::API::V2::Page::Section>] sections not attached to any stage
78
+ def unattached
79
+ select {|sec| !sec.attached?}
80
+ end
81
+
58
82
  private
59
83
 
60
- def scope_weight(pos: NOT_USED, before: NOT_USED, after: NOT_USED)
84
+ def scope_weight(section, pos: NOT_USED, before: NOT_USED, after: NOT_USED)
61
85
  case
62
86
  when used_param?(pos)
63
87
  if pos = to_section(pos)
@@ -71,6 +95,11 @@ module Ecoportal
71
95
  if after = to_section(after)
72
96
  after.weight
73
97
  end
98
+ end.yield_self do |weight|
99
+ weight = ordered.reject do |sec|
100
+ sec.id == section.id
101
+ end.last&.weight
102
+ weight ||= section_class.const_get(:INITIAL_WEIGHT)
74
103
  end
75
104
  end
76
105
 
@@ -86,8 +115,10 @@ module Ecoportal
86
115
  end
87
116
 
88
117
  def fix_weights!
89
- ordered.each_with_index do |section, index|
90
- section.weight = index
118
+ unless self._parent.is_a?(Ecoportal::API::V2::Pages::PageStage)
119
+ ordered.each_with_index do |section, index|
120
+ section.weight = index
121
+ end
91
122
  end
92
123
  end
93
124
 
@@ -97,7 +128,6 @@ module Ecoportal
97
128
  return if pos < 0
98
129
  secs[pos]
99
130
  end
100
-
101
131
  end
102
132
  end
103
133
  end
@@ -17,19 +17,55 @@ module Ecoportal
17
17
  embeds_one :creator_flags, klass: "Ecoportal::API::V2::Page::PermissionFlags"
18
18
  passthrough :can
19
19
 
20
+ def ooze
21
+ self._parent.ooze
22
+ end
23
+
24
+ # @yield [section] do some stuff with section.
25
+ # @yieldparam section [Ecoportal::API::V2::Page::Section] one of the sections of this stage
26
+ # @return [Array<Ecoportal::API::V2::Page::Section>] sections attached to this stage.
20
27
  def sections
21
28
  sec_ids = section_ids.to_a
22
29
  root.sections.values_at(*sec_ids).select.with_index do |sec, i|
23
30
  puts "Warning: section #{id} points to missing section #{sec_ids[i]}" if !sec
24
31
  fld && (!block_given? || yield(sec))
25
- end.sort_by {|sec| sec.weight}
32
+ end.sort_by.with_index {|sec, index| [sec.weight, index]}
26
33
  end
27
34
 
35
+ # Check if a section belongs to a stage
36
+ # @raise [ArgumentError] if none of the valid types of `sec_or_id` are used
37
+ # @param sec_or_id [String, Ecoportal::API::V2::Page::Section]
38
+ # @return [Boolean] whether or not the section belongs to the stage
39
+ def section?(sec_or_id)
40
+ case sec_or_id
41
+ when Ecoportal::API::V2::Page::Section
42
+ section?(sec_or_id.id)
43
+ when String
44
+ self.section_ids.include?(id)
45
+ else
46
+ raise ArgumentError.new("sec_or_id must be either a Section or a String. Given: #{sec_or_id.class}")
47
+ end
48
+ end
49
+
50
+ # Adds one or more sections to this stage
51
+ # @raise [ArgumentError] if any of the elements is not a Section
52
+ # @raise [Exception] if any of the sections does not belong to ooze.sections
53
+ # @param secs [Array<Ecoportal::API::V2::Page::Section>] sections to be added to this stage.
28
54
  def add_section(*secs)
29
- secs.each {|sec| section_ids.insert_one(sec.id)}
55
+ secs.each do |sec|
56
+ unless sec.is_a?(Ecoportal::API::V2::Page::Section)
57
+ msg = "Expected Ecoportal::API::V2::Page::Section. Given: #{sec.class}"
58
+ raise ArgumentError.new(msg)
59
+ end
60
+ unless ooze.sections.include?(sec)
61
+ msg = "The section '#{sec.heading}' (#{sec.id}) is not present in ooze.sections.\n"
62
+ msg += "Review your script (i.e. @var where you store previous ooze runs)."
63
+ raise msg
64
+ end
65
+ section_ids.insert_one(sec.id)
66
+ end
30
67
  self
31
68
  end
32
-
33
69
  end
34
70
  end
35
71
  end
@@ -7,6 +7,12 @@ module Ecoportal
7
7
 
8
8
  self.klass = :stage_class
9
9
 
10
+ def ooze
11
+ self._parent.ooze
12
+ end
13
+
14
+ # @param name [String, Regexp] the `name` of the stage to find.
15
+ # @return [Ecoportal::API::V2::Page::Stage, nil]
10
16
  def get_by_name(name)
11
17
  self.find do |stage|
12
18
  same_string?(stage.name, name)
@@ -14,9 +20,9 @@ module Ecoportal
14
20
  end
15
21
 
16
22
  #def ordered
17
- # self.each_with_index.sort_by do |stage, index|
18
- # (stage.ordering >= 9999) ? [index, index] : [stage.ordering, index]
19
- # end.map(&:first)
23
+ # self.sort_by.with_index do |stage, index|
24
+ # [stage.ordering, index]
25
+ # end
20
26
  #end
21
27
 
22
28
  end
@@ -10,7 +10,7 @@ module Ecoportal
10
10
  "permits", "mould_counter", "mould",
11
11
  "state", "task_priority",
12
12
  "votes_enabled", "upvotes", "downvotes",
13
- "force_errors", "subtags"
13
+ "forces", "force_errors", "subtags"
14
14
  ]
15
15
 
16
16
  passkey :id
@@ -24,10 +24,20 @@ module Ecoportal
24
24
  class_resolver :components_class, "Ecoportal::API::V2::Page::Components"
25
25
  class_resolver :sections_class, "Ecoportal::API::V2::Page::Sections"
26
26
  class_resolver :stages_class, "Ecoportal::API::V2::Page::Stages"
27
+ class_resolver :forces_class, "Ecoportal::API::V2::Page::Forces"
27
28
 
28
29
  embeds_many :components, enum_class: :components_class
29
30
  embeds_many :sections, enum_class: :sections_class
30
31
  embeds_many :stages, enum_class: :stages_class
32
+ embeds_many :forces, enum_class: :forces_class
33
+
34
+ def initialize(doc = [], parent: self, key: nil)
35
+ super(_doc_bug_fix(doc), parent: parent, key: key)
36
+ end
37
+
38
+ def ooze
39
+ self
40
+ end
31
41
 
32
42
  def as_update
33
43
  super.tap do |hash|
@@ -44,6 +54,35 @@ module Ecoportal
44
54
  self.stages.count > 0
45
55
  end
46
56
 
57
+ private
58
+
59
+ def _doc_bug_fix(hash)
60
+ hash.tap do |hash|
61
+ _fix_doc(hash["stages"], "flow_node_ids", "section_ids") if hash.key?("stages")
62
+ if hash.key?("sections")
63
+ _fix_doc(hash["sections"], "membrane_ids", "component_ids")
64
+ _fix_doc(hash["sections"], "left_membrane_ids", "left_component_ids")
65
+ _fix_doc(hash["sections"], "right_membrane_ids", "right_component_ids")
66
+ end
67
+ end
68
+ end
69
+
70
+ def _fix_doc(value, source, dest)
71
+ value.tap do |value|
72
+ case value
73
+ when Array
74
+ value.each {|v| _fix_doc(v, source, dest)}
75
+ when Hash
76
+ if value.key?(source) && !value.key?(dest)
77
+ value[dest] = value[source]
78
+ value.delete(source)
79
+ end
80
+ else
81
+ # Do nothing!
82
+ end
83
+ end
84
+ end
85
+
47
86
  end
48
87
  end
49
88
  end
@@ -57,3 +96,5 @@ require 'ecoportal/api/v2/page/section'
57
96
  require 'ecoportal/api/v2/page/sections'
58
97
  require 'ecoportal/api/v2/page/stage'
59
98
  require 'ecoportal/api/v2/page/stages'
99
+ require 'ecoportal/api/v2/page/force'
100
+ require 'ecoportal/api/v2/page/forces'
@@ -10,7 +10,7 @@ module Ecoportal
10
10
  embeds_many :permits, klass: "Ecoportal::API::V2::Page::Permit"
11
11
  passarray :force_errors, :subtags, order_matters: false
12
12
 
13
- # `id` of the stage we got the data of.
13
+ # @return [String] `id` of the stage we got the data of.
14
14
  def current_stage_id
15
15
  doc.dig("active_stage", "id") || doc["current_stage_id"]
16
16
  end
@@ -22,6 +22,44 @@ module Ecoportal
22
22
  end
23
23
  end
24
24
 
25
+ # @raise [Exception] if for this page instance, there are any of:
26
+ # 1. orphaned components (fields not belonging to any section)
27
+ # 2. components multi-section (fields belonging to more than one section)
28
+ # 3. orphaned sections (sections not belonging to any stage)
29
+ def as_update(*args, **kargs)
30
+ validate.tap do |validation|
31
+ raise validation if validation.is_a?(String)
32
+ end
33
+ super(*args, **kargs)
34
+ end
35
+
36
+ private
37
+
38
+ def validate
39
+ msg = ""
40
+ if (orphans = components.unattached).length > 0
41
+ msg += "There are fields not attached to any sections:"
42
+ msg += orphans.map do |fld|
43
+ fld.label
44
+ end.join("\n • ") + "\n"
45
+ end
46
+
47
+ if (multi = components.multi_section).length > 0
48
+ msg += "There are fields attached to more than one section:"
49
+ msg += orphans.map do |fld|
50
+ fld.label
51
+ end.join("\n • ") + "\n"
52
+ end
53
+
54
+ if (orphans = sections.unattached).length > 0
55
+ msg += "There are sections not attached to any stage:"
56
+ msg += orphans.map do |sec|
57
+ "'#{sec.header}' (#{sec.id})"
58
+ end.join("\n • ") + "\n"
59
+ end
60
+ msg.empty?? true : msg
61
+ end
62
+
25
63
  end
26
64
  end
27
65
  end
@@ -1,5 +1,5 @@
1
1
  module Ecoportal
2
2
  module API
3
- GEM2_VERSION = "0.8.12"
3
+ GEM2_VERSION = "0.8.16"
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ecoportal-api-v2
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.12
4
+ version: 0.8.16
5
5
  platform: ruby
6
6
  authors:
7
7
  - Oscar Segura
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-08-30 00:00:00.000000000 Z
11
+ date: 2021-09-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -218,6 +218,10 @@ files:
218
218
  - lib/ecoportal/api/v2/page/component/signature_field.rb
219
219
  - lib/ecoportal/api/v2/page/component/tag_field.rb
220
220
  - lib/ecoportal/api/v2/page/components.rb
221
+ - lib/ecoportal/api/v2/page/force.rb
222
+ - lib/ecoportal/api/v2/page/force/binding.rb
223
+ - lib/ecoportal/api/v2/page/force/bindings.rb
224
+ - lib/ecoportal/api/v2/page/forces.rb
221
225
  - lib/ecoportal/api/v2/page/permission_flags.rb
222
226
  - lib/ecoportal/api/v2/page/permit.rb
223
227
  - lib/ecoportal/api/v2/page/section.rb