feat: Creates a modal showing all the available keyboard shortcuts (#2728)
* feat: Adds modal showing all the available keyboard shortcuts * Minor fixes * Minor fixes * Spacing fixes * fix translations * Adds i18n * Review fixes * Review fixes * spacing fixes * Review fixes * Minor fixes Co-authored-by: Muhsin Keloth <muhsinkeramam@gmail.com>
This commit is contained in:
parent
bdc4ecffc1
commit
c3314dd186
8 changed files with 353 additions and 1 deletions
|
@ -175,6 +175,9 @@ export default {
|
|||
const allConversations = document.querySelectorAll(
|
||||
'.conversations-list .conversation'
|
||||
);
|
||||
if (hasPressedAltAndMKey(e)) {
|
||||
this.$refs.arrowDownButton.$el.click();
|
||||
}
|
||||
if (hasPressedAltAndEKey(e)) {
|
||||
const activeConversation = document.querySelector(
|
||||
'div.conversations-list div.conversation.active'
|
||||
|
|
|
@ -50,10 +50,17 @@
|
|||
:show="showOptionsMenu"
|
||||
@toggle-accounts="toggleAccountModal"
|
||||
@show-support-chat-window="toggleSupportChatWindow"
|
||||
@key-shortcut-modal="toggleKeyShortcutModal"
|
||||
@close="toggleOptions"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<woot-key-shortcut-modal
|
||||
v-if="showShortcutModal"
|
||||
@close="closeKeyShortcutModal"
|
||||
@clickaway="closeKeyShortcutModal"
|
||||
/>
|
||||
|
||||
<account-selector
|
||||
:show-account-modal="showAccountModal"
|
||||
@close-account-modal="toggleAccountModal"
|
||||
|
@ -86,6 +93,9 @@ import OptionsMenu from './sidebarComponents/OptionsMenu.vue';
|
|||
import AccountSelector from './sidebarComponents/AccountSelector.vue';
|
||||
import AddAccountModal from './sidebarComponents/AddAccountModal.vue';
|
||||
import AddLabelModal from '../../routes/dashboard/settings/labels/AddLabel';
|
||||
import WootKeyShortcutModal from 'components/widgets/modal/WootKeyShortcutModal';
|
||||
import { hasPressedCommandAndForwardSlash } from 'shared/helpers/KeyboardHelpers';
|
||||
import eventListenerMixins from 'shared/mixins/eventListenerMixins';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
|
@ -97,14 +107,16 @@ export default {
|
|||
AccountSelector,
|
||||
AddAccountModal,
|
||||
AddLabelModal,
|
||||
WootKeyShortcutModal,
|
||||
},
|
||||
mixins: [adminMixin, alertMixin],
|
||||
mixins: [adminMixin, alertMixin, eventListenerMixins],
|
||||
data() {
|
||||
return {
|
||||
showOptionsMenu: false,
|
||||
showAccountModal: false,
|
||||
showCreateAccountModal: false,
|
||||
showAddLabelModal: false,
|
||||
showShortcutModal: false,
|
||||
};
|
||||
},
|
||||
|
||||
|
@ -254,7 +266,19 @@ export default {
|
|||
this.$store.dispatch('teams/get');
|
||||
this.setChatwootUser();
|
||||
},
|
||||
|
||||
methods: {
|
||||
toggleKeyShortcutModal() {
|
||||
this.showShortcutModal = true;
|
||||
},
|
||||
closeKeyShortcutModal() {
|
||||
this.showShortcutModal = false;
|
||||
},
|
||||
handleKeyEvents(e) {
|
||||
if (hasPressedCommandAndForwardSlash(e)) {
|
||||
this.toggleKeyShortcutModal();
|
||||
}
|
||||
},
|
||||
toggleSupportChatWindow() {
|
||||
window.$chatwoot.toggle();
|
||||
},
|
||||
|
|
|
@ -26,6 +26,16 @@
|
|||
Contact Support
|
||||
</woot-button>
|
||||
</woot-dropdown-item>
|
||||
<woot-dropdown-item>
|
||||
<woot-button
|
||||
variant="clear"
|
||||
size="small"
|
||||
class=" change-accounts--button"
|
||||
@click="$emit('key-shortcut-modal')"
|
||||
>
|
||||
{{ $t('SIDEBAR_ITEMS.KEYBOARD_SHORTCUTS') }}
|
||||
</woot-button>
|
||||
</woot-dropdown-item>
|
||||
<woot-dropdown-item>
|
||||
<router-link
|
||||
:to="`/app/accounts/${accountId}/profile/settings`"
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
import WootKeyboardShortcutModal from './WootKeyShortcutModal.vue';
|
||||
|
||||
export default {
|
||||
title: 'Components/Shortcuts/Keyboard Shortcut',
|
||||
component: WootKeyboardShortcutModal,
|
||||
argTypes: {},
|
||||
};
|
||||
|
||||
const Template = (args, { argTypes }) => ({
|
||||
props: Object.keys(argTypes),
|
||||
components: { WootKeyboardShortcutModal },
|
||||
template:
|
||||
'<woot-keyboard-shortcut-modal v-bind="$props"></woot-keyboard-shortcut-modal>',
|
||||
});
|
||||
|
||||
export const KeyboardShortcut = Template.bind({});
|
||||
KeyboardShortcut.args = {};
|
|
@ -0,0 +1,182 @@
|
|||
<template>
|
||||
<transition name="slide-up">
|
||||
<div class="modal-mask">
|
||||
<div v-on-clickaway="() => $emit('clickaway')" class="modal-container">
|
||||
<div class="header-wrap">
|
||||
<div class="title-shortcut-key__wrap">
|
||||
<h2 class="page-title">
|
||||
{{ $t('SIDEBAR_ITEMS.KEYBOARD_SHORTCUTS') }}
|
||||
</h2>
|
||||
<div class="shortcut-key__wrap">
|
||||
<p class="shortcut-key">
|
||||
{{ $t('KEYBOARD_SHORTCUTS.KEYS.COMMAND_KEY') }}
|
||||
</p>
|
||||
<p class="shortcut-key key">
|
||||
{{ $t('KEYBOARD_SHORTCUTS.KEYS.FORWARD_SLASH_KEY') }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<i class="ion-android-close modal--close" @click="$emit('close')"></i>
|
||||
</div>
|
||||
|
||||
<div class="shortcut__wrap">
|
||||
<div class="title-key__wrap">
|
||||
<span class="sub-block-title">
|
||||
{{ $t('KEYBOARD_SHORTCUTS.TITLE.OPEN_CONVERSATION') }}
|
||||
</span>
|
||||
<div class="shortcut-key__wrap">
|
||||
<div class="open-conversation__key">
|
||||
<span class="shortcut-key">
|
||||
{{ $t('KEYBOARD_SHORTCUTS.KEYS.ALT_OR_OPTION_KEY') }}
|
||||
</span>
|
||||
<span class="shortcut-key">
|
||||
J
|
||||
</span>
|
||||
<span class="forward-slash sub-block-title">
|
||||
{{ $t('KEYBOARD_SHORTCUTS.KEYS.FORWARD_SLASH_KEY') }}
|
||||
</span>
|
||||
</div>
|
||||
<span class="shortcut-key">
|
||||
{{ $t('KEYBOARD_SHORTCUTS.KEYS.ALT_OR_OPTION_KEY') }}
|
||||
</span>
|
||||
<span class="shortcut-key key">
|
||||
K
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="title-key__wrap">
|
||||
<span class="sub-block-title">
|
||||
{{ $t('KEYBOARD_SHORTCUTS.TITLE.RESOLVE_AND_NEXT') }}
|
||||
</span>
|
||||
<div class="shortcut-key__wrap">
|
||||
<span class="shortcut-key">
|
||||
{{ $t('KEYBOARD_SHORTCUTS.KEYS.COMMAND_KEY') }}
|
||||
</span>
|
||||
<span class="shortcut-key">
|
||||
{{ $t('KEYBOARD_SHORTCUTS.KEYS.ALT_OR_OPTION_KEY') }}
|
||||
</span>
|
||||
<span class="shortcut-key key">
|
||||
E
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
v-for="shortcutKey in shortcutKeys"
|
||||
:key="shortcutKey.id"
|
||||
class="title-key__wrap"
|
||||
>
|
||||
<span class="sub-block-title">
|
||||
{{ title(shortcutKey) }}
|
||||
</span>
|
||||
<div class="shortcut-key__wrap">
|
||||
<span class="shortcut-key">
|
||||
{{ shortcutKey.firstkey }}
|
||||
</span>
|
||||
<span class="shortcut-key key">
|
||||
{{ shortcutKey.secondKey }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</transition>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mixin as clickaway } from 'vue-clickaway';
|
||||
import { SHORTCUT_KEYS } from './constants';
|
||||
|
||||
export default {
|
||||
mixins: [clickaway],
|
||||
data() {
|
||||
return {
|
||||
shortcutKeys: SHORTCUT_KEYS,
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
title(item) {
|
||||
return this.$t(`KEYBOARD_SHORTCUTS.TITLE.${item.label}`);
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.modal-container {
|
||||
padding: var(--space-medium) var(--space-large) var(--space-large)
|
||||
var(--space-large);
|
||||
width: fit-content;
|
||||
}
|
||||
|
||||
.header-wrap {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.title-shortcut-key__wrap {
|
||||
display: flex;
|
||||
margin-bottom: var(--space-small);
|
||||
}
|
||||
|
||||
.page-title {
|
||||
font-size: var(--font-size-big);
|
||||
font-weight: var(--font-weight-bold);
|
||||
}
|
||||
|
||||
.shortcut-key__wrap {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: var(--space-smaller);
|
||||
margin-left: var(--space-small);
|
||||
}
|
||||
|
||||
.shortcut__wrap {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, 0.5fr);
|
||||
gap: var(--space-smaller) var(--space-large);
|
||||
margin-top: var(--space-small);
|
||||
}
|
||||
|
||||
.title-key__wrap {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
min-width: 40rem;
|
||||
}
|
||||
|
||||
.sub-block-title {
|
||||
font-size: var(--font-size-small);
|
||||
font-weight: var(--font-weight-medium);
|
||||
}
|
||||
|
||||
.forward-slash {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-weight: var(--font-weight-bold);
|
||||
}
|
||||
|
||||
.shortcut-key {
|
||||
background: var(--color-background);
|
||||
padding: var(--space-small) var(--space-one);
|
||||
font-weight: var(--font-weight-bold);
|
||||
font-size: var(--font-size-mini);
|
||||
align-items: center;
|
||||
border-radius: var(--border-radius-normal);
|
||||
margin-right: var(--space-small);
|
||||
}
|
||||
|
||||
.key {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
min-width: var(--space-large);
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
.open-conversation__key {
|
||||
display: flex;
|
||||
margin-right: var(--space-small);
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,86 @@
|
|||
export const SHORTCUT_KEYS = [
|
||||
{
|
||||
id: 1,
|
||||
label: 'NAVIGATE_DROPDOWN',
|
||||
firstkey: 'Up',
|
||||
secondKey: 'Down',
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
label: 'RESOLVE_CONVERSATION',
|
||||
firstkey: 'Alt / ⌥',
|
||||
secondKey: 'E',
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
label: 'GO_TO_CONVERSATION_DASHBOARD',
|
||||
firstkey: 'Alt / ⌥',
|
||||
secondKey: 'C',
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
label: 'ADD_ATTACHMENT',
|
||||
firstkey: 'Alt / ⌥',
|
||||
secondKey: 'A',
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
label: 'GO_TO_CONTACTS_DASHBOARD',
|
||||
firstkey: 'Alt / ⌥',
|
||||
secondKey: 'V',
|
||||
},
|
||||
{
|
||||
id: 6,
|
||||
label: 'TOGGLE_SIDEBAR',
|
||||
firstkey: 'Alt / ⌥',
|
||||
secondKey: 'O',
|
||||
},
|
||||
{
|
||||
id: 7,
|
||||
label: 'GO_TO_REPORTS_SIDEBAR',
|
||||
firstkey: 'Alt / ⌥',
|
||||
secondKey: 'R',
|
||||
},
|
||||
{
|
||||
id: 8,
|
||||
label: 'MOVE_TO_NEXT_TAB',
|
||||
firstkey: 'Alt / ⌥',
|
||||
secondKey: 'N',
|
||||
},
|
||||
{
|
||||
id: 9,
|
||||
label: 'GO_TO_SETTINGS',
|
||||
firstkey: 'Alt / ⌥',
|
||||
secondKey: 'S',
|
||||
},
|
||||
{
|
||||
id: 10,
|
||||
label: 'SWITCH_CONVERSATION_STATUS',
|
||||
firstkey: 'Alt / ⌥',
|
||||
secondKey: 'B',
|
||||
},
|
||||
{
|
||||
id: 11,
|
||||
label: 'SWITCH_TO_PRIVATE_NOTE',
|
||||
firstkey: 'Alt / ⌥',
|
||||
secondKey: 'P',
|
||||
},
|
||||
{
|
||||
id: 12,
|
||||
label: 'TOGGLE_RICH_CONTENT_EDITOR',
|
||||
firstkey: 'Alt / ⌥',
|
||||
secondKey: 'W',
|
||||
},
|
||||
{
|
||||
id: 13,
|
||||
label: 'SWITCH_TO_REPLY',
|
||||
firstkey: 'Alt / ⌥',
|
||||
secondKey: 'L',
|
||||
},
|
||||
{
|
||||
id: 14,
|
||||
label: 'TOGGLE_SNOOZE_DROPDOWN',
|
||||
firstkey: 'Alt / ⌥',
|
||||
secondKey: 'M',
|
||||
},
|
||||
];
|
|
@ -98,6 +98,7 @@
|
|||
"CHANGE_ACCOUNTS": "Switch Account",
|
||||
"SELECTOR_SUBTITLE": "Select an account from the following list",
|
||||
"PROFILE_SETTINGS": "Profile Settings",
|
||||
"KEYBOARD_SHORTCUTS": "Keyboard Shortcuts",
|
||||
"LOGOUT": "Logout"
|
||||
},
|
||||
"APP_GLOBAL": {
|
||||
|
@ -159,5 +160,30 @@
|
|||
},
|
||||
"SUBMIT": "Submit"
|
||||
}
|
||||
},
|
||||
"KEYBOARD_SHORTCUTS": {
|
||||
"TITLE": {
|
||||
"OPEN_CONVERSATION": "Open conversation",
|
||||
"RESOLVE_AND_NEXT": "Resolve and move to next",
|
||||
"NAVIGATE_DROPDOWN": "Navigate dropdown items",
|
||||
"RESOLVE_CONVERSATION": "Resolve Conversation",
|
||||
"GO_TO_CONVERSATION_DASHBOARD": "Go to Conversation Dashboard",
|
||||
"ADD_ATTACHMENT": "Add Attachment",
|
||||
"GO_TO_CONTACTS_DASHBOARD": "Go to Contacts Dashboard",
|
||||
"TOGGLE_SIDEBAR": "Toggle Sidebar",
|
||||
"GO_TO_REPORTS_SIDEBAR": "Go to Reports sidebar",
|
||||
"MOVE_TO_NEXT_TAB": "Move to next tab in conversation list",
|
||||
"GO_TO_SETTINGS": "Go to Settings",
|
||||
"SWITCH_CONVERSATION_STATUS": "Switch Conversation status",
|
||||
"SWITCH_TO_PRIVATE_NOTE": "Switch to Private Note",
|
||||
"TOGGLE_RICH_CONTENT_EDITOR": "Toggle Rich Content editor",
|
||||
"SWITCH_TO_REPLY": "Switch to Reply",
|
||||
"TOGGLE_SNOOZE_DROPDOWN": "Toggle snooze dropdown"
|
||||
},
|
||||
"KEYS": {
|
||||
"COMMAND_KEY": "⌘",
|
||||
"ALT_OR_OPTION_KEY": "Alt / ⌥",
|
||||
"FORWARD_SLASH_KEY": "/"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,6 +10,10 @@ export const hasPressedShift = e => {
|
|||
return e.shiftKey;
|
||||
};
|
||||
|
||||
export const hasPressedCommandAndForwardSlash = e => {
|
||||
return e.metaKey && e.keyCode === 191;
|
||||
};
|
||||
|
||||
export const hasPressedAltAndCKey = e => {
|
||||
return e.altKey && e.keyCode === 67;
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue