Files
chatwoot/app/javascript/dashboard/modules/conversations/components/MessageContextMenu.vue
Shivam Mishra c51a458c25 style: apply fixes for eslint issues [cw-3590] (#10210)
These fixes are all auto generated and can be merged directly

Fixes the following issues

1. Event used on components should be hypenated
2. Attribute orders in components
3. Use `unmounted` instead of `destroyed`
4. Add explicit `emits` declarations for components, autofixed [using
this
script](https://gist.github.com/scmmishra/6f549109b96400006bb69bbde392eddf)


We ignore the top level v-if for now, we will fix it later
2024-10-03 15:02:12 +05:30

288 lines
7.6 KiB
Vue

<script>
import { useAlert } from 'dashboard/composables';
import { mapGetters } from 'vuex';
import { useMessageFormatter } from 'shared/composables/useMessageFormatter';
import ContextMenu from 'dashboard/components/ui/ContextMenu.vue';
import AddCannedModal from 'dashboard/routes/dashboard/settings/canned/AddCanned.vue';
import { copyTextToClipboard } from 'shared/helpers/clipboard';
import { conversationUrl, frontendURL } from '../../../helper/URLHelper';
import {
ACCOUNT_EVENTS,
CONVERSATION_EVENTS,
} from '../../../helper/AnalyticsHelper/events';
import TranslateModal from 'dashboard/components/widgets/conversation/bubble/TranslateModal.vue';
import MenuItem from '../../../components/widgets/conversation/contextMenu/menuItem.vue';
import { useTrack } from 'dashboard/composables';
export default {
components: {
AddCannedModal,
TranslateModal,
MenuItem,
ContextMenu,
},
props: {
message: {
type: Object,
required: true,
},
isOpen: {
type: Boolean,
default: false,
},
enabledOptions: {
type: Object,
default: () => ({}),
},
contextMenuPosition: {
type: Object,
default: () => ({}),
},
},
emits: ['open', 'close', 'replyTo'],
setup() {
const { getPlainText } = useMessageFormatter();
return {
getPlainText,
};
},
data() {
return {
isCannedResponseModalOpen: false,
showTranslateModal: false,
showDeleteModal: false,
};
},
computed: {
...mapGetters({
getAccount: 'accounts/getAccount',
currentAccountId: 'getCurrentAccountId',
}),
plainTextContent() {
return this.getPlainText(this.messageContent);
},
conversationId() {
return this.message.conversation_id;
},
messageId() {
return this.message.id;
},
messageContent() {
return this.message.content;
},
contentAttributes() {
return this.message.content_attributes;
},
},
methods: {
async copyLinkToMessage() {
const fullConversationURL =
window.chatwootConfig.hostURL +
frontendURL(
conversationUrl({
id: this.conversationId,
accountId: this.currentAccountId,
})
);
await copyTextToClipboard(
`${fullConversationURL}?messageId=${this.messageId}`
);
useAlert(this.$t('CONVERSATION.CONTEXT_MENU.LINK_COPIED'));
this.handleClose();
},
async handleCopy() {
await copyTextToClipboard(this.plainTextContent);
useAlert(this.$t('CONTACT_PANEL.COPY_SUCCESSFUL'));
this.handleClose();
},
showCannedResponseModal() {
useTrack(ACCOUNT_EVENTS.ADDED_TO_CANNED_RESPONSE);
this.isCannedResponseModalOpen = true;
},
hideCannedResponseModal() {
this.isCannedResponseModalOpen = false;
this.handleClose();
},
handleOpen(e) {
this.$emit('open', e);
},
handleClose(e) {
this.$emit('close', e);
},
handleTranslate() {
const { locale } = this.getAccount(this.currentAccountId);
this.$store.dispatch('translateMessage', {
conversationId: this.conversationId,
messageId: this.messageId,
targetLanguage: locale || 'en',
});
useTrack(CONVERSATION_EVENTS.TRANSLATE_A_MESSAGE);
this.handleClose();
this.showTranslateModal = true;
},
handleReplyTo() {
this.$emit('replyTo', this.message);
this.handleClose();
},
onCloseTranslateModal() {
this.showTranslateModal = false;
},
openDeleteModal() {
this.handleClose();
this.showDeleteModal = true;
},
async confirmDeletion() {
try {
await this.$store.dispatch('deleteMessage', {
conversationId: this.conversationId,
messageId: this.messageId,
});
useAlert(this.$t('CONVERSATION.SUCCESS_DELETE_MESSAGE'));
this.handleClose();
} catch (error) {
useAlert(this.$t('CONVERSATION.FAIL_DELETE_MESSSAGE'));
}
},
closeDeleteModal() {
this.showDeleteModal = false;
},
},
};
</script>
<template>
<div class="context-menu">
<!-- Add To Canned Responses -->
<woot-modal
v-if="isCannedResponseModalOpen && enabledOptions['cannedResponse']"
v-model:show="isCannedResponseModalOpen"
:on-close="hideCannedResponseModal"
>
<AddCannedModal
:response-content="plainTextContent"
:on-close="hideCannedResponseModal"
/>
</woot-modal>
<!-- Translate Content -->
<TranslateModal
v-if="showTranslateModal"
:content="messageContent"
:content-attributes="contentAttributes"
@close="onCloseTranslateModal"
/>
<!-- Confirm Deletion -->
<woot-delete-modal
v-if="showDeleteModal"
v-model:show="showDeleteModal"
class="context-menu--delete-modal"
:on-close="closeDeleteModal"
:on-confirm="confirmDeletion"
:title="$t('CONVERSATION.CONTEXT_MENU.DELETE_CONFIRMATION.TITLE')"
:message="$t('CONVERSATION.CONTEXT_MENU.DELETE_CONFIRMATION.MESSAGE')"
:confirm-text="$t('CONVERSATION.CONTEXT_MENU.DELETE_CONFIRMATION.DELETE')"
:reject-text="$t('CONVERSATION.CONTEXT_MENU.DELETE_CONFIRMATION.CANCEL')"
/>
<woot-button
icon="more-vertical"
color-scheme="secondary"
variant="clear"
size="small"
@click="handleOpen"
/>
<ContextMenu
v-if="isOpen && !isCannedResponseModalOpen"
:x="contextMenuPosition.x"
:y="contextMenuPosition.y"
@close="handleClose"
>
<div class="menu-container">
<MenuItem
v-if="enabledOptions['replyTo']"
:option="{
icon: 'arrow-reply',
label: $t('CONVERSATION.CONTEXT_MENU.REPLY_TO'),
}"
variant="icon"
@click.stop="handleReplyTo"
/>
<MenuItem
v-if="enabledOptions['copy']"
:option="{
icon: 'clipboard',
label: $t('CONVERSATION.CONTEXT_MENU.COPY'),
}"
variant="icon"
@click.stop="handleCopy"
/>
<MenuItem
v-if="enabledOptions['copy']"
:option="{
icon: 'translate',
label: $t('CONVERSATION.CONTEXT_MENU.TRANSLATE'),
}"
variant="icon"
@click.stop="handleTranslate"
/>
<hr />
<MenuItem
:option="{
icon: 'link',
label: $t('CONVERSATION.CONTEXT_MENU.COPY_PERMALINK'),
}"
variant="icon"
@click.stop="copyLinkToMessage"
/>
<MenuItem
v-if="enabledOptions['cannedResponse']"
:option="{
icon: 'comment-add',
label: $t('CONVERSATION.CONTEXT_MENU.CREATE_A_CANNED_RESPONSE'),
}"
variant="icon"
@click.stop="showCannedResponseModal"
/>
<hr v-if="enabledOptions['delete']" />
<MenuItem
v-if="enabledOptions['delete']"
:option="{
icon: 'delete',
label: $t('CONVERSATION.CONTEXT_MENU.DELETE'),
}"
variant="icon"
@click.stop="openDeleteModal"
/>
</div>
</ContextMenu>
</div>
</template>
<style lang="scss" scoped>
.menu-container {
@apply p-1 bg-white dark:bg-slate-900 shadow-xl rounded-md;
hr:first-child {
@apply hidden;
}
hr {
@apply m-1 border-b border-solid border-slate-50 dark:border-slate-800/50;
}
}
.context-menu--delete-modal {
::v-deep {
.modal-container {
@apply max-w-[30rem];
h2 {
@apply font-medium text-base;
}
}
.modal-footer {
@apply pt-4 pb-8 px-8;
}
}
}
</style>