ecoportal-api-v2 0.8.9 → 0.8.13
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +63 -1
- data/lib/ecoportal/api/common/content/array_model.rb +1 -1
- data/lib/ecoportal/api/common/content/collection_model.rb +46 -21
- data/lib/ecoportal/api/common/content/doc_helpers.rb +2 -2
- data/lib/ecoportal/api/common/content/double_model.rb +97 -9
- data/lib/ecoportal/api/common/content/hash_diff_patch.rb +13 -3
- data/lib/ecoportal/api/v2/page/component/action.rb +4 -3
- data/lib/ecoportal/api/v2/page/component/action_field.rb +3 -3
- data/lib/ecoportal/api/v2/page/component/chart_field/config.rb +2 -2
- data/lib/ecoportal/api/v2/page/component/checklist_field.rb +3 -3
- data/lib/ecoportal/api/v2/page/component/checklist_item.rb +4 -3
- data/lib/ecoportal/api/v2/page/component/file.rb +13 -3
- data/lib/ecoportal/api/v2/page/component/files_field.rb +37 -1
- data/lib/ecoportal/api/v2/page/component/gauge_field.rb +3 -3
- data/lib/ecoportal/api/v2/page/component/gauge_stop.rb +5 -5
- data/lib/ecoportal/api/v2/page/component/image.rb +2 -1
- data/lib/ecoportal/api/v2/page/component/number_field.rb +1 -0
- data/lib/ecoportal/api/v2/page/component/people_field.rb +14 -2
- data/lib/ecoportal/api/v2/page/component/people_viewable_field.rb +14 -0
- data/lib/ecoportal/api/v2/page/component/selection_field.rb +3 -3
- data/lib/ecoportal/api/v2/page/component/selection_option.rb +4 -3
- data/lib/ecoportal/api/v2/page/component/signature_field.rb +3 -2
- data/lib/ecoportal/api/v2/page/component.rb +11 -7
- data/lib/ecoportal/api/v2/page/permit.rb +2 -1
- data/lib/ecoportal/api/v2/page/section.rb +12 -6
- data/lib/ecoportal/api/v2/page/sections.rb +16 -5
- data/lib/ecoportal/api/v2/page/stage.rb +2 -2
- data/lib/ecoportal/api/v2/page/stages.rb +3 -3
- data/lib/ecoportal/api/v2/page.rb +50 -2
- data/lib/ecoportal/api/v2/pages/page_stage.rb +13 -0
- data/lib/ecoportal/api/v2/pages.rb +3 -0
- data/lib/ecoportal/api/v2/registers/search_results.rb +13 -0
- data/lib/ecoportal/api/v2/registers.rb +15 -2
- data/lib/ecoportal/api/v2_version.rb +1 -1
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 146b0998371f28683143b8a95ae1b68e11f8f079698502bede31c8e29369fc97
|
4
|
+
data.tar.gz: 4ce0f3dd75e4e1d822d4540fa0ff1e3e18a7c7dca1c54d7030bdb475adc21a93
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 21605169ab88cb159ee32a2f6f36e3100b183a03a7f9c895b33631934811bb9e3f16c6bc6101ddfac562854f8762f545a743b68c55d662c97be54ff35fc5b9e8
|
7
|
+
data.tar.gz: d2a66296e4b9194667983ba5c37c646fd6a12e037138870aa2771c743fc75dbf9b2ee91d07af7b1e4b501ad1afd846b427a8b92f5dc99ee4551200cc742dcd20
|
data/CHANGELOG.md
CHANGED
@@ -1,7 +1,69 @@
|
|
1
1
|
# Change Log
|
2
2
|
All notable changes to this project will be documented in this file.
|
3
3
|
|
4
|
-
## [0.8.
|
4
|
+
## [0.8.13] - 2021-08-xx
|
5
|
+
|
6
|
+
### Added
|
7
|
+
### Changed
|
8
|
+
### Fixed
|
9
|
+
- `Ecoportal::API::V2::Stage::Sections`
|
10
|
+
- `weight` fixing should only happen on entire page, **not** on stage sections that could change the order of section shared with other stages
|
11
|
+
- `#scope_weight` was not excluding the section when using `weight` of the last one
|
12
|
+
- Several classes with `embeds_many` were performing the `ordering` of those elements in the wrong way
|
13
|
+
- `Ecoportall::API::Common::Content::DoubleModel`
|
14
|
+
- `#replace_original_doc` had a couple of typos
|
15
|
+
- `#replace_doc` should only remove the variable referring to the current object and only if `new_doc` is `nil`
|
16
|
+
- `Ecoportal::API::Common::Content::CollectionModel` on insertion and deletion it was removing instance variable objects.
|
17
|
+
- 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.
|
18
|
+
- 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.
|
19
|
+
- `Ecoportal::API::Common::Content::ArrayModel` on initialize, default `doc` should be an `Array`
|
20
|
+
|
21
|
+
## [0.8.12] - 2021-08-30
|
22
|
+
|
23
|
+
### Added
|
24
|
+
- `Ecoportal::API::V2::Pages::PageStage#current_stage`
|
25
|
+
|
26
|
+
### Fixed
|
27
|
+
- `Ecoportal::API::Common::Content::DocHelpers#get_body` typo and wrong parameters on call.
|
28
|
+
- `Ecoportal::API::V2::Pages#update` should always return `Result` object.
|
29
|
+
- `Ecoportal::API::V2::Registers#search` was not using `cursor_id` to iterate.
|
30
|
+
|
31
|
+
## [0.8.11] - 2021-08-27
|
32
|
+
|
33
|
+
### Added
|
34
|
+
- `Ecoportal::API::V2::Page#stages?`
|
35
|
+
- `Ecoportal::API::V2::Pages::PageStage#current_stage_id`
|
36
|
+
- `Ecoportal::API::V2::Registers#search` added option keyed parameter `:only_first`
|
37
|
+
- which will make the method return the first `Ecoportal::API::V2::Registers::SearchResults`
|
38
|
+
- This has been **added** with the aim of knowing how many results out of how many entries.
|
39
|
+
|
40
|
+
### Changed
|
41
|
+
- `Ecoportal::API::V2::Pages::PageStage#update` won't update unless there's something to update.
|
42
|
+
|
43
|
+
### Fixed
|
44
|
+
|
45
|
+
|
46
|
+
## [0.8.10] - 2021-08-22
|
47
|
+
|
48
|
+
### Added
|
49
|
+
- `Ecoportal::API::Common::Content::CollectionModel#[]` now supports position as well
|
50
|
+
- `Ecoportal::API::V2::Page::Component::FilesField#add_file`: support for adding files
|
51
|
+
- `Ecoportal::API::V2::Page::Component::PeopleField#viewable_fields`: support for managing `viewable_fields`
|
52
|
+
|
53
|
+
### Changed
|
54
|
+
|
55
|
+
### Fixed
|
56
|
+
- `Ecoportal::API::V2::Page::Component::FilesField`: was not requiring `File`
|
57
|
+
- `Ecoportal::API::V2::Page::Component::NumberField#value`: it was missing :/
|
58
|
+
- `Ecoportal::API::Common::Content::HashDiffPatch` did not support nested objects in Arrays, where the nested object wouldn't have a `patch_ver`. This **fix** allows for it
|
59
|
+
- `Ecoportal::API::Common::Content::DoubleModel.passforced` to define `methods` that should always be present. This allows to define `patch_ver` as a forced `key` in models that have it
|
60
|
+
- The enforcement (`self.class.enforce!`) happens on `initialize`
|
61
|
+
- `passenforced` subjacent model `forced_model_keys` is inheritable
|
62
|
+
- `Ecoportal::API::Common::Content::CollectionModel`:
|
63
|
+
- Method `upsert!` was not working fine the parameters `pos`, `before` and `after`
|
64
|
+
- Method `delete!` did not support position
|
65
|
+
|
66
|
+
## [0.8.9] - 2021-08-16
|
5
67
|
|
6
68
|
### Added
|
7
69
|
- `Ecoportal::API::Common::Content::ModelHelpers`
|
@@ -110,6 +110,9 @@ module Ecoportal
|
|
110
110
|
end
|
111
111
|
|
112
112
|
# Transforms `value` into the actual `key` to access the object in the doc `Array`
|
113
|
+
# @note
|
114
|
+
# - The name of the method is after the paren't class method
|
115
|
+
# - This method would have been better called `_doc_pos` :)
|
113
116
|
def _doc_key(value)
|
114
117
|
#print "*(#{value.class})"
|
115
118
|
return super(value) unless value.is_a?(Hash) || value.is_a?(Content::DoubleModel)
|
@@ -143,17 +146,21 @@ module Ecoportal
|
|
143
146
|
end
|
144
147
|
|
145
148
|
# Get an element usign the `key`.
|
149
|
+
# @param value [String, Hash, Ecoportal::API::Common::Content::DoubleModel]
|
150
|
+
# @return [Object] the `items_class` element object
|
146
151
|
def [](value)
|
147
152
|
items_by_key[get_key(value)]
|
148
153
|
end
|
149
154
|
|
155
|
+
# @return [Array<Object>] the `items_class` element object
|
150
156
|
def values_at(*keys)
|
151
157
|
keys.map {|key| self[key]}
|
152
158
|
end
|
153
159
|
|
154
160
|
# Tries to find the element `value`, if it exists, it updates it
|
155
|
-
#
|
156
|
-
# @
|
161
|
+
# Otherwise it pushes it to the end
|
162
|
+
# @value [Hash, Ecoportal::API::Common::Content::DoubleModel] the eleement to be added
|
163
|
+
# @return [Object] the `items_class` element object
|
157
164
|
def upsert!(value, pos: NOT_USED, before: NOT_USED, after: NOT_USED)
|
158
165
|
unless value.is_a?(Hash) || value.is_a?(Content::DoubleModel)
|
159
166
|
raise "'Content::DoubleModel' or 'Hash' doc required"
|
@@ -163,7 +170,10 @@ module Ecoportal
|
|
163
170
|
if item = self[value]
|
164
171
|
item.replace_doc(item_doc)
|
165
172
|
else
|
166
|
-
_doc_upsert(item_doc, pos: pos, before: before, after: after)
|
173
|
+
_doc_upsert(item_doc, pos: pos, before: before, after: after).tap do |pos_idx|
|
174
|
+
_items.insert(pos_idx, new_item(item_doc))
|
175
|
+
@indexed = false
|
176
|
+
end
|
167
177
|
end
|
168
178
|
(item || self[item_doc]).tap do |item|
|
169
179
|
yield(item) if block_given?
|
@@ -171,12 +181,18 @@ module Ecoportal
|
|
171
181
|
end
|
172
182
|
|
173
183
|
# Deletes `value` from this `CollectionModel` instance
|
184
|
+
# @param value [String, Hash, Ecoportal::API::Common::Content::DoubleModel]
|
185
|
+
# - When used as `String`, the `key` value (i.e. `id` value) is expected
|
186
|
+
# - When used as `Hash`, it should be the `doc` of the target element
|
187
|
+
# - When used as `DoubleModel`, it should be the specific object to be deleted
|
174
188
|
def delete!(value)
|
175
|
-
unless value.is_a?(Hash) || value.is_a?(Content::DoubleModel)
|
189
|
+
unless value.is_a?(Hash) || value.is_a?(Content::DoubleModel) || value.is_a?(String)
|
176
190
|
raise "'Content::DoubleModel' or 'Hash' doc required"
|
177
191
|
end
|
178
192
|
if item = self[value]
|
179
193
|
_doc_delete(item.doc)
|
194
|
+
@indexed = false
|
195
|
+
_items.delete(item)
|
180
196
|
end
|
181
197
|
end
|
182
198
|
|
@@ -187,7 +203,8 @@ module Ecoportal
|
|
187
203
|
def items_key; self.class.items_key; end
|
188
204
|
|
189
205
|
def on_change
|
190
|
-
|
206
|
+
@indexed = false
|
207
|
+
#variables_remove!
|
191
208
|
end
|
192
209
|
|
193
210
|
# Gets the `key` of the object `value`
|
@@ -199,6 +216,8 @@ module Ecoportal
|
|
199
216
|
value[items_key]
|
200
217
|
when String
|
201
218
|
value
|
219
|
+
when Numeric
|
220
|
+
get_key(self.to_a[value])
|
202
221
|
end
|
203
222
|
end
|
204
223
|
|
@@ -243,25 +262,16 @@ module Ecoportal
|
|
243
262
|
# @return [Object] the element deleted from `doc`
|
244
263
|
def _doc_delete(value)
|
245
264
|
if current_pos = _doc_key(value)
|
246
|
-
_doc_items.delete_at(current_pos)
|
247
|
-
on_change
|
248
|
-
end
|
265
|
+
_doc_items.delete_at(current_pos)
|
249
266
|
end
|
250
267
|
end
|
251
268
|
|
252
269
|
def _doc_upsert(value, pos: NOT_USED, before: NOT_USED, after: NOT_USED)
|
253
|
-
current_pos =
|
254
|
-
|
255
|
-
|
256
|
-
pos
|
257
|
-
when used_param?(before)
|
258
|
-
_doc_key(before)
|
259
|
-
when used_param?(after)
|
260
|
-
if i = _doc_key(after)
|
261
|
-
i + 1
|
262
|
-
end
|
263
|
-
end
|
270
|
+
current_pos = if elem = self[value]
|
271
|
+
_doc_key(elem)
|
272
|
+
end
|
264
273
|
|
274
|
+
pos = scope_position(pos: pos, before: before, after: after)
|
265
275
|
pos ||= current_pos
|
266
276
|
|
267
277
|
if current_pos && pos
|
@@ -270,14 +280,29 @@ module Ecoportal
|
|
270
280
|
end
|
271
281
|
|
272
282
|
pos = (pos && pos < _doc_items.length)? pos : _doc_items.length
|
273
|
-
|
274
283
|
pos.tap do |i|
|
275
284
|
_doc_items.insert(pos, value)
|
276
|
-
on_change
|
277
285
|
end
|
278
286
|
|
279
287
|
end
|
280
288
|
|
289
|
+
def scope_position(pos: NOT_USED, before: NOT_USED, after: NOT_USED)
|
290
|
+
case
|
291
|
+
when used_param?(pos)
|
292
|
+
if elem = self[pos]
|
293
|
+
_doc_key(elem) - 1
|
294
|
+
end
|
295
|
+
when used_param?(before)
|
296
|
+
if elem = self[before]
|
297
|
+
_doc_key(elem) - 1
|
298
|
+
end
|
299
|
+
when used_param?(after)
|
300
|
+
if elem = self[after]
|
301
|
+
_doc_key(elem)
|
302
|
+
end
|
303
|
+
end
|
304
|
+
end
|
305
|
+
|
281
306
|
end
|
282
307
|
end
|
283
308
|
end
|
@@ -13,9 +13,9 @@ module Ecoportal
|
|
13
13
|
when doc.respond_to?(:as_update)
|
14
14
|
doc.as_update
|
15
15
|
when doc.respond_to?(:as_json)
|
16
|
-
Common::Content::
|
16
|
+
Common::Content::HashDiffPatch.patch_diff(doc.as_json, nil)
|
17
17
|
when doc.is_a?(Hash)
|
18
|
-
Common::Content::
|
18
|
+
Common::Content::HashDiffPatch.patch_diff(doc, nil)
|
19
19
|
else
|
20
20
|
raise "Could not get body for doc: #{doc}"
|
21
21
|
end
|
@@ -37,6 +37,8 @@ module Ecoportal
|
|
37
37
|
|
38
38
|
# Same as `attr_reader` but links to a subjacent `Hash` model property
|
39
39
|
# @note it does **not** create an _instance variable_
|
40
|
+
# @param methods [Array<Symbol>] the method that exposes the value
|
41
|
+
# as well as its `key` in the underlying `Hash` model.
|
40
42
|
def pass_reader(*methods)
|
41
43
|
methods.each do |method|
|
42
44
|
method = method.to_s.freeze
|
@@ -52,6 +54,8 @@ module Ecoportal
|
|
52
54
|
|
53
55
|
# Same as `attr_writer` but links to a subjacent `Hash` model property
|
54
56
|
# @note it does **not** create an _instance variable_
|
57
|
+
# @param methods [Array<Symbol>] the method that exposes the value
|
58
|
+
# as well as its `key` in the underlying `Hash` model.
|
55
59
|
def pass_writer(*methods)
|
56
60
|
methods.each do |method|
|
57
61
|
method = method.to_s.freeze
|
@@ -70,6 +74,8 @@ module Ecoportal
|
|
70
74
|
# no chance you can avoid invinite loop for `get_key` without setting an
|
71
75
|
# instance variable key at the moment of the object creation, when the
|
72
76
|
# `doc` is firstly received
|
77
|
+
# @param method [Symbol] the method that exposes the value
|
78
|
+
# as well as its `key` in the underlying `Hash` model.
|
73
79
|
def passkey(method)
|
74
80
|
method = method.to_s.freeze
|
75
81
|
var = instance_variable_name(method)
|
@@ -91,7 +97,33 @@ module Ecoportal
|
|
91
97
|
self
|
92
98
|
end
|
93
99
|
|
100
|
+
# These are methods that should always be present in patch update
|
101
|
+
# @note
|
102
|
+
# - `DoubleModel` can be used with objects that do not use `patch_ver`
|
103
|
+
# - This ensures that does that do, will get the correct patch update model
|
104
|
+
# @param method [Symbol] the method that exposes the value
|
105
|
+
# as well as its `key` in the underlying `Hash` model.
|
106
|
+
# @param default [Value] the default value that
|
107
|
+
# this `key` will be written in the model when it doesn't exixt
|
108
|
+
def passforced(method, default: , read_only: false)
|
109
|
+
model_forced_keys[method.to_s.freeze] = default
|
110
|
+
passthrough(method, read_only: read_only)
|
111
|
+
end
|
112
|
+
|
113
|
+
# Ensures `doc` has the `model_forced_keys`. If it doesn't, it adds those missing
|
114
|
+
# with the defined `default` values
|
115
|
+
def enforce!(doc)
|
116
|
+
return unless doc && doc.is_a?(Hash)
|
117
|
+
return if model_forced_keys.empty?
|
118
|
+
model_forced_keys.each do |key, default|
|
119
|
+
doc[key] = default unless doc.key?(key)
|
120
|
+
end
|
121
|
+
doc
|
122
|
+
end
|
123
|
+
|
94
124
|
# Same as `attr_accessor` but links to a subjacent `Hash` model property
|
125
|
+
# @param methods [Array<Symbol>] the method that exposes the value
|
126
|
+
# as well as its `key` in the underlying `Hash` model.
|
95
127
|
# @param read_only [Boolean] should it only define the reader?
|
96
128
|
def passthrough(*methods, read_only: false)
|
97
129
|
pass_reader *methods
|
@@ -101,6 +133,8 @@ module Ecoportal
|
|
101
133
|
|
102
134
|
# To link as a `Time` date to a subjacent `Hash` model property
|
103
135
|
# @see Ecoportal::API::Common::Content::DoubleModel#passthrough
|
136
|
+
# @param methods [Array<Symbol>] the method that exposes the value
|
137
|
+
# as well as its `key` in the underlying `Hash` model.
|
104
138
|
# @param read_only [Boolean] should it only define the reader?
|
105
139
|
def passdate(*methods, read_only: false)
|
106
140
|
pass_reader(*methods) {|value| to_time(value)}
|
@@ -111,6 +145,8 @@ module Ecoportal
|
|
111
145
|
end
|
112
146
|
|
113
147
|
# To link as a `Boolean` to a subjacent `Hash` model property
|
148
|
+
# @param methods [Array<Symbol>] the method that exposes the value
|
149
|
+
# as well as its `key` in the underlying `Hash` model.
|
114
150
|
# @param read_only [Boolean] should it only define the reader?
|
115
151
|
def passboolean(*methods, read_only: false)
|
116
152
|
pass_reader(*methods) {|value| value}
|
@@ -121,6 +157,8 @@ module Ecoportal
|
|
121
157
|
end
|
122
158
|
|
123
159
|
# To link as plain `Array` to a subjacent `Hash` model property
|
160
|
+
# @param methods [Array<Symbol>] the method that exposes the value
|
161
|
+
# as well as its `key` in the underlying `Hash` model.
|
124
162
|
# @param order_matters [Boolean] does the order matter
|
125
163
|
# @param uniq [Boolean] should it contain unique elements
|
126
164
|
def passarray(*methods, order_matters: true, uniq: true)
|
@@ -142,6 +180,10 @@ module Ecoportal
|
|
142
180
|
end
|
143
181
|
|
144
182
|
# Helper to embed one nested object under one property
|
183
|
+
# @param method [Symbol] the method that exposes the embeded object
|
184
|
+
# @param key [Symbol] the `key` that embeds it to the underlying `Hash` model
|
185
|
+
# @nullable [Boolean] to specify if this object can be `nil`
|
186
|
+
# @param klass [Class, String] the class of the embedded object
|
145
187
|
def embeds_one(method, key: method, nullable: false, klass:)
|
146
188
|
embed(method, key: key, nullable: nullable, multiple: false, klass: klass)
|
147
189
|
end
|
@@ -149,7 +191,11 @@ module Ecoportal
|
|
149
191
|
# @note
|
150
192
|
# - if you have a dedicated `Enumerable` class to manage `many`, you should use `:enum_class`
|
151
193
|
# - otherwise, just indicate the child class in `:klass` and it will auto generate the class
|
152
|
-
# @param
|
194
|
+
# @param method [Symbol] the method that exposes the embeded object
|
195
|
+
# @param key [Symbol] the `key` that embeds it to the underlying `Hash` model
|
196
|
+
# @param order_matters [Boolean] to state if the order will matter
|
197
|
+
# @param klass [Class, String] the class of the individual elements it embeds
|
198
|
+
# @param enum_class [Class, String] the class of the collection that will hold the individual elements
|
153
199
|
def embeds_many(method, key: method, order_matters: false, order_key: nil, klass: nil, enum_class: nil)
|
154
200
|
if enum_class
|
155
201
|
eclass = enum_class
|
@@ -186,8 +232,15 @@ module Ecoportal
|
|
186
232
|
end
|
187
233
|
end
|
188
234
|
|
235
|
+
# The list of keys that will be forced in the model
|
236
|
+
def model_forced_keys
|
237
|
+
@forced_model_keys ||= {}
|
238
|
+
end
|
239
|
+
|
189
240
|
end
|
190
241
|
|
242
|
+
inheritable_class_vars :forced_model_keys
|
243
|
+
|
191
244
|
attr_reader :_parent, :_key
|
192
245
|
|
193
246
|
def initialize(doc = {}, parent: self, key: nil)
|
@@ -195,6 +248,8 @@ module Ecoportal
|
|
195
248
|
@_parent = parent || self
|
196
249
|
@_key = key || self
|
197
250
|
|
251
|
+
self.class.enforce!(doc)
|
252
|
+
|
198
253
|
if _parent == self
|
199
254
|
@doc = doc
|
200
255
|
@original_doc = JSON.parse(@doc.to_json)
|
@@ -211,11 +266,13 @@ module Ecoportal
|
|
211
266
|
_parent.root
|
212
267
|
end
|
213
268
|
|
269
|
+
# @return [String] the `value` of the `key` method (i.e. `id` value)
|
214
270
|
def key
|
215
271
|
raise "No key_method defined for #{self.class}" unless key_method?
|
216
272
|
self.method(key_method).call
|
217
273
|
end
|
218
274
|
|
275
|
+
# @param [String] the `value` of the `key` method (i.e. `id` value)
|
219
276
|
def key=(value)
|
220
277
|
raise "No key_method defined for #{self.class}" unless key_method?
|
221
278
|
method = "#{key_method}="
|
@@ -234,16 +291,25 @@ module Ecoportal
|
|
234
291
|
end
|
235
292
|
end
|
236
293
|
|
294
|
+
# @return [nil, Hash] the underlying `Hash` model as is (carrying current changes)
|
237
295
|
def doc
|
238
296
|
raise UnlinkedModel.new(from: "#{self.class}#doc", key: _key) unless linked?
|
239
|
-
|
240
|
-
|
297
|
+
if is_root?
|
298
|
+
@doc
|
299
|
+
else
|
300
|
+
_parent.doc.dig(*[_doc_key(_key)].flatten)
|
301
|
+
end
|
241
302
|
end
|
242
303
|
|
304
|
+
# The `original_doc` holds the model as is now on server-side.
|
305
|
+
# @return [nil, Hash] the underlying `Hash` model as after last `consolidate!` changes
|
243
306
|
def original_doc
|
244
307
|
raise UnlinkedModel.new(from: "#{self.class}#original_doc", key: _key) unless linked?
|
245
|
-
|
246
|
-
|
308
|
+
if is_root?
|
309
|
+
@original_doc
|
310
|
+
else
|
311
|
+
_parent.original_doc.dig(*[_doc_key(_key)].flatten)
|
312
|
+
end
|
247
313
|
end
|
248
314
|
|
249
315
|
def as_json
|
@@ -254,19 +320,31 @@ module Ecoportal
|
|
254
320
|
doc.to_json(*args)
|
255
321
|
end
|
256
322
|
|
323
|
+
# @return [nil, Hash] the patch `Hash` model including only the changes between
|
324
|
+
# `original_doc` and `doc`
|
257
325
|
def as_update
|
258
326
|
new_doc = as_json
|
259
327
|
Common::Content::HashDiffPatch.patch_diff(new_doc, original_doc)
|
260
328
|
end
|
261
329
|
|
330
|
+
# @return [Boolean] stating if there are changes
|
262
331
|
def dirty?
|
263
332
|
as_update != {}
|
264
333
|
end
|
265
334
|
|
335
|
+
# It makes `original_doc` to be like `doc`
|
336
|
+
# @note
|
337
|
+
# - after executing it, there will be no pending changes
|
338
|
+
# - you should technically run this command, after a successful update request to the server
|
266
339
|
def consolidate!
|
267
340
|
replace_original_doc(JSON.parse(doc.to_json))
|
268
341
|
end
|
269
342
|
|
343
|
+
# It makes `doc` to be like `original`
|
344
|
+
# @note
|
345
|
+
# - after executing it, changes in `doc` will be lost
|
346
|
+
# - you should technically run this command only if you want to remove certain changes
|
347
|
+
# @key [Symbol] the specific part of the model you want to `reset`
|
270
348
|
def reset!(key = nil)
|
271
349
|
if key
|
272
350
|
keys = [key].flatten.compact
|
@@ -289,8 +367,8 @@ module Ecoportal
|
|
289
367
|
@doc = new_doc
|
290
368
|
else
|
291
369
|
dig_set(_parent.doc, [_doc_key(_key)].flatten, new_doc)
|
292
|
-
_parent.variable_remove!(_key)
|
293
|
-
variables_remove!
|
370
|
+
_parent.variable_remove!(_key) unless new_doc
|
371
|
+
#variables_remove!
|
294
372
|
end
|
295
373
|
end
|
296
374
|
|
@@ -307,9 +385,9 @@ module Ecoportal
|
|
307
385
|
def replace_original_doc(new_doc)
|
308
386
|
raise UnlinkedModel.new(from: "#{self.class}#replace_original_doc", key: _key) unless linked?
|
309
387
|
if is_root?
|
310
|
-
@
|
388
|
+
@original_doc = new_doc
|
311
389
|
else
|
312
|
-
dig_set(_parent.
|
390
|
+
dig_set(_parent.original_doc, [_doc_key(_key)].flatten, new_doc)
|
313
391
|
end
|
314
392
|
end
|
315
393
|
|
@@ -331,11 +409,21 @@ module Ecoportal
|
|
331
409
|
|
332
410
|
# Removes all the persistent variables
|
333
411
|
def variables_remove!
|
412
|
+
#puts "going to remove vars: #{@_dim_vars} on #{self.class} (parent: #{identify_parent(self._parent)})"
|
334
413
|
@_dim_vars.dup.map {|k| variable_remove!(k)}
|
335
414
|
end
|
336
415
|
|
337
416
|
private
|
338
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
|
+
|
339
427
|
def instance_variable_name(key)
|
340
428
|
self.class.instance_variable_name(key)
|
341
429
|
end
|
@@ -60,6 +60,8 @@ module Ecoportal
|
|
60
60
|
a == b
|
61
61
|
end
|
62
62
|
|
63
|
+
# Compares `a` as charring changes of `b`
|
64
|
+
# @return [Hash] patch data object with only changes
|
63
65
|
def patch_data(a, b = nil, delete: false)
|
64
66
|
{}.tap do |data_hash|
|
65
67
|
if delete
|
@@ -75,11 +77,17 @@ module Ecoportal
|
|
75
77
|
data_hash[key] = patch_diff(a_value, b_value)
|
76
78
|
data_hash.delete(key) if data_hash[key] == NO_CHANGES
|
77
79
|
end
|
80
|
+
#if (data_hash.keys - ID_KEYS).empty?
|
78
81
|
if (data_hash.keys - META_KEYS).empty?
|
79
82
|
return NO_CHANGES
|
80
83
|
else
|
81
|
-
patch_ver = (b && b["patch_ver"]) || 1
|
82
|
-
data_hash["patch_ver"] = patch_ver
|
84
|
+
#patch_ver = (b && b["patch_ver"]) || 1
|
85
|
+
#data_hash["patch_ver"] = patch_ver
|
86
|
+
if b && b.key?("patch_ver")
|
87
|
+
data_hash["patch_ver"] = b["patch_ver"]
|
88
|
+
elsif a && a.key?("patch_ver")
|
89
|
+
data_hash["patch_ver"] = a["patch_ver"]
|
90
|
+
end
|
83
91
|
end
|
84
92
|
end
|
85
93
|
end
|
@@ -172,7 +180,9 @@ module Ecoportal
|
|
172
180
|
arr.any? {|a| nested_array?(a)}
|
173
181
|
when arr.length == 1
|
174
182
|
arr = arr.first
|
175
|
-
arr.any?
|
183
|
+
arr.any? do |item|
|
184
|
+
item.is_a?(Hash) && item.has_key?("patch_ver")
|
185
|
+
end
|
176
186
|
else
|
177
187
|
false
|
178
188
|
end
|
@@ -7,14 +7,15 @@ module Ecoportal
|
|
7
7
|
class << self
|
8
8
|
def new_doc
|
9
9
|
{
|
10
|
-
"id"
|
11
|
-
"weight"
|
10
|
+
"id" => new_uuid,
|
11
|
+
"weight" => 99
|
12
12
|
}
|
13
13
|
end
|
14
14
|
end
|
15
15
|
|
16
16
|
passkey :id
|
17
|
-
|
17
|
+
passforced :patch_ver, default: 1
|
18
|
+
passthrough :name
|
18
19
|
passthrough :weight, :other_information
|
19
20
|
passboolean :complete
|
20
21
|
|
@@ -25,9 +25,9 @@ module Ecoportal
|
|
25
25
|
end
|
26
26
|
|
27
27
|
def ordered_tasks
|
28
|
-
actions.
|
29
|
-
|
30
|
-
end
|
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.
|
23
|
-
|
24
|
-
end
|
22
|
+
items.sort_by.with_index do |item, index|
|
23
|
+
[item.weight, index]
|
24
|
+
end
|
25
25
|
end
|
26
26
|
|
27
27
|
private
|
@@ -8,14 +8,15 @@ module Ecoportal
|
|
8
8
|
class << self
|
9
9
|
def new_doc
|
10
10
|
{
|
11
|
-
"id"
|
12
|
-
"weight"
|
11
|
+
"id" => new_uuid,
|
12
|
+
"weight" => 9999
|
13
13
|
}
|
14
14
|
end
|
15
15
|
end
|
16
16
|
|
17
17
|
passkey :id
|
18
|
-
|
18
|
+
passforced :patch_ver, default: 1
|
19
|
+
passthrough :label
|
19
20
|
passthrough :weight
|
20
21
|
passboolean :checked
|
21
22
|
end
|
@@ -4,10 +4,20 @@ module Ecoportal
|
|
4
4
|
class Page
|
5
5
|
class Component
|
6
6
|
class File < Common::Content::DoubleModel
|
7
|
+
class << self
|
8
|
+
def new_doc
|
9
|
+
{
|
10
|
+
"id" => new_uuid,
|
11
|
+
"position" => 99
|
12
|
+
}
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
7
16
|
passkey :id
|
8
|
-
|
9
|
-
passthrough :
|
10
|
-
passthrough :content_type, :
|
17
|
+
passforced :patch_ver, default: 1
|
18
|
+
passthrough :position
|
19
|
+
passthrough :file_size, :content_type, :token, read_only: true
|
20
|
+
passthrough :file_container_id
|
11
21
|
passdate :file_update_at, read_only: true
|
12
22
|
end
|
13
23
|
end
|
@@ -4,10 +4,46 @@ module Ecoportal
|
|
4
4
|
class Page
|
5
5
|
class Component
|
6
6
|
class FilesField < Page::Component
|
7
|
-
embeds_many :items, klass: "Ecoportal::API::V2::Page::File", order_key: :position
|
7
|
+
embeds_many :items, klass: "Ecoportal::API::V2::Page::Component::File", order_key: :position
|
8
|
+
|
9
|
+
def add_file(container_id, pos: NOT_USED, before: NOT_USED, after: NOT_USED)
|
10
|
+
file_doc = items.items_class.new_doc
|
11
|
+
items.upsert!(file_doc, pos: pos, before: before, after: after) do |file|
|
12
|
+
file.file_container_id = container_id
|
13
|
+
if prev = previous_file(file)
|
14
|
+
file.position = prev.position
|
15
|
+
end
|
16
|
+
yield(file) if block_given?
|
17
|
+
fix_file_positions!
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def ordered_files
|
22
|
+
items.sort_by.with_index do |file, index|
|
23
|
+
[file.position, index]
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def fix_file_positions!
|
30
|
+
ordered_files.each_with_index do |file, index|
|
31
|
+
file.position = index
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def previous_file(value)
|
36
|
+
fls = ordered_files
|
37
|
+
pos = fls.index(value) - 1
|
38
|
+
return if pos < 0
|
39
|
+
fls[pos]
|
40
|
+
end
|
41
|
+
|
8
42
|
end
|
9
43
|
end
|
10
44
|
end
|
11
45
|
end
|
12
46
|
end
|
13
47
|
end
|
48
|
+
|
49
|
+
require 'ecoportal/api/v2/page/component/file'
|
@@ -21,9 +21,9 @@ module Ecoportal
|
|
21
21
|
end
|
22
22
|
|
23
23
|
def ordered_stops
|
24
|
-
stops.
|
25
|
-
|
26
|
-
end
|
24
|
+
stops.sort_by.with_index do |stop, index|
|
25
|
+
[stop.threshold, index]
|
26
|
+
end
|
27
27
|
end
|
28
28
|
|
29
29
|
end
|
@@ -8,16 +8,16 @@ module Ecoportal
|
|
8
8
|
class << self
|
9
9
|
def new_doc
|
10
10
|
{
|
11
|
-
"id"
|
12
|
-
"threshold"
|
13
|
-
"color"
|
11
|
+
"id" => new_uuid,
|
12
|
+
"threshold" => nil,
|
13
|
+
"color" => nil
|
14
14
|
}
|
15
15
|
end
|
16
16
|
end
|
17
17
|
|
18
18
|
passkey :id
|
19
|
-
|
20
|
-
passthrough :color
|
19
|
+
passforced :patch_ver, default: 1
|
20
|
+
passthrough :threshold, :color
|
21
21
|
|
22
22
|
# Assign the color to the stop.
|
23
23
|
# @note These are the available colors:
|
@@ -5,7 +5,8 @@ module Ecoportal
|
|
5
5
|
class Component
|
6
6
|
class Image < Common::Content::DoubleModel
|
7
7
|
passkey :id
|
8
|
-
|
8
|
+
passforced :patch_ver, default: 1
|
9
|
+
passthrough :weight
|
9
10
|
passthrough :height, :width, :caption
|
10
11
|
passthrough :dimensions, :styles
|
11
12
|
end
|
@@ -7,7 +7,7 @@ module Ecoportal
|
|
7
7
|
passboolean :is_me_button
|
8
8
|
passthrough :attach_mode
|
9
9
|
passthrough :person_schema_id
|
10
|
-
|
10
|
+
embeds_many :viewable_fields, klass: "Ecoportal::API::V2::Page::Component::PeopleViewableField"
|
11
11
|
|
12
12
|
passboolean :singular
|
13
13
|
passthrough :requires_number
|
@@ -30,6 +30,16 @@ module Ecoportal
|
|
30
30
|
people_ids.reject! {|id| ids.include?(id)}
|
31
31
|
end
|
32
32
|
|
33
|
+
# Adds a field to the `viewable_fields`
|
34
|
+
def add_viewable(field_id, pos: NOT_USED, before: NOT_USED, after: NOT_USED)
|
35
|
+
viewable_fields.upsert!({"id" => field_id}, pos: pos, before: before, after: after)
|
36
|
+
end
|
37
|
+
|
38
|
+
# Deletes a field from the `viewable_fields`
|
39
|
+
def delete_viewable(field_id)
|
40
|
+
viewable_fields.delete!(field_id)
|
41
|
+
end
|
42
|
+
|
33
43
|
# Quick config helper
|
34
44
|
# @param conf [Symbol, Array<Symbol>]
|
35
45
|
# - `:snapshot` to set mode to `snapshot`
|
@@ -64,7 +74,7 @@ module Ecoportal
|
|
64
74
|
unless (rest = hash_except(cnf.dup, *supported)).empty?
|
65
75
|
unused.push(rest)
|
66
76
|
end
|
67
|
-
|
77
|
+
|
68
78
|
if cnf.key?(:singular) then self.singular = !!cnf[:singular] end
|
69
79
|
if cnf.key?(:permits)
|
70
80
|
if permits = cnf[:permits]
|
@@ -121,3 +131,5 @@ module Ecoportal
|
|
121
131
|
end
|
122
132
|
end
|
123
133
|
end
|
134
|
+
|
135
|
+
require 'ecoportal/api/v2/page/component/people_viewable_field'
|
@@ -58,9 +58,9 @@ module Ecoportal
|
|
58
58
|
end
|
59
59
|
|
60
60
|
def ordered_options
|
61
|
-
options.
|
62
|
-
|
63
|
-
end
|
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
|
@@ -8,14 +8,15 @@ module Ecoportal
|
|
8
8
|
class << self
|
9
9
|
def new_doc
|
10
10
|
{
|
11
|
-
"id"
|
12
|
-
"weight"
|
11
|
+
"id" => new_uuid,
|
12
|
+
"weight" => 9999
|
13
13
|
}
|
14
14
|
end
|
15
15
|
end
|
16
16
|
|
17
17
|
passkey :id
|
18
|
-
|
18
|
+
passforced :patch_ver, default: 1
|
19
|
+
passthrough :name, :value
|
19
20
|
passthrough :weight
|
20
21
|
passboolean :selected
|
21
22
|
|
@@ -13,8 +13,9 @@ module Ecoportal
|
|
13
13
|
end
|
14
14
|
end
|
15
15
|
|
16
|
-
passthrough :signed_by_id, :signed_by_name, :
|
17
|
-
|
16
|
+
passthrough :signed_by_id, :signed_by_name, read_only: true
|
17
|
+
passthrough :signature_url, read_only: true
|
18
|
+
passdate :signature_updated_at, read_only: true
|
18
19
|
passthrough :signature_content, :color
|
19
20
|
|
20
21
|
end
|
@@ -26,13 +26,16 @@ module Ecoportal
|
|
26
26
|
|
27
27
|
class << self
|
28
28
|
def new_doc(type: nil)
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
29
|
+
{
|
30
|
+
"id" => new_uuid
|
31
|
+
}.tap do |base_doc|
|
32
|
+
if type
|
33
|
+
base_doc.merge!({"type" => type})
|
34
|
+
if klass = get_class(base_doc)
|
35
|
+
base_doc.merge!(klass.new_doc || {})
|
36
|
+
end
|
37
|
+
end
|
33
38
|
end
|
34
|
-
return base_doc if base_doc&.key?("id")
|
35
|
-
(base_doc || {}).merge("id" => new_uuid)
|
36
39
|
end
|
37
40
|
|
38
41
|
def get_class(doc)
|
@@ -82,7 +85,8 @@ module Ecoportal
|
|
82
85
|
end
|
83
86
|
|
84
87
|
passkey :id
|
85
|
-
|
88
|
+
passforced :patch_ver, default: 1
|
89
|
+
passboolean :undeletable
|
86
90
|
passthrough :type, :label, :tooltip, :global_binding
|
87
91
|
passboolean :hidden, :deindex, :required
|
88
92
|
passthrough :accent
|
@@ -4,9 +4,10 @@ module Ecoportal
|
|
4
4
|
class Page
|
5
5
|
class Permit < Common::Content::DoubleModel
|
6
6
|
passkey :id
|
7
|
-
|
7
|
+
passforced :patch_ver, default: 1
|
8
8
|
passthrough :user_id, :user_name
|
9
9
|
passthrough :editable, :flags
|
10
|
+
embeds_one :flags, klass: "Ecoportal::API::V2::Page::PermissionFlags"
|
10
11
|
end
|
11
12
|
end
|
12
13
|
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
|
-
"id"
|
10
|
-
"type"
|
11
|
-
"weight"
|
11
|
+
"id" => new_uuid,
|
12
|
+
"type" => split ? "split" : "content",
|
13
|
+
"weight" => INITIAL_WEIGHT
|
12
14
|
}.tap do |out|
|
13
15
|
component_ids = if split
|
14
16
|
{
|
@@ -26,10 +28,11 @@ module Ecoportal
|
|
26
28
|
end
|
27
29
|
|
28
30
|
passkey :id
|
29
|
-
|
31
|
+
passforced :patch_ver, default: 1
|
32
|
+
passthrough :weight, :type
|
30
33
|
passthrough :heading, :left_heading, :right_heading
|
31
34
|
passarray :component_ids, :left_component_ids, :right_component_ids
|
32
|
-
|
35
|
+
passboolean :minimized
|
33
36
|
|
34
37
|
def split?
|
35
38
|
doc && doc["type"] == "split"
|
@@ -77,8 +80,9 @@ module Ecoportal
|
|
77
80
|
# @param field [Ecoportal::API::V2::Page::Component] the field to be added.
|
78
81
|
def add_component(field, after: nil, side: nil)
|
79
82
|
raise "field should be a Ecoportal::API::V2::Page::Component. Given: #{field.class}" unless field.is_a?(Ecoportal::API::V2::Page::Component)
|
83
|
+
# IMPORTANT NOTE: The code below creates objects, because field.section does a search on section.component_ids
|
80
84
|
if field.section == self
|
81
|
-
|
85
|
+
puts "Field with id '#{field.id}' already belongs to this section"
|
82
86
|
elsif sec = field.section
|
83
87
|
# Field belongs to another section
|
84
88
|
raise "Field with id '#{field.id}' belongs to section '#{sec.heading || "Unnamed"}' (id: '#{sec.id}')"
|
@@ -91,6 +95,7 @@ module Ecoportal
|
|
91
95
|
ids_ary = component_ids
|
92
96
|
fields = components
|
93
97
|
end
|
98
|
+
|
94
99
|
if after
|
95
100
|
after_fld = fields.find do |fld|
|
96
101
|
found = nil
|
@@ -99,6 +104,7 @@ module Ecoportal
|
|
99
104
|
found ||= same_string?(fld.label, after)
|
100
105
|
end
|
101
106
|
end
|
107
|
+
|
102
108
|
ids_ary.insert_one(field.id, after: after_fld&.id)
|
103
109
|
self
|
104
110
|
end
|
@@ -8,11 +8,15 @@ module Ecoportal
|
|
8
8
|
self.klass = :section_class
|
9
9
|
|
10
10
|
# Creates a new `section`
|
11
|
+
# @note
|
12
|
+
# - It won't fix weights unless all the sections of the ooze are present
|
13
|
+
# - This means that it doesn't fix section weights on stages,
|
14
|
+
# as shared sections could change order in other stages
|
11
15
|
def add(name: nil, split: false, pos: NOT_USED, before: NOT_USED, after: NOT_USED)
|
12
16
|
sec_doc = section_class.new_doc(split: split)
|
13
17
|
upsert!(sec_doc) do |section| #, pos: pos, before: before, after: after) do |section|
|
14
18
|
section.heading = name
|
15
|
-
if weight = scope_weight(pos: pos, before: before, after: after)
|
19
|
+
if weight = scope_weight(section, pos: pos, before: before, after: after)
|
16
20
|
section.weight = weight
|
17
21
|
end
|
18
22
|
fix_weights!
|
@@ -51,13 +55,13 @@ module Ecoportal
|
|
51
55
|
# Gets the sections ordered by `weight` (as they appear in the page)
|
52
56
|
def ordered
|
53
57
|
self.sort_by.with_index do |section, index|
|
54
|
-
|
58
|
+
[section.weight, index]
|
55
59
|
end
|
56
60
|
end
|
57
61
|
|
58
62
|
private
|
59
63
|
|
60
|
-
def scope_weight(pos: NOT_USED, before: NOT_USED, after: NOT_USED)
|
64
|
+
def scope_weight(section, pos: NOT_USED, before: NOT_USED, after: NOT_USED)
|
61
65
|
case
|
62
66
|
when used_param?(pos)
|
63
67
|
if pos = to_section(pos)
|
@@ -71,6 +75,11 @@ module Ecoportal
|
|
71
75
|
if after = to_section(after)
|
72
76
|
after.weight
|
73
77
|
end
|
78
|
+
end.yield_self do |weight|
|
79
|
+
weight = ordered.reject do |sec|
|
80
|
+
sec.id == section.id
|
81
|
+
end.last&.weight
|
82
|
+
weight ||= section_class.const_get(:INITIAL_WEIGHT)
|
74
83
|
end
|
75
84
|
end
|
76
85
|
|
@@ -86,8 +95,10 @@ module Ecoportal
|
|
86
95
|
end
|
87
96
|
|
88
97
|
def fix_weights!
|
89
|
-
|
90
|
-
|
98
|
+
unless self._parent.is_a?(Ecoportal::API::V2::Pages::PageStage)
|
99
|
+
ordered.each_with_index do |section, index|
|
100
|
+
section.weight = index
|
101
|
+
end
|
91
102
|
end
|
92
103
|
end
|
93
104
|
|
@@ -4,7 +4,7 @@ module Ecoportal
|
|
4
4
|
class Page
|
5
5
|
class Stage < Common::Content::DoubleModel
|
6
6
|
passkey :id
|
7
|
-
|
7
|
+
passforced :patch_ver, default: 1
|
8
8
|
passthrough :name, :ordering
|
9
9
|
passarray :subtags, order_matters: false
|
10
10
|
passarray :section_ids
|
@@ -22,7 +22,7 @@ module Ecoportal
|
|
22
22
|
root.sections.values_at(*sec_ids).select.with_index do |sec, i|
|
23
23
|
puts "Warning: section #{id} points to missing section #{sec_ids[i]}" if !sec
|
24
24
|
fld && (!block_given? || yield(sec))
|
25
|
-
end.sort_by {|sec| sec.weight}
|
25
|
+
end.sort_by.with_index {|sec, index| [sec.weight, index]}
|
26
26
|
end
|
27
27
|
|
28
28
|
def add_section(*secs)
|
@@ -14,9 +14,9 @@ module Ecoportal
|
|
14
14
|
end
|
15
15
|
|
16
16
|
#def ordered
|
17
|
-
# self.
|
18
|
-
#
|
19
|
-
# end
|
17
|
+
# self.sort_by.with_index do |stage, index|
|
18
|
+
# [stage.ordering, index]
|
19
|
+
# end
|
20
20
|
#end
|
21
21
|
|
22
22
|
end
|
@@ -2,9 +2,19 @@ module Ecoportal
|
|
2
2
|
module API
|
3
3
|
class V2
|
4
4
|
class Page < Common::Content::DoubleModel
|
5
|
-
ALLOWED_KEYS =
|
5
|
+
ALLOWED_KEYS = [
|
6
|
+
"id", "patch_ver", "name", "template_id",
|
7
|
+
"base_tags", "tags",
|
8
|
+
"time_zone", "created_at", "updated_at",
|
9
|
+
"components", "sections", "stages",
|
10
|
+
"permits", "mould_counter", "mould",
|
11
|
+
"state", "task_priority",
|
12
|
+
"votes_enabled", "upvotes", "downvotes",
|
13
|
+
"force_errors", "subtags"
|
14
|
+
]
|
15
|
+
|
6
16
|
passkey :id
|
7
|
-
|
17
|
+
passforced :patch_ver, default: 1
|
8
18
|
passthrough :name, :template_id
|
9
19
|
passarray :base_tags, :tags, order_matters: false
|
10
20
|
passthrough :time_zone
|
@@ -19,12 +29,50 @@ module Ecoportal
|
|
19
29
|
embeds_many :sections, enum_class: :sections_class
|
20
30
|
embeds_many :stages, enum_class: :stages_class
|
21
31
|
|
32
|
+
def initialize(doc = [], parent: self, key: nil)
|
33
|
+
super(_doc_bug_fix(doc), parent: parent, key: key)
|
34
|
+
end
|
35
|
+
|
22
36
|
def as_update
|
23
37
|
super.tap do |hash|
|
24
38
|
unless !hash
|
25
39
|
hash["data"].select! do |key, value|
|
26
40
|
ALLOWED_KEYS.include?(key)
|
27
41
|
end
|
42
|
+
return nil if (hash["data"].keys - ["patch_ver"]).empty?
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def stages?
|
48
|
+
self.stages.count > 0
|
49
|
+
end
|
50
|
+
|
51
|
+
private
|
52
|
+
|
53
|
+
def _doc_bug_fix(hash)
|
54
|
+
hash.tap do |hash|
|
55
|
+
_fix_doc(hash["stages"], "flow_node_ids", "section_ids") if hash.key?("stages")
|
56
|
+
if hash.key?("sections")
|
57
|
+
_fix_doc(hash["sections"], "membrane_ids", "component_ids")
|
58
|
+
_fix_doc(hash["sections"], "left_membrane_ids", "left_component_ids")
|
59
|
+
_fix_doc(hash["sections"], "right_membrane_ids", "right_component_ids")
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def _fix_doc(value, source, dest)
|
65
|
+
value.tap do |value|
|
66
|
+
case value
|
67
|
+
when Array
|
68
|
+
value.each {|v| _fix_doc(v, source, dest)}
|
69
|
+
when Hash
|
70
|
+
if value.key?(source) && !value.key?(dest)
|
71
|
+
value[dest] = value[source]
|
72
|
+
value.delete(source)
|
73
|
+
end
|
74
|
+
else
|
75
|
+
# Do nothing!
|
28
76
|
end
|
29
77
|
end
|
30
78
|
end
|
@@ -9,6 +9,19 @@ module Ecoportal
|
|
9
9
|
|
10
10
|
embeds_many :permits, klass: "Ecoportal::API::V2::Page::Permit"
|
11
11
|
passarray :force_errors, :subtags, order_matters: false
|
12
|
+
|
13
|
+
# `id` of the stage we got the data of.
|
14
|
+
def current_stage_id
|
15
|
+
doc.dig("active_stage", "id") || doc["current_stage_id"]
|
16
|
+
end
|
17
|
+
|
18
|
+
# @return [Ecoportal::API::V2::Page::Stage]
|
19
|
+
def current_stage
|
20
|
+
if stage_id = current_stage_id
|
21
|
+
stages[stage_id]
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
12
25
|
end
|
13
26
|
end
|
14
27
|
end
|
@@ -47,10 +47,13 @@ module Ecoportal
|
|
47
47
|
end
|
48
48
|
|
49
49
|
# Requests to update an existing page via api.
|
50
|
+
# @note It won't launch the update unless there are changes
|
50
51
|
# @param doc [Hash, Page] data that at least contains an `id` (internal or external) of the target page.
|
51
52
|
# @return [Response] an object with the api response.
|
52
53
|
def update(doc)
|
53
54
|
body = get_body(doc) # , level: "page"
|
55
|
+
# Launch only if there are changes
|
56
|
+
raise "Missing page object" unless body && body["page"]
|
54
57
|
id = get_id(doc)
|
55
58
|
client.patch("/pages/#{CGI.escape(id)}", data: body)
|
56
59
|
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module Ecoportal
|
2
|
+
module API
|
3
|
+
class V2
|
4
|
+
class Registers
|
5
|
+
class SearchResults < Common::Content::DoubleModel
|
6
|
+
passthrough :total, :total_before_filtering
|
7
|
+
passarray :tags, order_matters: false
|
8
|
+
embeds_many :results, klass: "Ecoportal::API::V2::Registers::PageResult"
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -9,6 +9,7 @@ module Ecoportal
|
|
9
9
|
|
10
10
|
class_resolver :register_class, "Ecoportal::API::V2::Registers::Register"
|
11
11
|
class_resolver :register_search_result_class, "Ecoportal::API::V2::Registers::PageResult"
|
12
|
+
class_resolver :register_search_results, "Ecoportal::API::V2::Registers::SearchResults"
|
12
13
|
|
13
14
|
attr_reader :client
|
14
15
|
|
@@ -35,7 +36,12 @@ module Ecoportal
|
|
35
36
|
# @param options [Hash] the search options
|
36
37
|
# @option options [Hash<Symbol, String>] :query plain search (like the search box in register).
|
37
38
|
# @option options [Hash<Symbol, Array<Object>>] :filters the set of filters.
|
39
|
+
# @option options [Boolean] if `true`, it only performs the first search and results `Ecoportal::API::V2::Registers::SearchResults`.
|
40
|
+
# @yield [result] something to do with search page-result.
|
41
|
+
# @yieldparam result [Ecoportal::V2::Registers::PageResult] a page result.
|
42
|
+
# @return [Ecoportal::API::V2::Registers, Ecoportal::API::V2::Registers::SearchResults]
|
38
43
|
def search(register_id, options = {})
|
44
|
+
only_first = options.delete(:only_first)
|
39
45
|
# supply a query string
|
40
46
|
# or a filter array (copy/paste from dev tools in the browser)
|
41
47
|
options = {query: nil, filters: []}.update(options)
|
@@ -49,6 +55,12 @@ module Ecoportal
|
|
49
55
|
end
|
50
56
|
end
|
51
57
|
|
58
|
+
if only_first
|
59
|
+
response = client.get("/registers/#{register_id}/search", params: options)
|
60
|
+
raise "Request failed - Status #{response.status}: #{response.body}" unless response.success?
|
61
|
+
return register_search_results.new(response.body["data"])
|
62
|
+
end
|
63
|
+
|
52
64
|
cursor_id = nil
|
53
65
|
results = 0
|
54
66
|
loop do
|
@@ -70,8 +82,8 @@ module Ecoportal
|
|
70
82
|
yield object
|
71
83
|
end
|
72
84
|
|
73
|
-
|
74
|
-
break
|
85
|
+
break if total <= results
|
86
|
+
break unless (cursor_id = data["cursor_id"])
|
75
87
|
end
|
76
88
|
self
|
77
89
|
end
|
@@ -87,3 +99,4 @@ require 'ecoportal/api/v2/registers/register'
|
|
87
99
|
require 'ecoportal/api/v2/registers/stage_result'
|
88
100
|
require 'ecoportal/api/v2/registers/stages_result'
|
89
101
|
require 'ecoportal/api/v2/registers/page_result'
|
102
|
+
require 'ecoportal/api/v2/registers/search_results'
|
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.
|
4
|
+
version: 0.8.13
|
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-
|
11
|
+
date: 2021-09-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -209,6 +209,7 @@ files:
|
|
209
209
|
- lib/ecoportal/api/v2/page/component/law_field.rb
|
210
210
|
- lib/ecoportal/api/v2/page/component/number_field.rb
|
211
211
|
- lib/ecoportal/api/v2/page/component/people_field.rb
|
212
|
+
- lib/ecoportal/api/v2/page/component/people_viewable_field.rb
|
212
213
|
- lib/ecoportal/api/v2/page/component/plain_text_field.rb
|
213
214
|
- lib/ecoportal/api/v2/page/component/reference_field.rb
|
214
215
|
- lib/ecoportal/api/v2/page/component/rich_text_field.rb
|
@@ -230,6 +231,7 @@ files:
|
|
230
231
|
- lib/ecoportal/api/v2/registers.rb
|
231
232
|
- lib/ecoportal/api/v2/registers/page_result.rb
|
232
233
|
- lib/ecoportal/api/v2/registers/register.rb
|
234
|
+
- lib/ecoportal/api/v2/registers/search_results.rb
|
233
235
|
- lib/ecoportal/api/v2/registers/stage_result.rb
|
234
236
|
- lib/ecoportal/api/v2/registers/stages_result.rb
|
235
237
|
- lib/ecoportal/api/v2/registers/template.rb
|