eco-helpers 3.2.2 → 3.2.4

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 (41) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +1 -1
  3. data/CHANGELOG.md +24 -1
  4. data/eco-helpers.gemspec +3 -3
  5. data/lib/eco/api/common/loaders/config/workflow/mailer.rb +1 -0
  6. data/lib/eco/api/common/people/person_entry.rb +1 -1
  7. data/lib/eco/api/common/people/person_parser.rb +1 -0
  8. data/lib/eco/api/organization/tag_tree.rb +11 -4
  9. data/lib/eco/api/usecases/default/locations/tagtree_upload_case.rb +20 -2
  10. data/lib/eco/api/usecases/graphql/helpers/location/base/tree_tracking.rb +14 -7
  11. data/lib/eco/api/usecases/graphql/helpers/location/base.rb +1 -1
  12. data/lib/eco/api/usecases/graphql/helpers/location/command/diff/as_update.rb +0 -1
  13. data/lib/eco/api/usecases/graphql/helpers/location/command/diffs/stages/diff_sortable/for_archive.rb +0 -1
  14. data/lib/eco/api/usecases/graphql/helpers/location/command/diffs/stages/diff_sortable/for_unarchive.rb +4 -2
  15. data/lib/eco/api/usecases/graphql/helpers/location/command/diffs/stages/diff_sortable.rb +1 -0
  16. data/lib/eco/api/usecases/graphql/helpers/location/command/diffs/stages/sortable/relation_safe_sort.rb +4 -0
  17. data/lib/eco/api/usecases/graphql/helpers/location/command/diffs/stages/sortable.rb +6 -1
  18. data/lib/eco/api/usecases/graphql/helpers/location/command/end_points/optimizations.rb +79 -0
  19. data/lib/eco/api/usecases/graphql/helpers/location/command/end_points.rb +101 -0
  20. data/lib/eco/api/usecases/graphql/helpers/location/command/input_unit_response.rb +69 -0
  21. data/lib/eco/api/usecases/graphql/helpers/location/command/result.rb +11 -10
  22. data/lib/eco/api/usecases/graphql/helpers/location/command/results.rb +126 -64
  23. data/lib/eco/api/usecases/graphql/helpers/location/command.rb +24 -30
  24. data/lib/eco/api/usecases/graphql/samples/location/command/dsl.rb +203 -38
  25. data/lib/eco/api/usecases/graphql/samples/location/command/results.rb +46 -14
  26. data/lib/eco/api/usecases/graphql/samples/location/command/service/tree_update.rb +0 -51
  27. data/lib/eco/api/usecases/graphql/samples/location/command/track_changed_ids.rb +6 -14
  28. data/lib/eco/api/usecases/graphql/samples/location/command.rb +1 -1
  29. data/lib/eco/api/usecases/graphql/samples/location/service/tree_diff/convertible/inputable.rb +4 -1
  30. data/lib/eco/api/usecases/graphql/samples/location/service/tree_diff.rb +6 -0
  31. data/lib/eco/api/usecases/graphql/samples/location/service/tree_to_list/converter/input.rb +1 -0
  32. data/lib/eco/api/usecases/lib/error_handling.rb +1 -1
  33. data/lib/eco/api/usecases/ooze_samples/helpers/creatable.rb +1 -0
  34. data/lib/eco/api/usecases/ooze_samples/helpers/rescuable.rb +1 -0
  35. data/lib/eco/data/hashes/array_diff.rb +14 -4
  36. data/lib/eco/data/locations/node_base/csv_convert.rb +9 -1
  37. data/lib/eco/data/locations/node_diff/nodes_diff/clustered_treeify.rb +1 -0
  38. data/lib/eco/data/locations/node_diff/nodes_diff.rb +6 -0
  39. data/lib/eco/version.rb +1 -1
  40. metadata +9 -7
  41. data/lib/eco/api/usecases/graphql/helpers/location/command/optimizations.rb +0 -84
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 415f7627b23706adc59420467cd7491f5990c267109a11f9128fa8dac908631c
4
- data.tar.gz: 8f04152b0e476c656c83fe752b091e83e042a322d0cdbb69e26bb8650c812f07
3
+ metadata.gz: ec05b98fd01a73712e5db28ef750583f57d96438f30a2e4e58fc531d007802e1
4
+ data.tar.gz: c1071fd1909830cfbb72838f9051234f9268a5bafa6e6b970a80790c05ef1ad5
5
5
  SHA512:
