Skip to content
Snippets Groups Projects
Commit 69bf7bfa authored by Robert Speicher's avatar Robert Speicher
Browse files

Merge branch 'dm-copy-diff-file-title-as-gfm' into 'master'

Copy diff file path as GFM

See merge request !9876
parents 00e00cac 12c18ee5
No related branches found
No related tags found
No related merge requests found
Showing
with 88 additions and 39 deletions
Loading
Loading
@@ -38,9 +38,35 @@ showTooltip = function(target, title) {
};
 
$(function() {
var clipboard;
clipboard = new Clipboard('[data-clipboard-target], [data-clipboard-text]');
const clipboard = new Clipboard('[data-clipboard-target], [data-clipboard-text]');
clipboard.on('success', genericSuccess);
return clipboard.on('error', genericError);
clipboard.on('error', genericError);
// This a workaround around ClipboardJS limitations to allow the context-specific copy/pasting of plain text or GFM.
// The Ruby `clipboard_button` helper sneaks a JSON hash with `text` and `gfm` keys into the `data-clipboard-text`
// attribute that ClipboardJS reads from.
// When ClipboardJS creates a new `textarea` (directly inside `body`, with a `readonly` attribute`), sets its value
// to the value of this data attribute, focusses on it, and finally programmatically issues the 'Copy' command,
// this code intercepts the copy command/event at the last minute to deconstruct this JSON hash and set the
// `text/plain` and `text/x-gfm` copy data types to the intended values.
$(document).on('copy', 'body > textarea[readonly]', function(e) {
const clipboardData = e.originalEvent.clipboardData;
if (!clipboardData) return;
const text = e.target.value;
let json;
try {
json = JSON.parse(text);
} catch (ex) {
return;
}
if (!json.text || !json.gfm) return;
e.preventDefault();
clipboardData.setData('text/plain', json.text);
clipboardData.setData('text/x-gfm', json.gfm);
});
});
Loading
Loading
@@ -210,13 +210,13 @@ module BlobHelper
end
 
def copy_file_path_button(file_path)
clipboard_button(clipboard_text: file_path, class: 'btn-clipboard btn-transparent prepend-left-5', title: 'Copy file path to clipboard')
clipboard_button(text: file_path, gfm: "`#{file_path}`", class: 'btn-clipboard btn-transparent prepend-left-5', title: 'Copy file path to clipboard')
end
 
def copy_blob_content_button(blob)
return if markup?(blob.name)
 
clipboard_button(clipboard_target: ".blob-content[data-blob-id='#{blob.id}']", class: "btn btn-sm", title: "Copy content to clipboard")
clipboard_button(target: ".blob-content[data-blob-id='#{blob.id}']", class: "btn btn-sm", title: "Copy content to clipboard")
end
 
def open_raw_file_button(path)
Loading
Loading
module ButtonHelper
# Output a "Copy to Clipboard" button
#
# data - Data attributes passed to `content_tag`
# 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(clipboard_text: "Foo")
# clipboard_button(text: "Foo")
# # => "<button class='...' data-clipboard-text='Foo'>...</button>"
#
# # Define the target element
# clipboard_button(clipboard_target: "div#foo")
# clipboard_button(target: "div#foo")
# # => "<button class='...' data-clipboard-target='div#foo'>...</button>"
#
# See http://clipboardjs.com/#usage
def clipboard_button(data = {})
css_class = data[:class] || 'btn-clipboard btn-transparent'
title = data[:title] || 'Copy to clipboard'
# 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
data = { toggle: 'tooltip', placement: 'bottom', container: 'body' }.merge(data)
content_tag :button,
icon('clipboard', 'aria-hidden': 'true'),
class: "btn #{css_class}",
Loading
Loading
Loading
Loading
@@ -19,7 +19,7 @@
Your New Personal Access Token
.form-group
= text_field_tag 'created-personal-access-token', flash[:personal_access_token], readonly: true, class: "form-control", 'aria-describedby' => "created-personal-access-token-help-block"
= clipboard_button(clipboard_text: flash[:personal_access_token], title: "Copy personal access token to clipboard", placement: "left")
= clipboard_button(text: flash[:personal_access_token], title: "Copy personal access token to clipboard", placement: "left")
%span#created-personal-access-token-help-block.help-block.text-danger Make sure you save it - you won't be able to access it again.
 
