ecoportal-api-oozes 0.5.5 → 0.6.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f6ecefc83d30f273a4ededb781765cde494d5e6e0facad8a501fc6ef023e73ee
4
- data.tar.gz: b1e0b4dab879d237580bb4d599ea500fe7a5154f6f7f874e418360bfefc9700d
3
+ metadata.gz: 65d013d143d1c5dc7b19de58086d973dedc454dbdc89f4ac1d5525e58342c457
4
+ data.tar.gz: f083e27753e51add116d0aeb12ebc13632dc1834a42e5b690f0da353216b2f4f
5
5
  SHA512:
6
- metadata.gz: 98694b883b97f35fc71c0633717d92ec9da2704bd6d63c824a38c43eca512645ab6f3ecd77924d41ae527d112ffc36fcc4190f82e06b4b6453d21ccca44de22d
7
- data.tar.gz: 9ef14de17795590c48d3b3cb0a6e2ba96be3b1d1ff76cee959a1860cbf1689d17b0551842352b7326094d1c8071a8569cf58c6b8feb5dd8933da8cd6a69521fc
6
+ metadata.gz: 90b0d48b663d8698b33e56d113a44b84197a48fc47b29640abae653fe4b49740bc975fb6e0781e24dea5ee5bc3a29dababafab008adc893c13fda0157ae91793
7
+ data.tar.gz: af2a47022b66bc5238b2c5a3235c192d5f164493d221d3f94c95f3156962dcbdb5749376abc8218cd8023d84b03c6a31fd8c23d54c2324f815c4e41b3e464041
@@ -0,0 +1,17 @@
1
+ # Change Log
2
+ All notable changes to this project will be documented in this file.
3
+
4
+ ## [0.6.0] - 2020-07-xx
5
+
6
+ ### Added
7
+ ### Changed
8
+ - upgraded `ecoportal-api` gem
9
+ ### Fixed
10
+
11
+ ## [0.5.9] - 2020-07-02
12
+
13
+ ### Added
14
+ - helper `Ecoportal::API::Common::Content::StringDigest#indexable_label`: to see the part of a label that gets indexed
15
+ - this `CHANGELOG.md` file
16
+ ### Changed
17
+ ### Fixed
@@ -5,7 +5,7 @@ require "ecoportal/api/v2/version"
5
5
 
6
6
  Gem::Specification.new do |spec|
7
7
  spec.name = "ecoportal-api-oozes"
8
- spec.version = Ecoportal::API::V2::VERSION
8
+ spec.version = Ecoportal::API::V2::GEM_VERSION
9
9
  spec.authors = ["Oscar Segura"]
10
10
  spec.email = ["rien@ecoportal.co.nz", "oscar@ecoportal.co.nz", "bozydar@ecoportal.co.nz"]
11
11
 
@@ -27,5 +27,5 @@ Gem::Specification.new do |spec|
27
27
  spec.add_development_dependency "redcarpet", "~> 3.5", ">= 3.5.0"
28
28
  spec.add_development_dependency "pry"
29
29
 
30
- spec.add_dependency 'ecoportal-api', '~> 0.5', '>= 0.5.5'
30
+ spec.add_dependency 'ecoportal-api', '~> 0.6', '>= 0.6.0'
31
31
  end
@@ -6,5 +6,5 @@ module Ecoportal
6
6
  end
7
7
  end
8
8
 
9
- require "ecoportal/api/common"
10
- require "ecoportal/api/v2"
9
+ require_relative "api/common"
10
+ require_relative "api/v2"
@@ -219,7 +219,6 @@ module Ecoportal
219
219
  end
220
220
  end
221
221
 
222
- # TODO
223
222
  def insert_one(value, pos: NOT_USED, before: NOT_USED, after: NOT_USED)
224
223
  i = index(value)
225
224
  return i if (i && uniq?)
@@ -145,18 +145,20 @@ module Ecoportal
145
145
  # Tries to find the element `value`, if it exists, it updates it
146
146
  # Otherwise it pushes it to the end
147
147
  # @return the element
148
- def upsert!(value)
148
+ def upsert!(value, pos: NOT_USED, before: NOT_USED, after: NOT_USED)
149
149
  unless value.is_a?(Hash) || value.is_a?(Content::DoubleModel)
