Module: ButtonHelper

Included in:
SortingHelper
Defined in:
app/helpers/button_helper.rb

Instance Method Summary collapse

Instance Method Details

#clipboard_button(data = {}) ⇒ Object

Output a “Copy to Clipboard” button

data - Data attributes passed to ‘content_tag` (default: {}):

:text   - Text to copy (optional)
:gfm    - GitLab Flavored Markdown to copy, if different from `text` (optional)
:target - Selector for target element to copy from (optional)
:class  - CSS classes to be applied to the button (optional)
:title  - Button's title attribute (used for the tooltip) (optional)
:button_text - Button's displayed label (optional)
:hide_tooltip - Whether the tooltip should be hidden (optional, default: false)
:hide_button_icon - Whether the icon should be hidden (optional, default: false)
:item_prop - itemprop attribute
:variant - Button variant (optional, default: :default)
:category - Button category (optional, default: :tertiary)
:size - Button size (optional, default: :small)

Examples:

# Define the clipboard's text
clipboard_button(text: "Foo")
# => "<button class='...' data-clipboard-text='Foo'>...</button>"

# Define the target element
clipboard_button(target: "div#foo")
# => "<button class='...' data-clipboard-target='div#foo'>...</button>"

See clipboardjs.com/#usage



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
# File 'app/helpers/button_helper.rb', line 31

def clipboard_button(data = {})
  css_class = data.delete(:class)
  title = data.delete(:title) || _('Copy')
  button_text = data[:button_text] || nil
  hide_tooltip = data[:hide_tooltip] || false
  hide_button_icon = data[:hide_button_icon] || false
  item_prop = data[:itemprop] || nil
  variant = data[:variant] || :default
  category = data[:category] || :tertiary
  size = data[:size] || :small

  # This supports code in app/assets/javascripts/copy_to_clipboard.js that
  # works around ClipboardJS limitations to allow the context-specific copy/pasting of plain text or GFM.
  if text = data.delete(:text)
    data[:clipboard_text] =
      if gfm = data.delete(:gfm)
        { text: text, gfm: gfm }
      else
        text
      end
  end

  target = data.delete(:target)
  data[:clipboard_target] = target if target

  unless hide_tooltip
    data = { toggle: 'tooltip', placement: 'bottom', container: 'body' }.merge(data)
  end

  render ::Pajamas::ButtonComponent.new(
    icon: hide_button_icon ? nil : 'copy-to-clipboard',
    variant: variant,
    category: category,
    size: size,
    button_options: { class: css_class, title: title, aria: { label: title, live: 'polite' }, data: data, itemprop: item_prop }) do
    button_text
  end
end

#deprecated_clipboard_button(data = {}) ⇒ Object

Output a “Copy to Clipboard” button Note: This is being replaced by a Pajamas-compliant helper that renders the button via ::Pajamas::ButtonComponent. Please use clipboard_button instead.

data - Data attributes passed to ‘content_tag` (default: {}):

:text   - Text to copy (optional)
:gfm    - GitLab Flavored Markdown to copy, if different from `text` (optional)
:target - Selector for target element to copy from (optional)

Examples:

# Define the clipboard's text
clipboard_button(text: "Foo")
# => "<button class='...' data-clipboard-text='Foo'>...</button>"

# Define the target element
clipboard_button(target: "div#foo")
# => "<button class='...' data-clipboard-target='div#foo'>...</button>"

See clipboardjs.com/#usage



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
# File 'app/helpers/button_helper.rb', line 90

def deprecated_clipboard_button(data = {})
  css_class = data.delete(:class) || 'btn-clipboard gl-button btn-default-tertiary btn-icon btn-sm'
  title = data.delete(:title) || _('Copy')
  button_text = data[:button_text] || nil
  hide_tooltip = data[:hide_tooltip] || false
  hide_button_icon = data[:hide_button_icon] || false
  item_prop = data[:itemprop] || nil

  # This supports code in app/assets/javascripts/copy_to_clipboard.js that
  # works around ClipboardJS limitations to allow the context-specific copy/pasting of plain text or GFM.
  if text = data.delete(:text)
    data[:clipboard_text] =
      if gfm = data.delete(:gfm)
        { text: text, gfm: gfm }
      else
        text
      end
  end

  target = data.delete(:target)
  data[:clipboard_target] = target if target

  unless hide_tooltip
    data = { toggle: 'tooltip', placement: 'bottom', container: 'body' }.merge(data)
  end

  button_attributes = {
    class: "btn #{css_class}",
    data: data,
    type: :button,
    title: title,
    aria: { label: title, live: 'polite' },
    itemprop: item_prop
  }

   :button, button_attributes do
    concat(sprite_icon('copy-to-clipboard', css_class: ['gl-icon', *('gl-button-icon' unless button_text.nil?)].join(' '))) unless hide_button_icon
    concat((:span, button_text, class: 'gl-button-text')) unless button_text.nil?
  end
