checkoff 0.243.0 → 0.244.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/checkoff.gemspec +39 -22
- data/lib/checkoff/attachments.rb +9 -9
- data/lib/checkoff/cli.rb +28 -16
- data/lib/checkoff/clients.rb +2 -0
- data/lib/checkoff/custom_fields.rb +5 -8
- data/lib/checkoff/events.rb +0 -2
- data/lib/checkoff/internal/asana_event_enrichment.rb +6 -4
- data/lib/checkoff/internal/asana_event_filter.rb +0 -3
- data/lib/checkoff/internal/config_loader.rb +1 -1
- data/lib/checkoff/internal/logging.rb +2 -0
- data/lib/checkoff/internal/project_hashes.rb +0 -1
- data/lib/checkoff/internal/project_timing.rb +0 -5
- data/lib/checkoff/internal/search_url/custom_field_param_converter.rb +6 -5
- data/lib/checkoff/internal/search_url/custom_field_variant.rb +0 -1
- data/lib/checkoff/internal/search_url/date_param_converter.rb +2 -5
- data/lib/checkoff/internal/search_url/parser.rb +4 -0
- data/lib/checkoff/internal/search_url/results_merger.rb +1 -0
- data/lib/checkoff/internal/search_url/simple_param_converter.rb +2 -4
- data/lib/checkoff/internal/selector_classes/common.rb +19 -1
- data/lib/checkoff/internal/selector_classes/function_evaluator.rb +1 -1
- data/lib/checkoff/internal/selector_classes/project.rb +8 -0
- data/lib/checkoff/internal/selector_classes/section.rb +2 -2
- data/lib/checkoff/internal/selector_classes/task/function_evaluator.rb +9 -0
- data/lib/checkoff/internal/selector_classes/task.rb +28 -27
- data/lib/checkoff/internal/selector_evaluator.rb +2 -0
- data/lib/checkoff/internal/task_hashes.rb +0 -3
- data/lib/checkoff/internal/task_timing.rb +4 -6
- data/lib/checkoff/internal/thread_local.rb +1 -1
- data/lib/checkoff/monkeypatches/resource_marshalling.rb +0 -2
- data/lib/checkoff/my_tasks.rb +2 -1
- data/lib/checkoff/portfolios.rb +1 -0
- data/lib/checkoff/projects.rb +5 -5
- data/lib/checkoff/resources.rb +0 -2
- data/lib/checkoff/section_selectors.rb +0 -1
- data/lib/checkoff/sections.rb +18 -14
- data/lib/checkoff/subtasks.rb +1 -1
- data/lib/checkoff/tags.rb +2 -4
- data/lib/checkoff/task_searches.rb +2 -8
- data/lib/checkoff/task_selectors.rb +2 -3
- data/lib/checkoff/tasks.rb +18 -11
- data/lib/checkoff/timelines.rb +12 -6
- data/lib/checkoff/timing.rb +5 -8
- data/lib/checkoff/version.rb +1 -1
- data/lib/checkoff/workspaces.rb +5 -4
- data/rbi/checkoff.rbi +618 -483
- data/sig/checkoff.rbs +574 -481
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: fe7608634ce1ab4835e6ef9aebe6e9b04697806b1d172ce24e6079d38d47c231
|
|
4
|
+
data.tar.gz: f64454aa021eec0f9efad1f5ce466f40629983727116af4814b723f8032a3179
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 8b761b1d9e319a11f2f7b70762a8a0c0a1a0a4c6cde0ca2123f752ee19a04096eeb34fdaa9c220bd274cb49da90acd4f0f0ea4e5ce4fc081e414e25a070668ad
|
|
7
|
+
data.tar.gz: 17ccc931fb2c5622bb9f1711003340cc86499cfe387c296f2dd2135d41702fb515eab1b194eb70eb7d24b91767f45f35efe2bdb3871f38c3271dd5eb7365dd67
|
data/checkoff.gemspec
CHANGED
|
@@ -2,40 +2,57 @@
|
|
|
2
2
|
# frozen_string_literal: true
|
|
3
3
|
|
|
4
4
|
lib = File.expand_path('lib', __dir__)
|
|
5
|
+
# @sg-ignore $LOAD_PATH is a special Object in RBS
|
|
5
6
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
6
7
|
require 'checkoff/version'
|
|
7
8
|
|
|
8
9
|
Gem::Specification.new do |spec|
|
|
9
|
-
|
|
10
|
-
spec.
|
|
11
|
-
|
|
12
|
-
spec.
|
|
13
|
-
|
|
14
|
-
spec.
|
|
15
|
-
|
|
10
|
+
# @sg-ignore
|
|
11
|
+
spec.name = 'checkoff'
|
|
12
|
+
# @sg-ignore
|
|
13
|
+
spec.version = Checkoff::VERSION
|
|
14
|
+
# @sg-ignore
|
|
15
|
+
spec.authors = ['Vince Broz']
|
|
16
|
+
# @sg-ignore
|
|
17
|
+
spec.email = ['vince@broz.cc']
|
|
18
|
+
# @sg-ignore
|
|
19
|
+
spec.summary = 'Command-line and gem client for Asana (unofficial)'
|
|
20
|
+
# @sg-ignore
|
|
21
|
+
spec.homepage = 'https://github.com/apiology/checkoff'
|
|
22
|
+
# @sg-ignore
|
|
23
|
+
spec.license = 'MIT license'
|
|
24
|
+
# @sg-ignore
|
|
16
25
|
spec.required_ruby_version = '>= 3.3'
|
|
17
|
-
|
|
18
|
-
spec.files
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
spec.
|
|
26
|
+
# @sg-ignore
|
|
27
|
+
spec.files = Dir['README.md',
|
|
28
|
+
'Rakefile',
|
|
29
|
+
'lib/checkoff.rb',
|
|
30
|
+
'{lib}/**/*',
|
|
31
|
+
'sig/**/*.rbs',
|
|
32
|
+
'sig/*.rbs',
|
|
33
|
+
'rbi/**/*.rbi',
|
|
34
|
+
'rbi/*.rbi',
|
|
35
|
+
'{exe}/*',
|
|
36
|
+
'checkoff.gemspec']
|
|
37
|
+
# @sg-ignore
|
|
38
|
+
spec.bindir = 'exe'
|
|
39
|
+
# @sg-ignore
|
|
40
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
|
41
|
+
# @sg-ignore
|
|
30
42
|
spec.require_paths = ['lib']
|
|
31
|
-
|
|
43
|
+
# @sg-ignore
|
|
32
44
|
spec.add_dependency 'activesupport'
|
|
45
|
+
# @sg-ignore
|
|
33
46
|
spec.add_dependency 'asana', '>0.10.0'
|
|
47
|
+
# @sg-ignore
|
|
34
48
|
spec.add_dependency 'cache_method'
|
|
49
|
+
# @sg-ignore
|
|
35
50
|
spec.add_dependency 'gli'
|
|
51
|
+
# @sg-ignore
|
|
36
52
|
spec.add_dependency 'mime-types'
|
|
53
|
+
# @sg-ignore
|
|
37
54
|
spec.add_dependency 'sorbet-runtime'
|
|
38
|
-
|
|
55
|
+
# @sg-ignore
|
|
39
56
|
spec.metadata = {
|
|
40
57
|
'rubygems_mfa_required' => 'false',
|
|
41
58
|
}
|
data/lib/checkoff/attachments.rb
CHANGED
|
@@ -83,9 +83,9 @@ module Checkoff
|
|
|
83
83
|
# @param verify_mode [Integer] - e.g., OpenSSL::SSL::VERIFY_NONE,OpenSSL::SSL::VERIFY_PEER
|
|
84
84
|
#
|
|
85
85
|
# @return [Object]
|
|
86
|
-
# @sg-ignore
|
|
87
86
|
def download_uri(uri, verify_mode: OpenSSL::SSL::VERIFY_PEER, &block)
|
|
88
87
|
out = nil
|
|
88
|
+
# @sg-ignore
|
|
89
89
|
Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == 'https', verify_mode:) do |http|
|
|
90
90
|
# @sg-ignore
|
|
91
91
|
http.request(Net::HTTP::Get.new(uri)) do |response|
|
|
@@ -100,19 +100,20 @@ module Checkoff
|
|
|
100
100
|
raise "Error downloading #{uri}: #{e}"
|
|
101
101
|
end
|
|
102
102
|
|
|
103
|
-
# @
|
|
104
|
-
# @param response [Net::HTTPResponse]
|
|
103
|
+
# @param response [#read_body]
|
|
105
104
|
#
|
|
106
105
|
# @yields [IO]
|
|
107
106
|
#
|
|
108
107
|
# @return [Object]
|
|
109
108
|
def write_tempfile_from_response(response)
|
|
110
109
|
Tempfile.create('checkoff') do |tempfile|
|
|
110
|
+
# @sg-ignore
|
|
111
111
|
tempfile.binmode
|
|
112
112
|
# @sg-ignore
|
|
113
113
|
response.read_body do |chunk|
|
|
114
114
|
tempfile.write(chunk)
|
|
115
115
|
end
|
|
116
|
+
# @sg-ignore
|
|
116
117
|
tempfile.rewind
|
|
117
118
|
|
|
118
119
|
yield tempfile
|
|
@@ -130,9 +131,12 @@ module Checkoff
|
|
|
130
131
|
uri = URI(url)
|
|
131
132
|
attachment_name ||= File.basename(uri.path)
|
|
132
133
|
download_uri(uri, verify_mode:) do |tempfile|
|
|
134
|
+
# @sg-ignore
|
|
133
135
|
content_type ||= content_type_from_filename(attachment_name)
|
|
136
|
+
# @sg-ignore
|
|
134
137
|
content_type ||= content_type_from_filename(uri.path)
|
|
135
138
|
|
|
139
|
+
# @sg-ignore
|
|
136
140
|
resource.attach(filename: attachment_name, mime: content_type,
|
|
137
141
|
io: tempfile)
|
|
138
142
|
end
|
|
@@ -145,6 +149,7 @@ module Checkoff
|
|
|
145
149
|
# @return [Asana::Resources::Attachment]
|
|
146
150
|
def create_attachment_from_url_alone!(url, resource, attachment_name:)
|
|
147
151
|
with_params = {
|
|
152
|
+
# @sg-ignore
|
|
148
153
|
'parent' => resource.gid,
|
|
149
154
|
'url' => url,
|
|
150
155
|
'resource_subtype' => 'external',
|
|
@@ -158,9 +163,7 @@ module Checkoff
|
|
|
158
163
|
# @param filename [String]
|
|
159
164
|
#
|
|
160
165
|
# @return [String,nil]
|
|
161
|
-
# @sg-ignore
|
|
162
166
|
def content_type_from_filename(filename)
|
|
163
|
-
# @sg-ignore
|
|
164
167
|
MIME::Types.type_for(filename)&.first&.content_type
|
|
165
168
|
end
|
|
166
169
|
|
|
@@ -183,25 +186,22 @@ module Checkoff
|
|
|
183
186
|
attr_reader :client
|
|
184
187
|
|
|
185
188
|
# bundle exec ./attachments.rb
|
|
186
|
-
# :nocov:
|
|
187
189
|
class << self
|
|
188
190
|
# @return [void]
|
|
189
191
|
def run
|
|
190
|
-
# @sg-ignore
|
|
191
192
|
# @type [String]
|
|
192
193
|
gid = ARGV[0] || raise('Please pass task gid as first argument')
|
|
193
|
-
# @sg-ignore
|
|
194
194
|
# @type [String]
|
|
195
195
|
url = ARGV[1] || raise('Please pass attachment URL as second argument')
|
|
196
196
|
|
|
197
197
|
tasks = Checkoff::Tasks.new
|
|
198
198
|
attachments = Checkoff::Attachments.new
|
|
199
199
|
task = tasks.task_by_gid(gid)
|
|
200
|
+
# @sg-ignore
|
|
200
201
|
attachment = attachments.create_attachment_from_url!(url, task)
|
|
201
202
|
puts "Results: #{attachment.inspect}"
|
|
202
203
|
end
|
|
203
204
|
end
|
|
204
|
-
# :nocov:
|
|
205
205
|
end
|
|
206
206
|
end
|
|
207
207
|
|
data/lib/checkoff/cli.rb
CHANGED
|
@@ -29,6 +29,7 @@ module Checkoff
|
|
|
29
29
|
end
|
|
30
30
|
|
|
31
31
|
@from_workspace_name = from_workspace_arg
|
|
32
|
+
# @sg-ignore
|
|
32
33
|
@from_project_name = project_arg_to_name(from_project_arg)
|
|
33
34
|
@from_section_name = from_section_arg
|
|
34
35
|
end
|
|
@@ -40,6 +41,7 @@ module Checkoff
|
|
|
40
41
|
if to_project_arg == :source_project
|
|
41
42
|
from_project_name
|
|
42
43
|
else
|
|
44
|
+
# @sg-ignore
|
|
43
45
|
project_arg_to_name(to_project_arg)
|
|
44
46
|
end
|
|
45
47
|
end
|
|
@@ -112,9 +114,9 @@ module Checkoff
|
|
|
112
114
|
end
|
|
113
115
|
end
|
|
114
116
|
|
|
115
|
-
# @param from_workspace_name [String]
|
|
117
|
+
# @param from_workspace_name [String, Symbol]
|
|
116
118
|
# @param from_project_name [String, Symbol]
|
|
117
|
-
# @param from_section_name [String, Symbol]
|
|
119
|
+
# @param from_section_name [String, Symbol, nil]
|
|
118
120
|
# @return [Enumerable<Asana::Resources::Task>]
|
|
119
121
|
def fetch_tasks(from_workspace_name, from_project_name, from_section_name)
|
|
120
122
|
if from_section_name == :all_sections
|
|
@@ -147,10 +149,11 @@ module Checkoff
|
|
|
147
149
|
# @param project_arg [String]
|
|
148
150
|
# @return [Symbol, String]
|
|
149
151
|
def project_arg_to_name(project_arg)
|
|
150
|
-
|
|
151
|
-
|
|
152
|
+
arg = project_arg.to_s
|
|
153
|
+
if arg.start_with?(':')
|
|
154
|
+
arg.delete_prefix(':').to_sym
|
|
152
155
|
else
|
|
153
|
-
|
|
156
|
+
arg
|
|
154
157
|
end
|
|
155
158
|
end
|
|
156
159
|
end
|
|
@@ -191,19 +194,21 @@ module Checkoff
|
|
|
191
194
|
elsif task_name.nil?
|
|
192
195
|
run_on_section(workspace_name, project_name, section_name)
|
|
193
196
|
else
|
|
197
|
+
# @sg-ignore
|
|
194
198
|
run_on_task(workspace_name, project_name, section_name, task_name)
|
|
195
199
|
end
|
|
196
200
|
end
|
|
197
201
|
|
|
198
202
|
private
|
|
199
203
|
|
|
200
|
-
# @param project_name [String]
|
|
204
|
+
# @param project_name [String, Symbol]
|
|
201
205
|
# @return [String, Symbol]
|
|
202
206
|
def validate_and_assign_project_name(project_name)
|
|
203
|
-
|
|
204
|
-
|
|
207
|
+
name = project_name.to_s
|
|
208
|
+
@project_name = if name.start_with?(':')
|
|
209
|
+
name.delete_prefix(':').to_sym
|
|
205
210
|
else
|
|
206
|
-
|
|
211
|
+
name
|
|
207
212
|
end
|
|
208
213
|
end
|
|
209
214
|
|
|
@@ -211,14 +216,13 @@ module Checkoff
|
|
|
211
216
|
# @param project [String, Symbol]
|
|
212
217
|
#
|
|
213
218
|
# @return [String]
|
|
214
|
-
# @sg-ignore
|
|
215
219
|
def run_on_project(workspace, project)
|
|
216
220
|
tasks_by_section =
|
|
221
|
+
# @sg-ignore
|
|
217
222
|
sections.tasks_by_section(workspace, project)
|
|
218
223
|
tasks_by_section.update(tasks_by_section) do |_key, tasks|
|
|
219
224
|
tasks_to_hash(tasks)
|
|
220
225
|
end
|
|
221
|
-
# @sg-ignore
|
|
222
226
|
tasks_by_section.to_json
|
|
223
227
|
end
|
|
224
228
|
|
|
@@ -226,11 +230,9 @@ module Checkoff
|
|
|
226
230
|
# @param project [String, Symbol]
|
|
227
231
|
# @param section [String, Symbol, nil]
|
|
228
232
|
# @return [String]
|
|
229
|
-
# @sg-ignore
|
|
230
233
|
def run_on_section(workspace, project, section)
|
|
231
234
|
section = nil if section == ''
|
|
232
235
|
tasks = sections.tasks(workspace, project, section) || []
|
|
233
|
-
# @sg-ignore
|
|
234
236
|
tasks_to_hash(tasks).to_json
|
|
235
237
|
end
|
|
236
238
|
|
|
@@ -239,11 +241,12 @@ module Checkoff
|
|
|
239
241
|
# @param section [String, Symbol, nil]
|
|
240
242
|
# @param task_name [String]
|
|
241
243
|
# @return [String]
|
|
242
|
-
# @sg-ignore
|
|
243
244
|
def run_on_task(workspace, project, section, task_name)
|
|
244
245
|
section = nil if section == ''
|
|
245
|
-
task = tasks.task(workspace, project, task_name, section_name: section)
|
|
246
|
-
#
|
|
246
|
+
task = tasks.task(workspace.to_s, project, task_name, section_name: section)
|
|
247
|
+
raise "Task not found: #{task_name}" if task.nil?
|
|
248
|
+
|
|
249
|
+
# @sg-ignore nil check above is not flow-sensitive
|
|
247
250
|
task_to_hash(task).to_json
|
|
248
251
|
end
|
|
249
252
|
|
|
@@ -312,6 +315,7 @@ module Checkoff
|
|
|
312
315
|
arg 'workspace'
|
|
313
316
|
arg 'task_name'
|
|
314
317
|
command :quickadd do |c|
|
|
318
|
+
# @sg-ignore
|
|
315
319
|
c.action do |_global_options, _options, args|
|
|
316
320
|
workspace_name = args.fetch(0)
|
|
317
321
|
task_name = args.fetch(1)
|
|
@@ -326,6 +330,7 @@ module Checkoff
|
|
|
326
330
|
arg 'section', :optional
|
|
327
331
|
arg 'task_name', :optional
|
|
328
332
|
command :view do |c|
|
|
333
|
+
# @sg-ignore
|
|
329
334
|
c.action do |_global_options, _options, args|
|
|
330
335
|
workspace_name = args.fetch(0)
|
|
331
336
|
project_name = args.fetch(1)
|
|
@@ -340,30 +345,37 @@ module Checkoff
|
|
|
340
345
|
|
|
341
346
|
# rubocop:disable Metrics/BlockLength
|
|
342
347
|
command :mv do |c|
|
|
348
|
+
# @sg-ignore
|
|
343
349
|
c.flag :from_workspace,
|
|
344
350
|
type: String,
|
|
345
351
|
default_value: :default_workspace,
|
|
346
352
|
desc: 'Workspace to move tasks from'
|
|
353
|
+
# @sg-ignore
|
|
347
354
|
c.flag :from_project,
|
|
348
355
|
type: String,
|
|
349
356
|
required: true,
|
|
350
357
|
desc: 'Project to move tasks from'
|
|
358
|
+
# @sg-ignore
|
|
351
359
|
c.flag :from_section,
|
|
352
360
|
type: String,
|
|
353
361
|
default_value: :all_sections,
|
|
354
362
|
desc: 'Section to move tasks from'
|
|
363
|
+
# @sg-ignore
|
|
355
364
|
c.flag :to_workspace,
|
|
356
365
|
type: String,
|
|
357
366
|
default_value: :source_workspace,
|
|
358
367
|
desc: 'Workspace to move tasks to'
|
|
368
|
+
# @sg-ignore
|
|
359
369
|
c.flag :to_project,
|
|
360
370
|
type: String,
|
|
361
371
|
default_value: :source_project,
|
|
362
372
|
desc: 'Section to move tasks to'
|
|
373
|
+
# @sg-ignore
|
|
363
374
|
c.flag :to_section,
|
|
364
375
|
type: String,
|
|
365
376
|
default_value: :source_section,
|
|
366
377
|
desc: 'Section to move tasks to'
|
|
378
|
+
# @sg-ignore
|
|
367
379
|
c.action do |_global_options, options, _args|
|
|
368
380
|
from_workspace = options.fetch('from_workspace')
|
|
369
381
|
from_project = options.fetch('from_project')
|
data/lib/checkoff/clients.rb
CHANGED
|
@@ -30,7 +30,9 @@ module Checkoff
|
|
|
30
30
|
# @return [Asana::Client]
|
|
31
31
|
def client
|
|
32
32
|
@client ||= @asana_client_class.new do |c|
|
|
33
|
+
# @sg-ignore
|
|
33
34
|
c.authentication :access_token, @config.fetch(:personal_access_token)
|
|
35
|
+
# @sg-ignore
|
|
34
36
|
c.default_headers 'asana-enable' =>
|
|
35
37
|
'new_project_templates,new_user_task_lists,new_memberships,new_goal_memberships'
|
|
36
38
|
end
|
|
@@ -41,6 +41,7 @@ module Checkoff
|
|
|
41
41
|
# @param custom_field_name [String]
|
|
42
42
|
#
|
|
43
43
|
# @return [Asana::Resources::CustomField]
|
|
44
|
+
# @sg-ignore
|
|
44
45
|
def custom_field_or_raise(workspace_name, custom_field_name)
|
|
45
46
|
cf = custom_field(workspace_name, custom_field_name)
|
|
46
47
|
raise "Could not find custom_field #{custom_field_name} under workspace #{workspace_name}." if cf.nil?
|
|
@@ -52,7 +53,6 @@ module Checkoff
|
|
|
52
53
|
# @param workspace_name [String]
|
|
53
54
|
# @param custom_field_name [String]
|
|
54
55
|
#
|
|
55
|
-
# @sg-ignore
|
|
56
56
|
# @return [Asana::Resources::CustomField,nil]
|
|
57
57
|
def custom_field(workspace_name, custom_field_name)
|
|
58
58
|
workspace = workspaces.workspace_or_raise(workspace_name)
|
|
@@ -78,6 +78,7 @@ module Checkoff
|
|
|
78
78
|
|
|
79
79
|
# @param resource [Asana::Resources::Project,Asana::Resources::Task]
|
|
80
80
|
# @param custom_field_name [String]
|
|
81
|
+
# @sg-ignore
|
|
81
82
|
# @return [Array<String>]
|
|
82
83
|
def resource_custom_field_values_names_by_name(resource, custom_field_name)
|
|
83
84
|
custom_field = resource_custom_field_by_name(resource, custom_field_name)
|
|
@@ -92,24 +93,22 @@ module Checkoff
|
|
|
92
93
|
end
|
|
93
94
|
end
|
|
94
95
|
|
|
95
|
-
# @sg-ignore
|
|
96
96
|
# @param resource [Asana::Resources::Task,Asana::Resources::Project]
|
|
97
97
|
# @param custom_field_name [String]
|
|
98
98
|
# @return [Hash, nil]
|
|
99
99
|
def resource_custom_field_by_name(resource, custom_field_name)
|
|
100
|
-
# @sg-ignore
|
|
101
100
|
# @type [Array<Hash>]
|
|
102
101
|
custom_fields = resource.custom_fields
|
|
103
102
|
if custom_fields.nil?
|
|
104
103
|
raise "custom fields not found on resource - did you add 'custom_fields' in your extra_fields argument?"
|
|
105
104
|
end
|
|
106
105
|
|
|
107
|
-
# @sg-ignore
|
|
108
106
|
# @type [Hash, nil]
|
|
109
107
|
custom_fields.find { |field| field.fetch('name') == custom_field_name }
|
|
110
108
|
end
|
|
111
109
|
|
|
112
110
|
# @param resource [Asana::Resources::Task,Asana::Resources::Project]
|
|
111
|
+
# @sg-ignore
|
|
113
112
|
# @param custom_field_name [String]
|
|
114
113
|
# @return [Hash]
|
|
115
114
|
def resource_custom_field_by_name_or_raise(resource, custom_field_name)
|
|
@@ -121,6 +120,7 @@ module Checkoff
|
|
|
121
120
|
custom_field
|
|
122
121
|
end
|
|
123
122
|
|
|
123
|
+
# @sg-ignore
|
|
124
124
|
# @param resource [Asana::Resources::Project,Asana::Resources::Task]
|
|
125
125
|
# @param custom_field_gid [String]
|
|
126
126
|
# @return [Hash]
|
|
@@ -131,7 +131,6 @@ module Checkoff
|
|
|
131
131
|
raise "Could not find custom_fields under project (was 'custom_fields' included in 'extra_fields'?)"
|
|
132
132
|
end
|
|
133
133
|
|
|
134
|
-
# @sg-ignore
|
|
135
134
|
# @type [Hash, nil]
|
|
136
135
|
matched_custom_field = custom_fields.find { |data| data.fetch('gid') == custom_field_gid }
|
|
137
136
|
if matched_custom_field.nil?
|
|
@@ -146,8 +145,8 @@ module Checkoff
|
|
|
146
145
|
|
|
147
146
|
# @param custom_field [Hash{String => Hash,Array<Hash>}]
|
|
148
147
|
#
|
|
149
|
-
# @sg-ignore
|
|
150
148
|
# @return [Array<Hash>]
|
|
149
|
+
# @sg-ignore
|
|
151
150
|
def resource_custom_field_enum_values(custom_field)
|
|
152
151
|
resource_subtype = custom_field.fetch('resource_subtype')
|
|
153
152
|
case resource_subtype
|
|
@@ -184,10 +183,8 @@ module Checkoff
|
|
|
184
183
|
class << self
|
|
185
184
|
# @return [void]
|
|
186
185
|
def run
|
|
187
|
-
# @sg-ignore
|
|
188
186
|
# @type [String]
|
|
189
187
|
workspace_name = ARGV[0] || raise('Please pass workspace name as first argument')
|
|
190
|
-
# @sg-ignore
|
|
191
188
|
# @type [String]
|
|
192
189
|
custom_field_name = ARGV[1] || raise('Please pass custom_field name as second argument')
|
|
193
190
|
custom_fields = Checkoff::CustomFields.new
|
data/lib/checkoff/events.rb
CHANGED
|
@@ -122,10 +122,8 @@ module Checkoff
|
|
|
122
122
|
class << self
|
|
123
123
|
# @return [void]
|
|
124
124
|
def run
|
|
125
|
-
# @sg-ignore
|
|
126
125
|
# @type [String]
|
|
127
126
|
# workspace_name = ARGV[0] || raise('Please pass workspace name as first argument')
|
|
128
|
-
# @sg-ignore
|
|
129
127
|
# @type [String]
|
|
130
128
|
# event_name = ARGV[1] || raise('Please pass event name as second argument')
|
|
131
129
|
# events = Checkoff::Events.new
|
|
@@ -73,9 +73,10 @@ module Checkoff
|
|
|
73
73
|
enrich_filter(filter)
|
|
74
74
|
end
|
|
75
75
|
resource = webhook_subscription&.fetch('resource', nil)
|
|
76
|
-
# @sg-ignore
|
|
77
76
|
name, resource_type = enrich_gid(resource) if resource
|
|
77
|
+
# @sg-ignore
|
|
78
78
|
webhook_subscription['checkoff:enriched:name'] = name if name
|
|
79
|
+
# @sg-ignore
|
|
79
80
|
webhook_subscription['checkoff:enriched:resource_type'] = resource_type if resource_type
|
|
80
81
|
end
|
|
81
82
|
|
|
@@ -89,18 +90,19 @@ module Checkoff
|
|
|
89
90
|
#
|
|
90
91
|
# @return [Array([String, nil], [String, nil])]
|
|
91
92
|
def enrich_gid(gid, resource_type: nil)
|
|
92
|
-
# @sg-ignore
|
|
93
93
|
resource, resource_type = resources.resource_by_gid(gid, resource_type:)
|
|
94
94
|
[resource&.name, resource_type]
|
|
95
95
|
end
|
|
96
96
|
|
|
97
97
|
# @param filter [Hash{String => String, Array<String>}]
|
|
98
98
|
#
|
|
99
|
+
# @sg-ignore
|
|
99
100
|
# @return [String, nil]
|
|
100
101
|
def enrich_filter_parent_gid!(filter)
|
|
101
102
|
parent_gid = filter['checkoff:parent.gid']
|
|
102
103
|
return unless parent_gid
|
|
103
104
|
|
|
105
|
+
# @sg-ignore
|
|
104
106
|
name, resource_type = enrich_gid(parent_gid)
|
|
105
107
|
filter['checkoff:enriched:parent.name'] = name if name
|
|
106
108
|
filter['checkoff:enriched:parent.resource_type'] = resource_type if resource_type
|
|
@@ -114,6 +116,7 @@ module Checkoff
|
|
|
114
116
|
|
|
115
117
|
return unless resource_gid
|
|
116
118
|
|
|
119
|
+
# @sg-ignore
|
|
117
120
|
task = tasks.task_by_gid(resource_gid)
|
|
118
121
|
task_name = task&.name
|
|
119
122
|
filter['checkoff:enriched:resource.name'] = task_name if task_name
|
|
@@ -136,6 +139,7 @@ module Checkoff
|
|
|
136
139
|
# @return [void]
|
|
137
140
|
def enrich_event_parent!(asana_event)
|
|
138
141
|
# @type [Hash{String => String }]
|
|
142
|
+
# @sg-ignore
|
|
139
143
|
parent = asana_event['parent']
|
|
140
144
|
|
|
141
145
|
return unless parent
|
|
@@ -144,7 +148,6 @@ module Checkoff
|
|
|
144
148
|
resource_type = parent.fetch('resource_type')
|
|
145
149
|
# @type [String]
|
|
146
150
|
gid = parent.fetch('gid')
|
|
147
|
-
# @sg-ignore
|
|
148
151
|
name, _resource_type = enrich_gid(gid, resource_type:)
|
|
149
152
|
parent['checkoff:enriched:name'] = name if name
|
|
150
153
|
|
|
@@ -163,7 +166,6 @@ module Checkoff
|
|
|
163
166
|
# @type [String]
|
|
164
167
|
gid = resource.fetch('gid')
|
|
165
168
|
|
|
166
|
-
# @sg-ignore
|
|
167
169
|
name, _resource_type = enrich_gid(gid, resource_type:)
|
|
168
170
|
resource['checkoff:enriched:name'] = name if name
|
|
169
171
|
|
|
@@ -56,7 +56,6 @@ module Checkoff
|
|
|
56
56
|
# @param asana_event [Hash]
|
|
57
57
|
# @param failures [Array<String>]
|
|
58
58
|
#
|
|
59
|
-
# @sg-ignore
|
|
60
59
|
# @return [Boolean]
|
|
61
60
|
def filter_matches_asana_event?(filter, asana_event, failures)
|
|
62
61
|
# @param key [String]
|
|
@@ -73,7 +72,6 @@ module Checkoff
|
|
|
73
72
|
# @param value [String, Array<String>]
|
|
74
73
|
# @param asana_event [Hash]
|
|
75
74
|
#
|
|
76
|
-
# @sg-ignore
|
|
77
75
|
# @return [Boolean]
|
|
78
76
|
def asana_event_matches_filter_item?(key, value, asana_event)
|
|
79
77
|
case key
|
|
@@ -122,7 +120,6 @@ module Checkoff
|
|
|
122
120
|
# @return [Asana::Resources::Task,nil]
|
|
123
121
|
def uncached_fetch_task(key, asana_event, fields)
|
|
124
122
|
# @type [Hash{String => String}]
|
|
125
|
-
# @sg-ignore
|
|
126
123
|
resource = asana_event.fetch('resource')
|
|
127
124
|
# @type [String]
|
|
128
125
|
resource_type = resource.fetch('resource_type')
|
|
@@ -20,6 +20,7 @@ module Checkoff
|
|
|
20
20
|
|
|
21
21
|
# @param key [Symbol]
|
|
22
22
|
# @return [Object]
|
|
23
|
+
# @sg-ignore
|
|
23
24
|
def [](key)
|
|
24
25
|
config_value = @config[key]
|
|
25
26
|
return config_value unless config_value.nil?
|
|
@@ -66,7 +67,6 @@ module Checkoff
|
|
|
66
67
|
filename = yaml_filename(sym)
|
|
67
68
|
return {} unless File.exist?(filename)
|
|
68
69
|
|
|
69
|
-
# @sg-ignore
|
|
70
70
|
YAML.load_file(filename).with_indifferent_access
|
|
71
71
|
end
|
|
72
72
|
|
|
@@ -21,7 +21,6 @@ module Checkoff
|
|
|
21
21
|
|
|
22
22
|
# @param project [Asana::Resources::Project]
|
|
23
23
|
#
|
|
24
|
-
# @sg-ignore
|
|
25
24
|
# @return [Date, nil]
|
|
26
25
|
def start_date(project)
|
|
27
26
|
return @date_class.parse(project.start_on) unless project.start_on.nil?
|
|
@@ -31,7 +30,6 @@ module Checkoff
|
|
|
31
30
|
|
|
32
31
|
# @param project [Asana::Resources::Project]
|
|
33
32
|
#
|
|
34
|
-
# @sg-ignore
|
|
35
33
|
# @return [Date, nil]
|
|
36
34
|
def due_date(project)
|
|
37
35
|
return @date_class.parse(project.due_on) unless project.due_on.nil?
|
|
@@ -45,7 +43,6 @@ module Checkoff
|
|
|
45
43
|
# @return [Time, Date, nil]
|
|
46
44
|
def custom_field(project, custom_field_name)
|
|
47
45
|
custom_field = @custom_fields.resource_custom_field_by_name_or_raise(project, custom_field_name)
|
|
48
|
-
# @sg-ignore
|
|
49
46
|
# @type [String, nil]
|
|
50
47
|
time_str = custom_field.fetch('display_value')
|
|
51
48
|
return nil if time_str.nil?
|
|
@@ -56,7 +53,6 @@ module Checkoff
|
|
|
56
53
|
# @param project [Asana::Resources::Project]
|
|
57
54
|
# @param field_name [Symbol,Array]
|
|
58
55
|
#
|
|
59
|
-
# @sg-ignore
|
|
60
56
|
# @return [Date, Time, nil]
|
|
61
57
|
def date_or_time_field_by_name(project, field_name)
|
|
62
58
|
return due_date(project) if field_name == :due
|
|
@@ -66,7 +62,6 @@ module Checkoff
|
|
|
66
62
|
return start_date(project) if field_name == :ready
|
|
67
63
|
|
|
68
64
|
if field_name.is_a?(Array)
|
|
69
|
-
# @sg-ignore
|
|
70
65
|
# @type [Symbol]
|
|
71
66
|
actual_field_name = field_name.first
|
|
72
67
|
args = field_name[1..]
|
|
@@ -22,13 +22,11 @@ module Checkoff
|
|
|
22
22
|
# @type task_selector [Array<Symbol, Array>]
|
|
23
23
|
task_selector = []
|
|
24
24
|
by_custom_field.each do |gid, single_custom_field_params|
|
|
25
|
-
# @sg-ignore
|
|
26
25
|
new_args, new_task_selector = convert_single_custom_field_params(gid,
|
|
27
26
|
single_custom_field_params)
|
|
28
27
|
|
|
29
28
|
args = ResultsMerger.merge_args(args, new_args)
|
|
30
29
|
|
|
31
|
-
# @sg-ignore
|
|
32
30
|
task_selector = ResultsMerger.merge_task_selectors(task_selector, new_task_selector)
|
|
33
31
|
end
|
|
34
32
|
[args, task_selector]
|
|
@@ -36,7 +34,6 @@ module Checkoff
|
|
|
36
34
|
|
|
37
35
|
private
|
|
38
36
|
|
|
39
|
-
# @sg-ignore
|
|
40
37
|
# @return [Hash{String => Hash}]
|
|
41
38
|
def by_custom_field
|
|
42
39
|
custom_field_params.group_by do |key, _value|
|
|
@@ -61,18 +58,20 @@ module Checkoff
|
|
|
61
58
|
|
|
62
59
|
# @param gid [String]
|
|
63
60
|
# @param single_custom_field_params [Hash{String => Array<String>}]
|
|
64
|
-
# @sg-ignore
|
|
65
61
|
# @return [Array(Hash{String => String}, Array<Symbol, Array>)]
|
|
62
|
+
# @sg-ignore
|
|
66
63
|
def convert_single_custom_field_params(gid, single_custom_field_params)
|
|
67
64
|
variant_key = "custom_field_#{gid}.variant"
|
|
68
65
|
variant = single_custom_field_params.fetch(variant_key)
|
|
69
66
|
remaining_params = single_custom_field_params.reject { |k, _v| k == variant_key }
|
|
70
67
|
raise "Teach me how to handle #{variant_key} = #{variant}" unless variant.length == 1
|
|
71
68
|
|
|
69
|
+
# @sg-ignore
|
|
72
70
|
# @type [Class<CustomFieldVariant>]
|
|
73
|
-
variant_class = VARIANTS[variant[0]]
|
|
74
71
|
# @sg-ignore
|
|
72
|
+
variant_class = VARIANTS[variant[0]]
|
|
75
73
|
# @type [Array(Hash{String => String}, Array<Symbol, Array>)]
|
|
74
|
+
# @sg-ignore
|
|
76
75
|
return variant_class.new(gid, remaining_params).convert unless variant_class.nil?
|
|
77
76
|
|
|
78
77
|
raise "Teach me how to handle #{variant_key} = #{variant}"
|
|
@@ -80,7 +79,9 @@ module Checkoff
|
|
|
80
79
|
|
|
81
80
|
# @param key [String]
|
|
82
81
|
# @return [String]
|
|
82
|
+
# @sg-ignore
|
|
83
83
|
def gid_from_custom_field_key(key)
|
|
84
|
+
# @sg-ignore
|
|
84
85
|
key.split('_')[2].split('.')[0]
|
|
85
86
|
end
|
|
86
87
|
|