150
150
  raise "'Content::DoubleModel' or 'Hash' doc required"
151
151
  end
152
152
  item_doc = value.is_a?(Content::DoubleModel)? value.doc : value
153
+ item_doc = JSON.parse(item_doc.to_json)
153
154
  if item = self[value]
154
- item.replace_doc(JSON.parse(item_doc.to_json))
155
+ item.replace_doc(item_doc)
155
156
  else
156
- item = new_item(item_doc)
157
- _doc_items << item.doc
157
+ _doc_upsert(item_doc, pos: pos, before: before, after: after)
158
+ end
159
+ (item || self[item_doc]).tap do |item|
160
+ yield(item) if block_given?
158
161
  end
159
- item
160
162
  end
161
163
 
162
164
  protected
@@ -165,6 +167,10 @@ module Ecoportal
165
167
  def uniq?; self.class.uniq; end
166
168
  def items_key; self.class.items_key; end
167
169
 
170
+ def on_change
171
+ variables_remove!
172
+ end
173
+
168
174
  # Gets the `key` of the object
169
175
  def get_key(value)
170
176
  case value
@@ -198,11 +204,9 @@ module Ecoportal
198
204
  self.class.new_item(value, parent: self)
199
205
  end
200
206
 
201
- private
202
-
203
207
  # Helper to remove tracked down instance variables
204
208
  def variable_remove!(key)
205
- if (k = get_key(key)) && (item = @items_by_key[k])
209
+ if @items_by_key && (k = get_key(key)) && (item = @items_by_key[k])
206
210
  _items.delete(item) if _items.include?(item)
207
211
  @items_by_key.delete(k)
208
212
  else
@@ -216,6 +220,36 @@ module Ecoportal
216
220
  super
217
221
  end
218
222
 
223
+ def _doc_upsert(value, pos: NOT_USED, before: NOT_USED, after: NOT_USED)
224
+ current_pos = _doc_key(value)
225
+ pos = case
226
+ when used_param?(pos)
227
+ pos
228
+ when used_param?(before)
229
+ _doc_key(before)
230
+ when used_param?(after)
231
+ puts "to add after #{after.id}"
232
+ if i = _doc_key(after)
233
+ i + 1
234
+ end
235
+ end
236
+
237
+ pos ||= current_pos
238
+
239
+ if current_pos && pos
240
+ _doc_items.delete(current_pos)
241
+ pos = (pos <= current_pos)? pos : pos - 1
242
+ end
243
+
244
+ pos = (pos && pos < _doc_items.length)? pos : _doc_items.length
245
+
246
+ pos.tap do |i|
247
+ _doc_items.insert(pos, value)
248
+ on_change
249
+ end
250
+
251
+ end
252
+
219
253
  end
220
254
  end
221
255
  end
@@ -1,3 +1,5 @@
1
+ require 'securerandom'
2
+
1
3
  module Ecoportal
2
4
  module API
3
5
  module Common
@@ -28,6 +30,10 @@ module Ecoportal
28
30
  @key = value.to_s.freeze
29
31
  end
30
32
 
33
+ def new_uuid(length: 12)
34
+ SecureRandom.hex(length)
35
+ end
36
+
31
37
  # Same as `attr_reader` but links to a subjacent `Hash` model property
32
38
  # @note it does **not** create an _instance variable_
33
39
  def pass_reader(*methods)
@@ -153,6 +159,7 @@ module Ecoportal
153
159
 
154
160
  embeds_one(method, key: key, multiple: true, klass: dim_class)
155
161
  end
162
+
156
163
  end
157
164
 
158
165
  attr_reader :_parent, :_key
@@ -250,16 +257,6 @@ module Ecoportal
250
257
  # self
251
258
  #end
252
259
 
253
- protected
254
-
255
- def is_root?
256
- _parent == self && !!defined?(@doc)
257
- end
258
-
259
- def linked?
260
- is_root? || !!_parent.doc
261
- end
262
-
263
260
  def replace_doc(new_doc)
264
261
  raise UnlinkedModel.new(from: "#{self.class}#replace_doc", key: _key) unless linked?
265
262
  if is_root?
@@ -271,6 +268,16 @@ module Ecoportal
271
268
  end
272
269
  end
273
270
 