%hr
Loading
Loading
Loading
Loading
@@ -10,7 +10,7 @@
- if @project && event.project != @project
%span at
%strong= link_to_project event.project
= clipboard_button(clipboard_text: event.ref_name, class: 'btn-clipboard btn-transparent', title: 'Copy branch to clipboard')
= clipboard_button(text: event.ref_name, class: 'btn-clipboard btn-transparent', title: 'Copy branch to clipboard')
#{time_ago_with_tooltip(event.created_at)}
 
.pull-right
Loading
Loading
.page-content-header
.header-main-content
%strong Commit #{@commit.short_id}
= clipboard_button(clipboard_text: @commit.id, title: "Copy commit SHA to clipboard")
= clipboard_button(text: @commit.id, title: "Copy commit SHA to clipboard")
%span.hidden-xs authored
#{time_ago_with_tooltip(@commit.authored_date)}
%span by
Loading
Loading
Loading
Loading
@@ -37,6 +37,6 @@
.commit-actions.flex-row.hidden-xs
- if commit.status(ref)
= render_commit_status(commit, ref: ref)
= clipboard_button(clipboard_text: commit.id, title: "Copy commit SHA to clipboard")
= clipboard_button(text: commit.id, title: "Copy commit SHA to clipboard")
= link_to commit.short_id, namespace_project_commit_path(project.namespace, project, commit), class: "commit-short-id btn btn-transparent"
= link_to_browse_code(project, commit)
Loading
Loading
@@ -16,7 +16,7 @@
.email-modal-input-group.input-group
= text_field_tag :issue_email, email, class: "monospace js-select-on-focus form-control", readonly: true
.input-group-btn
= clipboard_button(clipboard_target: '#issue_email')
= clipboard_button(target: '#issue_email')
%p
The subject will be used as the title of the new issue, and the message will be the description.
 
Loading
Loading
Loading
Loading
@@ -8,7 +8,7 @@
%p
%strong Step 1.
Fetch and check out the branch for this merge request
= clipboard_button(clipboard_target: "pre#merge-info-1", title: "Copy commands to clipboard")
= clipboard_button(target: "pre#merge-info-1", title: "Copy commands to clipboard")
%pre.dark#merge-info-1
- if @merge_request.for_fork?
:preserve
Loading
Loading
@@ -25,7 +25,7 @@
%p
%strong Step 3.
Merge the branch and fix any conflicts that come up
= clipboard_button(clipboard_target: "pre#merge-info-3", title: "Copy commands to clipboard")
= clipboard_button(target: "pre#merge-info-3", title: "Copy commands to clipboard")
%pre.dark#merge-info-3
- if @merge_request.for_fork?
:preserve
Loading
Loading
@@ -38,7 +38,7 @@
%p
%strong Step 4.
Push the result of the merge to GitLab
= clipboard_button(clipboard_target: "pre#merge-info-4", title: "Copy commands to clipboard")
= clipboard_button(target: "pre#merge-info-4", title: "Copy commands to clipboard")
%pre.dark#merge-info-4
:preserve
git push origin #{h @merge_request.target_branch}
Loading
Loading
Loading
Loading
@@ -46,4 +46,4 @@
\...
%span.js-details-content.hide
= link_to @pipeline.sha, namespace_project_commit_path(@project.namespace, @project, @pipeline.sha), class: "monospace commit-hash-full"
= clipboard_button(clipboard_text: @pipeline.sha, title: "Copy commit SHA to clipboard")
= clipboard_button(text: @pipeline.sha, title: "Copy commit SHA to clipboard")
%tr.tag
%td
= escape_once(tag.name)
= clipboard_button(clipboard_text: "docker pull #{tag.path}")
= clipboard_button(text: "docker pull #{tag.path}")
%td
- if tag.revision
%span.has-tooltip{ title: "#{tag.revision}" }
Loading
Loading
Loading
Loading
@@ -22,14 +22,14 @@
.col-sm-10.col-xs-12.input-group
= text_field_tag :display_name, "GitLab / #{@project.name_with_namespace}", class: 'form-control input-sm', readonly: 'readonly'
.input-group-btn
= clipboard_button(clipboard_target: '#display_name')
= clipboard_button(target: '#display_name')
 
.form-group
= label_tag :description, 'Description', class: 'col-sm-2 col-xs-12 control-label'
.col-sm-10.col-xs-12.input-group
= text_field_tag :description, run_actions_text, class: 'form-control input-sm', readonly: 'readonly'
.input-group-btn
= clipboard_button(clipboard_target: '#description')
= clipboard_button(target: '#description')
 
.form-group
= label_tag nil, 'Command trigger word', class: 'col-sm-2 col-xs-12 control-label'
Loading
Loading
@@ -46,7 +46,7 @@
.col-sm-10.col-xs-12.input-group
= text_field_tag :request_url, service_trigger_url(subject), class: 'form-control input-sm', readonly: 'readonly'
.input-group-btn
= clipboard_button(clipboard_target: '#request_url')
= clipboard_button(target: '#request_url')
 
.form-group
= label_tag nil, 'Request method', class: 'col-sm-2 col-xs-12 control-label'
Loading
Loading
@@ -57,14 +57,14 @@
.col-sm-10.col-xs-12.input-group
= text_field_tag :response_username, 'GitLab', class: 'form-control input-sm', readonly: 'readonly'
.input-group-btn
= clipboard_button(clipboard_target: '#response_username')
= clipboard_button(target: '#response_username')
 
.form-group
= label_tag :response_icon, 'Response icon', class: 'col-sm-2 col-xs-12 control-label'
.col-sm-10.col-xs-12.input-group
= text_field_tag :response_icon, asset_url('gitlab_logo.png'), class: 'form-control input-sm', readonly: 'readonly'
.input-group-btn
= clipboard_button(clipboard_target: '#response_icon')
= clipboard_button(target: '#response_icon')
 
.form-group
= label_tag nil, 'Autocomplete', class: 'col-sm-2 col-xs-12 control-label'
Loading
Loading
@@ -75,14 +75,14 @@
.col-sm-10.col-xs-12.input-group
= text_field_tag :autocomplete_hint, '[help]', class: 'form-control input-sm', readonly: 'readonly'
.input-group-btn
= clipboard_button(clipboard_target: '#autocomplete_hint')
= clipboard_button(target: '#autocomplete_hint')
 
.form-group
= label_tag :autocomplete_description, 'Autocomplete description', class: 'col-sm-2 col-xs-12 control-label'
.col-sm-10.col-xs-12.input-group
= text_field_tag :autocomplete_description, run_actions_text, class: 'form-control input-sm', readonly: 'readonly'
.input-group-btn
= clipboard_button(clipboard_target: '#autocomplete_description')
= clipboard_button(target: '#autocomplete_description')
 
%hr
 
Loading
Loading
Loading
Loading
@@ -40,7 +40,7 @@
.col-sm-10.col-xs-12.input-group
= text_field_tag :url, service_trigger_url(subject), class: 'form-control input-sm', readonly: 'readonly'
.input-group-btn
= clipboard_button(clipboard_target: '#url')
= clipboard_button(target: '#url')
 
.form-group
= label_tag nil, 'Method', class: 'col-sm-2 col-xs-12 control-label'
Loading
Loading
@@ -51,7 +51,7 @@
.col-sm-10.col-xs-12.input-group
= text_field_tag :customize_name, 'GitLab', class: 'form-control input-sm', readonly: 'readonly'
.input-group-btn
= clipboard_button(clipboard_target: '#customize_name')
= clipboard_button(target: '#customize_name')
 
.form-group
= label_tag nil, 'Customize icon', class: 'col-sm-2 col-xs-12 control-label'
Loading
Loading
@@ -68,21 +68,21 @@
.col-sm-10.col-xs-12.input-group
= text_field_tag :autocomplete_description, run_actions_text, class: 'form-control input-sm', readonly: 'readonly'
.input-group-btn
= clipboard_button(clipboard_target: '#autocomplete_description')
= clipboard_button(target: '#autocomplete_description')
 
.form-group
= label_tag :autocomplete_usage_hint, 'Autocomplete usage hint', class: 'col-sm-2 col-xs-12 control-label'
.col-sm-10.col-xs-12.input-group
= text_field_tag :autocomplete_usage_hint, '[help]', class: 'form-control input-sm', readonly: 'readonly'
.input-group-btn
= clipboard_button(clipboard_target: '#autocomplete_usage_hint')
= clipboard_button(target: '#autocomplete_usage_hint')
 
