checkoff 0.53.1 → 0.55.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: 234864e30843bb30b598e38ef8e2571a6b5f6bbf37f07db7af5d4249ffe8ada2
4
- data.tar.gz: 4e2eef390cc3fca5a3022a816811acadfc710983ec96f288567d6892f7d08e22
3
+ metadata.gz: e441dfbcef11d610f73873858235bd110aa27b730a40eca5c5a38aac3e27ff5c
4
+ data.tar.gz: 4810a4c39437830b9dd6a909102328d6f413600a30bf2fe92702d1a59fe4ae61
5
5
  SHA512:
6
- metadata.gz: b035b186ac2b3fd74507020d165aa4b50c1c95d1a5848cbae0f579013dbf4fd6c6b0a3f648b00901544c525924ea7596009446777bb91db3ca5412fad6448136
7
- data.tar.gz: c35c867d9aaac72f54355fb371ea298afb55ccf9502d6baca0f2bc928ca4a0896a3bd5c784c052a6f566852933fbac88dd51a2d0764e4940edd132b5d21f5c8d
6
+ metadata.gz: '08ad245068e7a1278a90943eff26e239175aa2874b9db59b682448f3069f8d3e71bddae0f21cefcddf2f315a95cfc0094800759487953fb519be6af9935886d1'
7
+ data.tar.gz: 02c0f071c4d722f26014d2029e13794a26e15ab1396291177e80b8d4506e301bd33b2e3984296314e8a57bf522c589c1a9f4684810564f8f3b387b1e780bbbe3
data/.solargraph.yml CHANGED
@@ -3,6 +3,9 @@ include:
3
3
  - "**/*.rb"
4
4
  - ".git-hooks/**/*.rb"
5
5
  exclude:
6
+ - spec/**/*
7
+ - feature/**/*
8
+ - test/**/*
6
9
  - vendor/**/*
7
10
  - ".bundle/**/*"
8
11
  require: []
data/Gemfile.lock CHANGED
@@ -12,7 +12,7 @@ GIT
12
12
  PATH
13
13
  remote: .
14
14
  specs:
15
- checkoff (0.53.1)
15
+ checkoff (0.55.0)
16
16
  activesupport
17
17
  asana (> 0.10.0)
18
18
  cache_method
@@ -13,34 +13,88 @@ module Checkoff
13
13
  @date_url_params = date_url_params
14
14
  end
15
15
 
16
+ # @sg-ignore
17
+ # @return [Array(Hash<String, String>, Array<[Symbol, Array]>)]
18
+ def convert
19
+ return [{}, []] if date_url_params.empty?
20
+
21
+ out = nil
22
+
23
+ %w[due_date start_date].each do |prefix|
24
+ next unless date_url_params.key? "#{prefix}.operator"
25
+ raise 'Teach me how to handle simultaneous date parameters' unless out.nil?
26
+
27
+ out = convert_for_prefix(prefix)
28
+ end
29
+
30
+ raise "Teach me to handle these parameters: #{date_url_params.inspect}" unless date_url_params.empty?
31
+
32
+ out
33
+ end
34
+
35
+ private
36
+
37
+ # @sg-ignore
38
+ # @param prefix [String]
39
+ # @return [Array(Hash<String, String>, Array<[Symbol, Array]>)]
40
+ def convert_for_prefix(prefix)
41
+ # example params:
42
+ # due_date.operator=through_next
43
+ # due_date.value=0
44
+ # due_date.unit=day
45
+ operator = get_single_param("#{prefix}.operator")
46
+
47
+ out = if operator == 'through_next'
48
+ handle_through_next(prefix)
49
+ elsif operator == 'between'
50
+ handle_between(prefix)
51
+ else
52
+ raise "Teach me how to handle date mode: #{operator.inspect}."
53
+ end
54
+
55
+ # mark these as done by deleting from the hash
56
+ date_url_params.delete_if { |k, _| k.start_with? prefix }
57
+
58
+ out
59
+ end
60
+
61
+ # https://developers.asana.com/docs/search-tasks-in-a-workspace
62
+ API_PREFIX = {
63
+ 'due_date' => 'due_on',
64
+ 'start_date' => 'start_on',
65
+ }.freeze
66
+
67
+ # @param prefix [String]
16
68
  # @return [Array(Hash<String, String>, Array<[Symbol, Array]>)] See https://developers.asana.com/docs/search-tasks-in-a-workspace
17
- def handle_through_next
18
- due_date_value = get_single_param('due_date.value').to_i
69
+ def handle_through_next(prefix)
70
+ value = get_single_param("#{prefix}.value").to_i
19
71
 
20
- validate_unit_is_day!
72
+ validate_unit_is_day!(prefix)
21
73
 
22
74
  # @sg-ignore
23
75
  # @type [Date]
24
- before = Date.today + due_date_value
76
+ before = Date.today + value
77
+
25
78
  # 'due_on.before' => '2023-01-01',
26
79
  # 'due_on.after' => '2023-01-01',
27
80
  # [{ 'due_on.before' => '2023-09-01' }, []]
28
- [{ 'due_on.before' => before.to_s }, []]
81
+ [{ "#{API_PREFIX.fetch(prefix)}.before" => before.to_s }, []]
29
82
  end
30
83
 
84
+ # @param prefix [String]
31
85
  # @return [Array(Hash<String, String>, Array<[Symbol, Array]>)] See https://developers.asana.com/docs/search-tasks-in-a-workspace
