2018-08-18 07:19:57 -04:00
|
|
|
# frozen_string_literal: true
|
|
|
|
|
2013-05-07 12:26:41 -04:00
|
|
|
module LabelsHelper
|
2018-03-05 07:33:03 -05:00
|
|
|
extend self
|
2015-04-16 12:41:59 -04:00
|
|
|
|
2019-07-23 05:30:25 -04:00
|
|
|
def show_label_issuables_link?(label, issuables_type, current_user: nil)
|
2019-05-28 06:05:20 -04:00
|
|
|
return true unless label.project_label?
|
2017-03-30 06:39:02 -04:00
|
|
|
|
2019-07-23 05:30:25 -04:00
|
|
|
label.project.feature_available?(issuables_type, current_user)
|
2017-03-30 06:39:02 -04:00
|
|
|
end
|
|
|
|
|
2015-05-21 23:40:25 -04:00
|
|
|
# Link to a Label
|
|
|
|
#
|
2019-04-23 15:58:20 -04:00
|
|
|
# label - LabelPresenter object to link to
|
2015-12-18 08:20:15 -05:00
|
|
|
# type - The type of item the link will point to (:issue or
|
|
|
|
# :merge_request). If omitted, defaults to :issue.
|
2015-05-21 23:40:25 -04:00
|
|
|
# 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:
|
|
|
|
#
|
2016-10-17 15:48:46 -04:00
|
|
|
# # Allow the generated link to use the label's own subject
|
2015-05-21 23:40:25 -04:00
|
|
|
# link_to_label(label)
|
|
|
|
#
|
2016-09-20 12:54:29 -04:00
|
|
|
# # Force the generated link to use a provided group
|
|
|
|
# link_to_label(label, subject: Group.last)
|
2015-05-21 23:40:25 -04:00
|
|
|
#
|
|
|
|
# # Force the generated link to use a provided project
|
2016-09-20 12:54:29 -04:00
|
|
|
# link_to_label(label, subject: Project.last)
|
2015-05-21 23:40:25 -04:00
|
|
|
#
|
2015-12-18 08:20:15 -05:00
|
|
|
# # Force the generated link to point to merge requests instead of issues
|
|
|
|
# link_to_label(label, type: :merge_request)
|
|
|
|
#
|
2015-05-21 23:40:25 -04:00
|
|
|
# # Customize link body with a block
|
|
|
|
# link_to_label(label) { "My Custom Label Text" }
|
|
|
|
#
|
|
|
|
# Returns a String
|
2020-02-25 10:08:50 -05:00
|
|
|
def link_to_label(label, type: :issue, tooltip: true, small: false, &block)
|
2019-04-23 15:58:20 -04:00
|
|
|
link = label.filter_path(type: type)
|
2015-05-21 23:40:25 -04:00
|
|
|
|
|
|
|
if block_given?
|
2020-02-25 10:08:50 -05:00
|
|
|
link_to link, &block
|
2015-05-21 23:40:25 -04:00
|
|
|
else
|
2020-02-25 10:08:50 -05:00
|
|
|
render_label(label, link: link, tooltip: tooltip, small: small)
|
2015-05-21 23:40:25 -04:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2020-02-25 10:08:50 -05:00
|
|
|
def render_label(label, link: nil, tooltip: true, dataset: nil, small: false)
|
|
|
|
html = render_colored_label(label)
|
2019-04-02 06:48:20 -04:00
|
|
|
|
2020-02-25 10:08:50 -05:00
|
|
|
if link
|
|
|
|
title = label_tooltip_title(label) if tooltip
|
|
|
|
html = render_label_link(html, link: link, title: title, dataset: dataset)
|
|
|
|
end
|
|
|
|
|
|
|
|
wrap_label_html(html, small: small, label: label)
|
2019-04-02 06:48:20 -04:00
|
|
|
end
|
|
|
|
|
2020-02-25 10:08:50 -05:00
|
|
|
def render_colored_label(label, suffix: '')
|
|
|
|
render_label_text(
|
|
|
|
label.name,
|
|
|
|
suffix: suffix,
|
|
|
|
css_class: text_color_class_for_bg(label.color),
|
|
|
|
bg_color: label.color
|
|
|
|
)
|
|
|
|
end
|
2014-07-29 15:19:47 -04:00
|
|
|
|
2020-02-25 10:08:50 -05:00
|
|
|
# We need the `label` argument here for EE
|
|
|
|
def wrap_label_html(label_html, small:, label:)
|
|
|
|
wrapper_classes = %w(gl-label)
|
|
|
|
wrapper_classes << 'gl-label-sm' if small
|
2015-04-02 20:46:43 -04:00
|
|
|
|
2020-02-25 10:08:50 -05:00
|
|
|
%(<span class="#{wrapper_classes.join(' ')}">#{label_html}</span>).html_safe
|
2013-05-07 12:26:41 -04:00
|
|
|
end
|
2014-07-30 06:27:29 -04:00
|
|
|
|
2019-04-02 06:48:20 -04:00
|
|
|
def label_tooltip_title(label)
|
2019-07-15 07:29:56 -04:00
|
|
|
Sanitize.clean(label.description)
|
2019-04-02 06:48:20 -04:00
|
|
|
end
|
|
|
|
|
2014-07-30 06:27:29 -04:00
|
|
|
def suggested_colors
|
2019-05-15 17:23:56 -04:00
|
|
|
{
|
|
|
|
'#0033CC' => s_('SuggestedColors|UA blue'),
|
|
|
|
'#428BCA' => s_('SuggestedColors|Moderate blue'),
|
2019-05-30 04:36:44 -04:00
|
|
|
'#44AD8E' => s_('SuggestedColors|Lime green'),
|
2019-05-15 17:23:56 -04:00
|
|
|
'#A8D695' => s_('SuggestedColors|Feijoa'),
|
|
|
|
'#5CB85C' => s_('SuggestedColors|Slightly desaturated green'),
|
2019-05-30 04:36:44 -04:00
|
|
|
'#69D100' => s_('SuggestedColors|Bright green'),
|
2019-05-15 17:23:56 -04:00
|
|
|
'#004E00' => s_('SuggestedColors|Very dark lime green'),
|
|
|
|
'#34495E' => s_('SuggestedColors|Very dark desaturated blue'),
|
|
|
|
'#7F8C8D' => s_('SuggestedColors|Dark grayish cyan'),
|
|
|
|
'#A295D6' => s_('SuggestedColors|Slightly desaturated blue'),
|
|
|
|
'#5843AD' => s_('SuggestedColors|Dark moderate blue'),
|
|
|
|
'#8E44AD' => s_('SuggestedColors|Dark moderate violet'),
|
|
|
|
'#FFECDB' => s_('SuggestedColors|Very pale orange'),
|
|
|
|
'#AD4363' => s_('SuggestedColors|Dark moderate pink'),
|
|
|
|
'#D10069' => s_('SuggestedColors|Strong pink'),
|
|
|
|
'#CC0033' => s_('SuggestedColors|Strong red'),
|
|
|
|
'#FF0000' => s_('SuggestedColors|Pure red'),
|
|
|
|
'#D9534F' => s_('SuggestedColors|Soft red'),
|
|
|
|
'#D1D100' => s_('SuggestedColors|Strong yellow'),
|
|
|
|
'#F0AD4E' => s_('SuggestedColors|Soft orange'),
|
|
|
|
'#AD8D43' => s_('SuggestedColors|Dark moderate orange')
|
|
|
|
}
|
|
|
|
end
|
|
|
|
|
|
|
|
def render_suggested_colors
|
|
|
|
colors_html = suggested_colors.map do |color_hex_value, color_name|
|
|
|
|
link_to('', '#', class: "has-tooltip", style: "background-color: #{color_hex_value}", data: { color: color_hex_value }, title: color_name)
|
|
|
|
end
|
|
|
|
|
|
|
|
content_tag(:div, class: 'suggest-colors') do
|
|
|
|
colors_html.join.html_safe
|
|
|
|
end
|
2014-07-30 06:27:29 -04:00
|
|
|
end
|
2014-07-30 10:17:29 -04:00
|
|
|
|
2020-02-25 10:08:50 -05:00
|
|
|
def text_color_class_for_bg(bg_color)
|
2020-02-27 07:09:12 -05:00
|
|
|
if light_color?(bg_color)
|
2020-02-25 10:08:50 -05:00
|
|
|
'gl-label-text-dark'
|
|
|
|
else
|
|
|
|
'gl-label-text-light'
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2014-07-30 10:17:29 -04:00
|
|
|
def text_color_for_bg(bg_color)
|
2020-02-27 07:09:12 -05:00
|
|
|
if light_color?(bg_color)
|
|
|
|
'#333333'
|
2016-01-24 18:06:46 -05:00
|
|
|
else
|
2020-02-27 07:09:12 -05:00
|
|
|
'#FFFFFF'
|
2016-01-24 18:06:46 -05:00
|
|
|
end
|
2020-02-27 07:09:12 -05:00
|
|
|
end
|
2014-07-30 10:17:29 -04:00
|
|
|
|
2020-02-27 07:09:12 -05:00
|
|
|
def light_color?(color)
|
|
|
|
if color.length == 4
|
|
|
|
r, g, b = color[1, 4].scan(/./).map { |v| (v * 2).hex }
|
2014-07-30 10:17:29 -04:00
|
|
|
else
|
2020-02-27 07:09:12 -05:00
|
|
|
r, g, b = color[1, 7].scan(/.{2}/).map(&:hex)
|
2014-07-30 10:17:29 -04:00
|
|
|
end
|
2020-02-27 07:09:12 -05:00
|
|
|
|
|
|
|
(r + g + b) > 500
|
2014-07-30 10:17:29 -04:00
|
|
|
end
|
2015-03-26 22:13:49 -04:00
|
|
|
|
2018-10-03 06:36:35 -04:00
|
|
|
def labels_filter_path_with_defaults(only_group_labels: false, include_ancestor_groups: true, include_descendant_groups: false)
|
2018-04-04 11:40:29 -04:00
|
|
|
options = {}
|
|
|
|
options[:include_ancestor_groups] = include_ancestor_groups if include_ancestor_groups
|
|
|
|
options[:include_descendant_groups] = include_descendant_groups if include_descendant_groups
|
2018-10-03 06:36:35 -04:00
|
|
|
options[:only_group_labels] = only_group_labels if only_group_labels && @group
|
|
|
|
options[:format] = :json
|
|
|
|
|
|
|
|
labels_filter_path(options)
|
|
|
|
end
|
|
|
|
|
|
|
|
def labels_filter_path(options = {})
|
|
|
|
project = @target_project || @project
|
2018-10-31 10:47:53 -04:00
|
|
|
format = options.delete(:format)
|
2018-04-04 11:40:29 -04:00
|
|
|
|
2016-07-18 12:43:00 -04:00
|
|
|
if project
|
2018-10-03 06:36:35 -04:00
|
|
|
project_labels_path(project, format, options)
|
2017-08-28 17:56:49 -04:00
|
|
|
elsif @group
|
2018-10-03 06:36:35 -04:00
|
|
|
group_labels_path(@group, format, options)
|
2016-03-16 15:14:31 -04:00
|
|
|
else
|
2018-10-03 06:36:35 -04:00
|
|
|
dashboard_labels_path(format, options)
|
2016-03-16 15:14:31 -04:00
|
|
|
end
|
2015-03-26 22:13:49 -04:00
|
|
|
end
|
2015-04-02 20:46:43 -04:00
|
|
|
|
2016-11-15 18:11:13 -05:00
|
|
|
def label_subscription_status(label, project)
|
2016-11-15 16:59:12 -05:00
|
|
|
return 'group-level' if label.subscribed?(current_user)
|
2017-06-22 22:11:14 -04:00
|
|
|
return 'project-level' if label.subscribed?(current_user, project)
|
2016-11-15 16:59:12 -05:00
|
|
|
|
|
|
|
'unsubscribed'
|
|
|
|
end
|
|
|
|
|
2017-06-22 22:11:14 -04:00
|
|
|
def toggle_subscription_label_path(label, project)
|
2017-06-26 16:52:14 -04:00
|
|
|
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)
|
2017-06-29 13:06:35 -04:00
|
|
|
when 'project-level' then toggle_subscription_project_label_path(project, label)
|
|
|
|
when 'unsubscribed' then toggle_subscription_project_label_path(project, label)
|
2016-11-15 16:59:12 -05:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2017-06-22 22:11:14 -04:00
|
|
|
def label_subscription_toggle_button_text(label, project = nil)
|
2016-11-01 13:02:58 -04:00
|
|
|
label.subscribed?(current_user, project) ? 'Unsubscribe' : 'Subscribe'
|
2016-03-01 11:33:13 -05:00
|
|
|
end
|
|
|
|
|
2018-03-08 07:39:32 -05:00
|
|
|
def create_label_title(subject)
|
|
|
|
case subject
|
|
|
|
when Group
|
|
|
|
_('Create group label')
|
|
|
|
when Project
|
|
|
|
_('Create project label')
|
|
|
|
else
|
|
|
|
_('Create new label')
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def manage_labels_title(subject)
|
|
|
|
case subject
|
|
|
|
when Group
|
|
|
|
_('Manage group labels')
|
|
|
|
when Project
|
|
|
|
_('Manage project labels')
|
|
|
|
else
|
|
|
|
_('Manage labels')
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def view_labels_title(subject)
|
|
|
|
case subject
|
|
|
|
when Group
|
|
|
|
_('View group labels')
|
|
|
|
when Project
|
|
|
|
_('View project labels')
|
|
|
|
else
|
|
|
|
_('View labels')
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2018-05-29 05:35:26 -04:00
|
|
|
def label_status_tooltip(label, status)
|
2019-05-28 06:05:20 -04:00
|
|
|
type = label.project_label? ? 'project' : 'group'
|
2018-05-29 05:35:26 -04:00
|
|
|
level = status.unsubscribed? ? type : status.sub('-level', '')
|
|
|
|
action = status.unsubscribed? ? 'Subscribe' : 'Unsubscribe'
|
2018-05-29 05:25:45 -04:00
|
|
|
|
2018-05-29 05:35:26 -04:00
|
|
|
"#{action} at #{level} level"
|
2018-05-29 05:25:45 -04:00
|
|
|
end
|
|
|
|
|
2019-04-23 15:58:20 -04:00
|
|
|
def presented_labels_sorted_by_title(labels, subject)
|
|
|
|
labels.sort_by(&:title).map { |label| label.present(issuable_subject: subject) }
|
2019-02-21 11:06:14 -05:00
|
|
|
end
|
|
|
|
|
2019-04-02 06:48:20 -04:00
|
|
|
def label_dropdown_data(project, opts = {})
|
|
|
|
{
|
|
|
|
toggle: "dropdown",
|
|
|
|
field_name: opts[:field_name] || "label_name[]",
|
|
|
|
show_no: "true",
|
|
|
|
show_any: "true",
|
|
|
|
project_id: project&.try(:id),
|
|
|
|
namespace_path: project&.try(:namespace)&.try(:full_path),
|
|
|
|
project_path: project&.try(:path)
|
|
|
|
}.merge(opts)
|
|
|
|
end
|
|
|
|
|
|
|
|
def sidebar_label_dropdown_data(issuable_type, issuable_sidebar)
|
|
|
|
label_dropdown_data(nil, {
|
|
|
|
default_label: "Labels",
|
|
|
|
field_name: "#{issuable_type}[label_names][]",
|
|
|
|
ability_name: issuable_type,
|
|
|
|
namespace_path: issuable_sidebar[:namespace_path],
|
|
|
|
project_path: issuable_sidebar[:project_path],
|
|
|
|
issue_update: issuable_sidebar[:issuable_json_path],
|
|
|
|
labels: issuable_sidebar[:project_labels_path],
|
|
|
|
display: 'static'
|
|
|
|
})
|
|
|
|
end
|
|
|
|
|
2019-04-04 09:34:55 -04:00
|
|
|
def label_from_hash(hash)
|
|
|
|
klass = hash[:group_id] ? GroupLabel : ProjectLabel
|
|
|
|
|
|
|
|
klass.new(hash.slice(:color, :description, :title, :group_id, :project_id))
|
|
|
|
end
|
|
|
|
|
2019-04-22 01:54:23 -04:00
|
|
|
def issuable_types
|
|
|
|
['issues', 'merge requests']
|
|
|
|
end
|
2020-02-25 10:08:50 -05:00
|
|
|
|
|
|
|
private
|
|
|
|
|
|
|
|
def render_label_link(label_html, link:, title:, dataset:)
|
|
|
|
classes = %w(gl-link gl-label-link)
|
|
|
|
dataset ||= {}
|
|
|
|
|
|
|
|
if title.present?
|
|
|
|
classes << 'has-tooltip'
|
|
|
|
dataset.merge!(html: true, title: title)
|
|
|
|
end
|
|
|
|
|
|
|
|
link_to(label_html, link, class: classes.join(' '), data: dataset)
|
|
|
|
end
|
|
|
|
|
|
|
|
def render_label_text(name, suffix: '', css_class: nil, bg_color: nil)
|
|
|
|
<<~HTML.chomp.html_safe
|
|
|
|
<span
|
|
|
|
class="gl-label-text #{css_class}"
|
|
|
|
data-container="body"
|
|
|
|
data-html="true"
|
|
|
|
#{"style=\"background-color: #{bg_color}\"" if bg_color}
|
|
|
|
>#{ERB::Util.html_escape_once(name)}#{suffix}</span>
|
|
|
|
HTML
|
|
|
|
end
|
2013-05-07 12:26:41 -04:00
|
|
|
end
|
2019-09-13 09:26:31 -04:00
|
|
|
|
|
|
|
LabelsHelper.prepend_if_ee('EE::LabelsHelper')
|