checkoff 0.128.0 → 0.129.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: bdeff27a19c7a24911c5864a8f376979b78e19b17d56992cb1e9ef1c33c815f5
4
- data.tar.gz: 0e7ad84caa524a58699903a35b08b0865c6c32b5d494ab654b9df5c68506c97c
3
+ metadata.gz: 1c9d07ad7181d5b4c1dcf0df6542f92e5468a4ffef70231dc2c4a35f03f9fd45
4
+ data.tar.gz: fff0a9a8e7663a71e4c5a257b709fcebe57e712d4536d12b1890834c1dd75be5
5
5
  SHA512:
6
- metadata.gz: 34d9d43590df498315a1ee700c812de55e014e2b9f67a41b725baa8da89e907f93c6af5486275743e9bfb52e4a80f95089026dd5feb82f13e470f58f477cf037
7
- data.tar.gz: f6c41733167ddc1966d12fba1b6a00ab634eba365748531e4e9dde5096becb6e8dc43cc0fa07ffb330e5cfd18b00dbe2c81ee10d6c1c6f22837bb0273025908c
6
+ metadata.gz: ddebe33692c02e9798a4ffa65b9ba105c1a3a62c7f6482fccbf9fd2ca4ba9cce443680a26f4b488f40d3a8316baf70b9acfaa811e79cf552bc1fc900d62da48f
7
+ data.tar.gz: 1b49aeddc864873a270b08076d2d6ba9b107b25a8113714fd9e7a2e14b19e38ea59d143d33f6d75f6e1be23444230d25fdfcaf10bd0f8d82552f7b333a907a0e
data/GLOSSARY.md CHANGED
@@ -2,10 +2,15 @@
2
2
 
3
3
  * ready: See tasks.rb#task_ready?. Indicates a task is ready for
4
4
  a person to work on it. This is subtly different than what is used
5
- by Asana to mark a date as red/green! A task is ready if it is not
6
- dependent on an incomplete task and one of these is true:
5
+ by Asana to mark a date as red/green!
6
+
7
+ A task is ready if it is not dependent on an incomplete task and one
8
+ of these is true:
7
9
 
8
10
  * start is null and due on is today
9
11
  * start is null and due at is before now
10
12
  * start on is today
11
13
  * start at is before now
14
+
15
+ A project is ready if there is no start date, or if the start date
16
+ is today or in the past.
data/Gemfile.lock CHANGED
@@ -12,7 +12,7 @@ GIT
12
12
  PATH
13
13
  remote: .
14
14
  specs:
15
- checkoff (0.128.0)
15
+ checkoff (0.129.0)
16
16
  activesupport
17
17
  asana (> 0.10.0)
18
18
  cache_method
@@ -209,6 +209,13 @@
209
209
  #
210
210
  # # @return [Asana::Resources::Portfolio,nil]
211
211
  # def find_by_id(client, id, options: {}); end
212
+ # # Get portfolio items
213
+ # #
214
+ # # @param portfolio_gid [String] (required) Globally unique identifier for the portfolio.
215
+ # # @param options [Hash] the request I/O options
216
+ # #
217
+ # # @return [Enumerable<Asana::Resources::Project>]
218
+ # def get_items_for_portfolio(portfolio_gid: required("portfolio_gid"), options: {}); end
212
219
  # end
213
220
  # class User
214
221
  # # Returns the full user record for the currently authenticated user.
@@ -0,0 +1,80 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Checkoff
4
+ module Internal
5
+ # Utility methods for working with project dates and times
6
+ class ProjectTiming
7
+ # @param time_class [Class<Time>]
8
+ # @param date_class [Class<Date>]
9
+ # @param client [Asana::Client]
10
+ # @param custom_fields [Checkoff::CustomFields]
11
+ def initialize(time_class: Time, date_class: Date,
12
+ client: Checkoff::Clients.new.client,
13
+ custom_fields: Checkoff::CustomFields.new(client: client))
14
+ @time_class = time_class
15
+ @date_class = date_class
16
+ @custom_fields = custom_fields
17
+ end
18
+
19
+ # @param project [Asana::Resources::Project]
20
+ # @param field_name [Symbol]
21
+ #
22
+ # @sg-ignore
23
+ # @return [Date, nil]
24
+ def start_date(project)
25
+ return @date_class.parse(project.start_on) unless project.start_on.nil?
26
+
27
+ nil
28
+ end
29
+
30
+ # @param project [Asana::Resources::Project]
31
+ # @param field_name [Symbol]
32
+ #
33
+ # @sg-ignore
34
+ # @return [Date, nil]
35
+ def due_date(project)
36
+ return @date_class.parse(project.due_on) unless project.due_on.nil?
37
+
38
+ nil
39
+ end
40
+
41
+ # @param project [Asana::Resources::Project]
42
+ # @param custom_field_name [String]
43
+ #
44
+ # @return [Time, Date, nil]
45
+ def custom_field(project, custom_field_name)
46
+ custom_field = @custom_fields.resource_custom_field_by_name_or_raise(project, custom_field_name)
47
+ # @sg-ignore
48
+ # @type [String, nil]
49
+ time_str = custom_field.fetch('display_value')
50
+ return nil if time_str.nil?
51
+
52
+ Time.parse(time_str)
53
+ end
54
+
55
+ # @param project [Asana::Resources::Project]
56
+ # @param field_name [Symbol,Array]
57
+ #
58
+ # @sg-ignore
59
+ # @return [Date, Time, nil]
60
+ def date_or_time_field_by_name(project, field_name)
61
+ return due_date(project) if field_name == :due
62
+
63
+ return start_date(project) if field_name == :start
64
+
65
+ return start_date(project) if field_name == :ready
66
+
67
+ if field_name.is_a?(Array)
68
+ # @sg-ignore
69
+ # @type [Symbol]
70
+ actual_field_name = field_name.first
71
+ args = field_name[1..]
72
+
73
+ return custom_field(project, *args) if actual_field_name == :custom_field
74
+ end
75
+
76
+ raise "Teach me how to handle field #{field_name}"
77
+ end
78
+ end
79
+ end
80
+ end
@@ -20,6 +20,22 @@ module Checkoff
20
20
  resource.due_date
