summaryrefslogtreecommitdiff
path: root/app/serializers/entity_date_helper.rb
blob: cc0c2abf8632c1e3290e7a56f0ea0a40b7e24514 (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
# frozen_string_literal: true

module EntityDateHelper
  include ActionView::Helpers::DateHelper
  include ActionView::Helpers::TagHelper

  def interval_in_words(diff)
    return 'Not started' unless diff

    distance_of_time_in_words(Time.now, diff, scope: 'datetime.time_ago_in_words')
  end

  # Converts seconds into a hash such as:
  # { days: 1, hours: 3, mins: 42, seconds: 40 }
  #
  # It returns 0 seconds for zero or negative numbers
  # It rounds to nearest time unit and does not return zero
  # i.e { min: 1 } instead of { mins: 1, seconds: 0 }
  def distance_of_time_as_hash(diff)
    diff = diff.abs.floor

    return { seconds: 0 } if diff == 0

    mins = (diff / 60).floor
    seconds = diff % 60
    hours = (mins / 60).floor
    mins = mins % 60
    days = (hours / 24).floor
    hours = hours % 24

    duration_hash = {}

    duration_hash[:days] = days if days > 0
    duration_hash[:hours] = hours if hours > 0
    duration_hash[:mins] = mins if mins > 0
    duration_hash[:seconds] = seconds if seconds > 0

    duration_hash
  end

  # Generates an HTML-formatted string for remaining dates based on start_date and due_date
  #
  # It returns "Past due" for expired entities
  # It returns "Upcoming" for upcoming entities
  # If due date is provided, it returns "# days|weeks|months remaining|ago"
  # If start date is provided and elapsed, with no due date, it returns "# days elapsed"
  def remaining_days_in_words(entity)
    if entity.try(:expired?)
      content_tag(:strong, 'Past due')
    elsif entity.try(:upcoming?)
      content_tag(:strong, 'Upcoming')
    elsif entity.due_date
      is_upcoming = (entity.due_date - Date.today).to_i > 0
      time_ago = time_ago_in_words(entity.due_date)

      # https://gitlab.com/gitlab-org/gitlab-ce/issues/49440
      #
      # Need to improve the i18n here and do a full translation
      # of the string instead of piecewise translations.
      content = time_ago
        .gsub(/\d+/) { |match| "<strong>#{match}</strong>" }
        .remove("about ")
      remaining_or_ago = is_upcoming ? _("remaining") : _("ago")

      "#{content} #{remaining_or_ago}".html_safe
    elsif entity.start_date && entity.start_date.past?
      days = entity.elapsed_days
      "#{content_tag(:strong, days)} #{'day'.pluralize(days)} elapsed".html_safe
    end
  end
end