Commit fec2e27f authored by Jan Provaznik's avatar Jan Provaznik

[backend] backport of scoped labels

Scoped labels in EE require additional changes in CE code.
parent 97ab8539
......@@ -7,6 +7,9 @@ module IssuableActions
included do
before_action :authorize_destroy_issuable!, only: :destroy
before_action :authorize_admin_issuable!, only: :bulk_update
before_action only: :show do
push_frontend_feature_flag(:scoped_labels, default_enabled: true)
end
end
def permitted_keys
......
......@@ -46,7 +46,7 @@ module LabelsHelper
if block_given?
link_to link, class: css_class, &block
else
link_to render_colored_label(label, tooltip: tooltip), link, class: css_class
render_label(label, tooltip: tooltip, link: link, css: css_class)
end
end
......@@ -78,19 +78,33 @@ module LabelsHelper
end
end
def render_colored_label(label, label_suffix = '', tooltip: true)
def render_label(label, tooltip: true, link: nil, css: nil)
# if scoped label is used then EE wraps label tag with scoped label
# doc link
html = render_colored_label(label, tooltip: tooltip)
html = link_to(html, link, class: css) if link
html
end
def render_colored_label(label, label_suffix: '', tooltip: true, title: nil)
text_color = text_color_for_bg(label.color)
title ||= label_tooltip_title(label)
# Intentionally not using content_tag here so that this method can be called
# by LabelReferenceFilter
span = %(<span class="badge color-label #{"has-tooltip" if tooltip}" ) +
%(style="background-color: #{label.color}; color: #{text_color}" ) +
%(title="#{escape_once(label.description)}" data-container="body">) +
%(data-html="true" style="background-color: #{label.color}; color: #{text_color}" ) +
%(title="#{escape_once(title)}" data-container="body">) +
%(#{escape_once(label.name)}#{label_suffix}</span>)
span.html_safe
end
def label_tooltip_title(label)
label.description
end
def suggested_colors
[
'#0033CC',
......@@ -231,6 +245,31 @@ module LabelsHelper
labels.sort_by(&:title)
end
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
# Required for Banzai::Filter::LabelReferenceFilter
module_function :render_colored_label, :text_color_for_bg, :escape_once
module_function :render_colored_label, :text_color_for_bg, :escape_once, :label_tooltip_title
end
......@@ -4,7 +4,7 @@ class GlobalLabel
attr_accessor :title, :labels
alias_attribute :name, :title
delegate :color, :text_color, :description, to: :@first_label
delegate :color, :text_color, :description, :scoped_label?, to: :@first_label
def for_display
@first_label
......
......@@ -107,12 +107,13 @@ class IssuableBaseService < BaseService
@labels_service ||= ::Labels::AvailableLabelsService.new(current_user, parent, params)
end
def process_label_ids(attributes, existing_label_ids: nil)
def process_label_ids(attributes, existing_label_ids: nil, extra_label_ids: [])
label_ids = attributes.delete(:label_ids)
add_label_ids = attributes.delete(:add_label_ids)
remove_label_ids = attributes.delete(:remove_label_ids)
new_label_ids = existing_label_ids || label_ids || []
new_label_ids |= extra_label_ids
if add_label_ids.blank? && remove_label_ids.blank?
new_label_ids = label_ids if label_ids
......@@ -147,7 +148,7 @@ class IssuableBaseService < BaseService
params.delete(:state_event)
params[:author] ||= current_user
params[:label_ids] = issuable.label_ids.to_a + process_label_ids(params)
params[:label_ids] = process_label_ids(params, extra_label_ids: issuable.label_ids.to_a)
issuable.assign_attributes(params)
......
......@@ -2,7 +2,7 @@
.modal-dialog
.modal-content
.modal-header
%h3.page-title Delete #{render_colored_label(label, tooltip: false)} ?
%h3.page-title Delete #{render_label(label, tooltip: false)} ?
%button.close{ type: "button", "data-dismiss": "modal", "aria-label" => _('Close') }
%span{ "aria-hidden": true } &times;
......
......@@ -7,7 +7,7 @@
- if defined?(@project)
= link_to_label(label, subject: @project, tooltip: false)
- else
= render_colored_label(label, tooltip: false)
= render_label(label, tooltip: false)
.label-description
.append-right-default.prepend-left-default
- if label.description.present?
......
......@@ -21,13 +21,7 @@
%button.dropdown-menu-toggle.js-label-select.js-multiselect.js-issue-board-sidebar{ type: "button",
":data-selected" => "selectedLabels",
":data-labels" => "issue.assignableLabelsEndpoint",
data: { toggle: "dropdown",
field_name: "issue[label_names][]",
show_no: "true",
show_any: "true",
project_id: @project&.try(:id),
namespace_path: @namespace_path,
project_path: @project.try(:path) } }
data: label_dropdown_data(@project, namespace_path: @namespace_path, field_name: "issue[label_names][]") }
%span.dropdown-toggle-text
{{ labelDropdownTitle }}
= icon('chevron-down')
......
......@@ -8,7 +8,7 @@
- classes = local_assigns.fetch(:classes, [])
- selected = local_assigns.fetch(:selected, nil)
- dropdown_title = local_assigns.fetch(:dropdown_title, "Filter by label")
- dropdown_data = {toggle: 'dropdown', field_name: "label_name[]", show_no: "true", show_any: "true", namespace_path: @project.try(:namespace).try(:full_path), project_path: @project.try(:path), labels: labels_filter_path_with_defaults, default_label: "Labels"}
- dropdown_data = label_dropdown_data(@project, labels: labels_filter_path_with_defaults, default_label: "Labels")
- dropdown_data.merge!(data_options)
- label_name = local_assigns.fetch(:label_name, "Labels")
- no_default_styles = local_assigns.fetch(:no_default_styles, false)
......
......@@ -105,10 +105,9 @@
= link_to _('Edit'), '#', class: 'js-sidebar-dropdown-toggle edit-link float-right'
.value.issuable-show-labels.dont-hide.hide-collapsed.qa-labels-block{ class: ("has-labels" if selected_labels.any?) }
- if selected_labels.any?
- selected_labels.each do |label|
= link_to sidebar_label_filter_path(issuable_sidebar[:project_issuables_path], label[:title]) do
%span.badge.color-label.has-tooltip{ style: "background-color: #{label[:color]}; color: #{label[:text_color]}", title: label[:description], data: { container: "body" } }
= label[:title]
- selected_labels.each do |label_hash|
- label = Label.new(label_hash.slice(:color, :description, :title))
= render_label(label, link: sidebar_label_filter_path(issuable_sidebar[:project_issuables_path], label[:title]))
- else
%span.no-value
= _('None')
......@@ -116,7 +115,7 @@
- selected_labels.each do |label|
= hidden_field_tag "#{issuable_type}[label_names][]", label[:id], id: nil
.dropdown
%button.dropdown-menu-toggle.js-label-select.js-multiselect.js-label-sidebar-dropdown{ type: "button", data: {toggle: "dropdown", default_label: "Labels", field_name: "#{issuable_type}[label_names][]", ability_name: issuable_type, show_no: "true", show_any: "true", 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' } }
%button.dropdown-menu-toggle.js-label-select.js-multiselect.js-label-sidebar-dropdown{ type: "button", data: sidebar_label_dropdown_data(issuable_type, issuable_sidebar) }
%span.dropdown-toggle-text{ class: ("is-default" if selected_labels.empty?) }
= multi_label_name(selected_labels, "Labels")
= icon('chevron-down', 'aria-hidden': 'true')
......
......@@ -4,7 +4,9 @@
.form-group.row
= f.label :title, class: 'col-form-label col-sm-2'
.col-sm-10
= f.text_field :title, class: "form-control qa-label-title", required: true, autofocus: true
= f.text_field :title, class: "form-control js-label-title qa-label-title", required: true, autofocus: true
= render_if_exists 'shared/labels/create_label_help_text'
.form-group.row
= f.label :description, class: 'col-form-label col-sm-2'
.col-sm-10
......
......@@ -22,7 +22,7 @@
- labels.each do |label|
= link_to polymorphic_path(issuable_type_args, { milestone_title: @milestone.title, label_name: label.title, state: 'all' }) do
- render_colored_label(label)
- render_label(label)
%span.assignee-icon
- assignees.each do |assignee|
......
......@@ -5,8 +5,7 @@
%li.is-not-draggable
%span.label-row
%span.label-name
= link_to milestones_label_path(options) do
- render_colored_label(label, tooltip: false)
= render_label(label, tooltip: false, link: milestones_label_path(options))
%span.prepend-description-left
= markdown_field(label, :description)
......
......@@ -195,15 +195,21 @@ module Banzai
content = link_content || object_link_text(object, matches)
%(<a href="#{url}" #{data}
title="#{escape_once(title)}"
class="#{klass}">#{content}</a>)
link = %(<a href="#{url}" #{data}
title="#{escape_once(title)}"
class="#{klass}">#{content}</a>)
wrap_link(link, object)
else
match
end
end
end
def wrap_link(link, object)
link
end
def data_attributes_for(text, parent, object, link_content: false, link_reference: false)
object_parent_type = parent.is_a?(Group) ? :group : :project
......
......@@ -91,7 +91,11 @@ module Banzai
label_suffix = " <i>in #{reference}</i>" if reference.present?
end
LabelsHelper.render_colored_label(object, label_suffix)
LabelsHelper.render_colored_label(object, label_suffix: label_suffix, title: tooltip_title(object))
end
def tooltip_title(label)
nil
end
def full_path_ref?(matches)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment