Commit da1e920d authored by Nathan Friend's avatar Nathan Friend Committed by Paul Slaughter

Update (almost) all shortcuts to use `keysFor`

This commit refactors almost all keyboard shortcuts to use keysFor.

A small number of shortcuts have been left as-is because their
implementation is unconventional/unusual. These will be addressed
in follow-up commits.
parent ac9e66c4
...@@ -6,13 +6,29 @@ import Vue from 'vue'; ...@@ -6,13 +6,29 @@ import Vue from 'vue';
import { parseBoolean } from '~/lib/utils/common_utils'; import { parseBoolean } from '~/lib/utils/common_utils';
import findAndFollowLink from '~/lib/utils/navigation_utility'; import findAndFollowLink from '~/lib/utils/navigation_utility';
import { refreshCurrentPage, visitUrl } from '~/lib/utils/url_utility'; import { refreshCurrentPage, visitUrl } from '~/lib/utils/url_utility';
import {
import { keysFor, TOGGLE_PERFORMANCE_BAR, TOGGLE_CANARY } from './keybindings'; keysFor,
TOGGLE_KEYBOARD_SHORTCUTS_DIALOG,
START_SEARCH,
FOCUS_FILTER_BAR,
TOGGLE_PERFORMANCE_BAR,
TOGGLE_CANARY,
TOGGLE_MARKDOWN_PREVIEW,
GO_TO_YOUR_TODO_LIST,
GO_TO_ACTIVITY_FEED,
GO_TO_YOUR_ISSUES,
GO_TO_YOUR_MERGE_REQUESTS,
GO_TO_YOUR_PROJECTS,
GO_TO_YOUR_GROUPS,
GO_TO_MILESTONE_LIST,
GO_TO_YOUR_SNIPPETS,
GO_TO_PROJECT_FIND_FILE,
} from './keybindings';
import { disableShortcuts, shouldDisableShortcuts } from './shortcuts_toggle'; import { disableShortcuts, shouldDisableShortcuts } from './shortcuts_toggle';
const defaultStopCallback = Mousetrap.prototype.stopCallback; const defaultStopCallback = Mousetrap.prototype.stopCallback;
Mousetrap.prototype.stopCallback = function customStopCallback(e, element, combo) { Mousetrap.prototype.stopCallback = function customStopCallback(e, element, combo) {
if (['ctrl+shift+p', 'command+shift+p'].indexOf(combo) !== -1) { if (keysFor(TOGGLE_MARKDOWN_PREVIEW).indexOf(combo) !== -1) {
return false; return false;
} }
...@@ -58,28 +74,41 @@ export default class Shortcuts { ...@@ -58,28 +74,41 @@ export default class Shortcuts {
this.helpModalElement = null; this.helpModalElement = null;
this.helpModalVueInstance = null; this.helpModalVueInstance = null;
Mousetrap.bind('?', this.onToggleHelp); Mousetrap.bind(keysFor(TOGGLE_KEYBOARD_SHORTCUTS_DIALOG), this.onToggleHelp);
Mousetrap.bind('s', Shortcuts.focusSearch); Mousetrap.bind(keysFor(START_SEARCH), Shortcuts.focusSearch);
Mousetrap.bind('/', Shortcuts.focusSearch); Mousetrap.bind(keysFor(FOCUS_FILTER_BAR), this.focusFilter.bind(this));
Mousetrap.bind('f', this.focusFilter.bind(this));
Mousetrap.bind(keysFor(TOGGLE_PERFORMANCE_BAR), Shortcuts.onTogglePerfBar); Mousetrap.bind(keysFor(TOGGLE_PERFORMANCE_BAR), Shortcuts.onTogglePerfBar);
Mousetrap.bind(keysFor(TOGGLE_CANARY), Shortcuts.onToggleCanary); Mousetrap.bind(keysFor(TOGGLE_CANARY), Shortcuts.onToggleCanary);
const findFileURL = document.body.dataset.findFile; const findFileURL = document.body.dataset.findFile;
Mousetrap.bind('shift+t', () => findAndFollowLink('.shortcuts-todos')); Mousetrap.bind(keysFor(GO_TO_YOUR_TODO_LIST), () => findAndFollowLink('.shortcuts-todos'));
Mousetrap.bind('shift+a', () => findAndFollowLink('.dashboard-shortcuts-activity')); Mousetrap.bind(keysFor(GO_TO_ACTIVITY_FEED), () =>
Mousetrap.bind('shift+i', () => findAndFollowLink('.dashboard-shortcuts-issues')); findAndFollowLink('.dashboard-shortcuts-activity'),
Mousetrap.bind('shift+m', () => findAndFollowLink('.dashboard-shortcuts-merge_requests')); );
Mousetrap.bind('shift+p', () => findAndFollowLink('.dashboard-shortcuts-projects')); Mousetrap.bind(keysFor(GO_TO_YOUR_ISSUES), () =>
Mousetrap.bind('shift+g', () => findAndFollowLink('.dashboard-shortcuts-groups')); findAndFollowLink('.dashboard-shortcuts-issues'),
Mousetrap.bind('shift+l', () => findAndFollowLink('.dashboard-shortcuts-milestones')); );
Mousetrap.bind('shift+s', () => findAndFollowLink('.dashboard-shortcuts-snippets')); Mousetrap.bind(keysFor(GO_TO_YOUR_MERGE_REQUESTS), () =>
findAndFollowLink('.dashboard-shortcuts-merge_requests'),
Mousetrap.bind(['ctrl+shift+p', 'command+shift+p'], Shortcuts.toggleMarkdownPreview); );
Mousetrap.bind(keysFor(GO_TO_YOUR_PROJECTS), () =>
findAndFollowLink('.dashboard-shortcuts-projects'),
);
Mousetrap.bind(keysFor(GO_TO_YOUR_GROUPS), () =>
findAndFollowLink('.dashboard-shortcuts-groups'),
);
Mousetrap.bind(keysFor(GO_TO_MILESTONE_LIST), () =>
findAndFollowLink('.dashboard-shortcuts-milestones'),
);
Mousetrap.bind(keysFor(GO_TO_YOUR_SNIPPETS), () =>
findAndFollowLink('.dashboard-shortcuts-snippets'),
);
Mousetrap.bind(keysFor(TOGGLE_MARKDOWN_PREVIEW), Shortcuts.toggleMarkdownPreview);
if (typeof findFileURL !== 'undefined' && findFileURL !== null) { if (typeof findFileURL !== 'undefined' && findFileURL !== null) {
Mousetrap.bind('t', () => { Mousetrap.bind(keysFor(GO_TO_PROJECT_FIND_FILE), () => {
visitUrl(findFileURL); visitUrl(findFileURL);
}); });
} }
......
import Mousetrap from 'mousetrap'; import Mousetrap from 'mousetrap';
import { keysFor, PROJECT_FILES_GO_TO_PERMALINK } from '~/behaviors/shortcuts/keybindings';
import { import {
getLocationHash, getLocationHash,
updateHistory, updateHistory,
...@@ -28,7 +29,7 @@ export default class ShortcutsBlob extends Shortcuts { ...@@ -28,7 +29,7 @@ export default class ShortcutsBlob extends Shortcuts {
this.shortcircuitPermalinkButton(); this.shortcircuitPermalinkButton();
Mousetrap.bind('y', this.moveToFilePermalink.bind(this)); Mousetrap.bind(keysFor(PROJECT_FILES_GO_TO_PERMALINK), this.moveToFilePermalink.bind(this));
} }
moveToFilePermalink() { moveToFilePermalink() {
......
import Mousetrap from 'mousetrap'; import Mousetrap from 'mousetrap';
import {
keysFor,
PROJECT_FILES_MOVE_SELECTION_UP,
PROJECT_FILES_MOVE_SELECTION_DOWN,
PROJECT_FILES_OPEN_SELECTION,
PROJECT_FILES_GO_BACK,
} from '~/behaviors/shortcuts/keybindings';
import ShortcutsNavigation from './shortcuts_navigation'; import ShortcutsNavigation from './shortcuts_navigation';
export default class ShortcutsFindFile extends ShortcutsNavigation { export default class ShortcutsFindFile extends ShortcutsNavigation {
...@@ -10,7 +17,10 @@ export default class ShortcutsFindFile extends ShortcutsNavigation { ...@@ -10,7 +17,10 @@ export default class ShortcutsFindFile extends ShortcutsNavigation {
Mousetrap.prototype.stopCallback = function customStopCallback(e, element, combo) { Mousetrap.prototype.stopCallback = function customStopCallback(e, element, combo) {
if ( if (
element === projectFindFile.inputElement[0] && element === projectFindFile.inputElement[0] &&
(combo === 'up' || combo === 'down' || combo === 'esc' || combo === 'enter') (keysFor(PROJECT_FILES_MOVE_SELECTION_UP).includes(combo) ||
keysFor(PROJECT_FILES_MOVE_SELECTION_DOWN).includes(combo) ||
keysFor(PROJECT_FILES_GO_BACK).includes(combo) ||
keysFor(PROJECT_FILES_OPEN_SELECTION).includes(combo))
) { ) {
// when press up/down key in textbox, cursor prevent to move to home/end // when press up/down key in textbox, cursor prevent to move to home/end
e.preventDefault(); e.preventDefault();
...@@ -20,9 +30,9 @@ export default class ShortcutsFindFile extends ShortcutsNavigation { ...@@ -20,9 +30,9 @@ export default class ShortcutsFindFile extends ShortcutsNavigation {
return oldStopCallback.call(this, e, element, combo); return oldStopCallback.call(this, e, element, combo);
}; };
Mousetrap.bind('up', projectFindFile.selectRowUp); Mousetrap.bind(keysFor(PROJECT_FILES_MOVE_SELECTION_UP), projectFindFile.selectRowUp);
Mousetrap.bind('down', projectFindFile.selectRowDown); Mousetrap.bind(keysFor(PROJECT_FILES_MOVE_SELECTION_DOWN), projectFindFile.selectRowDown);
Mousetrap.bind('esc', projectFindFile.goToTree); Mousetrap.bind(keysFor(PROJECT_FILES_GO_BACK), projectFindFile.goToTree);
Mousetrap.bind('enter', projectFindFile.goToBlob); Mousetrap.bind(keysFor(PROJECT_FILES_OPEN_SELECTION), projectFindFile.goToBlob);
} }
} }
...@@ -5,18 +5,33 @@ import { getSelectedFragment } from '~/lib/utils/common_utils'; ...@@ -5,18 +5,33 @@ import { getSelectedFragment } from '~/lib/utils/common_utils';
import { isElementVisible } from '~/lib/utils/dom_utils'; import { isElementVisible } from '~/lib/utils/dom_utils';
import Sidebar from '../../right_sidebar'; import Sidebar from '../../right_sidebar';
import { CopyAsGFM } from '../markdown/copy_as_gfm'; import { CopyAsGFM } from '../markdown/copy_as_gfm';
import {
keysFor,
ISSUE_MR_CHANGE_ASSIGNEE,
ISSUE_MR_CHANGE_MILESTONE,
ISSUABLE_CHANGE_LABEL,
ISSUABLE_COMMENT_OR_REPLY,
ISSUABLE_EDIT_DESCRIPTION,
MR_COPY_SOURCE_BRANCH_NAME,
} from './keybindings';
import Shortcuts from './shortcuts'; import Shortcuts from './shortcuts';
export default class ShortcutsIssuable extends Shortcuts { export default class ShortcutsIssuable extends Shortcuts {
constructor() { constructor() {
super(); super();
Mousetrap.bind('a', () => ShortcutsIssuable.openSidebarDropdown('assignee')); Mousetrap.bind(keysFor(ISSUE_MR_CHANGE_ASSIGNEE), () =>
Mousetrap.bind('m', () => ShortcutsIssuable.openSidebarDropdown('milestone')); ShortcutsIssuable.openSidebarDropdown('assignee'),
Mousetrap.bind('l', () => ShortcutsIssuable.openSidebarDropdown('labels')); );
Mousetrap.bind('r', ShortcutsIssuable.replyWithSelectedText); Mousetrap.bind(keysFor(ISSUE_MR_CHANGE_MILESTONE), () =>
Mousetrap.bind('e', ShortcutsIssuable.editIssue); ShortcutsIssuable.openSidebarDropdown('milestone'),
Mousetrap.bind('b', ShortcutsIssuable.copyBranchName); );
Mousetrap.bind(keysFor(ISSUABLE_CHANGE_LABEL), () =>
ShortcutsIssuable.openSidebarDropdown('labels'),
);
Mousetrap.bind(keysFor(ISSUABLE_COMMENT_OR_REPLY), ShortcutsIssuable.replyWithSelectedText);
Mousetrap.bind(keysFor(ISSUABLE_EDIT_DESCRIPTION), ShortcutsIssuable.editIssue);
Mousetrap.bind(keysFor(MR_COPY_SOURCE_BRANCH_NAME), ShortcutsIssuable.copyBranchName);
} }
static replyWithSelectedText() { static replyWithSelectedText() {
......
import Mousetrap from 'mousetrap'; import Mousetrap from 'mousetrap';
import findAndFollowLink from '../../lib/utils/navigation_utility'; import findAndFollowLink from '../../lib/utils/navigation_utility';
import {
keysFor,
GO_TO_PROJECT_OVERVIEW,
GO_TO_PROJECT_ACTIVITY_FEED,
GO_TO_PROJECT_RELEASES,
GO_TO_PROJECT_FILES,
GO_TO_PROJECT_COMMITS,
GO_TO_PROJECT_JOBS,
GO_TO_PROJECT_REPO_GRAPH,
GO_TO_PROJECT_REPO_CHARTS,
GO_TO_PROJECT_ISSUES,
GO_TO_PROJECT_ISSUE_BOARDS,
GO_TO_PROJECT_MERGE_REQUESTS,
GO_TO_PROJECT_WIKI,
GO_TO_PROJECT_SNIPPETS,
GO_TO_PROJECT_KUBERNETES,
GO_TO_PROJECT_ENVIRONMENTS,
GO_TO_PROJECT_METRICS,
NEW_ISSUE,
} from './keybindings';
import Shortcuts from './shortcuts'; import Shortcuts from './shortcuts';
export default class ShortcutsNavigation extends Shortcuts { export default class ShortcutsNavigation extends Shortcuts {
constructor() { constructor() {
super(); super();
Mousetrap.bind('g p', () => findAndFollowLink('.shortcuts-project')); Mousetrap.bind(keysFor(GO_TO_PROJECT_OVERVIEW), () => findAndFollowLink('.shortcuts-project'));
Mousetrap.bind('g v', () => findAndFollowLink('.shortcuts-project-activity')); Mousetrap.bind(keysFor(GO_TO_PROJECT_ACTIVITY_FEED), () =>
Mousetrap.bind('g r', () => findAndFollowLink('.shortcuts-project-releases')); findAndFollowLink('.shortcuts-project-activity'),
Mousetrap.bind('g f', () => findAndFollowLink('.shortcuts-tree')); );
Mousetrap.bind('g c', () => findAndFollowLink('.shortcuts-commits')); Mousetrap.bind(keysFor(GO_TO_PROJECT_RELEASES), () =>
Mousetrap.bind('g j', () => findAndFollowLink('.shortcuts-builds')); findAndFollowLink('.shortcuts-project-releases'),
Mousetrap.bind('g n', () => findAndFollowLink('.shortcuts-network')); );
Mousetrap.bind('g d', () => findAndFollowLink('.shortcuts-repository-charts')); Mousetrap.bind(keysFor(GO_TO_PROJECT_FILES), () => findAndFollowLink('.shortcuts-tree'));
Mousetrap.bind('g i', () => findAndFollowLink('.shortcuts-issues')); Mousetrap.bind(keysFor(GO_TO_PROJECT_COMMITS), () => findAndFollowLink('.shortcuts-commits'));
Mousetrap.bind('g b', () => findAndFollowLink('.shortcuts-issue-boards')); Mousetrap.bind(keysFor(GO_TO_PROJECT_JOBS), () => findAndFollowLink('.shortcuts-builds'));
Mousetrap.bind('g m', () => findAndFollowLink('.shortcuts-merge_requests')); Mousetrap.bind(keysFor(GO_TO_PROJECT_REPO_GRAPH), () =>
Mousetrap.bind('g w', () => findAndFollowLink('.shortcuts-wiki')); findAndFollowLink('.shortcuts-network'),
Mousetrap.bind('g s', () => findAndFollowLink('.shortcuts-snippets')); );
Mousetrap.bind('g k', () => findAndFollowLink('.shortcuts-kubernetes')); Mousetrap.bind(keysFor(GO_TO_PROJECT_REPO_CHARTS), () =>
Mousetrap.bind('g e', () => findAndFollowLink('.shortcuts-environments')); findAndFollowLink('.shortcuts-repository-charts'),
Mousetrap.bind('g l', () => findAndFollowLink('.shortcuts-metrics')); );
Mousetrap.bind('i', () => findAndFollowLink('.shortcuts-new-issue')); Mousetrap.bind(keysFor(GO_TO_PROJECT_ISSUES), () => findAndFollowLink('.shortcuts-issues'));
Mousetrap.bind(keysFor(GO_TO_PROJECT_ISSUE_BOARDS), () =>
findAndFollowLink('.shortcuts-issue-boards'),
);
Mousetrap.bind(keysFor(GO_TO_PROJECT_MERGE_REQUESTS), () =>
findAndFollowLink('.shortcuts-merge_requests'),
);
Mousetrap.bind(keysFor(GO_TO_PROJECT_WIKI), () => findAndFollowLink('.shortcuts-wiki'));
Mousetrap.bind(keysFor(GO_TO_PROJECT_SNIPPETS), () => findAndFollowLink('.shortcuts-snippets'));
Mousetrap.bind(keysFor(GO_TO_PROJECT_KUBERNETES), () =>
findAndFollowLink('.shortcuts-kubernetes'),
);
Mousetrap.bind(keysFor(GO_TO_PROJECT_ENVIRONMENTS), () =>
findAndFollowLink('.shortcuts-environments'),
);
Mousetrap.bind(keysFor(GO_TO_PROJECT_METRICS), () => findAndFollowLink('.shortcuts-metrics'));
Mousetrap.bind(keysFor(NEW_ISSUE), () => findAndFollowLink('.shortcuts-new-issue'));
} }
} }
import Mousetrap from 'mousetrap'; import Mousetrap from 'mousetrap';
import {
keysFor,
REPO_GRAPH_SCROLL_BOTTOM,
REPO_GRAPH_SCROLL_DOWN,
REPO_GRAPH_SCROLL_LEFT,
REPO_GRAPH_SCROLL_RIGHT,
REPO_GRAPH_SCROLL_TOP,
REPO_GRAPH_SCROLL_UP,
} from './keybindings';
import ShortcutsNavigation from './shortcuts_navigation'; import ShortcutsNavigation from './shortcuts_navigation';
export default class ShortcutsNetwork extends ShortcutsNavigation { export default class ShortcutsNetwork extends ShortcutsNavigation {
constructor(graph) { constructor(graph) {
super(); super();
Mousetrap.bind(['left', 'h'], graph.scrollLeft); Mousetrap.bind(keysFor(REPO_GRAPH_SCROLL_LEFT), graph.scrollLeft);
Mousetrap.bind(['right', 'l'], graph.scrollRight); Mousetrap.bind(keysFor(REPO_GRAPH_SCROLL_RIGHT), graph.scrollRight);
Mousetrap.bind(['up', 'k'], graph.scrollUp); Mousetrap.bind(keysFor(REPO_GRAPH_SCROLL_UP), graph.scrollUp);
Mousetrap.bind(['down', 'j'], graph.scrollDown); Mousetrap.bind(keysFor(REPO_GRAPH_SCROLL_DOWN), graph.scrollDown);
Mousetrap.bind(['shift+up', 'shift+k'], graph.scrollTop); Mousetrap.bind(keysFor(REPO_GRAPH_SCROLL_TOP), graph.scrollTop);
Mousetrap.bind(['shift+down', 'shift+j'], graph.scrollBottom); Mousetrap.bind(keysFor(REPO_GRAPH_SCROLL_BOTTOM), graph.scrollBottom);
} }
} }
import Mousetrap from 'mousetrap'; import Mousetrap from 'mousetrap';
import findAndFollowLink from '../../lib/utils/navigation_utility'; import findAndFollowLink from '../../lib/utils/navigation_utility';
import { keysFor, EDIT_WIKI_PAGE } from './keybindings';
import ShortcutsNavigation from './shortcuts_navigation'; import ShortcutsNavigation from './shortcuts_navigation';
export default class ShortcutsWiki extends ShortcutsNavigation { export default class ShortcutsWiki extends ShortcutsNavigation {
constructor() { constructor() {
super(); super();
Mousetrap.bind('e', ShortcutsWiki.editWiki); Mousetrap.bind(keysFor(EDIT_WIKI_PAGE), ShortcutsWiki.editWiki);
} }
static editWiki() { static editWiki() {
......
...@@ -2,6 +2,11 @@ ...@@ -2,6 +2,11 @@
/* global Mousetrap */ /* global Mousetrap */
import 'mousetrap'; import 'mousetrap';
import { GlButton, GlButtonGroup, GlTooltipDirective } from '@gitlab/ui'; import { GlButton, GlButtonGroup, GlTooltipDirective } from '@gitlab/ui';
import {
keysFor,
ISSUE_PREVIOUS_DESIGN,
ISSUE_NEXT_DESIGN,
} from '~/behaviors/shortcuts/keybindings';
import { s__, sprintf } from '~/locale'; import { s__, sprintf } from '~/locale';
import allDesignsMixin from '../../mixins/all_designs'; import allDesignsMixin from '../../mixins/all_designs';
import { DESIGN_ROUTE_NAME } from '../../router/constants'; import { DESIGN_ROUTE_NAME } from '../../router/constants';
...@@ -46,11 +51,14 @@ export default { ...@@ -46,11 +51,14 @@ export default {
}, },
}, },
mounted() { mounted() {
Mousetrap.bind('left', () => this.navigateToDesign(this.previousDesign)); Mousetrap.bind(keysFor(ISSUE_PREVIOUS_DESIGN), () =>
Mousetrap.bind('right', () => this.navigateToDesign(this.nextDesign)); this.navigateToDesign(this.previousDesign),
);
Mousetrap.bind(keysFor(ISSUE_NEXT_DESIGN), () => this.navigateToDesign(this.nextDesign));
}, },
beforeDestroy() { beforeDestroy() {
Mousetrap.unbind(['left', 'right'], this.navigateToDesign); Mousetrap.unbind(keysFor(ISSUE_PREVIOUS_DESIGN));
Mousetrap.unbind(keysFor(ISSUE_NEXT_DESIGN));
}, },
methods: { methods: {
navigateToDesign(design) { navigateToDesign(design) {
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
import { GlLoadingIcon, GlAlert } from '@gitlab/ui'; import { GlLoadingIcon, GlAlert } from '@gitlab/ui';
import Mousetrap from 'mousetrap'; import Mousetrap from 'mousetrap';
import { ApolloMutation } from 'vue-apollo'; import { ApolloMutation } from 'vue-apollo';
import { keysFor, ISSUE_CLOSE_DESIGN } from '~/behaviors/shortcuts/keybindings';
import createFlash from '~/flash'; import createFlash from '~/flash';
import { fetchPolicies } from '~/lib/graphql'; import { fetchPolicies } from '~/lib/graphql';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin'; import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
...@@ -171,7 +172,7 @@ export default { ...@@ -171,7 +172,7 @@ export default {
}, },
}, },
mounted() { mounted() {
Mousetrap.bind('esc', this.closeDesign); Mousetrap.bind(keysFor(ISSUE_CLOSE_DESIGN), this.closeDesign);
this.trackPageViewEvent(); this.trackPageViewEvent();
// Set active discussion immediately. // Set active discussion immediately.
...@@ -180,7 +181,7 @@ export default { ...@@ -180,7 +181,7 @@ export default {
this.updateActiveDiscussionFromUrl(); this.updateActiveDiscussionFromUrl();
}, },
beforeDestroy() { beforeDestroy() {
Mousetrap.unbind('esc', this.closeDesign); Mousetrap.unbind(keysFor(ISSUE_CLOSE_DESIGN));
}, },
methods: { methods: {
addImageDiffNoteToStore(store, { data: { createImageDiffNote } }) { addImageDiffNoteToStore(store, { data: { createImageDiffNote } }) {
......
...@@ -3,6 +3,13 @@ import { GlLoadingIcon, GlPagination, GlSprintf } from '@gitlab/ui'; ...@@ -3,6 +3,13 @@ import { GlLoadingIcon, GlPagination, GlSprintf } from '@gitlab/ui';
import { GlBreakpointInstance as bp } from '@gitlab/ui/dist/utils'; import { GlBreakpointInstance as bp } from '@gitlab/ui/dist/utils';
import Mousetrap from 'mousetrap'; import Mousetrap from 'mousetrap';
import { mapState, mapGetters, mapActions } from 'vuex'; import { mapState, mapGetters, mapActions } from 'vuex';
import {
keysFor,
MR_PREVIOUS_FILE_IN_DIFF,
MR_NEXT_FILE_IN_DIFF,
MR_COMMITS_NEXT_COMMIT,
MR_COMMITS_PREVIOUS_COMMIT,
} from '~/behaviors/shortcuts/keybindings';
import { deprecatedCreateFlash as createFlash } from '~/flash'; import { deprecatedCreateFlash as createFlash } from '~/flash';
import { isSingleViewStyle } from '~/helpers/diffs_helper'; import { isSingleViewStyle } from '~/helpers/diffs_helper';
import { getParameterByName, parseBoolean } from '~/lib/utils/common_utils'; import { getParameterByName, parseBoolean } from '~/lib/utils/common_utils';
...@@ -406,30 +413,23 @@ export default { ...@@ -406,30 +413,23 @@ export default {
} }
}, },
setEventListeners() { setEventListeners() {
Mousetrap.bind(['[', 'k', ']', 'j'], (e, combo) => { Mousetrap.bind(keysFor(MR_PREVIOUS_FILE_IN_DIFF), () => this.jumpToFile(-1));
switch (combo) { Mousetrap.bind(keysFor(MR_NEXT_FILE_IN_DIFF), () => this.jumpToFile(+1));
case '[':
case 'k':
this.jumpToFile(-1);
break;
case ']':
case 'j':
this.jumpToFile(+1);
break;
default:
break;
}
});
if (this.commit) { if (this.commit) {
Mousetrap.bind('c', () => this.moveToNeighboringCommit({ direction: 'next' })); Mousetrap.bind(keysFor(MR_COMMITS_NEXT_COMMIT), () =>
Mousetrap.bind('x', () => this.moveToNeighboringCommit({ direction: 'previous' })); this.moveToNeighboringCommit({ direction: 'next' }),
);
Mousetrap.bind(keysFor(MR_COMMITS_PREVIOUS_COMMIT), () =>
this.moveToNeighboringCommit({ direction: 'previous' }),
);
} }
}, },
removeEventListeners() { removeEventListeners() {
Mousetrap.unbind(['[', 'k', ']', 'j']); Mousetrap.unbind(keysFor(MR_PREVIOUS_FILE_IN_DIFF));
Mousetrap.unbind('c'); Mousetrap.unbind(keysFor(MR_NEXT_FILE_IN_DIFF));
Mousetrap.unbind('x'); Mousetrap.unbind(keysFor(MR_COMMITS_NEXT_COMMIT));
Mousetrap.unbind(keysFor(MR_COMMITS_PREVIOUS_COMMIT));
}, },
jumpToFile(step) { jumpToFile(step) {
const targetIndex = this.currentDiffIndex + step; const targetIndex = this.currentDiffIndex + step;
......
<script> <script>
/* global Mousetrap */ /* global Mousetrap */
import 'mousetrap'; import 'mousetrap';
import {
keysFor,
MR_NEXT_UNRESOLVED_DISCUSSION,
MR_PREVIOUS_UNRESOLVED_DISCUSSION,
} from '~/behaviors/shortcuts/keybindings';
import eventHub from '~/notes/event_hub'; import eventHub from '~/notes/event_hub';
import discussionNavigation from '~/notes/mixins/discussion_navigation'; import discussionNavigation from '~/notes/mixins/discussion_navigation';
...@@ -10,12 +15,12 @@ export default { ...@@ -10,12 +15,12 @@ export default {
eventHub.$on('jumpToFirstUnresolvedDiscussion', this.jumpToFirstUnresolvedDiscussion); eventHub.$on('jumpToFirstUnresolvedDiscussion', this.jumpToFirstUnresolvedDiscussion);
}, },
mounted() { mounted() {
Mousetrap.bind('n', this.jumpToNextDiscussion); Mousetrap.bind(keysFor(MR_NEXT_UNRESOLVED_DISCUSSION), this.jumpToNextDiscussion);
Mousetrap.bind('p', this.jumpToPreviousDiscussion); Mousetrap.bind(keysFor(MR_PREVIOUS_UNRESOLVED_DISCUSSION), this.jumpToPreviousDiscussion);
}, },
beforeDestroy() { beforeDestroy() {
Mousetrap.unbind('n'); Mousetrap.unbind(keysFor(MR_NEXT_UNRESOLVED_DISCUSSION));
Mousetrap.unbind('p'); Mousetrap.unbind(keysFor(MR_PREVIOUS_UNRESOLVED_DISCUSSION));
eventHub.$off('jumpToFirstUnresolvedDiscussion', this.jumpToFirstUnresolvedDiscussion); eventHub.$off('jumpToFirstUnresolvedDiscussion', this.jumpToFirstUnresolvedDiscussion);
}, },
......
...@@ -3,6 +3,7 @@ import { GlIcon } from '@gitlab/ui'; ...@@ -3,6 +3,7 @@ import { GlIcon } from '@gitlab/ui';
import fuzzaldrinPlus from 'fuzzaldrin-plus'; import fuzzaldrinPlus from 'fuzzaldrin-plus';
import Mousetrap from 'mousetrap'; import Mousetrap from 'mousetrap';
import VirtualList from 'vue-virtual-scroll-list'; import VirtualList from 'vue-virtual-scroll-list';
import { keysFor, MR_GO_TO_FILE } from '~/behaviors/shortcuts/keybindings';
import { UP_KEY_CODE, DOWN_KEY_CODE, ENTER_KEY_CODE, ESC_KEY_CODE } from '~/lib/utils/keycodes'; import { UP_KEY_CODE, DOWN_KEY_CODE, ENTER_KEY_CODE, ESC_KEY_CODE } from '~/lib/utils/keycodes';
import Item from './item.vue'; import Item from './item.vue';
...@@ -128,7 +129,7 @@ export default { ...@@ -128,7 +129,7 @@ export default {
this.focusedIndex = 0; this.focusedIndex = 0;
} }
Mousetrap.bind(['t', 'mod+p'], (e) => { Mousetrap.bind(keysFor(MR_GO_TO_FILE), (e) => {
if (e.preventDefault) { if (e.preventDefault) {
e.preventDefault(); e.preventDefault();
} }
......
<script> <script>
import { GlPopover, GlButton, GlTooltipDirective, GlIcon } from '@gitlab/ui'; import { GlPopover, GlButton, GlTooltipDirective, GlIcon } from '@gitlab/ui';
import $ from 'jquery'; import $ from 'jquery';
import { keysFor, BOLD_TEXT, ITALIC_TEXT, LINK_TEXT } from '~/behaviors/shortcuts/keybindings';
import { getSelectedFragment } from '~/lib/utils/common_utils'; import { getSelectedFragment } from '~/lib/utils/common_utils';
import { s__ } from '~/locale'; import { s__ } from '~/locale';
import { CopyAsGFM } from '../../../behaviors/markdown/copy_as_gfm'; import { CopyAsGFM } from '../../../behaviors/markdown/copy_as_gfm';
...@@ -116,6 +117,11 @@ export default { ...@@ -116,6 +117,11 @@ export default {
.catch(() => {}); .catch(() => {});
}, },
}, },
shortcuts: {
bold: keysFor(BOLD_TEXT),
italic: keysFor(ITALIC_TEXT),
link: keysFor(LINK_TEXT),
},
}; };
</script> </script>
...@@ -143,7 +149,7 @@ export default { ...@@ -143,7 +149,7 @@ export default {
:button-title=" :button-title="
sprintf(s__('MarkdownEditor|Add bold text (%{modifierKey}B)'), { modifierKey }) sprintf(s__('MarkdownEditor|Add bold text (%{modifierKey}B)'), { modifierKey })
" "
shortcuts="mod+b" :shortcuts="$options.shortcuts.bold"
icon="bold" icon="bold"
/> />
<toolbar-button <toolbar-button
...@@ -151,7 +157,7 @@ export default { ...@@ -151,7 +157,7 @@ export default {
:button-title=" :button-title="
sprintf(s__('MarkdownEditor|Add italic text (%{modifierKey}I)'), { modifierKey }) sprintf(s__('MarkdownEditor|Add italic text (%{modifierKey}I)'), { modifierKey })
" "
shortcuts="mod+i" :shortcuts="$options.shortcuts.italic"
icon="italic" icon="italic"
/> />
<toolbar-button <toolbar-button
...@@ -208,7 +214,7 @@ export default { ...@@ -208,7 +214,7 @@ export default {
:button-title=" :button-title="
sprintf(s__('MarkdownEditor|Add a link (%{modifierKey}K)'), { modifierKey }) sprintf(s__('MarkdownEditor|Add a link (%{modifierKey}K)'), { modifierKey })
" "
shortcuts="mod+k" :shortcuts="$options.shortcuts.link"
icon="link" icon="link"
/> />
</div> </div>
......
import $ from 'jquery'; import $ from 'jquery';
import Cookies from 'js-cookie'; import Cookies from 'js-cookie';
import Mousetrap from 'mousetrap'; import Mousetrap from 'mousetrap';
import {
keysFor,
ISSUABLE_CHANGE_LABEL,
ISSUABLE_COMMENT_OR_REPLY,
ISSUABLE_EDIT_DESCRIPTION,
} from '~/behaviors/shortcuts/keybindings';
import ShortcutsIssuable from '~/behaviors/shortcuts/shortcuts_issuable'; import ShortcutsIssuable from '~/behaviors/shortcuts/shortcuts_issuable';
import { parseBoolean } from '~/lib/utils/common_utils'; import { parseBoolean } from '~/lib/utils/common_utils';
...@@ -10,11 +16,11 @@ export default class ShortcutsEpic extends ShortcutsIssuable { ...@@ -10,11 +16,11 @@ export default class ShortcutsEpic extends ShortcutsIssuable {
const $issuableSidebar = $('.js-issuable-update'); const $issuableSidebar = $('.js-issuable-update');
Mousetrap.bind('l', () => Mousetrap.bind(keysFor(ISSUABLE_CHANGE_LABEL), () =>
ShortcutsEpic.openSidebarDropdown($issuableSidebar.find('.js-labels-block')), ShortcutsEpic.openSidebarDropdown($issuableSidebar.find('.js-labels-block')),
); );
Mousetrap.bind('r', ShortcutsIssuable.replyWithSelectedText); Mousetrap.bind(keysFor(ISSUABLE_COMMENT_OR_REPLY), ShortcutsIssuable.replyWithSelectedText);
Mousetrap.bind('e', ShortcutsIssuable.editIssue); Mousetrap.bind(keysFor(ISSUABLE_EDIT_DESCRIPTION), ShortcutsIssuable.editIssue);
} }
static openSidebarDropdown($block) { static openSidebarDropdown($block) {
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
import { GlTooltipDirective as GlTooltip, GlButton, GlIcon, GlLoadingIcon } from '@gitlab/ui'; import { GlTooltipDirective as GlTooltip, GlButton, GlIcon, GlLoadingIcon } from '@gitlab/ui';
import Mousetrap from 'mousetrap'; import Mousetrap from 'mousetrap';
import { keysFor, ISSUABLE_CHANGE_LABEL } from '~/behaviors/shortcuts/keybindings';
import { s__, __ } from '~/locale'; import { s__, __ } from '~/locale';
import ProjectSelect from '~/vue_shared/components/sidebar/issuable_move_dropdown.vue'; import ProjectSelect from '~/vue_shared/components/sidebar/issuable_move_dropdown.vue';
import LabelsSelect from '~/vue_shared/components/sidebar/labels_select_vue/labels_select_root.vue'; import LabelsSelect from '~/vue_shared/components/sidebar/labels_select_vue/labels_select_root.vue';
...@@ -76,10 +77,10 @@ export default { ...@@ -76,10 +77,10 @@ export default {
}, },
mounted() { mounted() {
this.sidebarEl = document.querySelector('aside.right-sidebar'); this.sidebarEl = document.querySelector('aside.right-sidebar');
Mousetrap.bind('l', this.handleLabelsCollapsedButtonClick); Mousetrap.bind(keysFor(ISSUABLE_CHANGE_LABEL), this.handleLabelsCollapsedButtonClick);
}, },
beforeDestroy() { beforeDestroy() {
Mousetrap.unbind('l'); Mousetrap.unbind(keysFor(ISSUABLE_CHANGE_LABEL));
}, },
methods: { methods: {
handleTodoButtonClick() { handleTodoButtonClick() {
......
...@@ -5,6 +5,7 @@ import Mousetrap from 'mousetrap'; ...@@ -5,6 +5,7 @@ import Mousetrap from 'mousetrap';
import TestCaseSidebar from 'ee/test_case_show/components/test_case_sidebar.vue'; import TestCaseSidebar from 'ee/test_case_show/components/test_case_sidebar.vue';
import { mockCurrentUserTodo, mockLabels } from 'jest/issuable_list/mock_data'; import { mockCurrentUserTodo, mockLabels } from 'jest/issuable_list/mock_data';
import { keysFor, ISSUABLE_CHANGE_LABEL } from '~/behaviors/shortcuts/keybindings';
import ProjectSelect from '~/vue_shared/components/sidebar/issuable_move_dropdown.vue'; import ProjectSelect from '~/vue_shared/components/sidebar/issuable_move_dropdown.vue';
import LabelsSelect from '~/vue_shared/components/sidebar/labels_select_vue/labels_select_root.vue'; import LabelsSelect from '~/vue_shared/components/sidebar/labels_select_vue/labels_select_root.vue';
...@@ -99,7 +100,10 @@ describe('TestCaseSidebar', () => { ...@@ -99,7 +100,10 @@ describe('TestCaseSidebar', () => {
describe('mounted', () => { describe('mounted', () => {
it('binds key-press listener for `l` on Mousetrap', () => { it('binds key-press listener for `l` on Mousetrap', () => {
expect(mousetrapSpy).toHaveBeenCalledWith('l', wrapper.vm.handleLabelsCollapsedButtonClick); expect(mousetrapSpy).toHaveBeenCalledWith(
keysFor(ISSUABLE_CHANGE_LABEL),
wrapper.vm.handleLabelsCollapsedButtonClick,
);
}); });
}); });
......
...@@ -4995,6 +4995,9 @@ msgstr "" ...@@ -4995,6 +4995,9 @@ msgstr ""
msgid "Board|Load more issues" msgid "Board|Load more issues"
msgstr "" msgstr ""
msgid "Bold text"
msgstr ""
msgid "Both project and dashboard_path are required" msgid "Both project and dashboard_path are required"
msgstr "" msgstr ""
...@@ -6347,6 +6350,9 @@ msgstr "" ...@@ -6347,6 +6350,9 @@ msgstr ""
msgid "Close %{tabname}" msgid "Close %{tabname}"
msgstr "" msgstr ""
msgid "Close design"
msgstr ""
msgid "Close epic" msgid "Close epic"
msgstr "" msgstr ""
...@@ -12508,6 +12514,9 @@ msgstr "" ...@@ -12508,6 +12514,9 @@ msgstr ""
msgid "Expand milestones" msgid "Expand milestones"
msgstr "" msgstr ""
msgid "Expand panel"
msgstr ""
msgid "Expand sidebar" msgid "Expand sidebar"
msgstr "" msgstr ""
...@@ -13413,6 +13422,9 @@ msgstr "" ...@@ -13413,6 +13422,9 @@ msgstr ""
msgid "FlowdockService|Flowdock is a collaboration web app for technical teams." msgid "FlowdockService|Flowdock is a collaboration web app for technical teams."
msgstr "" msgstr ""
msgid "Focus filter bar"
msgstr ""
msgid "FogBugz Email" msgid "FogBugz Email"
msgstr "" msgstr ""
...@@ -17229,6 +17241,9 @@ msgstr "" ...@@ -17229,6 +17241,9 @@ msgstr ""
msgid "It's you" msgid "It's you"
msgstr "" msgstr ""
msgid "Italic text"
msgstr ""
msgid "Iteration" msgid "Iteration"
msgstr "" msgstr ""
...@@ -17628,21 +17643,6 @@ msgstr "" ...@@ -17628,21 +17643,6 @@ msgstr ""
msgid "KeyboardKey|Ctrl+" msgid "KeyboardKey|Ctrl+"
msgstr "" msgstr ""
msgid "KeyboardShortcuts|Commit (when editing commit message)"
msgstr ""
msgid "KeyboardShortcuts|Global Shortcuts"
msgstr ""
msgid "KeyboardShortcuts|Toggle GitLab Next"
msgstr ""
msgid "KeyboardShortcuts|Toggle the Performance Bar"
msgstr ""
msgid "KeyboardShortcuts|Web IDE"
msgstr ""
msgid "Keys" msgid "Keys"
msgstr "" msgstr ""
...@@ -18337,6 +18337,9 @@ msgstr "" ...@@ -18337,6 +18337,9 @@ msgstr ""
msgid "Link copied" msgid "Link copied"
msgstr "" msgstr ""
msgid "Link text"
msgstr ""
msgid "Link title" msgid "Link title"
msgstr "" msgstr ""
...@@ -19889,6 +19892,9 @@ msgstr "" ...@@ -19889,6 +19892,9 @@ msgstr ""
msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user." msgid "Mirroring will only be available if the feature is included in the plan of the selected group or user."
msgstr "" msgstr ""
msgid "Miscellaneous"
msgstr ""
msgid "Missing" msgid "Missing"
msgstr "" msgstr ""
...@@ -20627,6 +20633,9 @@ msgstr "" ...@@ -20627,6 +20633,9 @@ msgstr ""
msgid "Next commit" msgid "Next commit"
msgstr "" msgstr ""
msgid "Next design"
msgstr ""
msgid "Next file in diff" msgid "Next file in diff"
msgstr "" msgstr ""
...@@ -23128,6 +23137,9 @@ msgstr "" ...@@ -23128,6 +23137,9 @@ msgstr ""
msgid "Previous commit" msgid "Previous commit"
msgstr "" msgstr ""
msgid "Previous design"
msgstr ""
msgid "Previous file in diff" msgid "Previous file in diff"
msgstr "" msgstr ""
...@@ -31768,6 +31780,9 @@ msgstr "" ...@@ -31768,6 +31780,9 @@ msgstr ""
msgid "Toggle focus mode" msgid "Toggle focus mode"
msgstr "" msgstr ""
msgid "Toggle keyboard shortcuts help dialog"
msgstr ""
msgid "Toggle navigation" msgid "Toggle navigation"
msgstr "" msgstr ""
...@@ -33415,6 +33430,9 @@ msgstr "" ...@@ -33415,6 +33430,9 @@ msgstr ""
msgid "View log" msgid "View log"
msgstr "" msgstr ""
msgid "View logs"
msgstr ""
msgid "View merge request" msgid "View merge request"
msgstr "" msgstr ""
......
...@@ -2,6 +2,11 @@ ...@@ -2,6 +2,11 @@
import 'mousetrap'; import 'mousetrap';
import { shallowMount, createLocalVue } from '@vue/test-utils'; import { shallowMount, createLocalVue } from '@vue/test-utils';
import Vue from 'vue'; import Vue from 'vue';
import {
keysFor,
MR_NEXT_UNRESOLVED_DISCUSSION,
MR_PREVIOUS_UNRESOLVED_DISCUSSION,
} from '~/behaviors/shortcuts/keybindings';
import DiscussionNavigator from '~/notes/components/discussion_navigator.vue'; import DiscussionNavigator from '~/notes/components/discussion_navigator.vue';
import eventHub from '~/notes/event_hub'; import eventHub from '~/notes/event_hub';
...@@ -60,13 +65,13 @@ describe('notes/components/discussion_navigator', () => { ...@@ -60,13 +65,13 @@ describe('notes/components/discussion_navigator', () => {
}); });
it('calls jumpToNextDiscussion when pressing `n`', () => { it('calls jumpToNextDiscussion when pressing `n`', () => {
Mousetrap.trigger('n'); Mousetrap.trigger(keysFor(MR_NEXT_UNRESOLVED_DISCUSSION));
expect(jumpToNextDiscussion).toHaveBeenCalled(); expect(jumpToNextDiscussion).toHaveBeenCalled();
}); });
it('calls jumpToPreviousDiscussion when pressing `p`', () => { it('calls jumpToPreviousDiscussion when pressing `p`', () => {
Mousetrap.trigger('p'); Mousetrap.trigger(keysFor(MR_PREVIOUS_UNRESOLVED_DISCUSSION));
expect(jumpToPreviousDiscussion).toHaveBeenCalled(); expect(jumpToPreviousDiscussion).toHaveBeenCalled();
}); });
...@@ -87,8 +92,8 @@ describe('notes/components/discussion_navigator', () => { ...@@ -87,8 +92,8 @@ describe('notes/components/discussion_navigator', () => {
}); });
it('unbinds keys', () => { it('unbinds keys', () => {
expect(Mousetrap.unbind).toHaveBeenCalledWith('n'); expect(Mousetrap.unbind).toHaveBeenCalledWith(keysFor(MR_NEXT_UNRESOLVED_DISCUSSION));
expect(Mousetrap.unbind).toHaveBeenCalledWith('p'); expect(Mousetrap.unbind).toHaveBeenCalledWith(keysFor(MR_PREVIOUS_UNRESOLVED_DISCUSSION));
}); });
it('unbinds event hub listeners', () => { it('unbinds event hub listeners', () => {
......
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