checkoff 0.192.0 → 0.194.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f18c541bd2d95341686dc5db9637bdfe61cd0f5880f484067c3e20eabebaa717
4
- data.tar.gz: d3fc7101c367fab1388d75bf04b08d3e322c9cbeaed614ee2a5da008c2e732cf
3
+ metadata.gz: ebec494187b376d4803fa45da76cfdb6ca3b958290ec0308caacb4ac895fa092
4
+ data.tar.gz: 7d2fd1701ecbae61048495a6eb91587a3cc384f3aa067f01b7b580e9807d02a0
5
5
  SHA512:
6
- metadata.gz: 2c72b43aa09c8fe1bf713da082478f52aee59278cdd56a0149012c291cfde621f81979f40fc8267447ed6af5b0abc504ec46e51df18da7d5a295fbaa58be14ca
7
- data.tar.gz: 05b8ae1174c3d2352b6ef08525b34774a17276080b8fc14f6afa6c7fb55cd6fa05561a02252435c7803cac41ce6eb0ff28231aea01f0bbcefb0ebb34bfef9a13
6
+ metadata.gz: 9ce29418e9649e852ce60b1a3ac8c166e7da1d06bb52d496356bb01022be067b26846b82b631842ae80a8703824ba84731fd585c621df4b982effebdb3b50452
7
+ data.tar.gz: 29997815ab3aa694eb4d67758fb6cdd8f2e06a2467006b54b13f82c00ad3e385773e8ad69da448e7ef563d2b4c938b6e8719e923ddc95abe06d6f79403151444
data/Gemfile.lock CHANGED
@@ -12,7 +12,7 @@ GIT
12
12
  PATH
13
13
  remote: .
14
14
  specs:
15
- checkoff (0.192.0)
15
+ checkoff (0.194.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.15.5-arm64-darwin)
133
+ nokogiri (1.16.2-arm64-darwin)
134
134
  racc (~> 1.4)
135
- nokogiri (1.15.5-x86_64-darwin)
135
+ nokogiri (1.16.2-x86_64-darwin)
136
136
  racc (~> 1.4)
137
- nokogiri (1.15.5-x86_64-linux)
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)
@@ -54,6 +54,8 @@
54
54
  # class Task
55
55
  # # @return [String]
56
56
  # def resource_subtype; end
57
+ # # @return [Boolean,nil]
58
+ # def is_rendered_as_separator; end
57
59
  # # @return [String,nil]
58
60
  # def due_at; end
59
61
  # # @return [String,nil]
@@ -110,6 +112,16 @@
110
112
  # def get_custom_fields_for_workspace(workspace_gid: required("workspace_gid"), options: {}); end
111
113
  # end
112
114
  # class Task
115
+ # # Get subtasks from a task
116
+ # #
117
+ # # @param task_gid [String] (required) The task to operate on.
118
+ # # @param options [Hash] the request I/O options
119
+ # # > offset - [str] Offset token. An offset to the next page returned by the API. A pagination request will return an offset token, which can be used as an input parameter to the next request. If an offset is not passed in, the API will return the first page of results. 'Note: You can only pass in an offset that was returned to you via a previously paginated request.'
120
+ # # > limit - [int] Results per page. The number of objects to return per page. The value must be between 1 and 100.
121
+ # # > opt_fields - [list[str]] Defines fields to return. Some requests return *compact* representations of objects in order to conserve resources and complete the request more efficiently. Other times requests return more information than you may need. This option allows you to list the exact set of fields that the API should be sure to return for the objects. The field names should be provided as paths, described below. The id of included objects will always be returned, regardless of the field options.
122
+ # # > opt_pretty - [bool] Provides “pretty” output. Provides the response in a “pretty” format. In the case of JSON this means doing proper line breaking and indentation to make it readable. This will take extra time and increase the response size so it is advisable only to use this during debugging.
123
+ # # @return [Enumerable<Asana::Resources::Task>]
124
+ # def get_subtasks_for_task(task_gid: required("task_gid"), options: {}); end
113
125
  # # Returns the complete task record for a single task.
114
126
  # #
115
127
  # # @param id [String] The task to get.
@@ -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: %w[name completed_at start_at start_on due_at due_on tags
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: { fields: %w[name] + extra_fields })
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, per_page: 100, options: options).to_a
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
 
@@ -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
- options[:options][:fields] += extra_fields
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
- options[:options][:fields] += extra_fields
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.
@@ -7,32 +7,45 @@ require_relative 'projects'
7
7
  module Checkoff
8
8
  # Query different subtasks of Asana tasks
9
9
  class Subtasks
10
+ # @!parse
11
+ # extend CacheMethod::ClassMethods
12
+
10
13
  MINUTE = 60
11
14
  LONG_CACHE_TIME = MINUTE * 15
12
15
  SHORT_CACHE_TIME = MINUTE * 5
