Class: Checkoff::Tasks
- Inherits:
-
Object
- Object
- Checkoff::Tasks
- Includes:
- Logging
- Defined in:
- lib/checkoff/tasks.rb
Overview
Pull tasks from Asana
Constant Summary collapse
- MINUTE =
60
- HOUR =
MINUTE * 60
- DAY =
24 * HOUR
- REALLY_LONG_CACHE_TIME =
HOUR
- LONG_CACHE_TIME =
MINUTE * 15
- SHORT_CACHE_TIME =
MINUTE * 5
Instance Method Summary collapse
-
#add_task(name, workspace_gid: @workspaces.default_workspace_gid, assignee_gid: default_assignee_gid) ⇒ Asana::Resources::Task
Add a task.
- #all_dependent_tasks(task, extra_task_fields: []) ⇒ Array<Hash>
- #as_cache_key ⇒ Hash
- #date_or_time_field_by_name(task, field_name) ⇒ Date, ...
- #h_to_task(task_data) ⇒ Asana::Resources::Task
- #in_period?(task, field_name, period) ⇒ Boolean
-
#in_portfolio_named?(task, portfolio_name, workspace_name: @workspaces.default_workspace.name) ⇒ Boolean
True if the task is in a project which is in the given portfolio.
-
#incomplete_dependencies?(task) ⇒ Boolean
True if any of the task’s dependencies are marked incomplete.
-
#initialize(config: Checkoff::Internal::ConfigLoader.load(:asana), client: Checkoff::Clients.new(config: config).client, workspaces: Checkoff::Workspaces.new(config: config, client: client), sections: Checkoff::Sections.new(config: config, client: client), portfolios: Checkoff::Portfolios.new(config: config, client: client), custom_fields: Checkoff::CustomFields.new(config: config, client: client), time_class: Time, date_class: Date, asana_task: Asana::Resources::Task) ⇒ Tasks
constructor
A new instance of Tasks.
-
#task(workspace_name, project_name, task_name, section_name: :unspecified, only_uncompleted: true, extra_fields: []) ⇒ Asana::Resources::Task?
Pull a specific task by name.
-
#task_by_gid(task_gid, extra_fields: [], only_uncompleted: false) ⇒ Asana::Resources::Task?
Pull a specific task by GID.
-
#task_ready?(task, period: :now_or_before, ignore_dependencies: false) ⇒ Boolean
Indicates a task is ready for a person to work on it.
-
#task_to_h(task) ⇒ Hash
Builds on the standard API representation of an Asana task with some convenience keys:.
-
#url_of_task(task) ⇒ String
Return user-accessible URL for a task.
Methods included from Logging
#debug, #error, #finer, #info, #logger, #warn
Constructor Details
#initialize(config: Checkoff::Internal::ConfigLoader.load(:asana), client: Checkoff::Clients.new(config: config).client, workspaces: Checkoff::Workspaces.new(config: config, client: client), sections: Checkoff::Sections.new(config: config, client: client), portfolios: Checkoff::Portfolios.new(config: config, client: client), custom_fields: Checkoff::CustomFields.new(config: config, client: client), time_class: Time, date_class: Date, asana_task: Asana::Resources::Task) ⇒ Tasks
Returns a new instance of Tasks.
38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 |
# File 'lib/checkoff/tasks.rb', line 38 def initialize(config: Checkoff::Internal::ConfigLoader.load(:asana), client: Checkoff::Clients.new(config: config).client, workspaces: Checkoff::Workspaces.new(config: config, client: client), sections: Checkoff::Sections.new(config: config, client: client), portfolios: Checkoff::Portfolios.new(config: config, client: client), custom_fields: Checkoff::CustomFields.new(config: config, client: client), time_class: Time, date_class: Date, asana_task: Asana::Resources::Task) @config = config @sections = sections @time_class = time_class @date_class = date_class @asana_task = asana_task @client = client @portfolios = portfolios @custom_fields = custom_fields @workspaces = workspaces @timing = Checkoff::Timing.new(today_getter: date_class, now_getter: time_class) end |
Instance Method Details
#add_task(name, workspace_gid: @workspaces.default_workspace_gid, assignee_gid: default_assignee_gid) ⇒ Asana::Resources::Task
Add a task
154 155 156 157 158 159 160 |
# File 'lib/checkoff/tasks.rb', line 154 def add_task(name, workspace_gid: @workspaces.default_workspace_gid, assignee_gid: default_assignee_gid) @asana_task.create(client, assignee: assignee_gid, workspace: workspace_gid, name: name) end |
#all_dependent_tasks(task, extra_task_fields: []) ⇒ Array<Hash>
204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 |
# File 'lib/checkoff/tasks.rb', line 204 def all_dependent_tasks(task, extra_task_fields: []) dependent_tasks = [] # See note above - same applies as does in @dependencies # # @type [Array<Hash>] dependents = task.instance_variable_get(:@dependents) || [] dependents.each do |dependent_task_hash_or_obj| # seems like if we ever .inspect the task, it stashes the task # object instead of the hash. Try to avoid this - but maybe we # need to convert if it does happen. raise 'Found dependent task object!' if dependent_task_hash_or_obj.is_a?(Asana::Resources::Task) dependent_task_hash = dependent_task_hash_or_obj dependent_task = task_by_gid(dependent_task_hash.fetch('gid'), only_uncompleted: true, extra_fields: ['dependents'] + extra_task_fields) debug { "#{task.name} has dependent task #{dependent_task.name}" } unless dependent_task.nil? dependent_tasks << dependent_task dependent_tasks += all_dependent_tasks(dependent_task) end end dependent_tasks end |
#as_cache_key ⇒ Hash
273 274 275 |
# File 'lib/checkoff/tasks.rb', line 273 def as_cache_key {} end |
#date_or_time_field_by_name(task, field_name) ⇒ Date, ...
101 102 103 |
# File 'lib/checkoff/tasks.rb', line 101 def date_or_time_field_by_name(task, field_name) task_timing.date_or_time_field_by_name(task, field_name) end |
#h_to_task(task_data) ⇒ Asana::Resources::Task
251 252 253 |
# File 'lib/checkoff/tasks.rb', line 251 def h_to_task(task_data) Asana::Resources::Task.new(task_data, client: client) end |
#in_period?(task, field_name, period) ⇒ Boolean
85 86 87 88 89 90 |
# File 'lib/checkoff/tasks.rb', line 85 def in_period?(task, field_name, period) # @type [Date,Time,nil] task_date_or_time = task_timing.date_or_time_field_by_name(task, field_name) timing.in_period?(task_date_or_time, period) end |
#in_portfolio_named?(task, portfolio_name, workspace_name: @workspaces.default_workspace.name) ⇒ Boolean
True if the task is in a project which is in the given portfolio
260 261 262 263 264 265 266 267 268 269 270 |
# File 'lib/checkoff/tasks.rb', line 260 def in_portfolio_named?(task, portfolio_name, workspace_name: @workspaces.default_workspace.name) portfolio_projects = @portfolios.projects_in_portfolio(workspace_name, portfolio_name) task.memberships.any? do |membership| project_gid = membership.fetch('project').fetch('gid') portfolio_projects.any? do |portfolio_project| portfolio_project.gid == project_gid end end end |
#incomplete_dependencies?(task) ⇒ Boolean
True if any of the task’s dependencies are marked incomplete
Include ‘dependencies.gid’ in extra_fields of task passed in.
176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 |
# File 'lib/checkoff/tasks.rb', line 176 def incomplete_dependencies?(task) # Avoid a redundant fetch. Unfortunately, Ruby SDK allows # dependencies to be fetched along with other attributes--but # then doesn't use it and does another HTTP GET! At least this # way we can skip the extra HTTP GET in the common case when # there are no dependencies. # # https://github.com/Asana/ruby-asana/issues/125 # @sg-ignore # @type [Enumerable<Asana::Resources::Task>, nil] dependencies = task.instance_variable_get(:@dependencies) || [] dependencies.any? do |parent_task_info| # the real bummer though is that asana doesn't let you fetch # the completion status of dependencies, so we need to do this # regardless: parent_task_gid = parent_task_info.fetch('gid') parent_task = task_by_gid(parent_task_gid, only_uncompleted: false) parent_task.completed_at.nil? end end |
#task(workspace_name, project_name, task_name, section_name: :unspecified, only_uncompleted: true, extra_fields: []) ⇒ Asana::Resources::Task?
Pull a specific task by name
@sg-ignore
115 116 117 118 119 120 121 122 123 124 125 126 |
# File 'lib/checkoff/tasks.rb', line 115 def task(workspace_name, project_name, task_name, section_name: :unspecified, only_uncompleted: true, extra_fields: []) # @sg-ignore t = tasks(workspace_name, project_name, section_name: section_name, only_uncompleted: only_uncompleted, extra_fields: extra_fields) t.find { |task| task.name == task_name } end |
#task_by_gid(task_gid, extra_fields: [], only_uncompleted: false) ⇒ Asana::Resources::Task?
Pull a specific task by GID
136 137 138 139 140 141 142 143 144 |
# File 'lib/checkoff/tasks.rb', line 136 def task_by_gid(task_gid, extra_fields: [], only_uncompleted: false) # @type [Hash] = projects..fetch(:options, {}) [:fields] += extra_fields [:completed_since] = '9999-12-01' if only_uncompleted client.tasks.find_by_id(task_gid, options: ) end |
#task_ready?(task, period: :now_or_before, ignore_dependencies: false) ⇒ Boolean
Indicates a task is ready for a person to work on it. This is subtly different than what is used by Asana to mark a date as red/green! A task is ready if it is not dependent on an incomplete task and one of these is true:
-
start is null and due on is today
-
start is null and due at is before now
-
start on is today
-
start at is before now
76 77 78 79 80 |
# File 'lib/checkoff/tasks.rb', line 76 def task_ready?(task, period: :now_or_before, ignore_dependencies: false) return false if !ignore_dependencies && incomplete_dependencies?(task) in_period?(task, :ready, period) end |
#task_to_h(task) ⇒ Hash
Builds on the standard API representation of an Asana task with some convenience keys:
<regular keys from API response> + unwrapped:
membership_by_section_gid: Hash<String, Hash (membership)>
membership_by_project_gid: Hash<String, Hash (membership)>
membership_by_project_name: Hash<String, Hash (membership)>
task: String (name)
244 245 246 |
# File 'lib/checkoff/tasks.rb', line 244 def task_to_h(task) task_hashes.task_to_h(task) end |
#url_of_task(task) ⇒ String
Return user-accessible URL for a task
167 168 169 |
# File 'lib/checkoff/tasks.rb', line 167 def url_of_task(task) "https://app.asana.com/0/0/#{task.gid}/f" end |