checkoff 0.93.0 → 0.95.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: 49531006387df986e746c99973d425917777230710978cad819951ca8d696d7b
4
- data.tar.gz: ef9ea84d3a708b8a47425c77a63f83241f310d2b9b0fd71e01f15ec00d5eb4d7
3
+ metadata.gz: 31607f856925472f48fd4ae56a34d190bef6ea7105086b399e1f2755a0f1dfa5
4
+ data.tar.gz: 8af77b66a6a15caa5e5f3c5b46746f042d30d6ff56742845a6c537b3afe01d11
5
5
  SHA512:
6
- metadata.gz: 7d5e93cea9b3b00bb6d7622e7aa4aa93229820683118f72414ac60dd7b3fafd36fac60e1a79a16fc6091b4ba051ae3cc818b0e2f8c5a354ae57b4b849b562af0
7
- data.tar.gz: e4f24e5b32dfce8459a3c04fc89ba0b831f0d50f61dcc780864f441b1e119f29f774f2b47503ef6653b285b60c58273bb0bca8a80aa7feacea517019ce8139c1
6
+ metadata.gz: 5da70b5bbbd6538afa7b7953dfff42ec6377afe959f224c548d8886e64b36f1c101425c1ee51e6fced39ed8b06baa5f3c0f1aa96e92078cfebf1e1949ae4c3c9
7
+ data.tar.gz: 93f0ae0f4b00cf74cad672b3492b927ea72dc9f2dabd9b052e98da20098953848a69c55e79bcceda6ce6ce8c21fa77b0c08aff8f3378d0cb15a516f17e04a23e
data/Gemfile.lock CHANGED
@@ -12,7 +12,7 @@ GIT
12
12
  PATH
13
13
  remote: .
14
14
  specs:
15
- checkoff (0.93.0)
15
+ checkoff (0.95.0)
16
16
  activesupport
17
17
  asana (> 0.10.0)
18
18
  cache_method
@@ -50,6 +50,8 @@
50
50
  # def assignee; end
51
51
  # # @return [String, nil]
52
52
  # def html_notes; end
53
+ # # @return [Array<Hash{String => Hash{String => String}}>]
54
+ # def memberships; end
53
55
  # class << self
54
56
  # # @return [Asana::Resources::Task]
55
57
  # def create(client, assignee:, workspace:, name:); end
@@ -0,0 +1,57 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Checkoff
4
+ module Internal
5
+ # Builds on the standard API representation of an Asana task with some
6
+ # convenience keys.
7
+ class TaskHashes
8
+ # @param task [Asana::Resources::Task]
9
+ # @return [Hash]
10
+ def task_to_h(task)
11
+ # @type [Hash]
12
+ task_hash = task.to_h
13
+ task_hash['unwrapped'] = {}
14
+ unwrap_custom_fields(task_hash)
15
+ unwrap_memberships(task_hash)
16
+ task_hash['task'] = task.name
17
+ task_hash
18
+ end
19
+
20
+ private
21
+
22
+ # @param task_hash [Hash]
23
+ # @return [void]
24
+ def unwrap_custom_fields(task_hash)
25
+ unwrapped_custom_fields = task_hash.fetch('custom_fields', []).group_by do |cf|
26
+ cf['name']
27
+ end.transform_values(&:first)
28
+ task_hash['unwrapped']['custom_fields'] = unwrapped_custom_fields
29
+ end
30
+
31
+ # @param task_hash [Hash]
32
+ # @param resource [String]
33
+ # @param key [String]
34
+ #
35
+ # @return [void]
36
+ def unwrap_membership(task_hash, resource, key)
37
+ # @sg-ignore
38
+ # @type [Array<Hash>]
39
+ memberships = task_hash.fetch('memberships', [])
40
+ # @sg-ignore
41
+ # @type [Hash]
42
+ unwrapped = task_hash.fetch('unwrapped')
43
+ unwrapped["membership_by_#{resource}_#{key}"] = memberships.group_by do |membership|
44
+ membership[resource][key]
45
+ end.transform_values(&:first)
46
+ end
47
+
48
+ # @param task_hash [Hash]
49
+ # @return [void]
50
+ def unwrap_memberships(task_hash)
51
+ unwrap_membership(task_hash, 'section', 'gid')
52
+ unwrap_membership(task_hash, 'project', 'gid')
53
+ unwrap_membership(task_hash, 'project', 'name')
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Checkoff
4
+ module Internal
5
+ # Utility methods for working with task dates and times
6
+ class TaskTiming
7
+ # @param time_class [Class<Time>]
8
+ def initialize(time_class: Time)
9
+ @time_class = time_class
10
+ end
11
+
12
+ # @param task [Asana::Resources::Task]
13
+ # @return [Time, nil]
14
+ def start_time(task)
15
+ return @time_class.parse(task.start_at) if task.start_at
16
+ return @time_class.parse(task.start_on) if task.start_on
17
+
18
+ nil
19
+ end
20
+
21
+ # @param task [Asana::Resources::Task]
22
+ # @return [Time, nil]
23
+ def due_time(task)
24
+ return @time_class.parse(task.due_at) if task.due_at
25
+ return @time_class.parse(task.due_on) if task.due_on
26
+
27
+ nil
28
+ end
29
+ end
30
+ end
31
+ end
@@ -5,6 +5,8 @@
5
5
  require_relative 'sections'