end


158
159
160
161
162
163
164
165
166
167
168
# File 'app/helpers/button_helper.rb', line 158

def dropdown_item_with_description(title, description, href: nil, data: nil, default: false)
  active_class = "is-active" if default
  button_content = (:strong, title, class: 'dropdown-menu-inner-title')
  button_content << (:span, description, class: 'dropdown-menu-inner-content') if description

   (href ? :a : :span),
    (href ? button_content : title),
    class: "#{title.downcase}-selector #{active_class}",
    href: href,
    data: data
end

#http_clone_button(container, append_link: true) ⇒ Object



131
132
133
134
135
136
137
# File 'app/helpers/button_helper.rb', line 131

def http_clone_button(container, append_link: true)
  protocol = gitlab_config.protocol.upcase
  dropdown_description = http_dropdown_description(protocol)
  append_url = container.http_url_to_repo if append_link

  dropdown_item_with_description(protocol, dropdown_description, href: append_url, data: { clone_type: 'http' })
end

#http_dropdown_description(protocol) ⇒ Object



139
140
141
142
143
144
145
# File 'app/helpers/button_helper.rb', line 139

def http_dropdown_description(protocol)
  if current_user.try(:require_password_creation_for_git?)
    _("Set a password on your account to pull or push via %{protocol}.") % { protocol: protocol }
  elsif current_user.try(:require_personal_access_token_creation_for_git_auth?)
    _("Create a personal access token on your account to pull or push via %{protocol}.") % { protocol: protocol }
  end
end

Creates a link that looks like a button.

It renders a Pajamas::ButtonComponent.

It has the same API as ‘link_to`, but with some additional options specific to button rendering.

Examples:

# Default button
link_button_to _('Foo'), some_path

# Default button using a block
link_button_to some_path do
  _('Foo')
end

# Confirm variant
link_button_to _('Foo'), some_path, variant: :confirm

# With icon
link_button_to _('Foo'), some_path, icon: 'pencil'

# Icon-only
# NOTE: The content must be `nil` in order to correctly render. Use aria-label
# to ensure the link is accessible.
link_button_to nil, some_path, icon: 'pencil', 'aria-label': _('Foo')

# Small button
link_button_to _('Foo'), some_path, size: :small

# Secondary category danger button
link_button_to _('Foo'), some_path, variant: :danger, category: :secondary

For accessibility, ensure that icon-only links have aria-label set.



204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
# File 'app/helpers/button_helper.rb', line 204

def link_button_to(name = nil, href = nil, options = nil, &block)
  if block
    options = href
    href = name
  end

  options ||= {}

  # Ignore args that don't make sense for links, like disabled, loading, etc.
  options_for_button = %i[
    category
    variant
    size
    block
    selected
    icon
    target
    method
  ]

  args = options.slice(*options_for_button)
  button_options = options.except(*options_for_button)

  render Pajamas::ButtonComponent.new(href: href, **args, button_options: button_options) do
    block.present? ? yield : name
  end
end

#ssh_clone_button(container, append_link: true) ⇒ Object



147
148
149
150
151
152
153
154
155
156
# File 'app/helpers/button_helper.rb', line 147

def ssh_clone_button(container, append_link: true)
  if Gitlab::CurrentSettings.user_show_add_ssh_key_message? &&
      current_user.try(:require_ssh_key?)
    dropdown_description = s_("MissingSSHKeyWarningLink|You won't be able to pull or push repositories via SSH until you add an SSH key to your profile")
  end

  append_url = container.ssh_url_to_repo if append_link

  dropdown_item_with_description('SSH', dropdown_description, href: append_url, data: { clone_type: 'ssh' })
end