6
- metadata.gz: 9cb01334ae6ae73d528f5841c568ee3f13305cabf5051d5ef2bee3775d9dac5d6618a16436f62fa28ff9c06ba628ca1c04897e528ba3a367db8a8805affc4f44
7
- data.tar.gz: 6e9fe1d5c9cbda796692302ad551702c446ee73a44bdd83cb3e04a59de0ef3474e878d071d6977cd68fc7f0d19256a334a2c014c62ec79b63c918ad5d6463c48
6
+ metadata.gz: 779aa495731d5e3abcb145c983c6a8271e9d4a41fb939f4a63dda4735b08b0dfc7fd2df1fcafbfade6e65651fa3af24c27b94cf18ea6977d752ef8c36abbb1da
7
+ data.tar.gz: edc3abd001e262f4ed9bab3867bcd9e8f4d9de108ae58b8a16f581bf054e546908c175d1bd24f8541977f65b44972226cae0b1b58ef20ad112cb2b90af591c1c
data/.rubocop.yml CHANGED
@@ -1,5 +1,5 @@
1
1
  AllCops:
2
- TargetRubyVersion: 3.2.2
2
+ TargetRubyVersion: 3.2
3
3
  Exclude:
4
4
  - 'config/routes.rb'
5
5
  NewCops: enable
data/CHANGELOG.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file.
4
4
 
5
- ## [3.3.1] - 2025-06-xx
5
+ ## [3.2.5] - 2025-08-xx
6
6
 
7
7
  ### Added
8
8
 
@@ -10,6 +10,29 @@ All notable changes to this project will be documented in this file.
10
10
 
11
11
  ### Fixed
12
12
 
13
+ ## [3.2.4] - 2025-08-26
14
+
15
+ ### Fixed
16
+
17
+ - upgraded `ecoportal-api-graphql` **gem**
18
+ - **DRAFTING**: made it so we don't fetch structure but when needed.
19
+ - This adjustment significantly mitigates performance downfall.
20
+
21
+ ## [3.2.3] - 2025-08-21
22
+
23
+ ### Added
24
+
25
+ - `Person#phone_number`
26
+
27
+ ### Changed
28
+
29
+ - upgraded dependencies
30
+ - `ecoportal-api` gem
31
+
32
+ ### Fixed
33
+
34
+ - Switched to use DRAFTs on RS updates
35
+
13
36
  ## [3.2.2] - 2025-06-11
14
37
 
15
38
  ### Added
data/eco-helpers.gemspec CHANGED
@@ -20,7 +20,7 @@ Gem::Specification.new do |spec|
20
20
  spec.required_ruby_version = '>= 3.2.2'
21
21
 
22
22
  spec.files = `git ls-files -z`.split("\x0").reject do |f|
