Commit f264588c authored by Paul Slaughter's avatar Paul Slaughter

Merge branch 'nfriend-update-all-shortcuts-to-use-keybindings-js' into 'master'

Update keyboard shortcuts to use keybindings.js

See merge request gitlab-org/gitlab!45308
parents f7678655 da1e920d
import { memoize } from 'lodash'; import { memoize } from 'lodash';
import AccessorUtilities from '~/lib/utils/accessor'; import AccessorUtilities from '~/lib/utils/accessor';
import { s__ } from '~/locale'; import { __ } from '~/locale';
const isCustomizable = (command) => const isCustomizable = (command) =>
'customizable' in command ? Boolean(command.customizable) : true; 'customizable' in command ? Boolean(command.customizable) : true;
...@@ -33,42 +33,608 @@ export const getCustomizations = memoize(() => { ...@@ -33,42 +33,608 @@ export const getCustomizations = memoize(() => {
}); });
// All available commands // All available commands
export const TOGGLE_KEYBOARD_SHORTCUTS_DIALOG = {
id: 'globalShortcuts.toggleKeyboardShortcutsDialog',
description: __('Toggle keyboard shortcuts help dialog'),
defaultKeys: ['?'],
};
export const GO_TO_YOUR_PROJECTS = {
id: 'globalShortcuts.goToYourProjects',
description: __('Go to your projects'),
defaultKeys: ['shift+p'],
};
export const GO_TO_YOUR_GROUPS = {
id: 'globalShortcuts.goToYourGroups',
description: __('Go to your groups'),
defaultKeys: ['shift+g'],
};
export const GO_TO_ACTIVITY_FEED = {
id: 'globalShortcuts.goToActivityFeed',
description: __('Go to the activity feed'),
defaultKeys: ['shift+a'],
};
export const GO_TO_MILESTONE_LIST = {
id: 'globalShortcuts.goToMilestoneList',
description: __('Go to the milestone list'),
defaultKeys: ['shift+l'],
};
export const GO_TO_YOUR_SNIPPETS = {
id: 'globalShortcuts.goToYourSnippets',
description: __('Go to your snippets'),
defaultKeys: ['shift+s'],
};
export const START_SEARCH = {
id: 'globalShortcuts.startSearch',
description: __('Start search'),
defaultKeys: ['s', '/'],
};
export const FOCUS_FILTER_BAR = {
id: 'globalShortcuts.focusFilterBar',
description: __('Focus filter bar'),
defaultKeys: ['f'],
};
export const GO_TO_YOUR_ISSUES = {
id: 'globalShortcuts.goToYourIssues',
description: __('Go to your issues'),
defaultKeys: ['shift+i'],
};
export const GO_TO_YOUR_MERGE_REQUESTS = {
id: 'globalShortcuts.goToYourMergeRequests',
description: __('Go to your merge requests'),
defaultKeys: ['shift+m'],
};
export const GO_TO_YOUR_TODO_LIST = {
id: 'globalShortcuts.goToYourTodoList',
description: __('Go to your To-Do list'),
defaultKeys: ['shift+t'],
};
export const TOGGLE_PERFORMANCE_BAR = { export const TOGGLE_PERFORMANCE_BAR = {
id: 'globalShortcuts.togglePerformanceBar', id: 'globalShortcuts.togglePerformanceBar',
description: s__('KeyboardShortcuts|Toggle the Performance Bar'), description: __('Toggle the Performance Bar'),
// eslint-disable-next-line @gitlab/require-i18n-strings defaultKeys: ['p b'], // eslint-disable-line @gitlab/require-i18n-strings
defaultKeys: ['p b'],
}; };
export const TOGGLE_CANARY = { export const TOGGLE_CANARY = {
id: 'globalShortcuts.toggleCanary', id: 'globalShortcuts.toggleCanary',
description: s__('KeyboardShortcuts|Toggle GitLab Next'), description: __('Toggle GitLab Next'),
// eslint-disable-next-line @gitlab/require-i18n-strings defaultKeys: ['g x'], // eslint-disable-line @gitlab/require-i18n-strings
defaultKeys: ['g x'], };
export const BOLD_TEXT = {
id: 'editing.boldText',
description: __('Bold text'),
defaultKeys: ['mod+b'],
customizable: false,
};
export const ITALIC_TEXT = {
id: 'editing.italicText',
description: __('Italic text'),
defaultKeys: ['mod+i'],
customizable: false,
};
export const LINK_TEXT = {
id: 'editing.linkText',
description: __('Link text'),
defaultKeys: ['mod+k'],
customizable: false,
};
export const TOGGLE_MARKDOWN_PREVIEW = {
id: 'editing.toggleMarkdownPreview',
description: __('Toggle Markdown preview'),
// Note: Ideally, keyboard shortcuts should be made cross-platform by using the special `mod` key
// instead of binding both `ctrl` and `command` versions of the shortcut.
// See https://docs.gitlab.com/ee/development/fe_guide/keyboard_shortcuts.html#make-cross-platform-shortcuts.
// However, this particular shortcut has been in place since before the `mod` key was available.
// We've chosen to leave this implemented as-is for the time being to avoid breaking people's workflows.
// See discussion in https://gitlab.com/gitlab-org/gitlab/-/merge_requests/45308#note_527490548.
defaultKeys: ['ctrl+shift+p', 'command+shift+p'],
};
export const EDIT_RECENT_COMMENT = {
id: 'editing.editRecentComment',
description: __('Edit your most recent comment in a thread (from an empty textarea)'),
defaultKeys: ['up'],
};
export const EDIT_WIKI_PAGE = {
id: 'wiki.editWikiPage',
description: __('Edit wiki page'),
defaultKeys: ['e'],
};
export const REPO_GRAPH_SCROLL_LEFT = {
id: 'repositoryGraph.scrollLeft',
description: __('Scroll left'),
defaultKeys: ['left', 'h'],
};
export const REPO_GRAPH_SCROLL_RIGHT = {
id: 'repositoryGraph.scrollRight',
description: __('Scroll right'),
defaultKeys: ['right', 'l'],
};
export const REPO_GRAPH_SCROLL_UP = {
id: 'repositoryGraph.scrollUp',
description: __('Scroll up'),
defaultKeys: ['up', 'k'],
};
export const REPO_GRAPH_SCROLL_DOWN = {
id: 'repositoryGraph.scrollDown',
description: __('Scroll down'),
defaultKeys: ['down', 'j'],
};
export const REPO_GRAPH_SCROLL_TOP = {
id: 'repositoryGraph.scrollToTop',
description: __('Scroll to top'),
defaultKeys: ['shift+up', 'shift+k'],
};
export const REPO_GRAPH_SCROLL_BOTTOM = {
id: 'repositoryGraph.scrollToBottom',
description: __('Scroll to bottom'),
defaultKeys: ['shift+down', 'shift+j'],
};
export const GO_TO_PROJECT_OVERVIEW = {
id: 'project.goToOverview',
description: __("Go to the project's overview page"),
defaultKeys: ['g p'], // eslint-disable-line @gitlab/require-i18n-strings
};
export const GO_TO_PROJECT_ACTIVITY_FEED = {
id: 'project.goToActivityFeed',
description: __("Go to the project's activity feed"),
defaultKeys: ['g v'], // eslint-disable-line @gitlab/require-i18n-strings
};
export const GO_TO_PROJECT_RELEASES = {
id: 'project.goToReleases',
description: __('Go to releases'),
defaultKeys: ['g r'], // eslint-disable-line @gitlab/require-i18n-strings
};
export const GO_TO_PROJECT_FILES = {
id: 'project.goToFiles',
description: __('Go to files'),
defaultKeys: ['g f'], // eslint-disable-line @gitlab/require-i18n-strings
};
export const GO_TO_PROJECT_FIND_FILE = {
id: 'project.goToFindFile',
description: __('Go to find file'),
defaultKeys: ['t'],
};
export const GO_TO_PROJECT_COMMITS = {
id: 'project.goToCommits',
description: __('Go to commits'),
defaultKeys: ['g c'], // eslint-disable-line @gitlab/require-i18n-strings
};
export const GO_TO_PROJECT_REPO_GRAPH = {
id: 'project.goToRepoGraph',
description: __('Go to repository graph'),
defaultKeys: ['g n'], // eslint-disable-line @gitlab/require-i18n-strings
};
export const GO_TO_PROJECT_REPO_CHARTS = {
id: 'project.goToRepoCharts',
description: __('Go to repository charts'),
defaultKeys: ['g d'], // eslint-disable-line @gitlab/require-i18n-strings
};
export const GO_TO_PROJECT_ISSUES = {
id: 'project.goToIssues',
description: __('Go to issues'),
defaultKeys: ['g i'], // eslint-disable-line @gitlab/require-i18n-strings
};
export const NEW_ISSUE = {
id: 'project.newIssue',
description: __('New issue'),
defaultKeys: ['i'],
};
export const GO_TO_PROJECT_ISSUE_BOARDS = {
id: 'project.goToIssueBoards',
description: __('Go to issue boards'),
defaultKeys: ['g b'], // eslint-disable-line @gitlab/require-i18n-strings
};
export const GO_TO_PROJECT_MERGE_REQUESTS = {
id: 'project.goToMergeRequests',
description: __('Go to merge requests'),
defaultKeys: ['g m'], // eslint-disable-line @gitlab/require-i18n-strings
};
export const GO_TO_PROJECT_JOBS = {
id: 'project.goToJobs',
description: __('Go to jobs'),
defaultKeys: ['g j'], // eslint-disable-line @gitlab/require-i18n-strings
};
export const GO_TO_PROJECT_METRICS = {
id: 'project.goToMetrics',
description: __('Go to metrics'),
defaultKeys: ['g l'], // eslint-disable-line @gitlab/require-i18n-strings
};
export const GO_TO_PROJECT_ENVIRONMENTS = {
id: 'project.goToEnvironments',
description: __('Go to environments'),
defaultKeys: ['g e'], // eslint-disable-line @gitlab/require-i18n-strings
};
export const GO_TO_PROJECT_KUBERNETES = {
id: 'project.goToKubernetes',
description: __('Go to kubernetes'),
defaultKeys: ['g k'], // eslint-disable-line @gitlab/require-i18n-strings
};
export const GO_TO_PROJECT_SNIPPETS = {
id: 'project.goToSnippets',
description: __('Go to snippets'),
defaultKeys: ['g s'], // eslint-disable-line @gitlab/require-i18n-strings
};
export const GO_TO_PROJECT_WIKI = {
id: 'project.goToWiki',
description: __('Go to wiki'),
defaultKeys: ['g w'], // eslint-disable-line @gitlab/require-i18n-strings
};
export const PROJECT_FILES_MOVE_SELECTION_UP = {
id: 'projectFiles.moveSelectionUp',
description: __('Move selection up'),
defaultKeys: ['up'],
};
export const PROJECT_FILES_MOVE_SELECTION_DOWN = {
id: 'projectFiles.moveSelectionDown',
description: __('Move selection down'),
defaultKeys: ['down'],
};
export const PROJECT_FILES_OPEN_SELECTION = {
id: 'projectFiles.openSelection',
description: __('Open Selection'),
defaultKeys: ['enter'],
};
export const PROJECT_FILES_GO_BACK = {
id: 'projectFiles.goBack',
description: __('Go back (while searching for files)'),
defaultKeys: ['esc'],
};
export const PROJECT_FILES_GO_TO_PERMALINK = {
id: 'projectFiles.goToFilePermalink',
description: __('Go to file permalink (while viewing a file)'),
defaultKeys: ['y'],
};
export const ISSUABLE_COMMENT_OR_REPLY = {
id: 'issuables.commentReply',
description: __('Comment/Reply (quoting selected text)'),
defaultKeys: ['r'],
};
export const ISSUABLE_EDIT_DESCRIPTION = {
id: 'issuables.editDescription',
description: __('Edit description'),
defaultKeys: ['e'],
};
export const ISSUABLE_CHANGE_LABEL = {
id: 'issuables.changeLabel',
description: __('Change label'),
defaultKeys: ['l'],
};
export const ISSUE_MR_CHANGE_ASSIGNEE = {
id: 'issuesMRs.changeAssignee',
description: __('Change assignee'),
defaultKeys: ['a'],
};
export const ISSUE_MR_CHANGE_MILESTONE = {
id: 'issuesMRs.changeMilestone',
description: __('Change milestone'),
defaultKeys: ['m'],
};
export const MR_NEXT_FILE_IN_DIFF = {
id: 'mergeRequests.nextFileInDiff',
description: __('Next file in diff'),
defaultKeys: [']', 'j'],
};
export const MR_PREVIOUS_FILE_IN_DIFF = {
id: 'mergeRequests.previousFileInDiff',
description: __('Previous file in diff'),
defaultKeys: ['[', 'k'],
};
export const MR_GO_TO_FILE = {
id: 'mergeRequests.goToFile',
description: __('Go to file'),
defaultKeys: ['t', 'mod+p'],
customizable: false,
};
export const MR_NEXT_UNRESOLVED_DISCUSSION = {
id: 'mergeRequests.nextUnresolvedDiscussion',
description: __('Next unresolved discussion'),
defaultKeys: ['n'],
};
export const MR_PREVIOUS_UNRESOLVED_DISCUSSION = {
id: 'mergeRequests.previousUnresolvedDiscussion',
description: __('Previous unresolved discussion'),
defaultKeys: ['p'],
};
export const MR_COPY_SOURCE_BRANCH_NAME = {
id: 'mergeRequests.copySourceBranchName',
description: __('Copy source branch name'),
defaultKeys: ['b'],
};
export const MR_COMMITS_NEXT_COMMIT = {
id: 'mergeRequestCommits.nextCommit',
description: __('Next commit'),
defaultKeys: ['c'],
};
export const MR_COMMITS_PREVIOUS_COMMIT = {
id: 'mergeRequestCommits.previousCommit',
description: __('Previous commit'),
defaultKeys: ['x'],
};
export const ISSUE_NEXT_DESIGN = {
id: 'issues.nextDesign',
description: __('Next design'),
defaultKeys: ['right'],
};
export const ISSUE_PREVIOUS_DESIGN = {
id: 'issues.previousDesign',
description: __('Previous design'),
defaultKeys: ['left'],
};
export const ISSUE_CLOSE_DESIGN = {
id: 'issues.closeDesign',
description: __('Close design'),
defaultKeys: ['esc'],
};
export const WEB_IDE_GO_TO_FILE = {
id: 'webIDE.goToFile',
description: __('Go to file'),
defaultKeys: ['mod+p'],
}; };
export const WEB_IDE_COMMIT = { export const WEB_IDE_COMMIT = {
id: 'webIDE.commit', id: 'webIDE.commit',
description: s__('KeyboardShortcuts|Commit (when editing commit message)'), description: __('Commit (when editing commit message)'),
defaultKeys: ['mod+enter'], defaultKeys: ['mod+enter'],
customizable: false, customizable: false,
}; };
export const METRICS_EXPAND_PANEL = {
id: 'metrics.expandPanel',
description: __('Expand panel'),
defaultKeys: ['e'],
customizable: false,
};
export const METRICS_VIEW_LOGS = {
id: 'metrics.viewLogs',
description: __('View logs'),
defaultKeys: ['l'],
customizable: false,
};
export const METRICS_DOWNLOAD_CSV = {
id: 'metrics.downloadCSV',
description: __('Download CSV'),
defaultKeys: ['d'],
customizable: false,
};
export const METRICS_COPY_LINK_TO_CHART = {
id: 'metrics.copyLinkToChart',
description: __('Copy link to chart'),
defaultKeys: ['c'],
customizable: false,
};
export const METRICS_SHOW_ALERTS = {
id: 'metrics.showAlerts',
description: __('Alerts'),
defaultKeys: ['a'],
customizable: false,
};
// All keybinding groups // All keybinding groups
export const GLOBAL_SHORTCUTS_GROUP = { export const GLOBAL_SHORTCUTS_GROUP = {
id: 'globalShortcuts', id: 'globalShortcuts',
name: s__('KeyboardShortcuts|Global Shortcuts'), name: __('Global Shortcuts'),
keybindings: [TOGGLE_PERFORMANCE_BAR, TOGGLE_CANARY], keybindings: [
TOGGLE_KEYBOARD_SHORTCUTS_DIALOG,
GO_TO_YOUR_PROJECTS,
GO_TO_YOUR_GROUPS,
GO_TO_ACTIVITY_FEED,
GO_TO_MILESTONE_LIST,
GO_TO_YOUR_SNIPPETS,
START_SEARCH,
FOCUS_FILTER_BAR,
GO_TO_YOUR_ISSUES,
GO_TO_YOUR_MERGE_REQUESTS,
GO_TO_YOUR_TODO_LIST,
TOGGLE_PERFORMANCE_BAR,
],
};
export const EDITING_SHORTCUTS_GROUP = {
id: 'editing',
name: __('Editing'),
keybindings: [BOLD_TEXT, ITALIC_TEXT, LINK_TEXT, TOGGLE_MARKDOWN_PREVIEW, EDIT_RECENT_COMMENT],
};
export const WIKI_SHORTCUTS_GROUP = {
id: 'wiki',
name: __('Wiki'),
keybindings: [EDIT_WIKI_PAGE],
};
export const REPOSITORY_GRAPH_SHORTCUTS_GROUP = {
id: 'repositoryGraph',
name: __('Repository Graph'),
keybindings: [
REPO_GRAPH_SCROLL_LEFT,
REPO_GRAPH_SCROLL_RIGHT,
REPO_GRAPH_SCROLL_UP,
REPO_GRAPH_SCROLL_DOWN,
REPO_GRAPH_SCROLL_TOP,
REPO_GRAPH_SCROLL_BOTTOM,
],
};
export const PROJECT_SHORTCUTS_GROUP = {
id: 'project',
name: __('Project'),
keybindings: [
GO_TO_PROJECT_OVERVIEW,
GO_TO_PROJECT_ACTIVITY_FEED,
GO_TO_PROJECT_RELEASES,
GO_TO_PROJECT_FILES,
GO_TO_PROJECT_FIND_FILE,
GO_TO_PROJECT_COMMITS,
GO_TO_PROJECT_REPO_GRAPH,
GO_TO_PROJECT_REPO_CHARTS,
GO_TO_PROJECT_ISSUES,
NEW_ISSUE,
GO_TO_PROJECT_ISSUE_BOARDS,
GO_TO_PROJECT_MERGE_REQUESTS,
GO_TO_PROJECT_JOBS,
GO_TO_PROJECT_METRICS,
GO_TO_PROJECT_ENVIRONMENTS,
GO_TO_PROJECT_KUBERNETES,
GO_TO_PROJECT_SNIPPETS,
GO_TO_PROJECT_WIKI,
],
};
export const PROJECT_FILES_SHORTCUTS_GROUP = {
id: 'projectFiles',
name: __('Project Files'),
keybindings: [
PROJECT_FILES_MOVE_SELECTION_UP,
PROJECT_FILES_MOVE_SELECTION_DOWN,
PROJECT_FILES_OPEN_SELECTION,
PROJECT_FILES_GO_BACK,
PROJECT_FILES_GO_TO_PERMALINK,
],
};
export const ISSUABLE_SHORTCUTS_GROUP = {
id: 'issuables',
name: __('Epics, Issues, and Merge Requests'),
keybindings: [ISSUABLE_COMMENT_OR_REPLY, ISSUABLE_EDIT_DESCRIPTION, ISSUABLE_CHANGE_LABEL],
};
export const ISSUE_MR_SHORTCUTS_GROUP = {
id: 'issuesMRs',
name: __('Issues and Merge Requests'),
keybindings: [ISSUE_MR_CHANGE_ASSIGNEE, ISSUE_MR_CHANGE_MILESTONE],
}; };
export const WEB_IDE_GROUP = { export const MR_SHORTCUTS_GROUP = {
id: 'mergeRequests',
name: __('Merge Requests'),
keybindings: [
MR_NEXT_FILE_IN_DIFF,
MR_PREVIOUS_FILE_IN_DIFF,
MR_GO_TO_FILE,
MR_NEXT_UNRESOLVED_DISCUSSION,
MR_PREVIOUS_UNRESOLVED_DISCUSSION,
MR_COPY_SOURCE_BRANCH_NAME,
],
};
export const MR_COMMITS_SHORTCUTS_GROUP = {
id: 'mergeRequestCommits',
name: __('Merge Request Commits'),
keybindings: [MR_COMMITS_NEXT_COMMIT, MR_COMMITS_PREVIOUS_COMMIT],
};
export const ISSUES_SHORTCUTS_GROUP = {
id: 'issues',
name: __('Issues'),
keybindings: [ISSUE_NEXT_DESIGN, ISSUE_PREVIOUS_DESIGN, ISSUE_CLOSE_DESIGN],
};
export const WEB_IDE_SHORTCUTS_GROUP = {
id: 'webIDE', id: 'webIDE',
name: s__('KeyboardShortcuts|Web IDE'), name: __('Web IDE'),
keybindings: [WEB_IDE_COMMIT], keybindings: [WEB_IDE_GO_TO_FILE, WEB_IDE_COMMIT],
};
export const METRICS_SHORTCUTS_GROUP = {
id: 'metrics',
name: __('Metrics'),
keybindings: [
METRICS_EXPAND_PANEL,
METRICS_VIEW_LOGS,
METRICS_DOWNLOAD_CSV,
METRICS_COPY_LINK_TO_CHART,
METRICS_SHOW_ALERTS,
],
};
export const MISC_SHORTCUTS_GROUP = {
id: 'misc',
name: __('Miscellaneous'),
keybindings: [TOGGLE_CANARY],
}; };
/** All keybindings, grouped and ordered with descriptions */ /** All keybindings, grouped and ordered with descriptions */
export const keybindingGroups = [GLOBAL_SHORTCUTS_GROUP, WEB_IDE_GROUP]; export const keybindingGroups = [
GLOBAL_SHORTCUTS_GROUP,
EDITING_SHORTCUTS_GROUP,
WIKI_SHORTCUTS_GROUP,
REPOSITORY_GRAPH_SHORTCUTS_GROUP,
PROJECT_SHORTCUTS_GROUP,
PROJECT_FILES_SHORTCUTS_GROUP,
ISSUABLE_SHORTCUTS_GROUP,
ISSUE_MR_SHORTCUTS_GROUP,
MR_SHORTCUTS_GROUP,
MR_COMMITS_SHORTCUTS_GROUP,
ISSUES_SHORTCUTS_GROUP,
WEB_IDE_SHORTCUTS_GROUP,
METRICS_SHORTCUTS_GROUP,
MISC_SHORTCUTS_GROUP,
];
/** /**
* Gets keyboard shortcuts associated with a command * Gets keyboard shortcuts associated with a command
......
...@@ -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 ""
...@@ -31774,6 +31786,9 @@ msgstr "" ...@@ -31774,6 +31786,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 ""
...@@ -33421,6 +33436,9 @@ msgstr "" ...@@ -33421,6 +33436,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