b70d23c25a
Add spec for task_completion_status Add test cases for task_completion_status result Extracted shared samples Add new spec file for task completion status response Fix style errors Add changelog entry Changed samples to Hashes Remove test for successful request Remove not nil expectation Add task_completion_status to api documentation for issues Add task_completion_status to api documentation for merge_requests Refactor spec so it just requests one specific item Add task_completion_status to Taskable Simplified task completion status in entities Refactor spec so it separates status code check and content check Fix spec description text and field name
85 lines
2.5 KiB
Ruby
85 lines
2.5 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
require 'task_list'
|
|
require 'task_list/filter'
|
|
|
|
# Contains functionality for objects that can have task lists in their
|
|
# descriptions. Task list items can be added with Markdown like "* [x] Fix
|
|
# bugs".
|
|
#
|
|
# Used by MergeRequest and Issue
|
|
module Taskable
|
|
COMPLETED = 'completed'.freeze
|
|
INCOMPLETE = 'incomplete'.freeze
|
|
COMPLETE_PATTERN = /(\[[xX]\])/.freeze
|
|
INCOMPLETE_PATTERN = /(\[[\s]\])/.freeze
|
|
ITEM_PATTERN = %r{
|
|
^
|
|
\s*(?:[-+*]|(?:\d+\.)) # list prefix required - task item has to be always in a list
|
|
\s+ # whitespace prefix has to be always presented for a list item
|
|
(\[\s\]|\[[xX]\]) # checkbox
|
|
(\s.+) # followed by whitespace and some text.
|
|
}x.freeze
|
|
|
|
def self.get_tasks(content)
|
|
content.to_s.scan(ITEM_PATTERN).map do |checkbox, label|
|
|
# ITEM_PATTERN strips out the hyphen, but Item requires it. Rabble rabble.
|
|
TaskList::Item.new("- #{checkbox}", label.strip)
|
|
end
|
|
end
|
|
|
|
def self.get_updated_tasks(old_content:, new_content:)
|
|
old_tasks, new_tasks = get_tasks(old_content), get_tasks(new_content)
|
|
|
|
new_tasks.select.with_index do |new_task, i|
|
|
old_task = old_tasks[i]
|
|
next unless old_task
|
|
|
|
new_task.source == old_task.source && new_task.complete? != old_task.complete?
|
|
end
|
|
end
|
|
|
|
# Called by `TaskList::Summary`
|
|
def task_list_items
|
|
return [] if description.blank?
|
|
|
|
@task_list_items ||= Taskable.get_tasks(description) # rubocop:disable Gitlab/ModuleWithInstanceVariables
|
|
end
|
|
|
|
def tasks
|
|
@tasks ||= TaskList.new(self)
|
|
end
|
|
|
|
# Return true if this object's description has any task list items.
|
|
def tasks?
|
|
tasks.summary.items?
|
|
end
|
|
|
|
# Return a string that describes the current state of this Taskable's task
|
|
# list items, e.g. "12 of 20 tasks completed"
|
|
def task_status(short: false)
|
|
return '' if description.blank?
|
|
|
|
prep, completed = if short
|
|
['/', '']
|
|
else
|
|
[' of ', ' completed']
|
|
end
|
|
|
|
sum = tasks.summary
|
|
"#{sum.complete_count}#{prep}#{sum.item_count} #{'task'.pluralize(sum.item_count)}#{completed}"
|
|
end
|
|
|
|
# Return a short string that describes the current state of this Taskable's
|
|
# task list items -- for small screens
|
|
def task_status_short
|
|
task_status(short: true)
|
|
end
|
|
|
|
def task_completion_status
|
|
@task_completion_status ||= {
|
|
count: tasks.summary.item_count,
|
|
completed_count: tasks.summary.complete_count
|
|
}
|
|
end
|
|
end
|