271
+ protected
272
+
273
+ def is_root?
274
+ _parent == self && !!defined?(@doc)
275
+ end
276
+
277
+ def linked?
278
+ is_root? || !!_parent.doc
279
+ end
280
+
274
281
  def replace_original_doc(new_doc)
275
282
  raise UnlinkedModel.new(from: "#{self.class}#replace_original_doc", key: _key) unless linked?
276
283
  if is_root?
@@ -298,7 +305,7 @@ module Ecoportal
298
305
 
299
306
  # Removes all the persistent variables
300
307
  def variables_remove!
301
- @_dim_vars.map {|k| variable_remove!(k)}
308
+ @_dim_vars.dup.map {|k| variable_remove!(k)}
302
309
  end
303
310
 
304
311
  private
@@ -31,6 +31,8 @@ module Ecoportal
31
31
  # 3. the `data` property holds the specific changes of the object
32
32
  # - the `patch_ver` (compulsory) is **incremental** (for data integrity)
33
33
  # - the properties that have changed
34
+ # @note
35
+ # * there should not be difference between `null` and `""` (empty string)
34
36
  # @param a [Hash] current hash model
35
37
  # @param b [Hash] previous hash model
36
38
  # @return [Hash] a `patch data`
@@ -51,12 +53,19 @@ module Ecoportal
51
53
 
52
54
  private
53
55
 
56
+ def equal_values(a, b)
57
+ if a.is_a?(String) || b.is_a?(String)
58
+ return true if a.to_s.strip.empty? && b.to_s.strip.empty?
59
+ end
60
+ a == b
61
+ end
62
+
54
63
  def patch_data(a, b = nil)
55
64
  {}.tap do |data_hash|
56
65
  a.each do |key, a_value|
57
66
  b_value = b[key] if b_has_key = b && b.key?(key)
58
67
  is_meta_key = META_KEYS.include?(key)
59
- skip_equals = b_has_key && a_value == b_value
68
+ skip_equals = b_has_key && equal_values(a_value, b_value)
60
69
  next if is_meta_key || skip_equals
61
70
  data_hash[key] = patch_diff(a_value, b_value)
62
71
  data_hash.delete(key) if data_hash[key] == NO_CHANGES
@@ -99,14 +108,19 @@ module Ecoportal
99
108
  end
100
109
 
101
110
  def patch_data_array(a, b)
111
+ original_b = b
102
112
  a ||= []; b ||= []
103
113
  if !nested_array?(a, b)
104
114
  if a.length == b.length && (a & b).length == b.length
105
- NO_CHANGES
115
+ if original_b
116
+ NO_CHANGES
117
+ else
118
+ a
119
+ end
106
120
  else
107
121
  a
108
122
  end
109
- else
123
+ else # array with nested elements
110
124
  a_ids = array_ids(a)
111
125
  b_ids = array_ids(b)
112
126
 
@@ -116,19 +130,20 @@ module Ecoportal
116
130
 
117
131
  arr_delete = del_ids.map do |id|
118
132
  patch_delete(array_id_item(b, id))
119
- end
133
+ end.compact
120
134
 
121
135
  arr_update = oth_ids.map do |id|
122
136
  patch_update(array_id_item(a, id), array_id_item(b, id))
123
- end
137
+ end.compact
124
138
 
125
139
  arr_new = new_ids.map do |id|
126
140
  patch_new(array_id_item(a, id))
127
- end
141
+ end.compact
128
142
 
129
143
  (arr_delete.concat(arr_update).concat(arr_new)).tap do |patch_array|
130
144
  # remove data with no `id`
131
145
  patch_array.reject! {|item| !item.is_a?(Hash)}
146
+ return NO_CHANGES if patch_array.empty?
132
147
  end
133
148
  end
134
149
  end
@@ -7,12 +7,17 @@ module Ecoportal
7
7
  module StringDigest
8
8
  MAX_HASH_LABEL = 64
9
9
 
10
+ def indexable_label(str)
11
+ return nil unless str
12
+ lbl = str.downcase.gsub(/[^A-Za-z]+/,"-").slice(0, MAX_HASH_LABEL)
13
+ return nil unless lbl.length >= 3
14
+ lbl
15
+ end
16
+
10
17
  # Calculates the Hash of the field based on label
11
18
  def hash_label(str)