13
16
 
14
17
  extend Forwardable
15
18
 
19
+ # @param config [Hash]
20
+ # @param projects [Checkoff::Projects]
21
+ # @param clients [Checkoff::Clients]
16
22
  def initialize(config: Checkoff::Internal::ConfigLoader.load(:asana),
17
- projects: Checkoff::Projects.new(config: config))
23
+ projects: Checkoff::Projects.new(config: config),
24
+ clients: Checkoff::Clients.new(config: config))
18
25
  @projects = projects
26
+ @client = clients.client
19
27
  end
20
28
 
21
29
  # True if all subtasks of the task are completed
30
+ #
31
+ # @param task [Asana::Resources::Task]
22
32
  def all_subtasks_completed?(task)
23
- raw_subtasks = raw_subtasks(task)
24
- active_subtasks = @projects.active_tasks(raw_subtasks)
33
+ rs = raw_subtasks(task)
34
+ active_subtasks = @projects.active_tasks(rs)
25
35
  # anything left should be a section
26
36
  active_subtasks.all? { |subtask| subtask_section?(subtask) }
27
37
  end
28
38
 
29
39
  # pulls a Hash of subtasks broken out by section
40
+ #
30
41
  # @param tasks [Enumerable<Asana::Resources::Task>]
42
+ #
31
43
  # @return [Hash<[nil,String], Enumerable<Asana::Resources::Task>>]
32
44
  def by_section(tasks)
33
45
  current_section = nil
34
46
  by_section = { nil => [] }
35
47
  tasks.each do |task|
48
+ # @sg-ignore
36
49
  current_section, by_section = file_task_by_section(current_section,
37
50
  by_section, task)
38
51
  end
@@ -40,26 +53,59 @@ module Checkoff
40
53
  end
41
54
 
42
55
  # Returns all subtasks, including section headers
56
+ #
57
+ # @param task [Asana::Resources::Task]
58
+ #
59
+ # @return [Enumerable<Asana::Resources::Task>]
43
60
  def raw_subtasks(task)
44
- task_options = projects.task_options
45
- task_options[:options][:fields] << 'is_rendered_as_separator'
46
- task.subtasks(**task_options)
61
+ subtasks_by_gid(task.gid)
47
62
  end
48
- cache_method :raw_subtasks, SHORT_CACHE_TIME
63
+ cache_method :raw_subtasks, LONG_CACHE_TIME
64
+
65
+ # Pull a specific task by GID
66
+ #
67
+ # @param task_gid [String]
68
+ # @param extra_fields [Array<String>]
69
+ # @param only_uncompleted [Boolean]
70
+ #
71
+ # @return [Enumerable<Asana::Resources::Task>]
72
+ def subtasks_by_gid(task_gid,
73
+ extra_fields: [],
74
+ only_uncompleted: true)
75
+ # @type [Hash]
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, {})
79
+ client.tasks.get_subtasks_for_task(task_gid: task_gid,
80
+ # per_page: 100, # stub doesn't have this arg available
81
+ options: options)
82
+ end
83
+ cache_method :subtasks_by_gid, LONG_CACHE_TIME
49
84
 
50
85
  # True if the subtask passed in represents a section in the subtasks
51
86
  #
52
87
  # Note: expect this to be removed in a future version, as Asana is
53
88
  # expected to move to the new-style way of representing sections
54
89
  # as memberships with a separate API within a task.
90
+ #
91
+ # @param subtask [Asana::Resources::Task]
55
92
  def subtask_section?(subtask)
56
93
  subtask.is_rendered_as_separator
57
94
  end
58
95
 
59
96
  private
60
97
 
98
+ # @return [Checkoff::Projects]
61
99
  attr_reader :projects
62
100
 
101
+ # @return [Asana::Client]
102
+ attr_reader :client
103
+
104
+ # @param current_section [String,nil]
105
+ # @param by_section [Hash]
106
+ # @param task [Asana::Resources::Task]
107
+ #
108
+ # @return [Array<(String, Hash)>]
63
109
  def file_task_by_section(current_section, by_section, task)
64
110
  if subtask_section?(task)
65
111
  current_section = task.name
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 = build_task_options(projects.task_options, extra_fields, only_uncompleted)
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
- options = projects.task_options[:options]
197
- options[:fields] += ['custom_fields']
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
@@ -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 = projects.task_options.fetch(:options, {})
161
- options[:fields] += extra_fields
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
@@ -3,5 +3,5 @@
3
3
  # Command-line and gem client for Asana (unofficial)
4
4
  module Checkoff
5
5
  # Version of library
6
- VERSION = '0.192.0'
6
+ VERSION = '0.194.0'
7
7
  end
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.192.0
4
+ version: 0.194.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-05 00:00:00.000000000 Z
11
+ date: 2024-02-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport