Class: Ace::Support::Items::Molecules::StatusCategorizer
- Inherits:
-
Object
- Object
- Ace::Support::Items::Molecules::StatusCategorizer
- Defined in:
- lib/ace/support/items/molecules/status_categorizer.rb
Overview
Categorizes items into “up next” and “recently done” buckets for status overview displays. Generic — works with any item responding to :status, :file_path, :special_folder, :id.
Class Method Summary collapse
-
.categorize(items, up_next_limit:, recently_done_limit:, pending_statuses: ["pending"], done_statuses: ["done"], up_next_sorter: nil) ⇒ Hash
{ up_next: […], recently_done: [{ item:, completed_at: }] }.
Class Method Details
.categorize(items, up_next_limit:, recently_done_limit:, pending_statuses: ["pending"], done_statuses: ["done"], up_next_sorter: nil) ⇒ Hash
Returns { up_next: […], recently_done: [{ item:, completed_at: }] }.
19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
# File 'lib/ace/support/items/molecules/status_categorizer.rb', line 19 def self.categorize(items, up_next_limit:, recently_done_limit:, pending_statuses: ["pending"], done_statuses: ["done"], up_next_sorter: nil) up_next = if up_next_limit > 0 candidates = items .select { |i| pending_statuses.include?(i.status) && i.special_folder.nil? } sorted = if up_next_sorter up_next_sorter.call(candidates) else candidates.sort_by(&:id) end sorted.first(up_next_limit) else [] end recently_done = if recently_done_limit > 0 items .select { |i| done_statuses.include?(i.status) } .map { |i| {item: i, completed_at: safe_mtime(i.file_path)} } .sort_by { |entry| -(entry[:completed_at]&.to_f || 0) } .first(recently_done_limit) else [] end {up_next: up_next, recently_done: recently_done} end |