12
- return false unless str
13
- label = str.downcase.gsub(/[^A-Za-z]+/,"-").slice(0, MAX_HASH_LABEL)
14
- return false unless label.length >= 3
15
- return "z" + Digest::MD5.hexdigest(label).slice(0, 8);
19
+ return nil unless lbl = indexable_label(str)
20
+ "z" + Digest::MD5.hexdigest(lbl).slice(0, 8);
16
21
  end
17
22
 
18
23
  end
@@ -45,4 +45,3 @@ end
45
45
 
46
46
  require 'ecoportal/api/v2/registers'
47
47
  require 'ecoportal/api/v2/pages'
48
- #require 'ecoportal/api/v2/stages'
@@ -2,6 +2,7 @@ module Ecoportal
2
2
  module API
3
3
  class V2
4
4
  class Page < Common::Content::DoubleModel
5
+ ALLOWED_KEYS = %w[id patch_ver name template_id base_tags tags time_zone created_at updated_at can components sections stages]
5
6
  passkey :id
6
7
  passthrough :patch_ver
7
8
  passthrough :name, :template_id
@@ -17,6 +18,17 @@ module Ecoportal
17
18
  embeds_one :components, multiple: true, klass: :components_class
18
19
  embeds_one :sections, multiple: true, klass: :sections_class
19
20
  embeds_one :stages, multiple: true, klass: :stages_class
21
+
22
+ def as_update
23
+ super.tap do |hash|
24
+ unless !hash
25
+ hash["data"].select! do |key, value|
26
+ ALLOWED_KEYS.include?(key)
27
+ end
28
+ end
29
+ end
30
+ end
31
+
20
32
  end
21
33
  end
22
34
  end
@@ -23,6 +23,13 @@ module Ecoportal
23
23
  class_resolver :law_field_class, "Ecoportal::API::V2::Page::Component::LawField"
24
24
 
25
25
  class << self
26
+ def new_doc(type:)
27
+ {
28
+ "id" => new_uuid,
29
+ "type" => type
30
+ }
31
+ end
32
+
26
33
  def get_class(doc)
27
34
  if doc.is_a?(Hash)
28
35
  case doc["type"]
@@ -81,6 +88,10 @@ module Ecoportal
81
88
  root.sections.find {|sec| sec.component?(id)}
82
89
  end
83
90
 
91
+ def indexable_label
92
+ self.class.indexable_label(label)
93
+ end
94
+
84
95
  end
85
96
  end
86
97
  end
@@ -4,8 +4,8 @@ module Ecoportal
4
4
  class Page
5
5
  class Component
6
6
  class ActionField < Page::Component
7
- class_resolver :action_class, "Ecoportal::API::V2::Page::Component::Action"
8
- embeds_multiple :actions, klass: :action_class, order_key: :weight
7
+ #class_resolver :action_class, "Ecoportal::API::V2::Page::Component::Action"
8
+ embeds_multiple :actions, klass: "Ecoportal::API::V2::Page::Component::Action", order_key: :weight
9
9
  end
10
10
  end
11
11
  end
@@ -4,8 +4,8 @@ module Ecoportal
4
4
  class Page
5
5
  class Component
6
6
  class ChecklistField < Page::Component
7
- class_resolver :checklist_item_class, "Ecoportal::API::V2::Page::Component::ChecklistItem"
8
- embeds_multiple :items, klass: :checklist_item_class, order_key: :weight
7
+ #class_resolver :checklist_item_class, "Ecoportal::API::V2::Page::Component::ChecklistItem"
8
+ embeds_multiple :items, klass: "Ecoportal::API::V2::Page::Component::ChecklistItem", order_key: :weight
9
9
  end
10
10
  end
11
11
  end
@@ -4,8 +4,8 @@ module Ecoportal
4
4
  class Page
5
5
  class Component
6
6
  class FilesField < Page::Component
7
- class_resolver :file_class, "Ecoportal::API::V2::Page::File"
8
- embeds_multiple :items, klass: :file_class, order_key: :position
7
+ #class_resolver :file_class, "Ecoportal::API::V2::Page::File"
8
+ embeds_multiple :items, klass: "Ecoportal::API::V2::Page::File", order_key: :position
9
9
  end
10
10
  end
11
11
  end
@@ -4,8 +4,8 @@ module Ecoportal
4
4
  class Page
5
5
  class Component
6
6
  class ImagesField < Page::Component
7
- class_resolver :image_class, "Ecoportal::API::V2::Page::Image"
8
- embeds_multiple :images, klass: :image_class, order_key: :weight
7
+ #class_resolver :image_class, "Ecoportal::API::V2::Page::Image"
8
+ embeds_multiple :images, klass: "Ecoportal::API::V2::Page::Image", order_key: :weight
9
9
  end
10
10
  end
11
11
  end
@@ -5,6 +5,11 @@ module Ecoportal
5
5
  class Component
6
6
  class PeopleField < Page::Component
7
7
  passarray :people_ids
8
+
9
+ def add(id)
10
+ people_ids << id
11
+ end
12
+
8
13
  end
9
14
  end
10
15
  end
@@ -6,8 +6,69 @@ module Ecoportal
6
6
  class SelectionField < Page::Component
7
7
  passthrough :multiple, :other, :other_desc
8
8
 
9
- class_resolver :selection_option_class, "Ecoportal::API::V2::Page::Component::SelectionOption"
10
- embeds_multiple :options, klass: :selection_option_class, order_key: :weight
9
+ #class_resolver :selection_option_class, "Ecoportal::API::V2::Page::Component::SelectionOption"
10
+ embeds_multiple :options, klass: "Ecoportal::API::V2::Page::Component::SelectionOption", order_key: :weight
11
+
12
+ def select(value)
13
+ opt = options.find {|opt| opt.value == value}
14
+ sel = selected
15
+ return true if !multiple && opt == sel
16
+ sel.selected = false if !multiple && sel
17
+ opt.selected = true unless !opt
18
+ end
19
+
20
+ def selected
21
+ if multiple
22
+ options.select {|opt| opt.selected}
23
+ else
24
+ options.find {|opt| opt.selected}
25
+ end
26
+ end
27
+
28
+ def value
29
+ if multiple
30
+ selected.map {|opt| opt.value}
31
+ else
32
+ selected&.value
33
+ end
34
+ end
35
+
36
+ # a server bug prevents to add new options to an existing field
37
+ def add_option(name:, value:, pos: NOT_USED, before: NOT_USED, after: NOT_USED)
38
+ opt_doc = Ecoportal::API::V2::Page::Component::SelectionOption.new_doc
39
+ options.upsert!(opt_doc, pos: pos, before: before, after: after) do |option|
40
+ option.name = name
41
+ option.value = value
42
+ if prev = previous_option(option)
43
+ option.weight = prev.weight
44
+ end
45
+ yield(option) if block_given?
46
+ fix_option_weights!
47
+ end
48
+ end
49
+
50
+ def ordered_options
51
+ options.each_with_index.sort_by do |option, index|
52
+ (option.weight >= 9999) ? [index, index] : [option.weight, index]
53
+ end.map(&:first)
54
+ end
55
+
56
+ private
57
+
58
+ def fix_option_weights!
59
+ ordered_options.each_with_index do |option, index|
60
+ option.weight = index
61
+ end
62
+ end
63
+
64
+ def previous_option(value)
65
+ opts = ordered_options
66
+ pos = opts.index(value) - 1
67
+ return if pos < 0
68
+ opts[pos]
69
+ end
70
+
71
+
11
72
  end
12
73
  end
13
74
  end
@@ -4,6 +4,15 @@ module Ecoportal
4
4
  class Page
5
5
  class Component
6
6
  class SelectionOption < Common::Content::DoubleModel
7
+ class << self
8
+ def new_doc
9
+ {
10
+ "id" => new_uuid,
11
+ "weight" => 9999
12
+ }
13
+ end
14
+ end
15
+
7
16
  passkey :id
8
17
  passthrough :patch_ver, :name, :value
9
18
  passthrough :weight, :selected
@@ -13,6 +13,28 @@ module Ecoportal
13
13
 
14
14
  order_matters = true
15
15
 
