BigW Consortium Gitlab

global_milestone.rb 4.1 KB
Newer Older
1
class GlobalMilestone
2 3
  include Milestoneish

4
  EPOCH = DateTime.parse('1970-01-01')
Felipe Artur committed
5
  STATE_COUNT_HASH = { opened: 0, closed: 0, all: 0 }.freeze
6

7
  attr_accessor :title, :milestones
8 9
  alias_attribute :name, :title

10 11 12 13
  def for_display
    @first_milestone
  end

14
  def self.build_collection(projects, params)
Felipe Artur committed
15 16 17 18
    params =
      { project_ids: projects.map(&:id), state: params[:state] }

    child_milestones = MilestonesFinder.new(params).execute
19

20 21
    milestones = child_milestones.select(:id, :title).group_by(&:title).map do |title, grouped|
      milestones_relation = Milestone.where(id: grouped.map(&:id))
22
      new(title, milestones_relation)
23
    end
24 25 26 27 28 29 30 31 32

    milestones.sort_by { |milestone| milestone.due_date || EPOCH }
  end

  def self.build(projects, title)
    child_milestones = Milestone.of_projects(projects).where(title: title)
    return if child_milestones.blank?

    new(title, child_milestones)
33 34
  end

Felipe Artur committed
35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66
  def self.states_count(projects, group = nil)
    legacy_group_milestones_count = legacy_group_milestone_states_count(projects)
    group_milestones_count = group_milestones_states_count(group)

    legacy_group_milestones_count.merge(group_milestones_count) do |k, legacy_group_milestones_count, group_milestones_count|
      legacy_group_milestones_count + group_milestones_count
    end
  end

  def self.group_milestones_states_count(group)
    return STATE_COUNT_HASH unless group

    params = { group_ids: [group.id], state: 'all', order: nil }

    relation = MilestonesFinder.new(params).execute
    grouped_by_state = relation.group(:state).count

    {
      opened: grouped_by_state['active'] || 0,
      closed: grouped_by_state['closed'] || 0,
      all: grouped_by_state.values.sum
    }
  end

  # Counts the legacy group milestones which must be grouped by title
  def self.legacy_group_milestone_states_count(projects)
    return STATE_COUNT_HASH unless projects

    params = { project_ids: projects.map(&:id), state: 'all', order: nil }

    relation = MilestonesFinder.new(params).execute
    project_milestones_by_state_and_title = relation.group(:state, :title).count
67

Felipe Artur committed
68 69 70
    opened = count_by_state(project_milestones_by_state_and_title, 'active')
    closed = count_by_state(project_milestones_by_state_and_title, 'closed')
    all = project_milestones_by_state_and_title.map { |(_, title), _| title }.uniq.count
71

72
    {
73 74 75 76 77 78 79 80 81 82 83 84 85
      opened: opened,
      closed: closed,
      all: all
    }
  end

  def self.count_by_state(milestones_by_state_and_title, state)
    milestones_by_state_and_title.count do |(milestone_state, _), _|
      milestone_state == state
    end
  end
  private_class_method :count_by_state

86 87
  def initialize(title, milestones)
    @title = title
88
    @name = title
89
    @milestones = milestones
90
    @first_milestone = milestones.find {|m| m.description.present? } || milestones.first
91 92
  end

93 94 95 96
  def milestoneish_ids
    milestones.select(:id)
  end

97
  def safe_title
98
    @title.to_slug.normalize.to_s
99
  end
100

101
  def projects
102
    @projects ||= Project.for_milestones(milestoneish_ids)
103 104
  end

105
  def state
106 107
    milestones.each do |milestone|
      return 'active' if milestone.state != 'closed'
108
    end
109 110

    'closed'
111
  end
112 113 114 115 116 117 118 119 120

  def active?
    state == 'active'
  end

  def closed?
    state == 'closed'
  end

121
  def issues
122
    @issues ||= Issue.of_milestones(milestoneish_ids).includes(:project, :assignees, :labels)
123 124
  end

125
  def merge_requests
126
    @merge_requests ||= MergeRequest.of_milestones(milestoneish_ids).includes(:target_project, :assignee, :labels)
127 128 129
  end

  def participants
130
    @participants ||= milestones.map(&:participants).flatten.uniq
131
  end
132

133
  def labels
134
    @labels ||= GlobalLabel.build_collection(milestones.includes(:labels).map(&:labels).flatten)
135
                           .sort_by!(&:title)
136
  end
137 138 139 140 141 142 143 144 145 146

  def due_date
    return @due_date if defined?(@due_date)

    @due_date =
      if @milestones.all? { |x| x.due_date == @milestones.first.due_date }
        @milestones.first.due_date
      end
  end

147 148 149 150 151 152
  def start_date
    return @start_date if defined?(@start_date)

    @start_date =
      if @milestones.all? { |x| x.start_date == @milestones.first.start_date }
        @milestones.first.start_date
153 154
      end
  end
155
end