9f0083a96c
Make the Markdown parser recognize "[x]" or "[ ]" at the beginning of a list item and turn it into a checkbox input. Users who can modify the issue or MR can toggle the checkboxes directly or edit the Markdown to manage the tasks. Task status is also displayed in the MR and issue lists.
51 lines
1.6 KiB
Ruby
51 lines
1.6 KiB
Ruby
# 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
|
|
TASK_PATTERN_MD = /^(?<bullet> *[*-] *)\[(?<checked>[ xX])\]/.freeze
|
|
TASK_PATTERN_HTML = /^<li>\[(?<checked>[ xX])\]/.freeze
|
|
|
|
# Change the state of a task list item for this Taskable. Edit the object's
|
|
# description by finding the nth task item and changing its checkbox
|
|
# placeholder to "[x]" if +checked+ is true, or "[ ]" if it's false.
|
|
# Note: task numbering starts with 1
|
|
def update_nth_task(n, checked)
|
|
index = 0
|
|
check_char = checked ? 'x' : ' '
|
|
|
|
# Do this instead of using #gsub! so that ActiveRecord detects that a field
|
|
# has changed.
|
|
self.description = self.description.gsub(TASK_PATTERN_MD) do |match|
|
|
index += 1
|
|
case index
|
|
when n then "#{$LAST_MATCH_INFO[:bullet]}[#{check_char}]"
|
|
else match
|
|
end
|
|
end
|
|
|
|
save
|
|
end
|
|
|
|
# Return true if this object's description has any task list items.
|
|
def tasks?
|
|
description && description.match(TASK_PATTERN_MD)
|
|
end
|
|
|
|
# Return a string that describes the current state of this Taskable's task
|
|
# list items, e.g. "20 tasks (12 done, 8 unfinished)"
|
|
def task_status
|
|
return nil unless description
|
|
|
|
num_tasks = 0
|
|
num_done = 0
|
|
|
|
description.scan(TASK_PATTERN_MD) do
|
|
num_tasks += 1
|
|
num_done += 1 unless $LAST_MATCH_INFO[:checked] == ' '
|
|
end
|
|
|
|
"#{num_tasks} tasks (#{num_done} done, #{num_tasks - num_done} unfinished)"
|
|
end
|
|
end
|