iachat/app/javascript/dashboard/routes/dashboard/conversation/ContactPanel.vue
Sivin Varghese 79aa5a5d7f
feat: Replace alertMixin usage with useAlert (#9793)
# Pull Request Template

## Description

This PR will replace the usage of `alertMixin` from the code base with
the `useAlert` composable.

Fixes
https://linear.app/chatwoot/issue/CW-3462/replace-alertmixin-usage-with-usealert

## Type of change

- [x] Breaking change (fix or feature that would cause existing
functionality not to work as expected)

## How Has This Been Tested?

Please refer this issue description

https://linear.app/chatwoot/issue/CW-3462/replace-alertmixin-usage-with-usealert


## Checklist:

- [x] My code follows the style guidelines of this project
- [x] I have performed a self-review of my code
- [ ] I have commented on my code, particularly in hard-to-understand
areas
- [ ] I have made corresponding changes to the documentation
- [x] My changes generate no new warnings
- [x] I have added tests that prove my fix is effective or that my
feature works
- [x] New and existing unit tests pass locally with my changes
- [ ] Any dependent changes have been merged and published in downstream
modules

---------

Co-authored-by: Sojan Jose <sojan@pepalo.com>
2024-07-23 16:41:11 +05:30

272 lines
8.2 KiB
Vue

<template>
<div
class="overflow-y-auto bg-white border-l dark:bg-slate-900 text-slate-900 dark:text-slate-300 border-slate-50 dark:border-slate-800/50 rtl:border-l-0 rtl:border-r contact--panel"
>
<contact-info
:contact="contact"
:channel-type="channelType"
@toggle-panel="onPanelToggle"
/>
<draggable
:list="conversationSidebarItems"
:disabled="!dragEnabled"
animation="200"
class="list-group"
ghost-class="ghost"
handle=".drag-handle"
@start="dragging = true"
@end="onDragEnd"
>
<transition-group>
<div
v-for="element in conversationSidebarItems"
:key="element.name"
class="bg-white dark:bg-gray-800"
>
<div
v-if="element.name === 'conversation_actions'"
class="conversation--actions"
>
<accordion-item
:title="$t('CONVERSATION_SIDEBAR.ACCORDION.CONVERSATION_ACTIONS')"
:is-open="isContactSidebarItemOpen('is_conv_actions_open')"
@click="
value => toggleSidebarUIState('is_conv_actions_open', value)
"
>
<conversation-action
:conversation-id="conversationId"
:inbox-id="inboxId"
/>
</accordion-item>
</div>
<div
v-else-if="element.name === 'conversation_participants'"
class="conversation--actions"
>
<accordion-item
:title="$t('CONVERSATION_PARTICIPANTS.SIDEBAR_TITLE')"
:is-open="isContactSidebarItemOpen('is_conv_participants_open')"
@click="
value =>
toggleSidebarUIState('is_conv_participants_open', value)
"
>
<conversation-participant
:conversation-id="conversationId"
:inbox-id="inboxId"
/>
</accordion-item>
</div>
<div v-else-if="element.name === 'conversation_info'">
<accordion-item
:title="$t('CONVERSATION_SIDEBAR.ACCORDION.CONVERSATION_INFO')"
:is-open="isContactSidebarItemOpen('is_conv_details_open')"
compact
@click="
value => toggleSidebarUIState('is_conv_details_open', value)
"
>
<conversation-info
:conversation-attributes="conversationAdditionalAttributes"
:contact-attributes="contactAdditionalAttributes"
/>
</accordion-item>
</div>
<div v-else-if="element.name === 'contact_attributes'">
<accordion-item
:title="$t('CONVERSATION_SIDEBAR.ACCORDION.CONTACT_ATTRIBUTES')"
:is-open="isContactSidebarItemOpen('is_contact_attributes_open')"
compact
@click="
value =>
toggleSidebarUIState('is_contact_attributes_open', value)
"
>
<custom-attributes
attribute-type="contact_attribute"
attribute-class="conversation--attribute"
class="even"
attribute-from="conversation_contact_panel"
:contact-id="contact.id"
:empty-state-message="
$t('CONVERSATION_CUSTOM_ATTRIBUTES.NO_RECORDS_FOUND')
"
/>
</accordion-item>
</div>
<div v-else-if="element.name === 'previous_conversation'">
<accordion-item
v-if="contact.id"
:title="
$t('CONVERSATION_SIDEBAR.ACCORDION.PREVIOUS_CONVERSATION')
"
:is-open="isContactSidebarItemOpen('is_previous_conv_open')"
@click="
value => toggleSidebarUIState('is_previous_conv_open', value)
"
>
<contact-conversations
:contact-id="contact.id"
:conversation-id="conversationId"
/>
</accordion-item>
</div>
<woot-feature-toggle
v-else-if="element.name === 'macros'"
feature-key="macros"
>
<accordion-item
:title="$t('CONVERSATION_SIDEBAR.ACCORDION.MACROS')"
:is-open="isContactSidebarItemOpen('is_macro_open')"
compact
@click="value => toggleSidebarUIState('is_macro_open', value)"
>
<macros-list :conversation-id="conversationId" />
</accordion-item>
</woot-feature-toggle>
</div>
</transition-group>
</draggable>
</div>
</template>
<script>
import { mapGetters } from 'vuex';
import AccordionItem from 'dashboard/components/Accordion/AccordionItem.vue';
import ContactConversations from './ContactConversations.vue';
import ConversationAction from './ConversationAction.vue';
import ConversationParticipant from './ConversationParticipant.vue';
import ContactInfo from './contact/ContactInfo.vue';
import ConversationInfo from './ConversationInfo.vue';
import CustomAttributes from './customAttributes/CustomAttributes.vue';
import draggable from 'vuedraggable';
import uiSettingsMixin from 'dashboard/mixins/uiSettings';
import MacrosList from './Macros/List.vue';
export default {
components: {
AccordionItem,
ContactConversations,
ContactInfo,
ConversationInfo,
CustomAttributes,
ConversationAction,
ConversationParticipant,
draggable,
MacrosList,
},
mixins: [uiSettingsMixin],
props: {
conversationId: {
type: [Number, String],
required: true,
},
inboxId: {
type: Number,
default: undefined,
},
onToggle: {
type: Function,
default: () => {},
},
},
data() {
return {
dragEnabled: true,
conversationSidebarItems: [],
dragging: false,
};
},
computed: {
...mapGetters({
currentChat: 'getSelectedChat',
currentUser: 'getCurrentUser',
uiFlags: 'inboxAssignableAgents/getUIFlags',
}),
conversationAdditionalAttributes() {
return this.currentConversationMetaData.additional_attributes || {};
},
channelType() {
return this.currentChat.meta?.channel;
},
contact() {
return this.$store.getters['contacts/getContact'](this.contactId);
},
contactAdditionalAttributes() {
return this.contact.additional_attributes || {};
},
contactId() {
return this.currentChat.meta?.sender?.id;
},
currentConversationMetaData() {
return this.$store.getters[
'conversationMetadata/getConversationMetadata'
](this.conversationId);
},
hasContactAttributes() {
const { custom_attributes: customAttributes } = this.contact;
return customAttributes && Object.keys(customAttributes).length;
},
},
watch: {
conversationId(newConversationId, prevConversationId) {
if (newConversationId && newConversationId !== prevConversationId) {
this.getContactDetails();
}
},
contactId() {
this.getContactDetails();
},
},
mounted() {
this.conversationSidebarItems = this.conversationSidebarItemsOrder;
this.getContactDetails();
this.$store.dispatch('attributes/get', 0);
},
methods: {
onPanelToggle() {
this.onToggle();
},
getContactDetails() {
if (this.contactId) {
this.$store.dispatch('contacts/show', { id: this.contactId });
}
},
getAttributesByModel() {
if (this.contactId) {
this.$store.dispatch('contacts/show', { id: this.contactId });
}
},
openTranscriptModal() {
this.showTranscriptModal = true;
},
onDragEnd() {
this.dragging = false;
this.updateUISettings({
conversation_sidebar_items_order: this.conversationSidebarItems,
});
},
},
};
</script>
<style lang="scss" scoped>
::v-deep {
.contact--profile {
@apply pb-3 border-b border-solid border-slate-75 dark:border-slate-700;
}
.conversation--actions .multiselect-wrap--small {
.multiselect {
@apply box-border pl-6;
}
.multiselect__element {
span {
@apply w-full;
}
}
}
}
</style>