ecoportal-api-oozes 0.5.5

Sign up to get free protection for your applications and to get access to all the features.
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'