6
6
  require_relative 'workspaces'
7
7
  require_relative 'internal/config_loader'
8
+ require_relative 'internal/task_timing'
9
+ require_relative 'internal/task_hashes'
8
10
  require 'asana'
9
11
 
10
12
  module Checkoff
@@ -57,8 +59,8 @@ module Checkoff
57
59
  def task_ready?(task, ignore_dependencies: false)
58
60
  return false if !ignore_dependencies && incomplete_dependencies?(task)
59
61
 
60
- start = start_time(task)
61
- due = due_time(task)
62
+ start = task_timing.start_time(task)
63
+ due = task_timing.due_time(task)
62
64
 
63
65
  return true if start.nil? && due.nil?
64
66
 
@@ -79,12 +81,12 @@ module Checkoff
79
81
  only_uncompleted: true,
80
82
  extra_fields: [])
81
83
  # @sg-ignore
82
- tasks = tasks_from_section(workspace_name,
83
- project_name,
84
- section_name: section_name,
85
- only_uncompleted: only_uncompleted,
86
- extra_fields: extra_fields)
87
- tasks.find { |task| task.name == task_name }
84
+ t = tasks(workspace_name,
85
+ project_name,
86
+ section_name: section_name,
87
+ only_uncompleted: only_uncompleted,
88
+ extra_fields: extra_fields)
89
+ t.find { |task| task.name == task_name }
88
90
  end
89
91
  cache_method :task, SHORT_CACHE_TIME
90
92
 
@@ -144,18 +146,44 @@ module Checkoff
144
146
  end
145
147
  end
146
148
 
149
+ # Builds on the standard API representation of an Asana task with some
150
+ # convenience keys:
151
+ #
152
+ # <regular keys from API response>
153
+ # +
154
+ # unwrapped:
155
+ # membership_by_section_gid: Hash<String, Hash (membership)>
156
+ # membership_by_project_gid: Hash<String, Hash (membership)>
157
+ # membership_by_project_name: Hash<String, Hash (membership)>
158
+ # task: String (name)
159
+ #
160
+ # @param task [Asana::Resources::Task]
161
+ # @return [Hash]
162
+ def task_to_h(task)
163
+ task_hashes.task_to_h(task)
164
+ end
165
+
147
166
  private
148
167
 
168
+ # @return [Checkoff::Internal::TaskTiming]
169
+ def task_timing
170
+ @task_timing ||= Checkoff::Internal::TaskTiming.new(time_class: @time_class)
171
+ end
172
+
173
+ # @return [Checkoff::Internal::TaskHashes]
174
+ def task_hashes
175
+ @task_hashes ||= Checkoff::Internal::TaskHashes.new
176
+ end
177
+
149
178
  # @param workspace_name [String]
150
179
  # @param project_name [String, Symbol]
151
- # @param section_name [String, nil, :unspecified]
180
+ # @param section_name [String, nil, Symbol<:unspecified>]
152
181
  # @param only_uncompleted [Boolean]
153
182
  # @param extra_fields [Array<String>]
183
+ #
154
184
  # @return [Enumerable<Asana::Resources::Task>]
155
- def tasks_from_section(workspace_name, project_name,
156
- section_name:,
157
- only_uncompleted:,
158
- extra_fields:)
185
+ def tasks(workspace_name, project_name,
186
+ only_uncompleted:, extra_fields:, section_name: :unspecified)
159
187
  if section_name == :unspecified
160
188
  project = projects.project_or_raise(workspace_name, project_name)
161
189
  projects.tasks_from_project(project,
@@ -182,23 +210,5 @@ module Checkoff
182
210
  def default_assignee_gid
183
211
  @config.fetch(:default_assignee_gid)
184
212
  end
185
-
186
- # @param task [Asana::Resources::Task]
187
- # @return [Time, nil]
188
- def start_time(task)
189
- return @time_class.parse(task.start_at) if task.start_at
190
- return @time_class.parse(task.start_on) if task.start_on
191
-
192
- nil
193
- end
194
-
195
- # @param task [Asana::Resources::Task]
196
- # @return [Time, nil]
197
- def due_time(task)
198
- return @time_class.parse(task.due_at) if task.due_at
199
- return @time_class.parse(task.due_on) if task.due_on
200
-
201
- nil
202
- end
203
213
  end
204
214
  end
@@ -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.93.0'
6
+ VERSION = '0.95.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.93.0
4
+ version: 0.95.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: 2023-10-22 00:00:00.000000000 Z
11
+ date: 2023-10-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -152,7 +152,9 @@ files:
152
152
  - lib/checkoff/internal/selector_classes/task.rb
153
153
  - lib/checkoff/internal/selector_classes/task/function_evaluator.rb
154
154
  - lib/checkoff/internal/selector_evaluator.rb
155
+ - lib/checkoff/internal/task_hashes.rb
155
156
  - lib/checkoff/internal/task_selector_evaluator.rb
157
+ - lib/checkoff/internal/task_timing.rb
156
158
  - lib/checkoff/my_tasks.rb
157
159
  - lib/checkoff/portfolios.rb
158
160
  - lib/checkoff/project_selectors.rb