16
+ def get_by_type(type)
17
+ self.select do |comp|
18
+ comp.type.downcase == type.to_s.strip.downcase
19
+ end
20
+ end
21
+
22
+ def get_by_name(name, type: nil)
23
+ pool = type ? get_by_type(type) : self
24
+
25
+ pool.select do |comp|
26
+ comp.label.to_s.strip.downcase == name.to_s.strip.downcase
27
+ end.first
28
+ end
29
+
30
+ def add(label:, type:)
31
+ fld_doc = Ecoportal::API::V2::Page::Component.new_doc(type: type)
32
+ upsert!(fld_doc) do |fld|
33
+ fld.label = label
34
+ yield(fld) if block_given?
35
+ end
36
+ end
37
+
16
38
  end
17
39
  end
18
40
  end
@@ -3,6 +3,28 @@ module Ecoportal
3
3
  class V2
4
4
  class Page
5
5
  class Section < Common::Content::DoubleModel
6
+ class << self
7
+ def new_doc(split: false)
8
+ {
9
+ "id" => new_uuid,
10
+ "type" => split ? "split" : "content",
11
+ "weight" => 9999
12
+ }.tap do |out|
13
+ component_ids = if split
14
+ {
15
+ "left_component_ids" => [],
16
+ "right_component_ids" => []
17
+ }
18
+ else
19
+ {
20
+ "component_ids" => []
21
+ }
22
+ end
23
+ out.merge!(component_ids)
24
+ end
25
+ end
26
+ end
27
+
6
28
  passkey :id
7
29
  passthrough :patch_ver, :weight, :type
8
30
  passthrough :heading, :left_heading, :right_heading
@@ -22,9 +44,9 @@ module Ecoportal
22
44
  end
23
45
 
24
46
  def components
25
- sec_ids = all_component_ids
26
- root.components.values_at(*sec_ids).select.with_index do |fld, i|
27
- puts "Warning: section #{id} points to missing field #{sec_ids[i]}" if !fld
47
+ fld_ids = all_component_ids
48
+ root.components.values_at(*fld_ids).select.with_index do |fld, i|
49
+ puts "Warning: field #{id} points to missing field #{fld_ids[i]}" if !fld
28
50
  fld && (!block_given? || yield(fld))
29
51
  end
30
52
  end
@@ -7,6 +7,39 @@ module Ecoportal
7
7
 
8
8
  self.klass = :section_class
9
9
 
10
+ def add(name: nil, split: false, pos: NOT_USED, before: NOT_USED, after: NOT_USED)
11
+ sec_doc = Ecoportal::API::V2::Page::Section.new_doc(split: split)
12
+ upsert!(sec_doc, pos: pos, before: before, after: after) do |section|
13
+ section.heading = name
14
+ if prev = previous_section(section)
15
+ section.weight = prev.weight
16
+ end
17
+ yield(section) if block_given?
18
+ #fix_weights! # a server bug prevents to set the weight of existing sections
19
+ end
20
+ end
21
+
22
+ def ordered
23
+ each_with_index.sort_by do |section, index|
24
+ (section.weight >= 9999) ? [index, index] : [section.weight, index]
25
+ end.map(&:first)
26
+ end
27
+
28
+ private
29
+
30
+ def fix_weights!
31
+ ordered.each_with_index do |section, index|
32
+ section.weight = index
33
+ end
34
+ end
35
+
36
+ def previous_section(value)
37
+ secs = ordered
38
+ pos = secs.index(value) - 1
39
+ return if pos < 0
40
+ secs[pos]
41
+ end
42
+
10
43
  end
11
44
  end
12
45
  end
@@ -9,6 +9,19 @@ module Ecoportal
9
9
  passarray :subtags, order_matters: false
10
10
  passarray :section_ids
11
11
  passthrough :can
12
+
13
+ def sections
14
+ sec_ids = section_ids.to_a
15
+ root.sections.values_at(*sec_ids).select.with_index do |sec, i|
16
+ puts "Warning: section #{id} points to missing section #{sec_ids[i]}" if !sec
17
+ fld && (!block_given? || yield(sec))
18
+ end.sort_by {|sec| sec.weight}
19
+ end
20
+
21
+ def attach_section(section)
22
+ section_ids.insert_one(section.id)
23
+ end
24
+
12
25
  end
13
26
  end
14
27
  end
@@ -7,6 +7,12 @@ module Ecoportal
7
7
 
8
8
  self.klass = :stage_class
9
9
 
10
+ def get_by_name(name)
11
+ find do |stage|
12
+ stage.name.strip.downcase == name.to_s.strip.downcase
13
+ end
14
+ end
15
+
10
16
  end
