From faf104c1fefc7a9a4ea606f11b8ead4eebc7b916 Mon Sep 17 00:00:00 2001 From: Pranav Raj S Date: Mon, 2 Aug 2021 16:07:30 +0530 Subject: [PATCH] fix: Update tweet character count logic (#2709) --- app/javascript/dashboard/api/inbox/message.js | 43 +++++++++++---- .../dashboard/api/specs/inbox/message.spec.js | 32 +++++++++++- .../widgets/conversation/ConversationBox.vue | 4 +- .../widgets/conversation/Message.vue | 1 + .../widgets/conversation/MessagesView.vue | 13 ++--- .../widgets/conversation/ReplyBox.vue | 36 ++++++++++--- .../widgets/conversation/bubble/Actions.vue | 27 ++++++++-- .../i18n/locale/en/conversation.json | 2 +- .../twitter/send_on_twitter_service.rb | 2 + .../twitter/send_on_twitter_service_spec.rb | 52 ++++++++++++++++--- 10 files changed, 174 insertions(+), 38 deletions(-) diff --git a/app/javascript/dashboard/api/inbox/message.js b/app/javascript/dashboard/api/inbox/message.js index 84e77fb8b..98c250e60 100644 --- a/app/javascript/dashboard/api/inbox/message.js +++ b/app/javascript/dashboard/api/inbox/message.js @@ -2,6 +2,33 @@ /* global axios */ import ApiClient from '../ApiClient'; +export const buildCreatePayload = ({ + message, + isPrivate, + contentAttributes, + echoId, + file, +}) => { + let payload; + if (file) { + payload = new FormData(); + payload.append('attachments[]', file, file.name); + if (message) { + payload.append('content', message); + } + payload.append('private', isPrivate); + payload.append('echo_id', echoId); + } else { + payload = { + content: message, + private: isPrivate, + echo_id: echoId, + content_attributes: contentAttributes, + }; + } + return payload; +}; + class MessageApi extends ApiClient { constructor() { super('conversations', { accountScoped: true }); @@ -15,18 +42,16 @@ class MessageApi extends ApiClient { echo_id: echoId, file, }) { - const formData = new FormData(); - if (file) formData.append('attachments[]', file, file.name); - if (message) formData.append('content', message); - if (contentAttributes) - formData.append('content_attributes', JSON.stringify(contentAttributes)); - - formData.append('private', isPrivate); - formData.append('echo_id', echoId); return axios({ method: 'post', url: `${this.url}/${conversationId}/messages`, - data: formData, + data: buildCreatePayload({ + message, + isPrivate, + contentAttributes, + echoId, + file, + }), }); } diff --git a/app/javascript/dashboard/api/specs/inbox/message.spec.js b/app/javascript/dashboard/api/specs/inbox/message.spec.js index dd4814f23..ca8d313b4 100644 --- a/app/javascript/dashboard/api/specs/inbox/message.spec.js +++ b/app/javascript/dashboard/api/specs/inbox/message.spec.js @@ -1,4 +1,4 @@ -import messageAPI from '../../inbox/message'; +import messageAPI, { buildCreatePayload } from '../../inbox/message'; import ApiClient from '../../ApiClient'; import describeWithAPIMock from '../apiSpecHelper'; @@ -29,4 +29,34 @@ describe('#ConversationAPI', () => { ); }); }); + describe('#buildCreatePayload', () => { + it('builds form payload if file is available', () => { + const formPayload = buildCreatePayload({ + message: 'test content', + echoId: 12, + isPrivate: true, + file: new Blob(['test-content'], { type: 'application/pdf' }), + }); + expect(formPayload).toBeInstanceOf(FormData); + expect(formPayload.get('content')).toEqual('test content'); + expect(formPayload.get('echo_id')).toEqual('12'); + expect(formPayload.get('private')).toEqual('true'); + }); + + it('builds object payload if file is not available', () => { + expect( + buildCreatePayload({ + message: 'test content', + isPrivate: false, + echoId: 12, + contentAttributes: { in_reply_to: 12 }, + }) + ).toEqual({ + content: 'test content', + private: false, + echo_id: 12, + content_attributes: { in_reply_to: 12 }, + }); + }); + }); }); diff --git a/app/javascript/dashboard/components/widgets/conversation/ConversationBox.vue b/app/javascript/dashboard/components/widgets/conversation/ConversationBox.vue index 440f6e1e5..01c21c53f 100644 --- a/app/javascript/dashboard/components/widgets/conversation/ConversationBox.vue +++ b/app/javascript/dashboard/components/widgets/conversation/ConversationBox.vue @@ -53,9 +53,7 @@ export default { }, }, computed: { - ...mapGetters({ - currentChat: 'getSelectedChat', - }), + ...mapGetters({ currentChat: 'getSelectedChat' }), showContactPanel() { return this.isContactPanelOpen && this.currentChat.id; }, diff --git a/app/javascript/dashboard/components/widgets/conversation/Message.vue b/app/javascript/dashboard/components/widgets/conversation/Message.vue index 029ab5e6a..c519f99e9 100644 --- a/app/javascript/dashboard/components/widgets/conversation/Message.vue +++ b/app/javascript/dashboard/components/widgets/conversation/Message.vue @@ -46,6 +46,7 @@ :message-type="data.message_type" :readable-time="readableTime" :source-id="data.source_id" + :inbox-id="data.inbox_id" /> diff --git a/app/javascript/dashboard/components/widgets/conversation/MessagesView.vue b/app/javascript/dashboard/components/widgets/conversation/MessagesView.vue index 3f8fda58d..9b2c39996 100644 --- a/app/javascript/dashboard/components/widgets/conversation/MessagesView.vue +++ b/app/javascript/dashboard/components/widgets/conversation/MessagesView.vue @@ -33,11 +33,11 @@ - @@ -207,10 +208,10 @@ export default { selectedTweet() { if (this.selectedTweetId) { const { messages = [] } = this.getMessages; - const [selectedMessage = {}] = messages.filter( + const [selectedMessage] = messages.filter( message => message.id === this.selectedTweetId ); - return selectedMessage.content || ''; + return selectedMessage || {}; } return ''; }, diff --git a/app/javascript/dashboard/components/widgets/conversation/ReplyBox.vue b/app/javascript/dashboard/components/widgets/conversation/ReplyBox.vue index 9a2434fbf..ee2929743 100644 --- a/app/javascript/dashboard/components/widgets/conversation/ReplyBox.vue +++ b/app/javascript/dashboard/components/widgets/conversation/ReplyBox.vue @@ -107,9 +107,13 @@ export default { }, mixins: [clickaway, inboxMixin, uiSettingsMixin, alertMixin], props: { - inReplyTo: { - type: [String, Number], - default: '', + selectedTweet: { + type: [Object, String], + default: () => ({}), + }, + isATweet: { + type: Boolean, + default: false, }, }, data() { @@ -169,11 +173,14 @@ export default { return this.maxLength - this.message.length; }, isReplyButtonDisabled() { - const isMessageEmpty = this.isMessageEmpty; + if (this.isATweet && !this.inReplyTo) { + return true; + } if (this.hasAttachments) return false; + return ( - isMessageEmpty || + this.isMessageEmpty || this.message.length === 0 || this.message.length > this.maxLength ); @@ -198,7 +205,7 @@ export default { } if (this.isATwitterInbox) { if (this.conversationType === 'tweet') { - return MESSAGE_MAX_LENGTH.TWEET; + return MESSAGE_MAX_LENGTH.TWEET - this.replyToUserLength - 2; } } return MESSAGE_MAX_LENGTH.GENERAL; @@ -235,9 +242,22 @@ export default { isOnPrivateNote() { return this.replyType === REPLY_EDITOR_MODES.NOTE; }, + inReplyTo() { + const selectedTweet = this.selectedTweet || {}; + return selectedTweet.id; + }, + replyToUserLength() { + const selectedTweet = this.selectedTweet || {}; + const { + sender: { + additional_attributes: { screen_name: screenName = '' } = {}, + } = {}, + } = selectedTweet; + return screenName ? screenName.length : 0; + }, isMessageEmpty() { - if(!this.message) { - this.message = ''; + if (!this.message) { + return true; } return !this.message.trim().replace(/\n/g, '').length; }, diff --git a/app/javascript/dashboard/components/widgets/conversation/bubble/Actions.vue b/app/javascript/dashboard/components/widgets/conversation/bubble/Actions.vue index 8c6954672..59a0a9896 100644 --- a/app/javascript/dashboard/components/widgets/conversation/bubble/Actions.vue +++ b/app/javascript/dashboard/components/widgets/conversation/bubble/Actions.vue @@ -14,13 +14,13 @@ @mouseleave="isHovered = false" />