21
21
  end
22
22
  end
23
+
24
+ # :ready? function
25
+ class ReadyPFunctionEvaluator < FunctionEvaluator
26
+ FUNCTION_NAME = :ready?
27
+
28
+ def matches?
29
+ fn?(selector, FUNCTION_NAME)
30
+ end
31
+
32
+ # @param project [Asana::Resources::Project]
33
+ # @param period [Symbol<:now_or_before,:this_week>]
34
+ # @return [Boolean]
35
+ def evaluate(project, period = :now_or_before)
36
+ @projects.project_ready?(project, period: period)
37
+ end
38
+ end
23
39
  end
24
40
  end
25
41
  end
@@ -99,7 +99,7 @@ module Checkoff
99
99
  fields: ['name'],
100
100
  }
101
101
  options[:fields] += extra_project_fields
102
- portfolio.get_items(options: options)
102
+ client.portfolios.get_items_for_portfolio(portfolio_gid: portfolio.gid, options: options)
103
103
  end
104
104
 
105
105
  private
@@ -2,6 +2,7 @@
2
2
 
3
3
  require_relative 'internal/config_loader'
4
4
  require_relative 'internal/project_hashes'
5
+ require_relative 'internal/project_timing'
5
6
  require_relative 'workspaces'
6
7
  require_relative 'clients'
7
8
  require 'cache_method'
@@ -32,15 +33,21 @@ module Checkoff
32
33
  # @param client [Asana::Client]
33
34
  # @param workspaces [Checkoff::Workspaces]
34
35
  # @param project_hashes [Checkoff::Internal::ProjectHashes]
36
+ # @param project_timing [Checkoff::Internal::ProjectTiming]
37
+ # @param timing [Checkoff::Timing]
35
38
  def initialize(config: Checkoff::Internal::ConfigLoader.load(:asana),
36
39
  client: Checkoff::Clients.new(config: config).client,
37
40
  workspaces: Checkoff::Workspaces.new(config: config,
38
41
  client: client),
39
- project_hashes: Checkoff::Internal::ProjectHashes.new)
42
+ project_hashes: Checkoff::Internal::ProjectHashes.new,
43
+ project_timing: Checkoff::Internal::ProjectTiming.new(client: client),
44
+ timing: Checkoff::Timing.new)
40
45
  @config = config
41
46
  @workspaces = workspaces
42
47
  @client = client
43
48
  @project_hashes = project_hashes
49
+ @project_timing = project_timing
50
+ @timing = timing
44
51
  end
45
52
 
46
53
  # Default options used in Asana API to pull tasks
@@ -139,8 +146,37 @@ module Checkoff
139
146
  project_hashes.project_to_h(project_obj, project: project)
140
147
  end
141
148
 
149
+ # Indicates a project is ready for a person to work on it. This
150
+ # is subtly different than what is used by Asana to mark a date as
151
+ # red/green!
152
+ #
153
+ # A project is ready if there is no start date, or if the start
154
+ # date is today or in the past.
155
+ #
156
+ # @param project [Asana::Resources::Project]
157
+ # @param period [Symbol<:now_or_before,:this_week>]
158
+ def project_ready?(project, period: :now_or_before)
159
+ in_period?(project, :ready, period)
160
+ end
161
+
162
+ # @param project [Asana::Resources::Project]
163
+ # @param field_name [Symbol,Array]
164
+ # @param period [Symbol<:now_or_before,:this_week>,Array] See Checkoff::Timing#in_period?
165
+ def in_period?(project, field_name, period)
166
+ # @type [Date,Time,nil]
167
+ project_date = project_timing.date_or_time_field_by_name(project, field_name)
168
+
169
+ timing.in_period?(project_date, period)
170
+ end
171
+
142
172
  private
143
173
 
174
+ # @return [Checkoff::Timing]
175
+ attr_reader :timing
176
+
177
+ # @return [Checkoff::Internal::ProjectTiming]
178
+ attr_reader :project_timing
179
+
144
180
  # @return [Checkoff::Internal::ProjectHashes]
145
181
  attr_reader :project_hashes
146
182
 
@@ -54,7 +54,7 @@ module Checkoff
54
54
  @portfolios = portfolios
55
55
  @custom_fields = custom_fields
56
56
  @workspaces = workspaces
57
- @timing = Timing.new(today_getter: date_class, now_getter: time_class)
57
+ @timing = Checkoff::Timing.new(today_getter: date_class, now_getter: time_class)
58
58
  end
59
59
 
60
60
  # Indicates a task is ready for a person to work on it. This is
@@ -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.128.0'
6
+ VERSION = '0.129.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.128.0
4
+ version: 0.129.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-11-04 00:00:00.000000000 Z
11
+ date: 2023-11-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -135,6 +135,7 @@ files:
135
135
  - lib/checkoff/internal/create-class.sh
136
136
  - lib/checkoff/internal/project_hashes.rb
137
137
  - lib/checkoff/internal/project_selector_evaluator.rb
138
+ - lib/checkoff/internal/project_timing.rb
138
139
  - lib/checkoff/internal/search_url.rb
139
140
  - lib/checkoff/internal/search_url/custom_field_param_converter.rb
140
141
  - lib/checkoff/internal/search_url/custom_field_variant.rb