Module: Taskable
- Included in:
- Issuable
- Defined in:
- app/models/concerns/taskable.rb
Overview
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
Constant Summary collapse
- COMPLETED =
'completed'
- INCOMPLETE =
'incomplete'
- COMPLETE_PATTERN =
/\[[xX]\]/
- INCOMPLETE_PATTERN =
/\[[[:space:]]\]/
- ITEM_PATTERN =
%r{ ^ (?:(?:>\s{0,4})*) # optional blockquote characters ((?:\s*(?:[-+*]|(?:\d+[.)])))+) # list prefix (one or more) required - task item has to be always in a list \s+ # whitespace prefix has to be always presented for a list item ( # checkbox #{COMPLETE_PATTERN}|#{INCOMPLETE_PATTERN} ) (\s.+) # followed by whitespace and some text. }x
- ITEM_PATTERN_UNTRUSTED =
'^' \ '(?:(?:>\s{0,4})*)' \ '(?P<prefix>(?:\s*(?:[-+*]|(?:\d+[.)])))+)' \ '\s+' \ '(?P<checkbox>' \ "#{COMPLETE_PATTERN.source}|#{INCOMPLETE_PATTERN.source}" \ ')' \ '(?P<label>\s.+)'.freeze
- REGEX =
ignore tasks in code or html comment blocks. HTML blocks are ok as we allow tasks inside <detail> blocks
"#{::Gitlab::Regex.markdown_code_or_html_comments_untrusted}" \ "|" \ "(?P<task_item>" \ "#{ITEM_PATTERN_UNTRUSTED}" \ ")".freeze
Class Method Summary collapse
Instance Method Summary collapse
- #task_completion_status ⇒ Object
-
#task_list_items ⇒ Object
Called by ‘TaskList::Summary`.
-
#task_status(short: false) ⇒ Object
Return a string that describes the current state of this Taskable’s task list items, e.g.
-
#task_status_short ⇒ Object
Return a short string that describes the current state of this Taskable’s task list items – for small screens.
- #tasks ⇒ Object
-
#tasks? ⇒ Boolean
Return true if this object’s description has any task list items.
Class Method Details
.get_tasks(content) ⇒ Object
46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 |
# File 'app/models/concerns/taskable.rb', line 46 def self.get_tasks(content) items = [] regex = Gitlab::UntrustedRegexp.new(REGEX, multiline: true) regex.scan(content.to_s).each do |match| next unless regex.extract_named_group(:task_item, match) prefix = regex.extract_named_group(:prefix, match) checkbox = regex.extract_named_group(:checkbox, match) label = regex.extract_named_group(:label, match) items << TaskList::Item.new("#{prefix.strip} #{checkbox}", label.strip) end items end |
.get_updated_tasks(old_content:, new_content:) ⇒ Object
63 64 65 66 67 68 69 70 71 72 73 |
# File 'app/models/concerns/taskable.rb', line 63 def self.get_updated_tasks(old_content:, new_content:) old_tasks = get_tasks(old_content) new_tasks = 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 |
Instance Method Details
#task_completion_status ⇒ Object
113 114 115 116 117 118 |
# File 'app/models/concerns/taskable.rb', line 113 def task_completion_status @task_completion_status ||= { count: tasks.summary.item_count, completed_count: tasks.summary.complete_count } end |
#task_list_items ⇒ Object
Called by ‘TaskList::Summary`
76 77 78 79 80 |
# File 'app/models/concerns/taskable.rb', line 76 def task_list_items return [] if description.blank? @task_list_items ||= Taskable.get_tasks(description) # rubocop:disable Gitlab/ModuleWithInstanceVariables end |
#task_status(short: false) ⇒ Object
Return a string that describes the current state of this Taskable’s task list items, e.g. “12 of 20 checklist items completed”
93 94 95 96 97 98 99 100 101 102 103 104 105 |
# File 'app/models/concerns/taskable.rb', line 93 def task_status(short: false) return '' if description.blank? sum = tasks.summary checklist_item_noun = n_('checklist item', 'checklist items', sum.item_count) if short format(s_('Tasks|%{complete_count}/%{total_count} %{checklist_item_noun}'), checklist_item_noun: checklist_item_noun, complete_count: sum.complete_count, total_count: sum.item_count) else format(s_('Tasks|%{complete_count} of %{total_count} %{checklist_item_noun} completed'), checklist_item_noun: checklist_item_noun, complete_count: sum.complete_count, total_count: sum.item_count) end end |
#task_status_short ⇒ Object
Return a short string that describes the current state of this Taskable’s task list items – for small screens
109 110 111 |
# File 'app/models/concerns/taskable.rb', line 109 def task_status_short task_status(short: true) end |
#tasks ⇒ Object
82 83 84 |
# File 'app/models/concerns/taskable.rb', line 82 def tasks @tasks ||= TaskList.new(self) end |
#tasks? ⇒ Boolean
Return true if this object’s description has any task list items.
87 88 89 |
# File 'app/models/concerns/taskable.rb', line 87 def tasks? tasks.summary.items? end |