eco-helpers 2.1.12 → 2.2.1
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 +4 -4
- data/CHANGELOG.md +13 -3
- data/eco-helpers.gemspec +2 -2
- data/lib/eco/api/common/people/person_parser.rb +1 -1
- data/lib/eco/api/common/version_patches/ecoportal_api/external_person.rb +11 -1
- data/lib/eco/api/organization/tag_tree.rb +27 -17
- data/lib/eco/api/session/config/base_config.rb +28 -2
- data/lib/eco/api/session/config/files.rb +1 -7
- data/lib/eco/api/session/config/logger.rb +3 -38
- data/lib/eco/api/session/config/mailer.rb +3 -60
- data/lib/eco/api/session/config/people.rb +4 -26
- data/lib/eco/api/session/config/s3_storage.rb +3 -42
- data/lib/eco/api/session/config/sftp.rb +3 -48
- data/lib/eco/api/session/config/tagtree.rb +48 -0
- data/lib/eco/api/session/config.rb +11 -19
- data/lib/eco/api/usecases/default_cases/csv_to_tree_case/helper.rb +90 -0
- data/lib/eco/api/usecases/default_cases/csv_to_tree_case/node.rb +206 -0
- data/lib/eco/api/usecases/default_cases/csv_to_tree_case/nodes_cleaner.rb +73 -0
- data/lib/eco/api/usecases/default_cases/csv_to_tree_case/treeify.rb +33 -0
- data/lib/eco/api/usecases/default_cases/csv_to_tree_case.rb +44 -0
- data/lib/eco/api/usecases/default_cases.rb +1 -0
- data/lib/eco/api/usecases/graphql/base.rb +1 -1
- data/lib/eco/api/usecases/ooze_samples/helpers_migration/copying.rb +1 -1
- data/lib/eco/cli/config/default/usecases.rb +6 -0
- data/lib/eco/version.rb +1 -1
- metadata +15 -9
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c71f3bf20fae0dff4ec0ccd0ee8205b8af1dee3c9fabb02791f6102a84f7f9ab
|
4
|
+
data.tar.gz: 81ba2c67c4653941529051d433189101e6480313447fdbe6c64da617887371b7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b67b415da8341ab6d20a4165ef9f761777bcdb871635a33b0681a56228dae6138c779c31852ce2e748156fa41832ab1ea457ad1aa7ff9dc66c3e1c16dc016be4
|
7
|
+
data.tar.gz: 53e6154974cc3db39e56a127710c1a676e34af8786012b0f3c41051fe14d0b27cc55945875843cdfa1f5fb98d64ed8afcae7eebcd2cfb0cb30da43f7aee2c16f
|
data/CHANGELOG.md
CHANGED
@@ -1,14 +1,24 @@
|
|
1
1
|
# Change Log
|
2
2
|
All notable changes to this project will be documented in this file.
|
3
3
|
|
4
|
-
## [2.
|
4
|
+
## [2.2.2] - 2023-02-xx
|
5
5
|
|
6
6
|
### Added
|
7
7
|
### Changed
|
8
8
|
### Fixed
|
9
|
-
- `Eco::API::Session::Batch::Errors#str` remove double up on error message
|
10
|
-
- wrong require
|
11
9
|
|
10
|
+
## [2.2.1] - 2023-02-24
|
11
|
+
|
12
|
+
### Added
|
13
|
+
- `Ecoportal::API::V1::Person#contractor_organization_id`
|
14
|
+
- **Support** for **Reporting Structures** (breaking change)
|
15
|
+
- `Eco::API::UseCases::DefaultCases::CsvToTree` use case to generate tree json out of a csv
|
16
|
+
- The output file can be fed to `Eco::API::Organization::TagTree`
|
17
|
+
|
18
|
+
### Changed
|
19
|
+
- **Patch** `Ecoportal::API::V1::Person::VALID_TAG_REGEX` it now allows for dot `.`
|
20
|
+
- update gem dependencies
|
21
|
+
|
12
22
|
## [2.1.12] - 2022-11-30
|
13
23
|
|
14
24
|
### Fixed
|
data/eco-helpers.gemspec
CHANGED
@@ -31,8 +31,8 @@ Gem::Specification.new do |spec|
|
|
31
31
|
spec.add_development_dependency "redcarpet", ">= 3.5.1", "< 3.6"
|
32
32
|
|
33
33
|
spec.add_dependency 'ecoportal-api', '>= 0.8.5', '< 0.9'
|
34
|
-
spec.add_dependency 'ecoportal-api-v2', '>= 0.
|
35
|
-
spec.add_dependency 'ecoportal-api-graphql', '>= 0.
|
34
|
+
spec.add_dependency 'ecoportal-api-v2', '>= 1.0.1', '< 1.1'
|
35
|
+
spec.add_dependency 'ecoportal-api-graphql', '>= 0.2.2', '< 0.3'
|
36
36
|
spec.add_dependency 'aws-sdk-s3', '>= 1.83.0', '< 2'
|
37
37
|
spec.add_dependency 'aws-sdk-ses', '>= 1.36.0', '< 2'
|
38
38
|
spec.add_dependency 'dotenv', '>= 2.7.6', '< 2.8'
|
@@ -13,7 +13,7 @@ module Eco
|
|
13
13
|
autoloads_children_of "Eco::API::Common::Loaders::Parser"
|
14
14
|
autoload_namespace_ignore "Eco::API"
|
15
15
|
|
16
|
-
CORE_ATTRS = ["id", "external_id", "email", "name", "supervisor_id", "filter_tags", "freemium"]
|
16
|
+
CORE_ATTRS = ["id", "external_id", "email", "name", "supervisor_id", "filter_tags", "contractor_organization_id", "freemium"]
|
17
17
|
ACCOUNT_ATTRS = ["policy_group_ids", "default_tag", "send_invites", "landing_page_id", "login_provider_ids"]
|
18
18
|
TYPE = [:select, :text, :date, :number, :phone_number, :boolean, :multiple]
|
19
19
|
FORMAT = [:csv, :xml, :json, :xls]
|
@@ -3,6 +3,17 @@ module Ecoportal
|
|
3
3
|
class V1
|
4
4
|
# @attr entry [Eco::API::Common::People::PersonEntry, Hash] the input entry plain hash data used to update/create this person.
|
5
5
|
class Person
|
6
|
+
class << self
|
7
|
+
def redef_without_warning(const, value)
|
8
|
+
self.class.send(:remove_const, const) if self.class.const_defined?(const)
|
9
|
+
self.class.const_set(const, value)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
redef_without_warning('VALID_TAG_REGEX', /^[A-Za-z0-9 &_'\/.-]+$/)
|
14
|
+
|
15
|
+
passthrough :contractor_organization_id
|
16
|
+
|
6
17
|
attr_accessor :entry
|
7
18
|
|
8
19
|
def identify(section = :person)
|
@@ -13,7 +24,6 @@ module Ecoportal
|
|
13
24
|
"'#{name}' (#{str_id}ext_id: '#{external_id}'; email: '#{email}')"
|
14
25
|
end
|
15
26
|
end
|
16
|
-
|
17
27
|
end
|
18
28
|
end
|
19
29
|
end
|
@@ -1,10 +1,13 @@
|
|
1
1
|
module Eco
|
2
2
|
module API
|
3
3
|
module Organization
|
4
|
-
|
5
4
|
# Provides helpers to deal with tagtrees.
|
6
5
|
class TagTree
|
7
|
-
|
6
|
+
attr_accessor :id
|
7
|
+
alias_method :tag, :id
|
8
|
+
attr_accessor :name
|
9
|
+
|
10
|
+
attr_reader :nodes, :children_count
|
8
11
|
attr_reader :depth, :path
|
9
12
|
attr_reader :enviro
|
10
13
|
|
@@ -18,7 +21,7 @@ module Eco
|
|
18
21
|
# ]}]
|
19
22
|
# tree = TagTree.new(tree.to_json)
|
20
23
|
# @param tagtree [String] representation of the tagtree in json.
|
21
|
-
def initialize(tagtree = [], depth: -1, path: [], enviro: nil)
|
24
|
+
def initialize(tagtree = [], name: nil, id: nil, depth: -1, path: [], enviro: nil)
|
22
25
|
case tagtree
|
23
26
|
when String
|
24
27
|
@source = JSON.parse(tagtree)
|
@@ -30,23 +33,27 @@ module Eco
|
|
30
33
|
@enviro = enviro
|
31
34
|
|
32
35
|
@depth = depth
|
33
|
-
|
36
|
+
if @source.is_a?(Array)
|
37
|
+
@id = id
|
38
|
+
@name = name
|
39
|
+
@nodes = @source
|
40
|
+
else
|
41
|
+
@id = @source.values_at('tag', 'id').compact.first&.upcase
|
42
|
+
@name = @source['name']
|
43
|
+
@nodes = @source['nodes'] || []
|
44
|
+
end
|
34
45
|
|
35
46
|
@path = path || []
|
36
|
-
@path.push(@
|
47
|
+
@path.push(@id) unless top?
|
37
48
|
|
38
|
-
nodes =
|
39
|
-
|
49
|
+
@nodes = nodes.map do |cnode|
|
50
|
+
TagTree.new(cnode, depth: @depth + 1, path: @path.dup, enviro: @enviro)
|
51
|
+
end
|
40
52
|
@children_count = @nodes.count
|
41
53
|
|
42
54
|
init_hashes
|
43
55
|
end
|
44
56
|
|
45
|
-
# Updates the tag of the current tree
|
46
|
-
def tag=(value)
|
47
|
-
@tag = value
|
48
|
-
end
|
49
|
-
|
50
57
|
# @return [Eco::API::Organization::TagTree]
|
51
58
|
def dup
|
52
59
|
self.class.new(as_json)
|
@@ -69,7 +76,7 @@ module Eco
|
|
69
76
|
nodes_json
|
70
77
|
else
|
71
78
|
{
|
72
|
-
"
|
79
|
+
"id" => tag,
|
73
80
|
"nodes" => nodes_json
|
74
81
|
}
|
75
82
|
end
|
@@ -80,6 +87,11 @@ module Eco
|
|
80
87
|
@has_tags.empty?
|
81
88
|
end
|
82
89
|
|
90
|
+
# @return [Integer] the number of locations
|
91
|
+
def count
|
92
|
+
@hash_tags.keys.count
|
93
|
+
end
|
94
|
+
|
83
95
|
# @return [Integer] the highest `depth` of all the children.
|
84
96
|
def total_depth
|
85
97
|
@total_depth ||= if children_count > 0
|
@@ -245,12 +257,12 @@ module Eco
|
|
245
257
|
|
246
258
|
def init_hashes
|
247
259
|
@hash_tags = {}
|
248
|
-
@hash_tags[@
|
260
|
+
@hash_tags[@id] = self unless top?
|
249
261
|
@hash_tags = @nodes.reduce(@hash_tags) do |h,n|
|
250
262
|
h.merge(n.hash)
|
251
263
|
end
|
252
264
|
@hash_paths = {}
|
253
|
-
@hash_paths[@
|
265
|
+
@hash_paths[@id] = @path unless top?
|
254
266
|
@hash_paths = @nodes.reduce(@hash_paths) do |h,n|
|
255
267
|
h.merge(n.hash_paths)
|
256
268
|
end
|
@@ -266,9 +278,7 @@ module Eco
|
|
266
278
|
raise msg if !@enviro
|
267
279
|
@enviro.logger.warn(msg)
|
268
280
|
end
|
269
|
-
|
270
281
|
end
|
271
|
-
|
272
282
|
end
|
273
283
|
end
|
274
284
|
end
|
@@ -3,14 +3,41 @@ module Eco
|
|
3
3
|
class Session
|
4
4
|
class Config
|
5
5
|
class BaseConfig < Hash
|
6
|
-
|
7
6
|
attr_reader :config
|
8
7
|
|
8
|
+
class << self
|
9
|
+
def attr_key(*attrs)
|
10
|
+
attrs.each do |attr|
|
11
|
+
method = "#{attr}".freeze
|
12
|
+
if self.instance_methods.include?(method.to_sym)
|
13
|
+
puts "WARNING (#{self}): redefining method already defined '#{method}'."
|
14
|
+
end
|
15
|
+
|
16
|
+
define_method method do
|
17
|
+
self[method]
|
18
|
+
end
|
19
|
+
|
20
|
+
define_method "#{method}=" do |value|
|
21
|
+
self[method] = value
|
22
|
+
end
|
23
|
+
end
|
24
|
+
self
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
9
28
|
def initialize(config:)
|
10
29
|
super(nil)
|
11
30
|
@config = config
|
12
31
|
end
|
13
32
|
|
33
|
+
def file_manager
|
34
|
+
config.file_manager
|
35
|
+
end
|
36
|
+
|
37
|
+
def apis
|
38
|
+
config.apis
|
39
|
+
end
|
40
|
+
|
14
41
|
def clone(config:)
|
15
42
|
keys.each_with_object(self.class.new(config: config)) do |key, cnf|
|
16
43
|
begin
|
@@ -24,7 +51,6 @@ module Eco
|
|
24
51
|
end
|
25
52
|
end
|
26
53
|
end
|
27
|
-
|
28
54
|
end
|
29
55
|
end
|
30
56
|
end
|
@@ -24,13 +24,7 @@ module Eco
|
|
24
24
|
self["dir"]
|
25
25
|
end
|
26
26
|
|
27
|
-
|
28
|
-
self["timestamp_pattern"] = pattern
|
29
|
-
end
|
30
|
-
|
31
|
-
def timestamp_pattern
|
32
|
-
self["timestamp_pattern"]
|
33
|
-
end
|
27
|
+
attr_key :timestamp_pattern
|
34
28
|
|
35
29
|
def add_validation(format)
|
36
30
|
raise "Block must be given" unless block_given?
|
@@ -3,47 +3,12 @@ module Eco
|
|
3
3
|
class Session
|
4
4
|
class Config
|
5
5
|
class Logger < BaseConfig
|
6
|
-
|
7
|
-
|
8
|
-
self["console_level"] = value
|
9
|
-
end
|
10
|
-
|
11
|
-
def console_level
|
12
|
-
self["console_level"]
|
13
|
-
end
|
14
|
-
|
15
|
-
def file_level=(value)
|
16
|
-
self["file_level"] = value
|
17
|
-
end
|
18
|
-
|
19
|
-
def file_level
|
20
|
-
self["file_level"]
|
21
|
-
end
|
22
|
-
|
23
|
-
def file=(file)
|
24
|
-
self["file"] = file
|
25
|
-
end
|
26
|
-
|
27
|
-
def file
|
28
|
-
self["file"]
|
29
|
-
end
|
30
|
-
|
31
|
-
def timestamp_console=(value)
|
32
|
-
self["timestamp_console"] = value
|
33
|
-
end
|
34
|
-
|
35
|
-
def timestamp_console
|
36
|
-
self["timestamp_console"]
|
37
|
-
end
|
38
|
-
|
39
|
-
def log_connection=(value)
|
40
|
-
self["log_connection"] = !!value
|
41
|
-
end
|
6
|
+
attr_key :console_level, :file_level, :file
|
7
|
+
attr_key :timestamp_console, :log_connection
|
42
8
|
|
43
9
|
def log_connection?
|
44
|
-
|
10
|
+
!!log_connection
|
45
11
|
end
|
46
|
-
|
47
12
|
end
|
48
13
|
end
|
49
14
|
end
|
@@ -3,71 +3,14 @@ module Eco
|
|
3
3
|
class Session
|
4
4
|
class Config
|
5
5
|
class Mailer < BaseConfig
|
6
|
+
attr_key :access_key_id, :secret_access_key
|
7
|
+
attr_key :region, :server, :message_id_domain
|
8
|
+
attr_key :to, :from
|
6
9
|
|
7
10
|
def configured?
|
8
11
|
required = access_key_id && secret_access_key && region
|
9
12
|
!!required
|
10
13
|
end
|
11
|
-
|
12
|
-
def to=(value)
|
13
|
-
self["to"] = value
|
14
|
-
end
|
15
|
-
|
16
|
-
def to
|
17
|
-
self["to"]
|
18
|
-
end
|
19
|
-
|
20
|
-
def from=(value)
|
21
|
-
self["from"] = value
|
22
|
-
end
|
23
|
-
|
24
|
-
def from
|
25
|
-
self["from"]
|
26
|
-
end
|
27
|
-
|
28
|
-
def access_key_id=(key)
|
29
|
-
self["access_key_id"] = key
|
30
|
-
end
|
31
|
-
|
32
|
-
def access_key_id
|
33
|
-
self["access_key_id"]
|
34
|
-
end
|
35
|
-
|
36
|
-
def secret_access_key=(key)
|
37
|
-
self["secret_access_key"] = key
|
38
|
-
end
|
39
|
-
|
40
|
-
def secret_access_key
|
41
|
-
self["secret_access_key"]
|
42
|
-
end
|
43
|
-
|
44
|
-
# AWS::SES::Client
|
45
|
-
def region=(region)
|
46
|
-
self["region"] = region
|
47
|
-
end
|
48
|
-
|
49
|
-
def region
|
50
|
-
self["region"]
|
51
|
-
end
|
52
|
-
|
53
|
-
# AWS::SES::Base
|
54
|
-
def server=(domain)
|
55
|
-
self["server"] = domain
|
56
|
-
end
|
57
|
-
|
58
|
-
def server
|
59
|
-
self["server"]
|
60
|
-
end
|
61
|
-
|
62
|
-
# AWS::SES::Base
|
63
|
-
def message_id_domain=(domain)
|
64
|
-
self["message_id_domain"] = domain
|
65
|
-
end
|
66
|
-
|
67
|
-
def message_id_domain
|
68
|
-
self["message_id_domain"]
|
69
|
-
end
|
70
|
-
|
71
14
|
end
|
72
15
|
end
|
73
16
|
end
|
@@ -63,40 +63,19 @@ module Eco
|
|
63
63
|
end
|
64
64
|
|
65
65
|
# person model
|
66
|
-
|
67
|
-
self["default_usergroup"] = value
|
68
|
-
end
|
66
|
+
attr_key :default_usergroup, :default_schema, :default_login_method
|
69
67
|
|
70
|
-
def default_usergroup
|
71
|
-
self["default_usergroup"]
|
72
|
-
end
|
73
68
|
|
74
69
|
def default_usergroup?
|
75
|
-
!!
|
76
|
-
end
|
77
|
-
|
78
|
-
def default_schema=(name)
|
79
|
-
self["default_schema"] = name
|
80
|
-
end
|
81
|
-
|
82
|
-
def default_schema
|
83
|
-
self["default_schema"]
|
70
|
+
!!default_usergroup
|
84
71
|
end
|
85
72
|
|
86
73
|
def default_schema?
|
87
|
-
!!
|
88
|
-
end
|
89
|
-
|
90
|
-
def default_login_method=(name)
|
91
|
-
self["default_login_method"] = name
|
92
|
-
end
|
93
|
-
|
94
|
-
def default_login_method
|
95
|
-
self["default_login_method"]
|
74
|
+
!!default_schema
|
96
75
|
end
|
97
76
|
|
98
77
|
def default_login_method?
|
99
|
-
!!
|
78
|
+
!!default_login_method
|
100
79
|
end
|
101
80
|
|
102
81
|
# @return [Hash] with defined pairs format `key` and Person parsers.
|
@@ -116,7 +95,6 @@ module Eco
|
|
116
95
|
prs
|
117
96
|
end
|
118
97
|
end
|
119
|
-
|
120
98
|
end
|
121
99
|
end
|
122
100
|
end
|
@@ -3,52 +3,14 @@ module Eco
|
|
3
3
|
class Session
|
4
4
|
class Config
|
5
5
|
class S3Storage < BaseConfig
|
6
|
-
|
6
|
+
attr_key :bucket_name, :prefix, :region
|
7
|
+
attr_key :access_key_id, :secret_access_key
|
8
|
+
|
7
9
|
def configured?
|
8
10
|
required = bucket_name && prefix && access_key_id && secret_access_key && region
|
9
11
|
!!required
|
10
12
|
end
|
11
13
|
|
12
|
-
def bucket_name=(value)
|
13
|
-
self["bucket_name"] = value
|
14
|
-
end
|
15
|
-
|
16
|
-
def bucket_name
|
17
|
-
self["bucket_name"]
|
18
|
-
end
|
19
|
-
|
20
|
-
def prefix=(value)
|
21
|
-
self["prefix"] = value
|
22
|
-
end
|
23
|
-
|
24
|
-
def prefix
|
25
|
-
self["prefix"]
|
26
|
-
end
|
27
|
-
|
28
|
-
def access_key_id=(key)
|
29
|
-
self["access_key_id"] = key
|
30
|
-
end
|
31
|
-
|
32
|
-
def access_key_id
|
33
|
-
self["access_key_id"]
|
34
|
-
end
|
35
|
-
|
36
|
-
def secret_access_key=(key)
|
37
|
-
self["secret_access_key"] = key
|
38
|
-
end
|
39
|
-
|
40
|
-
def secret_access_key
|
41
|
-
self["secret_access_key"]
|
42
|
-
end
|
43
|
-
|
44
|
-
def region=(region)
|
45
|
-
self["region"] = region
|
46
|
-
end
|
47
|
-
|
48
|
-
def region
|
49
|
-
self["region"]
|
50
|
-
end
|
51
|
-
|
52
14
|
def target_files=(value)
|
53
15
|
self["target_files"] = [value].flatten
|
54
16
|
end
|
@@ -72,7 +34,6 @@ module Eco
|
|
72
34
|
def target_file_patterns
|
73
35
|
self["target_file_patterns"]
|
74
36
|
end
|
75
|
-
|
76
37
|
end
|
77
38
|
end
|
78
39
|
end
|
@@ -3,60 +3,15 @@ module Eco
|
|
3
3
|
class Session
|
4
4
|
class Config
|
5
5
|
class SFTP < BaseConfig
|
6
|
+
attr_key :host, :user
|
7
|
+
attr_key :password, :key_file
|
8
|
+
attr_key :base_path, :enviro_subpaths
|
6
9
|
|
7
10
|
def configured?
|
8
11
|
required = host && user && (key_file || password)
|
9
12
|
!!required
|
10
13
|
end
|
11
14
|
|
12
|
-
def host=(value)
|
13
|
-
self["host"] = value
|
14
|
-
end
|
15
|
-
|
16
|
-
def host
|
17
|
-
self["host"]
|
18
|
-
end
|
19
|
-
|
20
|
-
def user=(value)
|
21
|
-
self["user"] = value
|
22
|
-
end
|
23
|
-
|
24
|
-
def user
|
25
|
-
self["user"]
|
26
|
-
end
|
27
|
-
|
28
|
-
def password=(var)
|
29
|
-
self["password"] = var
|
30
|
-
end
|
31
|
-
|
32
|
-
def password
|
33
|
-
self["password"]
|
34
|
-
end
|
35
|
-
|
36
|
-
def key_file=(key)
|
37
|
-
self["key_file"] = key
|
38
|
-
end
|
39
|
-
|
40
|
-
def key_file
|
41
|
-
self["key_file"]
|
42
|
-
end
|
43
|
-
|
44
|
-
def base_path=(path)
|
45
|
-
self["base_path"] = path
|
46
|
-
end
|
47
|
-
|
48
|
-
def base_path
|
49
|
-
self["base_path"]
|
50
|
-
end
|
51
|
-
|
52
|
-
def enviro_subpaths=(hash)
|
53
|
-
self["enviro_subpaths"] = hash
|
54
|
-
end
|
55
|
-
|
56
|
-
def enviro_subpaths
|
57
|
-
self["enviro_subpaths"]
|
58
|
-
end
|
59
|
-
|
60
15
|
def enviro_subpath
|
61
16
|
enviro_subpaths[config.active_enviro]
|
62
17
|
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module Eco
|
2
|
+
module API
|
3
|
+
class Session
|
4
|
+
class Config
|
5
|
+
class TagTree < BaseConfig
|
6
|
+
attr_key :file
|
7
|
+
|
8
|
+
def scope_tree(enviro: nil)
|
9
|
+
return @tagtree if instance_variable_defined?(:@tagtree) && @tagtree.enviro == enviro
|
10
|
+
if tree_file = self.file
|
11
|
+
if (tree = file_manager.load_json(tree_file)) && !tree.empty?
|
12
|
+
@tagtree = Eco::API::Organization::TagTree.new(tree, enviro: enviro)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
@tagtree ||= live_tree(enviro: enviro)
|
16
|
+
end
|
17
|
+
|
18
|
+
# Among all the locations structures it selects the one with more location nodes
|
19
|
+
def live_tree(enviro: nil)
|
20
|
+
return @live_tree if instance_variable_defined?(:@live_tree) && @live_tree.enviro == enviro
|
21
|
+
trees = live_trees(enviro: enviro)
|
22
|
+
@live_tree = trees.reject do |tree|
|
23
|
+
tree.empty?
|
24
|
+
end.max {|a,b| a.count <=> b.count}
|
25
|
+
end
|
26
|
+
|
27
|
+
# Retrieves all the location structures of the organisation
|
28
|
+
def live_trees(enviro: nil)
|
29
|
+
[].tap do |trees|
|
30
|
+
next unless apis.active_api.version_available?(:graphql)
|
31
|
+
next unless graphql = apis.api(version: :graphql)
|
32
|
+
kargs = {
|
33
|
+
includeArchived: false,
|
34
|
+
includeUnpublished: false
|
35
|
+
}
|
36
|
+
next unless trees = graphql.currentOrganization.locationsStructures(**kargs)
|
37
|
+
trees.each do |tree|
|
38
|
+
args = { enviro: enviro, id: tree.id, name: tree.name}
|
39
|
+
eco_tree = Eco::API::Organization::TagTree.new(tree.treeify, **args)
|
40
|
+
trees.push(eco_tree)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -46,6 +46,12 @@ module Eco
|
|
46
46
|
def mailer
|
47
47
|
self["mailer"] ||= Eco::API::Session::Config::Mailer.new(config: self)
|
48
48
|
end
|
49
|
+
|
50
|
+
# Helper scope reporting structures.
|
51
|
+
# @return [Eco::API::Session::Config::TagTree]
|
52
|
+
def tagtree_config
|
53
|
+
org["tagtree_config"] ||= Eco::API::Session::Config::TagTree.new(config: self)
|
54
|
+
end
|
49
55
|
# @!endgroup
|
50
56
|
|
51
57
|
# @!group Logger
|
@@ -225,35 +231,20 @@ module Eco
|
|
225
231
|
end
|
226
232
|
|
227
233
|
def tagtree=(file)
|
228
|
-
|
234
|
+
tagtree_config.file = file
|
229
235
|
end
|
230
236
|
|
231
|
-
# It uses the `tagtree.json` file and in its absence, if `graphql` enabled, the `life_tagtree`
|
237
|
+
# It uses the `tagtree.json` file and in its absence, if `graphql` enabled, the largest `life_tagtree`
|
232
238
|
# @return [Eco::API::Organization::TagTree]
|
233
239
|
def tagtree(enviro: nil)
|
234
|
-
|
235
|
-
if tree_file = org["tagtree"]
|
236
|
-
tree = []
|
237
|
-
tree = file_manager.load_json(tree_file) unless !tree_file
|
238
|
-
@tagtree = Eco::API::Organization::TagTree.new(tree, enviro: enviro)
|
239
|
-
else
|
240
|
-
@tagtree = live_tree(enviro: enviro)
|
241
|
-
end
|
240
|
+
@tagtree ||= tagtree_config.scope_tree(enviro: enviro)
|
242
241
|
end
|
243
242
|
|
244
243
|
# It obtains the first of the live tagtree in the org
|
245
244
|
# @note it requires graphql connection configuration parameters
|
246
245
|
# @return [Eco::API::Organization::TagTree]
|
247
246
|
def live_tree(enviro: nil)
|
248
|
-
|
249
|
-
if apis.active_api.version_available?(:graphql)
|
250
|
-
graphql = apis.api(version: :graphql)
|
251
|
-
if tree = graphql.currentOrganization.tagTrees.to_a.first.treeify
|
252
|
-
@live_tree = Eco::API::Organization::TagTree.new(tree, enviro: enviro)
|
253
|
-
else
|
254
|
-
@live_tree = nil
|
255
|
-
end
|
256
|
-
end
|
247
|
+
@live_tree ||= tagtree_config.live_tree(enviro: enviro)
|
257
248
|
end
|
258
249
|
|
259
250
|
# @return [Eco::API::Organization::PolicyGroups]
|
@@ -415,5 +406,6 @@ require_relative 'config/sftp'
|
|
415
406
|
require_relative 'config/s3_storage'
|
416
407
|
require_relative 'config/files'
|
417
408
|
require_relative 'config/people'
|
409
|
+
require_relative 'config/tagtree'
|
418
410
|
require_relative 'config/post_launch'
|
419
411
|
require_relative 'config/workflow'
|
@@ -0,0 +1,90 @@
|
|
1
|
+
class Eco::API::UseCases::DefaultCases::CsvToTree
|
2
|
+
module Helper
|
3
|
+
extend NodesCleaner
|
4
|
+
extend Treeify
|
5
|
+
|
6
|
+
class << self
|
7
|
+
def csv_from(filename)
|
8
|
+
raise "Missing #{filename}" unless File.exists?(filename)
|
9
|
+
result = csv_from_file(filename)
|
10
|
+
if result.is_a?(Integer)
|
11
|
+
puts "An encoding problem was found on line #{result}"
|
12
|
+
result = csv_from_content(filename)
|
13
|
+
end
|
14
|
+
result
|
15
|
+
end
|
16
|
+
|
17
|
+
def csv_nodes(filename)
|
18
|
+
i = 1; prev_level = nil; prev_node = nil; prev_nodes = Array(1..11).zip(Array.new(11, nil)).to_h
|
19
|
+
nodes = csv_from(filename).each_with_object([]) do |row, out|
|
20
|
+
values = row.fields.map do |value|
|
21
|
+
value = value.to_s.strip
|
22
|
+
value.empty?? nil : value
|
23
|
+
end
|
24
|
+
i += 1
|
25
|
+
node = Node.new(i, *values)
|
26
|
+
prev_node ||= node
|
27
|
+
|
28
|
+
if prev_node.raw_level <= node.raw_level
|
29
|
+
node.set_high_levels(prev_node)
|
30
|
+
else
|
31
|
+
if parent_node = prev_nodes[node.raw_level - 1]
|
32
|
+
node.set_high_levels(parent_node)
|
33
|
+
else
|
34
|
+
raise "Node '#{node.raw_tag}' (#{node.row_num} row) doesn't have parent"
|
35
|
+
end
|
36
|
+
end
|
37
|
+
out << node
|
38
|
+
prev_nodes[node.raw_level] = node
|
39
|
+
prev_node = node
|
40
|
+
end
|
41
|
+
tidy_nodes(nodes)
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
|
46
|
+
def csv_from_content(filename)
|
47
|
+
CSV.parse(file_content(filename), headers: true)
|
48
|
+
end
|
49
|
+
|
50
|
+
def file_content(filename)
|
51
|
+
coding = encoding(filename)
|
52
|
+
coding = (coding != "utf-8")? "#{coding}|utf-8": coding
|
53
|
+
if content = File.read(filename, encoding: coding)
|
54
|
+
content.scrub do |bytes|
|
55
|
+
'<' + bytes.unpack('H*')[0] + '>'
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def csv_from_file(filename)
|
61
|
+
coding = encoding(filename)
|
62
|
+
coding = (coding != "utf-8")? "#{coding}|utf-8": coding
|
63
|
+
CSV.read(filename, headers: true, encoding: coding)
|
64
|
+
rescue CSV::MalformedCSVError => e
|
65
|
+
if line = e.message.match(/line (?<line>\d+)/i)[:line]
|
66
|
+
return line.to_i
|
67
|
+
else
|
68
|
+
raise
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def has_bom?(path)
|
73
|
+
return false if !path || file_empty?(path)
|
74
|
+
File.open(path, "rb") do |f|
|
75
|
+
bytes = f.read(3)
|
76
|
+
return bytes.unpack("C*") == [239, 187, 191]
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def encoding(path)
|
81
|
+
has_bom?(path) ? "bom" : "utf-8"
|
82
|
+
end
|
83
|
+
|
84
|
+
def file_empty?(path)
|
85
|
+
return true if !File.file?(path)
|
86
|
+
File.zero?(path)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
@@ -0,0 +1,206 @@
|
|
1
|
+
class Eco::API::UseCases::DefaultCases::CsvToTree
|
2
|
+
class Node < Struct.new(:row_num, :l1, :l2, :l3, :l4, :l5, :l6, :l7, :l8, :l9, :l10, :l11)
|
3
|
+
TAGS_ATTRS = [:l1, :l2, :l3, :l4, :l5, :l6, :l7, :l8, :l9, :l10, :l11]
|
4
|
+
ADDITIONAL_ATTRS = [:row_num]
|
5
|
+
ALL_ATTRS = ADDITIONAL_ATTRS + TAGS_ATTRS
|
6
|
+
ALLOWED_CHARACTERS = "A-Za-z0-9 &_'\/.-"
|
7
|
+
VALID_TAG_REGEX = /^[#{ALLOWED_CHARACTERS}]+$/
|
8
|
+
INVALID_TAG_REGEX = /[^#{ALLOWED_CHARACTERS}]+/
|
9
|
+
VALID_TAG_CHARS = /[#{ALLOWED_CHARACTERS}]+/
|
10
|
+
DOUBLE_BLANKS = /\s\s+/
|
11
|
+
|
12
|
+
attr_accessor :parentId
|
13
|
+
|
14
|
+
def nodeId
|
15
|
+
id
|
16
|
+
end
|
17
|
+
|
18
|
+
def id
|
19
|
+
tag.upcase
|
20
|
+
end
|
21
|
+
|
22
|
+
def name
|
23
|
+
tag
|
24
|
+
end
|
25
|
+
|
26
|
+
def tag
|
27
|
+
raw_tag.yield_self do |str|
|
28
|
+
partial = replace_not_allowed(str)
|
29
|
+
remove_double_blanks(partial).tap do |result|
|
30
|
+
if partial != str
|
31
|
+
invalid_chars = identify_invalid_characters(str)
|
32
|
+
puts "• (Row: #{self.row_num}) Invalid characters _#{invalid_chars}_ (removed): '#{str}' (converted to '#{result}')"
|
33
|
+
end
|
34
|
+
if result != partial
|
35
|
+
#puts "• There were DOUBLE BLANKS: tag '#{str}' (converted to '#{result}')"
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def raw_tag
|
42
|
+
values_at(*TAGS_ATTRS.reverse).compact.first
|
43
|
+
end
|
44
|
+
|
45
|
+
def level
|
46
|
+
actual_level
|
47
|
+
end
|
48
|
+
|
49
|
+
def actual_level
|
50
|
+
tags_array.compact.length
|
51
|
+
end
|
52
|
+
|
53
|
+
def raw_level
|
54
|
+
tags_array.index(raw_tag) + 1
|
55
|
+
end
|
56
|
+
|
57
|
+
def tag_idx
|
58
|
+
tags_array.index(raw_tag)
|
59
|
+
end
|
60
|
+
|
61
|
+
def previous_idx
|
62
|
+
idx = tag_idx - 1
|
63
|
+
idx < 0 ? nil : idx
|
64
|
+
end
|
65
|
+
|
66
|
+
def empty_idx
|
67
|
+
tary = tags_array
|
68
|
+
tary.index(nil) || tary.length + 1
|
69
|
+
end
|
70
|
+
|
71
|
+
def copy
|
72
|
+
self.class.new.set_attrs(**self.to_h)
|
73
|
+
end
|
74
|
+
|
75
|
+
# We got a missing level that is compacted in one row
|
76
|
+
# Here we get the missing intermediate levels
|
77
|
+
# This is done from upper to lower level to ensure processing order
|
78
|
+
# It skips last one, as that is this object already
|
79
|
+
def decouple(num = 1)
|
80
|
+
with_info = filled_idxs
|
81
|
+
# must be the last among filled_idxs, so let's use it to verify
|
82
|
+
unless with_info.last == tag_idx
|
83
|
+
raise "Review this (row #{row_num}; '#{raw_tag}'): tag_idx is #{tag_idx}, while last filled idx is #{with_info.last}"
|
84
|
+
end
|
85
|
+
len = with_info.length
|
86
|
+
target_idxs = with_info[len-(num+1)..-2]
|
87
|
+
target_idxs.map do |idx|
|
88
|
+
self.copy.tap do |dup|
|
89
|
+
dup.clear_level(idx_to_level(idx + 1))
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
def merge!(node)
|
95
|
+
override_upper_levels(node.tags_array)
|
96
|
+
end
|
97
|
+
|
98
|
+
def set_high_levels(node)
|
99
|
+
override_lower_levels(node.tags_array)
|
100
|
+
end
|
101
|
+
|
102
|
+
def clear_level(i)
|
103
|
+
case i
|
104
|
+
when Enumerable
|
105
|
+
target = i.to_a
|
106
|
+
when Integer
|
107
|
+
return false unless i >= 1 && i <= tag_attrs_count
|
108
|
+
target = Array(i..tag_attrs_count)
|
109
|
+
else
|
110
|
+
return false
|
111
|
+
end
|
112
|
+
return false if target.empty?
|
113
|
+
target.each do |n|
|
114
|
+
#puts "clearing 'l#{n}': #{attr("l#{n}")}"
|
115
|
+
set_attr("l#{n}", nil)
|
116
|
+
end
|
117
|
+
true
|
118
|
+
end
|
119
|
+
|
120
|
+
def override_upper_levels(src_tags_array, from_level: self.raw_level + 1)
|
121
|
+
target_lev = Array(from_level..tag_attrs_count)
|
122
|
+
target_tags = src_tags_array[level_to_idx(from_level)..level_to_idx(tag_attrs_count)]
|
123
|
+
target_lev.zip(target_tags).each do |(n, tag)|
|
124
|
+
set_attr("l#{n}", tag)
|
125
|
+
end
|
126
|
+
self
|
127
|
+
end
|
128
|
+
|
129
|
+
def override_lower_levels(src_tags_array, to_level: self.raw_level - 1)
|
130
|
+
target_lev = Array(1..to_level)
|
131
|
+
target_tags = src_tags_array[level_to_idx(1)..level_to_idx(to_level)]
|
132
|
+
target_lev.zip(target_tags).each do |(n, tag)|
|
133
|
+
set_attr("l#{n}", tag)
|
134
|
+
end
|
135
|
+
self
|
136
|
+
end
|
137
|
+
|
138
|
+
def idx_to_level(x)
|
139
|
+
x + 1
|
140
|
+
end
|
141
|
+
|
142
|
+
def level_to_idx(x)
|
143
|
+
x - 1
|
144
|
+
end
|
145
|
+
|
146
|
+
def filled_idxs
|
147
|
+
tags_array.each_with_index.with_object([]) do |(t, i), o|
|
148
|
+
o << i if t
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
def blanks_between?
|
153
|
+
actual_level > empty_idx
|
154
|
+
end
|
155
|
+
|
156
|
+
def tags_array
|
157
|
+
values_at(*TAGS_ATTRS)
|
158
|
+
end
|
159
|
+
|
160
|
+
def values_at(*attrs)
|
161
|
+
attrs.map {|a| attr(a)}
|
162
|
+
end
|
163
|
+
|
164
|
+
def to_h(*attrs)
|
165
|
+
attrs = ALL_ATTRS if attrs.empty?
|
166
|
+
ALL_ATTRS.zip(values_at(*ALL_ATTRS)).to_h
|
167
|
+
end
|
168
|
+
|
169
|
+
def slice(*attrs)
|
170
|
+
return {} if attrs.empty?
|
171
|
+
to_h(*attrs)
|
172
|
+
end
|
173
|
+
|
174
|
+
def set_attrs(**kargs)
|
175
|
+
kargs.each {|attr, value| set_attr(attr, value)}
|
176
|
+
self
|
177
|
+
end
|
178
|
+
|
179
|
+
def set_attr(attr, value)
|
180
|
+
self.send("#{attr}=", value)
|
181
|
+
end
|
182
|
+
|
183
|
+
def attr(sym)
|
184
|
+
self.send(sym.to_sym)
|
185
|
+
end
|
186
|
+
|
187
|
+
def tag_attrs_count
|
188
|
+
TAGS_ATTRS.length
|
189
|
+
end
|
190
|
+
|
191
|
+
def remove_double_blanks(str)
|
192
|
+
return nil if str.nil?
|
193
|
+
str.gsub(DOUBLE_BLANKS, ' ').strip
|
194
|
+
end
|
195
|
+
|
196
|
+
def replace_not_allowed(str)
|
197
|
+
return nil if str.nil?
|
198
|
+
return str if str.match(VALID_TAG_REGEX)
|
199
|
+
str.gsub(INVALID_TAG_REGEX, ' ')
|
200
|
+
end
|
201
|
+
|
202
|
+
def identify_invalid_characters(str)
|
203
|
+
str.gsub(VALID_TAG_CHARS, '')
|
204
|
+
end
|
205
|
+
end
|
206
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
class Eco::API::UseCases::DefaultCases::CsvToTree
|
2
|
+
module NodesCleaner
|
3
|
+
def repeated_tags
|
4
|
+
@repeated_tags ||= []
|
5
|
+
end
|
6
|
+
|
7
|
+
def done_tags
|
8
|
+
@done_tags ||= []
|
9
|
+
end
|
10
|
+
|
11
|
+
def fill_in_parents(nodes)
|
12
|
+
nodes.tap do |nodes|
|
13
|
+
prev_nodes = Array(1..11).zip(Array.new(11, nil)).to_h
|
14
|
+
nodes.each do |node|
|
15
|
+
if parent_node = prev_nodes[node.raw_level - 1]
|
16
|
+
node.parentId = parent_node.id
|
17
|
+
end
|
18
|
+
prev_nodes[node.raw_level] = node
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def tidy_nodes(nodes, prev_level: 0, main: true)
|
24
|
+
out = nodes.each_with_object([]) do |node, out|
|
25
|
+
if done_tags.include?(tag = node.tag)
|
26
|
+
repeated_tags << "#{tag} (level: #{node.level})"
|
27
|
+
else
|
28
|
+
level = node.actual_level
|
29
|
+
if level > prev_level + 1
|
30
|
+
gap = level - (prev_level + 1)
|
31
|
+
puts "(Row: #{node.row_num}) Tag '#{tag}' (lev #{level}) jumps #{gap} level(s) (expected #{prev_level + 1})."
|
32
|
+
#puts " " + node.tags_array.pretty_inspect
|
33
|
+
missing_nodes = node.decouple(gap)
|
34
|
+
puts " Adding missing upper level(s): " + missing_nodes.map(&:raw_tag).pretty_inspect
|
35
|
+
out.push(*tidy_nodes(missing_nodes, prev_level: prev_level, main: false))
|
36
|
+
# puts node.actual_level
|
37
|
+
# pp node.tags_array
|
38
|
+
level = prev_level + 1
|
39
|
+
end
|
40
|
+
out << node
|
41
|
+
done_tags << tag
|
42
|
+
prev_level = level
|
43
|
+
end
|
44
|
+
end
|
45
|
+
if main
|
46
|
+
unless repeated_tags.empty?
|
47
|
+
puts "There were #{repeated_tags.length} repeated tags. Only one included. These excluded:"
|
48
|
+
pp repeated_tags
|
49
|
+
end
|
50
|
+
end
|
51
|
+
fill_in_parents(out)
|
52
|
+
end
|
53
|
+
|
54
|
+
def to_rows(nodes, prev_level: 0, main: true)
|
55
|
+
out = tidy_nodes(nodes).each_with_object([]) do |node, out|
|
56
|
+
tag = node.tag
|
57
|
+
level = node.actual_level
|
58
|
+
out << (row = Array.new(level, nil))
|
59
|
+
row[-1..-1] = [tag.upcase]
|
60
|
+
prev_level = level
|
61
|
+
end
|
62
|
+
if main
|
63
|
+
# Normalize length
|
64
|
+
max_row = out.max {|a, b| a.length <=> b.length}
|
65
|
+
holder = Array.new(max_row.length, nil)
|
66
|
+
out = out.map do |row|
|
67
|
+
row.dup.concat(holder)[0..max_row.length-1]
|
68
|
+
end
|
69
|
+
end
|
70
|
+
out
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
class Eco::API::UseCases::DefaultCases::CsvToTree
|
2
|
+
module Treeify
|
3
|
+
def treeify(nodes, &block)
|
4
|
+
get_children(nil, parents_hash(nodes), &block)
|
5
|
+
end
|
6
|
+
|
7
|
+
private
|
8
|
+
|
9
|
+
def parents_hash(nodes)
|
10
|
+
nodes.each_with_object({}) do |node, parents|
|
11
|
+
(parents[node.parentId] ||= []).push(node)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def get_children(node_id, parents, &block)
|
16
|
+
(parents[node_id] ||= []).each_with_object([]) do |child, results|
|
17
|
+
node_hash = {
|
18
|
+
"id" => child.id,
|
19
|
+
"name" => child.name
|
20
|
+
}
|
21
|
+
|
22
|
+
if block_given?
|
23
|
+
yield_hash = yield(child)
|
24
|
+
node_hash.merge(yield_hash) if yield_hash.is_a?(Hash)
|
25
|
+
end
|
26
|
+
|
27
|
+
results << node_hash.merge({
|
28
|
+
"nodes" => get_children(child.id, parents, &block).compact
|
29
|
+
})
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
class Eco::API::UseCases::DefaultCases::CsvToTree < Eco::API::Common::Loaders::UseCase
|
2
|
+
name "csv-to-tree"
|
3
|
+
type :other
|
4
|
+
|
5
|
+
TIME_FORMAT = '%Y%m%dT%H%M%S'
|
6
|
+
|
7
|
+
attr_reader :session, :options
|
8
|
+
|
9
|
+
def main(session, options, usecase)
|
10
|
+
options[:end_get] = false
|
11
|
+
@session = session; @options = options
|
12
|
+
|
13
|
+
tree_struct = Helper.treeify(Helper.csv_nodes(input_file))
|
14
|
+
|
15
|
+
File.open(output_file, "w") do |fd|
|
16
|
+
json = tree_struct.to_json
|
17
|
+
fd << json
|
18
|
+
end
|
19
|
+
logger.info("Saved structure in '#{output_file}'")
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def input_file
|
25
|
+
@input_file ||= options.dig(:source, :file)
|
26
|
+
end
|
27
|
+
|
28
|
+
def output_file
|
29
|
+
@output_file ||= "#{active_enviro}_tree_#{timestamp}.json"
|
30
|
+
end
|
31
|
+
|
32
|
+
def timestamp(date = Time.now)
|
33
|
+
date.strftime(TIME_FORMAT)
|
34
|
+
end
|
35
|
+
|
36
|
+
def active_enviro
|
37
|
+
config.active_enviro
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
require_relative 'csv_to_tree_case/node'
|
42
|
+
require_relative 'csv_to_tree_case/nodes_cleaner'
|
43
|
+
require_relative 'csv_to_tree_case/treeify'
|
44
|
+
require_relative 'csv_to_tree_case/helper'
|
@@ -22,6 +22,7 @@ require_relative 'default_cases/create_case'
|
|
22
22
|
require_relative 'default_cases/create_details_case'
|
23
23
|
require_relative 'default_cases/create_details_with_supervisor_case'
|
24
24
|
require_relative 'default_cases/create_tag_paths_case'
|
25
|
+
require_relative 'default_cases/csv_to_tree_case'
|
25
26
|
require_relative 'default_cases/delete_trans_case'
|
26
27
|
require_relative 'default_cases/delete_sync_case'
|
27
28
|
require_relative 'default_cases/email_as_id_case'
|
@@ -71,7 +71,7 @@ class Eco::API::UseCases::OozeSamples
|
|
71
71
|
return src_fld, dst_fld if dst_flds.empty? || src_flds.empty?
|
72
72
|
|
73
73
|
if dst_flds.count > 1
|
74
|
-
logger.warn("There are #{dst_flds.count} destination '#{type}' fields named '#{label_dst}' (source: '#{
|
74
|
+
logger.warn("There are #{dst_flds.count} destination '#{type}' fields named '#{label_dst}' (source: '#{dst.id}'). Using first...")
|
75
75
|
end
|
76
76
|
|
77
77
|
if src_flds.count > 1
|
@@ -98,6 +98,12 @@ ASSETS.cli.config do |cnf|
|
|
98
98
|
desc = "Creates a CSV with the paths to each tag"
|
99
99
|
cases.add("-create-tag-paths", :other, desc, case_name: "create-tag-paths")
|
100
100
|
|
101
|
+
desc = "Creates a JSON file with the tagtree from a CSV file"
|
102
|
+
cases.add("-csv-to-tree", :other, desc, case_name: "csv-to-tree") do |session, options, usecase|
|
103
|
+
file = SCR.get_file("-csv-to-tree", required: true, should_exist: true)
|
104
|
+
options.deep_merge!(source: {file: file})
|
105
|
+
end
|
106
|
+
|
101
107
|
desc = "Cleans from filter_tags those tags that are not present in the tagtree (as per tagtree.json file)."
|
102
108
|
desc += " It will preserve standard register tags of most common registers (i.e. EVENT, RISK)."
|
103
109
|
cases.add("-clean-unknown-tags", :transform, desc, case_name: "clean-unknown-tags")
|
data/lib/eco/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: eco-helpers
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.1
|
4
|
+
version: 2.2.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Oscar Segura
|
@@ -136,40 +136,40 @@ dependencies:
|
|
136
136
|
requirements:
|
137
137
|
- - ">="
|
138
138
|
- !ruby/object:Gem::Version
|
139
|
-
version: 0.
|
139
|
+
version: 1.0.1
|
140
140
|
- - "<"
|
141
141
|
- !ruby/object:Gem::Version
|
142
|
-
version: '
|
142
|
+
version: '1.1'
|
143
143
|
type: :runtime
|
144
144
|
prerelease: false
|
145
145
|
version_requirements: !ruby/object:Gem::Requirement
|
146
146
|
requirements:
|
147
147
|
- - ">="
|
148
148
|
- !ruby/object:Gem::Version
|
149
|
-
version: 0.
|
149
|
+
version: 1.0.1
|
150
150
|
- - "<"
|
151
151
|
- !ruby/object:Gem::Version
|
152
|
-
version: '
|
152
|
+
version: '1.1'
|
153
153
|
- !ruby/object:Gem::Dependency
|
154
154
|
name: ecoportal-api-graphql
|
155
155
|
requirement: !ruby/object:Gem::Requirement
|
156
156
|
requirements:
|
157
157
|
- - ">="
|
158
158
|
- !ruby/object:Gem::Version
|
159
|
-
version: 0.
|
159
|
+
version: 0.2.2
|
160
160
|
- - "<"
|
161
161
|
- !ruby/object:Gem::Version
|
162
|
-
version: '0.
|
162
|
+
version: '0.3'
|
163
163
|
type: :runtime
|
164
164
|
prerelease: false
|
165
165
|
version_requirements: !ruby/object:Gem::Requirement
|
166
166
|
requirements:
|
167
167
|
- - ">="
|
168
168
|
- !ruby/object:Gem::Version
|
169
|
-
version: 0.
|
169
|
+
version: 0.2.2
|
170
170
|
- - "<"
|
171
171
|
- !ruby/object:Gem::Version
|
172
|
-
version: '0.
|
172
|
+
version: '0.3'
|
173
173
|
- !ruby/object:Gem::Dependency
|
174
174
|
name: aws-sdk-s3
|
175
175
|
requirement: !ruby/object:Gem::Requirement
|
@@ -540,6 +540,7 @@ files:
|
|
540
540
|
- lib/eco/api/session/config/post_launch.rb
|
541
541
|
- lib/eco/api/session/config/s3_storage.rb
|
542
542
|
- lib/eco/api/session/config/sftp.rb
|
543
|
+
- lib/eco/api/session/config/tagtree.rb
|
543
544
|
- lib/eco/api/session/config/workflow.rb
|
544
545
|
- lib/eco/api/usecases.rb
|
545
546
|
- lib/eco/api/usecases/base_case.rb
|
@@ -556,6 +557,11 @@ files:
|
|
556
557
|
- lib/eco/api/usecases/default_cases/create_details_case.rb
|
557
558
|
- lib/eco/api/usecases/default_cases/create_details_with_supervisor_case.rb
|
558
559
|
- lib/eco/api/usecases/default_cases/create_tag_paths_case.rb
|
560
|
+
- lib/eco/api/usecases/default_cases/csv_to_tree_case.rb
|
561
|
+
- lib/eco/api/usecases/default_cases/csv_to_tree_case/helper.rb
|
562
|
+
- lib/eco/api/usecases/default_cases/csv_to_tree_case/node.rb
|
563
|
+
- lib/eco/api/usecases/default_cases/csv_to_tree_case/nodes_cleaner.rb
|
564
|
+
- lib/eco/api/usecases/default_cases/csv_to_tree_case/treeify.rb
|
559
565
|
- lib/eco/api/usecases/default_cases/delete_sync_case.rb
|
560
566
|
- lib/eco/api/usecases/default_cases/delete_trans_case.rb
|
561
567
|
- lib/eco/api/usecases/default_cases/email_as_id_case.rb
|