checkoff 0.11.1 → 0.12.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f4eeb7148c4b835088d3fedc674bf3195b92c9889bfe935a745b50e0b7228c65
4
- data.tar.gz: 2a48471aae38c5ed10bed024968bb51ccd772f1e1efe3acd70b7a4c92bbb59ae
3
+ metadata.gz: 28bce7b1402a371b87f03a468cb1678cd02f7631a2a8f195a544b2bccc4af26e
4
+ data.tar.gz: f645e96e4526173f33e7b3140d9fec84b59330a4050819467a4456f0b9e10679
5
5
  SHA512:
6
- metadata.gz: cf4c95afee408b7937ea09c543c21e50b2855eba0393d9ac542e8d67f4eeb9c02c67b82cb23b7b00a81ca09f9678fafbe294baf947d3fcf1418ecd0208947298
7
- data.tar.gz: 3ec3e6ef6b0a6c1583a96326cd0fa545b500f61e21ddc97624aeab31dadcd9125928d2bc78bbb8e7ec2827837d700ab651d5bb26a201ddf2a14acb862c246777
6
+ metadata.gz: 1503cc4b41f8297a806b57311c2f7f3e0e6d7b93027109125c985b4dba056e2709fdcec43d5ca312f9778ba044d67c28e8a5c055a692b7067ebf442491de912e
7
+ data.tar.gz: 1b30b11537a9608e84ec1434c67a47579e0d6d2a8a88ee79084de24efc39c18e8b10fc1af5be5ccf7b4aac17509b4b16d540d2f4f2304b61f3100b0006ff2af4
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- checkoff (0.11.1)
4
+ checkoff (0.12.0)
5
5
  activesupport
6
6
  asana (> 0.10.0)
7
7
  cache_method
@@ -11,7 +11,7 @@ PATH
11
11
  GEM
12
12
  remote: https://rubygems.org/
13
13
  specs:
14
- activesupport (6.1.3.2)
14
+ activesupport (6.1.4)
15
15
  concurrent-ruby (~> 1.0, >= 1.0.2)
16
16
  i18n (>= 1.6, < 2)
17
17
  minitest (>= 5.1)
@@ -31,25 +31,29 @@ GEM
31
31
  concurrent-ruby (1.1.9)
32
32
  dalli (2.7.11)
33
33
  docile (1.4.0)
34
- faraday (1.4.2)
34
+ faraday (1.5.1)
35
35
  faraday-em_http (~> 1.0)
36
36
  faraday-em_synchrony (~> 1.0)
37
37
  faraday-excon (~> 1.1)
38
+ faraday-httpclient (~> 1.0.1)
38
39
  faraday-net_http (~> 1.0)
39
40
  faraday-net_http_persistent (~> 1.1)
41
+ faraday-patron (~> 1.0)
40
42
  multipart-post (>= 1.2, < 3)
41
43
  ruby2_keywords (>= 0.0.4)
42
44
  faraday-em_http (1.0.0)
43
45
  faraday-em_synchrony (1.0.0)
44
46
  faraday-excon (1.1.0)
47
+ faraday-httpclient (1.0.1)
45
48
  faraday-net_http (1.0.1)
46
- faraday-net_http_persistent (1.1.0)
49
+ faraday-net_http_persistent (1.2.0)
50
+ faraday-patron (1.0.0)
47
51
  faraday_middleware (1.0.0)
48
52
  faraday (~> 1.0)
49
53
  faraday_middleware-multi_json (0.0.6)
50
54
  faraday_middleware
51
55
  multi_json
52
- gli (2.20.0)
56
+ gli (2.20.1)
53
57
  i18n (1.8.10)
54
58
  concurrent-ruby (~> 1.0)
55
59
  imagen (0.1.8)
@@ -96,7 +100,7 @@ GEM
96
100
  rubocop-rake (0.5.1)
97
101
  rubocop
98
102
  ruby-progressbar (1.11.0)
99
- ruby2_keywords (0.0.4)
103
+ ruby2_keywords (0.0.5)
100
104
  rugged (1.1.0)
