summaryrefslogtreecommitdiff
path: root/app/helpers/labels_helper.rb
blob: c1c19062c917718bcaf29f57aa6fd7fef4c49fc5 (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
module LabelsHelper
  include ActionView::Helpers::TagHelper

  def show_label_issuables_link?(label, issuables_type, current_user: nil, project: nil)
    return true if label.is_a?(GroupLabel)
    return true unless project

    project.feature_available?(issuables_type, current_user)
  end

  # Link to a Label
  #
  # label   - Label object to link to
  # subject - Project/Group object which will be used as the context for the
  #           label's link. If omitted, defaults to the label's own group/project.
  # type    - The type of item the link will point to (:issue or
  #           :merge_request). If omitted, defaults to :issue.
  # block   - An optional block that will be passed to `link_to`, forming the
  #           body of the link element. If omitted, defaults to
  #           `render_colored_label`.
  #
  # Examples:
  #
  #   # Allow the generated link to use the label's own subject
  #   link_to_label(label)
  #
  #   # Force the generated link to use a provided group
  #   link_to_label(label, subject: Group.last)
  #
  #   # Force the generated link to use a provided project
  #   link_to_label(label, subject: Project.last)
  #
  #   # Force the generated link to point to merge requests instead of issues
  #   link_to_label(label, type: :merge_request)
  #
  #   # Customize link body with a block
  #   link_to_label(label) { "My Custom Label Text" }
  #
  # Returns a String
  def link_to_label(label, subject: nil, type: :issue, tooltip: true, css_class: nil, &block)
    link = label_filter_path(subject || label.subject, label, type: type)

    if block_given?
      link_to link, class: css_class, &block
    else
      link_to render_colored_label(label, tooltip: tooltip), link, class: css_class
    end
  end

  def label_filter_path(subject, label, type: :issue)
    case subject
    when Group
      send("#{type.to_s.pluralize}_group_path", # rubocop:disable GitlabSecurity/PublicSend
                  subject,
                  label_name: [label.name])
    when Project
      send("namespace_project_#{type.to_s.pluralize}_path", # rubocop:disable GitlabSecurity/PublicSend
                  subject.namespace,
                  subject,
                  label_name: [label.name])
    end
  end

  def edit_label_path(label)
    case label
    when GroupLabel then edit_group_label_path(label.group, label)
    when ProjectLabel then edit_project_label_path(label.project, label)
    end
  end

  def destroy_label_path(label)
    case label
    when GroupLabel then group_label_path(label.group, label)
    when ProjectLabel then project_label_path(label.project, label)
    end
  end

  def render_colored_label(label, label_suffix = '', tooltip: true)
    text_color = text_color_for_bg(label.color)

    # Intentionally not using content_tag here so that this method can be called
    # by LabelReferenceFilter
    span = %(<span class="label color-label #{"has-tooltip" if tooltip}" ) +
      %(style="background-color: #{label.color}; color: #{text_color}" ) +
      %(title="#{escape_once(label.description)}" data-container="body">) +
      %(#{escape_once(label.name)}#{label_suffix}</span>)

    span.html_safe
  end

  def suggested_colors
    [
      '#0033CC',
      '#428BCA',
      '#44AD8E',
      '#A8D695',
      '#5CB85C',
      '#69D100',
      '#004E00',
      '#34495E',
      '#7F8C8D',
      '#A295D6',
      '#5843AD',
      '#8E44AD',
      '#FFECDB',
      '#AD4363',
      '#D10069',
      '#CC0033',
      '#FF0000',
      '#D9534F',
      '#D1D100',
      '#F0AD4E',
      '#AD8D43'
    ]
  end

  def text_color_for_bg(bg_color)
    if bg_color.length == 4
      r, g, b = bg_color[1, 4].scan(/./).map { |v| (v * 2).hex }
    else
      r, g, b = bg_color[1, 7].scan(/.{2}/).map(&:hex)
    end

    if (r + g + b) > 500
      '#333333'
    else
      '#FFFFFF'
    end
  end

  def labels_filter_path(only_group_labels = false)
    project = @target_project || @project

    if project
      project_labels_path(project, :json)
    elsif @group
      options = { only_group_labels: only_group_labels } if only_group_labels
      group_labels_path(@group, :json, options)
    else
      dashboard_labels_path(:json)
    end
  end

  def can_subscribe_to_label_in_different_levels?(label)
    defined?(@project) && label.is_a?(GroupLabel)
  end

  def label_subscription_status(label, project)
    return 'group-level' if label.subscribed?(current_user)
    return 'project-level' if label.subscribed?(current_user, project)

    'unsubscribed'
  end

  def toggle_subscription_label_path(label, project)
    return toggle_subscription_group_label_path(label.group, label) unless project

    case label_subscription_status(label, project)
    when 'group-level' then toggle_subscription_group_label_path(label.group, label)
    when 'project-level' then toggle_subscription_project_label_path(project, label)
    when 'unsubscribed' then toggle_subscription_project_label_path(project, label)
    end
  end

  def label_subscription_toggle_button_text(label, project = nil)
    label.subscribed?(current_user, project) ? 'Unsubscribe' : 'Subscribe'
  end

  def label_deletion_confirm_text(label)
    case label
    when GroupLabel then 'Remove this label? This will affect all projects within the group. Are you sure?'
    when ProjectLabel then 'Remove this label? Are you sure?'
    end
  end

  # Required for Banzai::Filter::LabelReferenceFilter
  module_function :render_colored_label, :text_color_for_bg, :escape_once
end