Class: Checkoff::Tasks
- Inherits:
-
Object
- Object
- Checkoff::Tasks
- Extended by:
- T::Sig
- Includes:
- Logging
- Defined in:
- lib/checkoff/tasks.rb,
sig/checkoff.rbs
Overview
Pull tasks from Asana
Constant Summary collapse
- MINUTE =
60- HOUR =
MINUTE * 60
- DAY =
24 * HOUR
- REALLY_LONG_CACHE_TIME =
MINUTE * 30
- LONG_CACHE_TIME =
MINUTE * 15
- SHORT_CACHE_TIME =
MINUTE * 5
Instance Attribute Summary collapse
-
#client ⇒ Asana::Client
readonly
sord warn - Asana::Client wasn't able to be resolved to a constant in this project.
- #custom_fields ⇒ Checkoff::CustomFields readonly
- #timing ⇒ Checkoff::Timing readonly
Instance Method Summary collapse
-
#add_task(name, workspace_gid: @workspaces.default_workspace_gid, assignee_gid: default_assignee_gid) ⇒ Asana::Resources::Task
sord warn - Asana::Resources::Task wasn't able to be resolved to a constant in this project Add a task.
-
#all_dependent_tasks(task, extra_task_fields: []) ⇒ ::Array[Asana::Resources::Task]
sord warn - Asana::Resources::Task wasn't able to be resolved to a constant in this project sord warn - Asana::Resources::Task wasn't able to be resolved to a constant in this project @param
task. - #as_cache_key ⇒ Hash
-
#date_or_time_field_by_name(task, field_name) ⇒ Date, ...
sord warn - Asana::Resources::Task wasn't able to be resolved to a constant in this project @param
task. -
#debug ⇒ void
@param
message. -
#default_assignee_gid ⇒ String
@sg-ignore.
-
#error ⇒ void
@param
message. -
#finer ⇒ void
@param
message. -
#gid_for_task(workspace_name, project_name, section_name, task_name) ⇒ Object
@param
workspace_name. -
#h_to_task(task_data) ⇒ Asana::Resources::Task
sord warn - Asana::Resources::Task wasn't able to be resolved to a constant in this project @param
task_data. -
#in_period?(task, field_name, period) ⇒ Boolean
sord warn - Asana::Resources::Task wasn't able to be resolved to a constant in this project @param
task. -
#in_portfolio_more_than_once?(task, portfolio_name, workspace_name: @workspaces.default_workspace.name) ⇒ Boolean
sord warn - Asana::Resources::Task wasn't able to be resolved to a constant in this project True if the task is in a project which is in the given portfolio.
-
#in_portfolio_named?(task, portfolio_name, workspace_name: @workspaces.default_workspace.name) ⇒ Boolean
sord warn - Asana::Resources::Task wasn't able to be resolved to a constant in this project True if the task is in a project which is in the given portfolio.
-
#incomplete_dependencies?(task) ⇒ Boolean
sord warn - Asana::Resources::Task wasn't able to be resolved to a constant in this project True if any of the task's dependencies are marked incomplete.
-
#info ⇒ void
@param
message. -
#initialize(config: Checkoff::Internal::ConfigLoader.load(:asana), client: Checkoff::Clients.new(config:).client, workspaces: Checkoff::Workspaces.new(config:, client:), sections: Checkoff::Sections.new(config:, client:), portfolios: Checkoff::Portfolios.new(config:, client:), custom_fields: Checkoff::CustomFields.new(config:, client:), time_class: Time, date_class: Date, asana_task: Asana::Resources::Task) ⇒ Object
constructor
sord warn - Asana::Client wasn't able to be resolved to a constant in this project sord warn - Asana::Resources::Task wasn't able to be resolved to a constant in this project @param
config. -
#log_level ⇒ Symbol
@sg-ignore.
- #logger ⇒ ::Logger
- #projects ⇒ Checkoff::Projects
-
#task(workspace_name, project_name, task_name, section_name: :unspecified, only_uncompleted: true, extra_fields: []) ⇒ Object
sord warn - Asana::Resources::Task wasn't able to be resolved to a constant in this project Pull a specific task by name.
-
#task_by_gid(task_gid, extra_fields: [], only_uncompleted: true) ⇒ Asana::Resources::Task?
sord warn - Asana::Resources::Task wasn't able to be resolved to a constant in this project Pull a specific task by GID.
- #task_hashes ⇒ Checkoff::Internal::TaskHashes
-
#task_ready?(task, period: :now_or_before, ignore_dependencies: false) ⇒ Boolean
sord warn - Asana::Resources::Task wasn't able to be resolved to a constant in this project Indicates a task is ready for a person to work on it.
- #task_timing ⇒ Checkoff::Internal::TaskTiming
-
#task_to_h(task) ⇒ ::Hash[untyped, untyped]
sord warn - Asana::Resources::Task wasn't able to be resolved to a constant in this project Builds on the standard API representation of an Asana task with some convenience keys:.
-
#tasks(workspace_name, project_name, only_uncompleted:, extra_fields: [], section_name: :unspecified) ⇒ Object
sord warn - Asana::Resources::Task wasn't able to be resolved to a constant in this project @param
workspace_name. -
#url_of_task(task) ⇒ String
sord warn - Asana::Resources::Task wasn't able to be resolved to a constant in this project Return user-accessible URL for a task.
-
#warn ⇒ void
@param
message.
Constructor Details
#initialize(config: Checkoff::Internal::ConfigLoader.load(:asana), client: Checkoff::Clients.new(config:).client, workspaces: Checkoff::Workspaces.new(config:, client:), sections: Checkoff::Sections.new(config:, client:), portfolios: Checkoff::Portfolios.new(config:, client:), custom_fields: Checkoff::CustomFields.new(config:, client:), time_class: Time, date_class: Date, asana_task: Asana::Resources::Task) ⇒ Object
sord warn - Asana::Client wasn't able to be resolved to a constant in this project
sord warn - Asana::Resources::Task wasn't able to be resolved to a constant in this project
@param config
@param client
@param workspaces
@param sections
@param portfolios
@param custom_fields
@param time_class
@param date_class
@param asana_task
44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 |
# File 'lib/checkoff/tasks.rb', line 44 def initialize(config: Checkoff::Internal::ConfigLoader.load(:asana), client: Checkoff::Clients.new(config:).client, workspaces: Checkoff::Workspaces.new(config:, client:), sections: Checkoff::Sections.new(config:, client:), portfolios: Checkoff::Portfolios.new(config:, client:), custom_fields: Checkoff::CustomFields.new(config:, 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 Attribute Details
#client ⇒ Asana::Client (readonly)
sord warn - Asana::Client wasn't able to be resolved to a constant in this project
376 377 378 |
# File 'lib/checkoff/tasks.rb', line 376 def client @client end |
#custom_fields ⇒ Checkoff::CustomFields (readonly)
382 383 384 |
# File 'lib/checkoff/tasks.rb', line 382 def custom_fields @custom_fields end |
#timing ⇒ Checkoff::Timing (readonly)
379 380 381 |
# File 'lib/checkoff/tasks.rb', line 379 def timing @timing end |
Instance Method Details
#add_task(name, workspace_gid: @workspaces.default_workspace_gid, assignee_gid: default_assignee_gid) ⇒ Asana::Resources::Task
sord warn - Asana::Resources::Task wasn't able to be resolved to a constant in this project Add a task
@sg-ignore
@param name
@param workspace_gid
@param assignee_gid
185 186 187 188 189 190 191 |
# File 'lib/checkoff/tasks.rb', line 185 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:) end |
#all_dependent_tasks(task, extra_task_fields: []) ⇒ ::Array[Asana::Resources::Task]
sord warn - Asana::Resources::Task wasn't able to be resolved to a constant in this project
sord warn - Asana::Resources::Task wasn't able to be resolved to a constant in this project
@param task
@param extra_task_fields
240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 |
# File 'lib/checkoff/tasks.rb', line 240 def all_dependent_tasks(task, extra_task_fields: []) # @type [Array<Asana::Resources::Task>] dependent_tasks = T.let([], T::Array[Asana::Resources::Task]) # 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 #{T.must(dependent_task).name}" } next if dependent_task.nil? dependent_tasks << dependent_task dependent_tasks += all_dependent_tasks(dependent_task, extra_task_fields:) end dependent_tasks end |
#as_cache_key ⇒ Hash
335 336 337 |
# File 'lib/checkoff/tasks.rb', line 335 def as_cache_key {} end |
#date_or_time_field_by_name(task, field_name) ⇒ Date, ...
sord warn - Asana::Resources::Task wasn't able to be resolved to a constant in this project
@param task
@param field_name — :start - start_at or start_on (first set) :due - due_at or due_on (first set) :ready - start_at or start_on or due_at or due_on (first set) :modified - modified_at [:custom_field, "foo"] - 'Date' custom field type named 'foo'
107 108 109 |
# File 'lib/checkoff/tasks.rb', line 107 def date_or_time_field_by_name(task, field_name) task_timing.date_or_time_field_by_name(task, field_name) end |
#debug ⇒ void
This method returns an undefined value.
@param message
562 |
# File 'sig/checkoff.rbs', line 562
def debug: (?Object? message) -> void
|
#default_assignee_gid ⇒ String
@sg-ignore
391 392 393 |
# File 'lib/checkoff/tasks.rb', line 391 def default_assignee_gid @config.fetch(:default_assignee_gid) end |
#error ⇒ void
This method returns an undefined value.
@param message
553 |
# File 'sig/checkoff.rbs', line 553
def error: (?Object? message) -> void
|
#finer ⇒ void
This method returns an undefined value.
@param message
565 |
# File 'sig/checkoff.rbs', line 565
def finer: (?Object? message) -> void
|
#gid_for_task(workspace_name, project_name, section_name, task_name) ⇒ Object
@param workspace_name
@param project_name
@param section_name
@param task_name
143 144 145 146 147 148 149 150 151 152 |
# File 'lib/checkoff/tasks.rb', line 143 def gid_for_task(workspace_name, project_name, section_name, task_name) t = tasks(workspace_name, project_name, section_name:, only_uncompleted: false) task_for_gid = t.find { |task| task.name == task_name } return nil if task_for_gid.nil? task_for_gid.gid end |
#h_to_task(task_data) ⇒ Asana::Resources::Task
sord warn - Asana::Resources::Task wasn't able to be resolved to a constant in this project
@param task_data
289 290 291 |
# File 'lib/checkoff/tasks.rb', line 289 def h_to_task(task_data) task_hashes.h_to_task(task_data, client:) end |
#in_period?(task, field_name, period) ⇒ Boolean
sord warn - Asana::Resources::Task wasn't able to be resolved to a constant in this project
@param task
@param field_name
@param period — :now_or_before, :this_week - See Checkoff::Timing#in_period?_
91 92 93 94 95 96 |
# File 'lib/checkoff/tasks.rb', line 91 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_more_than_once?(task, portfolio_name, workspace_name: @workspaces.default_workspace.name) ⇒ Boolean
sord warn - Asana::Resources::Task wasn't able to be resolved to a constant in this project True if the task is in a project which is in the given portfolio
@param task
@param portfolio_name
@param workspace_name
317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 |
# File 'lib/checkoff/tasks.rb', line 317 def in_portfolio_more_than_once?(task, portfolio_name, workspace_name: @workspaces.default_workspace.name) portfolio_projects = @portfolios.projects_in_portfolio(workspace_name, portfolio_name) portfolio_project_gids = portfolio_projects.map(&:gid) seen = T.let(false, T::Boolean) task.memberships.each do |membership| m = T.cast(membership, T::Hash[String, T.untyped]) project_gid = T.cast(m.fetch('project'), T::Hash[String, T.untyped]).fetch('gid') next unless portfolio_project_gids.include?(project_gid) return true if seen seen = true end false end |
#in_portfolio_named?(task, portfolio_name, workspace_name: @workspaces.default_workspace.name) ⇒ Boolean
sord warn - Asana::Resources::Task wasn't able to be resolved to a constant in this project True if the task is in a project which is in the given portfolio
@sg-ignore Checkoff::Tasks#in_portfolio_named? return type could not be inferred
@param task
@param portfolio_name
@param workspace_name
300 301 302 303 304 305 306 307 308 309 |
# File 'lib/checkoff/tasks.rb', line 300 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| m = T.cast(membership, T::Hash[String, T.untyped]) project_gid = T.cast(m.fetch('project'), T::Hash[String, T.untyped]).fetch('gid') portfolio_projects.any? { |portfolio_project| portfolio_project.gid == project_gid } end == true end |
#incomplete_dependencies?(task) ⇒ Boolean
sord warn - Asana::Resources::Task wasn't able to be resolved to a constant in this project True if any of the task's dependencies are marked incomplete
@sg-ignore Include 'dependencies.gid' in extra_fields of task passed in.
@param task
208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 |
# File 'lib/checkoff/tasks.rb', line 208 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 # @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: # @sg-ignore parent_task_gid = parent_task_info.fetch('gid') parent_task = task_by_gid(parent_task_gid, only_uncompleted: false) # Embedded dependency GIDs can outlive the parent fetch (timing) or disagree # with cache_method TTL/coherency; treat unfetchable as incomplete. next true if parent_task.nil? parent_task.completed_at.nil? end end |
#info ⇒ void
This method returns an undefined value.
@param message
559 |
# File 'sig/checkoff.rbs', line 559
def info: (?Object? message) -> void
|
#log_level ⇒ Symbol
@sg-ignore
568 |
# File 'sig/checkoff.rbs', line 568
def log_level: () -> Symbol
|
#logger ⇒ ::Logger
550 |
# File 'sig/checkoff.rbs', line 550
def logger: () -> ::Logger
|
#projects ⇒ Checkoff::Projects
385 386 387 |
# File 'lib/checkoff/tasks.rb', line 385 def projects @projects ||= @sections.projects end |
#task(workspace_name, project_name, task_name, section_name: :unspecified, only_uncompleted: true, extra_fields: []) ⇒ Object
sord warn - Asana::Resources::Task wasn't able to be resolved to a constant in this project Pull a specific task by name
@param workspace_name
@param project_name
@param section_name
@param task_name
@param only_uncompleted
@param extra_fields
120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 |
# File 'lib/checkoff/tasks.rb', line 120 def task(workspace_name, project_name, task_name, section_name: :unspecified, only_uncompleted: true, extra_fields: []) thread_local = Checkoff::Internal::ThreadLocal.new # @type [String] # @sg-ignore task_gid = thread_local.with_thread_local_variable(:suppress_asana_webhook_watch_creation, true) do gid_for_task(workspace_name, project_name, section_name, task_name) end return nil if task_gid.nil? task_by_gid(task_gid, only_uncompleted:, extra_fields:) end |
#task_by_gid(task_gid, extra_fields: [], only_uncompleted: true) ⇒ Asana::Resources::Task?
sord warn - Asana::Resources::Task wasn't able to be resolved to a constant in this project Pull a specific task by GID
@param task_gid
@param extra_fields
@param only_uncompleted
162 163 164 165 166 167 168 169 170 171 172 173 174 |
# File 'lib/checkoff/tasks.rb', line 162 def task_by_gid(task_gid, extra_fields: [], only_uncompleted: true) = projects.(extra_fields:, only_uncompleted:) # @type [Hash] = .fetch(:options) { {} } [:completed_since] = [:completed_since] unless [:completed_since].nil? client.tasks.find_by_id(task_gid, options:) rescue Asana::Errors::NotFound => e debug e nil end |
#task_hashes ⇒ Checkoff::Internal::TaskHashes
349 350 351 |
# File 'lib/checkoff/tasks.rb', line 349 def task_hashes @task_hashes ||= Checkoff::Internal::TaskHashes.new end |
#task_ready?(task, period: :now_or_before, ignore_dependencies: false) ⇒ Boolean
sord warn - Asana::Resources::Task wasn't able to be resolved to a constant in this project 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
@param task
@param period — - :now_or_before or :this_week
@param ignore_dependencies
82 83 84 85 86 |
# File 'lib/checkoff/tasks.rb', line 82 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_timing ⇒ Checkoff::Internal::TaskTiming
342 343 344 345 346 |
# File 'lib/checkoff/tasks.rb', line 342 def task_timing @task_timing ||= Checkoff::Internal::TaskTiming.new(time_class: @time_class, date_class: @date_class, client:, custom_fields:) end |
#task_to_h(task) ⇒ ::Hash[untyped, untyped]
sord warn - Asana::Resources::Task wasn't able to be resolved to a constant in this project Builds on the standard API representation of an Asana task with some convenience keys:
@param task
282 283 284 |
# File 'lib/checkoff/tasks.rb', line 282 def task_to_h(task) task_hashes.task_to_h(task) end |
#tasks(workspace_name, project_name, only_uncompleted:, extra_fields: [], section_name: :unspecified) ⇒ Object
sord warn - Asana::Resources::Task wasn't able to be resolved to a constant in this project
@param workspace_name
@param project_name
@param section_name — - :unspecified
@param only_uncompleted
@param extra_fields
360 361 362 363 364 365 366 367 368 369 370 371 372 |
# File 'lib/checkoff/tasks.rb', line 360 def tasks(workspace_name, project_name, only_uncompleted:, extra_fields: [], section_name: :unspecified) if section_name == :unspecified project = projects.project_or_raise(workspace_name, project_name) projects.tasks_from_project(project, only_uncompleted:, extra_fields:) else @sections.tasks(workspace_name, project_name, section_name, only_uncompleted:, extra_fields:) end end |
#url_of_task(task) ⇒ String
sord warn - Asana::Resources::Task wasn't able to be resolved to a constant in this project Return user-accessible URL for a task
@param task
@return — end-user URL to the task in question
198 199 200 |
# File 'lib/checkoff/tasks.rb', line 198 def url_of_task(task) "https://app.asana.com/0/0/#{task.gid}/f" end |
#warn ⇒ void
This method returns an undefined value.
@param message
556 |
# File 'sig/checkoff.rbs', line 556
def warn: (?Object? message) -> void
|