eco-helpers 2.6.3 → 2.7.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/.rubocop.yml +95 -0
- data/CHANGELOG.md +135 -2
- data/Rakefile +13 -7
- data/eco-helpers.gemspec +3 -3
- data/lib/eco/api/common/loaders/base.rb +2 -2
- data/lib/eco/api/common/loaders/case_base.rb +1 -1
- data/lib/eco/api/common/loaders/config/workflow/mailer.rb +5 -5
- data/lib/eco/api/common/loaders/error_handler.rb +8 -5
- data/lib/eco/api/common/loaders/parser.rb +44 -22
- data/lib/eco/api/common/loaders/policy.rb +6 -4
- data/lib/eco/api/common/loaders/use_case.rb +13 -7
- data/lib/eco/api/common/people/base_parser.rb +0 -2
- data/lib/eco/api/common/people/default_parsers/boolean_parser.rb +0 -1
- data/lib/eco/api/common/people/default_parsers/csv_parser.rb +1 -1
- data/lib/eco/api/common/people/default_parsers/date_parser.rb +64 -12
- data/lib/eco/api/common/people/default_parsers/freemium_parser.rb +0 -1
- data/lib/eco/api/common/people/default_parsers/login_providers_parser.rb +13 -5
- data/lib/eco/api/common/people/default_parsers/multi_parser.rb +0 -1
- data/lib/eco/api/common/people/default_parsers/numeric_parser.rb +18 -5
- data/lib/eco/api/common/people/default_parsers/policy_groups_parser.rb +8 -8
- data/lib/eco/api/common/people/default_parsers/select_parser.rb +50 -26
- data/lib/eco/api/common/people/default_parsers/send_invites_parser.rb +6 -6
- data/lib/eco/api/common/people/default_parsers/xls_parser.rb +9 -12
- data/lib/eco/api/common/people/default_parsers.rb +1 -12
- data/lib/eco/api/common/people/entries.rb +13 -13
- data/lib/eco/api/common/people/entry_factory.rb +76 -45
- data/lib/eco/api/common/people/person_attribute_parser.rb +8 -12
- data/lib/eco/api/common/people/person_entry.rb +86 -75
- data/lib/eco/api/common/people/person_entry_attribute_mapper.rb +60 -44
- data/lib/eco/api/common/people/person_factory.rb +30 -22
- data/lib/eco/api/common/people/person_modifier.rb +11 -13
- data/lib/eco/api/common/people/person_parser.rb +101 -39
- data/lib/eco/api/common/people/supervisor_helpers.rb +25 -26
- data/lib/eco/api/common/session/base_session.rb +9 -9
- data/lib/eco/api/common/session/environment.rb +7 -5
- data/lib/eco/api/common/session/sftp.rb +59 -32
- data/lib/eco/api/common/version_patches/ecoportal_api/external_person.rb +10 -6
- data/lib/eco/api/common/version_patches/exception.rb +11 -13
- data/lib/eco/api/error.rb +32 -20
- data/lib/eco/api/microcases/set_supervisor.rb +0 -3
- data/lib/eco/api/organization/node_classifications.rb +82 -0
- data/lib/eco/api/organization/policy_groups.rb +4 -6
- data/lib/eco/api/organization/tag_tree.rb +169 -93
- data/lib/eco/api/organization.rb +1 -0
- data/lib/eco/api/session/batch/job.rb +1 -1
- data/lib/eco/api/session/config/tagtree.rb +41 -23
- data/lib/eco/api/session/config/workflow.rb +113 -88
- data/lib/eco/api/session/config.rb +6 -0
- data/lib/eco/api/session.rb +51 -29
- data/lib/eco/api/usecases/base_io.rb +28 -25
- data/lib/eco/api/usecases/default/locations/cli/tagtree_extract_cli.rb +7 -2
- data/lib/eco/api/usecases/default/locations/cli/tagtree_upload_cli.rb +21 -0
- data/lib/eco/api/usecases/default/locations/csv_to_tree_case.rb +3 -3
- data/lib/eco/api/usecases/default/locations/tagtree_extract_case.rb +54 -23
- data/lib/eco/api/usecases/default/locations/tagtree_upload_case.rb +87 -0
- data/lib/eco/api/usecases/default/locations.rb +1 -0
- data/lib/eco/api/usecases/default/people/analyse_people_case.rb +60 -56
- data/lib/eco/api/usecases/default/people/change_email_case.rb +8 -9
- data/lib/eco/api/usecases/default/people/clean_unknown_tags_case.rb +13 -11
- data/lib/eco/api/usecases/default/people/clear_abilities_case.rb +2 -2
- data/lib/eco/api/usecases/default/people/org_data_convert_case.rb +25 -27
- data/lib/eco/api/usecases/default/people/refresh_case.rb +2 -2
- data/lib/eco/api/usecases/default/people/reinvite_trans_case.rb +1 -1
- data/lib/eco/api/usecases/default/people/reinvite_trans_cli.rb +0 -1
- data/lib/eco/api/usecases/default/people/restore_db_case.rb +39 -34
- data/lib/eco/api/usecases/default/people/set_default_tag_case.rb +19 -15
- data/lib/eco/api/usecases/default/people/supers_cyclic_identify_case.rb +16 -12
- data/lib/eco/api/usecases/default_cases/hris_case.rb +17 -15
- data/lib/eco/api/usecases/default_cases/samples/sftp_case.rb +30 -16
- data/lib/eco/api/usecases/default_cases/to_csv_detailed_case.rb +0 -2
- data/lib/eco/api/usecases/graphql/base.rb +5 -3
- data/lib/eco/api/usecases/graphql/helpers/base/case_env.rb +4 -1
- data/lib/eco/api/usecases/graphql/helpers/base/graphql_env.rb +14 -0
- data/lib/eco/api/usecases/graphql/helpers/base.rb +5 -4
- data/lib/eco/api/usecases/graphql/helpers/location/base/classifications_parser.rb +60 -0
- data/lib/eco/api/usecases/graphql/helpers/location/base/tree_tracking.rb +72 -0
- data/lib/eco/api/usecases/graphql/helpers/location/base.rb +25 -59
- data/lib/eco/api/usecases/graphql/helpers/location/command/diff/as_update.rb +59 -0
- data/lib/eco/api/usecases/graphql/helpers/location/command/diff/compare.rb +49 -0
- data/lib/eco/api/usecases/graphql/helpers/location/command/diff.rb +11 -0
- data/lib/eco/api/usecases/graphql/helpers/location/command/diffs/stages/commandable.rb +46 -0
- data/lib/eco/api/usecases/graphql/helpers/location/command/diffs/stages/diff_sortable/for_archive.rb +23 -0
- data/lib/eco/api/usecases/graphql/helpers/location/command/diffs/stages/diff_sortable/for_unarchive.rb +65 -0
- data/lib/eco/api/usecases/graphql/helpers/location/command/diffs/stages/diff_sortable.rb +49 -0
- data/lib/eco/api/usecases/graphql/helpers/location/command/diffs/stages/sortable/relation_safe_sort.rb +119 -0
- data/lib/eco/api/usecases/graphql/helpers/location/command/diffs/stages/sortable.rb +59 -0
- data/lib/eco/api/usecases/graphql/helpers/location/command/diffs/stages.rb +82 -0
- data/lib/eco/api/usecases/graphql/helpers/location/command/diffs.rb +20 -0
- data/lib/eco/api/usecases/graphql/helpers/location/command/optimizations.rb +84 -0
- data/lib/eco/api/usecases/graphql/helpers/location/command/result.rb +4 -4
- data/lib/eco/api/usecases/graphql/helpers/location/command/results.rb +24 -12
- data/lib/eco/api/usecases/graphql/helpers/location/command.rb +21 -24
- data/lib/eco/api/usecases/graphql/helpers/location/tags_remap/tags_map.rb +1 -1
- data/lib/eco/api/usecases/graphql/helpers/location/tags_remap/tags_set.rb +10 -11
- data/lib/eco/api/usecases/graphql/helpers/location/tags_remap.rb +8 -9
- data/lib/eco/api/usecases/graphql/samples/location/command/dsl.rb +41 -12
- data/lib/eco/api/usecases/graphql/samples/location/command/results.rb +11 -80
- data/lib/eco/api/usecases/graphql/samples/location/command/service/tree_update.rb +89 -0
- data/lib/eco/api/usecases/graphql/samples/location/command/service.rb +6 -0
- data/lib/eco/api/usecases/graphql/samples/location/command/track_changed_ids.rb +89 -0
- data/lib/eco/api/usecases/graphql/samples/location/command.rb +3 -0
- data/lib/eco/api/usecases/graphql/samples/location/service/base.rb +9 -0
- data/lib/eco/api/usecases/graphql/samples/location/service/tree_diff/convertible/heading.rb +18 -0
- data/lib/eco/api/usecases/graphql/samples/location/service/tree_diff/convertible/inputable.rb +53 -0
- data/lib/eco/api/usecases/graphql/samples/location/service/tree_diff/convertible/parsing/classifications.rb +34 -0
- data/lib/eco/api/usecases/graphql/samples/location/service/tree_diff/convertible/parsing/helpers.rb +28 -0
- data/lib/eco/api/usecases/graphql/samples/location/service/tree_diff/convertible/parsing.rb +46 -0
- data/lib/eco/api/usecases/graphql/samples/location/service/tree_diff/convertible.rb +38 -0
- data/lib/eco/api/usecases/graphql/samples/location/service/tree_diff.rb +105 -0
- data/lib/eco/api/usecases/graphql/samples/location/service/tree_to_list/converter/discarded.rb +16 -0
- data/lib/eco/api/usecases/graphql/samples/location/service/tree_to_list/converter/input.rb +15 -0
- data/lib/eco/api/usecases/graphql/samples/location/service/tree_to_list/converter/node_attr_maps.rb +22 -0
- data/lib/eco/api/usecases/graphql/samples/location/service/tree_to_list/converter/parser.rb +45 -0
- data/lib/eco/api/usecases/graphql/samples/location/service/tree_to_list/converter.rb +36 -0
- data/lib/eco/api/usecases/graphql/samples/location/service/tree_to_list/output.rb +56 -0
- data/lib/eco/api/usecases/graphql/samples/location/service/tree_to_list.rb +41 -0
- data/lib/eco/api/usecases/graphql/samples/location/service.rb +8 -0
- data/lib/eco/api/usecases/graphql/samples/location.rb +1 -0
- data/lib/eco/api/usecases/graphql/utils/sftp.rb +96 -36
- data/lib/eco/api/usecases/ooze_cases/export_register_case.rb +8 -6
- data/lib/eco/api/usecases/ooze_samples/helpers/creatable.rb +4 -3
- data/lib/eco/api/usecases/ooze_samples/helpers/exportable_ooze.rb +39 -25
- data/lib/eco/api/usecases/ooze_samples/helpers/exportable_register.rb +13 -15
- data/lib/eco/api/usecases/ooze_samples/helpers/filters.rb +50 -21
- data/lib/eco/api/usecases/ooze_samples/helpers/ooze_handlers.rb +21 -11
- data/lib/eco/api/usecases/ooze_samples/helpers/rescuable.rb +2 -0
- data/lib/eco/api/usecases/ooze_samples/helpers/shortcuts.rb +49 -43
- data/lib/eco/api/usecases/ooze_samples/ooze_base_case.rb +17 -19
- data/lib/eco/api/usecases/ooze_samples/register_export_case.rb +48 -43
- data/lib/eco/api/usecases/ooze_samples/register_update_case.rb +34 -34
- data/lib/eco/api/usecases/ooze_samples/target_oozes_update_case.rb +8 -10
- data/lib/eco/api/usecases.rb +0 -1
- data/lib/eco/cli/config/use_cases.rb +31 -29
- data/lib/eco/cli_default/input_filters.rb +0 -5
- data/lib/eco/cli_default/people_filters.rb +4 -4
- data/lib/eco/cli_default/workflow.rb +13 -14
- data/lib/eco/csv/table.rb +34 -25
- data/lib/eco/data/hashes/array_diff.rb +24 -35
- data/lib/eco/data/hashes/diff_result/meta.rb +131 -0
- data/lib/eco/data/hashes/diff_result.rb +65 -57
- data/lib/eco/data/hashes/sanke_camel_indifferent_access.rb +278 -0
- data/lib/eco/data/hashes.rb +1 -1
- data/lib/eco/data/locations/convert.rb +1 -1
- data/lib/eco/data/locations/node_base/csv_convert.rb +19 -9
- data/lib/eco/data/locations/node_base/parsing.rb +4 -2
- data/lib/eco/data/locations/node_base/treeify.rb +149 -132
- data/lib/eco/data/locations/node_base.rb +15 -4
- data/lib/eco/data/locations/node_diff/accessors.rb +13 -5
- data/lib/eco/data/locations/node_diff/nodes_diff/clustered_treeify.rb +101 -0
- data/lib/eco/data/locations/node_diff/nodes_diff/diffs_tree.rb +99 -0
- data/lib/eco/data/locations/node_diff/{selectors.rb → nodes_diff/selectors.rb} +1 -1
- data/lib/eco/data/locations/node_diff/nodes_diff.rb +50 -35
- data/lib/eco/data/locations/node_diff.rb +45 -17
- data/lib/eco/data/locations/node_level/parsing.rb +15 -21
- data/lib/eco/data/locations/node_level.rb +66 -22
- data/lib/eco/data/locations/node_plain/parsing.rb +1 -1
- data/lib/eco/data/locations/node_plain.rb +60 -7
- data/lib/eco/data/strings/camel_case.rb +35 -0
- data/lib/eco/data/strings/snake_case.rb +18 -0
- data/lib/eco/data/strings.rb +8 -0
- data/lib/eco/data.rb +1 -0
- data/lib/eco/language/methods/call_detector.rb +11 -0
- data/lib/eco/language/methods/dsl_able.rb +7 -1
- data/lib/eco/language/methods.rb +2 -1
- data/lib/eco/language/models/collection.rb +23 -25
- data/lib/eco/language/models/parser_serializer.rb +24 -5
- data/lib/eco/version.rb +1 -1
- data/lib/eco-helpers.rb +0 -1
- metadata +54 -9
- data/lib/eco/data/hashes/diff_meta.rb +0 -52
@@ -6,23 +6,27 @@ module Eco
|
|
6
6
|
# This does not allow to capture the `name` and `id` of the locations
|
7
7
|
# structure itself into the json storing model.
|
8
8
|
class TagTree
|
9
|
-
HEADER = [
|
10
|
-
|
11
|
-
|
9
|
+
HEADER = %w[
|
10
|
+
id name weight parent_id
|
11
|
+
archived archived_token
|
12
|
+
classifications classification_names
|
13
|
+
level
|
12
14
|
].freeze
|
13
15
|
|
16
|
+
include Enumerable
|
17
|
+
|
18
|
+
attr_reader :source
|
19
|
+
|
14
20
|
attr_accessor :id
|
15
21
|
alias_method :tag, :id
|
22
|
+
|
16
23
|
attr_accessor :name, :weight
|
17
24
|
attr_accessor :archived, :archived_token
|
25
|
+
attr_accessor :classifications, :classification_names
|
18
26
|
|
19
27
|
attr_reader :parent
|
20
|
-
attr_reader :nodes
|
21
|
-
attr_reader :depth
|
22
|
-
|
23
|
-
attr_reader :source
|
24
|
-
|
25
|
-
include Enumerable
|
28
|
+
attr_reader :nodes
|
29
|
+
attr_reader :depth
|
26
30
|
|
27
31
|
# @example Node format:
|
28
32
|
# {"tag": "NODE NAME", "nodes": subtree}
|
@@ -34,33 +38,32 @@ module Eco
|
|
34
38
|
# ]}]
|
35
39
|
# tree = TagTree.new(tree.to_json)
|
36
40
|
# @param tagtree [String] representation of the tagtree in json.
|
37
|
-
def initialize(
|
38
|
-
|
39
|
-
|
41
|
+
def initialize(
|
42
|
+
tagtree = [],
|
43
|
+
name: nil, id: nil,
|
44
|
+
depth: -1, path: [],
|
45
|
+
parent: nil, _weight: nil # rubocop:disable Lint/UnderscorePrefixedVariableName
|
46
|
+
)
|
40
47
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
+
@source = parse_source_input(tagtree)
|
49
|
+
|
50
|
+
msg = "You are trying to initialize a TagTree with a null tagtree"
|
51
|
+
raise ArgumentError, msg unless source
|
52
|
+
|
53
|
+
@parent = parent
|
54
|
+
@depth = depth
|
55
|
+
@path = path || []
|
48
56
|
|
49
|
-
if
|
57
|
+
if source.is_a?(Array)
|
50
58
|
@id = id
|
51
59
|
@name = name
|
52
|
-
@raw_nodes =
|
60
|
+
@raw_nodes = source
|
53
61
|
else
|
54
|
-
|
55
|
-
|
56
|
-
@archived = @source['archived'] || false
|
57
|
-
@archived_token = @source['archived_token']
|
58
|
-
@source['weight'] = @weight = @source['weight'] || _weight
|
59
|
-
@raw_nodes = @source['nodes'] || []
|
62
|
+
source['weight'] ||= _weight
|
63
|
+
init_node
|
60
64
|
end
|
61
65
|
|
62
|
-
|
63
|
-
@path.push(@id) unless top?
|
66
|
+
self.path.push(self.id) unless top?
|
64
67
|
|
65
68
|
@nodes = @raw_nodes.map.with_index do |cnode, idx|
|
66
69
|
self.class.new(cnode, depth: depth + 1, path: @path.dup, parent: self, _weight: idx)
|
@@ -84,18 +87,19 @@ module Eco
|
|
84
87
|
end
|
85
88
|
|
86
89
|
# @return [Array] with the differences
|
87
|
-
def diff(tagtree,
|
90
|
+
def diff(tagtree, _differences: {}, _level: 0, **options)
|
88
91
|
require 'hashdiff'
|
89
|
-
Hashdiff.diff(
|
92
|
+
Hashdiff.diff(as_json, tagtree.as_json, **options.slice(:array_path, :similarity, :use_lcs))
|
90
93
|
end
|
91
94
|
|
92
95
|
# It generates a merged tagtree out of two sources
|
93
96
|
# @note it merges the first level nodes (and their children) as it comes
|
94
97
|
# @return [Eco::API::Organization::TagTree] result of merging both trees
|
95
98
|
def merge(other)
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
+
msg = "Expecting Eco::API::Organization::TagTree. Given: #{other.class}"
|
100
|
+
raise ArgumentError, msg unless other.is_a?(Eco::API::Organization::TagTree)
|
101
|
+
mid = [id, other.id].join('|')
|
102
|
+
mname = [name, other.name].join('|')
|
99
103
|
self.class.new(as_json | other.as_json, id: mid, name: mname)
|
100
104
|
end
|
101
105
|
|
@@ -187,7 +191,11 @@ module Eco
|
|
187
191
|
# @param include_archived [Boolean] whether it should include archived nodes.
|
188
192
|
# @param max_depth [Boolean] up to what level `depth` nodes should be included.
|
189
193
|
# @return [Array[Hash]] where `Hash` is a `node` (i.e. `{"tag" => TAG, "nodes": Array[Hash]}`)
|
190
|
-
def as_json(
|
194
|
+
def as_json( # rubocop:disable Metrics/AbcSize
|
195
|
+
include_children: true, include_archived: true,
|
196
|
+
max_depth: total_depth,
|
197
|
+
&block
|
198
|
+
)
|
191
199
|
max_depth ||= total_depth
|
192
200
|
return nil if max_depth < depth
|
193
201
|
return [] if top? && !include_children
|
@@ -202,17 +210,22 @@ module Eco
|
|
202
210
|
max_depth: max_depth
|
203
211
|
}
|
204
212
|
children_json = child_nodes.map {|nd| nd.as_json(**kargs, &block)}.compact
|
205
|
-
end
|
206
213
|
|
207
|
-
|
208
|
-
children_json
|
209
|
-
else
|
210
|
-
values = [id, name, weight, parent_id, archived, archived_token]
|
211
|
-
node_json = self.class::HEADER.zip(values).to_h
|
212
|
-
node_json["nodes"] = children_json if include_children
|
213
|
-
node_json = yield(node_json, self) if block_given?
|
214
|
-
node_json
|
214
|
+
return children_json if top?
|
215
215
|
end
|
216
|
+
|
217
|
+
values = [
|
218
|
+
id, name,
|
219
|
+
weight, parent_id,
|
220
|
+
archived, archived_token,
|
221
|
+
classifications.dup,
|
222
|
+
classification_names.dup,
|
223
|
+
depth + 1
|
224
|
+
]
|
225
|
+
node_json = self.class::HEADER.zip(values).to_h
|
226
|
+
node_json["nodes"] = children_json if include_children
|
227
|
+
node_json = yield(node_json, self) if block_given?
|
228
|
+
node_json
|
216
229
|
end
|
217
230
|
|
218
231
|
# Returns a plain list form of hash nodes.
|
@@ -233,11 +246,9 @@ module Eco
|
|
233
246
|
|
234
247
|
# @return [Integer] the highest `depth` of all the children.
|
235
248
|
def total_depth
|
236
|
-
@total_depth ||=
|
237
|
-
|
238
|
-
|
239
|
-
end
|
240
|
-
deepest_node.total_depth
|
249
|
+
@total_depth ||=
|
250
|
+
if children?
|
251
|
+
nodes.max_by(&:total_depth)&.total_depth
|
241
252
|
else
|
242
253
|
depth
|
243
254
|
end
|
@@ -245,20 +256,21 @@ module Eco
|
|
245
256
|
|
246
257
|
# @return [Integer] if there's only top level.
|
247
258
|
def flat?
|
248
|
-
|
259
|
+
total_depth <= 0
|
249
260
|
end
|
250
261
|
|
251
262
|
# Gets all the tags of the current node tree.
|
252
263
|
# @note
|
253
264
|
# - this will include the upper level tag(s) as well
|
254
265
|
# - to get all but the upper level tag(s) use `subtags` method instead
|
255
|
-
# @param depth [Integer] if empty, returns the list of tag nodes of that level.
|
266
|
+
# @param depth [Integer] if empty, returns the list of tag nodes of that level.
|
267
|
+
# Otherwise the list of tag nodes of the entire subtree.
|
256
268
|
# @return [Array<String>]
|
257
269
|
def tags(depth: nil)
|
258
|
-
if !depth || depth
|
270
|
+
if !depth || depth&.negative?
|
259
271
|
@hash_tags.keys
|
260
272
|
else
|
261
|
-
@hash_tags.select do |
|
273
|
+
@hash_tags.select do |_t, n|
|
262
274
|
n.depth == depth
|
263
275
|
end.keys
|
264
276
|
end
|
@@ -280,8 +292,8 @@ module Eco
|
|
280
292
|
# Returns all the tags with no children
|
281
293
|
# @return [Array<String>]
|
282
294
|
def leafs
|
283
|
-
tags.
|
284
|
-
|
295
|
+
tags.reject do |tag|
|
296
|
+
node(tag).children?
|
285
297
|
end
|
286
298
|
end
|
287
299
|
|
@@ -291,8 +303,8 @@ module Eco
|
|
291
303
|
end
|
292
304
|
|
293
305
|
# @return [Boolean] it has subnodes
|
294
|
-
def
|
295
|
-
children_count
|
306
|
+
def children?
|
307
|
+
children_count&.positive?
|
296
308
|
end
|
297
309
|
|
298
310
|
# Verifies if a tag exists in the tree.
|
@@ -314,7 +326,7 @@ module Eco
|
|
314
326
|
# @param list [Array<String>] source tags.
|
315
327
|
# @return [Array<String>]
|
316
328
|
def filter_tags(list)
|
317
|
-
return [] unless list
|
329
|
+
return [] unless list.is_a?(Array)
|
318
330
|
list.select {|str| tag?(str)}
|
319
331
|
end
|
320
332
|
|
@@ -324,7 +336,7 @@ module Eco
|
|
324
336
|
# @param key [String] tag to find the path to.
|
325
337
|
# @return [Array<String>]
|
326
338
|
def path(key = nil)
|
327
|
-
return @path.dup
|
339
|
+
return @path.dup unless key
|
328
340
|
@hash_paths[key.upcase].dup
|
329
341
|
end
|
330
342
|
|
@@ -341,24 +353,32 @@ module Eco
|
|
341
353
|
# original = ["SYDNEY", "RISK"]
|
342
354
|
# final = ["MELBOURNE", "EVENT"]
|
343
355
|
#
|
344
|
-
# tree.user_tags(initial: original, final: final)
|
345
|
-
#
|
346
|
-
# tree.user_tags(initial: original, final: final,
|
347
|
-
#
|
356
|
+
# tree.user_tags(initial: original, final: final)
|
357
|
+
# # out: ["MELBOURNE", "RISK"]
|
358
|
+
# tree.user_tags(initial: original, final: final, preserve_custom: false)
|
359
|
+
# # out: ["MELBOURNE"]
|
360
|
+
# tree.user_tags(initial: original, final: final, add_custom: true)
|
361
|
+
# # out: ["MELBOURNE", "RISK", "EVENT"]
|
362
|
+
# tree.user_tags(initial: original, final: final, preserve_custom: false, add_custom: true)
|
363
|
+
# # out: ["MELBOURNE", "EVENT"]
|
348
364
|
#
|
349
365
|
# @param initial [Array<String>] original tags a person has in their account.
|
350
|
-
# @param final [Array<String>] target tags the person should have in
|
351
|
-
#
|
352
|
-
# @param
|
366
|
+
# @param final [Array<String>] target tags the person should have in
|
367
|
+
# their account afterwards.
|
368
|
+
# @param preserve_custom [Boolean] indicates if original tags
|
369
|
+
# that are not in the tree should be added/preserved.
|
370
|
+
# @param add_custom [Boolean] indicates if target tags that are
|
371
|
+
# not in the tree should be really added.
|
353
372
|
# @return [Array<String>] with the treated final tags.
|
354
373
|
def user_tags(initial: [], final: [], preserve_custom: true, add_custom: false)
|
355
374
|
initial = [initial].flatten.compact
|
356
375
|
final = [final].flatten.compact
|
357
376
|
raise "Expected Array for initial: and final:" unless initial.is_a?(Array) && final.is_a?(Array)
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
377
|
+
|
378
|
+
final = filter_tags(final) unless add_custom
|
379
|
+
custom = initial - filter_tags(initial)
|
380
|
+
final |= custom if preserve_custom
|
381
|
+
new_tags = final - initial
|
362
382
|
# keep same order as they where
|
363
383
|
(initial & final) + new_tags
|
364
384
|
end
|
@@ -372,52 +392,108 @@ module Eco
|
|
372
392
|
# @param [Array<String>] values list of tags.
|
373
393
|
# @return [String] default tag.
|
374
394
|
def default_tag(*values)
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
ddepth = cnode.depth
|
383
|
-
elsif cnode.depth == ddepth
|
384
|
-
nodes.push(cnode)
|
395
|
+
default_tag = nil
|
396
|
+
values = filter_tags(values)
|
397
|
+
tnodes, ddepth = get_deepest_nodes_among_tags(*values)
|
398
|
+
|
399
|
+
unless tnodes.empty?
|
400
|
+
common = tnodes.reduce(tags.reverse) do |com, cnode|
|
401
|
+
com & cnode.path.reverse
|
385
402
|
end
|
403
|
+
default_tag = common.first if common.any? && ddepth&.positive?
|
386
404
|
end
|
387
405
|
|
388
|
-
default_tag
|
389
|
-
if nodes.length > 1
|
390
|
-
common = nodes.reduce(self.tags.reverse) {|com, cnode| com & cnode.path.reverse}
|
391
|
-
default_tag = common.first if common.length > 0 && ddepth > 0
|
392
|
-
end
|
393
|
-
default_tag ||= nodes.first&.tag if (ddepth > 0) || flat?
|
406
|
+
default_tag ||= tnodes.first&.tag if ddepth&.positive? || flat?
|
394
407
|
default_tag
|
395
408
|
end
|
396
409
|
|
397
410
|
protected
|
398
411
|
|
412
|
+
attr_reader :hash_paths
|
413
|
+
|
399
414
|
def hash
|
400
415
|
@hash_tags
|
401
416
|
end
|
402
417
|
|
403
|
-
|
404
|
-
|
418
|
+
private
|
419
|
+
|
420
|
+
def parse_source_input(value)
|
421
|
+
return value unless value.is_a?(String)
|
422
|
+
JSON.parse(value)
|
405
423
|
end
|
406
424
|
|
407
|
-
|
425
|
+
def init_node
|
426
|
+
return if source.is_a?(Array)
|
427
|
+
@id = source.values_at('tag', 'id').compact.first&.upcase
|
428
|
+
@name = source['name']
|
429
|
+
@weight = source['weight']
|
430
|
+
@archived = as_boolean(source['archived'])
|
431
|
+
@archived_token = source['archived_token']
|
432
|
+
@classifications = into_a(source['classifications']).map do |value|
|
433
|
+
treat_classication(value)
|
434
|
+
end
|
435
|
+
@classification_names = into_a(source['classification_names'])
|
436
|
+
@raw_nodes = source['nodes'] || []
|
437
|
+
end
|
408
438
|
|
409
439
|
def init_hashes
|
410
|
-
@hash_tags
|
440
|
+
@hash_tags = {}
|
411
441
|
@hash_tags[@id] = self unless top?
|
412
|
-
@hash_tags
|
442
|
+
@hash_tags = nodes.reduce(@hash_tags) do |h, n|
|
413
443
|
h.merge(n.hash)
|
414
444
|
end
|
415
|
-
@hash_paths
|
445
|
+
@hash_paths = {}
|
416
446
|
@hash_paths[@id] = @path unless top?
|
417
|
-
@hash_paths
|
447
|
+
@hash_paths = nodes.reduce(@hash_paths) do |h, n|
|
418
448
|
h.merge(n.hash_paths)
|
419
449
|
end
|
420
450
|
end
|
451
|
+
|
452
|
+
## Helpers
|
453
|
+
# Gathers the deepest nodes among `values`
|
454
|
+
# @note it will only return multiple nodes if they
|
455
|
+
# they are all at the same level
|
456
|
+
# @return [Array<Nodes, Integer>]
|
457
|
+
def get_deepest_nodes_among_tags(*values)
|
458
|
+
ddepth = -1
|
459
|
+
tnodes = []
|
460
|
+
|
461
|
+
values.each do |ttag|
|
462
|
+
msg = "Couldn't find the node of #{ttag} in the tag-tree definition"
|
463
|
+
raise msg unless (cnode = node(ttag))
|
464
|
+
|
465
|
+
next unless cnode.depth >= ddepth
|
466
|
+
next tnodes.push(cnode) if cnode.depth == ddepth
|
467
|
+
|
468
|
+
# cnode.depth > ddepth
|
469
|
+
tnodes = [cnode]
|
470
|
+
ddepth = cnode.depth
|
471
|
+
end
|
472
|
+
|
473
|
+
[tnodes, ddepth]
|
474
|
+
end
|
475
|
+
|
476
|
+
def treat_classication(value)
|
477
|
+
return value unless value.is_a?(String)
|
478
|
+
value.strip.gsub(/\W+/, '').downcase
|
479
|
+
end
|
480
|
+
|
481
|
+
# Helper to convert to array
|
482
|
+
def into_a(value)
|
483
|
+
if value.is_a?(String)
|
484
|
+
value.split('|')
|
485
|
+
else
|
486
|
+
[value].flatten
|
487
|
+
end.compact
|
488
|
+
end
|
489
|
+
|
490
|
+
def as_boolean(value)
|
491
|
+
return false if value.nil? || value == false
|
492
|
+
return true if value == true
|
493
|
+
return false if value.to_s.strip.empty?
|
494
|
+
return true if %w[yes x true].include?(value.downcase)
|
495
|
+
false
|
496
|
+
end
|
421
497
|
end
|
422
498
|
end
|
423
499
|
end
|
data/lib/eco/api/organization.rb
CHANGED
@@ -93,7 +93,7 @@ module Eco
|
|
93
93
|
end
|
94
94
|
|
95
95
|
# Adds an entry(ies) to the job queue.
|
96
|
-
# @param entry [Ecoportal::API::V1::Person,
|
96
|
+
# @param entry [Ecoportal::API::V1::Person, Enumerable<Person>] the person(s) we want to update, carrying the changes to be done.
|
97
97
|
# @param unique [Boolean] specifies if repeated entries should be avoided in the queue.
|
98
98
|
# @yield [person] callback before launching the batch job request against the server.
|
99
99
|
# @yieldparam person [Person] current person object that that should be treated by the callback before launching the batch.
|
@@ -8,12 +8,21 @@ module Eco
|
|
8
8
|
|
9
9
|
attr_key :file, :structure_id
|
10
10
|
|
11
|
+
# The location node classifications of the organization
|
12
|
+
# @return [Eco::API::Organization::NodeClassifications]
|
13
|
+
def node_classifications(active: true)
|
14
|
+
return [] unless (graphql = graphql_api)
|
15
|
+
|
16
|
+
node_types = graphql.locationStructure.nodeClassifications(active: active)
|
17
|
+
Eco::API::Organization::NodeClassifications.new(node_types)
|
18
|
+
end
|
19
|
+
|
11
20
|
# @note it retrieves the tree this way:
|
12
21
|
# 1. If there's a file tagtree.json file, it uses it
|
13
22
|
# 2. If no file, retrieves `structure_id` (config)
|
14
23
|
# @param include_archived [Boolean] whether or not it should include archived nodes.
|
15
24
|
# @return [Eco::API::Organization::TagTree]
|
16
|
-
def scope_tree(enviro: nil, include_archived: true, raise_on_missing: true)
|
25
|
+
def scope_tree(enviro: nil, include_archived: true, raise_on_missing: true) # rubocop:disable Lint/UnusedMethodArgument
|
17
26
|
return @tagtree if instance_variable_defined?(:@tagtree) && @tagtree.enviro == enviro
|
18
27
|
|
19
28
|
kargs = {
|
@@ -21,34 +30,34 @@ module Eco
|
|
21
30
|
includeArchivedNodes: include_archived
|
22
31
|
}
|
23
32
|
|
24
|
-
if tree_file =
|
33
|
+
if (tree_file = file)
|
25
34
|
if (tree = file_manager.load_json(tree_file)) && !tree.empty?
|
26
35
|
@tagtree = Eco::API::Organization::TagTree.new(tree)
|
27
36
|
end
|
28
|
-
elsif
|
29
|
-
kargs.merge(id:
|
37
|
+
elsif structure_id
|
38
|
+
kargs.merge(id: structure_id)
|
30
39
|
end
|
31
40
|
|
32
|
-
@tagtree ||= live_tree(**kargs).tap do |
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
41
|
+
@tagtree ||= live_tree(**kargs).tap do |tr| # rubocop:disable Naming/MemoizedInstanceVariableName
|
42
|
+
next if tr && !tr.empty?
|
43
|
+
|
44
|
+
msg = "Could not find a local or live locations structure."
|
45
|
+
raise MissingTagtree, msg
|
37
46
|
end
|
38
47
|
end
|
39
48
|
|
40
49
|
# Among all the locations structures it selects the one with more location nodes
|
41
50
|
# If `id` is provided, it only retrieves this locations structure.
|
42
51
|
# @param [enviro] used for re-caching
|
43
|
-
def live_tree(id: nil, enviro: nil, include_archived: false, **kargs, &block)
|
44
|
-
existing_cache =
|
52
|
+
def live_tree(id: nil, enviro: nil, include_archived: false, **kargs, &block) # rubocop:disable Metrics/AbcSize
|
53
|
+
existing_cache = !@live_tree.nil?
|
45
54
|
first_load = !existing_cache
|
46
55
|
|
47
56
|
target_change = existing_cache && id && @live_tree.id != id
|
48
57
|
enviro_change = existing_cache && enviro && @live_tree.enviro != enviro
|
49
58
|
|
50
59
|
switching_target = existing_cache && (target_change || enviro_change)
|
51
|
-
|
60
|
+
_refresh_cache = existing_cache && !switching_target
|
52
61
|
|
53
62
|
kargs = {
|
54
63
|
includeArchivedNodes: include_archived
|
@@ -59,10 +68,12 @@ module Eco
|
|
59
68
|
@live_tree = live_tree_get(**args, &block)
|
60
69
|
else
|
61
70
|
trees = live_trees(**kargs, &block)
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
71
|
+
if trees.count > 1
|
72
|
+
@live_tree = trees.reject(&:empty?).max do |a, b|
|
73
|
+
a.count <=> b.count
|
74
|
+
end
|
75
|
+
else
|
76
|
+
@live_tree = trees.first
|
66
77
|
end
|
67
78
|
end.tap do |tree|
|
68
79
|
if tree
|
@@ -85,8 +96,7 @@ module Eco
|
|
85
96
|
# @param include_archived [Boolean] whether or not to include archived **nodes**
|
86
97
|
# @return [Eco::API::Organization::TagTree, NilClass]
|
87
98
|
def live_tree_get(id: nil, include_archived: false, **kargs, &block)
|
88
|
-
return nil unless
|
89
|
-
return nil unless graphql = apis.api(version: :graphql)
|
99
|
+
return nil unless (graphql = graphql_api)
|
90
100
|
|
91
101
|
kargs = {
|
92
102
|
id: id,
|
@@ -94,9 +104,11 @@ module Eco
|
|
94
104
|
}.merge(kargs)
|
95
105
|
|
96
106
|
start = Time.now
|
97
|
-
|
107
|
+
tree = graphql.currentOrganization.locationStructure(**kargs, &block)
|
108
|
+
return nil unless tree
|
109
|
+
|
98
110
|
end_time = Time.now
|
99
|
-
secs
|
111
|
+
secs = (end_time - start).round(3)
|
100
112
|
|
101
113
|
Eco::API::Organization::TagTree.new(tree.treeify, id: tree.id, name: tree.name).tap do |eco_tree|
|
102
114
|
cnt = eco_tree.count
|
@@ -110,15 +122,16 @@ module Eco
|
|
110
122
|
# @return [Array<Eco::API::Organization::TagTree>]
|
111
123
|
def live_trees(include_archived: false, **kargs, &block)
|
112
124
|
[].tap do |eco_trees|
|
113
|
-
next unless
|
114
|
-
next unless graphql = apis.api(version: :graphql)
|
125
|
+
next unless (graphql = graphql_api)
|
115
126
|
|
116
127
|
kargs = {
|
117
128
|
includeArchivedNodes: include_archived
|
118
129
|
}.merge(kargs)
|
119
130
|
|
120
131
|
start = Time.now
|
121
|
-
|
132
|
+
trees = graphql.currentOrganization.locationStructures(**kargs, &block)
|
133
|
+
next unless trees
|
134
|
+
|
122
135
|
end_time = Time.now
|
123
136
|
secs = (end_time - start).round(3)
|
124
137
|
cnt = 0
|
@@ -134,6 +147,11 @@ module Eco
|
|
134
147
|
|
135
148
|
private
|
136
149
|
|
150
|
+
def graphql_api
|
151
|
+
return nil unless apis.active_api.version_available?(:graphql)
|
152
|
+
apis.api(version: :graphql)
|
153
|
+
end
|
154
|
+
|
137
155
|
def session
|
138
156
|
ASSETS.session
|
139
157
|
end
|