Compare commits

...

1 commit

Author SHA1 Message Date
Pranav Raj S
ead7a5fc87 feat: Link to a message 2022-11-09 19:11:20 -08:00
7 changed files with 78 additions and 13 deletions

View file

@ -20,11 +20,22 @@ class MessageFinder
conversation_messages.where.not('private = ? OR message_type = ?', true, 2) conversation_messages.where.not('private = ? OR message_type = ?', true, 2)
end end
def messages_in_desc_order
messages.reorder('created_at desc')
end
def current_messages def current_messages
messages_to_display = messages_in_desc_order
if @params[:before].present? if @params[:before].present?
messages.reorder('created_at desc').where('id < ?', @params[:before].to_i).limit(20).reverse messages_to_display = messages_to_display.where('id < ?', @params[:before].to_i)
else
messages.reorder('created_at desc').limit(20).reverse if @params[:after].present? && @params[:after].to_i < @params[:before].to_i - 25
messages_to_display = messages_to_display.where('id >= ?', @params[:after].to_i)
return messages_to_display.reverse
end
end end
messages_to_display.limit(20).reverse
end end
end end

View file

@ -75,9 +75,9 @@ class MessageApi extends ApiClient {
return axios.delete(`${this.url}/${conversationID}/messages/${messageId}`); return axios.delete(`${this.url}/${conversationID}/messages/${messageId}`);
} }
getPreviousMessages({ conversationId, before }) { getPreviousMessages({ conversationId, after, before }) {
return axios.get(`${this.url}/${conversationId}/messages`, { return axios.get(`${this.url}/${conversationId}/messages`, {
params: { before }, params: { after, before },
}); });
} }
} }

View file

@ -1,6 +1,7 @@
<template> <template>
<li <li
v-if="hasAttachments || data.content || isEmailContentType" v-if="hasAttachments || data.content || isEmailContentType"
:id="'message' + data.id"
:class="alignBubble" :class="alignBubble"
> >
<div :class="wrapClass"> <div :class="wrapClass">
@ -104,8 +105,10 @@
<div v-if="shouldShowContextMenu" class="context-menu-wrap"> <div v-if="shouldShowContextMenu" class="context-menu-wrap">
<context-menu <context-menu
v-if="isBubble && !isMessageDeleted" v-if="isBubble && !isMessageDeleted"
:id="data.id"
:is-open="showContextMenu" :is-open="showContextMenu"
:show-copy="hasText" :show-copy="hasText"
:conversation-id="data.conversation_id"
:show-canned-response-option="isOutgoing" :show-canned-response-option="isOutgoing"
:menu-position="contextMenuPosition" :menu-position="contextMenuPosition"
:message-content="data.content" :message-content="data.content"

View file

@ -304,8 +304,15 @@ export default {
setSelectedTweet(tweetId) { setSelectedTweet(tweetId) {
this.selectedTweetId = tweetId; this.selectedTweetId = tweetId;
}, },
onScrollToMessage() { onScrollToMessage({ messageId = '' } = {}) {
this.$nextTick(() => this.scrollToBottom()); this.$nextTick(() => {
const messageElement = document.getElementById('message' + messageId);
if (messageElement) {
messageElement.scrollIntoView({ behavior: 'smooth' });
} else {
this.scrollToBottom();
}
});
this.makeMessagesRead(); this.makeMessagesRead();
}, },
showPopoutReplyBox() { showPopoutReplyBox() {

View file

@ -47,6 +47,18 @@
</woot-button> </woot-button>
</woot-dropdown-item> </woot-dropdown-item>
<woot-dropdown-item>
<woot-button
variant="clear"
size="small"
icon="link"
color-scheme="secondary"
@click="copyLinkToMessage"
>
Copy Permalink
</woot-button>
</woot-dropdown-item>
<woot-dropdown-item> <woot-dropdown-item>
<woot-button <woot-button
v-if="showCannedResponseOption" v-if="showCannedResponseOption"
@ -72,6 +84,8 @@ import AddCannedModal from 'dashboard/routes/dashboard/settings/canned/AddCanned
import WootDropdownItem from 'shared/components/ui/dropdown/DropdownItem'; import WootDropdownItem from 'shared/components/ui/dropdown/DropdownItem';
import WootDropdownMenu from 'shared/components/ui/dropdown/DropdownMenu'; import WootDropdownMenu from 'shared/components/ui/dropdown/DropdownMenu';
import { copyTextToClipboard } from 'shared/helpers/clipboard'; import { copyTextToClipboard } from 'shared/helpers/clipboard';
import { conversationUrl, frontendURL } from '../../../helper/URLHelper';
import { mapGetters } from 'vuex';
export default { export default {
components: { components: {
@ -101,11 +115,22 @@ export default {
type: Boolean, type: Boolean,
default: true, default: true,
}, },
conversationId: {
type: Number,
required: true,
},
id: {
type: Number,
required: true,
},
}, },
data() { data() {
return { isCannedResponseModalOpen: false }; return { isCannedResponseModalOpen: false };
}, },
computed: { computed: {
...mapGetters({
currentAccountId: 'getCurrentAccountId',
}),
plainTextContent() { plainTextContent() {
return this.getPlainText(this.messageContent); return this.getPlainText(this.messageContent);
}, },
@ -114,6 +139,19 @@ export default {
handleContextMenuClick() { handleContextMenuClick() {
this.$emit('toggle', !this.isOpen); this.$emit('toggle', !this.isOpen);
}, },
async copyLinkToMessage() {
await copyTextToClipboard(
frontendURL(
conversationUrl({
id: this.conversationId,
accountId: this.currentAccountId,
}) +
'?messageId=' +
this.id
)
);
this.showAlert('Link Copied');
},
async handleCopy() { async handleCopy() {
await copyTextToClipboard(this.plainTextContent); await copyTextToClipboard(this.plainTextContent);
this.showAlert(this.$t('CONTACT_PANEL.COPY_SUCCESSFUL')); this.showAlert(this.$t('CONTACT_PANEL.COPY_SUCCESSFUL'));

View file

@ -160,9 +160,15 @@ export default {
) { ) {
return; return;
} }
this.$store.dispatch('setActiveChat', selectedConversation).then(() => { const { message_id: messageId } = this.$route.query;
bus.$emit(BUS_EVENTS.SCROLL_TO_MESSAGE); this.$store
}); .dispatch('setActiveChat', {
data: selectedConversation,
after: messageId,
})
.then(() => {
bus.$emit(BUS_EVENTS.SCROLL_TO_MESSAGE, { messageId });
});
} else { } else {
this.$store.dispatch('clearSelectedState'); this.$store.dispatch('clearSelectedState');
} }

View file

@ -82,15 +82,15 @@ const actions = {
} }
}, },
async setActiveChat({ commit, dispatch }, data) { async setActiveChat({ commit, dispatch }, { data, after }) {
commit(types.SET_CURRENT_CHAT_WINDOW, data); commit(types.SET_CURRENT_CHAT_WINDOW, data);
commit(types.CLEAR_ALL_MESSAGES_LOADED); commit(types.CLEAR_ALL_MESSAGES_LOADED);
if (data.dataFetched === undefined) { if (data.dataFetched === undefined) {
try { try {
await dispatch('fetchPreviousMessages', { await dispatch('fetchPreviousMessages', {
conversationId: data.id, after,
before: data.messages[0].id, before: data.messages[0].id,
conversationId: data.id,
}); });
Vue.set(data, 'dataFetched', true); Vue.set(data, 'dataFetched', true);
} catch (error) { } catch (error) {