checkoff 0.193.0 → 0.195.0
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/Gemfile.lock +4 -4
- data/lib/checkoff/internal/asana_event_enrichment.rb +11 -32
- data/lib/checkoff/projects.rb +39 -11
- data/lib/checkoff/resources.rb +131 -0
- data/lib/checkoff/sections.rb +4 -6
- data/lib/checkoff/subtasks.rb +3 -6
- data/lib/checkoff/tags.rb +2 -7
- data/lib/checkoff/task_searches.rb +2 -4
- data/lib/checkoff/tasks.rb +5 -3
- data/lib/checkoff/version.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c777dc82cc51fd0ec445c1413fc6f33ed37e98b8a41026446cec61f800ec0417
|
4
|
+
data.tar.gz: bb7edb3ed4eb31a171cd4204a338ea56b6097a4cee8bf299e451ee7ecf342e59
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 794bf6eba0270a4cb002421f2e0857b20268d348bec359dc5d1363f345a60f385d1dea1cf26f0530cabd015e1f06b4b037ca54b342174ac5415c1f93eed3afa7
|
7
|
+
data.tar.gz: c9263dd810014f080b6d52c6954dd86aca9f837b88e10c711be154c49f7652cdba92303d462bee08a1c25a2f34b3ef3b85a14557410892c052916ea82a7eb098
|
data/Gemfile.lock
CHANGED
@@ -12,7 +12,7 @@ GIT
|
|
12
12
|
PATH
|
13
13
|
remote: .
|
14
14
|
specs:
|
15
|
-
checkoff (0.
|
15
|
+
checkoff (0.195.0)
|
16
16
|
activesupport
|
17
17
|
asana (> 0.10.0)
|
18
18
|
cache_method
|
@@ -130,11 +130,11 @@ GEM
|
|
130
130
|
multi_xml (0.6.0)
|
131
131
|
multipart-post (2.3.0)
|
132
132
|
mutex_m (0.2.0)
|
133
|
-
nokogiri (1.
|
133
|
+
nokogiri (1.16.2-arm64-darwin)
|
134
134
|
racc (~> 1.4)
|
135
|
-
nokogiri (1.
|
135
|
+
nokogiri (1.16.2-x86_64-darwin)
|
136
136
|
racc (~> 1.4)
|
137
|
-
nokogiri (1.
|
137
|
+
nokogiri (1.16.2-x86_64-linux)
|
138
138
|
racc (~> 1.4)
|
139
139
|
oauth2 (1.4.11)
|
140
140
|
faraday (>= 0.17.3, < 3.0)
|
@@ -18,6 +18,7 @@ module Checkoff
|
|
18
18
|
# @param tasks [Checkoff::Tasks]
|
19
19
|
# @param sections [Checkoff::Sections]
|
20
20
|
# @param projects [Checkoff::Projects]
|
21
|
+
# @param resources [Checkoff::Resources]
|
21
22
|
# @param clients [Checkoff::Clients]
|
22
23
|
# @param client [Asana::Client]
|
23
24
|
# @param asana_event_enrichment [Checkoff::Internal::AsanaEventEnrichment]
|
@@ -26,12 +27,14 @@ module Checkoff
|
|
26
27
|
tasks: Checkoff::Tasks.new(config: config),
|
27
28
|
sections: Checkoff::Sections.new(config: config),
|
28
29
|
projects: Checkoff::Projects.new(config: config),
|
30
|
+
resources: Checkoff::Resources.new(config: config),
|
29
31
|
clients: Checkoff::Clients.new(config: config),
|
30
32
|
client: clients.client)
|
31
33
|
@workspaces = workspaces
|
32
34
|
@tasks = tasks
|
33
35
|
@sections = sections
|
34
36
|
@projects = projects
|
37
|
+
@resources = resources
|
35
38
|
@client = client
|
36
39
|
end
|
37
40
|
|
@@ -86,13 +89,9 @@ module Checkoff
|
|
86
89
|
#
|
87
90
|
# @return [Array<([String, nil], [String,nil])>]
|
88
91
|
def enrich_gid(gid, resource_type: nil)
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
name = method(:"enrich_#{resource_type_to_try}_gid").call(gid)
|
93
|
-
return [name, resource_type_to_try] if name
|
94
|
-
end
|
95
|
-
[nil, nil]
|
92
|
+
# @sg-ignore
|
93
|
+
resource, resource_type = resources.resource_by_gid(gid, resource_type: resource_type)
|
94
|
+
[resource&.name, resource_type]
|
96
95
|
end
|
97
96
|
|
98
97
|
# @param filter [Hash{String => String}]
|
@@ -108,30 +107,6 @@ module Checkoff
|
|
108
107
|
filter['checkoff:enriched:parent.resource_type'] = resource_type if resource_type
|
109
108
|
end
|
110
109
|
|
111
|
-
# @param gid [String]
|
112
|
-
#
|
113
|
-
# @return [String, nil]
|
114
|
-
def enrich_task_gid(gid)
|
115
|
-
task = tasks.task_by_gid(gid, only_uncompleted: false)
|
116
|
-
task&.name
|
117
|
-
end
|
118
|
-
|
119
|
-
# @param section_gid [String]
|
120
|
-
#
|
121
|
-
# @return [String, nil]
|
122
|
-
def enrich_section_gid(section_gid)
|
123
|
-
section = sections.section_by_gid(section_gid)
|
124
|
-
section&.name
|
125
|
-
end
|
126
|
-
|
127
|
-
# @param project_gid [String]
|
128
|
-
#
|
129
|
-
# @return [String, nil]
|
130
|
-
def enrich_project_gid(project_gid)
|
131
|
-
project = projects.project_by_gid(project_gid)
|
132
|
-
project&.name
|
133
|
-
end
|
134
|
-
|
135
110
|
# @param filter [Hash{String => String}]
|
136
111
|
#
|
137
112
|
# @return [void]
|
@@ -151,7 +126,8 @@ module Checkoff
|
|
151
126
|
section_gid = filter['checkoff:fetched.section.gid']
|
152
127
|
return unless section_gid
|
153
128
|
|
154
|
-
|
129
|
+
section = sections.section_by_gid(section_gid)
|
130
|
+
name = section&.name
|
155
131
|
filter['checkoff:enriched:fetched.section.name'] = name if name
|
156
132
|
end
|
157
133
|
|
@@ -208,6 +184,9 @@ module Checkoff
|
|
208
184
|
# @return [Checkoff::Workspaces]
|
209
185
|
attr_reader :workspaces
|
210
186
|
|
187
|
+
# @return [Checkoff::Resources]
|
188
|
+
attr_reader :resources
|
189
|
+
|
211
190
|
# @return [Asana::Client]
|
212
191
|
attr_reader :client
|
213
192
|
end
|
data/lib/checkoff/projects.rb
CHANGED
@@ -52,17 +52,46 @@ module Checkoff
|
|
52
52
|
@timing = timing
|
53
53
|
end
|
54
54
|
|
55
|
+
# @param extra_fields [Array<String>]
|
56
|
+
#
|
57
|
+
# @return [Array<String>]
|
58
|
+
def task_fields(extra_fields: [])
|
59
|
+
(%w[name completed_at start_at start_on due_at due_on tags
|
60
|
+
memberships.project.gid memberships.project.name
|
61
|
+
memberships.section.name dependencies] + extra_fields).sort.uniq
|
62
|
+
end
|
63
|
+
|
55
64
|
# Default options used in Asana API to pull tasks
|
65
|
+
#
|
66
|
+
# @param extra_fields [Array<String>]
|
67
|
+
# @param [Boolean] only_uncompleted
|
68
|
+
#
|
56
69
|
# @return [Hash<Symbol, Object>]
|
57
|
-
def task_options
|
58
|
-
{
|
70
|
+
def task_options(extra_fields: [], only_uncompleted: false)
|
71
|
+
options = {
|
59
72
|
per_page: 100,
|
60
73
|
options: {
|
61
|
-
fields:
|
62
|
-
memberships.project.gid memberships.project.name
|
63
|
-
memberships.section.name dependencies],
|
74
|
+
fields: task_fields(extra_fields: extra_fields),
|
64
75
|
},
|
65
76
|
}
|
77
|
+
options[:completed_since] = '9999-12-01' if only_uncompleted
|
78
|
+
options
|
79
|
+
end
|
80
|
+
|
81
|
+
# @param extra_project_fields [Array<String>]
|
82
|
+
#
|
83
|
+
# @return [Array<String>]
|
84
|
+
def project_fields(extra_project_fields: [])
|
85
|
+
(%w[name custom_fields] + extra_project_fields).sort.uniq
|
86
|
+
end
|
87
|
+
|
88
|
+
# Default options used in Asana API to pull projects
|
89
|
+
#
|
90
|
+
# @param extra_project_fields [Array<String>]
|
91
|
+
#
|
92
|
+
# @return [Hash<Symbol, Object>]
|
93
|
+
def project_options(extra_project_fields: [])
|
94
|
+
{ fields: project_fields(extra_project_fields: extra_project_fields) }
|
66
95
|
end
|
67
96
|
|
68
97
|
# pulls an Asana API project class given a name
|
@@ -103,7 +132,7 @@ module Checkoff
|
|
103
132
|
#
|
104
133
|
# @return [Asana::Resources::Project,nil]
|
105
134
|
def project_by_gid(gid, extra_fields: [])
|
106
|
-
projects.find_by_id(gid, options:
|
135
|
+
projects.find_by_id(gid, options: project_options(extra_project_fields: extra_fields))
|
107
136
|
rescue Asana::Errors::NotFound => e
|
108
137
|
debug e
|
109
138
|
nil
|
@@ -142,10 +171,8 @@ module Checkoff
|
|
142
171
|
def tasks_from_project_gid(project_gid,
|
143
172
|
only_uncompleted: true,
|
144
173
|
extra_fields: [])
|
145
|
-
options = task_options
|
146
|
-
options[:completed_since] = '9999-12-01' if only_uncompleted
|
174
|
+
options = task_options(extra_fields: extra_fields, only_uncompleted: only_uncompleted)
|
147
175
|
options[:project] = project_gid
|
148
|
-
options[:options][:fields] += extra_fields
|
149
176
|
# Note: 30 minute cache time on a raw Enumerable from SDK gives
|
150
177
|
# 'Your pagination token has expired' errors. So we go ahead
|
151
178
|
# and eagerly evaluate here so we can enjoy the cache.
|
@@ -158,11 +185,12 @@ module Checkoff
|
|
158
185
|
# @return [Enumerable<Asana::Resources::Project>]
|
159
186
|
def projects_by_workspace_name(workspace_name, extra_fields: [])
|
160
187
|
workspace = @workspaces.workspace_or_raise(workspace_name)
|
161
|
-
options = { fields: %w[name] + extra_fields }
|
162
188
|
# 15 minute cache resulted in 'Your pagination token has
|
163
189
|
# expired', so let's cache this a super long time and force
|
164
190
|
# evaluation
|
165
|
-
projects.find_by_workspace(workspace: workspace.gid,
|
191
|
+
projects.find_by_workspace(workspace: workspace.gid,
|
192
|
+
per_page: 100,
|
193
|
+
options: project_options(extra_project_fields: extra_fields)).to_a
|
166
194
|
end
|
167
195
|
cache_method :projects_by_workspace_name, REALLY_LONG_CACHE_TIME
|
168
196
|
|
@@ -0,0 +1,131 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
# frozen_string_literal: true
|
4
|
+
|
5
|
+
require 'forwardable'
|
6
|
+
require 'cache_method'
|
7
|
+
require_relative 'internal/config_loader'
|
8
|
+
require_relative 'workspaces'
|
9
|
+
require_relative 'clients'
|
10
|
+
|
11
|
+
# https://developers.asana.com/reference/resources
|
12
|
+
|
13
|
+
module Checkoff
|
14
|
+
# Deal with Asana resources across different resource types
|
15
|
+
class Resources
|
16
|
+
# @!parse
|
17
|
+
# extend CacheMethod::ClassMethods
|
18
|
+
|
19
|
+
MINUTE = 60
|
20
|
+
private_constant :MINUTE
|
21
|
+
HOUR = MINUTE * 60
|
22
|
+
private_constant :HOUR
|
23
|
+
DAY = 24 * HOUR
|
24
|
+
private_constant :DAY
|
25
|
+
REALLY_LONG_CACHE_TIME = HOUR * 1
|
26
|
+
private_constant :REALLY_LONG_CACHE_TIME
|
27
|
+
LONG_CACHE_TIME = MINUTE * 15
|
28
|
+
private_constant :LONG_CACHE_TIME
|
29
|
+
SHORT_CACHE_TIME = MINUTE
|
30
|
+
private_constant :SHORT_CACHE_TIME
|
31
|
+
|
32
|
+
# @param config [Hash]
|
33
|
+
# @param workspaces [Checkoff::Workspaces]
|
34
|
+
# @param tasks [Checkoff::Tasks]
|
35
|
+
# @param sections [Checkoff::Sections]
|
36
|
+
# @param projects [Checkoff::Projects]
|
37
|
+
# @param clients [Checkoff::Clients]
|
38
|
+
# @param client [Asana::Client]
|
39
|
+
def initialize(config: Checkoff::Internal::ConfigLoader.load(:asana),
|
40
|
+
workspaces: Checkoff::Workspaces.new(config: config),
|
41
|
+
tasks: Checkoff::Tasks.new(config: config),
|
42
|
+
sections: Checkoff::Sections.new(config: config),
|
43
|
+
projects: Checkoff::Projects.new(config: config),
|
44
|
+
clients: Checkoff::Clients.new(config: config),
|
45
|
+
client: clients.client)
|
46
|
+
@workspaces = workspaces
|
47
|
+
@tasks = tasks
|
48
|
+
@sections = sections
|
49
|
+
@projects = projects
|
50
|
+
@client = client
|
51
|
+
end
|
52
|
+
|
53
|
+
# Attempt to look up a GID, even in situations where we don't
|
54
|
+
# have a resource type provided.
|
55
|
+
#
|
56
|
+
# @param gid [String]
|
57
|
+
# @param resource_type [String,nil]
|
58
|
+
#
|
59
|
+
# @return [Array<([Asana::Resource, nil], [String,nil])>]
|
60
|
+
def resource_by_gid(gid, resource_type: nil)
|
61
|
+
%w[task section project].each do |resource_type_to_try|
|
62
|
+
next unless [resource_type_to_try, nil].include?(resource_type)
|
63
|
+
|
64
|
+
resource = method(:"fetch_#{resource_type_to_try}_gid").call(gid)
|
65
|
+
return [resource, resource_type_to_try] if resource
|
66
|
+
end
|
67
|
+
[nil, nil]
|
68
|
+
end
|
69
|
+
|
70
|
+
private
|
71
|
+
|
72
|
+
# @param gid [String]
|
73
|
+
#
|
74
|
+
# @return [Asana::Resources::Task, nil]
|
75
|
+
def fetch_task_gid(gid)
|
76
|
+
tasks.task_by_gid(gid, only_uncompleted: false)
|
77
|
+
end
|
78
|
+
|
79
|
+
# @param section_gid [String]
|
80
|
+
#
|
81
|
+
# @return [Asana::Resources::Section, nil]
|
82
|
+
def fetch_section_gid(section_gid)
|
83
|
+
sections.section_by_gid(section_gid)
|
84
|
+
end
|
85
|
+
|
86
|
+
# @param project_gid [String]
|
87
|
+
#
|
88
|
+
# @return [Asana::Resources::Project, nil]
|
89
|
+
def fetch_project_gid(project_gid)
|
90
|
+
projects.project_by_gid(project_gid)
|
91
|
+
end
|
92
|
+
|
93
|
+
# @return [Checkoff::Workspaces]
|
94
|
+
attr_reader :workspaces
|
95
|
+
|
96
|
+
# @return [Checkoff::Projects]
|
97
|
+
attr_reader :projects
|
98
|
+
|
99
|
+
# @return [Checkoff::Sections]
|
100
|
+
attr_reader :sections
|
101
|
+
|
102
|
+
# @return [Checkoff::Tasks]
|
103
|
+
attr_reader :tasks
|
104
|
+
|
105
|
+
# @return [Asana::Client]
|
106
|
+
attr_reader :client
|
107
|
+
|
108
|
+
# bundle exec ./resources.rb
|
109
|
+
# :nocov:
|
110
|
+
class << self
|
111
|
+
# @return [void]
|
112
|
+
def run
|
113
|
+
# # @sg-ignore
|
114
|
+
# # @type [String]
|
115
|
+
# workspace_name = ARGV[0] || raise('Please pass workspace name as first argument')
|
116
|
+
# # @sg-ignore
|
117
|
+
# # @type [String]
|
118
|
+
# resource_name = ARGV[1] || raise('Please pass resource name as second argument')
|
119
|
+
# resources = Checkoff::Resources.new
|
120
|
+
# resource = resources.resource_or_raise(workspace_name, resource_name)
|
121
|
+
# puts "Results: #{resource}"
|
122
|
+
end
|
123
|
+
end
|
124
|
+
# :nocov:
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
# :nocov:
|
129
|
+
abs_program_name = File.expand_path($PROGRAM_NAME)
|
130
|
+
Checkoff::Resources.run if abs_program_name == File.expand_path(__FILE__)
|
131
|
+
# :nocov:
|
data/lib/checkoff/sections.rb
CHANGED
@@ -106,9 +106,8 @@ module Checkoff
|
|
106
106
|
def tasks_by_section_gid(section_gid,
|
107
107
|
only_uncompleted: true,
|
108
108
|
extra_fields: [])
|
109
|
-
options = projects.task_options
|
110
|
-
|
111
|
-
options[:completed_since] = '9999-12-01' if only_uncompleted
|
109
|
+
options = projects.task_options(extra_fields: extra_fields,
|
110
|
+
only_uncompleted: only_uncompleted)
|
112
111
|
client.tasks.get_tasks(section: section_gid, **options)
|
113
112
|
end
|
114
113
|
|
@@ -127,9 +126,8 @@ module Checkoff
|
|
127
126
|
only_uncompleted: true,
|
128
127
|
extra_fields: [])
|
129
128
|
section = section_or_raise(workspace_name, project_name, section_name)
|
130
|
-
options = projects.task_options
|
131
|
-
|
132
|
-
options[:completed_since] = '9999-12-01' if only_uncompleted
|
129
|
+
options = projects.task_options(extra_fields: extra_fields,
|
130
|
+
only_uncompleted: only_uncompleted)
|
133
131
|
# Note: 30 minute cache time on a raw Enumerable from SDK gives
|
134
132
|
# 'Your pagination token has expired' errors. So we go ahead
|
135
133
|
# and eagerly evaluate here so we can enjoy the cache.
|
data/lib/checkoff/subtasks.rb
CHANGED
@@ -73,12 +73,9 @@ module Checkoff
|
|
73
73
|
extra_fields: [],
|
74
74
|
only_uncompleted: true)
|
75
75
|
# @type [Hash]
|
76
|
-
|
77
|
-
|
78
|
-
options
|
79
|
-
options[:fields].uniq!
|
80
|
-
|
81
|
-
options[:completed_since] = '9999-12-01' if only_uncompleted
|
76
|
+
all_options = projects.task_options(extra_fields: extra_fields + %w[is_rendered_as_separator],
|
77
|
+
only_uncompleted: only_uncompleted)
|
78
|
+
options = all_options.fetch(:options, {})
|
82
79
|
client.tasks.get_subtasks_for_task(task_gid: task_gid,
|
83
80
|
# per_page: 100, # stub doesn't have this arg available
|
84
81
|
options: options)
|
data/lib/checkoff/tags.rb
CHANGED
@@ -36,7 +36,8 @@ module Checkoff
|
|
36
36
|
extra_fields: [])
|
37
37
|
tag = tag_or_raise(workspace_name, tag_name)
|
38
38
|
|
39
|
-
options =
|
39
|
+
options = projects.task_options(extra_fields: extra_fields,
|
40
|
+
only_uncompleted: only_uncompleted)
|
40
41
|
|
41
42
|
params = build_params(options)
|
42
43
|
|
@@ -65,12 +66,6 @@ module Checkoff
|
|
65
66
|
|
66
67
|
attr_reader :workspaces, :projects, :client
|
67
68
|
|
68
|
-
def build_task_options(task_options, extra_fields, only_uncompleted)
|
69
|
-
task_options[:options][:fields] += extra_fields
|
70
|
-
task_options[:completed_since] = '9999-12-01' if only_uncompleted
|
71
|
-
task_options
|
72
|
-
end
|
73
|
-
|
74
69
|
def build_params(options)
|
75
70
|
{ limit: options[:per_page], completed_since: options[:completed_since] }.reject do |_, v|
|
76
71
|
v.nil? || Array(v).empty?
|
@@ -193,10 +193,8 @@ module Checkoff
|
|
193
193
|
# @return [Hash<Symbol, Object>]
|
194
194
|
def calculate_api_options(extra_fields)
|
195
195
|
# @type [Hash<Symbol, Object>]
|
196
|
-
|
197
|
-
|
198
|
-
options[:fields] += extra_fields
|
199
|
-
options
|
196
|
+
all_options = projects.task_options(extra_fields: ['custom_fields'] + extra_fields)
|
197
|
+
all_options[:options]
|
200
198
|
end
|
201
199
|
|
202
200
|
# bundle exec ./task_searches.rb
|
data/lib/checkoff/tasks.rb
CHANGED
@@ -156,10 +156,12 @@ module Checkoff
|
|
156
156
|
def task_by_gid(task_gid,
|
157
157
|
extra_fields: [],
|
158
158
|
only_uncompleted: true)
|
159
|
+
# @type [Hash{Symbol => Object}]
|
160
|
+
all_options = projects.task_options(extra_fields: extra_fields,
|
161
|
+
only_uncompleted: only_uncompleted)
|
159
162
|
# @type [Hash]
|
160
|
-
options =
|
161
|
-
options[:
|
162
|
-
options[:completed_since] = '9999-12-01' if only_uncompleted
|
163
|
+
options = all_options.fetch(:options, {})
|
164
|
+
options[:completed_since] = all_options[:completed_since] unless all_options[:completed_since].nil?
|
163
165
|
client.tasks.find_by_id(task_gid, options: options)
|
164
166
|
rescue Asana::Errors::NotFound => e
|
165
167
|
debug e
|
data/lib/checkoff/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: checkoff
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.195.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Vince Broz
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-02-
|
11
|
+
date: 2024-02-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -170,6 +170,7 @@ files:
|
|
170
170
|
- lib/checkoff/portfolios.rb
|
171
171
|
- lib/checkoff/project_selectors.rb
|
172
172
|
- lib/checkoff/projects.rb
|
173
|
+
- lib/checkoff/resources.rb
|
173
174
|
- lib/checkoff/section_selectors.rb
|
174
175
|
- lib/checkoff/sections.rb
|
175
176
|
- lib/checkoff/subtasks.rb
|