32
- def handle_between
33
- due_date_after = get_single_param('due_date.after')
34
- raise 'Teach me how to handle due_date_before' if date_url_params.key? 'due_date.before'
86
+ def handle_between(prefix)
87
+ after = get_single_param("#{prefix}.after")
88
+ raise "Teach me how to handle #{prefix}.before" if date_url_params.key? "#{prefix}.before"
35
89
 
36
- validate_unit_not_provided!
90
+ validate_unit_not_provided!(prefix)
37
91
 
38
92
  # Example value: 1702857600000
39
93
  # +1 is because API seems to operate on inclusive ranges
40
94
  # @type [Date]
41
95
  # @sg-ignore
42
- after = Time.at(due_date_after.to_i / 1000).to_date + 1
43
- [{ 'due_on.after' => after.to_s }, []]
96
+ after = Time.at(after.to_i / 1000).to_date + 1
97
+ [{ "#{API_PREFIX.fetch(prefix)}.after" => after.to_s }, []]
44
98
  end
45
99
 
46
100
  # @param param_key [String]
@@ -55,37 +109,20 @@ module Checkoff
55
109
  value[0]
56
110
  end
57
111
 
58
- # @return [Array(Hash<String, String>, Array<[Symbol, Array]>)]
59
- def convert
60
- return [{}, []] if date_url_params.empty?
61
-
62
- # example params:
63
- # due_date.operator=through_next
64
- # due_date.value=0
65
- # due_date.unit=day
66
- due_date_operator = get_single_param('due_date.operator')
67
-
68
- return handle_through_next if due_date_operator == 'through_next'
69
-
70
- return handle_between if due_date_operator == 'between'
71
-
72
- raise "Teach me how to handle date mode: #{due_date_operator.inspect}."
73
- end
74
-
75
- private
76
-
112
+ # @param prefix [String]
77
113
  # @return [void]
78
- def validate_unit_not_provided!
79
- return unless date_url_params.key? 'due_date.unit'
114
+ def validate_unit_not_provided!(prefix)
115
+ return unless date_url_params.key? "#{prefix}.unit"
80
116
 
81
- raise "Teach me how to handle other due_date.unit for these params: #{date_url_params.inspect}"
117
+ raise "Teach me how to handle other #{prefix}.unit for these params: #{date_url_params.inspect}"
82
118
  end
83
119
 
120
+ # @param prefix [String]
84
121
  # @return [void]
85
- def validate_unit_is_day!
86
- unit = date_url_params.fetch('due_date.unit').fetch(0)
122
+ def validate_unit_is_day!(prefix)
123
+ unit = date_url_params.fetch("#{prefix}.unit").fetch(0)
87
124
 
88
- raise 'Teach me how to handle other time units' unless unit == 'day'
125
+ raise "Teach me how to handle other time units: #{unit}" unless unit == 'day'
89
126
  end
90
127
 
91
128
  # @return [Hash<String, Array<String>>]
@@ -484,6 +484,38 @@ module Checkoff
484
484
  end
485
485
  end
486
486
 
487
+ # :last_story_created_less_than_n_days_ago function
488
+ class LastStoryCreatedLessThanNDaysAgoFunctionEvaluator < FunctionEvaluator
489
+ FUNCTION_NAME = :last_story_created_less_than_n_days_ago
490
+
491
+ def matches?
492
+ fn?(task_selector, FUNCTION_NAME)
493
+ end
494
+
495
+ def evaluate_arg?(_index)
496
+ false
497
+ end
498
+
499
+ # @param task [Asana::Resources::Task]
500
+ # @param num_days [Integer]
501
+ # @param excluding_resource_subtypes [Array<String>]
502
+ # @return [Boolean]
503
+ def evaluate(task, num_days, excluding_resource_subtypes)
504
+ # for whatever reason, .last on the enumerable does not impose ordering; .to_a does!
505
+
506
+ # @type [Array<Asana::Resources::Story>]
507
+ stories = task.stories.to_a.reject do |story|
508
+ excluding_resource_subtypes.include? story.resource_subtype
509
+ end
510
+ return true if stories.empty? # no stories == infinitely old!
511
+
512
+ last_story = stories.last
513
+ last_story_created_at = Time.parse(last_story.created_at)
514
+ n_days_ago = Time.now - (num_days * 24 * 60 * 60)
515
+ last_story_created_at < n_days_ago
516
+ end
517
+ end
518
+
487
519
  # String literals
488
520
  class StringLiteralEvaluator < FunctionEvaluator
489
521
  def matches?
@@ -567,6 +599,7 @@ module Checkoff
567
599
  Checkoff::TaskSelectorClasses::FieldGreaterThanOrEqualToNDaysFromTodayFunctionEvaluator,
568
600
  Checkoff::TaskSelectorClasses::CustomFieldLessThanNDaysFromNowFunctionEvaluator,
569
601
  Checkoff::TaskSelectorClasses::CustomFieldGreaterThanOrEqualToNDaysFromNowFunctionEvaluator,
602
+ Checkoff::TaskSelectorClasses::LastStoryCreatedLessThanNDaysAgoFunctionEvaluator,
570
603
  Checkoff::TaskSelectorClasses::StringLiteralEvaluator,
571
604
  Checkoff::TaskSelectorClasses::EstimateExceedsDurationFunctionEvaluator,
572
605
  ].freeze
@@ -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.53.1'
6
+ VERSION = '0.55.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.53.1
4
+ version: 0.55.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-09-12 00:00:00.000000000 Z
11
+ date: 2023-09-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport