summaryrefslogtreecommitdiff
path: root/app/helpers/milestones_helper.rb
blob: be8cb358de2d49e25b61a356744f03a763d23815 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
module MilestonesHelper
  def milestones_filter_path(opts = {})
    if @project
      project_milestones_path(@project, opts)
    elsif @group
      group_milestones_path(@group, opts)
    else
      dashboard_milestones_path(opts)
    end
  end

  def milestones_label_path(opts = {})
    if @project
      project_issues_path(@project, opts)
    elsif @group
      issues_group_path(@group, opts)
    else
      issues_dashboard_path(opts)
    end
  end

  def milestones_browse_issuables_path(milestone, state: nil, type:)
    opts = { milestone_title: milestone.title, state: state }

    if @project
      polymorphic_path([@project.namespace.becomes(Namespace), @project, type], opts)
    elsif @group
      polymorphic_url([type, @group], opts)
    else
      polymorphic_url([type, :dashboard], opts)
    end
  end

  def milestone_issues_by_label_count(milestone, label, state:)
    issues = milestone.issues.with_label(label.title)
    issues =
      case state
      when :opened
        issues.opened
      when :closed
        issues.closed
      else
        raise ArgumentError, "invalid milestone state `#{state}`"
      end

    issues.size
  end

  # Returns count of milestones for different states
  # Uses explicit hash keys as the 'opened' state URL params differs from the db value
  # and we need to add the total
  def milestone_counts(milestones)
    counts = milestones.reorder(nil).group(:state).count

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

  # Show 'active' class if provided GET param matches check
  # `or_blank` allows the function to return 'active' when given an empty param
  # Could be refactored to be simpler but that may make it harder to read
  def milestone_class_for_state(param, check, match_blank_param = false)
    if match_blank_param
      'active' if param.blank? || param == check
    elsif param == check
      'active'
    else
      check
    end
  end

  def milestone_progress_bar(milestone)
    options = {
      class: 'progress-bar progress-bar-success',
      style: "width: #{milestone.percent_complete(current_user)}%;"
    }

    content_tag :div, class: 'progress' do
      content_tag :div, nil, options
    end
  end

  def milestones_filter_dropdown_path
    project = @target_project || @project
    if project
      project_milestones_path(project, :json)
    elsif @group
      group_milestones_path(@group, :json)
    else
      dashboard_milestones_path(:json)
    end
  end

  def milestone_tooltip_title(milestone)
    if milestone.due_date
      [milestone.due_date.to_s(:medium), "(#{milestone_remaining_days(milestone)})"].join(' ')
    end
  end

  def milestone_remaining_days(milestone)
    if milestone.expired?
      content_tag(:strong, 'Past due')
    elsif milestone.upcoming?
      content_tag(:strong, 'Upcoming')
    elsif milestone.due_date
      time_ago = time_ago_in_words(milestone.due_date)
      content = time_ago.gsub(/\d+/) { |match| "<strong>#{match}</strong>" }
      content.slice!("about ")
      content << " remaining"
      content.html_safe
    elsif milestone.start_date && milestone.start_date.past?
      days    = milestone.elapsed_days
      content = content_tag(:strong, days)
      content << " #{'day'.pluralize(days)} elapsed"
      content.html_safe
    end
  end

  def milestone_date_range(milestone)
    if milestone.start_date && milestone.due_date
      "#{milestone.start_date.to_s(:medium)}–#{milestone.due_date.to_s(:medium)}"
    elsif milestone.due_date
      if milestone.due_date.past?
        "expired on #{milestone.due_date.to_s(:medium)}"
      else
        "expires on #{milestone.due_date.to_s(:medium)}"
      end
    elsif milestone.start_date
      if milestone.start_date.past?
        "started on #{milestone.start_date.to_s(:medium)}"
      else
        "starts on #{milestone.start_date.to_s(:medium)}"
      end
    end
  end

  def milestone_merge_request_tab_path(milestone)
    if @project
      merge_requests_project_milestone_path(@project, milestone, format: :json)
    elsif @group
      merge_requests_group_milestone_path(@group, milestone.safe_title, title: milestone.title, format: :json)
    else
      merge_requests_dashboard_milestone_path(milestone, title: milestone.title, format: :json)
    end
  end

  def milestone_participants_tab_path(milestone)
    if @project
      participants_project_milestone_path(@project, milestone, format: :json)
    elsif @group
      participants_group_milestone_path(@group, milestone.safe_title, title: milestone.title, format: :json)
    else
      participants_dashboard_milestone_path(milestone, title: milestone.title, format: :json)
    end
  end

  def milestone_labels_tab_path(milestone)
    if @project
      labels_project_milestone_path(@project, milestone, format: :json)
    elsif @group
      labels_group_milestone_path(@group, milestone.safe_title, title: milestone.title, format: :json)
    else
      labels_dashboard_milestone_path(milestone, title: milestone.title, format: :json)
    end
  end

  def group_milestone_route(milestone, params = {})
    params = nil if params.empty?

    if milestone.legacy_group_milestone?
      group_milestone_path(@group, milestone.safe_title, title: milestone.title, milestone: params)
    else
      group_milestone_path(@group, milestone.iid, milestone: params)
    end
  end
end