summaryrefslogtreecommitdiff
path: root/app/models/label_note.rb
blob: 13a2e1b0c72b746eb8e58ae377b7adc6b9ed455c (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
# frozen_string_literal: true

class LabelNote < Note
  attr_accessor :resource_parent
  attr_reader :events

  def self.from_events(events, resource: nil, resource_parent: nil)
    resource ||= events.first.issuable

    attrs = {
      system: true,
      author: events.first.user,
      created_at: events.first.created_at,
      discussion_id: events.first.discussion_id,
      noteable: resource,
      system_note_metadata: SystemNoteMetadata.new(action: 'label'),
      events: events,
      resource_parent: resource_parent
    }

    if resource_parent.is_a?(Project)
      attrs[:project_id] = resource_parent.id
    end

    LabelNote.new(attrs)
  end

  def events=(events)
    @events = events

    update_outdated_markdown
  end

  def cached_html_up_to_date?(markdown_field)
    true
  end

  def note
    @note ||= note_text
  end

  def note_html
    @note_html ||= "<p dir=\"auto\">#{note_text(html: true)}</p>"
  end

  def project
    resource_parent if resource_parent.is_a?(Project)
  end

  def group
    resource_parent if resource_parent.is_a?(Group)
  end

  private

  def update_outdated_markdown
    events.each do |event|
      if event.outdated_markdown?
        event.refresh_invalid_reference
      end
    end
  end

  def note_text(html: false)
    added = labels_str(label_refs_by_action('add', html), prefix: 'added', suffix: added_suffix)
    removed = labels_str(label_refs_by_action('remove', html), prefix: removed_prefix)

    [added, removed].compact.join(' and ')
  end

  def removed_prefix
    'removed'
  end

  def added_suffix
    ''
  end

  # returns string containing added/removed labels including
  # count of deleted labels:
  #
  # added ~1 ~2 + 1 deleted label
  # added 3 deleted labels
  # added ~1 ~2 labels
  def labels_str(label_refs, prefix: '', suffix: '')
    existing_refs = label_refs.select { |ref| ref.present? }.sort
    refs_str = existing_refs.empty? ? nil : existing_refs.join(' ')

    deleted = label_refs.count - existing_refs.count
    deleted_str = deleted == 0 ? nil : "#{deleted} deleted"

    return unless refs_str || deleted_str

    label_list_str = [refs_str, deleted_str].compact.join(' + ')
    suffix += ' label'.pluralize(deleted > 0 ? deleted : existing_refs.count)

    "#{prefix} #{label_list_str} #{suffix.squish}"
  end

  def label_refs_by_action(action, html)
    field = html ? :reference_html : :reference

    events.select { |e| e.action == action }.map(&field)
  end
end

LabelNote.prepend_if_ee('EE::LabelNote')