diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2021-04-21 02:50:22 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2021-04-21 02:50:22 +0300 |
commit | 9dc93a4519d9d5d7be48ff274127136236a3adb3 (patch) | |
tree | 70467ae3692a0e35e5ea56bcb803eb512a10bedb /app/assets/javascripts/behaviors | |
parent | 4b0f34b6d759d6299322b3a54453e930c6121ff0 (diff) |
Add latest changes from gitlab-org/gitlab@13-11-stable-eev13.11.0-rc43
Diffstat (limited to 'app/assets/javascripts/behaviors')
12 files changed, 786 insertions, 102 deletions
diff --git a/app/assets/javascripts/behaviors/deprecated_remove_row_behavior.js b/app/assets/javascripts/behaviors/deprecated_remove_row_behavior.js new file mode 100644 index 00000000000..5731474e3a4 --- /dev/null +++ b/app/assets/javascripts/behaviors/deprecated_remove_row_behavior.js @@ -0,0 +1,15 @@ +import $ from 'jquery'; + +export default function initDeprecatedRemoveRowBehavior() { + $('.js-remove-row').on('ajax:success', function removeRowAjaxSuccessCallback() { + $(this).closest('li').addClass('gl-display-none!'); + }); + + $('.js-remove-tr').on('ajax:before', function removeTRAjaxBeforeCallback() { + $(this).parent().find('.btn').addClass('disabled'); + }); + + $('.js-remove-tr').on('ajax:success', function removeTRAjaxSuccessCallback() { + $(this).closest('tr').addClass('gl-display-none!'); + }); +} diff --git a/app/assets/javascripts/behaviors/markdown/render_mermaid.js b/app/assets/javascripts/behaviors/markdown/render_mermaid.js index 0cb13815c7e..5b5148a850b 100644 --- a/app/assets/javascripts/behaviors/markdown/render_mermaid.js +++ b/app/assets/javascripts/behaviors/markdown/render_mermaid.js @@ -1,6 +1,7 @@ import $ from 'jquery'; import { once } from 'lodash'; import { deprecatedCreateFlash as flash } from '~/flash'; +import { darkModeEnabled } from '~/lib/utils/color_utils'; import { __, sprintf } from '~/locale'; // Renders diagrams and flowcharts from text using Mermaid in any element with the @@ -27,37 +28,34 @@ let renderedMermaidBlocks = 0; let mermaidModule = {}; +export function initMermaid(mermaid) { + let theme = 'neutral'; + + if (darkModeEnabled()) { + theme = 'dark'; + } + + mermaid.initialize({ + // mermaid core options + mermaid: { + startOnLoad: false, + }, + // mermaidAPI options + theme, + flowchart: { + useMaxWidth: true, + htmlLabels: false, + }, + securityLevel: 'strict', + }); + + return mermaid; +} + function importMermaidModule() { return import(/* webpackChunkName: 'mermaid' */ 'mermaid') .then((mermaid) => { - let theme = 'neutral'; - const ideDarkThemes = ['dark', 'solarized-dark', 'monokai']; - - if ( - ideDarkThemes.includes(window.gon?.user_color_scheme) && - // if on the Web IDE page - document.querySelector('.ide') - ) { - theme = 'dark'; - } - - mermaid.initialize({ - // mermaid core options - mermaid: { - startOnLoad: false, - }, - // mermaidAPI options - theme, - flowchart: { - useMaxWidth: true, - htmlLabels: false, - }, - securityLevel: 'strict', - }); - - mermaidModule = mermaid; - - return mermaid; + mermaidModule = initMermaid(mermaid); }) .catch((err) => { flash(sprintf(__("Can't load mermaid module: %{err}"), { err })); diff --git a/app/assets/javascripts/behaviors/shortcuts/keybindings.js b/app/assets/javascripts/behaviors/shortcuts/keybindings.js index a8fe00d26e6..6abbd7f3243 100644 --- a/app/assets/javascripts/behaviors/shortcuts/keybindings.js +++ b/app/assets/javascripts/behaviors/shortcuts/keybindings.js @@ -1,6 +1,6 @@ import { memoize } from 'lodash'; import AccessorUtilities from '~/lib/utils/accessor'; -import { s__ } from '~/locale'; +import { __ } from '~/locale'; const isCustomizable = (command) => 'customizable' in command ? Boolean(command.customizable) : true; @@ -33,42 +33,608 @@ export const getCustomizations = memoize(() => { }); // 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 = { id: 'globalShortcuts.togglePerformanceBar', - description: s__('KeyboardShortcuts|Toggle the Performance Bar'), - // eslint-disable-next-line @gitlab/require-i18n-strings - defaultKeys: ['p b'], + description: __('Toggle the Performance Bar'), + defaultKeys: ['p b'], // eslint-disable-line @gitlab/require-i18n-strings }; export const TOGGLE_CANARY = { id: 'globalShortcuts.toggleCanary', - description: s__('KeyboardShortcuts|Toggle GitLab Next'), - // eslint-disable-next-line @gitlab/require-i18n-strings - defaultKeys: ['g x'], + description: __('Toggle GitLab Next'), + defaultKeys: ['g x'], // eslint-disable-line @gitlab/require-i18n-strings +}; + +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 = { id: 'webIDE.commit', - description: s__('KeyboardShortcuts|Commit (when editing commit message)'), + description: __('Commit (when editing commit message)'), defaultKeys: ['mod+enter'], 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 export const GLOBAL_SHORTCUTS_GROUP = { id: 'globalShortcuts', - name: s__('KeyboardShortcuts|Global Shortcuts'), - keybindings: [TOGGLE_PERFORMANCE_BAR, TOGGLE_CANARY], + name: __('Global Shortcuts'), + 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', - name: s__('KeyboardShortcuts|Web IDE'), - keybindings: [WEB_IDE_COMMIT], + name: __('Web IDE'), + 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 */ -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 diff --git a/app/assets/javascripts/behaviors/shortcuts/shortcuts.js b/app/assets/javascripts/behaviors/shortcuts/shortcuts.js index e4ec68601e0..03cba78cf31 100644 --- a/app/assets/javascripts/behaviors/shortcuts/shortcuts.js +++ b/app/assets/javascripts/behaviors/shortcuts/shortcuts.js @@ -6,13 +6,29 @@ import Vue from 'vue'; import { parseBoolean } from '~/lib/utils/common_utils'; import findAndFollowLink from '~/lib/utils/navigation_utility'; import { refreshCurrentPage, visitUrl } from '~/lib/utils/url_utility'; - -import { keysFor, TOGGLE_PERFORMANCE_BAR, TOGGLE_CANARY } from './keybindings'; +import { + 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'; const defaultStopCallback = Mousetrap.prototype.stopCallback; 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; } @@ -58,28 +74,41 @@ export default class Shortcuts { this.helpModalElement = null; this.helpModalVueInstance = null; - Mousetrap.bind('?', this.onToggleHelp); - Mousetrap.bind('s', Shortcuts.focusSearch); - Mousetrap.bind('/', Shortcuts.focusSearch); - Mousetrap.bind('f', this.focusFilter.bind(this)); + Mousetrap.bind(keysFor(TOGGLE_KEYBOARD_SHORTCUTS_DIALOG), this.onToggleHelp); + Mousetrap.bind(keysFor(START_SEARCH), Shortcuts.focusSearch); + Mousetrap.bind(keysFor(FOCUS_FILTER_BAR), this.focusFilter.bind(this)); Mousetrap.bind(keysFor(TOGGLE_PERFORMANCE_BAR), Shortcuts.onTogglePerfBar); Mousetrap.bind(keysFor(TOGGLE_CANARY), Shortcuts.onToggleCanary); const findFileURL = document.body.dataset.findFile; - Mousetrap.bind('shift+t', () => findAndFollowLink('.shortcuts-todos')); - Mousetrap.bind('shift+a', () => findAndFollowLink('.dashboard-shortcuts-activity')); - Mousetrap.bind('shift+i', () => findAndFollowLink('.dashboard-shortcuts-issues')); - Mousetrap.bind('shift+m', () => findAndFollowLink('.dashboard-shortcuts-merge_requests')); - Mousetrap.bind('shift+p', () => findAndFollowLink('.dashboard-shortcuts-projects')); - Mousetrap.bind('shift+g', () => findAndFollowLink('.dashboard-shortcuts-groups')); - Mousetrap.bind('shift+l', () => findAndFollowLink('.dashboard-shortcuts-milestones')); - Mousetrap.bind('shift+s', () => findAndFollowLink('.dashboard-shortcuts-snippets')); - - Mousetrap.bind(['ctrl+shift+p', 'command+shift+p'], Shortcuts.toggleMarkdownPreview); + Mousetrap.bind(keysFor(GO_TO_YOUR_TODO_LIST), () => findAndFollowLink('.shortcuts-todos')); + Mousetrap.bind(keysFor(GO_TO_ACTIVITY_FEED), () => + findAndFollowLink('.dashboard-shortcuts-activity'), + ); + Mousetrap.bind(keysFor(GO_TO_YOUR_ISSUES), () => + findAndFollowLink('.dashboard-shortcuts-issues'), + ); + Mousetrap.bind(keysFor(GO_TO_YOUR_MERGE_REQUESTS), () => + findAndFollowLink('.dashboard-shortcuts-merge_requests'), + ); + 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) { - Mousetrap.bind('t', () => { + Mousetrap.bind(keysFor(GO_TO_PROJECT_FIND_FILE), () => { visitUrl(findFileURL); }); } diff --git a/app/assets/javascripts/behaviors/shortcuts/shortcuts_blob.js b/app/assets/javascripts/behaviors/shortcuts/shortcuts_blob.js index 11b4fcd4e1c..ab7fcbb35f1 100644 --- a/app/assets/javascripts/behaviors/shortcuts/shortcuts_blob.js +++ b/app/assets/javascripts/behaviors/shortcuts/shortcuts_blob.js @@ -1,4 +1,5 @@ import Mousetrap from 'mousetrap'; +import { keysFor, PROJECT_FILES_GO_TO_PERMALINK } from '~/behaviors/shortcuts/keybindings'; import { getLocationHash, updateHistory, @@ -28,7 +29,7 @@ export default class ShortcutsBlob extends Shortcuts { this.shortcircuitPermalinkButton(); - Mousetrap.bind('y', this.moveToFilePermalink.bind(this)); + Mousetrap.bind(keysFor(PROJECT_FILES_GO_TO_PERMALINK), this.moveToFilePermalink.bind(this)); } moveToFilePermalink() { diff --git a/app/assets/javascripts/behaviors/shortcuts/shortcuts_find_file.js b/app/assets/javascripts/behaviors/shortcuts/shortcuts_find_file.js index f0d2ecfd210..992e571e596 100644 --- a/app/assets/javascripts/behaviors/shortcuts/shortcuts_find_file.js +++ b/app/assets/javascripts/behaviors/shortcuts/shortcuts_find_file.js @@ -1,4 +1,11 @@ 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'; export default class ShortcutsFindFile extends ShortcutsNavigation { @@ -10,7 +17,10 @@ export default class ShortcutsFindFile extends ShortcutsNavigation { Mousetrap.prototype.stopCallback = function customStopCallback(e, element, combo) { if ( 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 e.preventDefault(); @@ -20,9 +30,9 @@ export default class ShortcutsFindFile extends ShortcutsNavigation { return oldStopCallback.call(this, e, element, combo); }; - Mousetrap.bind('up', projectFindFile.selectRowUp); - Mousetrap.bind('down', projectFindFile.selectRowDown); - Mousetrap.bind('esc', projectFindFile.goToTree); - Mousetrap.bind('enter', projectFindFile.goToBlob); + Mousetrap.bind(keysFor(PROJECT_FILES_MOVE_SELECTION_UP), projectFindFile.selectRowUp); + Mousetrap.bind(keysFor(PROJECT_FILES_MOVE_SELECTION_DOWN), projectFindFile.selectRowDown); + Mousetrap.bind(keysFor(PROJECT_FILES_GO_BACK), projectFindFile.goToTree); + Mousetrap.bind(keysFor(PROJECT_FILES_OPEN_SELECTION), projectFindFile.goToBlob); } } diff --git a/app/assets/javascripts/behaviors/shortcuts/shortcuts_help.vue b/app/assets/javascripts/behaviors/shortcuts/shortcuts_help.vue index 1277dd0ed37..49216cc4aa0 100644 --- a/app/assets/javascripts/behaviors/shortcuts/shortcuts_help.vue +++ b/app/assets/javascripts/behaviors/shortcuts/shortcuts_help.vue @@ -397,7 +397,7 @@ export default { <tbody> <tr> <th></th> - <th>{{ __('Epics, Issues, and Merge Requests') }}</th> + <th>{{ __('Epics, issues, and merge requests') }}</th> </tr> <tr> <td class="shortcut"> @@ -421,7 +421,7 @@ export default { <tbody> <tr> <th></th> - <th>{{ __('Issues and Merge Requests') }}</th> + <th>{{ __('Issues and merge requests') }}</th> </tr> <tr> <td class="shortcut"> @@ -439,7 +439,7 @@ export default { <tbody> <tr> <th></th> - <th>{{ __('Merge Requests') }}</th> + <th>{{ __('Merge requests') }}</th> </tr> <tr> <td class="shortcut"> @@ -485,7 +485,7 @@ export default { <tbody> <tr> <th></th> - <th>{{ __('Merge Request Commits') }}</th> + <th>{{ __('Merge request commits') }}</th> </tr> <tr> <td class="shortcut"> diff --git a/app/assets/javascripts/behaviors/shortcuts/shortcuts_issuable.js b/app/assets/javascripts/behaviors/shortcuts/shortcuts_issuable.js index 476745beb19..c2908133fd0 100644 --- a/app/assets/javascripts/behaviors/shortcuts/shortcuts_issuable.js +++ b/app/assets/javascripts/behaviors/shortcuts/shortcuts_issuable.js @@ -5,18 +5,33 @@ import { getSelectedFragment } from '~/lib/utils/common_utils'; import { isElementVisible } from '~/lib/utils/dom_utils'; import Sidebar from '../../right_sidebar'; 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'; export default class ShortcutsIssuable extends Shortcuts { constructor() { super(); - Mousetrap.bind('a', () => ShortcutsIssuable.openSidebarDropdown('assignee')); - Mousetrap.bind('m', () => ShortcutsIssuable.openSidebarDropdown('milestone')); - Mousetrap.bind('l', () => ShortcutsIssuable.openSidebarDropdown('labels')); - Mousetrap.bind('r', ShortcutsIssuable.replyWithSelectedText); - Mousetrap.bind('e', ShortcutsIssuable.editIssue); - Mousetrap.bind('b', ShortcutsIssuable.copyBranchName); + Mousetrap.bind(keysFor(ISSUE_MR_CHANGE_ASSIGNEE), () => + ShortcutsIssuable.openSidebarDropdown('assignee'), + ); + Mousetrap.bind(keysFor(ISSUE_MR_CHANGE_MILESTONE), () => + ShortcutsIssuable.openSidebarDropdown('milestone'), + ); + 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() { @@ -105,7 +120,7 @@ export default class ShortcutsIssuable extends Shortcuts { static copyBranchName() { // There are two buttons - one that is shown when the sidebar // is expanded, and one that is shown when it's collapsed. - const allCopyBtns = Array.from(document.querySelectorAll('.sidebar-source-branch button')); + const allCopyBtns = Array.from(document.querySelectorAll('.js-sidebar-source-branch button')); // Select whichever button is currently visible so that // the "Copied" tooltip is shown when a click is simulated. diff --git a/app/assets/javascripts/behaviors/shortcuts/shortcuts_navigation.js b/app/assets/javascripts/behaviors/shortcuts/shortcuts_navigation.js index b46b4132ba8..b188d3b0ec3 100644 --- a/app/assets/javascripts/behaviors/shortcuts/shortcuts_navigation.js +++ b/app/assets/javascripts/behaviors/shortcuts/shortcuts_navigation.js @@ -1,27 +1,63 @@ import Mousetrap from 'mousetrap'; 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'; export default class ShortcutsNavigation extends Shortcuts { constructor() { super(); - Mousetrap.bind('g p', () => findAndFollowLink('.shortcuts-project')); - Mousetrap.bind('g v', () => findAndFollowLink('.shortcuts-project-activity')); - Mousetrap.bind('g r', () => findAndFollowLink('.shortcuts-project-releases')); - Mousetrap.bind('g f', () => findAndFollowLink('.shortcuts-tree')); - Mousetrap.bind('g c', () => findAndFollowLink('.shortcuts-commits')); - Mousetrap.bind('g j', () => findAndFollowLink('.shortcuts-builds')); - Mousetrap.bind('g n', () => findAndFollowLink('.shortcuts-network')); - Mousetrap.bind('g d', () => findAndFollowLink('.shortcuts-repository-charts')); - Mousetrap.bind('g i', () => findAndFollowLink('.shortcuts-issues')); - Mousetrap.bind('g b', () => findAndFollowLink('.shortcuts-issue-boards')); - Mousetrap.bind('g m', () => findAndFollowLink('.shortcuts-merge_requests')); - Mousetrap.bind('g w', () => findAndFollowLink('.shortcuts-wiki')); - Mousetrap.bind('g s', () => findAndFollowLink('.shortcuts-snippets')); - Mousetrap.bind('g k', () => findAndFollowLink('.shortcuts-kubernetes')); - Mousetrap.bind('g e', () => findAndFollowLink('.shortcuts-environments')); - Mousetrap.bind('g l', () => findAndFollowLink('.shortcuts-metrics')); - Mousetrap.bind('i', () => findAndFollowLink('.shortcuts-new-issue')); + Mousetrap.bind(keysFor(GO_TO_PROJECT_OVERVIEW), () => findAndFollowLink('.shortcuts-project')); + Mousetrap.bind(keysFor(GO_TO_PROJECT_ACTIVITY_FEED), () => + findAndFollowLink('.shortcuts-project-activity'), + ); + Mousetrap.bind(keysFor(GO_TO_PROJECT_RELEASES), () => + findAndFollowLink('.shortcuts-project-releases'), + ); + Mousetrap.bind(keysFor(GO_TO_PROJECT_FILES), () => findAndFollowLink('.shortcuts-tree')); + Mousetrap.bind(keysFor(GO_TO_PROJECT_COMMITS), () => findAndFollowLink('.shortcuts-commits')); + Mousetrap.bind(keysFor(GO_TO_PROJECT_JOBS), () => findAndFollowLink('.shortcuts-builds')); + Mousetrap.bind(keysFor(GO_TO_PROJECT_REPO_GRAPH), () => + findAndFollowLink('.shortcuts-network'), + ); + Mousetrap.bind(keysFor(GO_TO_PROJECT_REPO_CHARTS), () => + findAndFollowLink('.shortcuts-repository-charts'), + ); + 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')); } } diff --git a/app/assets/javascripts/behaviors/shortcuts/shortcuts_network.js b/app/assets/javascripts/behaviors/shortcuts/shortcuts_network.js index 3e791e4673a..c33c092b009 100644 --- a/app/assets/javascripts/behaviors/shortcuts/shortcuts_network.js +++ b/app/assets/javascripts/behaviors/shortcuts/shortcuts_network.js @@ -1,15 +1,24 @@ 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'; export default class ShortcutsNetwork extends ShortcutsNavigation { constructor(graph) { super(); - Mousetrap.bind(['left', 'h'], graph.scrollLeft); - Mousetrap.bind(['right', 'l'], graph.scrollRight); - Mousetrap.bind(['up', 'k'], graph.scrollUp); - Mousetrap.bind(['down', 'j'], graph.scrollDown); - Mousetrap.bind(['shift+up', 'shift+k'], graph.scrollTop); - Mousetrap.bind(['shift+down', 'shift+j'], graph.scrollBottom); + Mousetrap.bind(keysFor(REPO_GRAPH_SCROLL_LEFT), graph.scrollLeft); + Mousetrap.bind(keysFor(REPO_GRAPH_SCROLL_RIGHT), graph.scrollRight); + Mousetrap.bind(keysFor(REPO_GRAPH_SCROLL_UP), graph.scrollUp); + Mousetrap.bind(keysFor(REPO_GRAPH_SCROLL_DOWN), graph.scrollDown); + Mousetrap.bind(keysFor(REPO_GRAPH_SCROLL_TOP), graph.scrollTop); + Mousetrap.bind(keysFor(REPO_GRAPH_SCROLL_BOTTOM), graph.scrollBottom); } } diff --git a/app/assets/javascripts/behaviors/shortcuts/shortcuts_toggle.vue b/app/assets/javascripts/behaviors/shortcuts/shortcuts_toggle.vue index 8418c0f66ac..6cbe443062a 100644 --- a/app/assets/javascripts/behaviors/shortcuts/shortcuts_toggle.vue +++ b/app/assets/javascripts/behaviors/shortcuts/shortcuts_toggle.vue @@ -1,9 +1,13 @@ <script> import { GlToggle } from '@gitlab/ui'; import AccessorUtilities from '~/lib/utils/accessor'; +import { __ } from '~/locale'; import { disableShortcuts, enableShortcuts, shouldDisableShortcuts } from './shortcuts_toggle'; export default { + i18n: { + toggleLabel: __('Keyboard shortcuts'), + }, components: { GlToggle, }, @@ -31,7 +35,7 @@ export default { <gl-toggle v-model="shortcutsEnabled" aria-describedby="shortcutsToggle" - label="Keyboard shortcuts" + :label="$options.i18n.toggleLabel" label-position="left" @change="onChange" /> diff --git a/app/assets/javascripts/behaviors/shortcuts/shortcuts_wiki.js b/app/assets/javascripts/behaviors/shortcuts/shortcuts_wiki.js index c609936a02a..59c1d2654bc 100644 --- a/app/assets/javascripts/behaviors/shortcuts/shortcuts_wiki.js +++ b/app/assets/javascripts/behaviors/shortcuts/shortcuts_wiki.js @@ -1,11 +1,12 @@ import Mousetrap from 'mousetrap'; import findAndFollowLink from '../../lib/utils/navigation_utility'; +import { keysFor, EDIT_WIKI_PAGE } from './keybindings'; import ShortcutsNavigation from './shortcuts_navigation'; export default class ShortcutsWiki extends ShortcutsNavigation { constructor() { super(); - Mousetrap.bind('e', ShortcutsWiki.editWiki); + Mousetrap.bind(keysFor(EDIT_WIKI_PAGE), ShortcutsWiki.editWiki); } static editWiki() { |