From cbae95422ddcbc0ee9c6b7d10cda8348283b3b68 Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Tue, 10 Oct 2023 19:13:12 +0530 Subject: [PATCH] feat: Implement reply to for reply editor (#8063) Co-authored-by: Pranav Raj S --- .../widgets/conversation/Message.vue | 10 +- .../widgets/conversation/ReplyBox.vue | 63 ++++++++++- .../widgets/conversation/ReplyToMessage.vue | 48 ++++++++ .../dashboard/constants/localStorage.js | 1 + .../i18n/locale/en/conversation.json | 2 + .../shared/components/EmojiOrIcon.vue | 1 + app/javascript/shared/constants/busEvents.js | 1 + app/javascript/shared/helpers/localStorage.js | 37 +++++- .../shared/helpers/specs/localStorage.spec.js | 107 ++++++++++++++++++ 9 files changed, 265 insertions(+), 5 deletions(-) create mode 100644 app/javascript/dashboard/components/widgets/conversation/ReplyToMessage.vue create mode 100644 app/javascript/shared/helpers/specs/localStorage.spec.js diff --git a/app/javascript/dashboard/components/widgets/conversation/Message.vue b/app/javascript/dashboard/components/widgets/conversation/Message.vue index 32ad10bd4..35feab802 100644 --- a/app/javascript/dashboard/components/widgets/conversation/Message.vue +++ b/app/javascript/dashboard/components/widgets/conversation/Message.vue @@ -150,6 +150,8 @@ import { MESSAGE_TYPE, MESSAGE_STATUS } from 'shared/constants/messages'; import { generateBotMessageContent } from './helpers/botMessageContentHelper'; import { BUS_EVENTS } from 'shared/constants/busEvents'; import { ACCOUNT_EVENTS } from 'dashboard/helper/AnalyticsHelper/events'; +import { LOCAL_STORAGE_KEYS } from 'dashboard/constants/localStorage'; +import { LocalStorage } from 'shared/helpers/localStorage'; export default { components: { @@ -502,7 +504,13 @@ export default { this.showContextMenu = false; this.contextMenuPosition = { x: null, y: null }; }, - handleReplyTo() {}, + handleReplyTo() { + const replyStorageKey = LOCAL_STORAGE_KEYS.MESSAGE_REPLY_TO; + const { conversation_id: conversationId, id: replyTo } = this.data; + + LocalStorage.updateJsonStore(replyStorageKey, conversationId, replyTo); + bus.$emit(BUS_EVENTS.TOGGLE_REPLY_TO_MESSAGE, this.data); + }, setupHighlightTimer() { if (Number(this.$route.query.messageId) !== Number(this.data.id)) { return; diff --git a/app/javascript/dashboard/components/widgets/conversation/ReplyBox.vue b/app/javascript/dashboard/components/widgets/conversation/ReplyBox.vue index 864f9b805..b1a407410 100644 --- a/app/javascript/dashboard/components/widgets/conversation/ReplyBox.vue +++ b/app/javascript/dashboard/components/widgets/conversation/ReplyBox.vue @@ -19,6 +19,13 @@ @click="$emit('click')" />
+ import('shared/components/emoji/EmojiInput'); @@ -185,6 +197,7 @@ export default { components: { EmojiInput, CannedResponse, + ReplyToMessage, ResizableTextArea, AttachmentPreview, ReplyTopPanel, @@ -214,6 +227,7 @@ export default { data() { return { message: '', + inReplyTo: {}, isFocused: false, showEmojiPicker: false, attachedFiles: [], @@ -246,7 +260,19 @@ export default { lastEmail: 'getLastEmailInSelectedChat', globalConfig: 'globalConfig/get', accountId: 'getCurrentAccountId', + isFeatureEnabledonAccount: 'accounts/isFeatureEnabledonAccount', }), + shouldShowReplyToMessage() { + return ( + this.inReplyTo?.id && + !this.isPrivate && + this.inboxHasFeature(INBOX_FEATURES.REPLY_TO) && + this.isFeatureEnabledonAccount( + this.accountId, + FEATURE_FLAGS.MESSAGE_REPLY_TO + ) + ); + }, showRichContentEditor() { if (this.isOnPrivateNote || this.isRichEditorEnabled) { return true; @@ -540,6 +566,9 @@ export default { true ); + this.fetchAndSetReplyTo(); + bus.$on(BUS_EVENTS.TOGGLE_REPLY_TO_MESSAGE, this.fetchAndSetReplyTo); + // A hacky fix to solve the drag and drop // Is showing on top of new conversation modal drag and drop // TODO need to find a better solution @@ -551,6 +580,7 @@ export default { destroyed() { document.removeEventListener('paste', this.onPaste); document.removeEventListener('keydown', this.handleKeyEvents); + bus.$off(BUS_EVENTS.TOGGLE_REPLY_TO_MESSAGE, this.fetchAndSetReplyTo); }, beforeDestroy() { bus.$off( @@ -841,6 +871,7 @@ export default { } this.attachedFiles = []; this.isRecordingAudio = false; + this.resetReplyToMessage(); }, clearEmailField() { this.ccEmails = ''; @@ -972,8 +1003,10 @@ export default { sender: this.sender, }; - if (this.inReplyTo) { - messagePayload.contentAttributes = { in_reply_to: this.inReplyTo }; + if (this.inReplyTo?.id) { + messagePayload.contentAttributes = { + in_reply_to: this.inReplyTo.id, + }; } if (this.attachedFiles && this.attachedFiles.length) { @@ -1046,6 +1079,30 @@ export default { this.bccEmails = bcc.join(', '); this.toEmails = to.join(', '); }, + fetchAndSetReplyTo() { + const replyStorageKey = LOCAL_STORAGE_KEYS.MESSAGE_REPLY_TO; + const replyToMessageId = LocalStorage.getFromJsonStore( + replyStorageKey, + this.conversationId + ); + + this.inReplyTo = this.currentChat.messages.find(message => { + if (message.id === replyToMessageId) { + return true; + } + return false; + }); + }, + resetReplyToMessage() { + const replyStorageKey = LOCAL_STORAGE_KEYS.MESSAGE_REPLY_TO; + LocalStorage.deleteFromJsonStore(replyStorageKey, this.conversationId); + bus.$emit(BUS_EVENTS.TOGGLE_REPLY_TO_MESSAGE); + }, + navigateToMessage(messageId) { + this.$nextTick(() => { + bus.$emit(BUS_EVENTS.SCROLL_TO_MESSAGE, { messageId }); + }); + }, onNewConversationModalActive(isActive) { // Issue is if the new conversation modal is open and we drag and drop the file // then the file is not getting attached to the new conversation modal diff --git a/app/javascript/dashboard/components/widgets/conversation/ReplyToMessage.vue b/app/javascript/dashboard/components/widgets/conversation/ReplyToMessage.vue new file mode 100644 index 000000000..528ffef95 --- /dev/null +++ b/app/javascript/dashboard/components/widgets/conversation/ReplyToMessage.vue @@ -0,0 +1,48 @@ + + + + + diff --git a/app/javascript/dashboard/constants/localStorage.js b/app/javascript/dashboard/constants/localStorage.js index 21360e178..ee6a4357a 100644 --- a/app/javascript/dashboard/constants/localStorage.js +++ b/app/javascript/dashboard/constants/localStorage.js @@ -4,4 +4,5 @@ export const LOCAL_STORAGE_KEYS = { DRAFT_MESSAGES: 'draftMessages', COLOR_SCHEME: 'color_scheme', DISMISSED_LABEL_SUGGESTIONS: 'labelSuggestionsDismissed', + MESSAGE_REPLY_TO: 'messageReplyTo', }; diff --git a/app/javascript/dashboard/i18n/locale/en/conversation.json b/app/javascript/dashboard/i18n/locale/en/conversation.json index ff50b1240..6a2d8a7ac 100644 --- a/app/javascript/dashboard/i18n/locale/en/conversation.json +++ b/app/javascript/dashboard/i18n/locale/en/conversation.json @@ -138,6 +138,8 @@ "PRIVATE_NOTE": "Private Note", "SEND": "Send", "CREATE": "Add Note", + "DISMISS_REPLY": "Dismiss reply", + "REPLYING_TO": "Replying to:", "TIP_FORMAT_ICON": "Show rich text editor", "TIP_EMOJI_ICON": "Show emoji selector", "TIP_ATTACH_ICON": "Attach files", diff --git a/app/javascript/shared/components/EmojiOrIcon.vue b/app/javascript/shared/components/EmojiOrIcon.vue index be06100e0..5cde463fe 100644 --- a/app/javascript/shared/components/EmojiOrIcon.vue +++ b/app/javascript/shared/components/EmojiOrIcon.vue @@ -9,6 +9,7 @@