Commit 55010526 authored by Mike Greiling's avatar Mike Greiling

Merge branch 'nfriend-add-copy-branch-name-shortcut' into 'master'

Add shortcut to copy source branch name on merge request page

See merge request gitlab-org/gitlab!36338
parents d642c9c1 abde9985
<script> <script>
import Mousetrap from 'mousetrap';
import { escape } from 'lodash'; import { escape } from 'lodash';
import { n__, s__, sprintf } from '~/locale'; import { n__, s__, sprintf } from '~/locale';
import { mergeUrlParams, webIDEUrl } from '~/lib/utils/url_utility'; import { mergeUrlParams, webIDEUrl } from '~/lib/utils/url_utility';
...@@ -74,6 +75,17 @@ export default { ...@@ -74,6 +75,17 @@ export default {
: ''; : '';
}, },
}, },
mounted() {
Mousetrap.bind('b', this.copyBranchName);
},
beforeDestroy() {
Mousetrap.unbind('b');
},
methods: {
copyBranchName() {
this.$refs.copyBranchNameButton.$el.click();
},
},
}; };
</script> </script>
<template> <template>
...@@ -89,6 +101,7 @@ export default { ...@@ -89,6 +101,7 @@ export default {
class="label-branch label-truncate js-source-branch" class="label-branch label-truncate js-source-branch"
v-html="mr.sourceBranchLink" v-html="mr.sourceBranchLink"
/><clipboard-button /><clipboard-button
ref="copyBranchNameButton"
:text="branchNameClipboardData" :text="branchNameClipboardData"
:title="__('Copy branch name')" :title="__('Copy branch name')"
css-class="btn-default btn-transparent btn-clipboard" css-class="btn-default btn-transparent btn-clipboard"
......
...@@ -309,6 +309,10 @@ ...@@ -309,6 +309,10 @@
%td.shortcut %td.shortcut
%kbd p %kbd p
%td= _('Previous unresolved discussion') %td= _('Previous unresolved discussion')
%tr
%td.shortcut
%kbd b
%td= _('Copy source branch name')
%tbody %tbody
%tr %tr
%th %th
......
---
title: Add keyboard shortcut ('b') to copy MR source branch name on MR page
merge_request: 36338
author:
type: added
...@@ -78,10 +78,11 @@ These shortcuts are available when viewing issues and merge requests. ...@@ -78,10 +78,11 @@ These shortcuts are available when viewing issues and merge requests.
| <kbd>m</kbd> | Change milestone. | | <kbd>m</kbd> | Change milestone. |
| <kbd>l</kbd> | Change label. | | <kbd>l</kbd> | Change label. |
| <kbd>r</kbd> | Start writing a comment. If any text is selected, it will be quoted in the comment. Can't be used to reply within a thread. | | <kbd>r</kbd> | Start writing a comment. If any text is selected, it will be quoted in the comment. Can't be used to reply within a thread. |
| <kbd>n</kbd> | Move to next unresolved discussion (Merge requests only). | | <kbd>n</kbd> | Move to next unresolved discussion (merge requests only). |
| <kbd>p</kbd> | Move to previous unresolved discussion (Merge requests only). | | <kbd>p</kbd> | Move to previous unresolved discussion (merge requests only). |
| <kbd>]</kbd> or <kbd>j</kbd> | Move to next file (Merge requests only). | | <kbd>]</kbd> or <kbd>j</kbd> | Move to next file (merge requests only). |
| <kbd>[</kbd> or <kbd>k</kbd> | Move to previous file (Merge requests only). | | <kbd>[</kbd> or <kbd>k</kbd> | Move to previous file (merge requests only). |
| <kbd>b</kbd> | Copy source branch name (merge requests only). |
### Project Files ### Project Files
......
...@@ -6593,6 +6593,9 @@ msgstr "" ...@@ -6593,6 +6593,9 @@ msgstr ""
msgid "Copy secret" msgid "Copy secret"
msgstr "" msgstr ""
msgid "Copy source branch name"
msgstr ""
msgid "Copy token" msgid "Copy token"
msgstr "" msgstr ""
......
import Vue from 'vue'; import Vue from 'vue';
import Mousetrap from 'mousetrap';
import mountComponent from 'helpers/vue_mount_component_helper'; import mountComponent from 'helpers/vue_mount_component_helper';
import headerComponent from '~/vue_merge_request_widget/components/mr_widget_header.vue'; import headerComponent from '~/vue_merge_request_widget/components/mr_widget_header.vue';
jest.mock('mousetrap', () => ({
bind: jest.fn(),
unbind: jest.fn(),
}));
describe('MRWidgetHeader', () => { describe('MRWidgetHeader', () => {
let vm; let vm;
let Component; let Component;
...@@ -126,6 +132,35 @@ describe('MRWidgetHeader', () => { ...@@ -126,6 +132,35 @@ describe('MRWidgetHeader', () => {
it('renders target branch', () => { it('renders target branch', () => {
expect(vm.$el.querySelector('.js-target-branch').textContent.trim()).toEqual('master'); expect(vm.$el.querySelector('.js-target-branch').textContent.trim()).toEqual('master');
}); });
describe('keyboard shortcuts', () => {
it('binds a keyboard shortcut handler to the "b" key', () => {
expect(Mousetrap.bind).toHaveBeenCalledWith('b', expect.any(Function));
});
it('triggers a click on the "copy to clipboard" button when the handler is executed', () => {
const testClickHandler = jest.fn();
vm.$refs.copyBranchNameButton.$el.addEventListener('click', testClickHandler);
// Get a reference to the function that was assigned to the "b" shortcut key.
const shortcutHandler = Mousetrap.bind.mock.calls[0][1];
expect(testClickHandler).not.toHaveBeenCalled();
// Simulate Mousetrap calling the function.
shortcutHandler();
expect(testClickHandler).toHaveBeenCalledTimes(1);
});
it('unbinds the keyboard shortcut when the component is destroyed', () => {
expect(Mousetrap.unbind).not.toHaveBeenCalled();
vm.$destroy();
expect(Mousetrap.unbind).toHaveBeenCalledWith('b');
});
});
}); });
describe('with an open merge request', () => { describe('with an open merge request', () => {
......
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