11
17
  end
12
18
  end
@@ -3,9 +3,11 @@ module Ecoportal
3
3
  class V2
4
4
  # @attr_reader client [Common::Client] a `Common::Client` object that holds the configuration of the api connection.
5
5
  class Pages
6
+ STAGE_REX = /stages\/(?<sid>.*)/
6
7
  extend Common::BaseClass
7
8
  include Common::Content::DocHelpers
8
9
 
10
+ class_resolver :stages_class, "Ecoportal::API::V2::Pages::Stages"
9
11
  class_resolver :page_class, "Ecoportal::API::V2::Page"
10
12
 
11
13
  attr_reader :client
@@ -16,14 +18,30 @@ module Ecoportal
16
18
  @client = client
17
19
  end
18
20
 
21
+ # Obtain specific object for pages api requests.
22
+ # @return [V2::Pages::Stages] an instance object ready to make pages api requests.
23
+ def stages
24
+ stages_class.new(client)
25
+ end
26
+
19
27
  # Gets a page via api.
20
- # @note if the request has `success?` the returned `object.result` gives an object with that `Page`.
28
+ # @note
29
+ # - if the request has `success?` the returned `object.result` gives an object with that `Page`.
30
+ # - if it failed to obtain the full page, it returns a `PageStage` with the active stage data.
21
31
  # @param doc [String, Hash, Page] data containing an `id` of the target page.
22
- # @return [Ecoportal::API::V2::Page] the target page.
32
+ # @return [Ecoportal::API::V2::Page, Ecoportal::API::V2::Pages::PageStage] the target page.
23
33
  def get(doc)
24
- id = get_id(doc)
25
- response = client.get("/pages/#{CGI.escape(id)}")
26
- Common::Content::WrappedResponse.new(response, page_class).result
34
+ pid = get_id(doc)
35
+ response = client.get("/pages/#{CGI.escape(pid)}")
36
+ wrapped = Common::Content::WrappedResponse.new(response, page_class)
37
+
38
+ return wrapped.result if wrapped.success?
39
+ if (response.status == 302) && (url = response.body["data"])
40
+ if sid = url_to_stage_id(url)
41
+ return stages.get(pid: pid, sid: sid)
42
+ end
43
+ end
44
+ raise "Could not get page #{pid} - Error #{response.status}: #{response.body}"
27
45
  end
28
46
 
29
47
  # Gets a `new` non-existing page via api with all the ids initialized.
@@ -32,8 +50,10 @@ module Ecoportal
32
50
  def get_new(from)
33
51
  id = get_id(from)
34
52
  response = client.get("/pages/new", params: {template_id: id})
35
- # TODO: make it so the obtained `doc` can be used as `doc`, yet `source_doc` to be empty {}
36
- #Common::Content::WrappedResponse.new(response, page_class).result
53
+ wrapped = Common::Content::WrappedResponse.new(response, page_class)
54
+
55
+ return wrapped.result if wrapped.success?
56
+ raise "Could not get new page from template #{id} - Error #{response.status}: #{response.body}"
37
57
  end
38
58
 
39
59
  # Requests a creation of a page via api.
@@ -55,9 +75,16 @@ module Ecoportal
55
75
  client.patch("/pages/#{CGI.escape(id)}", data: body)
56
76
  end
57
77
 
78
+ private
79
+
80
+ def url_to_stage_id(url)
81
+ (matches = url.match(STAGE_REX)) && matches[:sid]
82
+ end
83
+
58
84
  end
59
85
  end
60
86
  end
61
87
  end
62
88
 
63
89
  require 'ecoportal/api/v2/page'