.form-group
= label_tag :descriptive_label, 'Descriptive label', class: 'col-sm-2 col-xs-12 control-label'
.col-sm-10.col-xs-12.input-group
= text_field_tag :descriptive_label, 'Perform common operations on GitLab project', class: 'form-control input-sm', readonly: 'readonly'
.input-group-btn
= clipboard_button(clipboard_target: '#descriptive_label')
= clipboard_button(target: '#descriptive_label')
 
%hr
 
Loading
Loading
Loading
Loading
@@ -10,7 +10,7 @@
%i.fa.fa-angle-right
%small.light
= link_to @commit.short_id, namespace_project_commit_path(@project.namespace, @project, @commit), class: "monospace"
= clipboard_button(clipboard_text: @commit.id, title: "Copy commit SHA to clipboard")
= clipboard_button(text: @commit.id, title: "Copy commit SHA to clipboard")
= time_ago_with_tooltip(@commit.committed_date)
\-
= @commit.full_title
Loading
Loading
Loading
Loading
@@ -2,7 +2,7 @@
%td
- if can?(current_user, :admin_trigger, trigger)
%span= trigger.token
= clipboard_button(clipboard_text: trigger.token, title: "Copy trigger token to clipboard")
= clipboard_button(text: trigger.token, title: "Copy trigger token to clipboard")
- else
%span= trigger.short_token
 
Loading
Loading
Loading
Loading
@@ -19,7 +19,7 @@
 
= text_field_tag :project_clone, default_url_to_repo(project), class: "js-select-on-focus form-control", readonly: true
.input-group-btn
= clipboard_button(clipboard_target: '#project_clone', title: "Copy URL to clipboard")
= clipboard_button(target: '#project_clone', title: "Copy URL to clipboard")
 
:javascript
$('ul.clone-options-dropdown a').on('click',function(e){
Loading
Loading
Loading
Loading
@@ -33,7 +33,7 @@
- if impersonation
%td.token-token-container
= text_field_tag 'impersonation-token-token', token.token, readonly: true, class: "form-control"
= clipboard_button(clipboard_text: token.token)
= clipboard_button(text: token.token)
- path = impersonation ? revoke_admin_user_impersonation_token_path(token.user, token) : revoke_profile_personal_access_token_path(token)
%td= link_to "Revoke", path, method: :put, class: "btn btn-danger pull-right", data: { confirm: "Are you sure you want to revoke this #{type} Token? This action cannot be undone." }
- else
Loading
Loading
Loading
Loading
@@ -160,13 +160,13 @@
- project_ref = cross_project_reference(@project, issuable)
.block.project-reference
.sidebar-collapsed-icon.dont-change-state
= clipboard_button(clipboard_text: project_ref, title: "Copy reference to clipboard", placement: "left")
= clipboard_button(text: project_ref, title: "Copy reference to clipboard", placement: "left")
.cross-project-reference.hide-collapsed
%span
Reference:
%cite{ title: project_ref }
= project_ref
= clipboard_button(clipboard_text: project_ref, title: "Copy reference to clipboard", placement: "left")
= clipboard_button(text: project_ref, title: "Copy reference to clipboard", placement: "left")
 
:javascript
gl.IssuableResource = new gl.SubbableResource('#{issuable_json_path(issuable)}');
Loading
Loading
Loading
Loading
@@ -122,10 +122,10 @@
- if milestone_ref.present?
.block.reference
.sidebar-collapsed-icon.dont-change-state
= clipboard_button(clipboard_text: milestone_ref, title: "Copy reference to clipboard", placement: "left")
= clipboard_button(text: milestone_ref, title: "Copy reference to clipboard", placement: "left")
.cross-project-reference.hide-collapsed
%span
Reference:
%cite{ title: milestone_ref }
= milestone_ref
= clipboard_button(clipboard_text: milestone_ref, title: "Copy reference to clipboard", placement: "left")
= clipboard_button(text: milestone_ref, title: "Copy reference to clipboard", placement: "left")
---
title: After copying a diff file or blob path, pasting it into a comment field will format it as Markdown.
merge_request: 9876
author:
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment