ecoportal-api-oozes 0.5.5

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.
Files changed (60) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +20 -0
  3. data/.rspec +3 -0
  4. data/.rubocop.yml +55 -0
  5. data/.travis.yml +5 -0
  6. data/.yardopts +10 -0
  7. data/Gemfile +6 -0
  8. data/LICENSE +21 -0
  9. data/README.md +20 -0
  10. data/Rakefile +27 -0
  11. data/bin/console +14 -0
  12. data/bin/setup +8 -0
  13. data/ecoportal-api-oozes.gemspec +31 -0
  14. data/lib/ecoportal/api-oozes.rb +10 -0
  15. data/lib/ecoportal/api/common.rb +18 -0
  16. data/lib/ecoportal/api/common/content.rb +18 -0
  17. data/lib/ecoportal/api/common/content/array_model.rb +287 -0
  18. data/lib/ecoportal/api/common/content/class_helpers.rb +111 -0
  19. data/lib/ecoportal/api/common/content/client.rb +40 -0
  20. data/lib/ecoportal/api/common/content/collection_model.rb +223 -0
  21. data/lib/ecoportal/api/common/content/doc_helpers.rb +67 -0
  22. data/lib/ecoportal/api/common/content/double_model.rb +334 -0
  23. data/lib/ecoportal/api/common/content/hash_diff_patch.rb +162 -0
  24. data/lib/ecoportal/api/common/content/string_digest.rb +22 -0
  25. data/lib/ecoportal/api/common/content/wrapped_response.rb +42 -0
  26. data/lib/ecoportal/api/v2.rb +48 -0
  27. data/lib/ecoportal/api/v2/page.rb +30 -0
  28. data/lib/ecoportal/api/v2/page/component.rb +105 -0
  29. data/lib/ecoportal/api/v2/page/component/action.rb +17 -0
  30. data/lib/ecoportal/api/v2/page/component/action_field.rb +16 -0
  31. data/lib/ecoportal/api/v2/page/component/checklist_field.rb +16 -0
  32. data/lib/ecoportal/api/v2/page/component/checklist_item.rb +15 -0
  33. data/lib/ecoportal/api/v2/page/component/date_field.rb +13 -0
  34. data/lib/ecoportal/api/v2/page/component/file.rb +16 -0
  35. data/lib/ecoportal/api/v2/page/component/files_field.rb +14 -0
  36. data/lib/ecoportal/api/v2/page/component/gauge_field.rb +13 -0
  37. data/lib/ecoportal/api/v2/page/component/geo_field.rb +13 -0
  38. data/lib/ecoportal/api/v2/page/component/image.rb +16 -0
  39. data/lib/ecoportal/api/v2/page/component/images_field.rb +14 -0
  40. data/lib/ecoportal/api/v2/page/component/law_field.rb +12 -0
  41. data/lib/ecoportal/api/v2/page/component/number_field.rb +12 -0
  42. data/lib/ecoportal/api/v2/page/component/people_field.rb +13 -0
  43. data/lib/ecoportal/api/v2/page/component/plain_text_field.rb +13 -0
  44. data/lib/ecoportal/api/v2/page/component/reference_field.rb +12 -0
  45. data/lib/ecoportal/api/v2/page/component/rich_text_field.rb +13 -0
  46. data/lib/ecoportal/api/v2/page/component/selection_field.rb +18 -0
  47. data/lib/ecoportal/api/v2/page/component/selection_option.rb +15 -0
  48. data/lib/ecoportal/api/v2/page/component/signature_field.rb +14 -0
  49. data/lib/ecoportal/api/v2/page/component/tag_field.rb +12 -0
  50. data/lib/ecoportal/api/v2/page/components.rb +20 -0
  51. data/lib/ecoportal/api/v2/page/section.rb +36 -0
  52. data/lib/ecoportal/api/v2/page/sections.rb +14 -0
  53. data/lib/ecoportal/api/v2/page/stage.rb +16 -0
  54. data/lib/ecoportal/api/v2/page/stages.rb +14 -0
  55. data/lib/ecoportal/api/v2/pages.rb +63 -0
  56. data/lib/ecoportal/api/v2/register.rb +36 -0
  57. data/lib/ecoportal/api/v2/registers.rb +35 -0
  58. data/lib/ecoportal/api/v2/template.rb +10 -0
  59. data/lib/ecoportal/api/v2/version.rb +7 -0
  60. metadata +219 -0