101
105
  simplecov (0.21.2)
102
106
  docile (~> 1.1)
@@ -136,4 +140,4 @@ DEPENDENCIES
136
140
  undercover
137
141
 
138
142
  BUNDLED WITH
139
- 2.2.19
143
+ 2.2.24
data/README.md CHANGED
@@ -12,7 +12,7 @@ $ checkoff --help
12
12
  View tasks:
13
13
  checkoff view workspace project [section]
14
14
 
15
- 'project' can be set to a project name, or :my_tasks, :my_tasks_upcoming, :my_tasks_new, or :my_tasks_today
15
+ 'project' can be set to a project name, or :my_tasks for your user task list.
16
16
  ```
17
17
 
18
18
  Let's say we have a project like this:
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "result": {
3
- "line": 94.61,
4
- "branch": 71.42
3
+ "line": 97.0,
4
+ "branch": 80.95
5
5
  }
6
6
  }
@@ -35,6 +35,17 @@ module Checkoff
35
35
  @workspaces.client
36
36
  end
37
37
 
38
+ # Default options used in Asana API to pull taskso
39
+ def task_options
40
+ {
41
+ per_page: 100,
42
+ options: {
43
+ fields: %w[name completed_at due_at due_on tags
44
+ memberships.project.gid memberships.section.name dependencies],
45
+ },
46
+ }
47
+ end
48
+
38
49
  # pulls an Asana API project class given a name
39
50
  def project(workspace_name, project_name)
40
51
  if project_name.is_a?(Symbol) && project_name.to_s.start_with?('my_tasks')
@@ -84,15 +95,5 @@ module Checkoff
84
95
  gid = result.gid
85
96
  projects.find_by_id(gid)
86
97
  end
87
-
88
- def task_options
89
- {
90
- per_page: 100,
91
- options: {
92
- fields: %w[name completed_at due_at due_on assignee_status tags
93
- memberships.project.gid memberships.section.name dependencies],
94
- },
95
- }
96
- end
97
98
  end
98
99
  end
@@ -4,7 +4,6 @@ require 'forwardable'
4
4
 
5
5
  module Checkoff
6
6
  # Query different sections of Asana projects
7
- # rubocop:disable Metrics/ClassLength
8
7
  class Sections
9
8
  MINUTE = 60
10
9
  LONG_CACHE_TIME = MINUTE * 15
@@ -23,118 +22,74 @@ module Checkoff
23
22
  @time = time
24
23
  end
25
24
 
26
- # Given a list of tasks, pull a Hash of tasks with section name -> task list
27
- def by_section(tasks, project_gid)
28
- by_section = {}
29
- tasks.each do |task|
30
- file_task_by_section(by_section, task, project_gid)
31
- end
32
- by_section
33
- end
34
- cache_method :by_section, LONG_CACHE_TIME
35
-
36
- # Given a project object, pull all tasks, then provide a Hash of
37
- # tasks with section name -> task list of the uncompleted tasks
38
- def tasks_by_section_for_project(project)
39
- raw_tasks = projects.tasks_from_project(project)
40
- active_tasks = projects.active_tasks(raw_tasks)
41
- by_section(active_tasks, project.gid)
25
+ # Returns a list of Asana API section objects for a given project
26
+ def sections_or_raise(workspace_name, project_name)
27
+ project = project_or_raise(workspace_name, project_name)
28
+ client.sections.get_sections_for_project(project_gid: project.gid)
42
29
  end
43
30
 
44
31
  # Given a workspace name and project name, then provide a Hash of
45
32
  # tasks with section name -> task list of the uncompleted tasks
46
33
  def tasks_by_section(workspace_name, project_name)
47
34
  project = project_or_raise(workspace_name, project_name)
48
- case project_name
49
- when :my_tasks, :my_tasks_new, :my_tasks_today, :my_tasks_upcoming
50
- user_task_list_by_section(workspace_name, project_name)
51
- else
52
- tasks_by_section_for_project(project)
53
- end
35
+ tasks_by_section_for_project(project)
54
36
  end
55
37
  cache_method :tasks_by_section, SHORT_CACHE_TIME
56
38
 
57
39
  # XXX: Rename to section_tasks
58
40
  #
59
41
  # Pulls task objects from a specified section
60
- def tasks(workspace_name, project_name, section_name)
61
- tasks_by_section(workspace_name, project_name).fetch(section_name, [])
42
+ def tasks(workspace_name, project_name, section_name,
43
+ only_uncompleted: true,
44
+ extra_fields: [])
45
+ section = section_or_raise(workspace_name, project_name, section_name)
46
+ options = projects.task_options
47
+ # asana-0.10.3 gem doesn't support per_page - not sure if API
48
+ # itself does
49
+ options.delete(:per_page)
50
+ options[:options][:fields] += extra_fields
51
+ client.tasks.get_tasks_for_section(section_gid: section.gid,
52
+ **options).to_a
62
53
  end
63
54
  cache_method :tasks, SHORT_CACHE_TIME
64
55
 
65
56
  # Pulls just names of tasks from a given section.
66
57
  def section_task_names(workspace_name, project_name, section_name)
67
58
  tasks = tasks(workspace_name, project_name, section_name)
68
- if tasks.nil?
69
- by_section = tasks_by_section(workspace_name, project_name)
70
- desc = "#{workspace_name} | #{project_name} | #{section_name}"
71
- raise "Could not find task names for #{desc}. " \
72
- "Valid sections: #{by_section.keys}"
73
- end
74
59
  tasks.map(&:name)
75
60
  end
76
61
  cache_method :section_task_names, SHORT_CACHE_TIME
77
62
 
78
- # returns if a task's due field is at or before the current date/time
79
- def task_due?(task)
80
- if task.due_at
81
- Time.parse(task.due_at) <= time.now
82
- elsif task.due_on
83
- Date.parse(task.due_on) <= time.today
84
- else
85
- true # set a due date if you don't want to do this now
86
- end
87
- end
88
-
89
63
  private
90
64
 
91
- def_delegators :@projects, :client
92
-
93
- def file_task_by_section(by_section, task, project_gid)
94
- membership = task.memberships.find { |m| m['project']['gid'] == project_gid }
95
- raise "Could not find task in project_gid #{project_gid}: #{task}" if membership.nil?
96
-
97
- current_section = membership['section']['name']
98
- current_section = nil if current_section == '(no section)'
99
- by_section[current_section] ||= []
100
- by_section[current_section] << task
101
- end
102
-
103
- def legacy_tasks_by_section_for_project(project)
65
+ # Given a project object, pull all tasks, then provide a Hash of
66
+ # tasks with section name -> task list of the uncompleted tasks
67
+ def tasks_by_section_for_project(project)
104
68
  raw_tasks = projects.tasks_from_project(project)
105
69
  active_tasks = projects.active_tasks(raw_tasks)
106
- legacy_by_section(active_tasks)
70
+ by_section(active_tasks, project.gid)
107
71
  end
108
72
 
109
- def legacy_file_task_by_section(current_section, by_section, task)
110
- if task.name =~ /:$/
111
- current_section = task.name
112
- by_section[current_section] = []
113
- else
114
- by_section[current_section] ||= []
115
- by_section[current_section] << task
116
- end
117
- [current_section, by_section]
118
- end
73
+ def_delegators :@projects, :client
119
74
 
120
- def legacy_by_section(tasks)
121
- current_section = nil
75
+ # Given a list of tasks, pull a Hash of tasks with section name -> task list
76
+ def by_section(tasks, project_gid)
122
77
  by_section = {}
123
78
  tasks.each do |task|
124
- current_section, by_section =
125
- legacy_file_task_by_section(current_section, by_section, task)
79
+ file_task_by_section(by_section, task, project_gid)
126
80
  end
127
81
  by_section
128
82
  end
83
+ cache_method :by_section, LONG_CACHE_TIME
129
84
 
130
- def legacy_tasks_by_section_for_project_and_assignee_status(project,
131
- assignee_status)
132
- raw_tasks = projects.tasks_from_project(project)
133
- by_assignee_status =
134
- projects.active_tasks(raw_tasks)
135
- .group_by(&:assignee_status)
136
- active_tasks = by_assignee_status[assignee_status]
137
- legacy_by_section(active_tasks)
85
+ def file_task_by_section(by_section, task, project_gid)
86
+ membership = task.memberships.find { |m| m['project']['gid'] == project_gid }
87
+ raise "Could not find task in project_gid #{project_gid}: #{task}" if membership.nil?
88
+
89
+ current_section = membership['section']['name']
90
+ current_section = nil if current_section == '(no section)'
91
+ by_section[current_section] ||= []
92
+ by_section[current_section] << task
138
93
  end
139
94
 
140
95
  def project_or_raise(workspace_name, project_name)
@@ -146,49 +101,20 @@ module Checkoff
146
101
  project
147
102
  end
148
103
 
149
- def verify_legacy_user_task_list!(workspace_name)
150
- return unless user_task_list_migrated_to_real_sections?(workspace_name)
151
-
152
- raise NotImplementedError, 'Section-based user task lists not yet supported'
104
+ def section(workspace_name, project_name, section_name)
105
+ sections = sections_or_raise(workspace_name, project_name)
106
+ sections.find { |section| section.name.chomp(':') == section_name.chomp(':') }
153
107
  end
154
108
 
155
- ASSIGNEE_STATUS_BY_PROJECT_NAME = {
156
- my_tasks_new: 'inbox',
157
- my_tasks_today: 'today',
158
- my_tasks_upcoming: 'upcoming',
159
- }.freeze
160
-
161
- def user_task_list_by_section(workspace_name, project_name)
162
- verify_legacy_user_task_list!(workspace_name)
163
-
164
- project = projects.project(workspace_name, project_name)
165
- if project_name == :my_tasks
166
- legacy_tasks_by_section_for_project(project)
167
- else
168
- legacy_tasks_by_section_for_project_and_assignee_status(project,
169
- ASSIGNEE_STATUS_BY_PROJECT_NAME.fetch(project_name))
170
- end
171
- end
172
-
173
- def user_task_list_migrated_to_real_sections?(workspace_name)
174
- workspace = workspaces.workspace_by_name(workspace_name)
175
- result = client.user_task_lists.get_user_task_list_for_user(user_gid: 'me',
176
- workspace: workspace.gid)
177
- result.migration_status != 'not_migrated'
178
- end
109
+ def section_or_raise(workspace_name, project_name, section_name)
110
+ section = section(workspace_name, project_name, section_name)
111
+ if section.nil?
112
+ valid_sections = sections_or_raise(workspace_name, project_name).map(&:name)
179
113
 
180
- def project_task_names(workspace_name, project_name)
181
- by_section = tasks_by_section(workspace_name, project_name)
182
- by_section.flat_map do |section_name, tasks|
183
- task_names = tasks.map(&:name)
184
- if section_name.nil?
185
- task_names
186
- else
187
- [section_name, task_names]
188
- end
114
+ raise "Could not find section #{section_name} under project #{project_name} " \
115
+ "under workspace #{workspace_name}. Valid sections: #{valid_sections}"
189
116
  end
117
+ section
190
118
  end
191
- cache_method :project_task_names, SHORT_CACHE_TIME
192
119
  end
193
- # rubocop:enable Metrics/ClassLength
194
120
  end
@@ -54,10 +54,6 @@ module Checkoff
54
54
  @projects ||= @sections.projects
55
55
  end
56
56
 
57
- def tasks_minus_sections(tasks)
58
- @sections.by_section(tasks).values.flatten
59
- end
60
-
61
57
  def default_assignee_gid
62
58
  @config.fetch(:default_assignee_gid)
63
59
  end
@@ -2,5 +2,5 @@
2
2
 
3
3
  module Checkoff
4
4
  # Version of library
5
- VERSION = '0.11.1'
5
+ VERSION = '0.12.0'
6
6
  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.11.1
4
+ version: 0.12.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: 2021-06-11 00:00:00.000000000 Z
11
+ date: 2021-07-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport