Commit 8c2000a9 authored by Martin Wortschack's avatar Martin Wortschack

Merge branch '22113-improve-keyboard-shortcuts-or-allow-them-to-be-disabled' into 'master'

Allow keyboard shortcuts to be disabled

Closes #22113

See merge request gitlab-org/gitlab!18782
parents 5cd90761 b927da04
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 Vue from 'vue';
import { disableShortcuts, shouldDisableShortcuts } from './shortcuts_toggle';
import ShortcutsToggle from './shortcuts_toggle.vue';
import axios from '../../lib/utils/axios_utils'; import axios from '../../lib/utils/axios_utils';
import { refreshCurrentPage, visitUrl } from '../../lib/utils/url_utility'; import { refreshCurrentPage, visitUrl } from '../../lib/utils/url_utility';
import findAndFollowLink from '../../lib/utils/navigation_utility'; import findAndFollowLink from '../../lib/utils/navigation_utility';
...@@ -15,6 +18,15 @@ Mousetrap.stopCallback = (e, element, combo) => { ...@@ -15,6 +18,15 @@ Mousetrap.stopCallback = (e, element, combo) => {
return defaultStopCallback(e, element, combo); return defaultStopCallback(e, element, combo);
}; };
function initToggleButton() {
return new Vue({
el: document.querySelector('.js-toggle-shortcuts'),
render(createElement) {
return createElement(ShortcutsToggle);
},
});
}
export default class Shortcuts { export default class Shortcuts {
constructor() { constructor() {
this.onToggleHelp = this.onToggleHelp.bind(this); this.onToggleHelp = this.onToggleHelp.bind(this);
...@@ -48,6 +60,14 @@ export default class Shortcuts { ...@@ -48,6 +60,14 @@ export default class Shortcuts {
$(this).remove(); $(this).remove();
e.preventDefault(); e.preventDefault();
}); });
$('.js-shortcuts-modal-trigger')
.off('click')
.on('click', this.onToggleHelp);
if (shouldDisableShortcuts()) {
disableShortcuts();
}
} }
onToggleHelp(e) { onToggleHelp(e) {
...@@ -104,7 +124,8 @@ export default class Shortcuts { ...@@ -104,7 +124,8 @@ export default class Shortcuts {
} }
return $('.js-more-help-button').remove(); return $('.js-more-help-button').remove();
}); })
.then(initToggleButton);
} }
focusFilter(e) { focusFilter(e) {
......
import Mousetrap from 'mousetrap';
import 'mousetrap/plugins/pause/mousetrap-pause';
const shorcutsDisabledKey = 'shortcutsDisabled';
export const shouldDisableShortcuts = () => {
try {
return localStorage.getItem(shorcutsDisabledKey) === 'true';
} catch (e) {
return false;
}
};
export function enableShortcuts() {
localStorage.setItem(shorcutsDisabledKey, false);
Mousetrap.unpause();
}
export function disableShortcuts() {
localStorage.setItem(shorcutsDisabledKey, true);
Mousetrap.pause();
}
<script>
import { GlToggle, GlSprintf } from '@gitlab/ui';
import AccessorUtilities from '~/lib/utils/accessor';
import { disableShortcuts, enableShortcuts, shouldDisableShortcuts } from './shortcuts_toggle';
export default {
components: {
GlSprintf,
GlToggle,
},
data() {
return {
localStorageUsable: AccessorUtilities.isLocalStorageAccessSafe(),
shortcutsEnabled: !shouldDisableShortcuts(),
};
},
methods: {
onChange(value) {
this.shortcutsEnabled = value;
if (value) {
enableShortcuts();
} else {
disableShortcuts();
}
},
},
};
</script>
<template>
<div v-if="localStorageUsable" class="d-inline-flex align-items-center js-toggle-shortcuts">
<gl-toggle
v-model="shortcutsEnabled"
aria-describedby="shortcutsToggle"
class="prepend-left-10 mb-0"
label-position="right"
@change="onChange"
>
<template #labelOn>
<gl-sprintf
:message="__('%{screenreaderOnlyStart}Keyboard shorcuts%{screenreaderOnlyEnd} Enabled')"
>
<template #screenreaderOnly="{ content }">
<span class="sr-only">{{ content }}</span>
</template>
</gl-sprintf>
</template>
<template #labelOff>
<gl-sprintf
:message="__('%{screenreaderOnlyStart}Keyboard shorcuts%{screenreaderOnlyEnd} Disabled')"
>
<template #screenreaderOnly="{ content }">
<span class="sr-only">{{ content }}</span>
</template>
</gl-sprintf>
</template>
</gl-toggle>
<div id="shortcutsToggle" class="sr-only">{{ __('Enable or disable keyboard shortcuts') }}</div>
</div>
</template>
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
= _('Keyboard Shortcuts') = _('Keyboard Shortcuts')
%small %small
= link_to _('(Show all)'), '#', class: 'js-more-help-button' = link_to _('(Show all)'), '#', class: 'js-more-help-button'
.js-toggle-shortcuts
%button.close{ type: "button", "data-dismiss": "modal", "aria-label" => _('Close') } %button.close{ type: "button", "data-dismiss": "modal", "aria-label" => _('Close') }
%span{ "aria-hidden": true } &times; %span{ "aria-hidden": true } &times;
.modal-body .modal-body
......
...@@ -4,6 +4,10 @@ ...@@ -4,6 +4,10 @@
= link_to _("Help"), help_path = link_to _("Help"), help_path
%li %li
= link_to _("Support"), support_url = link_to _("Support"), support_url
%li
%button.js-shortcuts-modal-trigger{ type: "button" }
= _("Keyboard shortcuts")
%span.text-secondary.float-right{ "aria-hidden": true }= '?'.html_safe
= render_if_exists "shared/learn_gitlab_menu_item" = render_if_exists "shared/learn_gitlab_menu_item"
%li.divider %li.divider
%li %li
......
---
title: Allow keyboard shortcuts to be disabled
merge_request: 18782
author:
type: added
...@@ -6,7 +6,10 @@ disqus_identifier: 'https://docs.gitlab.com/ee/workflow/shortcuts.html' ...@@ -6,7 +6,10 @@ disqus_identifier: 'https://docs.gitlab.com/ee/workflow/shortcuts.html'
# GitLab keyboard shortcuts # GitLab keyboard shortcuts
GitLab has many useful keyboard shortcuts to make it easier to access different features. GitLab has many useful keyboard shortcuts to make it easier to access different features.
You can see the quick reference sheet within GitLab itself with <kbd>Shift</kbd> + <kbd>?</kbd>. You can see a modal listing keyboard shortcuts within GitLab itself by pressing <kbd>?</kbd>,
or clicking **Keyboard shortcuts** in the Help menu at the top right.
From [GitLab 12.8 onwards](https://gitlab.com/gitlab-org/gitlab/issues/22113),
keyboard shortcuts can be disabled using the **Enable**/**Disable** toggle in this modal window.
The [Global Shortcuts](#global-shortcuts) work from any area of GitLab, but you must The [Global Shortcuts](#global-shortcuts) work from any area of GitLab, but you must
be in specific pages for the other shortcuts to be available, as explained in each be in specific pages for the other shortcuts to be available, as explained in each
......
...@@ -375,6 +375,12 @@ msgid_plural "%{releases} releases" ...@@ -375,6 +375,12 @@ msgid_plural "%{releases} releases"
msgstr[0] "" msgstr[0] ""
msgstr[1] "" msgstr[1] ""
msgid "%{screenreaderOnlyStart}Keyboard shorcuts%{screenreaderOnlyEnd} Disabled"
msgstr ""
msgid "%{screenreaderOnlyStart}Keyboard shorcuts%{screenreaderOnlyEnd} Enabled"
msgstr ""
msgid "%{service_title} activated." msgid "%{service_title} activated."
msgstr "" msgstr ""
...@@ -7155,6 +7161,9 @@ msgstr "" ...@@ -7155,6 +7161,9 @@ msgstr ""
msgid "Enable mirror configuration" msgid "Enable mirror configuration"
msgstr "" msgstr ""
msgid "Enable or disable keyboard shortcuts"
msgstr ""
msgid "Enable or disable the Pseudonymizer data collection." msgid "Enable or disable the Pseudonymizer data collection."
msgstr "" msgstr ""
...@@ -10945,6 +10954,9 @@ msgstr "" ...@@ -10945,6 +10954,9 @@ msgstr ""
msgid "Keyboard Shortcuts" msgid "Keyboard Shortcuts"
msgstr "" msgstr ""
msgid "Keyboard shortcuts"
msgstr ""
msgid "Kubernetes" msgid "Kubernetes"
msgstr "" msgstr ""
......
...@@ -17,6 +17,59 @@ describe 'User uses shortcuts', :js do ...@@ -17,6 +17,59 @@ describe 'User uses shortcuts', :js do
wait_for_requests wait_for_requests
end end
context 'disabling shortcuts' do
before do
page.evaluate_script("localStorage.removeItem('shortcutsDisabled')")
end
it 'can disable shortcuts from help menu' do
open_modal_shortcut_keys
click_toggle_button
close_modal
open_modal_shortcut_keys
# modal-shortcuts still in the DOM, but hidden
expect(find('#modal-shortcuts', visible: false)).not_to be_visible
page.refresh
open_modal_shortcut_keys
# after reload, shortcuts modal doesn't exist at all until we add it
expect(page).not_to have_selector('#modal-shortcuts')
end
it 're-enables shortcuts' do
open_modal_shortcut_keys
click_toggle_button
close_modal
open_modal_from_help_menu
click_toggle_button
close_modal
open_modal_shortcut_keys
expect(find('#modal-shortcuts')).to be_visible
end
def open_modal_shortcut_keys
find('body').native.send_key('?')
end
def open_modal_from_help_menu
find('.header-help-dropdown-toggle').click
find('button', text: 'Keyboard shortcuts').click
end
def click_toggle_button
find('.js-toggle-shortcuts .gl-toggle').click
end
def close_modal
find('.modal button[aria-label="Close"]').click
end
end
context 'when navigating to the Project pages' do context 'when navigating to the Project pages' do
it 'redirects to the details page' do it 'redirects to the details page' do
visit project_issues_path(project) visit project_issues_path(project)
......
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