labels_helper.rb 4.13 KB
Newer Older
1
module LabelsHelper
2 3
  include ActionView::Helpers::TagHelper

4 5 6 7 8 9
  TABLE_FOR_ESCAPE_HTML_ENTITIES = {
    '&' => '&',
    '<' => '&lt;',
    '>' => '&gt;'
  }

Robert Speicher's avatar
Robert Speicher committed
10 11 12 13 14 15
  # Link to a Label
  #
  # label   - Label object to link to
  # project - Project object which will be used as the context for the label's
  #           link. If omitted, defaults to `@project`, or the label's own
  #           project.
16 17
  # type    - The type of item the link will point to (:issue or
  #           :merge_request). If omitted, defaults to :issue.
Robert Speicher's avatar
Robert Speicher committed
18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
  # 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 project
  #   link_to_label(label)
  #
  #   # Force the generated link to use @project
  #   @project = Project.first
  #   link_to_label(label)
  #
  #   # Force the generated link to use a provided project
  #   link_to_label(label, project: Project.last)
  #
34 35 36
  #   # Force the generated link to point to merge requests instead of issues
  #   link_to_label(label, type: :merge_request)
  #
Robert Speicher's avatar
Robert Speicher committed
37 38 39 40
  #   # Customize link body with a block
  #   link_to_label(label) { "My Custom Label Text" }
  #
  # Returns a String
Phil Hughes's avatar
Phil Hughes committed
41
  def link_to_label(label, project: nil, type: :issue, tooltip: true, css_class: nil, &block)
Robert Speicher's avatar
Robert Speicher committed
42
    project ||= @project || label.project
43
    link = label_filter_path(project, label, type: type)
Robert Speicher's avatar
Robert Speicher committed
44 45

    if block_given?
Phil Hughes's avatar
Phil Hughes committed
46
      link_to link, class: css_class, &block
Robert Speicher's avatar
Robert Speicher committed
47
    else
Phil Hughes's avatar
Phil Hughes committed
48
      link_to render_colored_label(label, tooltip: tooltip), link, class: css_class
Robert Speicher's avatar
Robert Speicher committed
49 50 51
    end
  end

52 53 54 55 56 57 58
  def label_filter_path(project, label, type: issue)
    send("namespace_project_#{type.to_s.pluralize}_path",
                project.namespace,
                project,
                label_name: [label.name])
  end

59
  def project_label_names
60
    @project.labels.pluck(:title)
61 62
  end

63
  def render_colored_label(label, label_suffix = '', tooltip: true)
64
    label_color = label.color || Label::DEFAULT_COLOR
65
    text_color = text_color_for_bg(label_color)
66

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

    span.html_safe
75
  end
76

77
  def render_colored_cross_project_label(label, tooltip: true)
78
    label_suffix = label.project.name_with_namespace
79
    label_suffix = " <i>in #{escape_once(label_suffix)}</i>"
80
    render_colored_label(label, label_suffix, tooltip: tooltip)
81 82
  end

83 84
  def suggested_colors
    [
phortx's avatar
phortx committed
85
      '#0033CC',
86
      '#428BCA',
phortx's avatar
phortx committed
87 88
      '#44AD8E',
      '#A8D695',
89
      '#5CB85C',
phortx's avatar
phortx committed
90 91
      '#69D100',
      '#004E00',
92 93
      '#34495E',
      '#7F8C8D',
phortx's avatar
phortx committed
94 95
      '#A295D6',
      '#5843AD',
96
      '#8E44AD',
phortx's avatar
phortx committed
97
      '#FFECDB',
98 99 100 101 102 103 104 105
      '#AD4363',
      '#D10069',
      '#CC0033',
      '#FF0000',
      '#D9534F',
      '#D1D100',
      '#F0AD4E',
      '#AD8D43'
106 107
    ]
  end
108 109

  def text_color_for_bg(bg_color)
110 111 112 113 114
    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
115 116

    if (r + g + b) > 500
117
      '#333333'
118
    else
119
      '#FFFFFF'
120 121
    end
  end
122

123 124 125 126
  def labels_filter_path
    if @project
      namespace_project_labels_path(@project.namespace, @project, :json)
    else
127
      dashboard_labels_path(:json)
128
    end
129
  end
130

131 132 133 134 135 136 137 138
  def label_subscription_status(label)
    label.subscribed?(current_user) ? 'subscribed' : 'unsubscribed'
  end

  def label_subscription_toggle_button_text(label)
    label.subscribed?(current_user) ? 'Unsubscribe' : 'Subscribe'
  end

139 140 141 142
  def unescape_html_entities(value)
    value.to_s.gsub(/(&gt;)|(&lt;)|(&amp;)/, TABLE_FOR_ESCAPE_HTML_ENTITIES.invert)
  end

143
  # Required for Banzai::Filter::LabelReferenceFilter
144
  module_function :render_colored_label, :render_colored_cross_project_label,
145
                  :text_color_for_bg, :escape_once, :unescape_html_entities
146
end