From beedfc47bfde31545ab67cfa7c0c8d4007ad040f Mon Sep 17 00:00:00 2001 From: Sivin Varghese <64252451+iamsivin@users.noreply.github.com> Date: Tue, 4 Oct 2022 03:57:34 +0530 Subject: [PATCH] feat: Allow users to select `Cmd+Enter` as a hotkey (#4401) Co-authored-by: Pranav Raj S --- .../dashboard/components/ui/PreviewCard.vue | 113 ++++++++++++++++++ .../widgets/WootWriter/ReplyBottomPanel.vue | 32 ----- .../widgets/conversation/ReplyBox.vue | 100 ++++++++-------- .../i18n/locale/en/conversation.json | 1 - .../dashboard/i18n/locale/en/settings.json | 15 +++ .../dashboard/mixins/specs/uiSettings.spec.js | 24 ++++ app/javascript/dashboard/mixins/uiSettings.js | 19 ++- .../dashboard/settings/profile/Index.vue | 77 +++++++++++- .../settings/profile/MessageSignature.vue | 2 +- .../settings/profile/NotificationSettings.vue | 6 +- .../shared/helpers/KeyboardHelpers.js | 26 ++++ .../helpers/specs/KeyboardHelpers.spec.js | 22 +++- .../images/dashboard/editor/cmd-editor.png | Bin 0 -> 149362 bytes .../images/dashboard/editor/enter-editor.png | Bin 0 -> 147829 bytes 14 files changed, 344 insertions(+), 93 deletions(-) create mode 100644 app/javascript/dashboard/components/ui/PreviewCard.vue create mode 100644 public/assets/images/dashboard/editor/cmd-editor.png create mode 100644 public/assets/images/dashboard/editor/enter-editor.png diff --git a/app/javascript/dashboard/components/ui/PreviewCard.vue b/app/javascript/dashboard/components/ui/PreviewCard.vue new file mode 100644 index 000000000..751a070a5 --- /dev/null +++ b/app/javascript/dashboard/components/ui/PreviewCard.vue @@ -0,0 +1,113 @@ + + + + + diff --git a/app/javascript/dashboard/components/widgets/WootWriter/ReplyBottomPanel.vue b/app/javascript/dashboard/components/widgets/WootWriter/ReplyBottomPanel.vue index 74cd9de4d..9ace1ceb2 100644 --- a/app/javascript/dashboard/components/widgets/WootWriter/ReplyBottomPanel.vue +++ b/app/javascript/dashboard/components/widgets/WootWriter/ReplyBottomPanel.vue @@ -91,17 +91,6 @@
-
- - -
{ }); }); }); + +describe('isEditorHotKeyEnabled', () => { + it('returns true if hot key is not configured and enter to send flag is true', () => { + expect( + isEditorHotKeyEnabled({ enter_to_send_enabled: true }, 'enter') + ).toEqual(true); + expect( + isEditorHotKeyEnabled({ enter_to_send_enabled: true }, 'cmd_enter') + ).toEqual(false); + + expect(isEditorHotKeyEnabled({}, 'cmd_enter')).toEqual(true); + expect(isEditorHotKeyEnabled({}, 'enter')).toEqual(false); + }); + + it('returns correct value if hot key is configured', () => { + expect( + isEditorHotKeyEnabled({ editor_message_key: 'enter' }, 'enter') + ).toEqual(true); + expect( + isEditorHotKeyEnabled({ editor_message_key: 'cmd_enter' }, 'enter') + ).toEqual(false); + }); +}); diff --git a/app/javascript/dashboard/mixins/uiSettings.js b/app/javascript/dashboard/mixins/uiSettings.js index e265975e1..adc407eb3 100644 --- a/app/javascript/dashboard/mixins/uiSettings.js +++ b/app/javascript/dashboard/mixins/uiSettings.js @@ -10,11 +10,24 @@ export const DEFAULT_CONTACT_SIDEBAR_ITEMS_ORDER = [ { name: 'contact_labels' }, { name: 'previous_conversation' }, ]; + +export const isEditorHotKeyEnabled = (uiSettings, key) => { + const { + editor_message_key: editorMessageKey, + enter_to_send_enabled: enterToSendEnabled, + } = uiSettings || {}; + if (!editorMessageKey) { + if (enterToSendEnabled) { + return key === 'enter'; + } + return key === 'cmd_enter'; + } + return editorMessageKey === key; +}; + export default { computed: { - ...mapGetters({ - uiSettings: 'getUISettings', - }), + ...mapGetters({ uiSettings: 'getUISettings' }), conversationSidebarItemsOrder() { const { conversation_sidebar_items_order: itemsOrder } = this.uiSettings; return itemsOrder || DEFAULT_CONVERSATION_SIDEBAR_ITEMS_ORDER; diff --git a/app/javascript/dashboard/routes/dashboard/settings/profile/Index.vue b/app/javascript/dashboard/routes/dashboard/settings/profile/Index.vue index 53152f09d..23b5425e2 100644 --- a/app/javascript/dashboard/routes/dashboard/settings/profile/Index.vue +++ b/app/javascript/dashboard/routes/dashboard/settings/profile/Index.vue @@ -70,6 +70,31 @@
+
+
+

+ {{ $t('PROFILE_SETTINGS.FORM.SEND_MESSAGE.TITLE') }} +

+

+ {{ $t('PROFILE_SETTINGS.FORM.SEND_MESSAGE.NOTE') }} +

+
+
+ +
+
@@ -102,14 +127,19 @@ import alertMixin from 'shared/mixins/alertMixin'; import ChangePassword from './ChangePassword'; import MessageSignature from './MessageSignature'; import globalConfigMixin from 'shared/mixins/globalConfigMixin'; +import uiSettingsMixin, { + isEditorHotKeyEnabled, +} from 'dashboard/mixins/uiSettings'; +import PreviewCard from 'dashboard/components/ui/PreviewCard.vue'; export default { components: { NotificationSettings, ChangePassword, MessageSignature, + PreviewCard, }, - mixins: [alertMixin, globalConfigMixin], + mixins: [alertMixin, globalConfigMixin, uiSettingsMixin], data() { return { avatarFile: '', @@ -119,6 +149,28 @@ export default { email: '', isProfileUpdating: false, errorMessage: '', + keyOptions: [ + { + key: 'enter', + src: '/assets/images/dashboard/editor/enter-editor.png', + heading: this.$t( + 'PROFILE_SETTINGS.FORM.SEND_MESSAGE.CARD.ENTER_KEY.HEADING' + ), + content: this.$t( + 'PROFILE_SETTINGS.FORM.SEND_MESSAGE.CARD.ENTER_KEY.CONTENT' + ), + }, + { + key: 'cmd_enter', + src: '/assets/images/dashboard/editor/cmd-editor.png', + heading: this.$t( + 'PROFILE_SETTINGS.FORM.SEND_MESSAGE.CARD.CMD_ENTER_KEY.HEADING' + ), + content: this.$t( + 'PROFILE_SETTINGS.FORM.SEND_MESSAGE.CARD.CMD_ENTER_KEY.CONTENT' + ), + }, + ], }; }, validations: { @@ -158,6 +210,7 @@ export default { this.avatarUrl = this.currentUser.avatar_url; this.displayName = this.currentUser.display_name; }, + isEditorHotKeyEnabled, async updateUser() { this.$v.$touch(); if (this.$v.$invalid) { @@ -207,6 +260,12 @@ export default { showDeleteButton() { return this.avatarUrl && !this.avatarUrl.includes('www.gravatar.com'); }, + toggleEditorMessageKey(key) { + this.updateUISettings({ editor_message_key: key }); + this.showAlert( + this.$t('PROFILE_SETTINGS.FORM.SEND_MESSAGE.UPDATE_SUCCESS') + ); + }, }, }; @@ -216,18 +275,32 @@ export default { @import '~dashboard/assets/scss/mixins.scss'; .profile--settings { - padding: 24px; overflow: auto; + padding: 24px; } .profile--settings--row { @include border-normal-bottom; + align-items: center; + display: flex; padding: $space-normal; + .small-3 { padding: $space-normal $space-medium $space-normal 0; } + .small-9 { padding: $space-normal; } + + .card-preview { + display: flex; + flex-direction: row; + + .preview-button { + cursor: pointer; + margin-right: var(--space-normal); + } + } } diff --git a/app/javascript/dashboard/routes/dashboard/settings/profile/MessageSignature.vue b/app/javascript/dashboard/routes/dashboard/settings/profile/MessageSignature.vue index e08e4fdee..557f239dc 100644 --- a/app/javascript/dashboard/routes/dashboard/settings/profile/MessageSignature.vue +++ b/app/javascript/dashboard/routes/dashboard/settings/profile/MessageSignature.vue @@ -77,7 +77,7 @@ export default { methods: { initValues() { const { message_signature: messageSignature } = this.currentUser; - this.messageSignature = messageSignature; + this.messageSignature = messageSignature || ''; }, async updateSignature() { this.$v.$touch(); diff --git a/app/javascript/dashboard/routes/dashboard/settings/profile/NotificationSettings.vue b/app/javascript/dashboard/routes/dashboard/settings/profile/NotificationSettings.vue index bbf92b43d..60584d726 100644 --- a/app/javascript/dashboard/routes/dashboard/settings/profile/NotificationSettings.vue +++ b/app/javascript/dashboard/routes/dashboard/settings/profile/NotificationSettings.vue @@ -154,7 +154,7 @@ ) }}

-
+