@@ -0,0 +1,162 @@
1
+ module Ecoportal
2
+ module API
3
+ module Common
4
+ module Content
5
+ module HashDiffPatch
6
+ ID_KEYS = %w[id]
7
+ META_KEYS = %w[id patch_ver]
8
+ NO_CHANGES = "%not-changed!%"
9
+ extend Content::DocHelpers
10
+
11
+ class << self
12
+ # The `patch data` is built as follows:
13
+ # 1. detect changes that have occurred translate into one `operation` of `OP_TYPE`:
14
+ # * `changed`: meaning that the object has changed (existed and has not been removed)
15
+ # * `delete`: the object has been removed
16
+ # * `new`: the object is new
17
+ # 2. at the level of the target object of the model, the object is opened for change
18
+ # with `id` and `operation` as follows:
19
+ #
20
+ # ```json
21
+ # {
22
+ # "id": "objectID",
23
+ # "operation": "OP_TYPE",
24
+ # "data": {
25
+ # "patch_ver": "prev_patch_ver_+1",
26
+ # "property": "value",
27
+ # "...": "..."
28
+ # }
29
+ # }
30
+ # ```
31
+ # 3. the `data` property holds the specific changes of the object
32
+ # - the `patch_ver` (compulsory) is **incremental** (for data integrity)
33
+ # - the properties that have changed
34
+ # @param a [Hash] current hash model
35
+ # @param b [Hash] previous hash model
36
+ # @return [Hash] a `patch data`
37
+ def patch_diff(a, b)
38
+ case
39
+ when b.is_a?(Hash) && !empty?(b) && empty?(a)
40
+ patch_delete(b)
41
+ when a.is_a?(Hash) && !empty?(a) && empty?(b)
42
+ patch_new(a)
43
+ when a.is_a?(Hash) && b.is_a?(Hash)
44
+ patch_update(a, b)
45
+ when any_array?(a, b)
46
+ patch_data_array(a, b)
47
+ else
48
+ a
49
+ end
50
+ end
51
+
52
+ private
53
+
54
+ def patch_data(a, b = nil)
55
+ {}.tap do |data_hash|
56
+ a.each do |key, a_value|
57
+ b_value = b[key] if b_has_key = b && b.key?(key)
58
+ is_meta_key = META_KEYS.include?(key)
59
+ skip_equals = b_has_key && a_value == b_value
60
+ next if is_meta_key || skip_equals
61
+ data_hash[key] = patch_diff(a_value, b_value)
62
+ data_hash.delete(key) if data_hash[key] == NO_CHANGES
63
+ end
64
+ if (data_hash.keys - META_KEYS).empty?
65
+ return NO_CHANGES
66
+ else
67
+ patch_ver = (b && b["patch_ver"]) || 1
68
+ data_hash["patch_ver"] = patch_ver
69
+ end
70
+ end
71
+ end
72
+
73
+ def patch_delete(b)
74
+ return NO_CHANGES unless b.is_a?(Hash) && id = get_id(b, exception: false)
75
+ {
76
+ "id" => id,
77
+ "operation" => "delete"
78
+ }
79
+ end
80
+
81
+ def patch_new(a)
82
+ return NO_CHANGES unless a.is_a?(Hash) && id = get_id(a, exception: false)
83
+ {
84
+ "id" => id,
85
+ "operation" => "new",
86
+ "data" => patch_data(a)
87
+ }
88
+ end
89
+
90
+ def patch_update(a, b)
91
+ return NO_CHANGES unless a.is_a?(Hash) && id = get_id(a, exception: false)
92
+ {
93
+ "id" => id,
94
+ "operation" => "changed",
95
+ "data" => patch_data(a, b)
96
+ }.tap do |update_hash|
97
+ return nil unless update_hash["data"] != NO_CHANGES
98
+ end
99
+ end
100
+
101
+ def patch_data_array(a, b)
102
+ a ||= []; b ||= []
103
+ if !nested_array?(a, b)
104
+ if a.length == b.length && (a & b).length == b.length
105
+ NO_CHANGES
106
+ else
107
+ a
108
+ end
109
+ else
110
+ a_ids = array_ids(a)
111
+ b_ids = array_ids(b)
112
+
113
+ del_ids = b_ids - a_ids
114
+ oth_ids = b_ids & a_ids
115
+ new_ids = a_ids - b_ids
116
+
117
+ arr_delete = del_ids.map do |id|
118
+ patch_delete(array_id_item(b, id))
119
+ end
120
+
121
+ arr_update = oth_ids.map do |id|
122
+ patch_update(array_id_item(a, id), array_id_item(b, id))
123
+ end
124
+
125
+ arr_new = new_ids.map do |id|
126
+ patch_new(array_id_item(a, id))
127
+ end
128
+
129
+ (arr_delete.concat(arr_update).concat(arr_new)).tap do |patch_array|
130
+ # remove data with no `id`
131
+ patch_array.reject! {|item| !item.is_a?(Hash)}
132
+ end
133
+ end
134
+ end
135
+
136
+ def nested_array?(*arr)
137
+ case
138
+ when arr.length > 1
139
+ arr.any? {|a| nested_array?(a)}
140
+ when arr.length == 1
141
+ arr = arr.first
142
+ arr.any? {|item| item.is_a?(Hash)}
143
+ else
144
+ false
145
+ end
146
+ end
147
+
148
+ def any_array?(a, b)
149
+ [a, b].any? {|item| item.is_a?(Array)}
150
+ end
151
+
152
+ def empty?(a)
153
+ bool = !a
154
+ bool ||= a.respond_to?(:empty?) && a.empty?
155
+ end
156
+
157
+ end
158
+ end
159
+ end
160
+ end
161
+ end
162
+ end
@@ -0,0 +1,22 @@
1
+ require 'digest'
2
+
3
+ module Ecoportal
4
+ module API
5
+ module Common
6
+ module Content
7
+ module StringDigest
8
+ MAX_HASH_LABEL = 64
9
+
10
+ # Calculates the Hash of the field based on label
11
+ 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);
16
+ end
17
+
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,42 @@
1
+ module Ecoportal
2
+ module API
3
+ module Common
4
+ module Content
5
+ class WrappedResponse < Common::WrappedResponse
6
+ include Enumerable
7
+
8
+ attr_reader :response, :result
9
+
10
+ def initialize(response, klass, key: nil)
11
+ @response = response
12
+ @klass = klass
13
+ @key = key
14
+
15
+ if @response.success?
16
+ @result =
17
+ if data.is_a?(Array)
18
+ data.map do |doc|
19
+ @klass.new(doc)
20
+ end
21
+ else
22
+ @klass.new(data)
23
+ end
24
+ end
25
+ end
26
+
27
+ def data
28
+ return @data if instance_variable_defined?(:@data)
29
+ @data = (response.body || {})["data"]
30
+ @data = @data[key] if @key && @data
31
+ @data
32
+ end
33
+
34
+ def body
35
+ data.to_s
36
+ end
37
+
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,48 @@
1
+ module Ecoportal
2
+ module API
3
+ # @attr_reader client [Common::Client] a `Common::Client` object that holds the configuration of the api connection.
4
+ # @attr_reader logger [Logger] the logger.
5
+ class V2
6
+ extend Common::BaseClass
7
+ include Common::Logging
8
+
9
+ VERSION = "v2"
10
+
11
+ class_resolver :registers_class, "Ecoportal::API::V2::Registers"
12
+ class_resolver :pages_class, "Ecoportal::API::V2::Pages"
13
+
14
+ attr_reader :client, :logger
15
+
16
+ # Creates an `V2` object to scope version specific api requests.
17
+ # @param api_key [String] the key version to stablish the api connection.
18
+ # @param host [String] api server domain.
19
+ # @param logger [Logger] an object with `Logger` interface to generate logs.
20
+ def initialize(api_key, host: "live.ecoportal.com", logger: default_logger)
21
+ @logger = logger
22
+ @client = Common::Content::Client.new(
23
+ api_key: api_key,
24
+ host: host,
25
+ version: self.class::VERSION,
26
+ logger: @logger
27
+ )
28
+ end
29
+
30
+ # Obtain specific object for schema api requests.
31
+ # @return [Registers] an instance object ready to make registers api requests.
32
+ def registers
33
+ registers_class.new(client)
34
+ end
35
+
36
+ # Obtain specific object for pages api requests.
37
+ # @return [Pages] an instance object ready to make pages api requests.
38
+ def pages
39
+ pages_class.new(client)
40
+ end
41
+
42
+ end
43
+ end
44
+ end
45
+
46
+ require 'ecoportal/api/v2/registers'
47
+ require 'ecoportal/api/v2/pages'
48
+ #require 'ecoportal/api/v2/stages'
@@ -0,0 +1,30 @@
1
+ module Ecoportal
2
+ module API
3
+ class V2
4
+ class Page < Common::Content::DoubleModel
5
+ passkey :id
6
+ passthrough :patch_ver
7
+ passthrough :name, :template_id
8
+ passarray :base_tags, :tags, order_matters: false
9
+ passthrough :time_zone
10
+ passdate :created_at, :updated_at, read_only: true
11
+ passthrough :can
12
+
13
+ class_resolver :components_class, "Ecoportal::API::V2::Page::Components"
14
+ class_resolver :sections_class, "Ecoportal::API::V2::Page::Sections"
15
+ class_resolver :stages_class, "Ecoportal::API::V2::Page::Stages"
16
+
17
+ embeds_one :components, multiple: true, klass: :components_class
18
+ embeds_one :sections, multiple: true, klass: :sections_class
19
+ embeds_one :stages, multiple: true, klass: :stages_class
20
+ end
21
+ end
22
+ end
23
+ end
24
+
25
+ require 'ecoportal/api/v2/page/component'
26
+ require 'ecoportal/api/v2/page/components'
27
+ require 'ecoportal/api/v2/page/section'
28
+ require 'ecoportal/api/v2/page/sections'
29
+ require 'ecoportal/api/v2/page/stage'
30
+ require 'ecoportal/api/v2/page/stages'
@@ -0,0 +1,105 @@
1
+ module Ecoportal
2
+ module API
3
+ class V2
4
+ class Page
5
+ class Component < Common::Content::DoubleModel
6
+ extend Ecoportal::API::Common::Content::StringDigest
7
+
8
+ class_resolver :tag_field_class, "Ecoportal::API::V2::Page::Component::TagField"
9
+ class_resolver :geo_field_class, "Ecoportal::API::V2::Page::Component::GeoField"
10
+ class_resolver :selection_field_class, "Ecoportal::API::V2::Page::Component::SelectionField"
11
+ class_resolver :date_field_class, "Ecoportal::API::V2::Page::Component::DateField"
12
+ class_resolver :number_field_class, "Ecoportal::API::V2::Page::Component::NumberField"
13
+ class_resolver :gauge_field_class, "Ecoportal::API::V2::Page::Component::GaugeField"
14
+ class_resolver :plain_text_field_class, "Ecoportal::API::V2::Page::Component::PlainTextField"
15
+ class_resolver :rich_text_field_class, "Ecoportal::API::V2::Page::Component::RichTextField"
16
+ class_resolver :people_field_class, "Ecoportal::API::V2::Page::Component::PeopleField"
17
+ class_resolver :checklist_field_class, "Ecoportal::API::V2::Page::Component::ChecklistField"
18
+ class_resolver :action_field_class, "Ecoportal::API::V2::Page::Component::ActionField"
19
+ class_resolver :files_field_class, "Ecoportal::API::V2::Page::Component::FilesField"
20
+ class_resolver :images_field_class, "Ecoportal::API::V2::Page::Component::ImagesField"
21
+ class_resolver :signature_field_class, "Ecoportal::API::V2::Page::Component::SignatureField"
22
+ class_resolver :reference_field_class, "Ecoportal::API::V2::Page::Component::ReferenceField"
23
+ class_resolver :law_field_class, "Ecoportal::API::V2::Page::Component::LawField"
24
+
25
+ class << self
26
+ def get_class(doc)
27
+ if doc.is_a?(Hash)
28
+ case doc["type"]
29
+ when "tag_field"
30
+ tag_field_class
31
+ when "geo"
32
+ geo_field_class
33
+ when "select"
34
+ selection_field_class
35
+ when "date"
36
+ date_field_class
37
+ when "number"
38
+ number_field_class
39
+ when "gauge"
40
+ gauge_field_class
41
+ when "plain_text"
42
+ plain_text_field_class
43
+ when "rich_text"
44
+ rich_text_field_class
45
+ when "people"
46
+ people_field_class
47
+ when "checklist"
48
+ checklist_field_class
49
+ when "page_action"
50
+ action_field_class
51
+ when "file"
52
+ files_field_class
53
+ when "image_gallery"
54
+ images_field_class
55
+ when "signature"
56
+ signature_field_class
57
+ when "cross_reference"
58
+ reference_field_class
59
+ when "law"
60
+ law_field_class
61
+ else
62
+ self
63
+ end
64
+ end
65
+ end
66
+ end
67
+
68
+ passkey :id
69
+ passthrough :patch_ver, :undeletable
70
+ passthrough :type, :label, :tooltip, :global_binding
71
+ passthrough :hidden, :accent, :deindex
72
+ passthrough :hide_view, :hidden_on_reports, :hidden_on_mobile
73
+
74
+ def ref
75
+ if digest = self.class.hash_label(label)
76
+ [type, digest].join(".")
77
+ end
78
+ end
79
+
80
+ def section
81
+ root.sections.find {|sec| sec.component?(id)}
82
+ end
83
+
84
+ end
85
+ end
86
+ end
87
+ end
88
+ end
89
+
90
+ require 'ecoportal/api/v2/page/component/tag_field'
91
+ require 'ecoportal/api/v2/page/component/geo_field'
92
+ require 'ecoportal/api/v2/page/component/selection_field'
93
+ require 'ecoportal/api/v2/page/component/date_field'
94
+ require 'ecoportal/api/v2/page/component/number_field'
95
+ require 'ecoportal/api/v2/page/component/gauge_field'
96
+ require 'ecoportal/api/v2/page/component/plain_text_field'
97
+ require 'ecoportal/api/v2/page/component/rich_text_field'
98
+ require 'ecoportal/api/v2/page/component/people_field'
99
+ require 'ecoportal/api/v2/page/component/checklist_field'
100
+ require 'ecoportal/api/v2/page/component/action_field'
101
+ require 'ecoportal/api/v2/page/component/files_field'
102
+ require 'ecoportal/api/v2/page/component/images_field'
103
+ require 'ecoportal/api/v2/page/component/signature_field'
104
+ require 'ecoportal/api/v2/page/component/reference_field'
105
+ require 'ecoportal/api/v2/page/component/law_field'
@@ -0,0 +1,17 @@
1
+ module Ecoportal
2
+ module API
3
+ class V2
4
+ class Page
5
+ class Component
6
+ class Action < Common::Content::DoubleModel
7
+ passkey :id
8
+ passthrough :patch_ver, :name
9
+ passthrough :weight, :complete, :overdue, :other_information
10
+ passdate :due_date, :created_at #, :completed_at
11
+ passthrough :created_by, :assigned_person_member_id
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,16 @@
1
+ module Ecoportal
2
+ module API
3
+ class V2
4
+ class Page
5
+ class Component
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
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
15
+
16
+ require 'ecoportal/api/v2/page/component/action'