mirror of
https://github.com/lingble/chatwoot.git
synced 2025-10-31 19:17:48 +00:00
Fixes https://github.com/chatwoot/chatwoot/issues/8436 Fixes https://github.com/chatwoot/chatwoot/issues/9767 Fixes https://github.com/chatwoot/chatwoot/issues/10156 Fixes https://github.com/chatwoot/chatwoot/issues/6031 Fixes https://github.com/chatwoot/chatwoot/issues/5696 Fixes https://github.com/chatwoot/chatwoot/issues/9250 Fixes https://github.com/chatwoot/chatwoot/issues/9762 --------- Co-authored-by: Pranav <pranavrajs@gmail.com> Co-authored-by: Sivin Varghese <64252451+iamsivin@users.noreply.github.com>
179 lines
4.8 KiB
Vue
Executable File
179 lines
4.8 KiB
Vue
Executable File
<script>
|
|
import { mapActions, mapGetters } from 'vuex';
|
|
import { getContrastingTextColor } from '@chatwoot/utils';
|
|
import CustomButton from 'shared/components/Button.vue';
|
|
import FooterReplyTo from 'widget/components/FooterReplyTo.vue';
|
|
import ChatInputWrap from 'widget/components/ChatInputWrap.vue';
|
|
import { BUS_EVENTS } from 'shared/constants/busEvents';
|
|
import { sendEmailTranscript } from 'widget/api/conversation';
|
|
import routerMixin from 'widget/mixins/routerMixin';
|
|
import { IFrameHelper } from '../helpers/utils';
|
|
import { CHATWOOT_ON_START_CONVERSATION } from '../constants/sdkEvents';
|
|
import { emitter } from 'shared/helpers/mitt';
|
|
|
|
export default {
|
|
components: {
|
|
ChatInputWrap,
|
|
CustomButton,
|
|
FooterReplyTo,
|
|
},
|
|
mixins: [routerMixin],
|
|
data() {
|
|
return {
|
|
inReplyTo: null,
|
|
};
|
|
},
|
|
computed: {
|
|
...mapGetters({
|
|
conversationAttributes: 'conversationAttributes/getConversationParams',
|
|
widgetColor: 'appConfig/getWidgetColor',
|
|
conversationSize: 'conversation/getConversationSize',
|
|
currentUser: 'contacts/getCurrentUser',
|
|
isWidgetStyleFlat: 'appConfig/isWidgetStyleFlat',
|
|
}),
|
|
textColor() {
|
|
return getContrastingTextColor(this.widgetColor);
|
|
},
|
|
hideReplyBox() {
|
|
const { allowMessagesAfterResolved } = window.chatwootWebChannel;
|
|
const { status } = this.conversationAttributes;
|
|
return !allowMessagesAfterResolved && status === 'resolved';
|
|
},
|
|
showEmailTranscriptButton() {
|
|
return this.hasEmail;
|
|
},
|
|
hasEmail() {
|
|
return this.currentUser && this.currentUser.has_email;
|
|
},
|
|
hasReplyTo() {
|
|
return (
|
|
this.inReplyTo && (this.inReplyTo.content || this.inReplyTo.attachments)
|
|
);
|
|
},
|
|
},
|
|
mounted() {
|
|
emitter.on(BUS_EVENTS.TOGGLE_REPLY_TO_MESSAGE, this.toggleReplyTo);
|
|
},
|
|
methods: {
|
|
...mapActions('conversation', [
|
|
'sendMessage',
|
|
'sendAttachment',
|
|
'clearConversations',
|
|
]),
|
|
...mapActions('conversationAttributes', [
|
|
'getAttributes',
|
|
'clearConversationAttributes',
|
|
]),
|
|
async handleSendMessage(content) {
|
|
await this.sendMessage({
|
|
content,
|
|
replyTo: this.inReplyTo ? this.inReplyTo.id : null,
|
|
});
|
|
// reset replyTo message after sending
|
|
this.inReplyTo = null;
|
|
// Update conversation attributes on new conversation
|
|
if (this.conversationSize === 0) {
|
|
this.getAttributes();
|
|
}
|
|
},
|
|
async handleSendAttachment(attachment) {
|
|
await this.sendAttachment({
|
|
attachment,
|
|
replyTo: this.inReplyTo ? this.inReplyTo.id : null,
|
|
});
|
|
this.inReplyTo = null;
|
|
},
|
|
startNewConversation() {
|
|
this.clearConversations();
|
|
this.clearConversationAttributes();
|
|
this.replaceRoute('prechat-form');
|
|
IFrameHelper.sendMessage({
|
|
event: 'onEvent',
|
|
eventIdentifier: CHATWOOT_ON_START_CONVERSATION,
|
|
data: { hasConversation: true },
|
|
});
|
|
},
|
|
toggleReplyTo(message) {
|
|
this.inReplyTo = message;
|
|
},
|
|
async sendTranscript() {
|
|
if (this.hasEmail) {
|
|
try {
|
|
await sendEmailTranscript();
|
|
emitter.emit(BUS_EVENTS.SHOW_ALERT, {
|
|
message: this.$t('EMAIL_TRANSCRIPT.SEND_EMAIL_SUCCESS'),
|
|
type: 'success',
|
|
});
|
|
} catch (error) {
|
|
emitter.$emit(BUS_EVENTS.SHOW_ALERT, {
|
|
message: this.$t('EMAIL_TRANSCRIPT.SEND_EMAIL_ERROR'),
|
|
});
|
|
}
|
|
}
|
|
},
|
|
},
|
|
};
|
|
</script>
|
|
|
|
<template>
|
|
<footer
|
|
v-if="!hideReplyBox"
|
|
class="relative z-50 mb-1"
|
|
:class="{
|
|
'rounded-lg': !isWidgetStyleFlat,
|
|
'pt-2.5 shadow-[0px_-20px_20px_1px_rgba(0,_0,_0,_0.05)] dark:shadow-[0px_-20px_20px_1px_rgba(0,_0,_0,_0.15)] rounded-t-none':
|
|
hasReplyTo,
|
|
}"
|
|
>
|
|
<FooterReplyTo
|
|
v-if="hasReplyTo"
|
|
:in-reply-to="inReplyTo"
|
|
@dismiss="inReplyTo = null"
|
|
/>
|
|
<ChatInputWrap
|
|
class="shadow-sm"
|
|
:on-send-message="handleSendMessage"
|
|
:on-send-attachment="handleSendAttachment"
|
|
/>
|
|
</footer>
|
|
<div v-else>
|
|
<CustomButton
|
|
class="font-medium"
|
|
block
|
|
:bg-color="widgetColor"
|
|
:text-color="textColor"
|
|
@click="startNewConversation"
|
|
>
|
|
{{ $t('START_NEW_CONVERSATION') }}
|
|
</CustomButton>
|
|
<CustomButton
|
|
v-if="showEmailTranscriptButton"
|
|
type="clear"
|
|
class="font-normal"
|
|
@click="sendTranscript"
|
|
>
|
|
{{ $t('EMAIL_TRANSCRIPT.BUTTON_TEXT') }}
|
|
</CustomButton>
|
|
</div>
|
|
</template>
|
|
|
|
<style scoped lang="scss">
|
|
@import 'widget/assets/scss/variables.scss';
|
|
|
|
.branding {
|
|
align-items: center;
|
|
color: $color-body;
|
|
display: flex;
|
|
font-size: $font-size-default;
|
|
justify-content: center;
|
|
padding: $space-one;
|
|
text-align: center;
|
|
text-decoration: none;
|
|
|
|
img {
|
|
margin-right: $space-small;
|
|
max-width: $space-two;
|
|
}
|
|
}
|
|
</style>
|