23
- f.match(%r{^(test|spec|features)/})
23
+ f.match(/^(test|spec|features)\//)
24
24
  end
25
25
 
26
26
  #spec.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
@@ -41,8 +41,8 @@ Gem::Specification.new do |spec|
41
41
  spec.add_dependency 'bcrypt_pbkdf', '~> 1.0'
42
42
  spec.add_dependency 'docx', '>= 0.8.0', '< 0.9'
43
43
  spec.add_dependency 'dotenv', '~> 3'
44
- spec.add_dependency 'ecoportal-api', '~> 0.10', '>= 0.10.11'
45
- spec.add_dependency 'ecoportal-api-graphql', '~> 1.3', '>= 1.3.1'
44
+ spec.add_dependency 'ecoportal-api', '~> 0.10', '>= 0.10.14'
45
+ spec.add_dependency 'ecoportal-api-graphql', '~> 1.3', '>= 1.3.3'
46
46
  spec.add_dependency 'ecoportal-api-v2', '~> 3.3', '>= 3.3.1'
47
47
  spec.add_dependency 'ed25519', '~> 1.2'
48
48
  spec.add_dependency 'fast_excel', '>= 0.5.0', '< 0.6'
@@ -75,6 +75,7 @@ class Eco::API::Common::Loaders::Workflow::Mailer < Eco::API::Common::Loaders::W
75
75
  host(io).downcase.start_with?('live.')
76
76
  end
77
77
 
78
+ # @note this initiates a connection to the API (undesired)
78
79
  def host(io)
79
80
  io.session.api.client.host
80
81
  end
@@ -9,7 +9,7 @@ module Eco
9
9
  BOOLEAN_ATTRS = %w[
10
10
  freemium accept_eula archived
11
11
  ].freeze
12
- MULTI_ATTRS = %w[
12
+ MULTI_ATTRS = %w[
13
13
  policy_group_ids filter_tags login_provider_ids starred_ids
14
14
  ].freeze
15
15
  NUMERIC_ATTRS = %w[
@@ -17,6 +17,7 @@ module Eco
17
17
 
18
18
  CORE_ATTRS = %w[
19
19
  id external_id email name
20
+ phone_number
20
21
  supervisor_id filter_tags
21
22
  archived
22
23
  contractor_organization_id
@@ -68,7 +68,13 @@ module Eco
68
68
  @path.push(self.id) unless top?
69
69
 
70
70
  @nodes = @raw_nodes.map.with_index do |cnode, idx|
71
- self.class.new(cnode, depth: depth + 1, path: @path.dup, parent: self, _weight: idx)
71
+ self.class.new(
72
+ cnode,
73
+ depth: depth + 1,
74
+ path: @path.dup,
75
+ parent: self,
76
+ _weight: idx
77
+ )
72
78
  end
73
79
 
74
80
  init_hashes
@@ -199,8 +205,9 @@ module Eco
199
205
  # @param max_depth [Boolean] up to what level `depth` nodes should be included.
200
206
  # @return [Array[Hash]] where `Hash` is a `node` (i.e. `{"tag" => TAG, "nodes": Array[Hash]}`)
201
207
  def as_json( # rubocop:disable Metrics/AbcSize
202
- include_children: true, include_archived: true,
203
- max_depth: total_depth,
208
+ include_children: true,
209
+ include_archived: true,
210
+ max_depth: total_depth,
204
211
  &block
205
212
  )
206
213
  max_depth ||= total_depth
@@ -230,7 +237,7 @@ module Eco
230
237
  depth + 1
231
238
  ]
232
239
  node_json = self.class::HEADER.zip(values).to_h
233
- node_json["nodes"] = children_json if include_children
240
+ node_json['nodes'] = children_json if include_children
234
241
  node_json = yield(node_json, self) if block_given?
235
242
  node_json
236
243
  end
@@ -1,7 +1,7 @@
1
1
  class Eco::API::UseCases::Default::Locations::TagtreeUpload < Eco::API::UseCases::GraphQL::Samples::Location::Command
2
2
  require_relative 'cli/tagtree_upload_cli'
3
3
 
4
- name "tagtree-upload"
4
+ name 'tagtree-upload'
5
5
  type :other
6
6
 
7
7
  COMMANDS_PER_PAGE = 45
@@ -11,10 +11,28 @@ class Eco::API::UseCases::Default::Locations::TagtreeUpload < Eco::API::UseCases
11
11
  false
12
12
  end
13
13
 
14
+ def compare_live_with_file?
15
+ true
16
+ end
17
+
18
+ # # With given the commands, it generates the input of the endpoint mutation.
19
+ # # @param commands [Array<Hash>]
20
+ # def input(commands, force_continue: force_continue?)
21
+ # {
22
+ # clientMutationId: '',
23
+ # id: target_structure_id,
24
+ # force: force_continue,
25
+ # commands: commands
26
+ # }
27
+ # end
28
+
14
29
  # We only define the `:insert` stage
15
30
  def inputs(force_continue: force_continue?)
16
31
  {}.tap do |stages|
17
- stages[:insert] = input(insert_commands, force_continue: force_continue)
32
+ stages[:insert] = input(
33
+ insert_commands,
34
+ force_continue: force_continue
35
+ )
18
36
  end.each do |stage, input|
19
37
  yield(input, stage) if block_given?
20
38
  end
@@ -29,16 +29,20 @@ module Eco::API::UseCases::GraphQL::Helpers::Location
29
29
  # At any moment we want to know how the live tree is
30
30
  # @note it also does a backup
31
31
  # @return [Eco::API::Organization::TagTree] the latest tree (`current_tree`)
32
- def track_current_tree(tree)
32
+ def track_current_tree(tree) # rubocop:disable Metrics/AbcSize
33
+ return unless track_current_tree?
33
34
  return if simulate?
34
35
  return if tree.nil?
35
36
 
36
- latest_tree = tree if tree.is_a?(Eco::API::Organization::TagTree)
37
- if tree.respond_to?(:treeify) && track_current_tree?
37
+ tree_id = current_tree&.id
38
+ tree_name = current_tree&.name
39
+ tree_id = tree.id if tree.respond_to?(:id)
40
+ tree_name = tree.name if tree.respond_to?(:name)
41
+ latest_tree = tree if tree.is_a?(Eco::API::Organization::TagTree)
42
+
43
+ if tree.respond_to?(:treeify)
38
44
  latest_tree ||= Eco::API::Organization::TagTree.new(
39
- tree.treeify,
40
- id: tree.id,
41
- name: tree.name
45
+ tree.treeify
42
46
  )
43
47
  end
44
48
 
@@ -46,6 +50,9 @@ module Eco::API::UseCases::GraphQL::Helpers::Location
46
50
  next unless latest_tree.is_a?(Eco::API::Organization::TagTree)
47
51
  next if latest_tree.empty?
48
52
 
53
+ latest_tree.id = tree_id if latest_tree.id.nil?
54
+ latest_tree.name = tree_name if latest_tree.name.nil?
55
+
49
56
  # a backup happens:
50
57
  self.current_tree = latest_tree
51
58
  end
@@ -53,7 +60,7 @@ module Eco::API::UseCases::GraphQL::Helpers::Location
53
60
 
54
61
  # @param tree [Eco::API::Organization::TagTree, Hash, Array]
55
62
  # @return [Boolean] whether or not the backup was created
56
- def backup_tree(tree = current_tree || live_tree)
63
+ def backup_tree(tree = current_tree || live_tree) # rubocop:disable Naming/PredicateMethod
57
64
  return false if simulate?
58
65
  case tree
59
66
  when Eco::API::Organization::TagTree
@@ -22,7 +22,7 @@ module Eco::API::UseCases::GraphQL::Helpers::Location
22
22
  log(:warn) { msg }
23
23
 
24
24
  # a backup happens:
25
- return nil unless (self.current_tree = session_live_tree)
25
+ return unless (self.current_tree = session_live_tree)
26
26
 
27
27
  @target_structure_id = current_tree.id
28
28
  end
@@ -18,7 +18,6 @@ class Eco::API::UseCases::GraphQL::Helpers::Location::Command::Diff
18
18
  class_ids = class_ids.compact.map {|val| val.split('|')}.flatten.uniq
19
19
  h['classificationIds'] = class_ids
20
20
  end
21
-
22
21
  if archive? || insert?
23
22
  # We assume archives do not have `move` nor update `id` or `name`
24
23
  h['nodeId'] = node_id || node_id_prev
@@ -2,7 +2,6 @@ class Eco::API::UseCases::GraphQL::Helpers::Location::Command::Diffs
2
2
  module Stages
3
3
  module DiffSortable
4
4
  module ForArchive
5
-
6
5
  private
7
6
 
8
7
  def only_first_ancestor_in_chains(raw_diffs)
@@ -2,9 +2,11 @@ class Eco::API::UseCases::GraphQL::Helpers::Location::Command::Diffs
2
2
  module Stages
3
3
  module DiffSortable
4
4
  module ForUnarchive
5
- # we require the original tree to be able to track what ancestors
5
+ # We require the original tree to be able to track what ancestors
6
6
  # should be unarchived, with the aim of unarchiving a node that
7
- # is target of update (i.e. revive and move somewhere else)
7
+ # is target of update (i.e. revive and move somewhere else).
8
+ # @note it is **IMPORTANT** to note, that only the original tree
9
+ # is required. NO need to track the intermediate tree.
8
10
  def original_tree
9
11
  defined?(super)? super : @original_tree
10
12
  end
@@ -7,6 +7,7 @@ class Eco::API::UseCases::GraphQL::Helpers::Location::Command::Diffs
7
7
  class << self
8
8
  def included(base)
9
9
  super
10
+
10
11
  base.send(:include, Sortable)
11
12
  end
12
13
  end
@@ -33,11 +33,13 @@ class Eco::API::UseCases::GraphQL::Helpers::Location::Command::Diffs
33
33
  pending = parents_hash.dup
34
34
  treeify = proc do |item|
35
35
  next item unless (children = pending.delete(item))
36
+
36
37
  {item => children.map {|child| treeify.call(child)}}
37
38
  end
38
39
 
39
40
  sorted_tree = top_parents.each_with_object(unpaired) do |item, tree|
40
41
  next unless pending.key?(item)
42
+
41
43
  tree << treeify.call(item)
42
44
  end
43
45
 
@@ -87,10 +89,12 @@ class Eco::API::UseCases::GraphQL::Helpers::Location::Command::Diffs
87
89
  def paired_related_nodes
88
90
  paired_combinations.each_with_object([]) do |pair, chained|
89
91
  next if (result = compare_two(*pair)).zero?
92
+
90
93
  chained << (result.negative?? pair : pair.reverse)
91
94
  end
92
95
  end
93
96
 
97
+ # @note non optimal... that's why `clusterer_class` would be used instead.
94
98
  def paired_combinations
95
99
  list.combination(2).to_a
96
100
  end
@@ -9,6 +9,7 @@ class Eco::API::UseCases::GraphQL::Helpers::Location::Command::Diffs
9
9
  class << self
10
10
  def included(base)
11
11
  super
12
+
12
13
  base.extend(Stages)
13
14
  end
14
15
  end
@@ -16,7 +17,11 @@ class Eco::API::UseCases::GraphQL::Helpers::Location::Command::Diffs
16
17
  private
17
18
 
18
19
  def diffs_sort(list, cluster_mode: nil, &block)
19
- RelationSafeSort.new(list, cluster_mode: cluster_mode, &block).sort
20
+ RelationSafeSort.new(
21
+ list,
22
+ cluster_mode: cluster_mode,
23
+ &block
24
+ ).sort
20
25
  end
21
26
 
22
27
  # @note As can't update archived nodes, it happens before :id update (:prev),
@@ -0,0 +1,79 @@
1
+ module Eco::API::UseCases::GraphQL::Helpers::Location
2
+ module Command::EndPoints
3
+ module Optimizations
4
+ DEFAULT_COMMANDS_PER_PAGE = 45
5
+
6
+ # Prevents each request from timing out
7
+ def commands_per_page
8
+ if self.class.const_defined?(:COMMANDS_PER_PAGE)
9
+ self.class::COMMANDS_PER_PAGE
10
+ else
11
+ DEFAULT_COMMANDS_PER_PAGE
12
+ end
13
+ end
14
+
15
+ # Whether to stop or continue on command fail
16
+ def force_continue?
17
+ false
18
+ end
19
+
20
+ # Commands payload without querying Structure
21
+ # @note this servces the purpose of optimizing/speeding up the requests.
22
+ def commands_payload_without_structure_block
23
+ proc {
24
+ clientMutationId
25
+ ok
26
+ errors { # rubocop:disable Style/BlockDelimiters
27
+ details
28
+ fullMessages
29
+ messages
30
+ }
31
+ draft { # rubocop:disable Style/BlockDelimiters
32
+ ___Ecoportal__API__GraphQL__Fragment__LocationDraft
33
+ }
34
+ }
35
+ end
36
+
37
+ def create_payload_without_structure_block
38
+ proc {
39
+ # work-around:
40
+ clientMutationId
41
+ errors { # rubocop:disable Style/BlockDelimiters
42
+ details
43
+ fullMessages
44
+ messages
45
+ }
46
+ draft { # rubocop:disable Style/BlockDelimiters
47
+ ___Ecoportal__API__GraphQL__Fragment__LocationDraft
48
+ }
49
+ }
50
+ end
51
+
52
+ def publish_payload_without_structure_block
53
+ proc {
54
+ clientMutationId
55
+ ok
56
+ error { # rubocop:disable Style/BlockDelimiters
57
+ ___Ecoportal__API__GraphQL__Fragment__LocationsError
58
+ }
59
+ errors { # rubocop:disable Style/BlockDelimiters
60
+ details
61
+ fullMessages
62
+ messages
63
+ }
64
+ results { # rubocop:disable Style/BlockDelimiters
65
+ ok
66
+ command { # rubocop:disable Style/BlockDelimiters
67
+ id
68
+ state
69
+ __typename
70
+ }
71
+ error { # rubocop:disable Style/BlockDelimiters
72
+ ___Ecoportal__API__GraphQL__Fragment__LocationsError
73
+ }
74
+ }
75
+ }
76
+ end
77
+ end
78
+ end
79
+ end
@@ -0,0 +1,101 @@
1
+ module Eco::API::UseCases::GraphQL::Helpers::Location
2
+ module Command::EndPoints
3
+ include Eco::Language::AuxiliarLogger
4
+ include Eco::API::UseCases::GraphQL::Helpers::Location::Base
5
+
6
+ require_relative 'end_points/optimizations'
7
+
8
+ include Optimizations
9
+
10
+ def fetch_draft(
11
+ draft_id,
12
+ structure_id:,
13
+ &block
14
+ )
15
+ log(:info) { "Going to fetch draft #{draft_id} (for #{structure_id})..." }
16
+
17
+ graphql.currentOrganization.locationDraftById(
18
+ id: draft_id,
19
+ structureId: structure_id,
20
+ &block
21
+ )
22
+ end
23
+
24
+ def create_draft(
25
+ structure_id,
26
+ name: Time.now.iso8601,
27
+ notes: ''
28
+ )
29
+ log(:info) { "Going to create draft (for #{structure_id})..." }
30
+
31
+ graphql.locationStructure.draft.create(
32
+ input: {
33
+ structureId: structure_id,
34
+ name: name,
35
+ notes: notes
36
+ }
37
+ ).tap do |payload|
38
+ unless payload.error?
39
+ log(:info) { "Created draft '#{payload.draft&.id}' (for #{structure_id})" }
40
+ next
41
+ end
42
+
43
+ msg = "Could not create draft for #{structure_id}:\n"
44
+ msg << JSON.pretty_generate(payload.error_doc)
45
+
46
+ raise StandardError, msg
47
+ end
48
+ end
49
+
50
+ def delete_draft(draft_id)
51
+ graphql.locationStructure.draft.delete(
52
+ input: {
53
+ id: draft_id
54
+ }
55
+ ).tap do |payload|
56
+ unless payload.error?
57
+ log(:info) { "Deleted draft #{draft_id}" }
58
+ next
59
+ end
60
+
61
+ msg = "Could not delete draft #{draft_id}:\n"
62
+ msg << JSON.pretty_generate(payload.error_doc)
63
+
64
+ raise StandardError, msg
65
+ end
66
+ end
67
+
68
+ def publish_draft(
69
+ draft_id,
70
+ preview: false,
71
+ force: false
72
+ )
73
+ log(:info) { "Going to publish draft #{draft_id}..." }
74
+
75
+ graphql.locationStructure.draft.publish(
76
+ input: {
77
+ id: draft_id,
78
+ preview: preview,
79
+ force: force
80
+ }
81
+ ).tap do |payload|
82
+ unless payload.error?
83
+ log(:info) { "Published draft #{draft_id}" }
84
+ next
85
+ end
86
+
87
+ msg = "Could not publish draft #{draft_id}:\n"
88
+ msg << JSON.pretty_generate(payload.error_doc)
89
+
90
+ raise StandardError, msg
91
+ end
92
+ end
93
+
94
+ def add_commands(input, &block)
95
+ graphql.locationStructure.draft.addCommands(
96
+ input: input,
97
+ &block
98
+ )
99
+ end
100
+ end
101
+ end
@@ -0,0 +1,69 @@
1
+ module Eco::API::UseCases::GraphQL::Helpers::Location::Command
2
+ class InputUnitResponse
3
+ attr_reader :input, :response
4
+
5
+ def initialize(input, response)
6
+ @input = input
7
+ @response = response
8
+ end
9
+
10
+ def draft
11
+ response&.draft
12
+ end
13
+
14
+ def structure
15
+ draft&.structure
16
+ end
17
+
18
+ def commands
19
+ input[:commands]
20
+ end
21
+
22
+ # brief summary of the error
23
+ def error_doc
24
+ if (err_doc = response&.error_doc)
25
+ return err_doc
26
+ end
27
+
28
+ conflictingIds if conflictingIds?
29
+ end
30
+
31
+ def error?
32
+ return false if response.nil?
33
+ return true if conflictingIds?
34
+
35
+ response.error? # draft might have previous, but we will stop anyway!
36
+ end
37
+ alias_method :errors?, :error?
38
+
39
+ def ok?
40
+ !errors?
41
+ end
42
+
43
+ def conflictingIds? # rubocop:disable Naming/MethodName
44
+ conflictingIds.any?
45
+ end
46
+
47
+ def conflictingIds # rubocop:disable Naming/MethodName
48
+ draft_conflicting_ids & target_ids
49
+ end
50
+
51
+ private
52
+
53
+ def draft_conflicting_ids
54
+ return [] unless draft
55
+
56
+ draft.conflictingIds || []
57
+ end
58
+
59
+ def target_ids
60
+ return [] unless commands.is_a?(Array)
61
+
62
+ commands.map do |cmd|
63
+ next cmd.target_ids if cmd.respond_to?(:target_ids)
64
+
65
+ cmd.values_at(:nodeId, :newId, :id)
66
+ end.flatten.compact.uniq
67
+ end
68
+ end
69
+ end
@@ -7,14 +7,11 @@ module Eco::API::UseCases::GraphQL::Helpers::Location::Command
7
7
  @result = result
8
8
  end
9
9
 
10
- def command
10
+ # @return [Symbol] the command type
11
+ def command_type
11
12
  input.keys.first
12
13
  end
13
14
 
14
- def command_input_data
15
- input[command]
16
- end
17
-
18
15
  def node_id
19
16
  command_input_data[:nodeId]
20
17
  end
@@ -24,7 +21,7 @@ module Eco::API::UseCases::GraphQL::Helpers::Location::Command
24
21
  end
25
22
 
26
23
  def applied?
27
- !pending?
24
+ !pending? && success?
28
25
  end
29
26
 
30
27
  def success?
@@ -47,20 +44,24 @@ module Eco::API::UseCases::GraphQL::Helpers::Location::Command
47
44
 
48
45
  feed = []
49
46
  feed.concat(error.validationErrors.map(&:message)) unless error.validationErrors.empty?
50
- feed << "Command: #{command_input_data.pretty_inspect}"
47
+ feed << "Command: #{JSON.pretty_generate(command_input_data)}"
51
48
 
52
49
  msg << " * #{feed.join("\n * ")}"
53
50
  msg.join("\n")
54
51
  end
55
52
 
56
- def command_result
53
+ def command_result_data
57
54
  result&.command
58
55
  end
59
56
 
57
+ def command_input_data
58
+ input[command]
59
+ end
60
+
60
61
  def command_id
61
- return unless result
62
+ return unless command_result_data
62
63
 
63
- command_result['id']
64
+ command_result_data['id']
64
65
  end
65
66
 
66
67
  def as_json