90
+ require 'ecoportal/api/v2/pages/stages'
@@ -0,0 +1,11 @@
1
+ module Ecoportal
2
+ module API
3
+ class V2
4
+ class Pages
5
+ class PageStage < V2::Page
6
+
7
+ end
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,52 @@
1
+ module Ecoportal
2
+ module API
3
+ class V2
4
+ class Pages
5
+ # This API Integration level has been added due to relative permissions
6
+ # - a **user** with api access may have access to a specific `stage` but not to the full `page`
7
+ #
8
+ # @attr_reader client [Common::Client] a `Common::Client` object that holds the configuration of the api connection.
9
+ class Stages
10
+ extend Common::BaseClass
11
+ include Common::Content::DocHelpers
12
+
13
+ class_resolver :page_stage_class, "Ecoportal::API::V2::Pages::PageStage"
14
+
15
+ attr_reader :client
16
+
17
+ # @param client [Common::Client] a `Common::Client` object that holds the configuration of the api connection.
18
+ # @return [Schemas] an instance object ready to make schema api requests.
19
+ def initialize(client)
20
+ @client = client
21
+ end
22
+
23
+ # Gets a stage via api.
24
+ # @note if the request has `success?` the returned `object.result` gives an object with that `Stage`.
25
+ # @param doc [String, Hash, Stage] data containing an `id` of the target page.
26
+ # @return [Ecoportal::API::V2::Stage, Ecoportal::API::V2::Pages::PageStage] the target stage.
27
+ def get(pid:, sid:)
28
+ pid = get_id(pid)
29
+ response = client.get("/pages/#{CGI.escape(pid)}/stages/#{CGI.escape(sid)}/")
30
+ wrapped = Common::Content::WrappedResponse.new(response, page_stage_class)
31
+
32
+ return wrapped.result if wrapped.success?
33
+ raise "Could not get stage {#{sid}} of page #{pid} - Error #{response.status}: #{response.body}"
34
+ end
35
+
36
+ # Requests to update an existing stage via api.
37
+ # @param doc [Hash, Stage] data that at least contains an `id` (internal or external) of the target stage.
38
+ # @return [Response] an object with the api response.
39
+ def update(doc, pid: nil, sid:)
40
+ body = get_body(doc)
41
+ pid = pid || get_id(doc)
42
+ path = "/pages/#{CGI.escape(pid)}/stages/#{CGI.escape(sid)}/"
43
+ client.patch(path, data: body)
44
+ end
45
+
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
51
+
52
+ require 'ecoportal/api/v2/pages/page_stage'
@@ -1,7 +1,7 @@
1
1
  module Ecoportal
2
2
  module API
3
3
  class V2
4
- VERSION = "0.5.5"
4
+ GEM_VERSION = "0.6.0"
5
5
  end
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ecoportal-api-oozes
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.5
4
+ version: 0.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Oscar Segura
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-03-30 00:00:00.000000000 Z
11
+ date: 2020-07-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -110,22 +110,22 @@ dependencies:
110
110
  name: ecoportal-api
111
111
  requirement: !ruby/object:Gem::Requirement
112
112
  requirements:
113
- - - "~>"
114
- - !ruby/object:Gem::Version
115
- version: '0.5'
116
113
  - - ">="
117
114
  - !ruby/object:Gem::Version
118
- version: 0.5.5
115
+ version: 0.6.0
116
+ - - "~>"
117
+ - !ruby/object:Gem::Version
118
+ version: '0.6'
119
119
  type: :runtime
120
120
  prerelease: false
121
121
  version_requirements: !ruby/object:Gem::Requirement
122
122
  requirements:
123
- - - "~>"
124
- - !ruby/object:Gem::Version
125
- version: '0.5'
126
123
  - - ">="
127
124
  - !ruby/object:Gem::Version
128
- version: 0.5.5
125
+ version: 0.6.0
126
+ - - "~>"
127
+ - !ruby/object:Gem::Version
128
+ version: '0.6'
129
129
  description:
130
130
  email:
131
131
  - rien@ecoportal.co.nz
@@ -140,6 +140,7 @@ files:
140
140
  - ".rubocop.yml"
141
141
  - ".travis.yml"
142
142
  - ".yardopts"
143
+ - CHANGELOG.md
143
144
  - Gemfile
144
145
  - LICENSE
145
146
  - README.md
@@ -189,6 +190,8 @@ files:
189
190
  - lib/ecoportal/api/v2/page/stage.rb
190
191
  - lib/ecoportal/api/v2/page/stages.rb
191
192
  - lib/ecoportal/api/v2/pages.rb
193
+ - lib/ecoportal/api/v2/pages/page_stage.rb
194
+ - lib/ecoportal/api/v2/pages/stages.rb
192
195
  - lib/ecoportal/api/v2/register.rb
193
196
  - lib/ecoportal/api/v2/registers.rb
194
197
  - lib/ecoportal/api/v2/template.rb